layers-ui-table.js 2.5 MB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971
  1. /******/ (function (modules) { // webpackBootstrap
  2. /******/ // The module cache
  3. /******/ var installedModules = {};
  4. /******/
  5. /******/ // The require function
  6. /******/ function __webpack_require__(moduleId) {
  7. /******/
  8. /******/ // Check if module is in cache
  9. /******/ if (installedModules[moduleId]) {
  10. /******/ return installedModules[moduleId].exports;
  11. /******/ }
  12. /******/ // Create a new module (and put it into the cache)
  13. /******/ var module = installedModules[moduleId] = {
  14. /******/ i: moduleId,
  15. /******/ l: false,
  16. /******/ exports: {}
  17. /******/};
  18. /******/
  19. /******/ // Execute the module function
  20. /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  21. /******/
  22. /******/ // Flag the module as loaded
  23. /******/ module.l = true;
  24. /******/
  25. /******/ // Return the exports of the module
  26. /******/ return module.exports;
  27. /******/ }
  28. /******/
  29. /******/
  30. /******/ // expose the modules object (__webpack_modules__)
  31. /******/ __webpack_require__.m = modules;
  32. /******/
  33. /******/ // expose the module cache
  34. /******/ __webpack_require__.c = installedModules;
  35. /******/
  36. /******/ // identity function for calling harmony imports with the correct context
  37. /******/ __webpack_require__.i = function (value) {
  38. return value;
  39. };
  40. /******/
  41. /******/ // define getter function for harmony exports
  42. /******/ __webpack_require__.d = function (exports, name, getter) {
  43. /******/ if (!__webpack_require__.o(exports, name)) {
  44. /******/ Object.defineProperty(exports, name, {
  45. /******/ configurable: false,
  46. /******/ enumerable: true,
  47. /******/ get: getter
  48. /******/});
  49. /******/ }
  50. /******/ };
  51. /******/
  52. /******/ // getDefaultExport function for compatibility with non-harmony modules
  53. /******/ __webpack_require__.n = function (module) {
  54. /******/ var getter = module && module.__esModule ?
  55. /******/ function getDefault() {
  56. return module['default'];
  57. } :
  58. /******/ function getModuleExports() {
  59. return module;
  60. };
  61. /******/ __webpack_require__.d(getter, 'a', getter);
  62. /******/ return getter;
  63. /******/ };
  64. /******/
  65. /******/ // Object.prototype.hasOwnProperty.call
  66. /******/ __webpack_require__.o = function (object, property) {
  67. return Object.prototype.hasOwnProperty.call(object, property);
  68. };
  69. /******/
  70. /******/ // __webpack_public_path__
  71. /******/ __webpack_require__.p = "";
  72. /******/
  73. /******/ // Load entry module and return exports
  74. /******/ return __webpack_require__(__webpack_require__.s = 40);
  75. /******/ })
  76. /************************************************************************/
  77. /******/({
  78. /***/ 0:
  79. /***/ (function (module, exports, __webpack_require__) {
  80. "use strict";
  81. Object.defineProperty(exports, "__esModule", {
  82. value: true
  83. });
  84. var _jquery = __webpack_require__(1);
  85. var _jquery2 = _interopRequireDefault(_jquery);
  86. function _interopRequireDefault(obj) {
  87. return obj && obj.__esModule ? obj : {default: obj};
  88. }
  89. /**
  90. * --------------------------------------------------------------------------
  91. * Bootstrap (v4.0.0-beta): util.js
  92. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  93. * --------------------------------------------------------------------------
  94. */
  95. var Util = function () {
  96. /**
  97. * ------------------------------------------------------------------------
  98. * Private TransitionEnd Helpers
  99. * ------------------------------------------------------------------------
  100. */
  101. var transition = false;
  102. var MAX_UID = 1000000;
  103. var TransitionEndEvent = {
  104. WebkitTransition: 'webkitTransitionEnd',
  105. MozTransition: 'transitionend',
  106. OTransition: 'oTransitionEnd otransitionend',
  107. transition: 'transitionend'
  108. // shoutout AngusCroll (https://goo.gl/pxwQGp)
  109. };
  110. function toType(obj) {
  111. return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
  112. }
  113. function getSpecialTransitionEndEvent() {
  114. return {
  115. bindType: transition.end,
  116. delegateType: transition.end,
  117. handle: function handle(event) {
  118. if ((0, _jquery2.default)(event.target).is(this)) {
  119. return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params
  120. }
  121. return undefined; // eslint-disable-line no-undefined
  122. }
  123. };
  124. }
  125. function transitionEndTest() {
  126. if (window.QUnit) {
  127. return false;
  128. }
  129. var el = document.createElement('bootstrap');
  130. for (var name in TransitionEndEvent) {
  131. if (typeof el.style[name] !== 'undefined') {
  132. return {
  133. end: TransitionEndEvent[name]
  134. };
  135. }
  136. }
  137. return false;
  138. }
  139. function transitionEndEmulator(duration) {
  140. var _this = this;
  141. var called = false;
  142. (0, _jquery2.default)(this).one(Util.TRANSITION_END, function () {
  143. called = true;
  144. });
  145. setTimeout(function () {
  146. if (!called) {
  147. Util.triggerTransitionEnd(_this);
  148. }
  149. }, duration);
  150. return this;
  151. }
  152. function setTransitionEndSupport() {
  153. transition = transitionEndTest();
  154. _jquery2.default.fn.emulateTransitionEnd = transitionEndEmulator;
  155. if (Util.supportsTransitionEnd()) {
  156. _jquery2.default.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();
  157. }
  158. }
  159. function parseOption(item) {
  160. if ('true' === item) {
  161. return true;
  162. } else if ('false' === item) {
  163. return false;
  164. } else if (!isNaN(item * 1)) {
  165. return parseFloat(item);
  166. } else {
  167. return item;
  168. }
  169. }
  170. /**
  171. * --------------------------------------------------------------------------
  172. * Public Util Api
  173. * --------------------------------------------------------------------------
  174. */
  175. var Util = {
  176. TRANSITION_END: 'bsTransitionEnd',
  177. getUID: function getUID(prefix) {
  178. do {
  179. // eslint-disable-next-line no-bitwise
  180. prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here
  181. } while (document.getElementById(prefix));
  182. return prefix;
  183. },
  184. getSelectorFromElement: function getSelectorFromElement(element) {
  185. var selector = element.getAttribute('data-target');
  186. if (!selector || selector === '#') {
  187. selector = element.getAttribute('href') || '';
  188. }
  189. try {
  190. var $selector = (0, _jquery2.default)(document).find(selector);
  191. return $selector.length > 0 ? selector : null;
  192. } catch (error) {
  193. return null;
  194. }
  195. },
  196. reflow: function reflow(element) {
  197. return element.offsetHeight;
  198. },
  199. triggerTransitionEnd: function triggerTransitionEnd(element) {
  200. (0, _jquery2.default)(element).trigger(transition.end);
  201. },
  202. supportsTransitionEnd: function supportsTransitionEnd() {
  203. return Boolean(transition);
  204. },
  205. isElement: function isElement(obj) {
  206. return (obj[0] || obj).nodeType;
  207. },
  208. typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {
  209. for (var property in configTypes) {
  210. if (Object.prototype.hasOwnProperty.call(configTypes, property)) {
  211. var expectedTypes = configTypes[property];
  212. var value = config[property];
  213. var valueType = value && Util.isElement(value) ? 'element' : toType(value);
  214. if (!new RegExp(expectedTypes).test(valueType)) {
  215. throw new Error(componentName.toUpperCase() + ': ' + ('Option "' + property + '" provided type "' + valueType + '" ') + ('but expected type "' + expectedTypes + '".'));
  216. }
  217. }
  218. }
  219. },
  220. parseDataOptions: function parseDataOptions(dataOptions) {
  221. var options = [];
  222. var string = dataOptions.split(';');
  223. string.forEach(function (item, index) {
  224. var option = item.split(':');
  225. option = option.map(function (item) {
  226. return item.trim();
  227. });
  228. if (option[0]) {
  229. options[option[0]] = parseOption(option[1]);
  230. }
  231. });
  232. return options;
  233. }
  234. };
  235. setTransitionEndSupport();
  236. return Util;
  237. }(_jquery2.default);
  238. exports.default = Util;
  239. /***/ }),
  240. /***/ 1:
  241. /***/ (function (module, exports) {
  242. module.exports = jQuery;
  243. /***/ }),
  244. /***/ 10:
  245. /***/ (function (module, exports, __webpack_require__) {
  246. "use strict";
  247. var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
  248. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  249. return typeof obj;
  250. } : function (obj) {
  251. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  252. };
  253. /*! Responsive 2.2.0
  254. * 2014-2017 SpryMedia Ltd - datatables.net/license
  255. */
  256. /**
  257. * @summary Responsive
  258. * @description Responsive tables plug-in for DataTables
  259. * @version 2.2.0
  260. * @file dataTables.responsive.js
  261. * @author SpryMedia Ltd (www.sprymedia.co.uk)
  262. * @contact www.sprymedia.co.uk/contact
  263. * @copyright Copyright 2014-2017 SpryMedia Ltd.
  264. *
  265. * This source file is free software, available under the following license:
  266. * MIT license - http://datatables.net/license/mit
  267. *
  268. * This source file is distributed in the hope that it will be useful, but
  269. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  270. * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  271. *
  272. * For details please refer to: http://www.datatables.net
  273. */
  274. (function (factory) {
  275. if (true) {
  276. // AMD
  277. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1), __webpack_require__(2)], __WEBPACK_AMD_DEFINE_RESULT__ = function ($) {
  278. return factory($, window, document);
  279. }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
  280. __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  281. } else if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
  282. // CommonJS
  283. module.exports = function (root, $) {
  284. if (!root) {
  285. root = window;
  286. }
  287. if (!$ || !$.fn.dataTable) {
  288. $ = require('datatables.net')(root, $).$;
  289. }
  290. return factory($, root, root.document);
  291. };
  292. } else {
  293. // Browser
  294. factory(jQuery, window, document);
  295. }
  296. })(function ($, window, document, undefined) {
  297. 'use strict';
  298. var DataTable = $.fn.dataTable;
  299. /**
  300. * Responsive is a plug-in for the DataTables library that makes use of
  301. * DataTables' ability to change the visibility of columns, changing the
  302. * visibility of columns so the displayed columns fit into the table container.
  303. * The end result is that complex tables will be dynamically adjusted to fit
  304. * into the viewport, be it on a desktop, tablet or mobile browser.
  305. *
  306. * Responsive for DataTables has two modes of operation, which can used
  307. * individually or combined:
  308. *
  309. * * Class name based control - columns assigned class names that match the
  310. * breakpoint logic can be shown / hidden as required for each breakpoint.
  311. * * Automatic control - columns are automatically hidden when there is no
  312. * room left to display them. Columns removed from the right.
  313. *
  314. * In additional to column visibility control, Responsive also has built into
  315. * options to use DataTables' child row display to show / hide the information
  316. * from the table that has been hidden. There are also two modes of operation
  317. * for this child row display:
  318. *
  319. * * Inline - when the control element that the user can use to show / hide
  320. * child rows is displayed inside the first column of the table.
  321. * * Column - where a whole column is dedicated to be the show / hide control.
  322. *
  323. * Initialisation of Responsive is performed by:
  324. *
  325. * * Adding the class `responsive` or `dt-responsive` to the table. In this case
  326. * Responsive will automatically be initialised with the default configuration
  327. * options when the DataTable is created.
  328. * * Using the `responsive` option in the DataTables configuration options. This
  329. * can also be used to specify the configuration options, or simply set to
  330. * `true` to use the defaults.
  331. *
  332. * @class
  333. * @param {object} settings DataTables settings object for the host table
  334. * @param {object} [opts] Configuration options
  335. * @requires jQuery 1.7+
  336. * @requires DataTables 1.10.3+
  337. *
  338. * @example
  339. * $('#example').DataTable( {
  340. * responsive: true
  341. * } );
  342. * } );
  343. */
  344. var Responsive = function Responsive(settings, opts) {
  345. // Sanity check that we are using DataTables 1.10 or newer
  346. if (!DataTable.versionCheck || !DataTable.versionCheck('1.10.3')) {
  347. throw 'DataTables Responsive requires DataTables 1.10.3 or newer';
  348. }
  349. this.s = {
  350. dt: new DataTable.Api(settings),
  351. columns: [],
  352. current: []
  353. };
  354. // Check if responsive has already been initialised on this table
  355. if (this.s.dt.settings()[0].responsive) {
  356. return;
  357. }
  358. // details is an object, but for simplicity the user can give it as a string
  359. // or a boolean
  360. if (opts && typeof opts.details === 'string') {
  361. opts.details = {type: opts.details};
  362. } else if (opts && opts.details === false) {
  363. opts.details = {type: false};
  364. } else if (opts && opts.details === true) {
  365. opts.details = {type: 'inline'};
  366. }
  367. this.c = $.extend(true, {}, Responsive.defaults, DataTable.defaults.responsive, opts);
  368. settings.responsive = this;
  369. this._constructor();
  370. };
  371. $.extend(Responsive.prototype, {
  372. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  373. * Constructor
  374. */
  375. /**
  376. * Initialise the Responsive instance
  377. *
  378. * @private
  379. */
  380. _constructor: function _constructor() {
  381. var that = this;
  382. var dt = this.s.dt;
  383. var dtPrivateSettings = dt.settings()[0];
  384. var oldWindowWidth = $(window).width();
  385. dt.settings()[0]._responsive = this;
  386. // Use DataTables' throttle function to avoid processor thrashing on
  387. // resize
  388. $(window).on('resize.dtr orientationchange.dtr', DataTable.util.throttle(function () {
  389. // iOS has a bug whereby resize can fire when only scrolling
  390. // See: http://stackoverflow.com/questions/8898412
  391. var width = $(window).width();
  392. if (width !== oldWindowWidth) {
  393. that._resize();
  394. oldWindowWidth = width;
  395. }
  396. }));
  397. // DataTables doesn't currently trigger an event when a row is added, so
  398. // we need to hook into its private API to enforce the hidden rows when
  399. // new data is added
  400. dtPrivateSettings.oApi._fnCallbackReg(dtPrivateSettings, 'aoRowCreatedCallback', function (tr, data, idx) {
  401. if ($.inArray(false, that.s.current) !== - 1) {
  402. $('>td, >th', tr).each(function (i) {
  403. var idx = dt.column.index('toData', i);
  404. if (that.s.current[idx] === false) {
  405. $(this).css('display', 'none');
  406. }
  407. });
  408. }
  409. });
  410. // Destroy event handler
  411. dt.on('destroy.dtr', function () {
  412. dt.off('.dtr');
  413. $(dt.table().body()).off('.dtr');
  414. $(window).off('resize.dtr orientationchange.dtr');
  415. // Restore the columns that we've hidden
  416. $.each(that.s.current, function (i, val) {
  417. if (val === false) {
  418. that._setColumnVis(i, true);
  419. }
  420. });
  421. });
  422. // Reorder the breakpoints array here in case they have been added out
  423. // of order
  424. this.c.breakpoints.sort(function (a, b) {
  425. return a.width < b.width ? 1 : a.width > b.width ? - 1 : 0;
  426. });
  427. this._classLogic();
  428. this._resizeAuto();
  429. // Details handler
  430. var details = this.c.details;
  431. if (details.type !== false) {
  432. that._detailsInit();
  433. // DataTables will trigger this event on every column it shows and
  434. // hides individually
  435. dt.on('column-visibility.dtr', function (e, ctx, col, vis) {
  436. that._classLogic();
  437. that._resizeAuto();
  438. that._resize();
  439. });
  440. // Redraw the details box on each draw which will happen if the data
  441. // has changed. This is used until DataTables implements a native
  442. // `updated` event for rows
  443. dt.on('draw.dtr', function () {
  444. that._redrawChildren();
  445. });
  446. $(dt.table().node()).addClass('dtr-' + details.type);
  447. }
  448. dt.on('column-reorder.dtr', function (e, settings, details) {
  449. that._classLogic();
  450. that._resizeAuto();
  451. that._resize();
  452. });
  453. // Change in column sizes means we need to calc
  454. dt.on('column-sizing.dtr', function () {
  455. that._resizeAuto();
  456. that._resize();
  457. });
  458. // On Ajax reload we want to reopen any child rows which are displayed
  459. // by responsive
  460. dt.on('preXhr.dtr', function () {
  461. var rowIds = [];
  462. dt.rows().every(function () {
  463. if (this.child.isShown()) {
  464. rowIds.push(this.id(true));
  465. }
  466. });
  467. dt.one('draw.dtr', function () {
  468. dt.rows(rowIds).every(function () {
  469. that._detailsDisplay(this, false);
  470. });
  471. });
  472. });
  473. dt.on('init.dtr', function (e, settings, details) {
  474. that._resizeAuto();
  475. that._resize();
  476. // If columns were hidden, then DataTables needs to adjust the
  477. // column sizing
  478. if ($.inArray(false, that.s.current)) {
  479. dt.columns.adjust();
  480. }
  481. });
  482. // First pass - draw the table for the current viewport size
  483. this._resize();
  484. },
  485. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  486. * Private methods
  487. */
  488. /**
  489. * Calculate the visibility for the columns in a table for a given
  490. * breakpoint. The result is pre-determined based on the class logic if
  491. * class names are used to control all columns, but the width of the table
  492. * is also used if there are columns which are to be automatically shown
  493. * and hidden.
  494. *
  495. * @param {string} breakpoint Breakpoint name to use for the calculation
  496. * @return {array} Array of boolean values initiating the visibility of each
  497. * column.
  498. * @private
  499. */
  500. _columnsVisiblity: function _columnsVisiblity(breakpoint) {
  501. var dt = this.s.dt;
  502. var columns = this.s.columns;
  503. var i, ien;
  504. // Create an array that defines the column ordering based first on the
  505. // column's priority, and secondly the column index. This allows the
  506. // columns to be removed from the right if the priority matches
  507. var order = columns.map(function (col, idx) {
  508. return {
  509. columnIdx: idx,
  510. priority: col.priority
  511. };
  512. }).sort(function (a, b) {
  513. if (a.priority !== b.priority) {
  514. return a.priority - b.priority;
  515. }
  516. return a.columnIdx - b.columnIdx;
  517. });
  518. // Class logic - determine which columns are in this breakpoint based
  519. // on the classes. If no class control (i.e. `auto`) then `-` is used
  520. // to indicate this to the rest of the function
  521. var display = $.map(columns, function (col) {
  522. return col.auto && col.minWidth === null ? false : col.auto === true ? '-' : $.inArray(breakpoint, col.includeIn) !== - 1;
  523. });
  524. // Auto column control - first pass: how much width is taken by the
  525. // ones that must be included from the non-auto columns
  526. var requiredWidth = 0;
  527. for (i = 0, ien = display.length; i < ien; i++) {
  528. if (display[i] === true) {
  529. requiredWidth += columns[i].minWidth;
  530. }
  531. }
  532. // Second pass, use up any remaining width for other columns. For
  533. // scrolling tables we need to subtract the width of the scrollbar. It
  534. // may not be requires which makes this sub-optimal, but it would
  535. // require another full redraw to make complete use of those extra few
  536. // pixels
  537. var scrolling = dt.settings()[0].oScroll;
  538. var bar = scrolling.sY || scrolling.sX ? scrolling.iBarWidth : 0;
  539. var widthAvailable = dt.table().container().offsetWidth - bar;
  540. var usedWidth = widthAvailable - requiredWidth;
  541. // Control column needs to always be included. This makes it sub-
  542. // optimal in terms of using the available with, but to stop layout
  543. // thrashing or overflow. Also we need to account for the control column
  544. // width first so we know how much width is available for the other
  545. // columns, since the control column might not be the first one shown
  546. for (i = 0, ien = display.length; i < ien; i++) {
  547. if (columns[i].control) {
  548. usedWidth -= columns[i].minWidth;
  549. }
  550. }
  551. // Allow columns to be shown (counting by priority and then right to
  552. // left) until we run out of room
  553. var empty = false;
  554. for (i = 0, ien = order.length; i < ien; i++) {
  555. var colIdx = order[i].columnIdx;
  556. if (display[colIdx] === '-' && !columns[colIdx].control && columns[colIdx].minWidth) {
  557. // Once we've found a column that won't fit we don't let any
  558. // others display either, or columns might disappear in the
  559. // middle of the table
  560. if (empty || usedWidth - columns[colIdx].minWidth < 0) {
  561. empty = true;
  562. display[colIdx] = false;
  563. } else {
  564. display[colIdx] = true;
  565. }
  566. usedWidth -= columns[colIdx].minWidth;
  567. }
  568. }
  569. // Determine if the 'control' column should be shown (if there is one).
  570. // This is the case when there is a hidden column (that is not the
  571. // control column). The two loops look inefficient here, but they are
  572. // trivial and will fly through. We need to know the outcome from the
  573. // first , before the action in the second can be taken
  574. var showControl = false;
  575. for (i = 0, ien = columns.length; i < ien; i++) {
  576. if (!columns[i].control && !columns[i].never && !display[i]) {
  577. showControl = true;
  578. break;
  579. }
  580. }
  581. for (i = 0, ien = columns.length; i < ien; i++) {
  582. if (columns[i].control) {
  583. display[i] = showControl;
  584. }
  585. }
  586. // Finally we need to make sure that there is at least one column that
  587. // is visible
  588. if ($.inArray(true, display) === - 1) {
  589. display[0] = true;
  590. }
  591. return display;
  592. },
  593. /**
  594. * Create the internal `columns` array with information about the columns
  595. * for the table. This includes determining which breakpoints the column
  596. * will appear in, based upon class names in the column, which makes up the
  597. * vast majority of this method.
  598. *
  599. * @private
  600. */
  601. _classLogic: function _classLogic() {
  602. var that = this;
  603. var calc = {};
  604. var breakpoints = this.c.breakpoints;
  605. var dt = this.s.dt;
  606. var columns = dt.columns().eq(0).map(function (i) {
  607. var column = this.column(i);
  608. var className = column.header().className;
  609. var priority = dt.settings()[0].aoColumns[i].responsivePriority;
  610. if (priority === undefined) {
  611. var dataPriority = $(column.header()).data('priority');
  612. priority = dataPriority !== undefined ? dataPriority * 1 : 10000;
  613. }
  614. return {
  615. className: className,
  616. includeIn: [],
  617. auto: false,
  618. control: false,
  619. never: className.match(/\bnever\b/) ? true : false,
  620. priority: priority
  621. };
  622. });
  623. // Simply add a breakpoint to `includeIn` array, ensuring that there are
  624. // no duplicates
  625. var add = function add(colIdx, name) {
  626. var includeIn = columns[colIdx].includeIn;
  627. if ($.inArray(name, includeIn) === - 1) {
  628. includeIn.push(name);
  629. }
  630. };
  631. var column = function column(colIdx, name, operator, matched) {
  632. var size, i, ien;
  633. if (!operator) {
  634. columns[colIdx].includeIn.push(name);
  635. } else if (operator === 'max-') {
  636. // Add this breakpoint and all smaller
  637. size = that._find(name).width;
  638. for (i = 0, ien = breakpoints.length; i < ien; i++) {
  639. if (breakpoints[i].width <= size) {
  640. add(colIdx, breakpoints[i].name);
  641. }
  642. }
  643. } else if (operator === 'min-') {
  644. // Add this breakpoint and all larger
  645. size = that._find(name).width;
  646. for (i = 0, ien = breakpoints.length; i < ien; i++) {
  647. if (breakpoints[i].width >= size) {
  648. add(colIdx, breakpoints[i].name);
  649. }
  650. }
  651. } else if (operator === 'not-') {
  652. // Add all but this breakpoint
  653. for (i = 0, ien = breakpoints.length; i < ien; i++) {
  654. if (breakpoints[i].name.indexOf(matched) === - 1) {
  655. add(colIdx, breakpoints[i].name);
  656. }
  657. }
  658. }
  659. };
  660. // Loop over each column and determine if it has a responsive control
  661. // class
  662. columns.each(function (col, i) {
  663. var classNames = col.className.split(' ');
  664. var hasClass = false;
  665. // Split the class name up so multiple rules can be applied if needed
  666. for (var k = 0, ken = classNames.length; k < ken; k++) {
  667. var className = $.trim(classNames[k]);
  668. if (className === 'all') {
  669. // Include in all
  670. hasClass = true;
  671. col.includeIn = $.map(breakpoints, function (a) {
  672. return a.name;
  673. });
  674. return;
  675. } else if (className === 'none' || col.never) {
  676. // Include in none (default) and no auto
  677. hasClass = true;
  678. return;
  679. } else if (className === 'control') {
  680. // Special column that is only visible, when one of the other
  681. // columns is hidden. This is used for the details control
  682. hasClass = true;
  683. col.control = true;
  684. return;
  685. }
  686. $.each(breakpoints, function (j, breakpoint) {
  687. // Does this column have a class that matches this breakpoint?
  688. var brokenPoint = breakpoint.name.split('-');
  689. var re = new RegExp('(min\\-|max\\-|not\\-)?(' + brokenPoint[0] + ')(\\-[_a-zA-Z0-9])?');
  690. var match = className.match(re);
  691. if (match) {
  692. hasClass = true;
  693. if (match[2] === brokenPoint[0] && match[3] === '-' + brokenPoint[1]) {
  694. // Class name matches breakpoint name fully
  695. column(i, breakpoint.name, match[1], match[2] + match[3]);
  696. } else if (match[2] === brokenPoint[0] && !match[3]) {
  697. // Class name matched primary breakpoint name with no qualifier
  698. column(i, breakpoint.name, match[1], match[2]);
  699. }
  700. }
  701. });
  702. }
  703. // If there was no control class, then automatic sizing is used
  704. if (!hasClass) {
  705. col.auto = true;
  706. }
  707. });
  708. this.s.columns = columns;
  709. },
  710. /**
  711. * Show the details for the child row
  712. *
  713. * @param {DataTables.Api} row API instance for the row
  714. * @param {boolean} update Update flag
  715. * @private
  716. */
  717. _detailsDisplay: function _detailsDisplay(row, update) {
  718. var that = this;
  719. var dt = this.s.dt;
  720. var details = this.c.details;
  721. if (details && details.type !== false) {
  722. var res = details.display(row, update, function () {
  723. return details.renderer(dt, row[0], that._detailsObj(row[0]));
  724. });
  725. if (res === true || res === false) {
  726. $(dt.table().node()).triggerHandler('responsive-display.dt', [dt, row, res, update]);
  727. }
  728. }
  729. },
  730. /**
  731. * Initialisation for the details handler
  732. *
  733. * @private
  734. */
  735. _detailsInit: function _detailsInit() {
  736. var that = this;
  737. var dt = this.s.dt;
  738. var details = this.c.details;
  739. // The inline type always uses the first child as the target
  740. if (details.type === 'inline') {
  741. details.target = 'td:first-child, th:first-child';
  742. }
  743. // Keyboard accessibility
  744. dt.on('draw.dtr', function () {
  745. that._tabIndexes();
  746. });
  747. that._tabIndexes(); // Initial draw has already happened
  748. $(dt.table().body()).on('keyup.dtr', 'td, th', function (e) {
  749. if (e.keyCode === 13 && $(this).data('dtr-keyboard')) {
  750. $(this).click();
  751. }
  752. });
  753. // type.target can be a string jQuery selector or a column index
  754. var target = details.target;
  755. var selector = typeof target === 'string' ? target : 'td, th';
  756. // Click handler to show / hide the details rows when they are available
  757. $(dt.table().body()).on('click.dtr mousedown.dtr mouseup.dtr', selector, function (e) {
  758. // If the table is not collapsed (i.e. there is no hidden columns)
  759. // then take no action
  760. if (!$(dt.table().node()).hasClass('collapsed')) {
  761. return;
  762. }
  763. // Check that the row is actually a DataTable's controlled node
  764. if ($.inArray($(this).closest('tr').get(0), dt.rows().nodes().toArray()) === - 1) {
  765. return;
  766. }
  767. // For column index, we determine if we should act or not in the
  768. // handler - otherwise it is already okay
  769. if (typeof target === 'number') {
  770. var targetIdx = target < 0 ? dt.columns().eq(0).length + target : target;
  771. if (dt.cell(this).index().column !== targetIdx) {
  772. return;
  773. }
  774. }
  775. // $().closest() includes itself in its check
  776. var row = dt.row($(this).closest('tr'));
  777. // Check event type to do an action
  778. if (e.type === 'click') {
  779. // The renderer is given as a function so the caller can execute it
  780. // only when they need (i.e. if hiding there is no point is running
  781. // the renderer)
  782. that._detailsDisplay(row, false);
  783. } else if (e.type === 'mousedown') {
  784. // For mouse users, prevent the focus ring from showing
  785. $(this).css('outline', 'none');
  786. } else if (e.type === 'mouseup') {
  787. // And then re-allow at the end of the click
  788. $(this).blur().css('outline', '');
  789. }
  790. });
  791. },
  792. /**
  793. * Get the details to pass to a renderer for a row
  794. * @param {int} rowIdx Row index
  795. * @private
  796. */
  797. _detailsObj: function _detailsObj(rowIdx) {
  798. var that = this;
  799. var dt = this.s.dt;
  800. return $.map(this.s.columns, function (col, i) {
  801. // Never and control columns should not be passed to the renderer
  802. if (col.never || col.control) {
  803. return;
  804. }
  805. return {
  806. title: dt.settings()[0].aoColumns[i].sTitle,
  807. data: dt.cell(rowIdx, i).render(that.c.orthogonal),
  808. hidden: dt.column(i).visible() && !that.s.current[i],
  809. columnIndex: i,
  810. rowIndex: rowIdx
  811. };
  812. });
  813. },
  814. /**
  815. * Find a breakpoint object from a name
  816. *
  817. * @param {string} name Breakpoint name to find
  818. * @return {object} Breakpoint description object
  819. * @private
  820. */
  821. _find: function _find(name) {
  822. var breakpoints = this.c.breakpoints;
  823. for (var i = 0, ien = breakpoints.length; i < ien; i++) {
  824. if (breakpoints[i].name === name) {
  825. return breakpoints[i];
  826. }
  827. }
  828. },
  829. /**
  830. * Re-create the contents of the child rows as the display has changed in
  831. * some way.
  832. *
  833. * @private
  834. */
  835. _redrawChildren: function _redrawChildren() {
  836. var that = this;
  837. var dt = this.s.dt;
  838. dt.rows({page: 'current'}).iterator('row', function (settings, idx) {
  839. var row = dt.row(idx);
  840. that._detailsDisplay(dt.row(idx), true);
  841. });
  842. },
  843. /**
  844. * Alter the table display for a resized viewport. This involves first
  845. * determining what breakpoint the window currently is in, getting the
  846. * column visibilities to apply and then setting them.
  847. *
  848. * @private
  849. */
  850. _resize: function _resize() {
  851. var that = this;
  852. var dt = this.s.dt;
  853. var width = $(window).width();
  854. var breakpoints = this.c.breakpoints;
  855. var breakpoint = breakpoints[0].name;
  856. var columns = this.s.columns;
  857. var i, ien;
  858. var oldVis = this.s.current.slice();
  859. // Determine what breakpoint we are currently at
  860. for (i = breakpoints.length - 1; i >= 0; i--) {
  861. if (width <= breakpoints[i].width) {
  862. breakpoint = breakpoints[i].name;
  863. break;
  864. }
  865. }
  866. // Show the columns for that break point
  867. var columnsVis = this._columnsVisiblity(breakpoint);
  868. this.s.current = columnsVis;
  869. // Set the class before the column visibility is changed so event
  870. // listeners know what the state is. Need to determine if there are
  871. // any columns that are not visible but can be shown
  872. var collapsedClass = false;
  873. for (i = 0, ien = columns.length; i < ien; i++) {
  874. if (columnsVis[i] === false && !columns[i].never && !columns[i].control) {
  875. collapsedClass = true;
  876. break;
  877. }
  878. }
  879. $(dt.table().node()).toggleClass('collapsed', collapsedClass);
  880. var changed = false;
  881. dt.columns().eq(0).each(function (colIdx, i) {
  882. if (columnsVis[i] !== oldVis[i]) {
  883. changed = true;
  884. that._setColumnVis(colIdx, columnsVis[i]);
  885. }
  886. });
  887. if (changed) {
  888. this._redrawChildren();
  889. // Inform listeners of the change
  890. $(dt.table().node()).trigger('responsive-resize.dt', [dt, this.s.current]);
  891. // If no records, update the "No records" display element
  892. if (dt.page.info().recordsDisplay === 0) {
  893. dt.draw();
  894. }
  895. }
  896. },
  897. /**
  898. * Determine the width of each column in the table so the auto column hiding
  899. * has that information to work with. This method is never going to be 100%
  900. * perfect since column widths can change slightly per page, but without
  901. * seriously compromising performance this is quite effective.
  902. *
  903. * @private
  904. */
  905. _resizeAuto: function _resizeAuto() {
  906. var dt = this.s.dt;
  907. var columns = this.s.columns;
  908. // Are we allowed to do auto sizing?
  909. if (!this.c.auto) {
  910. return;
  911. }
  912. // Are there any columns that actually need auto-sizing, or do they all
  913. // have classes defined
  914. if ($.inArray(true, $.map(columns, function (c) {
  915. return c.auto;
  916. })) === - 1) {
  917. return;
  918. }
  919. // Need to restore all children. They will be reinstated by a re-render
  920. if (!$.isEmptyObject(_childNodeStore)) {
  921. $.each(_childNodeStore, function (key) {
  922. var idx = key.split('-');
  923. _childNodesRestore(dt, idx[0] * 1, idx[1] * 1);
  924. });
  925. }
  926. // Clone the table with the current data in it
  927. var tableWidth = dt.table().node().offsetWidth;
  928. var columnWidths = dt.columns;
  929. var clonedTable = dt.table().node().cloneNode(false);
  930. var clonedHeader = $(dt.table().header().cloneNode(false)).appendTo(clonedTable);
  931. var clonedBody = $(dt.table().body()).clone(false, false).empty().appendTo(clonedTable); // use jQuery because of IE8
  932. // Header
  933. var headerCells = dt.columns().header().filter(function (idx) {
  934. return dt.column(idx).visible();
  935. }).to$().clone(false).css('display', 'table-cell');
  936. // Body rows - we don't need to take account of DataTables' column
  937. // visibility since we implement our own here (hence the `display` set)
  938. $(clonedBody).append($(dt.rows({page: 'current'}).nodes()).clone(false)).find('th, td').css('display', '');
  939. // Footer
  940. var footer = dt.table().footer();
  941. if (footer) {
  942. var clonedFooter = $(footer.cloneNode(false)).appendTo(clonedTable);
  943. var footerCells = dt.columns().footer().filter(function (idx) {
  944. return dt.column(idx).visible();
  945. }).to$().clone(false).css('display', 'table-cell');
  946. $('<tr/>').append(footerCells).appendTo(clonedFooter);
  947. }
  948. $('<tr/>').append(headerCells).appendTo(clonedHeader);
  949. // In the inline case extra padding is applied to the first column to
  950. // give space for the show / hide icon. We need to use this in the
  951. // calculation
  952. if (this.c.details.type === 'inline') {
  953. $(clonedTable).addClass('dtr-inline collapsed');
  954. }
  955. // It is unsafe to insert elements with the same name into the DOM
  956. // multiple times. For example, cloning and inserting a checked radio
  957. // clears the chcecked state of the original radio.
  958. $(clonedTable).find('[name]').removeAttr('name');
  959. var inserted = $('<div/>').css({
  960. width: 1,
  961. height: 1,
  962. overflow: 'hidden',
  963. clear: 'both'
  964. }).append(clonedTable);
  965. inserted.insertBefore(dt.table().node());
  966. // The cloned header now contains the smallest that each column can be
  967. headerCells.each(function (i) {
  968. var idx = dt.column.index('fromVisible', i);
  969. columns[idx].minWidth = this.offsetWidth || 0;
  970. });
  971. inserted.remove();
  972. },
  973. /**
  974. * Set a column's visibility.
  975. *
  976. * We don't use DataTables' column visibility controls in order to ensure
  977. * that column visibility can Responsive can no-exist. Since only IE8+ is
  978. * supported (and all evergreen browsers of course) the control of the
  979. * display attribute works well.
  980. *
  981. * @param {integer} col Column index
  982. * @param {boolean} showHide Show or hide (true or false)
  983. * @private
  984. */
  985. _setColumnVis: function _setColumnVis(col, showHide) {
  986. var dt = this.s.dt;
  987. var display = showHide ? '' : 'none'; // empty string will remove the attr
  988. $(dt.column(col).header()).css('display', display);
  989. $(dt.column(col).footer()).css('display', display);
  990. dt.column(col).nodes().to$().css('display', display);
  991. // If the are child nodes stored, we might need to reinsert them
  992. if (!$.isEmptyObject(_childNodeStore)) {
  993. dt.cells(null, col).indexes().each(function (idx) {
  994. _childNodesRestore(dt, idx.row, idx.column);
  995. });
  996. }
  997. },
  998. /**
  999. * Update the cell tab indexes for keyboard accessibility. This is called on
  1000. * every table draw - that is potentially inefficient, but also the least
  1001. * complex option given that column visibility can change on the fly. Its a
  1002. * shame user-focus was removed from CSS 3 UI, as it would have solved this
  1003. * issue with a single CSS statement.
  1004. *
  1005. * @private
  1006. */
  1007. _tabIndexes: function _tabIndexes() {
  1008. var dt = this.s.dt;
  1009. var cells = dt.cells({page: 'current'}).nodes().to$();
  1010. var ctx = dt.settings()[0];
  1011. var target = this.c.details.target;
  1012. cells.filter('[data-dtr-keyboard]').removeData('[data-dtr-keyboard]');
  1013. var selector = typeof target === 'number' ? ':eq(' + target + ')' : target;
  1014. // This is a bit of a hack - we need to limit the selected nodes to just
  1015. // those of this table
  1016. if (selector === 'td:first-child, th:first-child') {
  1017. selector = '>td:first-child, >th:first-child';
  1018. }
  1019. $(selector, dt.rows({page: 'current'}).nodes()).attr('tabIndex', ctx.iTabIndex).data('dtr-keyboard', 1);
  1020. }
  1021. });
  1022. /**
  1023. * List of default breakpoints. Each item in the array is an object with two
  1024. * properties:
  1025. *
  1026. * * `name` - the breakpoint name.
  1027. * * `width` - the breakpoint width
  1028. *
  1029. * @name Responsive.breakpoints
  1030. * @static
  1031. */
  1032. Responsive.breakpoints = [{name: 'desktop', width: Infinity}, {name: 'tablet-l', width: 1024}, {name: 'tablet-p', width: 768}, {name: 'mobile-l', width: 480}, {name: 'mobile-p', width: 320}];
  1033. /**
  1034. * Display methods - functions which define how the hidden data should be shown
  1035. * in the table.
  1036. *
  1037. * @namespace
  1038. * @name Responsive.defaults
  1039. * @static
  1040. */
  1041. Responsive.display = {
  1042. childRow: function childRow(row, update, render) {
  1043. if (update) {
  1044. if ($(row.node()).hasClass('parent')) {
  1045. row.child(render(), 'child').show();
  1046. return true;
  1047. }
  1048. } else {
  1049. if (!row.child.isShown()) {
  1050. row.child(render(), 'child').show();
  1051. $(row.node()).addClass('parent');
  1052. return true;
  1053. } else {
  1054. row.child(false);
  1055. $(row.node()).removeClass('parent');
  1056. return false;
  1057. }
  1058. }
  1059. },
  1060. childRowImmediate: function childRowImmediate(row, update, render) {
  1061. if (!update && row.child.isShown() || !row.responsive.hasHidden()) {
  1062. // User interaction and the row is show, or nothing to show
  1063. row.child(false);
  1064. $(row.node()).removeClass('parent');
  1065. return false;
  1066. } else {
  1067. // Display
  1068. row.child(render(), 'child').show();
  1069. $(row.node()).addClass('parent');
  1070. return true;
  1071. }
  1072. },
  1073. // This is a wrapper so the modal options for Bootstrap and jQuery UI can
  1074. // have options passed into them. This specific one doesn't need to be a
  1075. // function but it is for consistency in the `modal` name
  1076. modal: function modal(options) {
  1077. return function (row, update, render) {
  1078. if (!update) {
  1079. // Show a modal
  1080. var close = function close() {
  1081. modal.remove(); // will tidy events for us
  1082. $(document).off('keypress.dtr');
  1083. };
  1084. var modal = $('<div class="dtr-modal"/>').append($('<div class="dtr-modal-display"/>').append($('<div class="dtr-modal-content"/>').append(render())).append($('<div class="dtr-modal-close">&times;</div>').click(function () {
  1085. close();
  1086. }))).append($('<div class="dtr-modal-background"/>').click(function () {
  1087. close();
  1088. })).appendTo('body');
  1089. $(document).on('keyup.dtr', function (e) {
  1090. if (e.keyCode === 27) {
  1091. e.stopPropagation();
  1092. close();
  1093. }
  1094. });
  1095. } else {
  1096. $('div.dtr-modal-content').empty().append(render());
  1097. }
  1098. if (options && options.header) {
  1099. $('div.dtr-modal-content').prepend('<h2>' + options.header(row) + '</h2>');
  1100. }
  1101. };
  1102. }
  1103. };
  1104. var _childNodeStore = {};
  1105. function _childNodes(dt, row, col) {
  1106. var name = row + '-' + col;
  1107. if (_childNodeStore[name]) {
  1108. return _childNodeStore[name];
  1109. }
  1110. // https://jsperf.com/childnodes-array-slice-vs-loop
  1111. var nodes = [];
  1112. var children = dt.cell(row, col).node().childNodes;
  1113. for (var i = 0, ien = children.length; i < ien; i++) {
  1114. nodes.push(children[i]);
  1115. }
  1116. _childNodeStore[name] = nodes;
  1117. return nodes;
  1118. }
  1119. function _childNodesRestore(dt, row, col) {
  1120. var name = row + '-' + col;
  1121. if (!_childNodeStore[name]) {
  1122. return;
  1123. }
  1124. var node = dt.cell(row, col).node();
  1125. var store = _childNodeStore[name];
  1126. var parent = store[0].parentNode;
  1127. var parentChildren = parent.childNodes;
  1128. var a = [];
  1129. for (var i = 0, ien = parentChildren.length; i < ien; i++) {
  1130. a.push(parentChildren[i]);
  1131. }
  1132. for (var j = 0, jen = a.length; j < jen; j++) {
  1133. node.appendChild(a[j]);
  1134. }
  1135. _childNodeStore[name] = undefined;
  1136. }
  1137. /**
  1138. * Display methods - functions which define how the hidden data should be shown
  1139. * in the table.
  1140. *
  1141. * @namespace
  1142. * @name Responsive.defaults
  1143. * @static
  1144. */
  1145. Responsive.renderer = {
  1146. listHiddenNodes: function listHiddenNodes() {
  1147. return function (api, rowIdx, columns) {
  1148. var ul = $('<ul data-dtr-index="' + rowIdx + '" class="dtr-details"/>');
  1149. var found = false;
  1150. var data = $.each(columns, function (i, col) {
  1151. if (col.hidden) {
  1152. $('<li data-dtr-index="' + col.columnIndex + '" data-dt-row="' + col.rowIndex + '" data-dt-column="' + col.columnIndex + '">' + '<span class="dtr-title">' + col.title + '</span> ' + '</li>').append($('<span class="dtr-data"/>').append(_childNodes(api, col.rowIndex, col.columnIndex))) // api.cell( col.rowIndex, col.columnIndex ).node().childNodes ) )
  1153. .appendTo(ul);
  1154. found = true;
  1155. }
  1156. });
  1157. return found ? ul : false;
  1158. };
  1159. },
  1160. listHidden: function listHidden() {
  1161. return function (api, rowIdx, columns) {
  1162. var data = $.map(columns, function (col) {
  1163. return col.hidden ? '<li data-dtr-index="' + col.columnIndex + '" data-dt-row="' + col.rowIndex + '" data-dt-column="' + col.columnIndex + '">' + '<span class="dtr-title">' + col.title + '</span> ' + '<span class="dtr-data">' + col.data + '</span>' + '</li>' : '';
  1164. }).join('');
  1165. return data ? $('<ul data-dtr-index="' + rowIdx + '" class="dtr-details"/>').append(data) : false;
  1166. };
  1167. },
  1168. tableAll: function tableAll(options) {
  1169. options = $.extend({
  1170. tableClass: ''
  1171. }, options);
  1172. return function (api, rowIdx, columns) {
  1173. var data = $.map(columns, function (col) {
  1174. return '<tr data-dt-row="' + col.rowIndex + '" data-dt-column="' + col.columnIndex + '">' + '<td>' + col.title + ':' + '</td> ' + '<td>' + col.data + '</td>' + '</tr>';
  1175. }).join('');
  1176. return $('<table class="' + options.tableClass + ' dtr-details" width="100%"/>').append(data);
  1177. };
  1178. }
  1179. };
  1180. /**
  1181. * Responsive default settings for initialisation
  1182. *
  1183. * @namespace
  1184. * @name Responsive.defaults
  1185. * @static
  1186. */
  1187. Responsive.defaults = {
  1188. /**
  1189. * List of breakpoints for the instance. Note that this means that each
  1190. * instance can have its own breakpoints. Additionally, the breakpoints
  1191. * cannot be changed once an instance has been creased.
  1192. *
  1193. * @type {Array}
  1194. * @default Takes the value of `Responsive.breakpoints`
  1195. */
  1196. breakpoints: Responsive.breakpoints,
  1197. /**
  1198. * Enable / disable auto hiding calculations. It can help to increase
  1199. * performance slightly if you disable this option, but all columns would
  1200. * need to have breakpoint classes assigned to them
  1201. *
  1202. * @type {Boolean}
  1203. * @default `true`
  1204. */
  1205. auto: true,
  1206. /**
  1207. * Details control. If given as a string value, the `type` property of the
  1208. * default object is set to that value, and the defaults used for the rest
  1209. * of the object - this is for ease of implementation.
  1210. *
  1211. * The object consists of the following properties:
  1212. *
  1213. * * `display` - A function that is used to show and hide the hidden details
  1214. * * `renderer` - function that is called for display of the child row data.
  1215. * The default function will show the data from the hidden columns
  1216. * * `target` - Used as the selector for what objects to attach the child
  1217. * open / close to
  1218. * * `type` - `false` to disable the details display, `inline` or `column`
  1219. * for the two control types
  1220. *
  1221. * @type {Object|string}
  1222. */
  1223. details: {
  1224. display: Responsive.display.childRow,
  1225. renderer: Responsive.renderer.listHidden(),
  1226. target: 0,
  1227. type: 'inline'
  1228. },
  1229. /**
  1230. * Orthogonal data request option. This is used to define the data type
  1231. * requested when Responsive gets the data to show in the child row.
  1232. *
  1233. * @type {String}
  1234. */
  1235. orthogonal: 'display'
  1236. };
  1237. /*
  1238. * API
  1239. */
  1240. var Api = $.fn.dataTable.Api;
  1241. // Doesn't do anything - work around for a bug in DT... Not documented
  1242. Api.register('responsive()', function () {
  1243. return this;
  1244. });
  1245. Api.register('responsive.index()', function (li) {
  1246. li = $(li);
  1247. return {
  1248. column: li.data('dtr-index'),
  1249. row: li.parent().data('dtr-index')
  1250. };
  1251. });
  1252. Api.register('responsive.rebuild()', function () {
  1253. return this.iterator('table', function (ctx) {
  1254. if (ctx._responsive) {
  1255. ctx._responsive._classLogic();
  1256. }
  1257. });
  1258. });
  1259. Api.register('responsive.recalc()', function () {
  1260. return this.iterator('table', function (ctx) {
  1261. if (ctx._responsive) {
  1262. ctx._responsive._resizeAuto();
  1263. ctx._responsive._resize();
  1264. }
  1265. });
  1266. });
  1267. Api.register('responsive.hasHidden()', function () {
  1268. var ctx = this.context[0];
  1269. return ctx._responsive ? $.inArray(false, ctx._responsive.s.current) !== - 1 : false;
  1270. });
  1271. /**
  1272. * Version information
  1273. *
  1274. * @name Responsive.version
  1275. * @static
  1276. */
  1277. Responsive.version = '2.2.0';
  1278. $.fn.dataTable.Responsive = Responsive;
  1279. $.fn.DataTable.Responsive = Responsive;
  1280. // Attach a listener to the document which listens for DataTables initialisation
  1281. // events so we can automatically initialise
  1282. $(document).on('preInit.dt.dtr', function (e, settings, json) {
  1283. if (e.namespace !== 'dt') {
  1284. return;
  1285. }
  1286. if ($(settings.nTable).hasClass('responsive') || $(settings.nTable).hasClass('dt-responsive') || settings.oInit.responsive || DataTable.defaults.responsive) {
  1287. var init = settings.oInit.responsive;
  1288. if (init !== false) {
  1289. new Responsive(settings, $.isPlainObject(init) ? init : {});
  1290. }
  1291. }
  1292. });
  1293. return Responsive;
  1294. });
  1295. /***/ }),
  1296. /***/ 2:
  1297. /***/ (function (module, exports, __webpack_require__) {
  1298. "use strict";
  1299. var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
  1300. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  1301. return typeof obj;
  1302. } : function (obj) {
  1303. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  1304. };
  1305. /*! DataTables 1.10.16
  1306. * ©2008-2017 SpryMedia Ltd - datatables.net/license
  1307. */
  1308. /**
  1309. * @summary DataTables
  1310. * @description Paginate, search and order HTML tables
  1311. * @version 1.10.16
  1312. * @file jquery.dataTables.js
  1313. * @author SpryMedia Ltd
  1314. * @contact www.datatables.net
  1315. * @copyright Copyright 2008-2017 SpryMedia Ltd.
  1316. *
  1317. * This source file is free software, available under the following license:
  1318. * MIT license - http://datatables.net/license
  1319. *
  1320. * This source file is distributed in the hope that it will be useful, but
  1321. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  1322. * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  1323. *
  1324. * For details please refer to: http://www.datatables.net
  1325. */
  1326. /*jslint evil: true, undef: true, browser: true */
  1327. /*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
  1328. (function (factory) {
  1329. "use strict";
  1330. if (true) {
  1331. // AMD
  1332. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)], __WEBPACK_AMD_DEFINE_RESULT__ = function ($) {
  1333. return factory($, window, document);
  1334. }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
  1335. __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  1336. } else if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
  1337. // CommonJS
  1338. module.exports = function (root, $) {
  1339. if (!root) {
  1340. // CommonJS environments without a window global must pass a
  1341. // root. This will give an error otherwise
  1342. root = window;
  1343. }
  1344. if (!$) {
  1345. $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
  1346. require('jquery') : require('jquery')(root);
  1347. }
  1348. return factory($, root, root.document);
  1349. };
  1350. } else {
  1351. // Browser
  1352. factory(jQuery, window, document);
  1353. }
  1354. })(function ($, window, document, undefined) {
  1355. "use strict";
  1356. /**
  1357. * DataTables is a plug-in for the jQuery Javascript library. It is a highly
  1358. * flexible tool, based upon the foundations of progressive enhancement,
  1359. * which will add advanced interaction controls to any HTML table. For a
  1360. * full list of features please refer to
  1361. * [DataTables.net](href="http://datatables.net).
  1362. *
  1363. * Note that the `DataTable` object is not a global variable but is aliased
  1364. * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
  1365. * be accessed.
  1366. *
  1367. * @class
  1368. * @param {object} [init={}] Configuration object for DataTables. Options
  1369. * are defined by {@link DataTable.defaults}
  1370. * @requires jQuery 1.7+
  1371. *
  1372. * @example
  1373. * // Basic initialisation
  1374. * $(document).ready( function {
  1375. * $('#example').dataTable();
  1376. * } );
  1377. *
  1378. * @example
  1379. * // Initialisation with configuration options - in this case, disable
  1380. * // pagination and sorting.
  1381. * $(document).ready( function {
  1382. * $('#example').dataTable( {
  1383. * "paginate": false,
  1384. * "sort": false
  1385. * } );
  1386. * } );
  1387. */
  1388. var DataTable = function DataTable(options) {
  1389. /**
  1390. * Perform a jQuery selector action on the table's TR elements (from the tbody) and
  1391. * return the resulting jQuery object.
  1392. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  1393. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  1394. * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
  1395. * criterion ("applied") or all TR elements (i.e. no filter).
  1396. * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
  1397. * Can be either 'current', whereby the current sorting of the table is used, or
  1398. * 'original' whereby the original order the data was read into the table is used.
  1399. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  1400. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  1401. * 'current' and filter is 'applied', regardless of what they might be given as.
  1402. * @returns {object} jQuery object, filtered by the given selector.
  1403. * @dtopt API
  1404. * @deprecated Since v1.10
  1405. *
  1406. * @example
  1407. * $(document).ready(function() {
  1408. * var oTable = $('#example').dataTable();
  1409. *
  1410. * // Highlight every second row
  1411. * oTable.$('tr:odd').css('backgroundColor', 'blue');
  1412. * } );
  1413. *
  1414. * @example
  1415. * $(document).ready(function() {
  1416. * var oTable = $('#example').dataTable();
  1417. *
  1418. * // Filter to rows with 'Webkit' in them, add a background colour and then
  1419. * // remove the filter, thus highlighting the 'Webkit' rows only.
  1420. * oTable.fnFilter('Webkit');
  1421. * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
  1422. * oTable.fnFilter('');
  1423. * } );
  1424. */
  1425. this.$ = function (sSelector, oOpts) {
  1426. return this.api(true).$(sSelector, oOpts);
  1427. };
  1428. /**
  1429. * Almost identical to $ in operation, but in this case returns the data for the matched
  1430. * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
  1431. * rather than any descendants, so the data can be obtained for the row/cell. If matching
  1432. * rows are found, the data returned is the original data array/object that was used to
  1433. * create the row (or a generated array if from a DOM source).
  1434. *
  1435. * This method is often useful in-combination with $ where both functions are given the
  1436. * same parameters and the array indexes will match identically.
  1437. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  1438. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  1439. * @param {string} [oOpts.filter=none] Select elements that meet the current filter
  1440. * criterion ("applied") or all elements (i.e. no filter).
  1441. * @param {string} [oOpts.order=current] Order of the data in the processed array.
  1442. * Can be either 'current', whereby the current sorting of the table is used, or
  1443. * 'original' whereby the original order the data was read into the table is used.
  1444. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  1445. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  1446. * 'current' and filter is 'applied', regardless of what they might be given as.
  1447. * @returns {array} Data for the matched elements. If any elements, as a result of the
  1448. * selector, were not TR, TD or TH elements in the DataTable, they will have a null
  1449. * entry in the array.
  1450. * @dtopt API
  1451. * @deprecated Since v1.10
  1452. *
  1453. * @example
  1454. * $(document).ready(function() {
  1455. * var oTable = $('#example').dataTable();
  1456. *
  1457. * // Get the data from the first row in the table
  1458. * var data = oTable._('tr:first');
  1459. *
  1460. * // Do something useful with the data
  1461. * alert( "First cell is: "+data[0] );
  1462. * } );
  1463. *
  1464. * @example
  1465. * $(document).ready(function() {
  1466. * var oTable = $('#example').dataTable();
  1467. *
  1468. * // Filter to 'Webkit' and get all data for
  1469. * oTable.fnFilter('Webkit');
  1470. * var data = oTable._('tr', {"search": "applied"});
  1471. *
  1472. * // Do something with the data
  1473. * alert( data.length+" rows matched the search" );
  1474. * } );
  1475. */
  1476. this._ = function (sSelector, oOpts) {
  1477. return this.api(true).rows(sSelector, oOpts).data();
  1478. };
  1479. /**
  1480. * Create a DataTables Api instance, with the currently selected tables for
  1481. * the Api's context.
  1482. * @param {boolean} [traditional=false] Set the API instance's context to be
  1483. * only the table referred to by the `DataTable.ext.iApiIndex` option, as was
  1484. * used in the API presented by DataTables 1.9- (i.e. the traditional mode),
  1485. * or if all tables captured in the jQuery object should be used.
  1486. * @return {DataTables.Api}
  1487. */
  1488. this.api = function (traditional) {
  1489. return traditional ? new _Api2(_fnSettingsFromNode(this[_ext.iApiIndex])) : new _Api2(this);
  1490. };
  1491. /**
  1492. * Add a single new row or multiple rows of data to the table. Please note
  1493. * that this is suitable for client-side processing only - if you are using
  1494. * server-side processing (i.e. "bServerSide": true), then to add data, you
  1495. * must add it to the data source, i.e. the server-side, through an Ajax call.
  1496. * @param {array|object} data The data to be added to the table. This can be:
  1497. * <ul>
  1498. * <li>1D array of data - add a single row with the data provided</li>
  1499. * <li>2D array of arrays - add multiple rows in a single call</li>
  1500. * <li>object - data object when using <i>mData</i></li>
  1501. * <li>array of objects - multiple data objects when using <i>mData</i></li>
  1502. * </ul>
  1503. * @param {bool} [redraw=true] redraw the table or not
  1504. * @returns {array} An array of integers, representing the list of indexes in
  1505. * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
  1506. * the table.
  1507. * @dtopt API
  1508. * @deprecated Since v1.10
  1509. *
  1510. * @example
  1511. * // Global var for counter
  1512. * var giCount = 2;
  1513. *
  1514. * $(document).ready(function() {
  1515. * $('#example').dataTable();
  1516. * } );
  1517. *
  1518. * function fnClickAddRow() {
  1519. * $('#example').dataTable().fnAddData( [
  1520. * giCount+".1",
  1521. * giCount+".2",
  1522. * giCount+".3",
  1523. * giCount+".4" ]
  1524. * );
  1525. *
  1526. * giCount++;
  1527. * }
  1528. */
  1529. this.fnAddData = function (data, redraw) {
  1530. var api = this.api(true);
  1531. /* Check if we want to add multiple rows or not */
  1532. var rows = $.isArray(data) && ($.isArray(data[0]) || $.isPlainObject(data[0])) ? api.rows.add(data) : api.row.add(data);
  1533. if (redraw === undefined || redraw) {
  1534. api.draw();
  1535. }
  1536. return rows.flatten().toArray();
  1537. };
  1538. /**
  1539. * This function will make DataTables recalculate the column sizes, based on the data
  1540. * contained in the table and the sizes applied to the columns (in the DOM, CSS or
  1541. * through the sWidth parameter). This can be useful when the width of the table's
  1542. * parent element changes (for example a window resize).
  1543. * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
  1544. * @dtopt API
  1545. * @deprecated Since v1.10
  1546. *
  1547. * @example
  1548. * $(document).ready(function() {
  1549. * var oTable = $('#example').dataTable( {
  1550. * "sScrollY": "200px",
  1551. * "bPaginate": false
  1552. * } );
  1553. *
  1554. * $(window).on('resize', function () {
  1555. * oTable.fnAdjustColumnSizing();
  1556. * } );
  1557. * } );
  1558. */
  1559. this.fnAdjustColumnSizing = function (bRedraw) {
  1560. var api = this.api(true).columns.adjust();
  1561. var settings = api.settings()[0];
  1562. var scroll = settings.oScroll;
  1563. if (bRedraw === undefined || bRedraw) {
  1564. api.draw(false);
  1565. } else if (scroll.sX !== "" || scroll.sY !== "") {
  1566. /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
  1567. _fnScrollDraw(settings);
  1568. }
  1569. };
  1570. /**
  1571. * Quickly and simply clear a table
  1572. * @param {bool} [bRedraw=true] redraw the table or not
  1573. * @dtopt API
  1574. * @deprecated Since v1.10
  1575. *
  1576. * @example
  1577. * $(document).ready(function() {
  1578. * var oTable = $('#example').dataTable();
  1579. *
  1580. * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
  1581. * oTable.fnClearTable();
  1582. * } );
  1583. */
  1584. this.fnClearTable = function (bRedraw) {
  1585. var api = this.api(true).clear();
  1586. if (bRedraw === undefined || bRedraw) {
  1587. api.draw();
  1588. }
  1589. };
  1590. /**
  1591. * The exact opposite of 'opening' a row, this function will close any rows which
  1592. * are currently 'open'.
  1593. * @param {node} nTr the table row to 'close'
  1594. * @returns {int} 0 on success, or 1 if failed (can't find the row)
  1595. * @dtopt API
  1596. * @deprecated Since v1.10
  1597. *
  1598. * @example
  1599. * $(document).ready(function() {
  1600. * var oTable;
  1601. *
  1602. * // 'open' an information row when a row is clicked on
  1603. * $('#example tbody tr').click( function () {
  1604. * if ( oTable.fnIsOpen(this) ) {
  1605. * oTable.fnClose( this );
  1606. * } else {
  1607. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  1608. * }
  1609. * } );
  1610. *
  1611. * oTable = $('#example').dataTable();
  1612. * } );
  1613. */
  1614. this.fnClose = function (nTr) {
  1615. this.api(true).row(nTr).child.hide();
  1616. };
  1617. /**
  1618. * Remove a row for the table
  1619. * @param {mixed} target The index of the row from aoData to be deleted, or
  1620. * the TR element you want to delete
  1621. * @param {function|null} [callBack] Callback function
  1622. * @param {bool} [redraw=true] Redraw the table or not
  1623. * @returns {array} The row that was deleted
  1624. * @dtopt API
  1625. * @deprecated Since v1.10
  1626. *
  1627. * @example
  1628. * $(document).ready(function() {
  1629. * var oTable = $('#example').dataTable();
  1630. *
  1631. * // Immediately remove the first row
  1632. * oTable.fnDeleteRow( 0 );
  1633. * } );
  1634. */
  1635. this.fnDeleteRow = function (target, callback, redraw) {
  1636. var api = this.api(true);
  1637. var rows = api.rows(target);
  1638. var settings = rows.settings()[0];
  1639. var data = settings.aoData[rows[0][0]];
  1640. rows.remove();
  1641. if (callback) {
  1642. callback.call(this, settings, data);
  1643. }
  1644. if (redraw === undefined || redraw) {
  1645. api.draw();
  1646. }
  1647. return data;
  1648. };
  1649. /**
  1650. * Restore the table to it's original state in the DOM by removing all of DataTables
  1651. * enhancements, alterations to the DOM structure of the table and event listeners.
  1652. * @param {boolean} [remove=false] Completely remove the table from the DOM
  1653. * @dtopt API
  1654. * @deprecated Since v1.10
  1655. *
  1656. * @example
  1657. * $(document).ready(function() {
  1658. * // This example is fairly pointless in reality, but shows how fnDestroy can be used
  1659. * var oTable = $('#example').dataTable();
  1660. * oTable.fnDestroy();
  1661. * } );
  1662. */
  1663. this.fnDestroy = function (remove) {
  1664. this.api(true).destroy(remove);
  1665. };
  1666. /**
  1667. * Redraw the table
  1668. * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
  1669. * @dtopt API
  1670. * @deprecated Since v1.10
  1671. *
  1672. * @example
  1673. * $(document).ready(function() {
  1674. * var oTable = $('#example').dataTable();
  1675. *
  1676. * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
  1677. * oTable.fnDraw();
  1678. * } );
  1679. */
  1680. this.fnDraw = function (complete) {
  1681. // Note that this isn't an exact match to the old call to _fnDraw - it takes
  1682. // into account the new data, but can hold position.
  1683. this.api(true).draw(complete);
  1684. };
  1685. /**
  1686. * Filter the input based on data
  1687. * @param {string} sInput String to filter the table on
  1688. * @param {int|null} [iColumn] Column to limit filtering to
  1689. * @param {bool} [bRegex=false] Treat as regular expression or not
  1690. * @param {bool} [bSmart=true] Perform smart filtering or not
  1691. * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
  1692. * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
  1693. * @dtopt API
  1694. * @deprecated Since v1.10
  1695. *
  1696. * @example
  1697. * $(document).ready(function() {
  1698. * var oTable = $('#example').dataTable();
  1699. *
  1700. * // Sometime later - filter...
  1701. * oTable.fnFilter( 'test string' );
  1702. * } );
  1703. */
  1704. this.fnFilter = function (sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive) {
  1705. var api = this.api(true);
  1706. if (iColumn === null || iColumn === undefined) {
  1707. api.search(sInput, bRegex, bSmart, bCaseInsensitive);
  1708. } else {
  1709. api.column(iColumn).search(sInput, bRegex, bSmart, bCaseInsensitive);
  1710. }
  1711. api.draw();
  1712. };
  1713. /**
  1714. * Get the data for the whole table, an individual row or an individual cell based on the
  1715. * provided parameters.
  1716. * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
  1717. * a TR node then the data source for the whole row will be returned. If given as a
  1718. * TD/TH cell node then iCol will be automatically calculated and the data for the
  1719. * cell returned. If given as an integer, then this is treated as the aoData internal
  1720. * data index for the row (see fnGetPosition) and the data for that row used.
  1721. * @param {int} [col] Optional column index that you want the data of.
  1722. * @returns {array|object|string} If mRow is undefined, then the data for all rows is
  1723. * returned. If mRow is defined, just data for that row, and is iCol is
  1724. * defined, only data for the designated cell is returned.
  1725. * @dtopt API
  1726. * @deprecated Since v1.10
  1727. *
  1728. * @example
  1729. * // Row data
  1730. * $(document).ready(function() {
  1731. * oTable = $('#example').dataTable();
  1732. *
  1733. * oTable.$('tr').click( function () {
  1734. * var data = oTable.fnGetData( this );
  1735. * // ... do something with the array / object of data for the row
  1736. * } );
  1737. * } );
  1738. *
  1739. * @example
  1740. * // Individual cell data
  1741. * $(document).ready(function() {
  1742. * oTable = $('#example').dataTable();
  1743. *
  1744. * oTable.$('td').click( function () {
  1745. * var sData = oTable.fnGetData( this );
  1746. * alert( 'The cell clicked on had the value of '+sData );
  1747. * } );
  1748. * } );
  1749. */
  1750. this.fnGetData = function (src, col) {
  1751. var api = this.api(true);
  1752. if (src !== undefined) {
  1753. var type = src.nodeName ? src.nodeName.toLowerCase() : '';
  1754. return col !== undefined || type == 'td' || type == 'th' ? api.cell(src, col).data() : api.row(src).data() || null;
  1755. }
  1756. return api.data().toArray();
  1757. };
  1758. /**
  1759. * Get an array of the TR nodes that are used in the table's body. Note that you will
  1760. * typically want to use the '$' API method in preference to this as it is more
  1761. * flexible.
  1762. * @param {int} [iRow] Optional row index for the TR element you want
  1763. * @returns {array|node} If iRow is undefined, returns an array of all TR elements
  1764. * in the table's body, or iRow is defined, just the TR element requested.
  1765. * @dtopt API
  1766. * @deprecated Since v1.10
  1767. *
  1768. * @example
  1769. * $(document).ready(function() {
  1770. * var oTable = $('#example').dataTable();
  1771. *
  1772. * // Get the nodes from the table
  1773. * var nNodes = oTable.fnGetNodes( );
  1774. * } );
  1775. */
  1776. this.fnGetNodes = function (iRow) {
  1777. var api = this.api(true);
  1778. return iRow !== undefined ? api.row(iRow).node() : api.rows().nodes().flatten().toArray();
  1779. };
  1780. /**
  1781. * Get the array indexes of a particular cell from it's DOM element
  1782. * and column index including hidden columns
  1783. * @param {node} node this can either be a TR, TD or TH in the table's body
  1784. * @returns {int} If nNode is given as a TR, then a single index is returned, or
  1785. * if given as a cell, an array of [row index, column index (visible),
  1786. * column index (all)] is given.
  1787. * @dtopt API
  1788. * @deprecated Since v1.10
  1789. *
  1790. * @example
  1791. * $(document).ready(function() {
  1792. * $('#example tbody td').click( function () {
  1793. * // Get the position of the current data from the node
  1794. * var aPos = oTable.fnGetPosition( this );
  1795. *
  1796. * // Get the data array for this row
  1797. * var aData = oTable.fnGetData( aPos[0] );
  1798. *
  1799. * // Update the data array and return the value
  1800. * aData[ aPos[1] ] = 'clicked';
  1801. * this.innerHTML = 'clicked';
  1802. * } );
  1803. *
  1804. * // Init DataTables
  1805. * oTable = $('#example').dataTable();
  1806. * } );
  1807. */
  1808. this.fnGetPosition = function (node) {
  1809. var api = this.api(true);
  1810. var nodeName = node.nodeName.toUpperCase();
  1811. if (nodeName == 'TR') {
  1812. return api.row(node).index();
  1813. } else if (nodeName == 'TD' || nodeName == 'TH') {
  1814. var cell = api.cell(node).index();
  1815. return [cell.row, cell.columnVisible, cell.column];
  1816. }
  1817. return null;
  1818. };
  1819. /**
  1820. * Check to see if a row is 'open' or not.
  1821. * @param {node} nTr the table row to check
  1822. * @returns {boolean} true if the row is currently open, false otherwise
  1823. * @dtopt API
  1824. * @deprecated Since v1.10
  1825. *
  1826. * @example
  1827. * $(document).ready(function() {
  1828. * var oTable;
  1829. *
  1830. * // 'open' an information row when a row is clicked on
  1831. * $('#example tbody tr').click( function () {
  1832. * if ( oTable.fnIsOpen(this) ) {
  1833. * oTable.fnClose( this );
  1834. * } else {
  1835. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  1836. * }
  1837. * } );
  1838. *
  1839. * oTable = $('#example').dataTable();
  1840. * } );
  1841. */
  1842. this.fnIsOpen = function (nTr) {
  1843. return this.api(true).row(nTr).child.isShown();
  1844. };
  1845. /**
  1846. * This function will place a new row directly after a row which is currently
  1847. * on display on the page, with the HTML contents that is passed into the
  1848. * function. This can be used, for example, to ask for confirmation that a
  1849. * particular record should be deleted.
  1850. * @param {node} nTr The table row to 'open'
  1851. * @param {string|node|jQuery} mHtml The HTML to put into the row
  1852. * @param {string} sClass Class to give the new TD cell
  1853. * @returns {node} The row opened. Note that if the table row passed in as the
  1854. * first parameter, is not found in the table, this method will silently
  1855. * return.
  1856. * @dtopt API
  1857. * @deprecated Since v1.10
  1858. *
  1859. * @example
  1860. * $(document).ready(function() {
  1861. * var oTable;
  1862. *
  1863. * // 'open' an information row when a row is clicked on
  1864. * $('#example tbody tr').click( function () {
  1865. * if ( oTable.fnIsOpen(this) ) {
  1866. * oTable.fnClose( this );
  1867. * } else {
  1868. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  1869. * }
  1870. * } );
  1871. *
  1872. * oTable = $('#example').dataTable();
  1873. * } );
  1874. */
  1875. this.fnOpen = function (nTr, mHtml, sClass) {
  1876. return this.api(true).row(nTr).child(mHtml, sClass).show().child()[0];
  1877. };
  1878. /**
  1879. * Change the pagination - provides the internal logic for pagination in a simple API
  1880. * function. With this function you can have a DataTables table go to the next,
  1881. * previous, first or last pages.
  1882. * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
  1883. * or page number to jump to (integer), note that page 0 is the first page.
  1884. * @param {bool} [bRedraw=true] Redraw the table or not
  1885. * @dtopt API
  1886. * @deprecated Since v1.10
  1887. *
  1888. * @example
  1889. * $(document).ready(function() {
  1890. * var oTable = $('#example').dataTable();
  1891. * oTable.fnPageChange( 'next' );
  1892. * } );
  1893. */
  1894. this.fnPageChange = function (mAction, bRedraw) {
  1895. var api = this.api(true).page(mAction);
  1896. if (bRedraw === undefined || bRedraw) {
  1897. api.draw(false);
  1898. }
  1899. };
  1900. /**
  1901. * Show a particular column
  1902. * @param {int} iCol The column whose display should be changed
  1903. * @param {bool} bShow Show (true) or hide (false) the column
  1904. * @param {bool} [bRedraw=true] Redraw the table or not
  1905. * @dtopt API
  1906. * @deprecated Since v1.10
  1907. *
  1908. * @example
  1909. * $(document).ready(function() {
  1910. * var oTable = $('#example').dataTable();
  1911. *
  1912. * // Hide the second column after initialisation
  1913. * oTable.fnSetColumnVis( 1, false );
  1914. * } );
  1915. */
  1916. this.fnSetColumnVis = function (iCol, bShow, bRedraw) {
  1917. var api = this.api(true).column(iCol).visible(bShow);
  1918. if (bRedraw === undefined || bRedraw) {
  1919. api.columns.adjust().draw();
  1920. }
  1921. };
  1922. /**
  1923. * Get the settings for a particular table for external manipulation
  1924. * @returns {object} DataTables settings object. See
  1925. * {@link DataTable.models.oSettings}
  1926. * @dtopt API
  1927. * @deprecated Since v1.10
  1928. *
  1929. * @example
  1930. * $(document).ready(function() {
  1931. * var oTable = $('#example').dataTable();
  1932. * var oSettings = oTable.fnSettings();
  1933. *
  1934. * // Show an example parameter from the settings
  1935. * alert( oSettings._iDisplayStart );
  1936. * } );
  1937. */
  1938. this.fnSettings = function () {
  1939. return _fnSettingsFromNode(this[_ext.iApiIndex]);
  1940. };
  1941. /**
  1942. * Sort the table by a particular column
  1943. * @param {int} iCol the data index to sort on. Note that this will not match the
  1944. * 'display index' if you have hidden data entries
  1945. * @dtopt API
  1946. * @deprecated Since v1.10
  1947. *
  1948. * @example
  1949. * $(document).ready(function() {
  1950. * var oTable = $('#example').dataTable();
  1951. *
  1952. * // Sort immediately with columns 0 and 1
  1953. * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
  1954. * } );
  1955. */
  1956. this.fnSort = function (aaSort) {
  1957. this.api(true).order(aaSort).draw();
  1958. };
  1959. /**
  1960. * Attach a sort listener to an element for a given column
  1961. * @param {node} nNode the element to attach the sort listener to
  1962. * @param {int} iColumn the column that a click on this node will sort on
  1963. * @param {function} [fnCallback] callback function when sort is run
  1964. * @dtopt API
  1965. * @deprecated Since v1.10
  1966. *
  1967. * @example
  1968. * $(document).ready(function() {
  1969. * var oTable = $('#example').dataTable();
  1970. *
  1971. * // Sort on column 1, when 'sorter' is clicked on
  1972. * oTable.fnSortListener( document.getElementById('sorter'), 1 );
  1973. * } );
  1974. */
  1975. this.fnSortListener = function (nNode, iColumn, fnCallback) {
  1976. this.api(true).order.listener(nNode, iColumn, fnCallback);
  1977. };
  1978. /**
  1979. * Update a table cell or row - this method will accept either a single value to
  1980. * update the cell with, an array of values with one element for each column or
  1981. * an object in the same format as the original data source. The function is
  1982. * self-referencing in order to make the multi column updates easier.
  1983. * @param {object|array|string} mData Data to update the cell/row with
  1984. * @param {node|int} mRow TR element you want to update or the aoData index
  1985. * @param {int} [iColumn] The column to update, give as null or undefined to
  1986. * update a whole row.
  1987. * @param {bool} [bRedraw=true] Redraw the table or not
  1988. * @param {bool} [bAction=true] Perform pre-draw actions or not
  1989. * @returns {int} 0 on success, 1 on error
  1990. * @dtopt API
  1991. * @deprecated Since v1.10
  1992. *
  1993. * @example
  1994. * $(document).ready(function() {
  1995. * var oTable = $('#example').dataTable();
  1996. * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
  1997. * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
  1998. * } );
  1999. */
  2000. this.fnUpdate = function (mData, mRow, iColumn, bRedraw, bAction) {
  2001. var api = this.api(true);
  2002. if (iColumn === undefined || iColumn === null) {
  2003. api.row(mRow).data(mData);
  2004. } else {
  2005. api.cell(mRow, iColumn).data(mData);
  2006. }
  2007. if (bAction === undefined || bAction) {
  2008. api.columns.adjust();
  2009. }
  2010. if (bRedraw === undefined || bRedraw) {
  2011. api.draw();
  2012. }
  2013. return 0;
  2014. };
  2015. /**
  2016. * Provide a common method for plug-ins to check the version of DataTables being used, in order
  2017. * to ensure compatibility.
  2018. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
  2019. * formats "X" and "X.Y" are also acceptable.
  2020. * @returns {boolean} true if this version of DataTables is greater or equal to the required
  2021. * version, or false if this version of DataTales is not suitable
  2022. * @method
  2023. * @dtopt API
  2024. * @deprecated Since v1.10
  2025. *
  2026. * @example
  2027. * $(document).ready(function() {
  2028. * var oTable = $('#example').dataTable();
  2029. * alert( oTable.fnVersionCheck( '1.9.0' ) );
  2030. * } );
  2031. */
  2032. this.fnVersionCheck = _ext.fnVersionCheck;
  2033. var _that = this;
  2034. var emptyInit = options === undefined;
  2035. var len = this.length;
  2036. if (emptyInit) {
  2037. options = {};
  2038. }
  2039. this.oApi = this.internal = _ext.internal;
  2040. // Extend with old style plug-in API methods
  2041. for (var fn in DataTable.ext.internal) {
  2042. if (fn) {
  2043. this[fn] = _fnExternApiFunc(fn);
  2044. }
  2045. }
  2046. this.each(function () {
  2047. // For each initialisation we want to give it a clean initialisation
  2048. // object that can be bashed around
  2049. var o = {};
  2050. var oInit = len > 1 ? // optimisation for single table case
  2051. _fnExtend(o, options, true) : options;
  2052. /*global oInit,_that,emptyInit*/
  2053. var i = 0,
  2054. iLen,
  2055. j,
  2056. jLen,
  2057. k,
  2058. kLen;
  2059. var sId = this.getAttribute('id');
  2060. var bInitHandedOff = false;
  2061. var defaults = DataTable.defaults;
  2062. var $this = $(this);
  2063. /* Sanity check */
  2064. if (this.nodeName.toLowerCase() != 'table') {
  2065. _fnLog(null, 0, 'Non-table node initialisation (' + this.nodeName + ')', 2);
  2066. return;
  2067. }
  2068. /* Backwards compatibility for the defaults */
  2069. _fnCompatOpts(defaults);
  2070. _fnCompatCols(defaults.column);
  2071. /* Convert the camel-case defaults to Hungarian */
  2072. _fnCamelToHungarian(defaults, defaults, true);
  2073. _fnCamelToHungarian(defaults.column, defaults.column, true);
  2074. /* Setting up the initialisation object */
  2075. _fnCamelToHungarian(defaults, $.extend(oInit, $this.data()));
  2076. /* Check to see if we are re-initialising a table */
  2077. var allSettings = DataTable.settings;
  2078. for (i = 0, iLen = allSettings.length; i < iLen; i++) {
  2079. var s = allSettings[i];
  2080. /* Base check on table node */
  2081. if (s.nTable == this || s.nTHead.parentNode == this || s.nTFoot && s.nTFoot.parentNode == this) {
  2082. var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
  2083. var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
  2084. if (emptyInit || bRetrieve) {
  2085. return s.oInstance;
  2086. } else if (bDestroy) {
  2087. s.oInstance.fnDestroy();
  2088. break;
  2089. } else {
  2090. _fnLog(s, 0, 'Cannot reinitialise DataTable', 3);
  2091. return;
  2092. }
  2093. }
  2094. /* If the element we are initialising has the same ID as a table which was previously
  2095. * initialised, but the table nodes don't match (from before) then we destroy the old
  2096. * instance by simply deleting it. This is under the assumption that the table has been
  2097. * destroyed by other methods. Anyone using non-id selectors will need to do this manually
  2098. */
  2099. if (s.sTableId == this.id) {
  2100. allSettings.splice(i, 1);
  2101. break;
  2102. }
  2103. }
  2104. /* Ensure the table has an ID - required for accessibility */
  2105. if (sId === null || sId === "") {
  2106. sId = "DataTables_Table_" + DataTable.ext._unique++;
  2107. this.id = sId;
  2108. }
  2109. /* Create the settings object for this table and set some of the default parameters */
  2110. var oSettings = $.extend(true, {}, DataTable.models.oSettings, {
  2111. "sDestroyWidth": $this[0].style.width,
  2112. "sInstance": sId,
  2113. "sTableId": sId
  2114. });
  2115. oSettings.nTable = this;
  2116. oSettings.oApi = _that.internal;
  2117. oSettings.oInit = oInit;
  2118. allSettings.push(oSettings);
  2119. // Need to add the instance after the instance after the settings object has been added
  2120. // to the settings array, so we can self reference the table instance if more than one
  2121. oSettings.oInstance = _that.length === 1 ? _that : $this.dataTable();
  2122. // Backwards compatibility, before we apply all the defaults
  2123. _fnCompatOpts(oInit);
  2124. if (oInit.oLanguage) {
  2125. _fnLanguageCompat(oInit.oLanguage);
  2126. }
  2127. // If the length menu is given, but the init display length is not, use the length menu
  2128. if (oInit.aLengthMenu && !oInit.iDisplayLength) {
  2129. oInit.iDisplayLength = $.isArray(oInit.aLengthMenu[0]) ? oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
  2130. }
  2131. // Apply the defaults and init options to make a single init object will all
  2132. // options defined from defaults and instance options.
  2133. oInit = _fnExtend($.extend(true, {}, defaults), oInit);
  2134. // Map the initialisation options onto the settings object
  2135. _fnMap(oSettings.oFeatures, oInit, ["bPaginate", "bLengthChange", "bFilter", "bSort", "bSortMulti", "bInfo", "bProcessing", "bAutoWidth", "bSortClasses", "bServerSide", "bDeferRender"]);
  2136. _fnMap(oSettings, oInit, ["asStripeClasses", "ajax", "fnServerData", "fnFormatNumber", "sServerMethod", "aaSorting", "aaSortingFixed", "aLengthMenu", "sPaginationType", "sAjaxSource", "sAjaxDataProp", "iStateDuration", "sDom", "bSortCellsTop", "iTabIndex", "fnStateLoadCallback", "fnStateSaveCallback", "renderer", "searchDelay", "rowId", ["iCookieDuration", "iStateDuration"], // backwards compat
  2137. ["oSearch", "oPreviousSearch"], ["aoSearchCols", "aoPreSearchCols"], ["iDisplayLength", "_iDisplayLength"]]);
  2138. _fnMap(oSettings.oScroll, oInit, [["sScrollX", "sX"], ["sScrollXInner", "sXInner"], ["sScrollY", "sY"], ["bScrollCollapse", "bCollapse"]]);
  2139. _fnMap(oSettings.oLanguage, oInit, "fnInfoCallback");
  2140. /* Callback functions which are array driven */
  2141. _fnCallbackReg(oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user');
  2142. _fnCallbackReg(oSettings, 'aoServerParams', oInit.fnServerParams, 'user');
  2143. _fnCallbackReg(oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user');
  2144. _fnCallbackReg(oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user');
  2145. _fnCallbackReg(oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user');
  2146. _fnCallbackReg(oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user');
  2147. _fnCallbackReg(oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user');
  2148. _fnCallbackReg(oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user');
  2149. _fnCallbackReg(oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user');
  2150. _fnCallbackReg(oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user');
  2151. _fnCallbackReg(oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user');
  2152. oSettings.rowIdFn = _fnGetObjectDataFn(oInit.rowId);
  2153. /* Browser support detection */
  2154. _fnBrowserDetect(oSettings);
  2155. var oClasses = oSettings.oClasses;
  2156. $.extend(oClasses, DataTable.ext.classes, oInit.oClasses);
  2157. $this.addClass(oClasses.sTable);
  2158. if (oSettings.iInitDisplayStart === undefined) {
  2159. /* Display start point, taking into account the save saving */
  2160. oSettings.iInitDisplayStart = oInit.iDisplayStart;
  2161. oSettings._iDisplayStart = oInit.iDisplayStart;
  2162. }
  2163. if (oInit.iDeferLoading !== null) {
  2164. oSettings.bDeferLoading = true;
  2165. var tmp = $.isArray(oInit.iDeferLoading);
  2166. oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
  2167. oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
  2168. }
  2169. /* Language definitions */
  2170. var oLanguage = oSettings.oLanguage;
  2171. $.extend(true, oLanguage, oInit.oLanguage);
  2172. if (oLanguage.sUrl) {
  2173. /* Get the language definitions from a file - because this Ajax call makes the language
  2174. * get async to the remainder of this function we use bInitHandedOff to indicate that
  2175. * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
  2176. */
  2177. $.ajax({
  2178. dataType: 'json',
  2179. url: oLanguage.sUrl,
  2180. success: function success(json) {
  2181. _fnLanguageCompat(json);
  2182. _fnCamelToHungarian(defaults.oLanguage, json);
  2183. $.extend(true, oLanguage, json);
  2184. _fnInitialise(oSettings);
  2185. },
  2186. error: function error() {
  2187. // Error occurred loading language file, continue on as best we can
  2188. _fnInitialise(oSettings);
  2189. }
  2190. });
  2191. bInitHandedOff = true;
  2192. }
  2193. /*
  2194. * Stripes
  2195. */
  2196. if (oInit.asStripeClasses === null) {
  2197. oSettings.asStripeClasses = [oClasses.sStripeOdd, oClasses.sStripeEven];
  2198. }
  2199. /* Remove row stripe classes if they are already on the table row */
  2200. var stripeClasses = oSettings.asStripeClasses;
  2201. var rowOne = $this.children('tbody').find('tr').eq(0);
  2202. if ($.inArray(true, $.map(stripeClasses, function (el, i) {
  2203. return rowOne.hasClass(el);
  2204. })) !== - 1) {
  2205. $('tbody tr', this).removeClass(stripeClasses.join(' '));
  2206. oSettings.asDestroyStripes = stripeClasses.slice();
  2207. }
  2208. /*
  2209. * Columns
  2210. * See if we should load columns automatically or use defined ones
  2211. */
  2212. var anThs = [];
  2213. var aoColumnsInit;
  2214. var nThead = this.getElementsByTagName('thead');
  2215. if (nThead.length !== 0) {
  2216. _fnDetectHeader(oSettings.aoHeader, nThead[0]);
  2217. anThs = _fnGetUniqueThs(oSettings);
  2218. }
  2219. /* If not given a column array, generate one with nulls */
  2220. if (oInit.aoColumns === null) {
  2221. aoColumnsInit = [];
  2222. for (i = 0, iLen = anThs.length; i < iLen; i++) {
  2223. aoColumnsInit.push(null);
  2224. }
  2225. } else {
  2226. aoColumnsInit = oInit.aoColumns;
  2227. }
  2228. /* Add the columns */
  2229. for (i = 0, iLen = aoColumnsInit.length; i < iLen; i++) {
  2230. _fnAddColumn(oSettings, anThs ? anThs[i] : null);
  2231. }
  2232. /* Apply the column definitions */
  2233. _fnApplyColumnDefs(oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
  2234. _fnColumnOptions(oSettings, iCol, oDef);
  2235. });
  2236. /* HTML5 attribute detection - build an mData object automatically if the
  2237. * attributes are found
  2238. */
  2239. if (rowOne.length) {
  2240. var a = function a(cell, name) {
  2241. return cell.getAttribute('data-' + name) !== null ? name : null;
  2242. };
  2243. $(rowOne[0]).children('th, td').each(function (i, cell) {
  2244. var col = oSettings.aoColumns[i];
  2245. if (col.mData === i) {
  2246. var sort = a(cell, 'sort') || a(cell, 'order');
  2247. var filter = a(cell, 'filter') || a(cell, 'search');
  2248. if (sort !== null || filter !== null) {
  2249. col.mData = {
  2250. _: i + '.display',
  2251. sort: sort !== null ? i + '.@data-' + sort : undefined,
  2252. type: sort !== null ? i + '.@data-' + sort : undefined,
  2253. filter: filter !== null ? i + '.@data-' + filter : undefined
  2254. };
  2255. _fnColumnOptions(oSettings, i);
  2256. }
  2257. }
  2258. });
  2259. }
  2260. var features = oSettings.oFeatures;
  2261. var loadedInit = function loadedInit() {
  2262. /*
  2263. * Sorting
  2264. * @todo For modularisation (1.11) this needs to do into a sort start up handler
  2265. */
  2266. // If aaSorting is not defined, then we use the first indicator in asSorting
  2267. // in case that has been altered, so the default sort reflects that option
  2268. if (oInit.aaSorting === undefined) {
  2269. var sorting = oSettings.aaSorting;
  2270. for (i = 0, iLen = sorting.length; i < iLen; i++) {
  2271. sorting[i][1] = oSettings.aoColumns[i].asSorting[0];
  2272. }
  2273. }
  2274. /* Do a first pass on the sorting classes (allows any size changes to be taken into
  2275. * account, and also will apply sorting disabled classes if disabled
  2276. */
  2277. _fnSortingClasses(oSettings);
  2278. if (features.bSort) {
  2279. _fnCallbackReg(oSettings, 'aoDrawCallback', function () {
  2280. if (oSettings.bSorted) {
  2281. var aSort = _fnSortFlatten(oSettings);
  2282. var sortedColumns = {};
  2283. $.each(aSort, function (i, val) {
  2284. sortedColumns[val.src] = val.dir;
  2285. });
  2286. _fnCallbackFire(oSettings, null, 'order', [oSettings, aSort, sortedColumns]);
  2287. _fnSortAria(oSettings);
  2288. }
  2289. });
  2290. }
  2291. _fnCallbackReg(oSettings, 'aoDrawCallback', function () {
  2292. if (oSettings.bSorted || _fnDataSource(oSettings) === 'ssp' || features.bDeferRender) {
  2293. _fnSortingClasses(oSettings);
  2294. }
  2295. }, 'sc');
  2296. /*
  2297. * Final init
  2298. * Cache the header, body and footer as required, creating them if needed
  2299. */
  2300. // Work around for Webkit bug 83867 - store the caption-side before removing from doc
  2301. var captions = $this.children('caption').each(function () {
  2302. this._captionSide = $(this).css('caption-side');
  2303. });
  2304. var thead = $this.children('thead');
  2305. if (thead.length === 0) {
  2306. thead = $('<thead/>').appendTo($this);
  2307. }
  2308. oSettings.nTHead = thead[0];
  2309. var tbody = $this.children('tbody');
  2310. if (tbody.length === 0) {
  2311. tbody = $('<tbody/>').appendTo($this);
  2312. }
  2313. oSettings.nTBody = tbody[0];
  2314. var tfoot = $this.children('tfoot');
  2315. if (tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "")) {
  2316. // If we are a scrolling table, and no footer has been given, then we need to create
  2317. // a tfoot element for the caption element to be appended to
  2318. tfoot = $('<tfoot/>').appendTo($this);
  2319. }
  2320. if (tfoot.length === 0 || tfoot.children().length === 0) {
  2321. $this.addClass(oClasses.sNoFooter);
  2322. } else if (tfoot.length > 0) {
  2323. oSettings.nTFoot = tfoot[0];
  2324. _fnDetectHeader(oSettings.aoFooter, oSettings.nTFoot);
  2325. }
  2326. /* Check if there is data passing into the constructor */
  2327. if (oInit.aaData) {
  2328. for (i = 0; i < oInit.aaData.length; i++) {
  2329. _fnAddData(oSettings, oInit.aaData[i]);
  2330. }
  2331. } else if (oSettings.bDeferLoading || _fnDataSource(oSettings) == 'dom') {
  2332. /* Grab the data from the page - only do this when deferred loading or no Ajax
  2333. * source since there is no point in reading the DOM data if we are then going
  2334. * to replace it with Ajax data
  2335. */
  2336. _fnAddTr(oSettings, $(oSettings.nTBody).children('tr'));
  2337. }
  2338. /* Copy the data index array */
  2339. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  2340. /* Initialisation complete - table can be drawn */
  2341. oSettings.bInitialised = true;
  2342. /* Check if we need to initialise the table (it might not have been handed off to the
  2343. * language processor)
  2344. */
  2345. if (bInitHandedOff === false) {
  2346. _fnInitialise(oSettings);
  2347. }
  2348. };
  2349. /* Must be done after everything which can be overridden by the state saving! */
  2350. if (oInit.bStateSave) {
  2351. features.bStateSave = true;
  2352. _fnCallbackReg(oSettings, 'aoDrawCallback', _fnSaveState, 'state_save');
  2353. _fnLoadState(oSettings, oInit, loadedInit);
  2354. } else {
  2355. loadedInit();
  2356. }
  2357. });
  2358. _that = null;
  2359. return this;
  2360. };
  2361. /*
  2362. * It is useful to have variables which are scoped locally so only the
  2363. * DataTables functions can access them and they don't leak into global space.
  2364. * At the same time these functions are often useful over multiple files in the
  2365. * core and API, so we list, or at least document, all variables which are used
  2366. * by DataTables as private variables here. This also ensures that there is no
  2367. * clashing of variable names and that they can easily referenced for reuse.
  2368. */
  2369. // Defined else where
  2370. // _selector_run
  2371. // _selector_opts
  2372. // _selector_first
  2373. // _selector_row_indexes
  2374. var _ext; // DataTable.ext
  2375. var _Api2; // DataTable.Api
  2376. var _api_register; // DataTable.Api.register
  2377. var _api_registerPlural; // DataTable.Api.registerPlural
  2378. var _re_dic = {};
  2379. var _re_new_lines = /[\r\n]/g;
  2380. var _re_html = /<.*?>/g;
  2381. // This is not strict ISO8601 - Date.parse() is quite lax, although
  2382. // implementations differ between browsers.
  2383. var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
  2384. // Escape regular expression special characters
  2385. var _re_escape_regex = new RegExp('(\\' + ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-'].join('|\\') + ')', 'g');
  2386. // http://en.wikipedia.org/wiki/Foreign_exchange_market
  2387. // - \u20BD - Russian ruble.
  2388. // - \u20a9 - South Korean Won
  2389. // - \u20BA - Turkish Lira
  2390. // - \u20B9 - Indian Rupee
  2391. // - R - Brazil (R$) and South Africa
  2392. // - fr - Swiss Franc
  2393. // - kr - Swedish krona, Norwegian krone and Danish krone
  2394. // - \u2009 is thin space and \u202F is narrow no-break space, both used in many
  2395. // standards as thousands separators.
  2396. var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
  2397. var _empty = function _empty(d) {
  2398. return !d || d === true || d === '-' ? true : false;
  2399. };
  2400. var _intVal = function _intVal(s) {
  2401. var integer = parseInt(s, 10);
  2402. return !isNaN(integer) && isFinite(s) ? integer : null;
  2403. };
  2404. // Convert from a formatted number with characters other than `.` as the
  2405. // decimal place, to a Javascript number
  2406. var _numToDecimal = function _numToDecimal(num, decimalPoint) {
  2407. // Cache created regular expressions for speed as this function is called often
  2408. if (!_re_dic[decimalPoint]) {
  2409. _re_dic[decimalPoint] = new RegExp(_fnEscapeRegex(decimalPoint), 'g');
  2410. }
  2411. return typeof num === 'string' && decimalPoint !== '.' ? num.replace(/\./g, '').replace(_re_dic[decimalPoint], '.') : num;
  2412. };
  2413. var _isNumber = function _isNumber(d, decimalPoint, formatted) {
  2414. var strType = typeof d === 'string';
  2415. // If empty return immediately so there must be a number if it is a
  2416. // formatted string (this stops the string "k", or "kr", etc being detected
  2417. // as a formatted number for currency
  2418. if (_empty(d)) {
  2419. return true;
  2420. }
  2421. if (decimalPoint && strType) {
  2422. d = _numToDecimal(d, decimalPoint);
  2423. }
  2424. if (formatted && strType) {
  2425. d = d.replace(_re_formatted_numeric, '');
  2426. }
  2427. return !isNaN(parseFloat(d)) && isFinite(d);
  2428. };
  2429. // A string without HTML in it can be considered to be HTML still
  2430. var _isHtml = function _isHtml(d) {
  2431. return _empty(d) || typeof d === 'string';
  2432. };
  2433. var _htmlNumeric = function _htmlNumeric(d, decimalPoint, formatted) {
  2434. if (_empty(d)) {
  2435. return true;
  2436. }
  2437. var html = _isHtml(d);
  2438. return !html ? null : _isNumber(_stripHtml(d), decimalPoint, formatted) ? true : null;
  2439. };
  2440. var _pluck = function _pluck(a, prop, prop2) {
  2441. var out = [];
  2442. var i = 0,
  2443. ien = a.length;
  2444. // Could have the test in the loop for slightly smaller code, but speed
  2445. // is essential here
  2446. if (prop2 !== undefined) {
  2447. for (; i < ien; i++) {
  2448. if (a[i] && a[i][prop]) {
  2449. out.push(a[i][prop][prop2]);
  2450. }
  2451. }
  2452. } else {
  2453. for (; i < ien; i++) {
  2454. if (a[i]) {
  2455. out.push(a[i][prop]);
  2456. }
  2457. }
  2458. }
  2459. return out;
  2460. };
  2461. // Basically the same as _pluck, but rather than looping over `a` we use `order`
  2462. // as the indexes to pick from `a`
  2463. var _pluck_order = function _pluck_order(a, order, prop, prop2) {
  2464. var out = [];
  2465. var i = 0,
  2466. ien = order.length;
  2467. // Could have the test in the loop for slightly smaller code, but speed
  2468. // is essential here
  2469. if (prop2 !== undefined) {
  2470. for (; i < ien; i++) {
  2471. if (a[order[i]][prop]) {
  2472. out.push(a[order[i]][prop][prop2]);
  2473. }
  2474. }
  2475. } else {
  2476. for (; i < ien; i++) {
  2477. out.push(a[order[i]][prop]);
  2478. }
  2479. }
  2480. return out;
  2481. };
  2482. var _range = function _range(len, start) {
  2483. var out = [];
  2484. var end;
  2485. if (start === undefined) {
  2486. start = 0;
  2487. end = len;
  2488. } else {
  2489. end = start;
  2490. start = len;
  2491. }
  2492. for (var i = start; i < end; i++) {
  2493. out.push(i);
  2494. }
  2495. return out;
  2496. };
  2497. var _removeEmpty = function _removeEmpty(a) {
  2498. var out = [];
  2499. for (var i = 0, ien = a.length; i < ien; i++) {
  2500. if (a[i]) {
  2501. // careful - will remove all falsy values!
  2502. out.push(a[i]);
  2503. }
  2504. }
  2505. return out;
  2506. };
  2507. var _stripHtml = function _stripHtml(d) {
  2508. return d.replace(_re_html, '');
  2509. };
  2510. /**
  2511. * Determine if all values in the array are unique. This means we can short
  2512. * cut the _unique method at the cost of a single loop. A sorted array is used
  2513. * to easily check the values.
  2514. *
  2515. * @param {array} src Source array
  2516. * @return {boolean} true if all unique, false otherwise
  2517. * @ignore
  2518. */
  2519. var _areAllUnique = function _areAllUnique(src) {
  2520. if (src.length < 2) {
  2521. return true;
  2522. }
  2523. var sorted = src.slice().sort();
  2524. var last = sorted[0];
  2525. for (var i = 1, ien = sorted.length; i < ien; i++) {
  2526. if (sorted[i] === last) {
  2527. return false;
  2528. }
  2529. last = sorted[i];
  2530. }
  2531. return true;
  2532. };
  2533. /**
  2534. * Find the unique elements in a source array.
  2535. *
  2536. * @param {array} src Source array
  2537. * @return {array} Array of unique items
  2538. * @ignore
  2539. */
  2540. var _unique = function _unique(src) {
  2541. if (_areAllUnique(src)) {
  2542. return src.slice();
  2543. }
  2544. // A faster unique method is to use object keys to identify used values,
  2545. // but this doesn't work with arrays or objects, which we must also
  2546. // consider. See jsperf.com/compare-array-unique-versions/4 for more
  2547. // information.
  2548. var out = [],
  2549. val,
  2550. i,
  2551. ien = src.length,
  2552. j,
  2553. k = 0;
  2554. again: for (i = 0; i < ien; i++) {
  2555. val = src[i];
  2556. for (j = 0; j < k; j++) {
  2557. if (out[j] === val) {
  2558. continue again;
  2559. }
  2560. }
  2561. out.push(val);
  2562. k++;
  2563. }
  2564. return out;
  2565. };
  2566. /**
  2567. * DataTables utility methods
  2568. *
  2569. * This namespace provides helper methods that DataTables uses internally to
  2570. * create a DataTable, but which are not exclusively used only for DataTables.
  2571. * These methods can be used by extension authors to save the duplication of
  2572. * code.
  2573. *
  2574. * @namespace
  2575. */
  2576. DataTable.util = {
  2577. /**
  2578. * Throttle the calls to a function. Arguments and context are maintained
  2579. * for the throttled function.
  2580. *
  2581. * @param {function} fn Function to be called
  2582. * @param {integer} freq Call frequency in mS
  2583. * @return {function} Wrapped function
  2584. */
  2585. throttle: function throttle(fn, freq) {
  2586. var frequency = freq !== undefined ? freq : 200,
  2587. last,
  2588. timer;
  2589. return function () {
  2590. var that = this,
  2591. now = + new Date(),
  2592. args = arguments;
  2593. if (last && now < last + frequency) {
  2594. clearTimeout(timer);
  2595. timer = setTimeout(function () {
  2596. last = undefined;
  2597. fn.apply(that, args);
  2598. }, frequency);
  2599. } else {
  2600. last = now;
  2601. fn.apply(that, args);
  2602. }
  2603. };
  2604. },
  2605. /**
  2606. * Escape a string such that it can be used in a regular expression
  2607. *
  2608. * @param {string} val string to escape
  2609. * @returns {string} escaped string
  2610. */
  2611. escapeRegex: function escapeRegex(val) {
  2612. return val.replace(_re_escape_regex, '\\$1');
  2613. }
  2614. };
  2615. /**
  2616. * Create a mapping object that allows camel case parameters to be looked up
  2617. * for their Hungarian counterparts. The mapping is stored in a private
  2618. * parameter called `_hungarianMap` which can be accessed on the source object.
  2619. * @param {object} o
  2620. * @memberof DataTable#oApi
  2621. */
  2622. function _fnHungarianMap(o) {
  2623. var hungarian = 'a aa ai ao as b fn i m o s ',
  2624. match,
  2625. newKey,
  2626. map = {};
  2627. $.each(o, function (key, val) {
  2628. match = key.match(/^([^A-Z]+?)([A-Z])/);
  2629. if (match && hungarian.indexOf(match[1] + ' ') !== - 1) {
  2630. newKey = key.replace(match[0], match[2].toLowerCase());
  2631. map[newKey] = key;
  2632. if (match[1] === 'o') {
  2633. _fnHungarianMap(o[key]);
  2634. }
  2635. }
  2636. });
  2637. o._hungarianMap = map;
  2638. }
  2639. /**
  2640. * Convert from camel case parameters to Hungarian, based on a Hungarian map
  2641. * created by _fnHungarianMap.
  2642. * @param {object} src The model object which holds all parameters that can be
  2643. * mapped.
  2644. * @param {object} user The object to convert from camel case to Hungarian.
  2645. * @param {boolean} force When set to `true`, properties which already have a
  2646. * Hungarian value in the `user` object will be overwritten. Otherwise they
  2647. * won't be.
  2648. * @memberof DataTable#oApi
  2649. */
  2650. function _fnCamelToHungarian(src, user, force) {
  2651. if (!src._hungarianMap) {
  2652. _fnHungarianMap(src);
  2653. }
  2654. var hungarianKey;
  2655. $.each(user, function (key, val) {
  2656. hungarianKey = src._hungarianMap[key];
  2657. if (hungarianKey !== undefined && (force || user[hungarianKey] === undefined)) {
  2658. // For objects, we need to buzz down into the object to copy parameters
  2659. if (hungarianKey.charAt(0) === 'o') {
  2660. // Copy the camelCase options over to the hungarian
  2661. if (!user[hungarianKey]) {
  2662. user[hungarianKey] = {};
  2663. }
  2664. $.extend(true, user[hungarianKey], user[key]);
  2665. _fnCamelToHungarian(src[hungarianKey], user[hungarianKey], force);
  2666. } else {
  2667. user[hungarianKey] = user[key];
  2668. }
  2669. }
  2670. });
  2671. }
  2672. /**
  2673. * Language compatibility - when certain options are given, and others aren't, we
  2674. * need to duplicate the values over, in order to provide backwards compatibility
  2675. * with older language files.
  2676. * @param {object} oSettings dataTables settings object
  2677. * @memberof DataTable#oApi
  2678. */
  2679. function _fnLanguageCompat(lang) {
  2680. var defaults = DataTable.defaults.oLanguage;
  2681. var zeroRecords = lang.sZeroRecords;
  2682. /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
  2683. * sZeroRecords - assuming that is given.
  2684. */
  2685. if (!lang.sEmptyTable && zeroRecords && defaults.sEmptyTable === "No data available in table") {
  2686. _fnMap(lang, lang, 'sZeroRecords', 'sEmptyTable');
  2687. }
  2688. /* Likewise with loading records */
  2689. if (!lang.sLoadingRecords && zeroRecords && defaults.sLoadingRecords === "Loading...") {
  2690. _fnMap(lang, lang, 'sZeroRecords', 'sLoadingRecords');
  2691. }
  2692. // Old parameter name of the thousands separator mapped onto the new
  2693. if (lang.sInfoThousands) {
  2694. lang.sThousands = lang.sInfoThousands;
  2695. }
  2696. var decimal = lang.sDecimal;
  2697. if (decimal) {
  2698. _addNumericSort(decimal);
  2699. }
  2700. }
  2701. /**
  2702. * Map one parameter onto another
  2703. * @param {object} o Object to map
  2704. * @param {*} knew The new parameter name
  2705. * @param {*} old The old parameter name
  2706. */
  2707. var _fnCompatMap = function _fnCompatMap(o, knew, old) {
  2708. if (o[knew] !== undefined) {
  2709. o[old] = o[knew];
  2710. }
  2711. };
  2712. /**
  2713. * Provide backwards compatibility for the main DT options. Note that the new
  2714. * options are mapped onto the old parameters, so this is an external interface
  2715. * change only.
  2716. * @param {object} init Object to map
  2717. */
  2718. function _fnCompatOpts(init) {
  2719. _fnCompatMap(init, 'ordering', 'bSort');
  2720. _fnCompatMap(init, 'orderMulti', 'bSortMulti');
  2721. _fnCompatMap(init, 'orderClasses', 'bSortClasses');
  2722. _fnCompatMap(init, 'orderCellsTop', 'bSortCellsTop');
  2723. _fnCompatMap(init, 'order', 'aaSorting');
  2724. _fnCompatMap(init, 'orderFixed', 'aaSortingFixed');
  2725. _fnCompatMap(init, 'paging', 'bPaginate');
  2726. _fnCompatMap(init, 'pagingType', 'sPaginationType');
  2727. _fnCompatMap(init, 'pageLength', 'iDisplayLength');
  2728. _fnCompatMap(init, 'searching', 'bFilter');
  2729. // Boolean initialisation of x-scrolling
  2730. if (typeof init.sScrollX === 'boolean') {
  2731. init.sScrollX = init.sScrollX ? '100%' : '';
  2732. }
  2733. if (typeof init.scrollX === 'boolean') {
  2734. init.scrollX = init.scrollX ? '100%' : '';
  2735. }
  2736. // Column search objects are in an array, so it needs to be converted
  2737. // element by element
  2738. var searchCols = init.aoSearchCols;
  2739. if (searchCols) {
  2740. for (var i = 0, ien = searchCols.length; i < ien; i++) {
  2741. if (searchCols[i]) {
  2742. _fnCamelToHungarian(DataTable.models.oSearch, searchCols[i]);
  2743. }
  2744. }
  2745. }
  2746. }
  2747. /**
  2748. * Provide backwards compatibility for column options. Note that the new options
  2749. * are mapped onto the old parameters, so this is an external interface change
  2750. * only.
  2751. * @param {object} init Object to map
  2752. */
  2753. function _fnCompatCols(init) {
  2754. _fnCompatMap(init, 'orderable', 'bSortable');
  2755. _fnCompatMap(init, 'orderData', 'aDataSort');
  2756. _fnCompatMap(init, 'orderSequence', 'asSorting');
  2757. _fnCompatMap(init, 'orderDataType', 'sortDataType');
  2758. // orderData can be given as an integer
  2759. var dataSort = init.aDataSort;
  2760. if (typeof dataSort === 'number' && !$.isArray(dataSort)) {
  2761. init.aDataSort = [dataSort];
  2762. }
  2763. }
  2764. /**
  2765. * Browser feature detection for capabilities, quirks
  2766. * @param {object} settings dataTables settings object
  2767. * @memberof DataTable#oApi
  2768. */
  2769. function _fnBrowserDetect(settings) {
  2770. // We don't need to do this every time DataTables is constructed, the values
  2771. // calculated are specific to the browser and OS configuration which we
  2772. // don't expect to change between initialisations
  2773. if (!DataTable.__browser) {
  2774. var browser = {};
  2775. DataTable.__browser = browser;
  2776. // Scrolling feature / quirks detection
  2777. var n = $('<div/>').css({
  2778. position: 'fixed',
  2779. top: 0,
  2780. left: $(window).scrollLeft() * - 1, // allow for scrolling
  2781. height: 1,
  2782. width: 1,
  2783. overflow: 'hidden'
  2784. }).append($('<div/>').css({
  2785. position: 'absolute',
  2786. top: 1,
  2787. left: 1,
  2788. width: 100,
  2789. overflow: 'scroll'
  2790. }).append($('<div/>').css({
  2791. width: '100%',
  2792. height: 10
  2793. }))).appendTo('body');
  2794. var outer = n.children();
  2795. var inner = outer.children();
  2796. // Numbers below, in order, are:
  2797. // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
  2798. //
  2799. // IE6 XP: 100 100 100 83
  2800. // IE7 Vista: 100 100 100 83
  2801. // IE 8+ Windows: 83 83 100 83
  2802. // Evergreen Windows: 83 83 100 83
  2803. // Evergreen Mac with scrollbars: 85 85 100 85
  2804. // Evergreen Mac without scrollbars: 100 100 100 100
  2805. // Get scrollbar width
  2806. browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
  2807. // IE6/7 will oversize a width 100% element inside a scrolling element, to
  2808. // include the width of the scrollbar, while other browsers ensure the inner
  2809. // element is contained without forcing scrolling
  2810. browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
  2811. // In rtl text layout, some browsers (most, but not all) will place the
  2812. // scrollbar on the left, rather than the right.
  2813. browser.bScrollbarLeft = Math.round(inner.offset().left) !== 1;
  2814. // IE8- don't provide height and width for getBoundingClientRect
  2815. browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
  2816. n.remove();
  2817. }
  2818. $.extend(settings.oBrowser, DataTable.__browser);
  2819. settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
  2820. }
  2821. /**
  2822. * Array.prototype reduce[Right] method, used for browsers which don't support
  2823. * JS 1.6. Done this way to reduce code size, since we iterate either way
  2824. * @param {object} settings dataTables settings object
  2825. * @memberof DataTable#oApi
  2826. */
  2827. function _fnReduce(that, fn, init, start, end, inc) {
  2828. var i = start,
  2829. value,
  2830. isSet = false;
  2831. if (init !== undefined) {
  2832. value = init;
  2833. isSet = true;
  2834. }
  2835. while (i !== end) {
  2836. if (!that.hasOwnProperty(i)) {
  2837. continue;
  2838. }
  2839. value = isSet ? fn(value, that[i], i, that) : that[i];
  2840. isSet = true;
  2841. i += inc;
  2842. }
  2843. return value;
  2844. }
  2845. /**
  2846. * Add a column to the list used for the table with default values
  2847. * @param {object} oSettings dataTables settings object
  2848. * @param {node} nTh The th element for this column
  2849. * @memberof DataTable#oApi
  2850. */
  2851. function _fnAddColumn(oSettings, nTh) {
  2852. // Add column to aoColumns array
  2853. var oDefaults = DataTable.defaults.column;
  2854. var iCol = oSettings.aoColumns.length;
  2855. var oCol = $.extend({}, DataTable.models.oColumn, oDefaults, {
  2856. "nTh": nTh ? nTh : document.createElement('th'),
  2857. "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',
  2858. "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
  2859. "mData": oDefaults.mData ? oDefaults.mData : iCol,
  2860. idx: iCol
  2861. });
  2862. oSettings.aoColumns.push(oCol);
  2863. // Add search object for column specific search. Note that the `searchCols[ iCol ]`
  2864. // passed into extend can be undefined. This allows the user to give a default
  2865. // with only some of the parameters defined, and also not give a default
  2866. var searchCols = oSettings.aoPreSearchCols;
  2867. searchCols[iCol] = $.extend({}, DataTable.models.oSearch, searchCols[iCol]);
  2868. // Use the default column options function to initialise classes etc
  2869. _fnColumnOptions(oSettings, iCol, $(nTh).data());
  2870. }
  2871. /**
  2872. * Apply options for a column
  2873. * @param {object} oSettings dataTables settings object
  2874. * @param {int} iCol column index to consider
  2875. * @param {object} oOptions object with sType, bVisible and bSearchable etc
  2876. * @memberof DataTable#oApi
  2877. */
  2878. function _fnColumnOptions(oSettings, iCol, oOptions) {
  2879. var oCol = oSettings.aoColumns[iCol];
  2880. var oClasses = oSettings.oClasses;
  2881. var th = $(oCol.nTh);
  2882. // Try to get width information from the DOM. We can't get it from CSS
  2883. // as we'd need to parse the CSS stylesheet. `width` option can override
  2884. if (!oCol.sWidthOrig) {
  2885. // Width attribute
  2886. oCol.sWidthOrig = th.attr('width') || null;
  2887. // Style attribute
  2888. var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
  2889. if (t) {
  2890. oCol.sWidthOrig = t[1];
  2891. }
  2892. }
  2893. /* User specified column options */
  2894. if (oOptions !== undefined && oOptions !== null) {
  2895. // Backwards compatibility
  2896. _fnCompatCols(oOptions);
  2897. // Map camel case parameters to their Hungarian counterparts
  2898. _fnCamelToHungarian(DataTable.defaults.column, oOptions);
  2899. /* Backwards compatibility for mDataProp */
  2900. if (oOptions.mDataProp !== undefined && !oOptions.mData) {
  2901. oOptions.mData = oOptions.mDataProp;
  2902. }
  2903. if (oOptions.sType) {
  2904. oCol._sManualType = oOptions.sType;
  2905. }
  2906. // `class` is a reserved word in Javascript, so we need to provide
  2907. // the ability to use a valid name for the camel case input
  2908. if (oOptions.className && !oOptions.sClass) {
  2909. oOptions.sClass = oOptions.className;
  2910. }
  2911. if (oOptions.sClass) {
  2912. th.addClass(oOptions.sClass);
  2913. }
  2914. $.extend(oCol, oOptions);
  2915. _fnMap(oCol, oOptions, "sWidth", "sWidthOrig");
  2916. /* iDataSort to be applied (backwards compatibility), but aDataSort will take
  2917. * priority if defined
  2918. */
  2919. if (oOptions.iDataSort !== undefined) {
  2920. oCol.aDataSort = [oOptions.iDataSort];
  2921. }
  2922. _fnMap(oCol, oOptions, "aDataSort");
  2923. }
  2924. /* Cache the data get and set functions for speed */
  2925. var mDataSrc = oCol.mData;
  2926. var mData = _fnGetObjectDataFn(mDataSrc);
  2927. var mRender = oCol.mRender ? _fnGetObjectDataFn(oCol.mRender) : null;
  2928. var attrTest = function attrTest(src) {
  2929. return typeof src === 'string' && src.indexOf('@') !== - 1;
  2930. };
  2931. oCol._bAttrSrc = $.isPlainObject(mDataSrc) && (attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter));
  2932. oCol._setter = null;
  2933. oCol.fnGetData = function (rowData, type, meta) {
  2934. var innerData = mData(rowData, type, undefined, meta);
  2935. return mRender && type ? mRender(innerData, type, rowData, meta) : innerData;
  2936. };
  2937. oCol.fnSetData = function (rowData, val, meta) {
  2938. return _fnSetObjectDataFn(mDataSrc)(rowData, val, meta);
  2939. };
  2940. // Indicate if DataTables should read DOM data as an object or array
  2941. // Used in _fnGetRowElements
  2942. if (typeof mDataSrc !== 'number') {
  2943. oSettings._rowReadObject = true;
  2944. }
  2945. /* Feature sorting overrides column specific when off */
  2946. if (!oSettings.oFeatures.bSort) {
  2947. oCol.bSortable = false;
  2948. th.addClass(oClasses.sSortableNone); // Have to add class here as order event isn't called
  2949. }
  2950. /* Check that the class assignment is correct for sorting */
  2951. var bAsc = $.inArray('asc', oCol.asSorting) !== - 1;
  2952. var bDesc = $.inArray('desc', oCol.asSorting) !== - 1;
  2953. if (!oCol.bSortable || !bAsc && !bDesc) {
  2954. oCol.sSortingClass = oClasses.sSortableNone;
  2955. oCol.sSortingClassJUI = "";
  2956. } else if (bAsc && !bDesc) {
  2957. oCol.sSortingClass = oClasses.sSortableAsc;
  2958. oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
  2959. } else if (!bAsc && bDesc) {
  2960. oCol.sSortingClass = oClasses.sSortableDesc;
  2961. oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
  2962. } else {
  2963. oCol.sSortingClass = oClasses.sSortable;
  2964. oCol.sSortingClassJUI = oClasses.sSortJUI;
  2965. }
  2966. }
  2967. /**
  2968. * Adjust the table column widths for new data. Note: you would probably want to
  2969. * do a redraw after calling this function!
  2970. * @param {object} settings dataTables settings object
  2971. * @memberof DataTable#oApi
  2972. */
  2973. function _fnAdjustColumnSizing(settings) {
  2974. /* Not interested in doing column width calculation if auto-width is disabled */
  2975. if (settings.oFeatures.bAutoWidth !== false) {
  2976. var columns = settings.aoColumns;
  2977. _fnCalculateColumnWidths(settings);
  2978. for (var i = 0, iLen = columns.length; i < iLen; i++) {
  2979. columns[i].nTh.style.width = columns[i].sWidth;
  2980. }
  2981. }
  2982. var scroll = settings.oScroll;
  2983. if (scroll.sY !== '' || scroll.sX !== '') {
  2984. _fnScrollDraw(settings);
  2985. }
  2986. _fnCallbackFire(settings, null, 'column-sizing', [settings]);
  2987. }
  2988. /**
  2989. * Covert the index of a visible column to the index in the data array (take account
  2990. * of hidden columns)
  2991. * @param {object} oSettings dataTables settings object
  2992. * @param {int} iMatch Visible column index to lookup
  2993. * @returns {int} i the data index
  2994. * @memberof DataTable#oApi
  2995. */
  2996. function _fnVisibleToColumnIndex(oSettings, iMatch) {
  2997. var aiVis = _fnGetColumns(oSettings, 'bVisible');
  2998. return typeof aiVis[iMatch] === 'number' ? aiVis[iMatch] : null;
  2999. }
  3000. /**
  3001. * Covert the index of an index in the data array and convert it to the visible
  3002. * column index (take account of hidden columns)
  3003. * @param {int} iMatch Column index to lookup
  3004. * @param {object} oSettings dataTables settings object
  3005. * @returns {int} i the data index
  3006. * @memberof DataTable#oApi
  3007. */
  3008. function _fnColumnIndexToVisible(oSettings, iMatch) {
  3009. var aiVis = _fnGetColumns(oSettings, 'bVisible');
  3010. var iPos = $.inArray(iMatch, aiVis);
  3011. return iPos !== - 1 ? iPos : null;
  3012. }
  3013. /**
  3014. * Get the number of visible columns
  3015. * @param {object} oSettings dataTables settings object
  3016. * @returns {int} i the number of visible columns
  3017. * @memberof DataTable#oApi
  3018. */
  3019. function _fnVisbleColumns(oSettings) {
  3020. var vis = 0;
  3021. // No reduce in IE8, use a loop for now
  3022. $.each(oSettings.aoColumns, function (i, col) {
  3023. if (col.bVisible && $(col.nTh).css('display') !== 'none') {
  3024. vis++;
  3025. }
  3026. });
  3027. return vis;
  3028. }
  3029. /**
  3030. * Get an array of column indexes that match a given property
  3031. * @param {object} oSettings dataTables settings object
  3032. * @param {string} sParam Parameter in aoColumns to look for - typically
  3033. * bVisible or bSearchable
  3034. * @returns {array} Array of indexes with matched properties
  3035. * @memberof DataTable#oApi
  3036. */
  3037. function _fnGetColumns(oSettings, sParam) {
  3038. var a = [];
  3039. $.map(oSettings.aoColumns, function (val, i) {
  3040. if (val[sParam]) {
  3041. a.push(i);
  3042. }
  3043. });
  3044. return a;
  3045. }
  3046. /**
  3047. * Calculate the 'type' of a column
  3048. * @param {object} settings dataTables settings object
  3049. * @memberof DataTable#oApi
  3050. */
  3051. function _fnColumnTypes(settings) {
  3052. var columns = settings.aoColumns;
  3053. var data = settings.aoData;
  3054. var types = DataTable.ext.type.detect;
  3055. var i, ien, j, jen, k, ken;
  3056. var col, cell, detectedType, cache;
  3057. // For each column, spin over the
  3058. for (i = 0, ien = columns.length; i < ien; i++) {
  3059. col = columns[i];
  3060. cache = [];
  3061. if (!col.sType && col._sManualType) {
  3062. col.sType = col._sManualType;
  3063. } else if (!col.sType) {
  3064. for (j = 0, jen = types.length; j < jen; j++) {
  3065. for (k = 0, ken = data.length; k < ken; k++) {
  3066. // Use a cache array so we only need to get the type data
  3067. // from the formatter once (when using multiple detectors)
  3068. if (cache[k] === undefined) {
  3069. cache[k] = _fnGetCellData(settings, k, i, 'type');
  3070. }
  3071. detectedType = types[j](cache[k], settings);
  3072. // If null, then this type can't apply to this column, so
  3073. // rather than testing all cells, break out. There is an
  3074. // exception for the last type which is `html`. We need to
  3075. // scan all rows since it is possible to mix string and HTML
  3076. // types
  3077. if (!detectedType && j !== types.length - 1) {
  3078. break;
  3079. }
  3080. // Only a single match is needed for html type since it is
  3081. // bottom of the pile and very similar to string
  3082. if (detectedType === 'html') {
  3083. break;
  3084. }
  3085. }
  3086. // Type is valid for all data points in the column - use this
  3087. // type
  3088. if (detectedType) {
  3089. col.sType = detectedType;
  3090. break;
  3091. }
  3092. }
  3093. // Fall back - if no type was detected, always use string
  3094. if (!col.sType) {
  3095. col.sType = 'string';
  3096. }
  3097. }
  3098. }
  3099. }
  3100. /**
  3101. * Take the column definitions and static columns arrays and calculate how
  3102. * they relate to column indexes. The callback function will then apply the
  3103. * definition found for a column to a suitable configuration object.
  3104. * @param {object} oSettings dataTables settings object
  3105. * @param {array} aoColDefs The aoColumnDefs array that is to be applied
  3106. * @param {array} aoCols The aoColumns array that defines columns individually
  3107. * @param {function} fn Callback function - takes two parameters, the calculated
  3108. * column index and the definition for that column.
  3109. * @memberof DataTable#oApi
  3110. */
  3111. function _fnApplyColumnDefs(oSettings, aoColDefs, aoCols, fn) {
  3112. var i, iLen, j, jLen, k, kLen, def;
  3113. var columns = oSettings.aoColumns;
  3114. // Column definitions with aTargets
  3115. if (aoColDefs) {
  3116. /* Loop over the definitions array - loop in reverse so first instance has priority */
  3117. for (i = aoColDefs.length - 1; i >= 0; i--) {
  3118. def = aoColDefs[i];
  3119. /* Each definition can target multiple columns, as it is an array */
  3120. var aTargets = def.targets !== undefined ? def.targets : def.aTargets;
  3121. if (!$.isArray(aTargets)) {
  3122. aTargets = [aTargets];
  3123. }
  3124. for (j = 0, jLen = aTargets.length; j < jLen; j++) {
  3125. if (typeof aTargets[j] === 'number' && aTargets[j] >= 0) {
  3126. /* Add columns that we don't yet know about */
  3127. while (columns.length <= aTargets[j]) {
  3128. _fnAddColumn(oSettings);
  3129. }
  3130. /* Integer, basic index */
  3131. fn(aTargets[j], def);
  3132. } else if (typeof aTargets[j] === 'number' && aTargets[j] < 0) {
  3133. /* Negative integer, right to left column counting */
  3134. fn(columns.length + aTargets[j], def);
  3135. } else if (typeof aTargets[j] === 'string') {
  3136. /* Class name matching on TH element */
  3137. for (k = 0, kLen = columns.length; k < kLen; k++) {
  3138. if (aTargets[j] == "_all" || $(columns[k].nTh).hasClass(aTargets[j])) {
  3139. fn(k, def);
  3140. }
  3141. }
  3142. }
  3143. }
  3144. }
  3145. }
  3146. // Statically defined columns array
  3147. if (aoCols) {
  3148. for (i = 0, iLen = aoCols.length; i < iLen; i++) {
  3149. fn(i, aoCols[i]);
  3150. }
  3151. }
  3152. }
  3153. /**
  3154. * Add a data array to the table, creating DOM node etc. This is the parallel to
  3155. * _fnGatherData, but for adding rows from a Javascript source, rather than a
  3156. * DOM source.
  3157. * @param {object} oSettings dataTables settings object
  3158. * @param {array} aData data array to be added
  3159. * @param {node} [nTr] TR element to add to the table - optional. If not given,
  3160. * DataTables will create a row automatically
  3161. * @param {array} [anTds] Array of TD|TH elements for the row - must be given
  3162. * if nTr is.
  3163. * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
  3164. * @memberof DataTable#oApi
  3165. */
  3166. function _fnAddData(oSettings, aDataIn, nTr, anTds) {
  3167. /* Create the object for storing information about this new row */
  3168. var iRow = oSettings.aoData.length;
  3169. var oData = $.extend(true, {}, DataTable.models.oRow, {
  3170. src: nTr ? 'dom' : 'data',
  3171. idx: iRow
  3172. });
  3173. oData._aData = aDataIn;
  3174. oSettings.aoData.push(oData);
  3175. /* Create the cells */
  3176. var nTd, sThisType;
  3177. var columns = oSettings.aoColumns;
  3178. // Invalidate the column types as the new data needs to be revalidated
  3179. for (var i = 0, iLen = columns.length; i < iLen; i++) {
  3180. columns[i].sType = null;
  3181. }
  3182. /* Add to the display array */
  3183. oSettings.aiDisplayMaster.push(iRow);
  3184. var id = oSettings.rowIdFn(aDataIn);
  3185. if (id !== undefined) {
  3186. oSettings.aIds[id] = oData;
  3187. }
  3188. /* Create the DOM information, or register it if already present */
  3189. if (nTr || !oSettings.oFeatures.bDeferRender) {
  3190. _fnCreateTr(oSettings, iRow, nTr, anTds);
  3191. }
  3192. return iRow;
  3193. }
  3194. /**
  3195. * Add one or more TR elements to the table. Generally we'd expect to
  3196. * use this for reading data from a DOM sourced table, but it could be
  3197. * used for an TR element. Note that if a TR is given, it is used (i.e.
  3198. * it is not cloned).
  3199. * @param {object} settings dataTables settings object
  3200. * @param {array|node|jQuery} trs The TR element(s) to add to the table
  3201. * @returns {array} Array of indexes for the added rows
  3202. * @memberof DataTable#oApi
  3203. */
  3204. function _fnAddTr(settings, trs) {
  3205. var row;
  3206. // Allow an individual node to be passed in
  3207. if (!(trs instanceof $)) {
  3208. trs = $(trs);
  3209. }
  3210. return trs.map(function (i, el) {
  3211. row = _fnGetRowElements(settings, el);
  3212. return _fnAddData(settings, row.data, el, row.cells);
  3213. });
  3214. }
  3215. /**
  3216. * Take a TR element and convert it to an index in aoData
  3217. * @param {object} oSettings dataTables settings object
  3218. * @param {node} n the TR element to find
  3219. * @returns {int} index if the node is found, null if not
  3220. * @memberof DataTable#oApi
  3221. */
  3222. function _fnNodeToDataIndex(oSettings, n) {
  3223. return n._DT_RowIndex !== undefined ? n._DT_RowIndex : null;
  3224. }
  3225. /**
  3226. * Take a TD element and convert it into a column data index (not the visible index)
  3227. * @param {object} oSettings dataTables settings object
  3228. * @param {int} iRow The row number the TD/TH can be found in
  3229. * @param {node} n The TD/TH element to find
  3230. * @returns {int} index if the node is found, -1 if not
  3231. * @memberof DataTable#oApi
  3232. */
  3233. function _fnNodeToColumnIndex(oSettings, iRow, n) {
  3234. return $.inArray(n, oSettings.aoData[iRow].anCells);
  3235. }
  3236. /**
  3237. * Get the data for a given cell from the internal cache, taking into account data mapping
  3238. * @param {object} settings dataTables settings object
  3239. * @param {int} rowIdx aoData row id
  3240. * @param {int} colIdx Column index
  3241. * @param {string} type data get type ('display', 'type' 'filter' 'sort')
  3242. * @returns {*} Cell data
  3243. * @memberof DataTable#oApi
  3244. */
  3245. function _fnGetCellData(settings, rowIdx, colIdx, type) {
  3246. var draw = settings.iDraw;
  3247. var col = settings.aoColumns[colIdx];
  3248. var rowData = settings.aoData[rowIdx]._aData;
  3249. var defaultContent = col.sDefaultContent;
  3250. var cellData = col.fnGetData(rowData, type, {
  3251. settings: settings,
  3252. row: rowIdx,
  3253. col: colIdx
  3254. });
  3255. if (cellData === undefined) {
  3256. if (settings.iDrawError != draw && defaultContent === null) {
  3257. _fnLog(settings, 0, "Requested unknown parameter " + (typeof col.mData == 'function' ? '{function}' : "'" + col.mData + "'") + " for row " + rowIdx + ", column " + colIdx, 4);
  3258. settings.iDrawError = draw;
  3259. }
  3260. return defaultContent;
  3261. }
  3262. // When the data source is null and a specific data type is requested (i.e.
  3263. // not the original data), we can use default column data
  3264. if ((cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined) {
  3265. cellData = defaultContent;
  3266. } else if (typeof cellData === 'function') {
  3267. // If the data source is a function, then we run it and use the return,
  3268. // executing in the scope of the data object (for instances)
  3269. return cellData.call(rowData);
  3270. }
  3271. if (cellData === null && type == 'display') {
  3272. return '';
  3273. }
  3274. return cellData;
  3275. }
  3276. /**
  3277. * Set the value for a specific cell, into the internal data cache
  3278. * @param {object} settings dataTables settings object
  3279. * @param {int} rowIdx aoData row id
  3280. * @param {int} colIdx Column index
  3281. * @param {*} val Value to set
  3282. * @memberof DataTable#oApi
  3283. */
  3284. function _fnSetCellData(settings, rowIdx, colIdx, val) {
  3285. var col = settings.aoColumns[colIdx];
  3286. var rowData = settings.aoData[rowIdx]._aData;
  3287. col.fnSetData(rowData, val, {
  3288. settings: settings,
  3289. row: rowIdx,
  3290. col: colIdx
  3291. });
  3292. }
  3293. // Private variable that is used to match action syntax in the data property object
  3294. var __reArray = /\[.*?\]$/;
  3295. var __reFn = /\(\)$/;
  3296. /**
  3297. * Split string on periods, taking into account escaped periods
  3298. * @param {string} str String to split
  3299. * @return {array} Split string
  3300. */
  3301. function _fnSplitObjNotation(str) {
  3302. return $.map(str.match(/(\\.|[^\.])+/g) || [''], function (s) {
  3303. return s.replace(/\\\./g, '.');
  3304. });
  3305. }
  3306. /**
  3307. * Return a function that can be used to get data from a source object, taking
  3308. * into account the ability to use nested objects as a source
  3309. * @param {string|int|function} mSource The data source for the object
  3310. * @returns {function} Data get function
  3311. * @memberof DataTable#oApi
  3312. */
  3313. function _fnGetObjectDataFn(mSource) {
  3314. if ($.isPlainObject(mSource)) {
  3315. /* Build an object of get functions, and wrap them in a single call */
  3316. var o = {};
  3317. $.each(mSource, function (key, val) {
  3318. if (val) {
  3319. o[key] = _fnGetObjectDataFn(val);
  3320. }
  3321. });
  3322. return function (data, type, row, meta) {
  3323. var t = o[type] || o._;
  3324. return t !== undefined ? t(data, type, row, meta) : data;
  3325. };
  3326. } else if (mSource === null) {
  3327. /* Give an empty string for rendering / sorting etc */
  3328. return function (data) {
  3329. // type, row and meta also passed, but not used
  3330. return data;
  3331. };
  3332. } else if (typeof mSource === 'function') {
  3333. return function (data, type, row, meta) {
  3334. return mSource(data, type, row, meta);
  3335. };
  3336. } else if (typeof mSource === 'string' && (mSource.indexOf('.') !== - 1 || mSource.indexOf('[') !== - 1 || mSource.indexOf('(') !== - 1)) {
  3337. /* If there is a . in the source string then the data source is in a
  3338. * nested object so we loop over the data for each level to get the next
  3339. * level down. On each loop we test for undefined, and if found immediately
  3340. * return. This allows entire objects to be missing and sDefaultContent to
  3341. * be used if defined, rather than throwing an error
  3342. */
  3343. var fetchData = function fetchData(data, type, src) {
  3344. var arrayNotation, funcNotation, out, innerSrc;
  3345. if (src !== "") {
  3346. var a = _fnSplitObjNotation(src);
  3347. for (var i = 0, iLen = a.length; i < iLen; i++) {
  3348. // Check if we are dealing with special notation
  3349. arrayNotation = a[i].match(__reArray);
  3350. funcNotation = a[i].match(__reFn);
  3351. if (arrayNotation) {
  3352. // Array notation
  3353. a[i] = a[i].replace(__reArray, '');
  3354. // Condition allows simply [] to be passed in
  3355. if (a[i] !== "") {
  3356. data = data[a[i]];
  3357. }
  3358. out = [];
  3359. // Get the remainder of the nested object to get
  3360. a.splice(0, i + 1);
  3361. innerSrc = a.join('.');
  3362. // Traverse each entry in the array getting the properties requested
  3363. if ($.isArray(data)) {
  3364. for (var j = 0, jLen = data.length; j < jLen; j++) {
  3365. out.push(fetchData(data[j], type, innerSrc));
  3366. }
  3367. }
  3368. // If a string is given in between the array notation indicators, that
  3369. // is used to join the strings together, otherwise an array is returned
  3370. var join = arrayNotation[0].substring(1, arrayNotation[0].length - 1);
  3371. data = join === "" ? out : out.join(join);
  3372. // The inner call to fetchData has already traversed through the remainder
  3373. // of the source requested, so we exit from the loop
  3374. break;
  3375. } else if (funcNotation) {
  3376. // Function call
  3377. a[i] = a[i].replace(__reFn, '');
  3378. data = data[a[i]]();
  3379. continue;
  3380. }
  3381. if (data === null || data[a[i]] === undefined) {
  3382. return undefined;
  3383. }
  3384. data = data[a[i]];
  3385. }
  3386. }
  3387. return data;
  3388. };
  3389. return function (data, type) {
  3390. // row and meta also passed, but not used
  3391. return fetchData(data, type, mSource);
  3392. };
  3393. } else {
  3394. /* Array or flat object mapping */
  3395. return function (data, type) {
  3396. // row and meta also passed, but not used
  3397. return data[mSource];
  3398. };
  3399. }
  3400. }
  3401. /**
  3402. * Return a function that can be used to set data from a source object, taking
  3403. * into account the ability to use nested objects as a source
  3404. * @param {string|int|function} mSource The data source for the object
  3405. * @returns {function} Data set function
  3406. * @memberof DataTable#oApi
  3407. */
  3408. function _fnSetObjectDataFn(mSource) {
  3409. if ($.isPlainObject(mSource)) {
  3410. /* Unlike get, only the underscore (global) option is used for for
  3411. * setting data since we don't know the type here. This is why an object
  3412. * option is not documented for `mData` (which is read/write), but it is
  3413. * for `mRender` which is read only.
  3414. */
  3415. return _fnSetObjectDataFn(mSource._);
  3416. } else if (mSource === null) {
  3417. /* Nothing to do when the data source is null */
  3418. return function () {};
  3419. } else if (typeof mSource === 'function') {
  3420. return function (data, val, meta) {
  3421. mSource(data, 'set', val, meta);
  3422. };
  3423. } else if (typeof mSource === 'string' && (mSource.indexOf('.') !== - 1 || mSource.indexOf('[') !== - 1 || mSource.indexOf('(') !== - 1)) {
  3424. /* Like the get, we need to get data from a nested object */
  3425. var setData = function setData(data, val, src) {
  3426. var a = _fnSplitObjNotation(src),
  3427. b;
  3428. var aLast = a[a.length - 1];
  3429. var arrayNotation, funcNotation, o, innerSrc;
  3430. for (var i = 0, iLen = a.length - 1; i < iLen; i++) {
  3431. // Check if we are dealing with an array notation request
  3432. arrayNotation = a[i].match(__reArray);
  3433. funcNotation = a[i].match(__reFn);
  3434. if (arrayNotation) {
  3435. a[i] = a[i].replace(__reArray, '');
  3436. data[a[i]] = [];
  3437. // Get the remainder of the nested object to set so we can recurse
  3438. b = a.slice();
  3439. b.splice(0, i + 1);
  3440. innerSrc = b.join('.');
  3441. // Traverse each entry in the array setting the properties requested
  3442. if ($.isArray(val)) {
  3443. for (var j = 0, jLen = val.length; j < jLen; j++) {
  3444. o = {};
  3445. setData(o, val[j], innerSrc);
  3446. data[a[i]].push(o);
  3447. }
  3448. } else {
  3449. // We've been asked to save data to an array, but it
  3450. // isn't array data to be saved. Best that can be done
  3451. // is to just save the value.
  3452. data[a[i]] = val;
  3453. }
  3454. // The inner call to setData has already traversed through the remainder
  3455. // of the source and has set the data, thus we can exit here
  3456. return;
  3457. } else if (funcNotation) {
  3458. // Function call
  3459. a[i] = a[i].replace(__reFn, '');
  3460. data = data[a[i]](val);
  3461. }
  3462. // If the nested object doesn't currently exist - since we are
  3463. // trying to set the value - create it
  3464. if (data[a[i]] === null || data[a[i]] === undefined) {
  3465. data[a[i]] = {};
  3466. }
  3467. data = data[a[i]];
  3468. }
  3469. // Last item in the input - i.e, the actual set
  3470. if (aLast.match(__reFn)) {
  3471. // Function call
  3472. data = data[aLast.replace(__reFn, '')](val);
  3473. } else {
  3474. // If array notation is used, we just want to strip it and use the property name
  3475. // and assign the value. If it isn't used, then we get the result we want anyway
  3476. data[aLast.replace(__reArray, '')] = val;
  3477. }
  3478. };
  3479. return function (data, val) {
  3480. // meta is also passed in, but not used
  3481. return setData(data, val, mSource);
  3482. };
  3483. } else {
  3484. /* Array or flat object mapping */
  3485. return function (data, val) {
  3486. // meta is also passed in, but not used
  3487. data[mSource] = val;
  3488. };
  3489. }
  3490. }
  3491. /**
  3492. * Return an array with the full table data
  3493. * @param {object} oSettings dataTables settings object
  3494. * @returns array {array} aData Master data array
  3495. * @memberof DataTable#oApi
  3496. */
  3497. function _fnGetDataMaster(settings) {
  3498. return _pluck(settings.aoData, '_aData');
  3499. }
  3500. /**
  3501. * Nuke the table
  3502. * @param {object} oSettings dataTables settings object
  3503. * @memberof DataTable#oApi
  3504. */
  3505. function _fnClearTable(settings) {
  3506. settings.aoData.length = 0;
  3507. settings.aiDisplayMaster.length = 0;
  3508. settings.aiDisplay.length = 0;
  3509. settings.aIds = {};
  3510. }
  3511. /**
  3512. * Take an array of integers (index array) and remove a target integer (value - not
  3513. * the key!)
  3514. * @param {array} a Index array to target
  3515. * @param {int} iTarget value to find
  3516. * @memberof DataTable#oApi
  3517. */
  3518. function _fnDeleteIndex(a, iTarget, splice) {
  3519. var iTargetIndex = - 1;
  3520. for (var i = 0, iLen = a.length; i < iLen; i++) {
  3521. if (a[i] == iTarget) {
  3522. iTargetIndex = i;
  3523. } else if (a[i] > iTarget) {
  3524. a[i]--;
  3525. }
  3526. }
  3527. if (iTargetIndex != - 1 && splice === undefined) {
  3528. a.splice(iTargetIndex, 1);
  3529. }
  3530. }
  3531. /**
  3532. * Mark cached data as invalid such that a re-read of the data will occur when
  3533. * the cached data is next requested. Also update from the data source object.
  3534. *
  3535. * @param {object} settings DataTables settings object
  3536. * @param {int} rowIdx Row index to invalidate
  3537. * @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom'
  3538. * or 'data'
  3539. * @param {int} [colIdx] Column index to invalidate. If undefined the whole
  3540. * row will be invalidated
  3541. * @memberof DataTable#oApi
  3542. *
  3543. * @todo For the modularisation of v1.11 this will need to become a callback, so
  3544. * the sort and filter methods can subscribe to it. That will required
  3545. * initialisation options for sorting, which is why it is not already baked in
  3546. */
  3547. function _fnInvalidate(settings, rowIdx, src, colIdx) {
  3548. var row = settings.aoData[rowIdx];
  3549. var i, ien;
  3550. var cellWrite = function cellWrite(cell, col) {
  3551. // This is very frustrating, but in IE if you just write directly
  3552. // to innerHTML, and elements that are overwritten are GC'ed,
  3553. // even if there is a reference to them elsewhere
  3554. while (cell.childNodes.length) {
  3555. cell.removeChild(cell.firstChild);
  3556. }
  3557. cell.innerHTML = _fnGetCellData(settings, rowIdx, col, 'display');
  3558. };
  3559. // Are we reading last data from DOM or the data object?
  3560. if (src === 'dom' || (!src || src === 'auto') && row.src === 'dom') {
  3561. // Read the data from the DOM
  3562. row._aData = _fnGetRowElements(settings, row, colIdx, colIdx === undefined ? undefined : row._aData).data;
  3563. } else {
  3564. // Reading from data object, update the DOM
  3565. var cells = row.anCells;
  3566. if (cells) {
  3567. if (colIdx !== undefined) {
  3568. cellWrite(cells[colIdx], colIdx);
  3569. } else {
  3570. for (i = 0, ien = cells.length; i < ien; i++) {
  3571. cellWrite(cells[i], i);
  3572. }
  3573. }
  3574. }
  3575. }
  3576. // For both row and cell invalidation, the cached data for sorting and
  3577. // filtering is nulled out
  3578. row._aSortData = null;
  3579. row._aFilterData = null;
  3580. // Invalidate the type for a specific column (if given) or all columns since
  3581. // the data might have changed
  3582. var cols = settings.aoColumns;
  3583. if (colIdx !== undefined) {
  3584. cols[colIdx].sType = null;
  3585. } else {
  3586. for (i = 0, ien = cols.length; i < ien; i++) {
  3587. cols[i].sType = null;
  3588. }
  3589. // Update DataTables special `DT_*` attributes for the row
  3590. _fnRowAttributes(settings, row);
  3591. }
  3592. }
  3593. /**
  3594. * Build a data source object from an HTML row, reading the contents of the
  3595. * cells that are in the row.
  3596. *
  3597. * @param {object} settings DataTables settings object
  3598. * @param {node|object} TR element from which to read data or existing row
  3599. * object from which to re-read the data from the cells
  3600. * @param {int} [colIdx] Optional column index
  3601. * @param {array|object} [d] Data source object. If `colIdx` is given then this
  3602. * parameter should also be given and will be used to write the data into.
  3603. * Only the column in question will be written
  3604. * @returns {object} Object with two parameters: `data` the data read, in
  3605. * document order, and `cells` and array of nodes (they can be useful to the
  3606. * caller, so rather than needing a second traversal to get them, just return
  3607. * them from here).
  3608. * @memberof DataTable#oApi
  3609. */
  3610. function _fnGetRowElements(settings, row, colIdx, d) {
  3611. var tds = [],
  3612. td = row.firstChild,
  3613. name,
  3614. col,
  3615. o,
  3616. i = 0,
  3617. contents,
  3618. columns = settings.aoColumns,
  3619. objectRead = settings._rowReadObject;
  3620. // Allow the data object to be passed in, or construct
  3621. d = d !== undefined ? d : objectRead ? {} : [];
  3622. var attr = function attr(str, td) {
  3623. if (typeof str === 'string') {
  3624. var idx = str.indexOf('@');
  3625. if (idx !== - 1) {
  3626. var attr = str.substring(idx + 1);
  3627. var setter = _fnSetObjectDataFn(str);
  3628. setter(d, td.getAttribute(attr));
  3629. }
  3630. }
  3631. };
  3632. // Read data from a cell and store into the data object
  3633. var cellProcess = function cellProcess(cell) {
  3634. if (colIdx === undefined || colIdx === i) {
  3635. col = columns[i];
  3636. contents = $.trim(cell.innerHTML);
  3637. if (col && col._bAttrSrc) {
  3638. var setter = _fnSetObjectDataFn(col.mData._);
  3639. setter(d, contents);
  3640. attr(col.mData.sort, cell);
  3641. attr(col.mData.type, cell);
  3642. attr(col.mData.filter, cell);
  3643. } else {
  3644. // Depending on the `data` option for the columns the data can
  3645. // be read to either an object or an array.
  3646. if (objectRead) {
  3647. if (!col._setter) {
  3648. // Cache the setter function
  3649. col._setter = _fnSetObjectDataFn(col.mData);
  3650. }
  3651. col._setter(d, contents);
  3652. } else {
  3653. d[i] = contents;
  3654. }
  3655. }
  3656. }
  3657. i++;
  3658. };
  3659. if (td) {
  3660. // `tr` element was passed in
  3661. while (td) {
  3662. name = td.nodeName.toUpperCase();
  3663. if (name == "TD" || name == "TH") {
  3664. cellProcess(td);
  3665. tds.push(td);
  3666. }
  3667. td = td.nextSibling;
  3668. }
  3669. } else {
  3670. // Existing row object passed in
  3671. tds = row.anCells;
  3672. for (var j = 0, jen = tds.length; j < jen; j++) {
  3673. cellProcess(tds[j]);
  3674. }
  3675. }
  3676. // Read the ID from the DOM if present
  3677. var rowNode = row.firstChild ? row : row.nTr;
  3678. if (rowNode) {
  3679. var id = rowNode.getAttribute('id');
  3680. if (id) {
  3681. _fnSetObjectDataFn(settings.rowId)(d, id);
  3682. }
  3683. }
  3684. return {
  3685. data: d,
  3686. cells: tds
  3687. };
  3688. }
  3689. /**
  3690. * Create a new TR element (and it's TD children) for a row
  3691. * @param {object} oSettings dataTables settings object
  3692. * @param {int} iRow Row to consider
  3693. * @param {node} [nTrIn] TR element to add to the table - optional. If not given,
  3694. * DataTables will create a row automatically
  3695. * @param {array} [anTds] Array of TD|TH elements for the row - must be given
  3696. * if nTr is.
  3697. * @memberof DataTable#oApi
  3698. */
  3699. function _fnCreateTr(oSettings, iRow, nTrIn, anTds) {
  3700. var row = oSettings.aoData[iRow],
  3701. rowData = row._aData,
  3702. cells = [],
  3703. nTr,
  3704. nTd,
  3705. oCol,
  3706. i,
  3707. iLen;
  3708. if (row.nTr === null) {
  3709. nTr = nTrIn || document.createElement('tr');
  3710. row.nTr = nTr;
  3711. row.anCells = cells;
  3712. /* Use a private property on the node to allow reserve mapping from the node
  3713. * to the aoData array for fast look up
  3714. */
  3715. nTr._DT_RowIndex = iRow;
  3716. /* Special parameters can be given by the data source to be used on the row */
  3717. _fnRowAttributes(oSettings, row);
  3718. /* Process each column */
  3719. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  3720. oCol = oSettings.aoColumns[i];
  3721. nTd = nTrIn ? anTds[i] : document.createElement(oCol.sCellType);
  3722. nTd._DT_CellIndex = {
  3723. row: iRow,
  3724. column: i
  3725. };
  3726. cells.push(nTd);
  3727. // Need to create the HTML if new, or if a rendering function is defined
  3728. if ((!nTrIn || oCol.mRender || oCol.mData !== i) && (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i + '.display')) {
  3729. nTd.innerHTML = _fnGetCellData(oSettings, iRow, i, 'display');
  3730. }
  3731. /* Add user defined class */
  3732. if (oCol.sClass) {
  3733. nTd.className += ' ' + oCol.sClass;
  3734. }
  3735. // Visibility - add or remove as required
  3736. if (oCol.bVisible && !nTrIn) {
  3737. nTr.appendChild(nTd);
  3738. } else if (!oCol.bVisible && nTrIn) {
  3739. nTd.parentNode.removeChild(nTd);
  3740. }
  3741. if (oCol.fnCreatedCell) {
  3742. oCol.fnCreatedCell.call(oSettings.oInstance, nTd, _fnGetCellData(oSettings, iRow, i), rowData, iRow, i);
  3743. }
  3744. }
  3745. _fnCallbackFire(oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow]);
  3746. }
  3747. // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
  3748. // and deployed
  3749. row.nTr.setAttribute('role', 'row');
  3750. }
  3751. /**
  3752. * Add attributes to a row based on the special `DT_*` parameters in a data
  3753. * source object.
  3754. * @param {object} settings DataTables settings object
  3755. * @param {object} DataTables row object for the row to be modified
  3756. * @memberof DataTable#oApi
  3757. */
  3758. function _fnRowAttributes(settings, row) {
  3759. var tr = row.nTr;
  3760. var data = row._aData;
  3761. if (tr) {
  3762. var id = settings.rowIdFn(data);
  3763. if (id) {
  3764. tr.id = id;
  3765. }
  3766. if (data.DT_RowClass) {
  3767. // Remove any classes added by DT_RowClass before
  3768. var a = data.DT_RowClass.split(' ');
  3769. row.__rowc = row.__rowc ? _unique(row.__rowc.concat(a)) : a;
  3770. $(tr).removeClass(row.__rowc.join(' ')).addClass(data.DT_RowClass);
  3771. }
  3772. if (data.DT_RowAttr) {
  3773. $(tr).attr(data.DT_RowAttr);
  3774. }
  3775. if (data.DT_RowData) {
  3776. $(tr).data(data.DT_RowData);
  3777. }
  3778. }
  3779. }
  3780. /**
  3781. * Create the HTML header for the table
  3782. * @param {object} oSettings dataTables settings object
  3783. * @memberof DataTable#oApi
  3784. */
  3785. function _fnBuildHead(oSettings) {
  3786. var i, ien, cell, row, column;
  3787. var thead = oSettings.nTHead;
  3788. var tfoot = oSettings.nTFoot;
  3789. var createHeader = $('th, td', thead).length === 0;
  3790. var classes = oSettings.oClasses;
  3791. var columns = oSettings.aoColumns;
  3792. if (createHeader) {
  3793. row = $('<tr/>').appendTo(thead);
  3794. }
  3795. for (i = 0, ien = columns.length; i < ien; i++) {
  3796. column = columns[i];
  3797. cell = $(column.nTh).addClass(column.sClass);
  3798. if (createHeader) {
  3799. cell.appendTo(row);
  3800. }
  3801. // 1.11 move into sorting
  3802. if (oSettings.oFeatures.bSort) {
  3803. cell.addClass(column.sSortingClass);
  3804. if (column.bSortable !== false) {
  3805. cell.attr('tabindex', oSettings.iTabIndex).attr('aria-controls', oSettings.sTableId);
  3806. _fnSortAttachListener(oSettings, column.nTh, i);
  3807. }
  3808. }
  3809. if (column.sTitle != cell[0].innerHTML) {
  3810. cell.html(column.sTitle);
  3811. }
  3812. _fnRenderer(oSettings, 'header')(oSettings, cell, column, classes);
  3813. }
  3814. if (createHeader) {
  3815. _fnDetectHeader(oSettings.aoHeader, thead);
  3816. }
  3817. /* ARIA role for the rows */
  3818. $(thead).find('>tr').attr('role', 'row');
  3819. /* Deal with the footer - add classes if required */
  3820. $(thead).find('>tr>th, >tr>td').addClass(classes.sHeaderTH);
  3821. $(tfoot).find('>tr>th, >tr>td').addClass(classes.sFooterTH);
  3822. // Cache the footer cells. Note that we only take the cells from the first
  3823. // row in the footer. If there is more than one row the user wants to
  3824. // interact with, they need to use the table().foot() method. Note also this
  3825. // allows cells to be used for multiple columns using colspan
  3826. if (tfoot !== null) {
  3827. var cells = oSettings.aoFooter[0];
  3828. for (i = 0, ien = cells.length; i < ien; i++) {
  3829. column = columns[i];
  3830. column.nTf = cells[i].cell;
  3831. if (column.sClass) {
  3832. $(column.nTf).addClass(column.sClass);
  3833. }
  3834. }
  3835. }
  3836. }
  3837. /**
  3838. * Draw the header (or footer) element based on the column visibility states. The
  3839. * methodology here is to use the layout array from _fnDetectHeader, modified for
  3840. * the instantaneous column visibility, to construct the new layout. The grid is
  3841. * traversed over cell at a time in a rows x columns grid fashion, although each
  3842. * cell insert can cover multiple elements in the grid - which is tracks using the
  3843. * aApplied array. Cell inserts in the grid will only occur where there isn't
  3844. * already a cell in that position.
  3845. * @param {object} oSettings dataTables settings object
  3846. * @param array {objects} aoSource Layout array from _fnDetectHeader
  3847. * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
  3848. * @memberof DataTable#oApi
  3849. */
  3850. function _fnDrawHead(oSettings, aoSource, bIncludeHidden) {
  3851. var i, iLen, j, jLen, k, kLen, n, nLocalTr;
  3852. var aoLocal = [];
  3853. var aApplied = [];
  3854. var iColumns = oSettings.aoColumns.length;
  3855. var iRowspan, iColspan;
  3856. if (!aoSource) {
  3857. return;
  3858. }
  3859. if (bIncludeHidden === undefined) {
  3860. bIncludeHidden = false;
  3861. }
  3862. /* Make a copy of the master layout array, but without the visible columns in it */
  3863. for (i = 0, iLen = aoSource.length; i < iLen; i++) {
  3864. aoLocal[i] = aoSource[i].slice();
  3865. aoLocal[i].nTr = aoSource[i].nTr;
  3866. /* Remove any columns which are currently hidden */
  3867. for (j = iColumns - 1; j >= 0; j--) {
  3868. if (!oSettings.aoColumns[j].bVisible && !bIncludeHidden) {
  3869. aoLocal[i].splice(j, 1);
  3870. }
  3871. }
  3872. /* Prep the applied array - it needs an element for each row */
  3873. aApplied.push([]);
  3874. }
  3875. for (i = 0, iLen = aoLocal.length; i < iLen; i++) {
  3876. nLocalTr = aoLocal[i].nTr;
  3877. /* All cells are going to be replaced, so empty out the row */
  3878. if (nLocalTr) {
  3879. while (n = nLocalTr.firstChild) {
  3880. nLocalTr.removeChild(n);
  3881. }
  3882. }
  3883. for (j = 0, jLen = aoLocal[i].length; j < jLen; j++) {
  3884. iRowspan = 1;
  3885. iColspan = 1;
  3886. /* Check to see if there is already a cell (row/colspan) covering our target
  3887. * insert point. If there is, then there is nothing to do.
  3888. */
  3889. if (aApplied[i][j] === undefined) {
  3890. nLocalTr.appendChild(aoLocal[i][j].cell);
  3891. aApplied[i][j] = 1;
  3892. /* Expand the cell to cover as many rows as needed */
  3893. while (aoLocal[i + iRowspan] !== undefined && aoLocal[i][j].cell == aoLocal[i + iRowspan][j].cell) {
  3894. aApplied[i + iRowspan][j] = 1;
  3895. iRowspan++;
  3896. }
  3897. /* Expand the cell to cover as many columns as needed */
  3898. while (aoLocal[i][j + iColspan] !== undefined && aoLocal[i][j].cell == aoLocal[i][j + iColspan].cell) {
  3899. /* Must update the applied array over the rows for the columns */
  3900. for (k = 0; k < iRowspan; k++) {
  3901. aApplied[i + k][j + iColspan] = 1;
  3902. }
  3903. iColspan++;
  3904. }
  3905. /* Do the actual expansion in the DOM */
  3906. $(aoLocal[i][j].cell).attr('rowspan', iRowspan).attr('colspan', iColspan);
  3907. }
  3908. }
  3909. }
  3910. }
  3911. /**
  3912. * Insert the required TR nodes into the table for display
  3913. * @param {object} oSettings dataTables settings object
  3914. * @memberof DataTable#oApi
  3915. */
  3916. function _fnDraw(oSettings) {
  3917. /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
  3918. var aPreDraw = _fnCallbackFire(oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings]);
  3919. if ($.inArray(false, aPreDraw) !== - 1) {
  3920. _fnProcessingDisplay(oSettings, false);
  3921. return;
  3922. }
  3923. var i, iLen, n;
  3924. var anRows = [];
  3925. var iRowCount = 0;
  3926. var asStripeClasses = oSettings.asStripeClasses;
  3927. var iStripes = asStripeClasses.length;
  3928. var iOpenRows = oSettings.aoOpenRows.length;
  3929. var oLang = oSettings.oLanguage;
  3930. var iInitDisplayStart = oSettings.iInitDisplayStart;
  3931. var bServerSide = _fnDataSource(oSettings) == 'ssp';
  3932. var aiDisplay = oSettings.aiDisplay;
  3933. oSettings.bDrawing = true;
  3934. /* Check and see if we have an initial draw position from state saving */
  3935. if (iInitDisplayStart !== undefined && iInitDisplayStart !== - 1) {
  3936. oSettings._iDisplayStart = bServerSide ? iInitDisplayStart : iInitDisplayStart >= oSettings.fnRecordsDisplay() ? 0 : iInitDisplayStart;
  3937. oSettings.iInitDisplayStart = - 1;
  3938. }
  3939. var iDisplayStart = oSettings._iDisplayStart;
  3940. var iDisplayEnd = oSettings.fnDisplayEnd();
  3941. /* Server-side processing draw intercept */
  3942. if (oSettings.bDeferLoading) {
  3943. oSettings.bDeferLoading = false;
  3944. oSettings.iDraw++;
  3945. _fnProcessingDisplay(oSettings, false);
  3946. } else if (!bServerSide) {
  3947. oSettings.iDraw++;
  3948. } else if (!oSettings.bDestroying && !_fnAjaxUpdate(oSettings)) {
  3949. return;
  3950. }
  3951. if (aiDisplay.length !== 0) {
  3952. var iStart = bServerSide ? 0 : iDisplayStart;
  3953. var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
  3954. for (var j = iStart; j < iEnd; j++) {
  3955. var iDataIndex = aiDisplay[j];
  3956. var aoData = oSettings.aoData[iDataIndex];
  3957. if (aoData.nTr === null) {
  3958. _fnCreateTr(oSettings, iDataIndex);
  3959. }
  3960. var nRow = aoData.nTr;
  3961. /* Remove the old striping classes and then add the new one */
  3962. if (iStripes !== 0) {
  3963. var sStripe = asStripeClasses[iRowCount % iStripes];
  3964. if (aoData._sRowStripe != sStripe) {
  3965. $(nRow).removeClass(aoData._sRowStripe).addClass(sStripe);
  3966. aoData._sRowStripe = sStripe;
  3967. }
  3968. }
  3969. // Row callback functions - might want to manipulate the row
  3970. // iRowCount and j are not currently documented. Are they at all
  3971. // useful?
  3972. _fnCallbackFire(oSettings, 'aoRowCallback', null, [nRow, aoData._aData, iRowCount, j]);
  3973. anRows.push(nRow);
  3974. iRowCount++;
  3975. }
  3976. } else {
  3977. /* Table is empty - create a row with an empty message in it */
  3978. var sZero = oLang.sZeroRecords;
  3979. if (oSettings.iDraw == 1 && _fnDataSource(oSettings) == 'ajax') {
  3980. sZero = oLang.sLoadingRecords;
  3981. } else if (oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0) {
  3982. sZero = oLang.sEmptyTable;
  3983. }
  3984. anRows[0] = $('<tr/>', {'class': iStripes ? asStripeClasses[0] : ''}).append($('<td />', {
  3985. 'valign': 'top',
  3986. 'colSpan': _fnVisbleColumns(oSettings),
  3987. 'class': oSettings.oClasses.sRowEmpty
  3988. }).html(sZero))[0];
  3989. }
  3990. /* Header and footer callbacks */
  3991. _fnCallbackFire(oSettings, 'aoHeaderCallback', 'header', [$(oSettings.nTHead).children('tr')[0], _fnGetDataMaster(oSettings), iDisplayStart, iDisplayEnd, aiDisplay]);
  3992. _fnCallbackFire(oSettings, 'aoFooterCallback', 'footer', [$(oSettings.nTFoot).children('tr')[0], _fnGetDataMaster(oSettings), iDisplayStart, iDisplayEnd, aiDisplay]);
  3993. var body = $(oSettings.nTBody);
  3994. body.children().detach();
  3995. body.append($(anRows));
  3996. /* Call all required callback functions for the end of a draw */
  3997. _fnCallbackFire(oSettings, 'aoDrawCallback', 'draw', [oSettings]);
  3998. /* Draw is complete, sorting and filtering must be as well */
  3999. oSettings.bSorted = false;
  4000. oSettings.bFiltered = false;
  4001. oSettings.bDrawing = false;
  4002. }
  4003. /**
  4004. * Redraw the table - taking account of the various features which are enabled
  4005. * @param {object} oSettings dataTables settings object
  4006. * @param {boolean} [holdPosition] Keep the current paging position. By default
  4007. * the paging is reset to the first page
  4008. * @memberof DataTable#oApi
  4009. */
  4010. function _fnReDraw(settings, holdPosition) {
  4011. var features = settings.oFeatures,
  4012. sort = features.bSort,
  4013. filter = features.bFilter;
  4014. if (sort) {
  4015. _fnSort(settings);
  4016. }
  4017. if (filter) {
  4018. _fnFilterComplete(settings, settings.oPreviousSearch);
  4019. } else {
  4020. // No filtering, so we want to just use the display master
  4021. settings.aiDisplay = settings.aiDisplayMaster.slice();
  4022. }
  4023. if (holdPosition !== true) {
  4024. settings._iDisplayStart = 0;
  4025. }
  4026. // Let any modules know about the draw hold position state (used by
  4027. // scrolling internally)
  4028. settings._drawHold = holdPosition;
  4029. _fnDraw(settings);
  4030. settings._drawHold = false;
  4031. }
  4032. /**
  4033. * Add the options to the page HTML for the table
  4034. * @param {object} oSettings dataTables settings object
  4035. * @memberof DataTable#oApi
  4036. */
  4037. function _fnAddOptionsHtml(oSettings) {
  4038. var classes = oSettings.oClasses;
  4039. var table = $(oSettings.nTable);
  4040. var holding = $('<div/>').insertBefore(table); // Holding element for speed
  4041. var features = oSettings.oFeatures;
  4042. // All DataTables are wrapped in a div
  4043. var insert = $('<div/>', {
  4044. id: oSettings.sTableId + '_wrapper',
  4045. 'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' ' + classes.sNoFooter)
  4046. });
  4047. oSettings.nHolding = holding[0];
  4048. oSettings.nTableWrapper = insert[0];
  4049. oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
  4050. /* Loop over the user set positioning and place the elements as needed */
  4051. var aDom = oSettings.sDom.split('');
  4052. var featureNode, cOption, nNewNode, cNext, sAttr, j;
  4053. for (var i = 0; i < aDom.length; i++) {
  4054. featureNode = null;
  4055. cOption = aDom[i];
  4056. if (cOption == '<') {
  4057. /* New container div */
  4058. nNewNode = $('<div/>')[0];
  4059. /* Check to see if we should append an id and/or a class name to the container */
  4060. cNext = aDom[i + 1];
  4061. if (cNext == "'" || cNext == '"') {
  4062. sAttr = "";
  4063. j = 2;
  4064. while (aDom[i + j] != cNext) {
  4065. sAttr += aDom[i + j];
  4066. j++;
  4067. }
  4068. /* Replace jQuery UI constants @todo depreciated */
  4069. if (sAttr == "H") {
  4070. sAttr = classes.sJUIHeader;
  4071. } else if (sAttr == "F") {
  4072. sAttr = classes.sJUIFooter;
  4073. }
  4074. /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
  4075. * breaks the string into parts and applies them as needed
  4076. */
  4077. if (sAttr.indexOf('.') != - 1) {
  4078. var aSplit = sAttr.split('.');
  4079. nNewNode.id = aSplit[0].substr(1, aSplit[0].length - 1);
  4080. nNewNode.className = aSplit[1];
  4081. } else if (sAttr.charAt(0) == "#") {
  4082. nNewNode.id = sAttr.substr(1, sAttr.length - 1);
  4083. } else {
  4084. nNewNode.className = sAttr;
  4085. }
  4086. i += j; /* Move along the position array */
  4087. }
  4088. insert.append(nNewNode);
  4089. insert = $(nNewNode);
  4090. } else if (cOption == '>') {
  4091. /* End container div */
  4092. insert = insert.parent();
  4093. }
  4094. // @todo Move options into their own plugins?
  4095. else if (cOption == 'l' && features.bPaginate && features.bLengthChange) {
  4096. /* Length */
  4097. featureNode = _fnFeatureHtmlLength(oSettings);
  4098. } else if (cOption == 'f' && features.bFilter) {
  4099. /* Filter */
  4100. featureNode = _fnFeatureHtmlFilter(oSettings);
  4101. } else if (cOption == 'r' && features.bProcessing) {
  4102. /* pRocessing */
  4103. featureNode = _fnFeatureHtmlProcessing(oSettings);
  4104. } else if (cOption == 't') {
  4105. /* Table */
  4106. featureNode = _fnFeatureHtmlTable(oSettings);
  4107. } else if (cOption == 'i' && features.bInfo) {
  4108. /* Info */
  4109. featureNode = _fnFeatureHtmlInfo(oSettings);
  4110. } else if (cOption == 'p' && features.bPaginate) {
  4111. /* Pagination */
  4112. featureNode = _fnFeatureHtmlPaginate(oSettings);
  4113. } else if (DataTable.ext.feature.length !== 0) {
  4114. /* Plug-in features */
  4115. var aoFeatures = DataTable.ext.feature;
  4116. for (var k = 0, kLen = aoFeatures.length; k < kLen; k++) {
  4117. if (cOption == aoFeatures[k].cFeature) {
  4118. featureNode = aoFeatures[k].fnInit(oSettings);
  4119. break;
  4120. }
  4121. }
  4122. }
  4123. /* Add to the 2D features array */
  4124. if (featureNode) {
  4125. var aanFeatures = oSettings.aanFeatures;
  4126. if (!aanFeatures[cOption]) {
  4127. aanFeatures[cOption] = [];
  4128. }
  4129. aanFeatures[cOption].push(featureNode);
  4130. insert.append(featureNode);
  4131. }
  4132. }
  4133. /* Built our DOM structure - replace the holding div with what we want */
  4134. holding.replaceWith(insert);
  4135. oSettings.nHolding = null;
  4136. }
  4137. /**
  4138. * Use the DOM source to create up an array of header cells. The idea here is to
  4139. * create a layout grid (array) of rows x columns, which contains a reference
  4140. * to the cell that that point in the grid (regardless of col/rowspan), such that
  4141. * any column / row could be removed and the new grid constructed
  4142. * @param array {object} aLayout Array to store the calculated layout in
  4143. * @param {node} nThead The header/footer element for the table
  4144. * @memberof DataTable#oApi
  4145. */
  4146. function _fnDetectHeader(aLayout, nThead) {
  4147. var nTrs = $(nThead).children('tr');
  4148. var nTr, nCell;
  4149. var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
  4150. var bUnique;
  4151. var fnShiftCol = function fnShiftCol(a, i, j) {
  4152. var k = a[i];
  4153. while (k[j]) {
  4154. j++;
  4155. }
  4156. return j;
  4157. };
  4158. aLayout.splice(0, aLayout.length);
  4159. /* We know how many rows there are in the layout - so prep it */
  4160. for (i = 0, iLen = nTrs.length; i < iLen; i++) {
  4161. aLayout.push([]);
  4162. }
  4163. /* Calculate a layout array */
  4164. for (i = 0, iLen = nTrs.length; i < iLen; i++) {
  4165. nTr = nTrs[i];
  4166. iColumn = 0;
  4167. /* For every cell in the row... */
  4168. nCell = nTr.firstChild;
  4169. while (nCell) {
  4170. if (nCell.nodeName.toUpperCase() == "TD" || nCell.nodeName.toUpperCase() == "TH") {
  4171. /* Get the col and rowspan attributes from the DOM and sanitise them */
  4172. iColspan = nCell.getAttribute('colspan') * 1;
  4173. iRowspan = nCell.getAttribute('rowspan') * 1;
  4174. iColspan = !iColspan || iColspan === 0 || iColspan === 1 ? 1 : iColspan;
  4175. iRowspan = !iRowspan || iRowspan === 0 || iRowspan === 1 ? 1 : iRowspan;
  4176. /* There might be colspan cells already in this row, so shift our target
  4177. * accordingly
  4178. */
  4179. iColShifted = fnShiftCol(aLayout, i, iColumn);
  4180. /* Cache calculation for unique columns */
  4181. bUnique = iColspan === 1 ? true : false;
  4182. /* If there is col / rowspan, copy the information into the layout grid */
  4183. for (l = 0; l < iColspan; l++) {
  4184. for (k = 0; k < iRowspan; k++) {
  4185. aLayout[i + k][iColShifted + l] = {
  4186. "cell": nCell,
  4187. "unique": bUnique
  4188. };
  4189. aLayout[i + k].nTr = nTr;
  4190. }
  4191. }
  4192. }
  4193. nCell = nCell.nextSibling;
  4194. }
  4195. }
  4196. }
  4197. /**
  4198. * Get an array of unique th elements, one for each column
  4199. * @param {object} oSettings dataTables settings object
  4200. * @param {node} nHeader automatically detect the layout from this node - optional
  4201. * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
  4202. * @returns array {node} aReturn list of unique th's
  4203. * @memberof DataTable#oApi
  4204. */
  4205. function _fnGetUniqueThs(oSettings, nHeader, aLayout) {
  4206. var aReturn = [];
  4207. if (!aLayout) {
  4208. aLayout = oSettings.aoHeader;
  4209. if (nHeader) {
  4210. aLayout = [];
  4211. _fnDetectHeader(aLayout, nHeader);
  4212. }
  4213. }
  4214. for (var i = 0, iLen = aLayout.length; i < iLen; i++) {
  4215. for (var j = 0, jLen = aLayout[i].length; j < jLen; j++) {
  4216. if (aLayout[i][j].unique && (!aReturn[j] || !oSettings.bSortCellsTop)) {
  4217. aReturn[j] = aLayout[i][j].cell;
  4218. }
  4219. }
  4220. }
  4221. return aReturn;
  4222. }
  4223. /**
  4224. * Create an Ajax call based on the table's settings, taking into account that
  4225. * parameters can have multiple forms, and backwards compatibility.
  4226. *
  4227. * @param {object} oSettings dataTables settings object
  4228. * @param {array} data Data to send to the server, required by
  4229. * DataTables - may be augmented by developer callbacks
  4230. * @param {function} fn Callback function to run when data is obtained
  4231. */
  4232. function _fnBuildAjax(oSettings, data, fn) {
  4233. // Compatibility with 1.9-, allow fnServerData and event to manipulate
  4234. _fnCallbackFire(oSettings, 'aoServerParams', 'serverParams', [data]);
  4235. // Convert to object based for 1.10+ if using the old array scheme which can
  4236. // come from server-side processing or serverParams
  4237. if (data && $.isArray(data)) {
  4238. var tmp = {};
  4239. var rbracket = /(.*?)\[\]$/;
  4240. $.each(data, function (key, val) {
  4241. var match = val.name.match(rbracket);
  4242. if (match) {
  4243. // Support for arrays
  4244. var name = match[0];
  4245. if (!tmp[name]) {
  4246. tmp[name] = [];
  4247. }
  4248. tmp[name].push(val.value);
  4249. } else {
  4250. tmp[val.name] = val.value;
  4251. }
  4252. });
  4253. data = tmp;
  4254. }
  4255. var ajaxData;
  4256. var ajax = oSettings.ajax;
  4257. var instance = oSettings.oInstance;
  4258. var callback = function callback(json) {
  4259. _fnCallbackFire(oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR]);
  4260. fn(json);
  4261. };
  4262. if ($.isPlainObject(ajax) && ajax.data) {
  4263. ajaxData = ajax.data;
  4264. var newData = $.isFunction(ajaxData) ? ajaxData(data, oSettings) : // fn can manipulate data or return
  4265. ajaxData; // an object object or array to merge
  4266. // If the function returned something, use that alone
  4267. data = $.isFunction(ajaxData) && newData ? newData : $.extend(true, data, newData);
  4268. // Remove the data property as we've resolved it already and don't want
  4269. // jQuery to do it again (it is restored at the end of the function)
  4270. delete ajax.data;
  4271. }
  4272. var baseAjax = {
  4273. "data": data,
  4274. "success": function success(json) {
  4275. var error = json.error || json.sError;
  4276. if (error) {
  4277. _fnLog(oSettings, 0, error);
  4278. }
  4279. oSettings.json = json;
  4280. callback(json);
  4281. },
  4282. "dataType": "json",
  4283. "cache": false,
  4284. "type": oSettings.sServerMethod,
  4285. "error": function error(xhr, _error, thrown) {
  4286. var ret = _fnCallbackFire(oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR]);
  4287. if ($.inArray(true, ret) === - 1) {
  4288. if (_error == "parsererror") {
  4289. _fnLog(oSettings, 0, 'Invalid JSON response', 1);
  4290. } else if (xhr.readyState === 4) {
  4291. _fnLog(oSettings, 0, 'Ajax error', 7);
  4292. }
  4293. }
  4294. _fnProcessingDisplay(oSettings, false);
  4295. }
  4296. };
  4297. // Store the data submitted for the API
  4298. oSettings.oAjaxData = data;
  4299. // Allow plug-ins and external processes to modify the data
  4300. _fnCallbackFire(oSettings, null, 'preXhr', [oSettings, data]);
  4301. if (oSettings.fnServerData) {
  4302. // DataTables 1.9- compatibility
  4303. oSettings.fnServerData.call(instance, oSettings.sAjaxSource, $.map(data, function (val, key) {
  4304. // Need to convert back to 1.9 trad format
  4305. return {name: key, value: val};
  4306. }), callback, oSettings);
  4307. } else if (oSettings.sAjaxSource || typeof ajax === 'string') {
  4308. // DataTables 1.9- compatibility
  4309. oSettings.jqXHR = $.ajax($.extend(baseAjax, {
  4310. url: ajax || oSettings.sAjaxSource
  4311. }));
  4312. } else if ($.isFunction(ajax)) {
  4313. // Is a function - let the caller define what needs to be done
  4314. oSettings.jqXHR = ajax.call(instance, data, callback, oSettings);
  4315. } else {
  4316. // Object to extend the base settings
  4317. oSettings.jqXHR = $.ajax($.extend(baseAjax, ajax));
  4318. // Restore for next time around
  4319. ajax.data = ajaxData;
  4320. }
  4321. }
  4322. /**
  4323. * Update the table using an Ajax call
  4324. * @param {object} settings dataTables settings object
  4325. * @returns {boolean} Block the table drawing or not
  4326. * @memberof DataTable#oApi
  4327. */
  4328. function _fnAjaxUpdate(settings) {
  4329. if (settings.bAjaxDataGet) {
  4330. settings.iDraw++;
  4331. _fnProcessingDisplay(settings, true);
  4332. _fnBuildAjax(settings, _fnAjaxParameters(settings), function (json) {
  4333. _fnAjaxUpdateDraw(settings, json);
  4334. });
  4335. return false;
  4336. }
  4337. return true;
  4338. }
  4339. /**
  4340. * Build up the parameters in an object needed for a server-side processing
  4341. * request. Note that this is basically done twice, is different ways - a modern
  4342. * method which is used by default in DataTables 1.10 which uses objects and
  4343. * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
  4344. * the sAjaxSource option is used in the initialisation, or the legacyAjax
  4345. * option is set.
  4346. * @param {object} oSettings dataTables settings object
  4347. * @returns {bool} block the table drawing or not
  4348. * @memberof DataTable#oApi
  4349. */
  4350. function _fnAjaxParameters(settings) {
  4351. var columns = settings.aoColumns,
  4352. columnCount = columns.length,
  4353. features = settings.oFeatures,
  4354. preSearch = settings.oPreviousSearch,
  4355. preColSearch = settings.aoPreSearchCols,
  4356. i,
  4357. data = [],
  4358. dataProp,
  4359. column,
  4360. columnSearch,
  4361. sort = _fnSortFlatten(settings),
  4362. displayStart = settings._iDisplayStart,
  4363. displayLength = features.bPaginate !== false ? settings._iDisplayLength : - 1;
  4364. var param = function param(name, value) {
  4365. data.push({'name': name, 'value': value});
  4366. };
  4367. // DataTables 1.9- compatible method
  4368. param('sEcho', settings.iDraw);
  4369. param('iColumns', columnCount);
  4370. param('sColumns', _pluck(columns, 'sName').join(','));
  4371. param('iDisplayStart', displayStart);
  4372. param('iDisplayLength', displayLength);
  4373. // DataTables 1.10+ method
  4374. var d = {
  4375. draw: settings.iDraw,
  4376. columns: [],
  4377. order: [],
  4378. start: displayStart,
  4379. length: displayLength,
  4380. search: {
  4381. value: preSearch.sSearch,
  4382. regex: preSearch.bRegex
  4383. }
  4384. };
  4385. for (i = 0; i < columnCount; i++) {
  4386. column = columns[i];
  4387. columnSearch = preColSearch[i];
  4388. dataProp = typeof column.mData == "function" ? 'function' : column.mData;
  4389. d.columns.push({
  4390. data: dataProp,
  4391. name: column.sName,
  4392. searchable: column.bSearchable,
  4393. orderable: column.bSortable,
  4394. search: {
  4395. value: columnSearch.sSearch,
  4396. regex: columnSearch.bRegex
  4397. }
  4398. });
  4399. param("mDataProp_" + i, dataProp);
  4400. if (features.bFilter) {
  4401. param('sSearch_' + i, columnSearch.sSearch);
  4402. param('bRegex_' + i, columnSearch.bRegex);
  4403. param('bSearchable_' + i, column.bSearchable);
  4404. }
  4405. if (features.bSort) {
  4406. param('bSortable_' + i, column.bSortable);
  4407. }
  4408. }
  4409. if (features.bFilter) {
  4410. param('sSearch', preSearch.sSearch);
  4411. param('bRegex', preSearch.bRegex);
  4412. }
  4413. if (features.bSort) {
  4414. $.each(sort, function (i, val) {
  4415. d.order.push({column: val.col, dir: val.dir});
  4416. param('iSortCol_' + i, val.col);
  4417. param('sSortDir_' + i, val.dir);
  4418. });
  4419. param('iSortingCols', sort.length);
  4420. }
  4421. // If the legacy.ajax parameter is null, then we automatically decide which
  4422. // form to use, based on sAjaxSource
  4423. var legacy = DataTable.ext.legacy.ajax;
  4424. if (legacy === null) {
  4425. return settings.sAjaxSource ? data : d;
  4426. }
  4427. // Otherwise, if legacy has been specified then we use that to decide on the
  4428. // form
  4429. return legacy ? data : d;
  4430. }
  4431. /**
  4432. * Data the data from the server (nuking the old) and redraw the table
  4433. * @param {object} oSettings dataTables settings object
  4434. * @param {object} json json data return from the server.
  4435. * @param {string} json.sEcho Tracking flag for DataTables to match requests
  4436. * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
  4437. * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
  4438. * @param {array} json.aaData The data to display on this page
  4439. * @param {string} [json.sColumns] Column ordering (sName, comma separated)
  4440. * @memberof DataTable#oApi
  4441. */
  4442. function _fnAjaxUpdateDraw(settings, json) {
  4443. // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
  4444. // Support both
  4445. var compat = function compat(old, modern) {
  4446. return json[old] !== undefined ? json[old] : json[modern];
  4447. };
  4448. var data = _fnAjaxDataSrc(settings, json);
  4449. var draw = compat('sEcho', 'draw');
  4450. var recordsTotal = compat('iTotalRecords', 'recordsTotal');
  4451. var recordsFiltered = compat('iTotalDisplayRecords', 'recordsFiltered');
  4452. if (draw) {
  4453. // Protect against out of sequence returns
  4454. if (draw * 1 < settings.iDraw) {
  4455. return;
  4456. }
  4457. settings.iDraw = draw * 1;
  4458. }
  4459. _fnClearTable(settings);
  4460. settings._iRecordsTotal = parseInt(recordsTotal, 10);
  4461. settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
  4462. for (var i = 0, ien = data.length; i < ien; i++) {
  4463. _fnAddData(settings, data[i]);
  4464. }
  4465. settings.aiDisplay = settings.aiDisplayMaster.slice();
  4466. settings.bAjaxDataGet = false;
  4467. _fnDraw(settings);
  4468. if (!settings._bInitComplete) {
  4469. _fnInitComplete(settings, json);
  4470. }
  4471. settings.bAjaxDataGet = true;
  4472. _fnProcessingDisplay(settings, false);
  4473. }
  4474. /**
  4475. * Get the data from the JSON data source to use for drawing a table. Using
  4476. * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
  4477. * source object, or from a processing function.
  4478. * @param {object} oSettings dataTables settings object
  4479. * @param {object} json Data source object / array from the server
  4480. * @return {array} Array of data to use
  4481. */
  4482. function _fnAjaxDataSrc(oSettings, json) {
  4483. var dataSrc = $.isPlainObject(oSettings.ajax) && oSettings.ajax.dataSrc !== undefined ? oSettings.ajax.dataSrc : oSettings.sAjaxDataProp; // Compatibility with 1.9-.
  4484. // Compatibility with 1.9-. In order to read from aaData, check if the
  4485. // default has been changed, if not, check for aaData
  4486. if (dataSrc === 'data') {
  4487. return json.aaData || json[dataSrc];
  4488. }
  4489. return dataSrc !== "" ? _fnGetObjectDataFn(dataSrc)(json) : json;
  4490. }
  4491. /**
  4492. * Generate the node required for filtering text
  4493. * @returns {node} Filter control element
  4494. * @param {object} oSettings dataTables settings object
  4495. * @memberof DataTable#oApi
  4496. */
  4497. function _fnFeatureHtmlFilter(settings) {
  4498. var classes = settings.oClasses;
  4499. var tableId = settings.sTableId;
  4500. var language = settings.oLanguage;
  4501. var previousSearch = settings.oPreviousSearch;
  4502. var features = settings.aanFeatures;
  4503. var input = '<input type="search" class="' + classes.sFilterInput + '"/>';
  4504. var str = language.sSearch;
  4505. str = str.match(/_INPUT_/) ? str.replace('_INPUT_', input) : str + input;
  4506. var filter = $('<div/>', {
  4507. 'id': !features.f ? tableId + '_filter' : null,
  4508. 'class': classes.sFilter
  4509. }).append($('<label/>').append(str));
  4510. var searchFn = function searchFn() {
  4511. /* Update all other filter input elements for the new display */
  4512. var n = features.f;
  4513. var val = !this.value ? "" : this.value; // mental IE8 fix :-(
  4514. /* Now do the filter */
  4515. if (val != previousSearch.sSearch) {
  4516. _fnFilterComplete(settings, {
  4517. "sSearch": val,
  4518. "bRegex": previousSearch.bRegex,
  4519. "bSmart": previousSearch.bSmart,
  4520. "bCaseInsensitive": previousSearch.bCaseInsensitive
  4521. });
  4522. // Need to redraw, without resorting
  4523. settings._iDisplayStart = 0;
  4524. _fnDraw(settings);
  4525. }
  4526. };
  4527. var searchDelay = settings.searchDelay !== null ? settings.searchDelay : _fnDataSource(settings) === 'ssp' ? 400 : 0;
  4528. var jqFilter = $('input', filter).val(previousSearch.sSearch).attr('placeholder', language.sSearchPlaceholder).on('keyup.DT search.DT input.DT paste.DT cut.DT', searchDelay ? _fnThrottle(searchFn, searchDelay) : searchFn).on('keypress.DT', function (e) {
  4529. /* Prevent form submission */
  4530. if (e.keyCode == 13) {
  4531. return false;
  4532. }
  4533. }).attr('aria-controls', tableId);
  4534. // Update the input elements whenever the table is filtered
  4535. $(settings.nTable).on('search.dt.DT', function (ev, s) {
  4536. if (settings === s) {
  4537. // IE9 throws an 'unknown error' if document.activeElement is used
  4538. // inside an iframe or frame...
  4539. try {
  4540. if (jqFilter[0] !== document.activeElement) {
  4541. jqFilter.val(previousSearch.sSearch);
  4542. }
  4543. } catch (e) {
  4544. }
  4545. }
  4546. });
  4547. return filter[0];
  4548. }
  4549. /**
  4550. * Filter the table using both the global filter and column based filtering
  4551. * @param {object} oSettings dataTables settings object
  4552. * @param {object} oSearch search information
  4553. * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
  4554. * @memberof DataTable#oApi
  4555. */
  4556. function _fnFilterComplete(oSettings, oInput, iForce) {
  4557. var oPrevSearch = oSettings.oPreviousSearch;
  4558. var aoPrevSearch = oSettings.aoPreSearchCols;
  4559. var fnSaveFilter = function fnSaveFilter(oFilter) {
  4560. /* Save the filtering values */
  4561. oPrevSearch.sSearch = oFilter.sSearch;
  4562. oPrevSearch.bRegex = oFilter.bRegex;
  4563. oPrevSearch.bSmart = oFilter.bSmart;
  4564. oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
  4565. };
  4566. var fnRegex = function fnRegex(o) {
  4567. // Backwards compatibility with the bEscapeRegex option
  4568. return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
  4569. };
  4570. // Resolve any column types that are unknown due to addition or invalidation
  4571. // @todo As per sort - can this be moved into an event handler?
  4572. _fnColumnTypes(oSettings);
  4573. /* In server-side processing all filtering is done by the server, so no point hanging around here */
  4574. if (_fnDataSource(oSettings) != 'ssp') {
  4575. /* Global filter */
  4576. _fnFilter(oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive);
  4577. fnSaveFilter(oInput);
  4578. /* Now do the individual column filter */
  4579. for (var i = 0; i < aoPrevSearch.length; i++) {
  4580. _fnFilterColumn(oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]), aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive);
  4581. }
  4582. /* Custom filtering */
  4583. _fnFilterCustom(oSettings);
  4584. } else {
  4585. fnSaveFilter(oInput);
  4586. }
  4587. /* Tell the draw function we have been filtering */
  4588. oSettings.bFiltered = true;
  4589. _fnCallbackFire(oSettings, null, 'search', [oSettings]);
  4590. }
  4591. /**
  4592. * Apply custom filtering functions
  4593. * @param {object} oSettings dataTables settings object
  4594. * @memberof DataTable#oApi
  4595. */
  4596. function _fnFilterCustom(settings) {
  4597. var filters = DataTable.ext.search;
  4598. var displayRows = settings.aiDisplay;
  4599. var row, rowIdx;
  4600. for (var i = 0, ien = filters.length; i < ien; i++) {
  4601. var rows = [];
  4602. // Loop over each row and see if it should be included
  4603. for (var j = 0, jen = displayRows.length; j < jen; j++) {
  4604. rowIdx = displayRows[j];
  4605. row = settings.aoData[rowIdx];
  4606. if (filters[i](settings, row._aFilterData, rowIdx, row._aData, j)) {
  4607. rows.push(rowIdx);
  4608. }
  4609. }
  4610. // So the array reference doesn't break set the results into the
  4611. // existing array
  4612. displayRows.length = 0;
  4613. $.merge(displayRows, rows);
  4614. }
  4615. }
  4616. /**
  4617. * Filter the table on a per-column basis
  4618. * @param {object} oSettings dataTables settings object
  4619. * @param {string} sInput string to filter on
  4620. * @param {int} iColumn column to filter
  4621. * @param {bool} bRegex treat search string as a regular expression or not
  4622. * @param {bool} bSmart use smart filtering or not
  4623. * @param {bool} bCaseInsensitive Do case insenstive matching or not
  4624. * @memberof DataTable#oApi
  4625. */
  4626. function _fnFilterColumn(settings, searchStr, colIdx, regex, smart, caseInsensitive) {
  4627. if (searchStr === '') {
  4628. return;
  4629. }
  4630. var data;
  4631. var out = [];
  4632. var display = settings.aiDisplay;
  4633. var rpSearch = _fnFilterCreateSearch(searchStr, regex, smart, caseInsensitive);
  4634. for (var i = 0; i < display.length; i++) {
  4635. data = settings.aoData[display[i]]._aFilterData[colIdx];
  4636. if (rpSearch.test(data)) {
  4637. out.push(display[i]);
  4638. }
  4639. }
  4640. settings.aiDisplay = out;
  4641. }
  4642. /**
  4643. * Filter the data table based on user input and draw the table
  4644. * @param {object} settings dataTables settings object
  4645. * @param {string} input string to filter on
  4646. * @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
  4647. * @param {bool} regex treat as a regular expression or not
  4648. * @param {bool} smart perform smart filtering or not
  4649. * @param {bool} caseInsensitive Do case insenstive matching or not
  4650. * @memberof DataTable#oApi
  4651. */
  4652. function _fnFilter(settings, input, force, regex, smart, caseInsensitive) {
  4653. var rpSearch = _fnFilterCreateSearch(input, regex, smart, caseInsensitive);
  4654. var prevSearch = settings.oPreviousSearch.sSearch;
  4655. var displayMaster = settings.aiDisplayMaster;
  4656. var display, invalidated, i;
  4657. var filtered = [];
  4658. // Need to take account of custom filtering functions - always filter
  4659. if (DataTable.ext.search.length !== 0) {
  4660. force = true;
  4661. }
  4662. // Check if any of the rows were invalidated
  4663. invalidated = _fnFilterData(settings);
  4664. // If the input is blank - we just want the full data set
  4665. if (input.length <= 0) {
  4666. settings.aiDisplay = displayMaster.slice();
  4667. } else {
  4668. // New search - start from the master array
  4669. if (invalidated || force || prevSearch.length > input.length || input.indexOf(prevSearch) !== 0 || settings.bSorted // On resort, the display master needs to be
  4670. // re-filtered since indexes will have changed
  4671. ) {
  4672. settings.aiDisplay = displayMaster.slice();
  4673. }
  4674. // Search the display array
  4675. display = settings.aiDisplay;
  4676. for (i = 0; i < display.length; i++) {
  4677. if (rpSearch.test(settings.aoData[display[i]]._sFilterRow)) {
  4678. filtered.push(display[i]);
  4679. }
  4680. }
  4681. settings.aiDisplay = filtered;
  4682. }
  4683. }
  4684. /**
  4685. * Build a regular expression object suitable for searching a table
  4686. * @param {string} sSearch string to search for
  4687. * @param {bool} bRegex treat as a regular expression or not
  4688. * @param {bool} bSmart perform smart filtering or not
  4689. * @param {bool} bCaseInsensitive Do case insensitive matching or not
  4690. * @returns {RegExp} constructed object
  4691. * @memberof DataTable#oApi
  4692. */
  4693. function _fnFilterCreateSearch(search, regex, smart, caseInsensitive) {
  4694. search = regex ? search : _fnEscapeRegex(search);
  4695. if (smart) {
  4696. /* For smart filtering we want to allow the search to work regardless of
  4697. * word order. We also want double quoted text to be preserved, so word
  4698. * order is important - a la google. So this is what we want to
  4699. * generate:
  4700. *
  4701. * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
  4702. */
  4703. var a = $.map(search.match(/"[^"]+"|[^ ]+/g) || [''], function (word) {
  4704. if (word.charAt(0) === '"') {
  4705. var m = word.match(/^"(.*)"$/);
  4706. word = m ? m[1] : word;
  4707. }
  4708. return word.replace('"', '');
  4709. });
  4710. search = '^(?=.*?' + a.join(')(?=.*?') + ').*$';
  4711. }
  4712. return new RegExp(search, caseInsensitive ? 'i' : '');
  4713. }
  4714. /**
  4715. * Escape a string such that it can be used in a regular expression
  4716. * @param {string} sVal string to escape
  4717. * @returns {string} escaped string
  4718. * @memberof DataTable#oApi
  4719. */
  4720. var _fnEscapeRegex = DataTable.util.escapeRegex;
  4721. var __filter_div = $('<div>')[0];
  4722. var __filter_div_textContent = __filter_div.textContent !== undefined;
  4723. // Update the filtering data for each row if needed (by invalidation or first run)
  4724. function _fnFilterData(settings) {
  4725. var columns = settings.aoColumns;
  4726. var column;
  4727. var i, j, ien, jen, filterData, cellData, row;
  4728. var fomatters = DataTable.ext.type.search;
  4729. var wasInvalidated = false;
  4730. for (i = 0, ien = settings.aoData.length; i < ien; i++) {
  4731. row = settings.aoData[i];
  4732. if (!row._aFilterData) {
  4733. filterData = [];
  4734. for (j = 0, jen = columns.length; j < jen; j++) {
  4735. column = columns[j];
  4736. if (column.bSearchable) {
  4737. cellData = _fnGetCellData(settings, i, j, 'filter');
  4738. if (fomatters[column.sType]) {
  4739. cellData = fomatters[column.sType](cellData);
  4740. }
  4741. // Search in DataTables 1.10 is string based. In 1.11 this
  4742. // should be altered to also allow strict type checking.
  4743. if (cellData === null) {
  4744. cellData = '';
  4745. }
  4746. if (typeof cellData !== 'string' && cellData.toString) {
  4747. cellData = cellData.toString();
  4748. }
  4749. } else {
  4750. cellData = '';
  4751. }
  4752. // If it looks like there is an HTML entity in the string,
  4753. // attempt to decode it so sorting works as expected. Note that
  4754. // we could use a single line of jQuery to do this, but the DOM
  4755. // method used here is much faster http://jsperf.com/html-decode
  4756. if (cellData.indexOf && cellData.indexOf('&') !== - 1) {
  4757. __filter_div.innerHTML = cellData;
  4758. cellData = __filter_div_textContent ? __filter_div.textContent : __filter_div.innerText;
  4759. }
  4760. if (cellData.replace) {
  4761. cellData = cellData.replace(/[\r\n]/g, '');
  4762. }
  4763. filterData.push(cellData);
  4764. }
  4765. row._aFilterData = filterData;
  4766. row._sFilterRow = filterData.join(' ');
  4767. wasInvalidated = true;
  4768. }
  4769. }
  4770. return wasInvalidated;
  4771. }
  4772. /**
  4773. * Convert from the internal Hungarian notation to camelCase for external
  4774. * interaction
  4775. * @param {object} obj Object to convert
  4776. * @returns {object} Inverted object
  4777. * @memberof DataTable#oApi
  4778. */
  4779. function _fnSearchToCamel(obj) {
  4780. return {
  4781. search: obj.sSearch,
  4782. smart: obj.bSmart,
  4783. regex: obj.bRegex,
  4784. caseInsensitive: obj.bCaseInsensitive
  4785. };
  4786. }
  4787. /**
  4788. * Convert from camelCase notation to the internal Hungarian. We could use the
  4789. * Hungarian convert function here, but this is cleaner
  4790. * @param {object} obj Object to convert
  4791. * @returns {object} Inverted object
  4792. * @memberof DataTable#oApi
  4793. */
  4794. function _fnSearchToHung(obj) {
  4795. return {
  4796. sSearch: obj.search,
  4797. bSmart: obj.smart,
  4798. bRegex: obj.regex,
  4799. bCaseInsensitive: obj.caseInsensitive
  4800. };
  4801. }
  4802. /**
  4803. * Generate the node required for the info display
  4804. * @param {object} oSettings dataTables settings object
  4805. * @returns {node} Information element
  4806. * @memberof DataTable#oApi
  4807. */
  4808. function _fnFeatureHtmlInfo(settings) {
  4809. var tid = settings.sTableId,
  4810. nodes = settings.aanFeatures.i,
  4811. n = $('<div/>', {
  4812. 'class': settings.oClasses.sInfo,
  4813. 'id': !nodes ? tid + '_info' : null
  4814. });
  4815. if (!nodes) {
  4816. // Update display on each draw
  4817. settings.aoDrawCallback.push({
  4818. "fn": _fnUpdateInfo,
  4819. "sName": "information"
  4820. });
  4821. n.attr('role', 'status').attr('aria-live', 'polite');
  4822. // Table is described by our info div
  4823. $(settings.nTable).attr('aria-describedby', tid + '_info');
  4824. }
  4825. return n[0];
  4826. }
  4827. /**
  4828. * Update the information elements in the display
  4829. * @param {object} settings dataTables settings object
  4830. * @memberof DataTable#oApi
  4831. */
  4832. function _fnUpdateInfo(settings) {
  4833. /* Show information about the table */
  4834. var nodes = settings.aanFeatures.i;
  4835. if (nodes.length === 0) {
  4836. return;
  4837. }
  4838. var lang = settings.oLanguage,
  4839. start = settings._iDisplayStart + 1,
  4840. end = settings.fnDisplayEnd(),
  4841. max = settings.fnRecordsTotal(),
  4842. total = settings.fnRecordsDisplay(),
  4843. out = total ? lang.sInfo : lang.sInfoEmpty;
  4844. if (total !== max) {
  4845. /* Record set after filtering */
  4846. out += ' ' + lang.sInfoFiltered;
  4847. }
  4848. // Convert the macros
  4849. out += lang.sInfoPostFix;
  4850. out = _fnInfoMacros(settings, out);
  4851. var callback = lang.fnInfoCallback;
  4852. if (callback !== null) {
  4853. out = callback.call(settings.oInstance, settings, start, end, max, total, out);
  4854. }
  4855. $(nodes).html(out);
  4856. }
  4857. function _fnInfoMacros(settings, str) {
  4858. // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
  4859. // internally
  4860. var formatter = settings.fnFormatNumber,
  4861. start = settings._iDisplayStart + 1,
  4862. len = settings._iDisplayLength,
  4863. vis = settings.fnRecordsDisplay(),
  4864. all = len === - 1;
  4865. return str.replace(/_START_/g, formatter.call(settings, start)).replace(/_END_/g, formatter.call(settings, settings.fnDisplayEnd())).replace(/_MAX_/g, formatter.call(settings, settings.fnRecordsTotal())).replace(/_TOTAL_/g, formatter.call(settings, vis)).replace(/_PAGE_/g, formatter.call(settings, all ? 1 : Math.ceil(start / len))).replace(/_PAGES_/g, formatter.call(settings, all ? 1 : Math.ceil(vis / len)));
  4866. }
  4867. /**
  4868. * Draw the table for the first time, adding all required features
  4869. * @param {object} settings dataTables settings object
  4870. * @memberof DataTable#oApi
  4871. */
  4872. function _fnInitialise(settings) {
  4873. var i,
  4874. iLen,
  4875. iAjaxStart = settings.iInitDisplayStart;
  4876. var columns = settings.aoColumns,
  4877. column;
  4878. var features = settings.oFeatures;
  4879. var deferLoading = settings.bDeferLoading; // value modified by the draw
  4880. /* Ensure that the table data is fully initialised */
  4881. if (!settings.bInitialised) {
  4882. setTimeout(function () {
  4883. _fnInitialise(settings);
  4884. }, 200);
  4885. return;
  4886. }
  4887. /* Show the display HTML options */
  4888. _fnAddOptionsHtml(settings);
  4889. /* Build and draw the header / footer for the table */
  4890. _fnBuildHead(settings);
  4891. _fnDrawHead(settings, settings.aoHeader);
  4892. _fnDrawHead(settings, settings.aoFooter);
  4893. /* Okay to show that something is going on now */
  4894. _fnProcessingDisplay(settings, true);
  4895. /* Calculate sizes for columns */
  4896. if (features.bAutoWidth) {
  4897. _fnCalculateColumnWidths(settings);
  4898. }
  4899. for (i = 0, iLen = columns.length; i < iLen; i++) {
  4900. column = columns[i];
  4901. if (column.sWidth) {
  4902. column.nTh.style.width = _fnStringToCss(column.sWidth);
  4903. }
  4904. }
  4905. _fnCallbackFire(settings, null, 'preInit', [settings]);
  4906. // If there is default sorting required - let's do it. The sort function
  4907. // will do the drawing for us. Otherwise we draw the table regardless of the
  4908. // Ajax source - this allows the table to look initialised for Ajax sourcing
  4909. // data (show 'loading' message possibly)
  4910. _fnReDraw(settings);
  4911. // Server-side processing init complete is done by _fnAjaxUpdateDraw
  4912. var dataSrc = _fnDataSource(settings);
  4913. if (dataSrc != 'ssp' || deferLoading) {
  4914. // if there is an ajax source load the data
  4915. if (dataSrc == 'ajax') {
  4916. _fnBuildAjax(settings, [], function (json) {
  4917. var aData = _fnAjaxDataSrc(settings, json);
  4918. // Got the data - add it to the table
  4919. for (i = 0; i < aData.length; i++) {
  4920. _fnAddData(settings, aData[i]);
  4921. }
  4922. // Reset the init display for cookie saving. We've already done
  4923. // a filter, and therefore cleared it before. So we need to make
  4924. // it appear 'fresh'
  4925. settings.iInitDisplayStart = iAjaxStart;
  4926. _fnReDraw(settings);
  4927. _fnProcessingDisplay(settings, false);
  4928. _fnInitComplete(settings, json);
  4929. }, settings);
  4930. } else {
  4931. _fnProcessingDisplay(settings, false);
  4932. _fnInitComplete(settings);
  4933. }
  4934. }
  4935. }
  4936. /**
  4937. * Draw the table for the first time, adding all required features
  4938. * @param {object} oSettings dataTables settings object
  4939. * @param {object} [json] JSON from the server that completed the table, if using Ajax source
  4940. * with client-side processing (optional)
  4941. * @memberof DataTable#oApi
  4942. */
  4943. function _fnInitComplete(settings, json) {
  4944. settings._bInitComplete = true;
  4945. // When data was added after the initialisation (data or Ajax) we need to
  4946. // calculate the column sizing
  4947. if (json || settings.oInit.aaData) {
  4948. _fnAdjustColumnSizing(settings);
  4949. }
  4950. _fnCallbackFire(settings, null, 'plugin-init', [settings, json]);
  4951. _fnCallbackFire(settings, 'aoInitComplete', 'init', [settings, json]);
  4952. }
  4953. function _fnLengthChange(settings, val) {
  4954. var len = parseInt(val, 10);
  4955. settings._iDisplayLength = len;
  4956. _fnLengthOverflow(settings);
  4957. // Fire length change event
  4958. _fnCallbackFire(settings, null, 'length', [settings, len]);
  4959. }
  4960. /**
  4961. * Generate the node required for user display length changing
  4962. * @param {object} settings dataTables settings object
  4963. * @returns {node} Display length feature node
  4964. * @memberof DataTable#oApi
  4965. */
  4966. function _fnFeatureHtmlLength(settings) {
  4967. var classes = settings.oClasses,
  4968. tableId = settings.sTableId,
  4969. menu = settings.aLengthMenu,
  4970. d2 = $.isArray(menu[0]),
  4971. lengths = d2 ? menu[0] : menu,
  4972. language = d2 ? menu[1] : menu;
  4973. var select = $('<select/>', {
  4974. 'name': tableId + '_length',
  4975. 'aria-controls': tableId,
  4976. 'class': classes.sLengthSelect
  4977. });
  4978. for (var i = 0, ien = lengths.length; i < ien; i++) {
  4979. select[0][i] = new Option(typeof language[i] === 'number' ? settings.fnFormatNumber(language[i]) : language[i], lengths[i]);
  4980. }
  4981. var div = $('<div><label/></div>').addClass(classes.sLength);
  4982. if (!settings.aanFeatures.l) {
  4983. div[0].id = tableId + '_length';
  4984. }
  4985. div.children().append(settings.oLanguage.sLengthMenu.replace('_MENU_', select[0].outerHTML));
  4986. // Can't use `select` variable as user might provide their own and the
  4987. // reference is broken by the use of outerHTML
  4988. $('select', div).val(settings._iDisplayLength).on('change.DT', function (e) {
  4989. _fnLengthChange(settings, $(this).val());
  4990. _fnDraw(settings);
  4991. });
  4992. // Update node value whenever anything changes the table's length
  4993. $(settings.nTable).on('length.dt.DT', function (e, s, len) {
  4994. if (settings === s) {
  4995. $('select', div).val(len);
  4996. }
  4997. });
  4998. return div[0];
  4999. }
  5000. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  5001. * Note that most of the paging logic is done in
  5002. * DataTable.ext.pager
  5003. */
  5004. /**
  5005. * Generate the node required for default pagination
  5006. * @param {object} oSettings dataTables settings object
  5007. * @returns {node} Pagination feature node
  5008. * @memberof DataTable#oApi
  5009. */
  5010. function _fnFeatureHtmlPaginate(settings) {
  5011. var type = settings.sPaginationType,
  5012. plugin = DataTable.ext.pager[type],
  5013. modern = typeof plugin === 'function',
  5014. redraw = function redraw(settings) {
  5015. _fnDraw(settings);
  5016. },
  5017. node = $('<div/>').addClass(settings.oClasses.sPaging + type)[0],
  5018. features = settings.aanFeatures;
  5019. if (!modern) {
  5020. plugin.fnInit(settings, node, redraw);
  5021. }
  5022. /* Add a draw callback for the pagination on first instance, to update the paging display */
  5023. if (!features.p) {
  5024. node.id = settings.sTableId + '_paginate';
  5025. settings.aoDrawCallback.push({
  5026. "fn": function fn(settings) {
  5027. if (modern) {
  5028. var start = settings._iDisplayStart,
  5029. len = settings._iDisplayLength,
  5030. visRecords = settings.fnRecordsDisplay(),
  5031. all = len === - 1,
  5032. page = all ? 0 : Math.ceil(start / len),
  5033. pages = all ? 1 : Math.ceil(visRecords / len),
  5034. buttons = plugin(page, pages),
  5035. i,
  5036. ien;
  5037. for (i = 0, ien = features.p.length; i < ien; i++) {
  5038. _fnRenderer(settings, 'pageButton')(settings, features.p[i], i, buttons, page, pages);
  5039. }
  5040. } else {
  5041. plugin.fnUpdate(settings, redraw);
  5042. }
  5043. },
  5044. "sName": "pagination"
  5045. });
  5046. }
  5047. return node;
  5048. }
  5049. /**
  5050. * Alter the display settings to change the page
  5051. * @param {object} settings DataTables settings object
  5052. * @param {string|int} action Paging action to take: "first", "previous",
  5053. * "next" or "last" or page number to jump to (integer)
  5054. * @param [bool] redraw Automatically draw the update or not
  5055. * @returns {bool} true page has changed, false - no change
  5056. * @memberof DataTable#oApi
  5057. */
  5058. function _fnPageChange(settings, action, redraw) {
  5059. var start = settings._iDisplayStart,
  5060. len = settings._iDisplayLength,
  5061. records = settings.fnRecordsDisplay();
  5062. if (records === 0 || len === - 1) {
  5063. start = 0;
  5064. } else if (typeof action === "number") {
  5065. start = action * len;
  5066. if (start > records) {
  5067. start = 0;
  5068. }
  5069. } else if (action == "first") {
  5070. start = 0;
  5071. } else if (action == "previous") {
  5072. start = len >= 0 ? start - len : 0;
  5073. if (start < 0) {
  5074. start = 0;
  5075. }
  5076. } else if (action == "next") {
  5077. if (start + len < records) {
  5078. start += len;
  5079. }
  5080. } else if (action == "last") {
  5081. start = Math.floor((records - 1) / len) * len;
  5082. } else {
  5083. _fnLog(settings, 0, "Unknown paging action: " + action, 5);
  5084. }
  5085. var changed = settings._iDisplayStart !== start;
  5086. settings._iDisplayStart = start;
  5087. if (changed) {
  5088. _fnCallbackFire(settings, null, 'page', [settings]);
  5089. if (redraw) {
  5090. _fnDraw(settings);
  5091. }
  5092. }
  5093. return changed;
  5094. }
  5095. /**
  5096. * Generate the node required for the processing node
  5097. * @param {object} settings dataTables settings object
  5098. * @returns {node} Processing element
  5099. * @memberof DataTable#oApi
  5100. */
  5101. function _fnFeatureHtmlProcessing(settings) {
  5102. return $('<div/>', {
  5103. 'id': !settings.aanFeatures.r ? settings.sTableId + '_processing' : null,
  5104. 'class': settings.oClasses.sProcessing
  5105. }).html(settings.oLanguage.sProcessing).insertBefore(settings.nTable)[0];
  5106. }
  5107. /**
  5108. * Display or hide the processing indicator
  5109. * @param {object} settings dataTables settings object
  5110. * @param {bool} show Show the processing indicator (true) or not (false)
  5111. * @memberof DataTable#oApi
  5112. */
  5113. function _fnProcessingDisplay(settings, show) {
  5114. if (settings.oFeatures.bProcessing) {
  5115. $(settings.aanFeatures.r).css('display', show ? 'block' : 'none');
  5116. }
  5117. _fnCallbackFire(settings, null, 'processing', [settings, show]);
  5118. }
  5119. /**
  5120. * Add any control elements for the table - specifically scrolling
  5121. * @param {object} settings dataTables settings object
  5122. * @returns {node} Node to add to the DOM
  5123. * @memberof DataTable#oApi
  5124. */
  5125. function _fnFeatureHtmlTable(settings) {
  5126. var table = $(settings.nTable);
  5127. // Add the ARIA grid role to the table
  5128. table.attr('role', 'grid');
  5129. // Scrolling from here on in
  5130. var scroll = settings.oScroll;
  5131. if (scroll.sX === '' && scroll.sY === '') {
  5132. return settings.nTable;
  5133. }
  5134. var scrollX = scroll.sX;
  5135. var scrollY = scroll.sY;
  5136. var classes = settings.oClasses;
  5137. var caption = table.children('caption');
  5138. var captionSide = caption.length ? caption[0]._captionSide : null;
  5139. var headerClone = $(table[0].cloneNode(false));
  5140. var footerClone = $(table[0].cloneNode(false));
  5141. var footer = table.children('tfoot');
  5142. var _div = '<div/>';
  5143. var size = function size(s) {
  5144. return !s ? null : _fnStringToCss(s);
  5145. };
  5146. if (!footer.length) {
  5147. footer = null;
  5148. }
  5149. /*
  5150. * The HTML structure that we want to generate in this function is:
  5151. * div - scroller
  5152. * div - scroll head
  5153. * div - scroll head inner
  5154. * table - scroll head table
  5155. * thead - thead
  5156. * div - scroll body
  5157. * table - table (master table)
  5158. * thead - thead clone for sizing
  5159. * tbody - tbody
  5160. * div - scroll foot
  5161. * div - scroll foot inner
  5162. * table - scroll foot table
  5163. * tfoot - tfoot
  5164. */
  5165. var scroller = $(_div, {'class': classes.sScrollWrapper}).append($(_div, {'class': classes.sScrollHead}).css({
  5166. overflow: 'hidden',
  5167. position: 'relative',
  5168. border: 0,
  5169. width: scrollX ? size(scrollX) : '100%'
  5170. }).append($(_div, {'class': classes.sScrollHeadInner}).css({
  5171. 'box-sizing': 'content-box',
  5172. width: scroll.sXInner || '100%'
  5173. }).append(headerClone.removeAttr('id').css('margin-left', 0).append(captionSide === 'top' ? caption : null).append(table.children('thead'))))).append($(_div, {'class': classes.sScrollBody}).css({
  5174. position: 'relative',
  5175. overflow: 'auto',
  5176. width: size(scrollX)
  5177. }).append(table));
  5178. if (footer) {
  5179. scroller.append($(_div, {'class': classes.sScrollFoot}).css({
  5180. overflow: 'hidden',
  5181. border: 0,
  5182. width: scrollX ? size(scrollX) : '100%'
  5183. }).append($(_div, {'class': classes.sScrollFootInner}).append(footerClone.removeAttr('id').css('margin-left', 0).append(captionSide === 'bottom' ? caption : null).append(table.children('tfoot')))));
  5184. }
  5185. var children = scroller.children();
  5186. var scrollHead = children[0];
  5187. var scrollBody = children[1];
  5188. var scrollFoot = footer ? children[2] : null;
  5189. // When the body is scrolled, then we also want to scroll the headers
  5190. if (scrollX) {
  5191. $(scrollBody).on('scroll.DT', function (e) {
  5192. var scrollLeft = this.scrollLeft;
  5193. scrollHead.scrollLeft = scrollLeft;
  5194. if (footer) {
  5195. scrollFoot.scrollLeft = scrollLeft;
  5196. }
  5197. });
  5198. }
  5199. $(scrollBody).css(scrollY && scroll.bCollapse ? 'max-height' : 'height', scrollY);
  5200. settings.nScrollHead = scrollHead;
  5201. settings.nScrollBody = scrollBody;
  5202. settings.nScrollFoot = scrollFoot;
  5203. // On redraw - align columns
  5204. settings.aoDrawCallback.push({
  5205. "fn": _fnScrollDraw,
  5206. "sName": "scrolling"
  5207. });
  5208. return scroller[0];
  5209. }
  5210. /**
  5211. * Update the header, footer and body tables for resizing - i.e. column
  5212. * alignment.
  5213. *
  5214. * Welcome to the most horrible function DataTables. The process that this
  5215. * function follows is basically:
  5216. * 1. Re-create the table inside the scrolling div
  5217. * 2. Take live measurements from the DOM
  5218. * 3. Apply the measurements to align the columns
  5219. * 4. Clean up
  5220. *
  5221. * @param {object} settings dataTables settings object
  5222. * @memberof DataTable#oApi
  5223. */
  5224. function _fnScrollDraw(settings) {
  5225. // Given that this is such a monster function, a lot of variables are use
  5226. // to try and keep the minimised size as small as possible
  5227. var scroll = settings.oScroll,
  5228. scrollX = scroll.sX,
  5229. scrollXInner = scroll.sXInner,
  5230. scrollY = scroll.sY,
  5231. barWidth = scroll.iBarWidth,
  5232. divHeader = $(settings.nScrollHead),
  5233. divHeaderStyle = divHeader[0].style,
  5234. divHeaderInner = divHeader.children('div'),
  5235. divHeaderInnerStyle = divHeaderInner[0].style,
  5236. divHeaderTable = divHeaderInner.children('table'),
  5237. divBodyEl = settings.nScrollBody,
  5238. divBody = $(divBodyEl),
  5239. divBodyStyle = divBodyEl.style,
  5240. divFooter = $(settings.nScrollFoot),
  5241. divFooterInner = divFooter.children('div'),
  5242. divFooterTable = divFooterInner.children('table'),
  5243. header = $(settings.nTHead),
  5244. table = $(settings.nTable),
  5245. tableEl = table[0],
  5246. tableStyle = tableEl.style,
  5247. footer = settings.nTFoot ? $(settings.nTFoot) : null,
  5248. browser = settings.oBrowser,
  5249. ie67 = browser.bScrollOversize,
  5250. dtHeaderCells = _pluck(settings.aoColumns, 'nTh'),
  5251. headerTrgEls,
  5252. footerTrgEls,
  5253. headerSrcEls,
  5254. footerSrcEls,
  5255. headerCopy,
  5256. footerCopy,
  5257. headerWidths = [],
  5258. footerWidths = [],
  5259. headerContent = [],
  5260. footerContent = [],
  5261. idx,
  5262. correction,
  5263. sanityWidth,
  5264. zeroOut = function zeroOut(nSizer) {
  5265. var style = nSizer.style;
  5266. style.paddingTop = "0";
  5267. style.paddingBottom = "0";
  5268. style.borderTopWidth = "0";
  5269. style.borderBottomWidth = "0";
  5270. style.height = 0;
  5271. };
  5272. // If the scrollbar visibility has changed from the last draw, we need to
  5273. // adjust the column sizes as the table width will have changed to account
  5274. // for the scrollbar
  5275. var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
  5276. if (settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined) {
  5277. settings.scrollBarVis = scrollBarVis;
  5278. _fnAdjustColumnSizing(settings);
  5279. return; // adjust column sizing will call this function again
  5280. } else {
  5281. settings.scrollBarVis = scrollBarVis;
  5282. }
  5283. /*
  5284. * 1. Re-create the table inside the scrolling div
  5285. */
  5286. // Remove the old minimised thead and tfoot elements in the inner table
  5287. table.children('thead, tfoot').remove();
  5288. if (footer) {
  5289. footerCopy = footer.clone().prependTo(table);
  5290. footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
  5291. footerSrcEls = footerCopy.find('tr');
  5292. }
  5293. // Clone the current header and footer elements and then place it into the inner table
  5294. headerCopy = header.clone().prependTo(table);
  5295. headerTrgEls = header.find('tr'); // original header is in its own table
  5296. headerSrcEls = headerCopy.find('tr');
  5297. headerCopy.find('th, td').removeAttr('tabindex');
  5298. /*
  5299. * 2. Take live measurements from the DOM - do not alter the DOM itself!
  5300. */
  5301. // Remove old sizing and apply the calculated column widths
  5302. // Get the unique column headers in the newly created (cloned) header. We want to apply the
  5303. // calculated sizes to this header
  5304. if (!scrollX) {
  5305. divBodyStyle.width = '100%';
  5306. divHeader[0].style.width = '100%';
  5307. }
  5308. $.each(_fnGetUniqueThs(settings, headerCopy), function (i, el) {
  5309. idx = _fnVisibleToColumnIndex(settings, i);
  5310. el.style.width = settings.aoColumns[idx].sWidth;
  5311. });
  5312. if (footer) {
  5313. _fnApplyToChildren(function (n) {
  5314. n.style.width = "";
  5315. }, footerSrcEls);
  5316. }
  5317. // Size the table as a whole
  5318. sanityWidth = table.outerWidth();
  5319. if (scrollX === "") {
  5320. // No x scrolling
  5321. tableStyle.width = "100%";
  5322. // IE7 will make the width of the table when 100% include the scrollbar
  5323. // - which is shouldn't. When there is a scrollbar we need to take this
  5324. // into account.
  5325. if (ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")) {
  5326. tableStyle.width = _fnStringToCss(table.outerWidth() - barWidth);
  5327. }
  5328. // Recalculate the sanity width
  5329. sanityWidth = table.outerWidth();
  5330. } else if (scrollXInner !== "") {
  5331. // legacy x scroll inner has been given - use it
  5332. tableStyle.width = _fnStringToCss(scrollXInner);
  5333. // Recalculate the sanity width
  5334. sanityWidth = table.outerWidth();
  5335. }
  5336. // Hidden header should have zero height, so remove padding and borders. Then
  5337. // set the width based on the real headers
  5338. // Apply all styles in one pass
  5339. _fnApplyToChildren(zeroOut, headerSrcEls);
  5340. // Read all widths in next pass
  5341. _fnApplyToChildren(function (nSizer) {
  5342. headerContent.push(nSizer.innerHTML);
  5343. headerWidths.push(_fnStringToCss($(nSizer).css('width')));
  5344. }, headerSrcEls);
  5345. // Apply all widths in final pass
  5346. _fnApplyToChildren(function (nToSize, i) {
  5347. // Only apply widths to the DataTables detected header cells - this
  5348. // prevents complex headers from having contradictory sizes applied
  5349. if ($.inArray(nToSize, dtHeaderCells) !== - 1) {
  5350. nToSize.style.width = headerWidths[i];
  5351. }
  5352. }, headerTrgEls);
  5353. $(headerSrcEls).height(0);
  5354. /* Same again with the footer if we have one */
  5355. if (footer) {
  5356. _fnApplyToChildren(zeroOut, footerSrcEls);
  5357. _fnApplyToChildren(function (nSizer) {
  5358. footerContent.push(nSizer.innerHTML);
  5359. footerWidths.push(_fnStringToCss($(nSizer).css('width')));
  5360. }, footerSrcEls);
  5361. _fnApplyToChildren(function (nToSize, i) {
  5362. nToSize.style.width = footerWidths[i];
  5363. }, footerTrgEls);
  5364. $(footerSrcEls).height(0);
  5365. }
  5366. /*
  5367. * 3. Apply the measurements
  5368. */
  5369. // "Hide" the header and footer that we used for the sizing. We need to keep
  5370. // the content of the cell so that the width applied to the header and body
  5371. // both match, but we want to hide it completely. We want to also fix their
  5372. // width to what they currently are
  5373. _fnApplyToChildren(function (nSizer, i) {
  5374. nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">' + headerContent[i] + '</div>';
  5375. nSizer.style.width = headerWidths[i];
  5376. }, headerSrcEls);
  5377. if (footer) {
  5378. _fnApplyToChildren(function (nSizer, i) {
  5379. nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">' + footerContent[i] + '</div>';
  5380. nSizer.style.width = footerWidths[i];
  5381. }, footerSrcEls);
  5382. }
  5383. // Sanity check that the table is of a sensible width. If not then we are going to get
  5384. // misalignment - try to prevent this by not allowing the table to shrink below its min width
  5385. if (table.outerWidth() < sanityWidth) {
  5386. // The min width depends upon if we have a vertical scrollbar visible or not */
  5387. correction = divBodyEl.scrollHeight > divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll" ? sanityWidth + barWidth : sanityWidth;
  5388. // IE6/7 are a law unto themselves...
  5389. if (ie67 && (divBodyEl.scrollHeight > divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")) {
  5390. tableStyle.width = _fnStringToCss(correction - barWidth);
  5391. }
  5392. // And give the user a warning that we've stopped the table getting too small
  5393. if (scrollX === "" || scrollXInner !== "") {
  5394. _fnLog(settings, 1, 'Possible column misalignment', 6);
  5395. }
  5396. } else {
  5397. correction = '100%';
  5398. }
  5399. // Apply to the container elements
  5400. divBodyStyle.width = _fnStringToCss(correction);
  5401. divHeaderStyle.width = _fnStringToCss(correction);
  5402. if (footer) {
  5403. settings.nScrollFoot.style.width = _fnStringToCss(correction);
  5404. }
  5405. /*
  5406. * 4. Clean up
  5407. */
  5408. if (!scrollY) {
  5409. /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
  5410. * the scrollbar height from the visible display, rather than adding it on. We need to
  5411. * set the height in order to sort this. Don't want to do it in any other browsers.
  5412. */
  5413. if (ie67) {
  5414. divBodyStyle.height = _fnStringToCss(tableEl.offsetHeight + barWidth);
  5415. }
  5416. }
  5417. /* Finally set the width's of the header and footer tables */
  5418. var iOuterWidth = table.outerWidth();
  5419. divHeaderTable[0].style.width = _fnStringToCss(iOuterWidth);
  5420. divHeaderInnerStyle.width = _fnStringToCss(iOuterWidth);
  5421. // Figure out if there are scrollbar present - if so then we need a the header and footer to
  5422. // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
  5423. var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
  5424. var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right');
  5425. divHeaderInnerStyle[padding] = bScrolling ? barWidth + "px" : "0px";
  5426. if (footer) {
  5427. divFooterTable[0].style.width = _fnStringToCss(iOuterWidth);
  5428. divFooterInner[0].style.width = _fnStringToCss(iOuterWidth);
  5429. divFooterInner[0].style[padding] = bScrolling ? barWidth + "px" : "0px";
  5430. }
  5431. // Correct DOM ordering for colgroup - comes before the thead
  5432. table.children('colgroup').insertBefore(table.children('thead'));
  5433. /* Adjust the position of the header in case we loose the y-scrollbar */
  5434. divBody.scroll();
  5435. // If sorting or filtering has occurred, jump the scrolling back to the top
  5436. // only if we aren't holding the position
  5437. if ((settings.bSorted || settings.bFiltered) && !settings._drawHold) {
  5438. divBodyEl.scrollTop = 0;
  5439. }
  5440. }
  5441. /**
  5442. * Apply a given function to the display child nodes of an element array (typically
  5443. * TD children of TR rows
  5444. * @param {function} fn Method to apply to the objects
  5445. * @param array {nodes} an1 List of elements to look through for display children
  5446. * @param array {nodes} an2 Another list (identical structure to the first) - optional
  5447. * @memberof DataTable#oApi
  5448. */
  5449. function _fnApplyToChildren(fn, an1, an2) {
  5450. var index = 0,
  5451. i = 0,
  5452. iLen = an1.length;
  5453. var nNode1, nNode2;
  5454. while (i < iLen) {
  5455. nNode1 = an1[i].firstChild;
  5456. nNode2 = an2 ? an2[i].firstChild : null;
  5457. while (nNode1) {
  5458. if (nNode1.nodeType === 1) {
  5459. if (an2) {
  5460. fn(nNode1, nNode2, index);
  5461. } else {
  5462. fn(nNode1, index);
  5463. }
  5464. index++;
  5465. }
  5466. nNode1 = nNode1.nextSibling;
  5467. nNode2 = an2 ? nNode2.nextSibling : null;
  5468. }
  5469. i++;
  5470. }
  5471. }
  5472. var __re_html_remove = /<.*?>/g;
  5473. /**
  5474. * Calculate the width of columns for the table
  5475. * @param {object} oSettings dataTables settings object
  5476. * @memberof DataTable#oApi
  5477. */
  5478. function _fnCalculateColumnWidths(oSettings) {
  5479. var table = oSettings.nTable,
  5480. columns = oSettings.aoColumns,
  5481. scroll = oSettings.oScroll,
  5482. scrollY = scroll.sY,
  5483. scrollX = scroll.sX,
  5484. scrollXInner = scroll.sXInner,
  5485. columnCount = columns.length,
  5486. visibleColumns = _fnGetColumns(oSettings, 'bVisible'),
  5487. headerCells = $('th', oSettings.nTHead),
  5488. tableWidthAttr = table.getAttribute('width'),
  5489. // from DOM element
  5490. tableContainer = table.parentNode,
  5491. userInputs = false,
  5492. i,
  5493. column,
  5494. columnIdx,
  5495. width,
  5496. outerWidth,
  5497. browser = oSettings.oBrowser,
  5498. ie67 = browser.bScrollOversize;
  5499. var styleWidth = table.style.width;
  5500. if (styleWidth && styleWidth.indexOf('%') !== - 1) {
  5501. tableWidthAttr = styleWidth;
  5502. }
  5503. /* Convert any user input sizes into pixel sizes */
  5504. for (i = 0; i < visibleColumns.length; i++) {
  5505. column = columns[visibleColumns[i]];
  5506. if (column.sWidth !== null) {
  5507. column.sWidth = _fnConvertToWidth(column.sWidthOrig, tableContainer);
  5508. userInputs = true;
  5509. }
  5510. }
  5511. /* If the number of columns in the DOM equals the number that we have to
  5512. * process in DataTables, then we can use the offsets that are created by
  5513. * the web- browser. No custom sizes can be set in order for this to happen,
  5514. * nor scrolling used
  5515. */
  5516. if (ie67 || !userInputs && !scrollX && !scrollY && columnCount == _fnVisbleColumns(oSettings) && columnCount == headerCells.length) {
  5517. for (i = 0; i < columnCount; i++) {
  5518. var colIdx = _fnVisibleToColumnIndex(oSettings, i);
  5519. if (colIdx !== null) {
  5520. columns[colIdx].sWidth = _fnStringToCss(headerCells.eq(i).width());
  5521. }
  5522. }
  5523. } else {
  5524. // Otherwise construct a single row, worst case, table with the widest
  5525. // node in the data, assign any user defined widths, then insert it into
  5526. // the DOM and allow the browser to do all the hard work of calculating
  5527. // table widths
  5528. var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
  5529. .css('visibility', 'hidden').removeAttr('id');
  5530. // Clean up the table body
  5531. tmpTable.find('tbody tr').remove();
  5532. var tr = $('<tr/>').appendTo(tmpTable.find('tbody'));
  5533. // Clone the table header and footer - we can't use the header / footer
  5534. // from the cloned table, since if scrolling is active, the table's
  5535. // real header and footer are contained in different table tags
  5536. tmpTable.find('thead, tfoot').remove();
  5537. tmpTable.append($(oSettings.nTHead).clone()).append($(oSettings.nTFoot).clone());
  5538. // Remove any assigned widths from the footer (from scrolling)
  5539. tmpTable.find('tfoot th, tfoot td').css('width', '');
  5540. // Apply custom sizing to the cloned header
  5541. headerCells = _fnGetUniqueThs(oSettings, tmpTable.find('thead')[0]);
  5542. for (i = 0; i < visibleColumns.length; i++) {
  5543. column = columns[visibleColumns[i]];
  5544. headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ? _fnStringToCss(column.sWidthOrig) : '';
  5545. // For scrollX we need to force the column width otherwise the
  5546. // browser will collapse it. If this width is smaller than the
  5547. // width the column requires, then it will have no effect
  5548. if (column.sWidthOrig && scrollX) {
  5549. $(headerCells[i]).append($('<div/>').css({
  5550. width: column.sWidthOrig,
  5551. margin: 0,
  5552. padding: 0,
  5553. border: 0,
  5554. height: 1
  5555. }));
  5556. }
  5557. }
  5558. // Find the widest cell for each column and put it into the table
  5559. if (oSettings.aoData.length) {
  5560. for (i = 0; i < visibleColumns.length; i++) {
  5561. columnIdx = visibleColumns[i];
  5562. column = columns[columnIdx];
  5563. $(_fnGetWidestNode(oSettings, columnIdx)).clone(false).append(column.sContentPadding).appendTo(tr);
  5564. }
  5565. }
  5566. // Tidy the temporary table - remove name attributes so there aren't
  5567. // duplicated in the dom (radio elements for example)
  5568. $('[name]', tmpTable).removeAttr('name');
  5569. // Table has been built, attach to the document so we can work with it.
  5570. // A holding element is used, positioned at the top of the container
  5571. // with minimal height, so it has no effect on if the container scrolls
  5572. // or not. Otherwise it might trigger scrolling when it actually isn't
  5573. // needed
  5574. var holder = $('<div/>').css(scrollX || scrollY ? {
  5575. position: 'absolute',
  5576. top: 0,
  5577. left: 0,
  5578. height: 1,
  5579. right: 0,
  5580. overflow: 'hidden'
  5581. } : {}).append(tmpTable).appendTo(tableContainer);
  5582. // When scrolling (X or Y) we want to set the width of the table as
  5583. // appropriate. However, when not scrolling leave the table width as it
  5584. // is. This results in slightly different, but I think correct behaviour
  5585. if (scrollX && scrollXInner) {
  5586. tmpTable.width(scrollXInner);
  5587. } else if (scrollX) {
  5588. tmpTable.css('width', 'auto');
  5589. tmpTable.removeAttr('width');
  5590. // If there is no width attribute or style, then allow the table to
  5591. // collapse
  5592. if (tmpTable.width() < tableContainer.clientWidth && tableWidthAttr) {
  5593. tmpTable.width(tableContainer.clientWidth);
  5594. }
  5595. } else if (scrollY) {
  5596. tmpTable.width(tableContainer.clientWidth);
  5597. } else if (tableWidthAttr) {
  5598. tmpTable.width(tableWidthAttr);
  5599. }
  5600. // Get the width of each column in the constructed table - we need to
  5601. // know the inner width (so it can be assigned to the other table's
  5602. // cells) and the outer width so we can calculate the full width of the
  5603. // table. This is safe since DataTables requires a unique cell for each
  5604. // column, but if ever a header can span multiple columns, this will
  5605. // need to be modified.
  5606. var total = 0;
  5607. for (i = 0; i < visibleColumns.length; i++) {
  5608. var cell = $(headerCells[i]);
  5609. var border = cell.outerWidth() - cell.width();
  5610. // Use getBounding... where possible (not IE8-) because it can give
  5611. // sub-pixel accuracy, which we then want to round up!
  5612. var bounding = browser.bBounding ? Math.ceil(headerCells[i].getBoundingClientRect().width) : cell.outerWidth();
  5613. // Total is tracked to remove any sub-pixel errors as the outerWidth
  5614. // of the table might not equal the total given here (IE!).
  5615. total += bounding;
  5616. // Width for each column to use
  5617. columns[visibleColumns[i]].sWidth = _fnStringToCss(bounding - border);
  5618. }
  5619. table.style.width = _fnStringToCss(total);
  5620. // Finished with the table - ditch it
  5621. holder.remove();
  5622. }
  5623. // If there is a width attr, we want to attach an event listener which
  5624. // allows the table sizing to automatically adjust when the window is
  5625. // resized. Use the width attr rather than CSS, since we can't know if the
  5626. // CSS is a relative value or absolute - DOM read is always px.
  5627. if (tableWidthAttr) {
  5628. table.style.width = _fnStringToCss(tableWidthAttr);
  5629. }
  5630. if ((tableWidthAttr || scrollX) && !oSettings._reszEvt) {
  5631. var bindResize = function bindResize() {
  5632. $(window).on('resize.DT-' + oSettings.sInstance, _fnThrottle(function () {
  5633. _fnAdjustColumnSizing(oSettings);
  5634. }));
  5635. };
  5636. // IE6/7 will crash if we bind a resize event handler on page load.
  5637. // To be removed in 1.11 which drops IE6/7 support
  5638. if (ie67) {
  5639. setTimeout(bindResize, 1000);
  5640. } else {
  5641. bindResize();
  5642. }
  5643. oSettings._reszEvt = true;
  5644. }
  5645. }
  5646. /**
  5647. * Throttle the calls to a function. Arguments and context are maintained for
  5648. * the throttled function
  5649. * @param {function} fn Function to be called
  5650. * @param {int} [freq=200] call frequency in mS
  5651. * @returns {function} wrapped function
  5652. * @memberof DataTable#oApi
  5653. */
  5654. var _fnThrottle = DataTable.util.throttle;
  5655. /**
  5656. * Convert a CSS unit width to pixels (e.g. 2em)
  5657. * @param {string} width width to be converted
  5658. * @param {node} parent parent to get the with for (required for relative widths) - optional
  5659. * @returns {int} width in pixels
  5660. * @memberof DataTable#oApi
  5661. */
  5662. function _fnConvertToWidth(width, parent) {
  5663. if (!width) {
  5664. return 0;
  5665. }
  5666. var n = $('<div/>').css('width', _fnStringToCss(width)).appendTo(parent || document.body);
  5667. var val = n[0].offsetWidth;
  5668. n.remove();
  5669. return val;
  5670. }
  5671. /**
  5672. * Get the widest node
  5673. * @param {object} settings dataTables settings object
  5674. * @param {int} colIdx column of interest
  5675. * @returns {node} widest table node
  5676. * @memberof DataTable#oApi
  5677. */
  5678. function _fnGetWidestNode(settings, colIdx) {
  5679. var idx = _fnGetMaxLenString(settings, colIdx);
  5680. if (idx < 0) {
  5681. return null;
  5682. }
  5683. var data = settings.aoData[idx];
  5684. return !data.nTr ? // Might not have been created when deferred rendering
  5685. $('<td/>').html(_fnGetCellData(settings, idx, colIdx, 'display'))[0] : data.anCells[colIdx];
  5686. }
  5687. /**
  5688. * Get the maximum strlen for each data column
  5689. * @param {object} settings dataTables settings object
  5690. * @param {int} colIdx column of interest
  5691. * @returns {string} max string length for each column
  5692. * @memberof DataTable#oApi
  5693. */
  5694. function _fnGetMaxLenString(settings, colIdx) {
  5695. var s,
  5696. max = - 1,
  5697. maxIdx = - 1;
  5698. for (var i = 0, ien = settings.aoData.length; i < ien; i++) {
  5699. s = _fnGetCellData(settings, i, colIdx, 'display') + '';
  5700. s = s.replace(__re_html_remove, '');
  5701. s = s.replace(/&nbsp;/g, ' ');
  5702. if (s.length > max) {
  5703. max = s.length;
  5704. maxIdx = i;
  5705. }
  5706. }
  5707. return maxIdx;
  5708. }
  5709. /**
  5710. * Append a CSS unit (only if required) to a string
  5711. * @param {string} value to css-ify
  5712. * @returns {string} value with css unit
  5713. * @memberof DataTable#oApi
  5714. */
  5715. function _fnStringToCss(s) {
  5716. if (s === null) {
  5717. return '0px';
  5718. }
  5719. if (typeof s == 'number') {
  5720. return s < 0 ? '0px' : s + 'px';
  5721. }
  5722. // Check it has a unit character already
  5723. return s.match(/\d$/) ? s + 'px' : s;
  5724. }
  5725. function _fnSortFlatten(settings) {
  5726. var i,
  5727. iLen,
  5728. k,
  5729. kLen,
  5730. aSort = [],
  5731. aiOrig = [],
  5732. aoColumns = settings.aoColumns,
  5733. aDataSort,
  5734. iCol,
  5735. sType,
  5736. srcCol,
  5737. fixed = settings.aaSortingFixed,
  5738. fixedObj = $.isPlainObject(fixed),
  5739. nestedSort = [],
  5740. add = function add(a) {
  5741. if (a.length && !$.isArray(a[0])) {
  5742. // 1D array
  5743. nestedSort.push(a);
  5744. } else {
  5745. // 2D array
  5746. $.merge(nestedSort, a);
  5747. }
  5748. };
  5749. // Build the sort array, with pre-fix and post-fix options if they have been
  5750. // specified
  5751. if ($.isArray(fixed)) {
  5752. add(fixed);
  5753. }
  5754. if (fixedObj && fixed.pre) {
  5755. add(fixed.pre);
  5756. }
  5757. add(settings.aaSorting);
  5758. if (fixedObj && fixed.post) {
  5759. add(fixed.post);
  5760. }
  5761. for (i = 0; i < nestedSort.length; i++) {
  5762. srcCol = nestedSort[i][0];
  5763. aDataSort = aoColumns[srcCol].aDataSort;
  5764. for (k = 0, kLen = aDataSort.length; k < kLen; k++) {
  5765. iCol = aDataSort[k];
  5766. sType = aoColumns[iCol].sType || 'string';
  5767. if (nestedSort[i]._idx === undefined) {
  5768. nestedSort[i]._idx = $.inArray(nestedSort[i][1], aoColumns[iCol].asSorting);
  5769. }
  5770. aSort.push({
  5771. src: srcCol,
  5772. col: iCol,
  5773. dir: nestedSort[i][1],
  5774. index: nestedSort[i]._idx,
  5775. type: sType,
  5776. formatter: DataTable.ext.type.order[sType + "-pre"]
  5777. });
  5778. }
  5779. }
  5780. return aSort;
  5781. }
  5782. /**
  5783. * Change the order of the table
  5784. * @param {object} oSettings dataTables settings object
  5785. * @memberof DataTable#oApi
  5786. * @todo This really needs split up!
  5787. */
  5788. function _fnSort(oSettings) {
  5789. var i,
  5790. ien,
  5791. iLen,
  5792. j,
  5793. jLen,
  5794. k,
  5795. kLen,
  5796. sDataType,
  5797. nTh,
  5798. aiOrig = [],
  5799. oExtSort = DataTable.ext.type.order,
  5800. aoData = oSettings.aoData,
  5801. aoColumns = oSettings.aoColumns,
  5802. aDataSort,
  5803. data,
  5804. iCol,
  5805. sType,
  5806. oSort,
  5807. formatters = 0,
  5808. sortCol,
  5809. displayMaster = oSettings.aiDisplayMaster,
  5810. aSort;
  5811. // Resolve any column types that are unknown due to addition or invalidation
  5812. // @todo Can this be moved into a 'data-ready' handler which is called when
  5813. // data is going to be used in the table?
  5814. _fnColumnTypes(oSettings);
  5815. aSort = _fnSortFlatten(oSettings);
  5816. for (i = 0, ien = aSort.length; i < ien; i++) {
  5817. sortCol = aSort[i];
  5818. // Track if we can use the fast sort algorithm
  5819. if (sortCol.formatter) {
  5820. formatters++;
  5821. }
  5822. // Load the data needed for the sort, for each cell
  5823. _fnSortData(oSettings, sortCol.col);
  5824. }
  5825. /* No sorting required if server-side or no sorting array */
  5826. if (_fnDataSource(oSettings) != 'ssp' && aSort.length !== 0) {
  5827. // Create a value - key array of the current row positions such that we can use their
  5828. // current position during the sort, if values match, in order to perform stable sorting
  5829. for (i = 0, iLen = displayMaster.length; i < iLen; i++) {
  5830. aiOrig[displayMaster[i]] = i;
  5831. }
  5832. /* Do the sort - here we want multi-column sorting based on a given data source (column)
  5833. * and sorting function (from oSort) in a certain direction. It's reasonably complex to
  5834. * follow on it's own, but this is what we want (example two column sorting):
  5835. * fnLocalSorting = function(a,b){
  5836. * var iTest;
  5837. * iTest = oSort['string-asc']('data11', 'data12');
  5838. * if (iTest !== 0)
  5839. * return iTest;
  5840. * iTest = oSort['numeric-desc']('data21', 'data22');
  5841. * if (iTest !== 0)
  5842. * return iTest;
  5843. * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
  5844. * }
  5845. * Basically we have a test for each sorting column, if the data in that column is equal,
  5846. * test the next column. If all columns match, then we use a numeric sort on the row
  5847. * positions in the original data array to provide a stable sort.
  5848. *
  5849. * Note - I know it seems excessive to have two sorting methods, but the first is around
  5850. * 15% faster, so the second is only maintained for backwards compatibility with sorting
  5851. * methods which do not have a pre-sort formatting function.
  5852. */
  5853. if (formatters === aSort.length) {
  5854. // All sort types have formatting functions
  5855. displayMaster.sort(function (a, b) {
  5856. var x,
  5857. y,
  5858. k,
  5859. test,
  5860. sort,
  5861. len = aSort.length,
  5862. dataA = aoData[a]._aSortData,
  5863. dataB = aoData[b]._aSortData;
  5864. for (k = 0; k < len; k++) {
  5865. sort = aSort[k];
  5866. x = dataA[sort.col];
  5867. y = dataB[sort.col];
  5868. test = x < y ? - 1 : x > y ? 1 : 0;
  5869. if (test !== 0) {
  5870. return sort.dir === 'asc' ? test : - test;
  5871. }
  5872. }
  5873. x = aiOrig[a];
  5874. y = aiOrig[b];
  5875. return x < y ? - 1 : x > y ? 1 : 0;
  5876. });
  5877. } else {
  5878. // Depreciated - remove in 1.11 (providing a plug-in option)
  5879. // Not all sort types have formatting methods, so we have to call their sorting
  5880. // methods.
  5881. displayMaster.sort(function (a, b) {
  5882. var x,
  5883. y,
  5884. k,
  5885. l,
  5886. test,
  5887. sort,
  5888. fn,
  5889. len = aSort.length,
  5890. dataA = aoData[a]._aSortData,
  5891. dataB = aoData[b]._aSortData;
  5892. for (k = 0; k < len; k++) {
  5893. sort = aSort[k];
  5894. x = dataA[sort.col];
  5895. y = dataB[sort.col];
  5896. fn = oExtSort[sort.type + "-" + sort.dir] || oExtSort["string-" + sort.dir];
  5897. test = fn(x, y);
  5898. if (test !== 0) {
  5899. return test;
  5900. }
  5901. }
  5902. x = aiOrig[a];
  5903. y = aiOrig[b];
  5904. return x < y ? - 1 : x > y ? 1 : 0;
  5905. });
  5906. }
  5907. }
  5908. /* Tell the draw function that we have sorted the data */
  5909. oSettings.bSorted = true;
  5910. }
  5911. function _fnSortAria(settings) {
  5912. var label;
  5913. var nextSort;
  5914. var columns = settings.aoColumns;
  5915. var aSort = _fnSortFlatten(settings);
  5916. var oAria = settings.oLanguage.oAria;
  5917. // ARIA attributes - need to loop all columns, to update all (removing old
  5918. // attributes as needed)
  5919. for (var i = 0, iLen = columns.length; i < iLen; i++) {
  5920. var col = columns[i];
  5921. var asSorting = col.asSorting;
  5922. var sTitle = col.sTitle.replace(/<.*?>/g, "");
  5923. var th = col.nTh;
  5924. // IE7 is throwing an error when setting these properties with jQuery's
  5925. // attr() and removeAttr() methods...
  5926. th.removeAttribute('aria-sort');
  5927. /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
  5928. if (col.bSortable) {
  5929. if (aSort.length > 0 && aSort[0].col == i) {
  5930. th.setAttribute('aria-sort', aSort[0].dir == "asc" ? "ascending" : "descending");
  5931. nextSort = asSorting[aSort[0].index + 1] || asSorting[0];
  5932. } else {
  5933. nextSort = asSorting[0];
  5934. }
  5935. label = sTitle + (nextSort === "asc" ? oAria.sSortAscending : oAria.sSortDescending);
  5936. } else {
  5937. label = sTitle;
  5938. }
  5939. th.setAttribute('aria-label', label);
  5940. }
  5941. }
  5942. /**
  5943. * Function to run on user sort request
  5944. * @param {object} settings dataTables settings object
  5945. * @param {node} attachTo node to attach the handler to
  5946. * @param {int} colIdx column sorting index
  5947. * @param {boolean} [append=false] Append the requested sort to the existing
  5948. * sort if true (i.e. multi-column sort)
  5949. * @param {function} [callback] callback function
  5950. * @memberof DataTable#oApi
  5951. */
  5952. function _fnSortListener(settings, colIdx, append, callback) {
  5953. var col = settings.aoColumns[colIdx];
  5954. var sorting = settings.aaSorting;
  5955. var asSorting = col.asSorting;
  5956. var nextSortIdx;
  5957. var next = function next(a, overflow) {
  5958. var idx = a._idx;
  5959. if (idx === undefined) {
  5960. idx = $.inArray(a[1], asSorting);
  5961. }
  5962. return idx + 1 < asSorting.length ? idx + 1 : overflow ? null : 0;
  5963. };
  5964. // Convert to 2D array if needed
  5965. if (typeof sorting[0] === 'number') {
  5966. sorting = settings.aaSorting = [sorting];
  5967. }
  5968. // If appending the sort then we are multi-column sorting
  5969. if (append && settings.oFeatures.bSortMulti) {
  5970. // Are we already doing some kind of sort on this column?
  5971. var sortIdx = $.inArray(colIdx, _pluck(sorting, '0'));
  5972. if (sortIdx !== - 1) {
  5973. // Yes, modify the sort
  5974. nextSortIdx = next(sorting[sortIdx], true);
  5975. if (nextSortIdx === null && sorting.length === 1) {
  5976. nextSortIdx = 0; // can't remove sorting completely
  5977. }
  5978. if (nextSortIdx === null) {
  5979. sorting.splice(sortIdx, 1);
  5980. } else {
  5981. sorting[sortIdx][1] = asSorting[nextSortIdx];
  5982. sorting[sortIdx]._idx = nextSortIdx;
  5983. }
  5984. } else {
  5985. // No sort on this column yet
  5986. sorting.push([colIdx, asSorting[0], 0]);
  5987. sorting[sorting.length - 1]._idx = 0;
  5988. }
  5989. } else if (sorting.length && sorting[0][0] == colIdx) {
  5990. // Single column - already sorting on this column, modify the sort
  5991. nextSortIdx = next(sorting[0]);
  5992. sorting.length = 1;
  5993. sorting[0][1] = asSorting[nextSortIdx];
  5994. sorting[0]._idx = nextSortIdx;
  5995. } else {
  5996. // Single column - sort only on this column
  5997. sorting.length = 0;
  5998. sorting.push([colIdx, asSorting[0]]);
  5999. sorting[0]._idx = 0;
  6000. }
  6001. // Run the sort by calling a full redraw
  6002. _fnReDraw(settings);
  6003. // callback used for async user interaction
  6004. if (typeof callback == 'function') {
  6005. callback(settings);
  6006. }
  6007. }
  6008. /**
  6009. * Attach a sort handler (click) to a node
  6010. * @param {object} settings dataTables settings object
  6011. * @param {node} attachTo node to attach the handler to
  6012. * @param {int} colIdx column sorting index
  6013. * @param {function} [callback] callback function
  6014. * @memberof DataTable#oApi
  6015. */
  6016. function _fnSortAttachListener(settings, attachTo, colIdx, callback) {
  6017. var col = settings.aoColumns[colIdx];
  6018. _fnBindAction(attachTo, {}, function (e) {
  6019. /* If the column is not sortable - don't to anything */
  6020. if (col.bSortable === false) {
  6021. return;
  6022. }
  6023. // If processing is enabled use a timeout to allow the processing
  6024. // display to be shown - otherwise to it synchronously
  6025. if (settings.oFeatures.bProcessing) {
  6026. _fnProcessingDisplay(settings, true);
  6027. setTimeout(function () {
  6028. _fnSortListener(settings, colIdx, e.shiftKey, callback);
  6029. // In server-side processing, the draw callback will remove the
  6030. // processing display
  6031. if (_fnDataSource(settings) !== 'ssp') {
  6032. _fnProcessingDisplay(settings, false);
  6033. }
  6034. }, 0);
  6035. } else {
  6036. _fnSortListener(settings, colIdx, e.shiftKey, callback);
  6037. }
  6038. });
  6039. }
  6040. /**
  6041. * Set the sorting classes on table's body, Note: it is safe to call this function
  6042. * when bSort and bSortClasses are false
  6043. * @param {object} oSettings dataTables settings object
  6044. * @memberof DataTable#oApi
  6045. */
  6046. function _fnSortingClasses(settings) {
  6047. var oldSort = settings.aLastSort;
  6048. var sortClass = settings.oClasses.sSortColumn;
  6049. var sort = _fnSortFlatten(settings);
  6050. var features = settings.oFeatures;
  6051. var i, ien, colIdx;
  6052. if (features.bSort && features.bSortClasses) {
  6053. // Remove old sorting classes
  6054. for (i = 0, ien = oldSort.length; i < ien; i++) {
  6055. colIdx = oldSort[i].src;
  6056. // Remove column sorting
  6057. $(_pluck(settings.aoData, 'anCells', colIdx)).removeClass(sortClass + (i < 2 ? i + 1 : 3));
  6058. }
  6059. // Add new column sorting
  6060. for (i = 0, ien = sort.length; i < ien; i++) {
  6061. colIdx = sort[i].src;
  6062. $(_pluck(settings.aoData, 'anCells', colIdx)).addClass(sortClass + (i < 2 ? i + 1 : 3));
  6063. }
  6064. }
  6065. settings.aLastSort = sort;
  6066. }
  6067. // Get the data to sort a column, be it from cache, fresh (populating the
  6068. // cache), or from a sort formatter
  6069. function _fnSortData(settings, idx) {
  6070. // Custom sorting function - provided by the sort data type
  6071. var column = settings.aoColumns[idx];
  6072. var customSort = DataTable.ext.order[column.sSortDataType];
  6073. var customData;
  6074. if (customSort) {
  6075. customData = customSort.call(settings.oInstance, settings, idx, _fnColumnIndexToVisible(settings, idx));
  6076. }
  6077. // Use / populate cache
  6078. var row, cellData;
  6079. var formatter = DataTable.ext.type.order[column.sType + "-pre"];
  6080. for (var i = 0, ien = settings.aoData.length; i < ien; i++) {
  6081. row = settings.aoData[i];
  6082. if (!row._aSortData) {
  6083. row._aSortData = [];
  6084. }
  6085. if (!row._aSortData[idx] || customSort) {
  6086. cellData = customSort ? customData[i] : // If there was a custom sort function, use data from there
  6087. _fnGetCellData(settings, i, idx, 'sort');
  6088. row._aSortData[idx] = formatter ? formatter(cellData) : cellData;
  6089. }
  6090. }
  6091. }
  6092. /**
  6093. * Save the state of a table
  6094. * @param {object} oSettings dataTables settings object
  6095. * @memberof DataTable#oApi
  6096. */
  6097. function _fnSaveState(settings) {
  6098. if (!settings.oFeatures.bStateSave || settings.bDestroying) {
  6099. return;
  6100. }
  6101. /* Store the interesting variables */
  6102. var state = {
  6103. time: + new Date(),
  6104. start: settings._iDisplayStart,
  6105. length: settings._iDisplayLength,
  6106. order: $.extend(true, [], settings.aaSorting),
  6107. search: _fnSearchToCamel(settings.oPreviousSearch),
  6108. columns: $.map(settings.aoColumns, function (col, i) {
  6109. return {
  6110. visible: col.bVisible,
  6111. search: _fnSearchToCamel(settings.aoPreSearchCols[i])
  6112. };
  6113. })
  6114. };
  6115. _fnCallbackFire(settings, "aoStateSaveParams", 'stateSaveParams', [settings, state]);
  6116. settings.oSavedState = state;
  6117. settings.fnStateSaveCallback.call(settings.oInstance, settings, state);
  6118. }
  6119. /**
  6120. * Attempt to load a saved table state
  6121. * @param {object} oSettings dataTables settings object
  6122. * @param {object} oInit DataTables init object so we can override settings
  6123. * @param {function} callback Callback to execute when the state has been loaded
  6124. * @memberof DataTable#oApi
  6125. */
  6126. function _fnLoadState(settings, oInit, callback) {
  6127. var i, ien;
  6128. var columns = settings.aoColumns;
  6129. var loaded = function loaded(s) {
  6130. if (!s || !s.time) {
  6131. callback();
  6132. return;
  6133. }
  6134. // Allow custom and plug-in manipulation functions to alter the saved data set and
  6135. // cancelling of loading by returning false
  6136. var abStateLoad = _fnCallbackFire(settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s]);
  6137. if ($.inArray(false, abStateLoad) !== - 1) {
  6138. callback();
  6139. return;
  6140. }
  6141. // Reject old data
  6142. var duration = settings.iStateDuration;
  6143. if (duration > 0 && s.time < + new Date() - duration * 1000) {
  6144. callback();
  6145. return;
  6146. }
  6147. // Number of columns have changed - all bets are off, no restore of settings
  6148. if (s.columns && columns.length !== s.columns.length) {
  6149. callback();
  6150. return;
  6151. }
  6152. // Store the saved state so it might be accessed at any time
  6153. settings.oLoadedState = $.extend(true, {}, s);
  6154. // Restore key features - todo - for 1.11 this needs to be done by
  6155. // subscribed events
  6156. if (s.start !== undefined) {
  6157. settings._iDisplayStart = s.start;
  6158. settings.iInitDisplayStart = s.start;
  6159. }
  6160. if (s.length !== undefined) {
  6161. settings._iDisplayLength = s.length;
  6162. }
  6163. // Order
  6164. if (s.order !== undefined) {
  6165. settings.aaSorting = [];
  6166. $.each(s.order, function (i, col) {
  6167. settings.aaSorting.push(col[0] >= columns.length ? [0, col[1]] : col);
  6168. });
  6169. }
  6170. // Search
  6171. if (s.search !== undefined) {
  6172. $.extend(settings.oPreviousSearch, _fnSearchToHung(s.search));
  6173. }
  6174. // Columns
  6175. //
  6176. if (s.columns) {
  6177. for (i = 0, ien = s.columns.length; i < ien; i++) {
  6178. var col = s.columns[i];
  6179. // Visibility
  6180. if (col.visible !== undefined) {
  6181. columns[i].bVisible = col.visible;
  6182. }
  6183. // Search
  6184. if (col.search !== undefined) {
  6185. $.extend(settings.aoPreSearchCols[i], _fnSearchToHung(col.search));
  6186. }
  6187. }
  6188. }
  6189. _fnCallbackFire(settings, 'aoStateLoaded', 'stateLoaded', [settings, s]);
  6190. callback();
  6191. };
  6192. if (!settings.oFeatures.bStateSave) {
  6193. callback();
  6194. return;
  6195. }
  6196. var state = settings.fnStateLoadCallback.call(settings.oInstance, settings, loaded);
  6197. if (state !== undefined) {
  6198. loaded(state);
  6199. }
  6200. // otherwise, wait for the loaded callback to be executed
  6201. }
  6202. /**
  6203. * Return the settings object for a particular table
  6204. * @param {node} table table we are using as a dataTable
  6205. * @returns {object} Settings object - or null if not found
  6206. * @memberof DataTable#oApi
  6207. */
  6208. function _fnSettingsFromNode(table) {
  6209. var settings = DataTable.settings;
  6210. var idx = $.inArray(table, _pluck(settings, 'nTable'));
  6211. return idx !== - 1 ? settings[idx] : null;
  6212. }
  6213. /**
  6214. * Log an error message
  6215. * @param {object} settings dataTables settings object
  6216. * @param {int} level log error messages, or display them to the user
  6217. * @param {string} msg error message
  6218. * @param {int} tn Technical note id to get more information about the error.
  6219. * @memberof DataTable#oApi
  6220. */
  6221. function _fnLog(settings, level, msg, tn) {
  6222. msg = 'DataTables warning: ' + (settings ? 'table id=' + settings.sTableId + ' - ' : '') + msg;
  6223. if (tn) {
  6224. msg += '. For more information about this error, please see ' + 'http://datatables.net/tn/' + tn;
  6225. }
  6226. if (!level) {
  6227. // Backwards compatibility pre 1.10
  6228. var ext = DataTable.ext;
  6229. var type = ext.sErrMode || ext.errMode;
  6230. if (settings) {
  6231. _fnCallbackFire(settings, null, 'error', [settings, tn, msg]);
  6232. }
  6233. if (type == 'alert') {
  6234. alert(msg);
  6235. } else if (type == 'throw') {
  6236. throw new Error(msg);
  6237. } else if (typeof type == 'function') {
  6238. type(settings, tn, msg);
  6239. }
  6240. } else if (window.console && console.log) {
  6241. console.log(msg);
  6242. }
  6243. }
  6244. /**
  6245. * See if a property is defined on one object, if so assign it to the other object
  6246. * @param {object} ret target object
  6247. * @param {object} src source object
  6248. * @param {string} name property
  6249. * @param {string} [mappedName] name to map too - optional, name used if not given
  6250. * @memberof DataTable#oApi
  6251. */
  6252. function _fnMap(ret, src, name, mappedName) {
  6253. if ($.isArray(name)) {
  6254. $.each(name, function (i, val) {
  6255. if ($.isArray(val)) {
  6256. _fnMap(ret, src, val[0], val[1]);
  6257. } else {
  6258. _fnMap(ret, src, val);
  6259. }
  6260. });
  6261. return;
  6262. }
  6263. if (mappedName === undefined) {
  6264. mappedName = name;
  6265. }
  6266. if (src[name] !== undefined) {
  6267. ret[mappedName] = src[name];
  6268. }
  6269. }
  6270. /**
  6271. * Extend objects - very similar to jQuery.extend, but deep copy objects, and
  6272. * shallow copy arrays. The reason we need to do this, is that we don't want to
  6273. * deep copy array init values (such as aaSorting) since the dev wouldn't be
  6274. * able to override them, but we do want to deep copy arrays.
  6275. * @param {object} out Object to extend
  6276. * @param {object} extender Object from which the properties will be applied to
  6277. * out
  6278. * @param {boolean} breakRefs If true, then arrays will be sliced to take an
  6279. * independent copy with the exception of the `data` or `aaData` parameters
  6280. * if they are present. This is so you can pass in a collection to
  6281. * DataTables and have that used as your data source without breaking the
  6282. * references
  6283. * @returns {object} out Reference, just for convenience - out === the return.
  6284. * @memberof DataTable#oApi
  6285. * @todo This doesn't take account of arrays inside the deep copied objects.
  6286. */
  6287. function _fnExtend(out, extender, breakRefs) {
  6288. var val;
  6289. for (var prop in extender) {
  6290. if (extender.hasOwnProperty(prop)) {
  6291. val = extender[prop];
  6292. if ($.isPlainObject(val)) {
  6293. if (!$.isPlainObject(out[prop])) {
  6294. out[prop] = {};
  6295. }
  6296. $.extend(true, out[prop], val);
  6297. } else if (breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val)) {
  6298. out[prop] = val.slice();
  6299. } else {
  6300. out[prop] = val;
  6301. }
  6302. }
  6303. }
  6304. return out;
  6305. }
  6306. /**
  6307. * Bind an event handers to allow a click or return key to activate the callback.
  6308. * This is good for accessibility since a return on the keyboard will have the
  6309. * same effect as a click, if the element has focus.
  6310. * @param {element} n Element to bind the action to
  6311. * @param {object} oData Data object to pass to the triggered function
  6312. * @param {function} fn Callback function for when the event is triggered
  6313. * @memberof DataTable#oApi
  6314. */
  6315. function _fnBindAction(n, oData, fn) {
  6316. $(n).on('click.DT', oData, function (e) {
  6317. n.blur(); // Remove focus outline for mouse users
  6318. fn(e);
  6319. }).on('keypress.DT', oData, function (e) {
  6320. if (e.which === 13) {
  6321. e.preventDefault();
  6322. fn(e);
  6323. }
  6324. }).on('selectstart.DT', function () {
  6325. /* Take the brutal approach to cancelling text selection */
  6326. return false;
  6327. });
  6328. }
  6329. /**
  6330. * Register a callback function. Easily allows a callback function to be added to
  6331. * an array store of callback functions that can then all be called together.
  6332. * @param {object} oSettings dataTables settings object
  6333. * @param {string} sStore Name of the array storage for the callbacks in oSettings
  6334. * @param {function} fn Function to be called back
  6335. * @param {string} sName Identifying name for the callback (i.e. a label)
  6336. * @memberof DataTable#oApi
  6337. */
  6338. function _fnCallbackReg(oSettings, sStore, fn, sName) {
  6339. if (fn) {
  6340. oSettings[sStore].push({
  6341. "fn": fn,
  6342. "sName": sName
  6343. });
  6344. }
  6345. }
  6346. /**
  6347. * Fire callback functions and trigger events. Note that the loop over the
  6348. * callback array store is done backwards! Further note that you do not want to
  6349. * fire off triggers in time sensitive applications (for example cell creation)
  6350. * as its slow.
  6351. * @param {object} settings dataTables settings object
  6352. * @param {string} callbackArr Name of the array storage for the callbacks in
  6353. * oSettings
  6354. * @param {string} eventName Name of the jQuery custom event to trigger. If
  6355. * null no trigger is fired
  6356. * @param {array} args Array of arguments to pass to the callback function /
  6357. * trigger
  6358. * @memberof DataTable#oApi
  6359. */
  6360. function _fnCallbackFire(settings, callbackArr, eventName, args) {
  6361. var ret = [];
  6362. if (callbackArr) {
  6363. ret = $.map(settings[callbackArr].slice().reverse(), function (val, i) {
  6364. return val.fn.apply(settings.oInstance, args);
  6365. });
  6366. }
  6367. if (eventName !== null) {
  6368. var e = $.Event(eventName + '.dt');
  6369. $(settings.nTable).trigger(e, args);
  6370. ret.push(e.result);
  6371. }
  6372. return ret;
  6373. }
  6374. function _fnLengthOverflow(settings) {
  6375. var start = settings._iDisplayStart,
  6376. end = settings.fnDisplayEnd(),
  6377. len = settings._iDisplayLength;
  6378. /* If we have space to show extra rows (backing up from the end point - then do so */
  6379. if (start >= end) {
  6380. start = end - len;
  6381. }
  6382. // Keep the start record on the current page
  6383. start -= start % len;
  6384. if (len === - 1 || start < 0) {
  6385. start = 0;
  6386. }
  6387. settings._iDisplayStart = start;
  6388. }
  6389. function _fnRenderer(settings, type) {
  6390. var renderer = settings.renderer;
  6391. var host = DataTable.ext.renderer[type];
  6392. if ($.isPlainObject(renderer) && renderer[type]) {
  6393. // Specific renderer for this type. If available use it, otherwise use
  6394. // the default.
  6395. return host[renderer[type]] || host._;
  6396. } else if (typeof renderer === 'string') {
  6397. // Common renderer - if there is one available for this type use it,
  6398. // otherwise use the default
  6399. return host[renderer] || host._;
  6400. }
  6401. // Use the default
  6402. return host._;
  6403. }
  6404. /**
  6405. * Detect the data source being used for the table. Used to simplify the code
  6406. * a little (ajax) and to make it compress a little smaller.
  6407. *
  6408. * @param {object} settings dataTables settings object
  6409. * @returns {string} Data source
  6410. * @memberof DataTable#oApi
  6411. */
  6412. function _fnDataSource(settings) {
  6413. if (settings.oFeatures.bServerSide) {
  6414. return 'ssp';
  6415. } else if (settings.ajax || settings.sAjaxSource) {
  6416. return 'ajax';
  6417. }
  6418. return 'dom';
  6419. }
  6420. /**
  6421. * Computed structure of the DataTables API, defined by the options passed to
  6422. * `DataTable.Api.register()` when building the API.
  6423. *
  6424. * The structure is built in order to speed creation and extension of the Api
  6425. * objects since the extensions are effectively pre-parsed.
  6426. *
  6427. * The array is an array of objects with the following structure, where this
  6428. * base array represents the Api prototype base:
  6429. *
  6430. * [
  6431. * {
  6432. * name: 'data' -- string - Property name
  6433. * val: function () {}, -- function - Api method (or undefined if just an object
  6434. * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
  6435. * propExt: [ ... ] -- array - Array of Api object definitions to extend the property
  6436. * },
  6437. * {
  6438. * name: 'row'
  6439. * val: {},
  6440. * methodExt: [ ... ],
  6441. * propExt: [
  6442. * {
  6443. * name: 'data'
  6444. * val: function () {},
  6445. * methodExt: [ ... ],
  6446. * propExt: [ ... ]
  6447. * },
  6448. * ...
  6449. * ]
  6450. * }
  6451. * ]
  6452. *
  6453. * @type {Array}
  6454. * @ignore
  6455. */
  6456. var __apiStruct = [];
  6457. /**
  6458. * `Array.prototype` reference.
  6459. *
  6460. * @type object
  6461. * @ignore
  6462. */
  6463. var __arrayProto = Array.prototype;
  6464. /**
  6465. * Abstraction for `context` parameter of the `Api` constructor to allow it to
  6466. * take several different forms for ease of use.
  6467. *
  6468. * Each of the input parameter types will be converted to a DataTables settings
  6469. * object where possible.
  6470. *
  6471. * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one
  6472. * of:
  6473. *
  6474. * * `string` - jQuery selector. Any DataTables' matching the given selector
  6475. * with be found and used.
  6476. * * `node` - `TABLE` node which has already been formed into a DataTable.
  6477. * * `jQuery` - A jQuery object of `TABLE` nodes.
  6478. * * `object` - DataTables settings object
  6479. * * `DataTables.Api` - API instance
  6480. * @return {array|null} Matching DataTables settings objects. `null` or
  6481. * `undefined` is returned if no matching DataTable is found.
  6482. * @ignore
  6483. */
  6484. var _toSettings = function _toSettings(mixed) {
  6485. var idx, jq;
  6486. var settings = DataTable.settings;
  6487. var tables = $.map(settings, function (el, i) {
  6488. return el.nTable;
  6489. });
  6490. if (!mixed) {
  6491. return [];
  6492. } else if (mixed.nTable && mixed.oApi) {
  6493. // DataTables settings object
  6494. return [mixed];
  6495. } else if (mixed.nodeName && mixed.nodeName.toLowerCase() === 'table') {
  6496. // Table node
  6497. idx = $.inArray(mixed, tables);
  6498. return idx !== - 1 ? [settings[idx]] : null;
  6499. } else if (mixed && typeof mixed.settings === 'function') {
  6500. return mixed.settings().toArray();
  6501. } else if (typeof mixed === 'string') {
  6502. // jQuery selector
  6503. jq = $(mixed);
  6504. } else if (mixed instanceof $) {
  6505. // jQuery object (also DataTables instance)
  6506. jq = mixed;
  6507. }
  6508. if (jq) {
  6509. return jq.map(function (i) {
  6510. idx = $.inArray(this, tables);
  6511. return idx !== - 1 ? settings[idx] : null;
  6512. }).toArray();
  6513. }
  6514. };
  6515. /**
  6516. * DataTables API class - used to control and interface with one or more
  6517. * DataTables enhanced tables.
  6518. *
  6519. * The API class is heavily based on jQuery, presenting a chainable interface
  6520. * that you can use to interact with tables. Each instance of the API class has
  6521. * a "context" - i.e. the tables that it will operate on. This could be a single
  6522. * table, all tables on a page or a sub-set thereof.
  6523. *
  6524. * Additionally the API is designed to allow you to easily work with the data in
  6525. * the tables, retrieving and manipulating it as required. This is done by
  6526. * presenting the API class as an array like interface. The contents of the
  6527. * array depend upon the actions requested by each method (for example
  6528. * `rows().nodes()` will return an array of nodes, while `rows().data()` will
  6529. * return an array of objects or arrays depending upon your table's
  6530. * configuration). The API object has a number of array like methods (`push`,
  6531. * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
  6532. * `unique` etc) to assist your working with the data held in a table.
  6533. *
  6534. * Most methods (those which return an Api instance) are chainable, which means
  6535. * the return from a method call also has all of the methods available that the
  6536. * top level object had. For example, these two calls are equivalent:
  6537. *
  6538. * // Not chained
  6539. * api.row.add( {...} );
  6540. * api.draw();
  6541. *
  6542. * // Chained
  6543. * api.row.add( {...} ).draw();
  6544. *
  6545. * @class DataTable.Api
  6546. * @param {array|object|string|jQuery} context DataTable identifier. This is
  6547. * used to define which DataTables enhanced tables this API will operate on.
  6548. * Can be one of:
  6549. *
  6550. * * `string` - jQuery selector. Any DataTables' matching the given selector
  6551. * with be found and used.
  6552. * * `node` - `TABLE` node which has already been formed into a DataTable.
  6553. * * `jQuery` - A jQuery object of `TABLE` nodes.
  6554. * * `object` - DataTables settings object
  6555. * @param {array} [data] Data to initialise the Api instance with.
  6556. *
  6557. * @example
  6558. * // Direct initialisation during DataTables construction
  6559. * var api = $('#example').DataTable();
  6560. *
  6561. * @example
  6562. * // Initialisation using a DataTables jQuery object
  6563. * var api = $('#example').dataTable().api();
  6564. *
  6565. * @example
  6566. * // Initialisation as a constructor
  6567. * var api = new $.fn.DataTable.Api( 'table.dataTable' );
  6568. */
  6569. _Api2 = function _Api(context, data) {
  6570. if (!(this instanceof _Api2)) {
  6571. return new _Api2(context, data);
  6572. }
  6573. var settings = [];
  6574. var ctxSettings = function ctxSettings(o) {
  6575. var a = _toSettings(o);
  6576. if (a) {
  6577. settings = settings.concat(a);
  6578. }
  6579. };
  6580. if ($.isArray(context)) {
  6581. for (var i = 0, ien = context.length; i < ien; i++) {
  6582. ctxSettings(context[i]);
  6583. }
  6584. } else {
  6585. ctxSettings(context);
  6586. }
  6587. // Remove duplicates
  6588. this.context = _unique(settings);
  6589. // Initial data
  6590. if (data) {
  6591. $.merge(this, data);
  6592. }
  6593. // selector
  6594. this.selector = {
  6595. rows: null,
  6596. cols: null,
  6597. opts: null
  6598. };
  6599. _Api2.extend(this, this, __apiStruct);
  6600. };
  6601. DataTable.Api = _Api2;
  6602. // Don't destroy the existing prototype, just extend it. Required for jQuery 2's
  6603. // isPlainObject.
  6604. $.extend(_Api2.prototype, {
  6605. any: function any() {
  6606. return this.count() !== 0;
  6607. },
  6608. concat: __arrayProto.concat,
  6609. context: [], // array of table settings objects
  6610. count: function count() {
  6611. return this.flatten().length;
  6612. },
  6613. each: function each(fn) {
  6614. for (var i = 0, ien = this.length; i < ien; i++) {
  6615. fn.call(this, this[i], i, this);
  6616. }
  6617. return this;
  6618. },
  6619. eq: function eq(idx) {
  6620. var ctx = this.context;
  6621. return ctx.length > idx ? new _Api2(ctx[idx], this[idx]) : null;
  6622. },
  6623. filter: function filter(fn) {
  6624. var a = [];
  6625. if (__arrayProto.filter) {
  6626. a = __arrayProto.filter.call(this, fn, this);
  6627. } else {
  6628. // Compatibility for browsers without EMCA-252-5 (JS 1.6)
  6629. for (var i = 0, ien = this.length; i < ien; i++) {
  6630. if (fn.call(this, this[i], i, this)) {
  6631. a.push(this[i]);
  6632. }
  6633. }
  6634. }
  6635. return new _Api2(this.context, a);
  6636. },
  6637. flatten: function flatten() {
  6638. var a = [];
  6639. return new _Api2(this.context, a.concat.apply(a, this.toArray()));
  6640. },
  6641. join: __arrayProto.join,
  6642. indexOf: __arrayProto.indexOf || function (obj, start) {
  6643. for (var i = start || 0, ien = this.length; i < ien; i++) {
  6644. if (this[i] === obj) {
  6645. return i;
  6646. }
  6647. }
  6648. return - 1;
  6649. },
  6650. iterator: function iterator(flatten, type, fn, alwaysNew) {
  6651. var a = [],
  6652. ret,
  6653. i,
  6654. ien,
  6655. j,
  6656. jen,
  6657. context = this.context,
  6658. rows,
  6659. items,
  6660. item,
  6661. selector = this.selector;
  6662. // Argument shifting
  6663. if (typeof flatten === 'string') {
  6664. alwaysNew = fn;
  6665. fn = type;
  6666. type = flatten;
  6667. flatten = false;
  6668. }
  6669. for (i = 0, ien = context.length; i < ien; i++) {
  6670. var apiInst = new _Api2(context[i]);
  6671. if (type === 'table') {
  6672. ret = fn.call(apiInst, context[i], i);
  6673. if (ret !== undefined) {
  6674. a.push(ret);
  6675. }
  6676. } else if (type === 'columns' || type === 'rows') {
  6677. // this has same length as context - one entry for each table
  6678. ret = fn.call(apiInst, context[i], this[i], i);
  6679. if (ret !== undefined) {
  6680. a.push(ret);
  6681. }
  6682. } else if (type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell') {
  6683. // columns and rows share the same structure.
  6684. // 'this' is an array of column indexes for each context
  6685. items = this[i];
  6686. if (type === 'column-rows') {
  6687. rows = _selector_row_indexes(context[i], selector.opts);
  6688. }
  6689. for (j = 0, jen = items.length; j < jen; j++) {
  6690. item = items[j];
  6691. if (type === 'cell') {
  6692. ret = fn.call(apiInst, context[i], item.row, item.column, i, j);
  6693. } else {
  6694. ret = fn.call(apiInst, context[i], item, i, j, rows);
  6695. }
  6696. if (ret !== undefined) {
  6697. a.push(ret);
  6698. }
  6699. }
  6700. }
  6701. }
  6702. if (a.length || alwaysNew) {
  6703. var api = new _Api2(context, flatten ? a.concat.apply([], a) : a);
  6704. var apiSelector = api.selector;
  6705. apiSelector.rows = selector.rows;
  6706. apiSelector.cols = selector.cols;
  6707. apiSelector.opts = selector.opts;
  6708. return api;
  6709. }
  6710. return this;
  6711. },
  6712. lastIndexOf: __arrayProto.lastIndexOf || function (obj, start) {
  6713. // Bit cheeky...
  6714. return this.indexOf.apply(this.toArray.reverse(), arguments);
  6715. },
  6716. length: 0,
  6717. map: function map(fn) {
  6718. var a = [];
  6719. if (__arrayProto.map) {
  6720. a = __arrayProto.map.call(this, fn, this);
  6721. } else {
  6722. // Compatibility for browsers without EMCA-252-5 (JS 1.6)
  6723. for (var i = 0, ien = this.length; i < ien; i++) {
  6724. a.push(fn.call(this, this[i], i));
  6725. }
  6726. }
  6727. return new _Api2(this.context, a);
  6728. },
  6729. pluck: function pluck(prop) {
  6730. return this.map(function (el) {
  6731. return el[prop];
  6732. });
  6733. },
  6734. pop: __arrayProto.pop,
  6735. push: __arrayProto.push,
  6736. // Does not return an API instance
  6737. reduce: __arrayProto.reduce || function (fn, init) {
  6738. return _fnReduce(this, fn, init, 0, this.length, 1);
  6739. },
  6740. reduceRight: __arrayProto.reduceRight || function (fn, init) {
  6741. return _fnReduce(this, fn, init, this.length - 1, - 1, - 1);
  6742. },
  6743. reverse: __arrayProto.reverse,
  6744. // Object with rows, columns and opts
  6745. selector: null,
  6746. shift: __arrayProto.shift,
  6747. slice: function slice() {
  6748. return new _Api2(this.context, this);
  6749. },
  6750. sort: __arrayProto.sort, // ? name - order?
  6751. splice: __arrayProto.splice,
  6752. toArray: function toArray() {
  6753. return __arrayProto.slice.call(this);
  6754. },
  6755. to$: function to$() {
  6756. return $(this);
  6757. },
  6758. toJQuery: function toJQuery() {
  6759. return $(this);
  6760. },
  6761. unique: function unique() {
  6762. return new _Api2(this.context, _unique(this));
  6763. },
  6764. unshift: __arrayProto.unshift
  6765. });
  6766. _Api2.extend = function (scope, obj, ext) {
  6767. // Only extend API instances and static properties of the API
  6768. if (!ext.length || !obj || !(obj instanceof _Api2) && !obj.__dt_wrapper) {
  6769. return;
  6770. }
  6771. var i,
  6772. ien,
  6773. j,
  6774. jen,
  6775. struct,
  6776. inner,
  6777. methodScoping = function methodScoping(scope, fn, struc) {
  6778. return function () {
  6779. var ret = fn.apply(scope, arguments);
  6780. // Method extension
  6781. _Api2.extend(ret, ret, struc.methodExt);
  6782. return ret;
  6783. };
  6784. };
  6785. for (i = 0, ien = ext.length; i < ien; i++) {
  6786. struct = ext[i];
  6787. // Value
  6788. obj[struct.name] = typeof struct.val === 'function' ? methodScoping(scope, struct.val, struct) : $.isPlainObject(struct.val) ? {} : struct.val;
  6789. obj[struct.name].__dt_wrapper = true;
  6790. // Property extension
  6791. _Api2.extend(scope, obj[struct.name], struct.propExt);
  6792. }
  6793. };
  6794. // @todo - Is there need for an augment function?
  6795. // _Api.augment = function ( inst, name )
  6796. // {
  6797. // // Find src object in the structure from the name
  6798. // var parts = name.split('.');
  6799. // _Api.extend( inst, obj );
  6800. // };
  6801. // [
  6802. // {
  6803. // name: 'data' -- string - Property name
  6804. // val: function () {}, -- function - Api method (or undefined if just an object
  6805. // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
  6806. // propExt: [ ... ] -- array - Array of Api object definitions to extend the property
  6807. // },
  6808. // {
  6809. // name: 'row'
  6810. // val: {},
  6811. // methodExt: [ ... ],
  6812. // propExt: [
  6813. // {
  6814. // name: 'data'
  6815. // val: function () {},
  6816. // methodExt: [ ... ],
  6817. // propExt: [ ... ]
  6818. // },
  6819. // ...
  6820. // ]
  6821. // }
  6822. // ]
  6823. _Api2.register = _api_register = function _api_register(name, val) {
  6824. if ($.isArray(name)) {
  6825. for (var j = 0, jen = name.length; j < jen; j++) {
  6826. _Api2.register(name[j], val);
  6827. }
  6828. return;
  6829. }
  6830. var i,
  6831. ien,
  6832. heir = name.split('.'),
  6833. struct = __apiStruct,
  6834. key,
  6835. method;
  6836. var find = function find(src, name) {
  6837. for (var i = 0, ien = src.length; i < ien; i++) {
  6838. if (src[i].name === name) {
  6839. return src[i];
  6840. }
  6841. }
  6842. return null;
  6843. };
  6844. for (i = 0, ien = heir.length; i < ien; i++) {
  6845. method = heir[i].indexOf('()') !== - 1;
  6846. key = method ? heir[i].replace('()', '') : heir[i];
  6847. var src = find(struct, key);
  6848. if (!src) {
  6849. src = {
  6850. name: key,
  6851. val: {},
  6852. methodExt: [],
  6853. propExt: []
  6854. };
  6855. struct.push(src);
  6856. }
  6857. if (i === ien - 1) {
  6858. src.val = val;
  6859. } else {
  6860. struct = method ? src.methodExt : src.propExt;
  6861. }
  6862. }
  6863. };
  6864. _Api2.registerPlural = _api_registerPlural = function _api_registerPlural(pluralName, singularName, val) {
  6865. _Api2.register(pluralName, val);
  6866. _Api2.register(singularName, function () {
  6867. var ret = val.apply(this, arguments);
  6868. if (ret === this) {
  6869. // Returned item is the API instance that was passed in, return it
  6870. return this;
  6871. } else if (ret instanceof _Api2) {
  6872. // New API instance returned, want the value from the first item
  6873. // in the returned array for the singular result.
  6874. return ret.length ? $.isArray(ret[0]) ? new _Api2(ret.context, ret[0]) : // Array results are 'enhanced'
  6875. ret[0] : undefined;
  6876. }
  6877. // Non-API return - just fire it back
  6878. return ret;
  6879. });
  6880. };
  6881. /**
  6882. * Selector for HTML tables. Apply the given selector to the give array of
  6883. * DataTables settings objects.
  6884. *
  6885. * @param {string|integer} [selector] jQuery selector string or integer
  6886. * @param {array} Array of DataTables settings objects to be filtered
  6887. * @return {array}
  6888. * @ignore
  6889. */
  6890. var __table_selector = function __table_selector(selector, a) {
  6891. // Integer is used to pick out a table by index
  6892. if (typeof selector === 'number') {
  6893. return [a[selector]];
  6894. }
  6895. // Perform a jQuery selector on the table nodes
  6896. var nodes = $.map(a, function (el, i) {
  6897. return el.nTable;
  6898. });
  6899. return $(nodes).filter(selector).map(function (i) {
  6900. // Need to translate back from the table node to the settings
  6901. var idx = $.inArray(this, nodes);
  6902. return a[idx];
  6903. }).toArray();
  6904. };
  6905. /**
  6906. * Context selector for the API's context (i.e. the tables the API instance
  6907. * refers to.
  6908. *
  6909. * @name DataTable.Api#tables
  6910. * @param {string|integer} [selector] Selector to pick which tables the iterator
  6911. * should operate on. If not given, all tables in the current context are
  6912. * used. This can be given as a jQuery selector (for example `':gt(0)'`) to
  6913. * select multiple tables or as an integer to select a single table.
  6914. * @returns {DataTable.Api} Returns a new API instance if a selector is given.
  6915. */
  6916. _api_register('tables()', function (selector) {
  6917. // A new instance is created if there was a selector specified
  6918. return selector ? new _Api2(__table_selector(selector, this.context)) : this;
  6919. });
  6920. _api_register('table()', function (selector) {
  6921. var tables = this.tables(selector);
  6922. var ctx = tables.context;
  6923. // Truncate to the first matched table
  6924. return ctx.length ? new _Api2(ctx[0]) : tables;
  6925. });
  6926. _api_registerPlural('tables().nodes()', 'table().node()', function () {
  6927. return this.iterator('table', function (ctx) {
  6928. return ctx.nTable;
  6929. }, 1);
  6930. });
  6931. _api_registerPlural('tables().body()', 'table().body()', function () {
  6932. return this.iterator('table', function (ctx) {
  6933. return ctx.nTBody;
  6934. }, 1);
  6935. });
  6936. _api_registerPlural('tables().header()', 'table().header()', function () {
  6937. return this.iterator('table', function (ctx) {
  6938. return ctx.nTHead;
  6939. }, 1);
  6940. });
  6941. _api_registerPlural('tables().footer()', 'table().footer()', function () {
  6942. return this.iterator('table', function (ctx) {
  6943. return ctx.nTFoot;
  6944. }, 1);
  6945. });
  6946. _api_registerPlural('tables().containers()', 'table().container()', function () {
  6947. return this.iterator('table', function (ctx) {
  6948. return ctx.nTableWrapper;
  6949. }, 1);
  6950. });
  6951. /**
  6952. * Redraw the tables in the current context.
  6953. */
  6954. _api_register('draw()', function (paging) {
  6955. return this.iterator('table', function (settings) {
  6956. if (paging === 'page') {
  6957. _fnDraw(settings);
  6958. } else {
  6959. if (typeof paging === 'string') {
  6960. paging = paging === 'full-hold' ? false : true;
  6961. }
  6962. _fnReDraw(settings, paging === false);
  6963. }
  6964. });
  6965. });
  6966. /**
  6967. * Get the current page index.
  6968. *
  6969. * @return {integer} Current page index (zero based)
  6970. */ /**
  6971. * Set the current page.
  6972. *
  6973. * Note that if you attempt to show a page which does not exist, DataTables will
  6974. * not throw an error, but rather reset the paging.
  6975. *
  6976. * @param {integer|string} action The paging action to take. This can be one of:
  6977. * * `integer` - The page index to jump to
  6978. * * `string` - An action to take:
  6979. * * `first` - Jump to first page.
  6980. * * `next` - Jump to the next page
  6981. * * `previous` - Jump to previous page
  6982. * * `last` - Jump to the last page.
  6983. * @returns {DataTables.Api} this
  6984. */
  6985. _api_register('page()', function (action) {
  6986. if (action === undefined) {
  6987. return this.page.info().page; // not an expensive call
  6988. }
  6989. // else, have an action to take on all tables
  6990. return this.iterator('table', function (settings) {
  6991. _fnPageChange(settings, action);
  6992. });
  6993. });
  6994. /**
  6995. * Paging information for the first table in the current context.
  6996. *
  6997. * If you require paging information for another table, use the `table()` method
  6998. * with a suitable selector.
  6999. *
  7000. * @return {object} Object with the following properties set:
  7001. * * `page` - Current page index (zero based - i.e. the first page is `0`)
  7002. * * `pages` - Total number of pages
  7003. * * `start` - Display index for the first record shown on the current page
  7004. * * `end` - Display index for the last record shown on the current page
  7005. * * `length` - Display length (number of records). Note that generally `start
  7006. * + length = end`, but this is not always true, for example if there are
  7007. * only 2 records to show on the final page, with a length of 10.
  7008. * * `recordsTotal` - Full data set length
  7009. * * `recordsDisplay` - Data set length once the current filtering criterion
  7010. * are applied.
  7011. */
  7012. _api_register('page.info()', function (action) {
  7013. if (this.context.length === 0) {
  7014. return undefined;
  7015. }
  7016. var settings = this.context[0],
  7017. start = settings._iDisplayStart,
  7018. len = settings.oFeatures.bPaginate ? settings._iDisplayLength : - 1,
  7019. visRecords = settings.fnRecordsDisplay(),
  7020. all = len === - 1;
  7021. return {
  7022. "page": all ? 0 : Math.floor(start / len),
  7023. "pages": all ? 1 : Math.ceil(visRecords / len),
  7024. "start": start,
  7025. "end": settings.fnDisplayEnd(),
  7026. "length": len,
  7027. "recordsTotal": settings.fnRecordsTotal(),
  7028. "recordsDisplay": visRecords,
  7029. "serverSide": _fnDataSource(settings) === 'ssp'
  7030. };
  7031. });
  7032. /**
  7033. * Get the current page length.
  7034. *
  7035. * @return {integer} Current page length. Note `-1` indicates that all records
  7036. * are to be shown.
  7037. */ /**
  7038. * Set the current page length.
  7039. *
  7040. * @param {integer} Page length to set. Use `-1` to show all records.
  7041. * @returns {DataTables.Api} this
  7042. */
  7043. _api_register('page.len()', function (len) {
  7044. // Note that we can't call this function 'length()' because `length`
  7045. // is a Javascript property of functions which defines how many arguments
  7046. // the function expects.
  7047. if (len === undefined) {
  7048. return this.context.length !== 0 ? this.context[0]._iDisplayLength : undefined;
  7049. }
  7050. // else, set the page length
  7051. return this.iterator('table', function (settings) {
  7052. _fnLengthChange(settings, len);
  7053. });
  7054. });
  7055. var __reload = function __reload(settings, holdPosition, callback) {
  7056. // Use the draw event to trigger a callback
  7057. if (callback) {
  7058. var api = new _Api2(settings);
  7059. api.one('draw', function () {
  7060. callback(api.ajax.json());
  7061. });
  7062. }
  7063. if (_fnDataSource(settings) == 'ssp') {
  7064. _fnReDraw(settings, holdPosition);
  7065. } else {
  7066. _fnProcessingDisplay(settings, true);
  7067. // Cancel an existing request
  7068. var xhr = settings.jqXHR;
  7069. if (xhr && xhr.readyState !== 4) {
  7070. xhr.abort();
  7071. }
  7072. // Trigger xhr
  7073. _fnBuildAjax(settings, [], function (json) {
  7074. _fnClearTable(settings);
  7075. var data = _fnAjaxDataSrc(settings, json);
  7076. for (var i = 0, ien = data.length; i < ien; i++) {
  7077. _fnAddData(settings, data[i]);
  7078. }
  7079. _fnReDraw(settings, holdPosition);
  7080. _fnProcessingDisplay(settings, false);
  7081. });
  7082. }
  7083. };
  7084. /**
  7085. * Get the JSON response from the last Ajax request that DataTables made to the
  7086. * server. Note that this returns the JSON from the first table in the current
  7087. * context.
  7088. *
  7089. * @return {object} JSON received from the server.
  7090. */
  7091. _api_register('ajax.json()', function () {
  7092. var ctx = this.context;
  7093. if (ctx.length > 0) {
  7094. return ctx[0].json;
  7095. }
  7096. // else return undefined;
  7097. });
  7098. /**
  7099. * Get the data submitted in the last Ajax request
  7100. */
  7101. _api_register('ajax.params()', function () {
  7102. var ctx = this.context;
  7103. if (ctx.length > 0) {
  7104. return ctx[0].oAjaxData;
  7105. }
  7106. // else return undefined;
  7107. });
  7108. /**
  7109. * Reload tables from the Ajax data source. Note that this function will
  7110. * automatically re-draw the table when the remote data has been loaded.
  7111. *
  7112. * @param {boolean} [reset=true] Reset (default) or hold the current paging
  7113. * position. A full re-sort and re-filter is performed when this method is
  7114. * called, which is why the pagination reset is the default action.
  7115. * @returns {DataTables.Api} this
  7116. */
  7117. _api_register('ajax.reload()', function (callback, resetPaging) {
  7118. return this.iterator('table', function (settings) {
  7119. __reload(settings, resetPaging === false, callback);
  7120. });
  7121. });
  7122. /**
  7123. * Get the current Ajax URL. Note that this returns the URL from the first
  7124. * table in the current context.
  7125. *
  7126. * @return {string} Current Ajax source URL
  7127. */ /**
  7128. * Set the Ajax URL. Note that this will set the URL for all tables in the
  7129. * current context.
  7130. *
  7131. * @param {string} url URL to set.
  7132. * @returns {DataTables.Api} this
  7133. */
  7134. _api_register('ajax.url()', function (url) {
  7135. var ctx = this.context;
  7136. if (url === undefined) {
  7137. // get
  7138. if (ctx.length === 0) {
  7139. return undefined;
  7140. }
  7141. ctx = ctx[0];
  7142. return ctx.ajax ? $.isPlainObject(ctx.ajax) ? ctx.ajax.url : ctx.ajax : ctx.sAjaxSource;
  7143. }
  7144. // set
  7145. return this.iterator('table', function (settings) {
  7146. if ($.isPlainObject(settings.ajax)) {
  7147. settings.ajax.url = url;
  7148. } else {
  7149. settings.ajax = url;
  7150. }
  7151. // No need to consider sAjaxSource here since DataTables gives priority
  7152. // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
  7153. // value of `sAjaxSource` redundant.
  7154. });
  7155. });
  7156. /**
  7157. * Load data from the newly set Ajax URL. Note that this method is only
  7158. * available when `ajax.url()` is used to set a URL. Additionally, this method
  7159. * has the same effect as calling `ajax.reload()` but is provided for
  7160. * convenience when setting a new URL. Like `ajax.reload()` it will
  7161. * automatically redraw the table once the remote data has been loaded.
  7162. *
  7163. * @returns {DataTables.Api} this
  7164. */
  7165. _api_register('ajax.url().load()', function (callback, resetPaging) {
  7166. // Same as a reload, but makes sense to present it for easy access after a
  7167. // url change
  7168. return this.iterator('table', function (ctx) {
  7169. __reload(ctx, resetPaging === false, callback);
  7170. });
  7171. });
  7172. var _selector_run = function _selector_run(type, selector, selectFn, settings, opts) {
  7173. var out = [],
  7174. res,
  7175. a,
  7176. i,
  7177. ien,
  7178. j,
  7179. jen,
  7180. selectorType = typeof selector === 'undefined' ? 'undefined' : _typeof(selector);
  7181. // Can't just check for isArray here, as an API or jQuery instance might be
  7182. // given with their array like look
  7183. if (!selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined) {
  7184. selector = [selector];
  7185. }
  7186. for (i = 0, ien = selector.length; i < ien; i++) {
  7187. // Only split on simple strings - complex expressions will be jQuery selectors
  7188. a = selector[i] && selector[i].split && !selector[i].match(/[\[\(:]/) ? selector[i].split(',') : [selector[i]];
  7189. for (j = 0, jen = a.length; j < jen; j++) {
  7190. res = selectFn(typeof a[j] === 'string' ? $.trim(a[j]) : a[j]);
  7191. if (res && res.length) {
  7192. out = out.concat(res);
  7193. }
  7194. }
  7195. }
  7196. // selector extensions
  7197. var ext = _ext.selector[type];
  7198. if (ext.length) {
  7199. for (i = 0, ien = ext.length; i < ien; i++) {
  7200. out = ext[i](settings, opts, out);
  7201. }
  7202. }
  7203. return _unique(out);
  7204. };
  7205. var _selector_opts = function _selector_opts(opts) {
  7206. if (!opts) {
  7207. opts = {};
  7208. }
  7209. // Backwards compatibility for 1.9- which used the terminology filter rather
  7210. // than search
  7211. if (opts.filter && opts.search === undefined) {
  7212. opts.search = opts.filter;
  7213. }
  7214. return $.extend({
  7215. search: 'none',
  7216. order: 'current',
  7217. page: 'all'
  7218. }, opts);
  7219. };
  7220. var _selector_first = function _selector_first(inst) {
  7221. // Reduce the API instance to the first item found
  7222. for (var i = 0, ien = inst.length; i < ien; i++) {
  7223. if (inst[i].length > 0) {
  7224. // Assign the first element to the first item in the instance
  7225. // and truncate the instance and context
  7226. inst[0] = inst[i];
  7227. inst[0].length = 1;
  7228. inst.length = 1;
  7229. inst.context = [inst.context[i]];
  7230. return inst;
  7231. }
  7232. }
  7233. // Not found - return an empty instance
  7234. inst.length = 0;
  7235. return inst;
  7236. };
  7237. var _selector_row_indexes = function _selector_row_indexes(settings, opts) {
  7238. var i,
  7239. ien,
  7240. tmp,
  7241. a = [],
  7242. displayFiltered = settings.aiDisplay,
  7243. displayMaster = settings.aiDisplayMaster;
  7244. var search = opts.search,
  7245. // none, applied, removed
  7246. order = opts.order,
  7247. // applied, current, index (original - compatibility with 1.9)
  7248. page = opts.page; // all, current
  7249. if (_fnDataSource(settings) == 'ssp') {
  7250. // In server-side processing mode, most options are irrelevant since
  7251. // rows not shown don't exist and the index order is the applied order
  7252. // Removed is a special case - for consistency just return an empty
  7253. // array
  7254. return search === 'removed' ? [] : _range(0, displayMaster.length);
  7255. } else if (page == 'current') {
  7256. // Current page implies that order=current and fitler=applied, since it is
  7257. // fairly senseless otherwise, regardless of what order and search actually
  7258. // are
  7259. for (i = settings._iDisplayStart, ien = settings.fnDisplayEnd(); i < ien; i++) {
  7260. a.push(displayFiltered[i]);
  7261. }
  7262. } else if (order == 'current' || order == 'applied') {
  7263. a = search == 'none' ? displayMaster.slice() : // no search
  7264. search == 'applied' ? displayFiltered.slice() : // applied search
  7265. $.map(displayMaster, function (el, i) {
  7266. // removed search
  7267. return $.inArray(el, displayFiltered) === - 1 ? el : null;
  7268. });
  7269. } else if (order == 'index' || order == 'original') {
  7270. for (i = 0, ien = settings.aoData.length; i < ien; i++) {
  7271. if (search == 'none') {
  7272. a.push(i);
  7273. } else {
  7274. // applied | removed
  7275. tmp = $.inArray(i, displayFiltered);
  7276. if (tmp === - 1 && search == 'removed' || tmp >= 0 && search == 'applied') {
  7277. a.push(i);
  7278. }
  7279. }
  7280. }
  7281. }
  7282. return a;
  7283. };
  7284. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  7285. * Rows
  7286. *
  7287. * {} - no selector - use all available rows
  7288. * {integer} - row aoData index
  7289. * {node} - TR node
  7290. * {string} - jQuery selector to apply to the TR elements
  7291. * {array} - jQuery array of nodes, or simply an array of TR nodes
  7292. *
  7293. */
  7294. var __row_selector = function __row_selector(settings, selector, opts) {
  7295. var rows;
  7296. var run = function run(sel) {
  7297. var selInt = _intVal(sel);
  7298. var i, ien;
  7299. // Short cut - selector is a number and no options provided (default is
  7300. // all records, so no need to check if the index is in there, since it
  7301. // must be - dev error if the index doesn't exist).
  7302. if (selInt !== null && !opts) {
  7303. return [selInt];
  7304. }
  7305. if (!rows) {
  7306. rows = _selector_row_indexes(settings, opts);
  7307. }
  7308. if (selInt !== null && $.inArray(selInt, rows) !== - 1) {
  7309. // Selector - integer
  7310. return [selInt];
  7311. } else if (sel === null || sel === undefined || sel === '') {
  7312. // Selector - none
  7313. return rows;
  7314. }
  7315. // Selector - function
  7316. if (typeof sel === 'function') {
  7317. return $.map(rows, function (idx) {
  7318. var row = settings.aoData[idx];
  7319. return sel(idx, row._aData, row.nTr) ? idx : null;
  7320. });
  7321. }
  7322. // Get nodes in the order from the `rows` array with null values removed
  7323. var nodes = _removeEmpty(_pluck_order(settings.aoData, rows, 'nTr'));
  7324. // Selector - node
  7325. if (sel.nodeName) {
  7326. if (sel._DT_RowIndex !== undefined) {
  7327. return [sel._DT_RowIndex]; // Property added by DT for fast lookup
  7328. } else if (sel._DT_CellIndex) {
  7329. return [sel._DT_CellIndex.row];
  7330. } else {
  7331. var host = $(sel).closest('*[data-dt-row]');
  7332. return host.length ? [host.data('dt-row')] : [];
  7333. }
  7334. }
  7335. // ID selector. Want to always be able to select rows by id, regardless
  7336. // of if the tr element has been created or not, so can't rely upon
  7337. // jQuery here - hence a custom implementation. This does not match
  7338. // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
  7339. // but to select it using a CSS selector engine (like Sizzle or
  7340. // querySelect) it would need to need to be escaped for some characters.
  7341. // DataTables simplifies this for row selectors since you can select
  7342. // only a row. A # indicates an id any anything that follows is the id -
  7343. // unescaped.
  7344. if (typeof sel === 'string' && sel.charAt(0) === '#') {
  7345. // get row index from id
  7346. var rowObj = settings.aIds[sel.replace(/^#/, '')];
  7347. if (rowObj !== undefined) {
  7348. return [rowObj.idx];
  7349. }
  7350. // need to fall through to jQuery in case there is DOM id that
  7351. // matches
  7352. }
  7353. // Selector - jQuery selector string, array of nodes or jQuery object/
  7354. // As jQuery's .filter() allows jQuery objects to be passed in filter,
  7355. // it also allows arrays, so this will cope with all three options
  7356. return $(nodes).filter(sel).map(function () {
  7357. return this._DT_RowIndex;
  7358. }).toArray();
  7359. };
  7360. return _selector_run('row', selector, run, settings, opts);
  7361. };
  7362. _api_register('rows()', function (selector, opts) {
  7363. // argument shifting
  7364. if (selector === undefined) {
  7365. selector = '';
  7366. } else if ($.isPlainObject(selector)) {
  7367. opts = selector;
  7368. selector = '';
  7369. }
  7370. opts = _selector_opts(opts);
  7371. var inst = this.iterator('table', function (settings) {
  7372. return __row_selector(settings, selector, opts);
  7373. }, 1);
  7374. // Want argument shifting here and in __row_selector?
  7375. inst.selector.rows = selector;
  7376. inst.selector.opts = opts;
  7377. return inst;
  7378. });
  7379. _api_register('rows().nodes()', function () {
  7380. return this.iterator('row', function (settings, row) {
  7381. return settings.aoData[row].nTr || undefined;
  7382. }, 1);
  7383. });
  7384. _api_register('rows().data()', function () {
  7385. return this.iterator(true, 'rows', function (settings, rows) {
  7386. return _pluck_order(settings.aoData, rows, '_aData');
  7387. }, 1);
  7388. });
  7389. _api_registerPlural('rows().cache()', 'row().cache()', function (type) {
  7390. return this.iterator('row', function (settings, row) {
  7391. var r = settings.aoData[row];
  7392. return type === 'search' ? r._aFilterData : r._aSortData;
  7393. }, 1);
  7394. });
  7395. _api_registerPlural('rows().invalidate()', 'row().invalidate()', function (src) {
  7396. return this.iterator('row', function (settings, row) {
  7397. _fnInvalidate(settings, row, src);
  7398. });
  7399. });
  7400. _api_registerPlural('rows().indexes()', 'row().index()', function () {
  7401. return this.iterator('row', function (settings, row) {
  7402. return row;
  7403. }, 1);
  7404. });
  7405. _api_registerPlural('rows().ids()', 'row().id()', function (hash) {
  7406. var a = [];
  7407. var context = this.context;
  7408. // `iterator` will drop undefined values, but in this case we want them
  7409. for (var i = 0, ien = context.length; i < ien; i++) {
  7410. for (var j = 0, jen = this[i].length; j < jen; j++) {
  7411. var id = context[i].rowIdFn(context[i].aoData[this[i][j]]._aData);
  7412. a.push((hash === true ? '#' : '') + id);
  7413. }
  7414. }
  7415. return new _Api2(context, a);
  7416. });
  7417. _api_registerPlural('rows().remove()', 'row().remove()', function () {
  7418. var that = this;
  7419. this.iterator('row', function (settings, row, thatIdx) {
  7420. var data = settings.aoData;
  7421. var rowData = data[row];
  7422. var i, ien, j, jen;
  7423. var loopRow, loopCells;
  7424. data.splice(row, 1);
  7425. // Update the cached indexes
  7426. for (i = 0, ien = data.length; i < ien; i++) {
  7427. loopRow = data[i];
  7428. loopCells = loopRow.anCells;
  7429. // Rows
  7430. if (loopRow.nTr !== null) {
  7431. loopRow.nTr._DT_RowIndex = i;
  7432. }
  7433. // Cells
  7434. if (loopCells !== null) {
  7435. for (j = 0, jen = loopCells.length; j < jen; j++) {
  7436. loopCells[j]._DT_CellIndex.row = i;
  7437. }
  7438. }
  7439. }
  7440. // Delete from the display arrays
  7441. _fnDeleteIndex(settings.aiDisplayMaster, row);
  7442. _fnDeleteIndex(settings.aiDisplay, row);
  7443. _fnDeleteIndex(that[thatIdx], row, false); // maintain local indexes
  7444. // For server-side processing tables - subtract the deleted row from the count
  7445. if (settings._iRecordsDisplay > 0) {
  7446. settings._iRecordsDisplay--;
  7447. }
  7448. // Check for an 'overflow' they case for displaying the table
  7449. _fnLengthOverflow(settings);
  7450. // Remove the row's ID reference if there is one
  7451. var id = settings.rowIdFn(rowData._aData);
  7452. if (id !== undefined) {
  7453. delete settings.aIds[id];
  7454. }
  7455. });
  7456. this.iterator('table', function (settings) {
  7457. for (var i = 0, ien = settings.aoData.length; i < ien; i++) {
  7458. settings.aoData[i].idx = i;
  7459. }
  7460. });
  7461. return this;
  7462. });
  7463. _api_register('rows.add()', function (rows) {
  7464. var newRows = this.iterator('table', function (settings) {
  7465. var row, i, ien;
  7466. var out = [];
  7467. for (i = 0, ien = rows.length; i < ien; i++) {
  7468. row = rows[i];
  7469. if (row.nodeName && row.nodeName.toUpperCase() === 'TR') {
  7470. out.push(_fnAddTr(settings, row)[0]);
  7471. } else {
  7472. out.push(_fnAddData(settings, row));
  7473. }
  7474. }
  7475. return out;
  7476. }, 1);
  7477. // Return an Api.rows() extended instance, so rows().nodes() etc can be used
  7478. var modRows = this.rows( - 1);
  7479. modRows.pop();
  7480. $.merge(modRows, newRows);
  7481. return modRows;
  7482. });
  7483. /**
  7484. *
  7485. */
  7486. _api_register('row()', function (selector, opts) {
  7487. return _selector_first(this.rows(selector, opts));
  7488. });
  7489. _api_register('row().data()', function (data) {
  7490. var ctx = this.context;
  7491. if (data === undefined) {
  7492. // Get
  7493. return ctx.length && this.length ? ctx[0].aoData[this[0]]._aData : undefined;
  7494. }
  7495. // Set
  7496. ctx[0].aoData[this[0]]._aData = data;
  7497. // Automatically invalidate
  7498. _fnInvalidate(ctx[0], this[0], 'data');
  7499. return this;
  7500. });
  7501. _api_register('row().node()', function () {
  7502. var ctx = this.context;
  7503. return ctx.length && this.length ? ctx[0].aoData[this[0]].nTr || null : null;
  7504. });
  7505. _api_register('row.add()', function (row) {
  7506. // Allow a jQuery object to be passed in - only a single row is added from
  7507. // it though - the first element in the set
  7508. if (row instanceof $ && row.length) {
  7509. row = row[0];
  7510. }
  7511. var rows = this.iterator('table', function (settings) {
  7512. if (row.nodeName && row.nodeName.toUpperCase() === 'TR') {
  7513. return _fnAddTr(settings, row)[0];
  7514. }
  7515. return _fnAddData(settings, row);
  7516. });
  7517. // Return an Api.rows() extended instance, with the newly added row selected
  7518. return this.row(rows[0]);
  7519. });
  7520. var __details_add = function __details_add(ctx, row, data, klass) {
  7521. // Convert to array of TR elements
  7522. var rows = [];
  7523. var addRow = function addRow(r, k) {
  7524. // Recursion to allow for arrays of jQuery objects
  7525. if ($.isArray(r) || r instanceof $) {
  7526. for (var i = 0, ien = r.length; i < ien; i++) {
  7527. addRow(r[i], k);
  7528. }
  7529. return;
  7530. }
  7531. // If we get a TR element, then just add it directly - up to the dev
  7532. // to add the correct number of columns etc
  7533. if (r.nodeName && r.nodeName.toLowerCase() === 'tr') {
  7534. rows.push(r);
  7535. } else {
  7536. // Otherwise create a row with a wrapper
  7537. var created = $('<tr><td/></tr>').addClass(k);
  7538. $('td', created).addClass(k).html(r)[0].colSpan = _fnVisbleColumns(ctx);
  7539. rows.push(created[0]);
  7540. }
  7541. };
  7542. addRow(data, klass);
  7543. if (row._details) {
  7544. row._details.detach();
  7545. }
  7546. row._details = $(rows);
  7547. // If the children were already shown, that state should be retained
  7548. if (row._detailsShow) {
  7549. row._details.insertAfter(row.nTr);
  7550. }
  7551. };
  7552. var __details_remove = function __details_remove(api, idx) {
  7553. var ctx = api.context;
  7554. if (ctx.length) {
  7555. var row = ctx[0].aoData[idx !== undefined ? idx : api[0]];
  7556. if (row && row._details) {
  7557. row._details.remove();
  7558. row._detailsShow = undefined;
  7559. row._details = undefined;
  7560. }
  7561. }
  7562. };
  7563. var __details_display = function __details_display(api, show) {
  7564. var ctx = api.context;
  7565. if (ctx.length && api.length) {
  7566. var row = ctx[0].aoData[api[0]];
  7567. if (row._details) {
  7568. row._detailsShow = show;
  7569. if (show) {
  7570. row._details.insertAfter(row.nTr);
  7571. } else {
  7572. row._details.detach();
  7573. }
  7574. __details_events(ctx[0]);
  7575. }
  7576. }
  7577. };
  7578. var __details_events = function __details_events(settings) {
  7579. var api = new _Api2(settings);
  7580. var namespace = '.dt.DT_details';
  7581. var drawEvent = 'draw' + namespace;
  7582. var colvisEvent = 'column-visibility' + namespace;
  7583. var destroyEvent = 'destroy' + namespace;
  7584. var data = settings.aoData;
  7585. api.off(drawEvent + ' ' + colvisEvent + ' ' + destroyEvent);
  7586. if (_pluck(data, '_details').length > 0) {
  7587. // On each draw, insert the required elements into the document
  7588. api.on(drawEvent, function (e, ctx) {
  7589. if (settings !== ctx) {
  7590. return;
  7591. }
  7592. api.rows({page: 'current'}).eq(0).each(function (idx) {
  7593. // Internal data grab
  7594. var row = data[idx];
  7595. if (row._detailsShow) {
  7596. row._details.insertAfter(row.nTr);
  7597. }
  7598. });
  7599. });
  7600. // Column visibility change - update the colspan
  7601. api.on(colvisEvent, function (e, ctx, idx, vis) {
  7602. if (settings !== ctx) {
  7603. return;
  7604. }
  7605. // Update the colspan for the details rows (note, only if it already has
  7606. // a colspan)
  7607. var row,
  7608. visible = _fnVisbleColumns(ctx);
  7609. for (var i = 0, ien = data.length; i < ien; i++) {
  7610. row = data[i];
  7611. if (row._details) {
  7612. row._details.children('td[colspan]').attr('colspan', visible);
  7613. }
  7614. }
  7615. });
  7616. // Table destroyed - nuke any child rows
  7617. api.on(destroyEvent, function (e, ctx) {
  7618. if (settings !== ctx) {
  7619. return;
  7620. }
  7621. for (var i = 0, ien = data.length; i < ien; i++) {
  7622. if (data[i]._details) {
  7623. __details_remove(api, i);
  7624. }
  7625. }
  7626. });
  7627. }
  7628. };
  7629. // Strings for the method names to help minification
  7630. var _emp = '';
  7631. var _child_obj = _emp + 'row().child';
  7632. var _child_mth = _child_obj + '()';
  7633. // data can be:
  7634. // tr
  7635. // string
  7636. // jQuery or array of any of the above
  7637. _api_register(_child_mth, function (data, klass) {
  7638. var ctx = this.context;
  7639. if (data === undefined) {
  7640. // get
  7641. return ctx.length && this.length ? ctx[0].aoData[this[0]]._details : undefined;
  7642. } else if (data === true) {
  7643. // show
  7644. this.child.show();
  7645. } else if (data === false) {
  7646. // remove
  7647. __details_remove(this);
  7648. } else if (ctx.length && this.length) {
  7649. // set
  7650. __details_add(ctx[0], ctx[0].aoData[this[0]], data, klass);
  7651. }
  7652. return this;
  7653. });
  7654. _api_register([_child_obj + '.show()', _child_mth + '.show()' // only when `child()` was called with parameters (without
  7655. ], function (show) {
  7656. // it returns an object and this method is not executed)
  7657. __details_display(this, true);
  7658. return this;
  7659. });
  7660. _api_register([_child_obj + '.hide()', _child_mth + '.hide()' // only when `child()` was called with parameters (without
  7661. ], function () {
  7662. // it returns an object and this method is not executed)
  7663. __details_display(this, false);
  7664. return this;
  7665. });
  7666. _api_register([_child_obj + '.remove()', _child_mth + '.remove()' // only when `child()` was called with parameters (without
  7667. ], function () {
  7668. // it returns an object and this method is not executed)
  7669. __details_remove(this);
  7670. return this;
  7671. });
  7672. _api_register(_child_obj + '.isShown()', function () {
  7673. var ctx = this.context;
  7674. if (ctx.length && this.length) {
  7675. // _detailsShown as false or undefined will fall through to return false
  7676. return ctx[0].aoData[this[0]]._detailsShow || false;
  7677. }
  7678. return false;
  7679. });
  7680. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  7681. * Columns
  7682. *
  7683. * {integer} - column index (>=0 count from left, <0 count from right)
  7684. * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right)
  7685. * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right)
  7686. * "{string}:name" - column name
  7687. * "{string}" - jQuery selector on column header nodes
  7688. *
  7689. */
  7690. // can be an array of these items, comma separated list, or an array of comma
  7691. // separated lists
  7692. var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
  7693. // r1 and r2 are redundant - but it means that the parameters match for the
  7694. // iterator callback in columns().data()
  7695. var __columnData = function __columnData(settings, column, r1, r2, rows) {
  7696. var a = [];
  7697. for (var row = 0, ien = rows.length; row < ien; row++) {
  7698. a.push(_fnGetCellData(settings, rows[row], column));
  7699. }
  7700. return a;
  7701. };
  7702. var __column_selector = function __column_selector(settings, selector, opts) {
  7703. var columns = settings.aoColumns,
  7704. names = _pluck(columns, 'sName'),
  7705. nodes = _pluck(columns, 'nTh');
  7706. var run = function run(s) {
  7707. var selInt = _intVal(s);
  7708. // Selector - all
  7709. if (s === '') {
  7710. return _range(columns.length);
  7711. }
  7712. // Selector - index
  7713. if (selInt !== null) {
  7714. return [selInt >= 0 ? selInt : // Count from left
  7715. columns.length + selInt // Count from right (+ because its a negative value)
  7716. ];
  7717. }
  7718. // Selector = function
  7719. if (typeof s === 'function') {
  7720. var rows = _selector_row_indexes(settings, opts);
  7721. return $.map(columns, function (col, idx) {
  7722. return s(idx, __columnData(settings, idx, 0, 0, rows), nodes[idx]) ? idx : null;
  7723. });
  7724. }
  7725. // jQuery or string selector
  7726. var match = typeof s === 'string' ? s.match(__re_column_selector) : '';
  7727. if (match) {
  7728. switch (match[2]) {
  7729. case 'visIdx':
  7730. case 'visible':
  7731. var idx = parseInt(match[1], 10);
  7732. // Visible index given, convert to column index
  7733. if (idx < 0) {
  7734. // Counting from the right
  7735. var visColumns = $.map(columns, function (col, i) {
  7736. return col.bVisible ? i : null;
  7737. });
  7738. return [visColumns[visColumns.length + idx]];
  7739. }
  7740. // Counting from the left
  7741. return [_fnVisibleToColumnIndex(settings, idx)];
  7742. case 'name':
  7743. // match by name. `names` is column index complete and in order
  7744. return $.map(names, function (name, i) {
  7745. return name === match[1] ? i : null;
  7746. });
  7747. default:
  7748. return [];
  7749. }
  7750. }
  7751. // Cell in the table body
  7752. if (s.nodeName && s._DT_CellIndex) {
  7753. return [s._DT_CellIndex.column];
  7754. }
  7755. // jQuery selector on the TH elements for the columns
  7756. var jqResult = $(nodes).filter(s).map(function () {
  7757. return $.inArray(this, nodes); // `nodes` is column index complete and in order
  7758. }).toArray();
  7759. if (jqResult.length || !s.nodeName) {
  7760. return jqResult;
  7761. }
  7762. // Otherwise a node which might have a `dt-column` data attribute, or be
  7763. // a child or such an element
  7764. var host = $(s).closest('*[data-dt-column]');
  7765. return host.length ? [host.data('dt-column')] : [];
  7766. };
  7767. return _selector_run('column', selector, run, settings, opts);
  7768. };
  7769. var __setColumnVis = function __setColumnVis(settings, column, vis) {
  7770. var cols = settings.aoColumns,
  7771. col = cols[column],
  7772. data = settings.aoData,
  7773. row,
  7774. cells,
  7775. i,
  7776. ien,
  7777. tr;
  7778. // Get
  7779. if (vis === undefined) {
  7780. return col.bVisible;
  7781. }
  7782. // Set
  7783. // No change
  7784. if (col.bVisible === vis) {
  7785. return;
  7786. }
  7787. if (vis) {
  7788. // Insert column
  7789. // Need to decide if we should use appendChild or insertBefore
  7790. var insertBefore = $.inArray(true, _pluck(cols, 'bVisible'), column + 1);
  7791. for (i = 0, ien = data.length; i < ien; i++) {
  7792. tr = data[i].nTr;
  7793. cells = data[i].anCells;
  7794. if (tr) {
  7795. // insertBefore can act like appendChild if 2nd arg is null
  7796. tr.insertBefore(cells[column], cells[insertBefore] || null);
  7797. }
  7798. }
  7799. } else {
  7800. // Remove column
  7801. $(_pluck(settings.aoData, 'anCells', column)).detach();
  7802. }
  7803. // Common actions
  7804. col.bVisible = vis;
  7805. _fnDrawHead(settings, settings.aoHeader);
  7806. _fnDrawHead(settings, settings.aoFooter);
  7807. _fnSaveState(settings);
  7808. };
  7809. _api_register('columns()', function (selector, opts) {
  7810. // argument shifting
  7811. if (selector === undefined) {
  7812. selector = '';
  7813. } else if ($.isPlainObject(selector)) {
  7814. opts = selector;
  7815. selector = '';
  7816. }
  7817. opts = _selector_opts(opts);
  7818. var inst = this.iterator('table', function (settings) {
  7819. return __column_selector(settings, selector, opts);
  7820. }, 1);
  7821. // Want argument shifting here and in _row_selector?
  7822. inst.selector.cols = selector;
  7823. inst.selector.opts = opts;
  7824. return inst;
  7825. });
  7826. _api_registerPlural('columns().header()', 'column().header()', function (selector, opts) {
  7827. return this.iterator('column', function (settings, column) {
  7828. return settings.aoColumns[column].nTh;
  7829. }, 1);
  7830. });
  7831. _api_registerPlural('columns().footer()', 'column().footer()', function (selector, opts) {
  7832. return this.iterator('column', function (settings, column) {
  7833. return settings.aoColumns[column].nTf;
  7834. }, 1);
  7835. });
  7836. _api_registerPlural('columns().data()', 'column().data()', function () {
  7837. return this.iterator('column-rows', __columnData, 1);
  7838. });
  7839. _api_registerPlural('columns().dataSrc()', 'column().dataSrc()', function () {
  7840. return this.iterator('column', function (settings, column) {
  7841. return settings.aoColumns[column].mData;
  7842. }, 1);
  7843. });
  7844. _api_registerPlural('columns().cache()', 'column().cache()', function (type) {
  7845. return this.iterator('column-rows', function (settings, column, i, j, rows) {
  7846. return _pluck_order(settings.aoData, rows, type === 'search' ? '_aFilterData' : '_aSortData', column);
  7847. }, 1);
  7848. });
  7849. _api_registerPlural('columns().nodes()', 'column().nodes()', function () {
  7850. return this.iterator('column-rows', function (settings, column, i, j, rows) {
  7851. return _pluck_order(settings.aoData, rows, 'anCells', column);
  7852. }, 1);
  7853. });
  7854. _api_registerPlural('columns().visible()', 'column().visible()', function (vis, calc) {
  7855. var ret = this.iterator('column', function (settings, column) {
  7856. if (vis === undefined) {
  7857. return settings.aoColumns[column].bVisible;
  7858. } // else
  7859. __setColumnVis(settings, column, vis);
  7860. });
  7861. // Group the column visibility changes
  7862. if (vis !== undefined) {
  7863. // Second loop once the first is done for events
  7864. this.iterator('column', function (settings, column) {
  7865. _fnCallbackFire(settings, null, 'column-visibility', [settings, column, vis, calc]);
  7866. });
  7867. if (calc === undefined || calc) {
  7868. this.columns.adjust();
  7869. }
  7870. }
  7871. return ret;
  7872. });
  7873. _api_registerPlural('columns().indexes()', 'column().index()', function (type) {
  7874. return this.iterator('column', function (settings, column) {
  7875. return type === 'visible' ? _fnColumnIndexToVisible(settings, column) : column;
  7876. }, 1);
  7877. });
  7878. _api_register('columns.adjust()', function () {
  7879. return this.iterator('table', function (settings) {
  7880. _fnAdjustColumnSizing(settings);
  7881. }, 1);
  7882. });
  7883. _api_register('column.index()', function (type, idx) {
  7884. if (this.context.length !== 0) {
  7885. var ctx = this.context[0];
  7886. if (type === 'fromVisible' || type === 'toData') {
  7887. return _fnVisibleToColumnIndex(ctx, idx);
  7888. } else if (type === 'fromData' || type === 'toVisible') {
  7889. return _fnColumnIndexToVisible(ctx, idx);
  7890. }
  7891. }
  7892. });
  7893. _api_register('column()', function (selector, opts) {
  7894. return _selector_first(this.columns(selector, opts));
  7895. });
  7896. var __cell_selector = function __cell_selector(settings, selector, opts) {
  7897. var data = settings.aoData;
  7898. var rows = _selector_row_indexes(settings, opts);
  7899. var cells = _removeEmpty(_pluck_order(data, rows, 'anCells'));
  7900. var allCells = $([].concat.apply([], cells));
  7901. var row;
  7902. var columns = settings.aoColumns.length;
  7903. var a, i, ien, j, o, host;
  7904. var run = function run(s) {
  7905. var fnSelector = typeof s === 'function';
  7906. if (s === null || s === undefined || fnSelector) {
  7907. // All cells and function selectors
  7908. a = [];
  7909. for (i = 0, ien = rows.length; i < ien; i++) {
  7910. row = rows[i];
  7911. for (j = 0; j < columns; j++) {
  7912. o = {
  7913. row: row,
  7914. column: j
  7915. };
  7916. if (fnSelector) {
  7917. // Selector - function
  7918. host = data[row];
  7919. if (s(o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null)) {
  7920. a.push(o);
  7921. }
  7922. } else {
  7923. // Selector - all
  7924. a.push(o);
  7925. }
  7926. }
  7927. }
  7928. return a;
  7929. }
  7930. // Selector - index
  7931. if ($.isPlainObject(s)) {
  7932. return [s];
  7933. }
  7934. // Selector - jQuery filtered cells
  7935. var jqResult = allCells.filter(s).map(function (i, el) {
  7936. return {// use a new object, in case someone changes the values
  7937. row: el._DT_CellIndex.row,
  7938. column: el._DT_CellIndex.column
  7939. };
  7940. }).toArray();
  7941. if (jqResult.length || !s.nodeName) {
  7942. return jqResult;
  7943. }
  7944. // Otherwise the selector is a node, and there is one last option - the
  7945. // element might be a child of an element which has dt-row and dt-column
  7946. // data attributes
  7947. host = $(s).closest('*[data-dt-row]');
  7948. return host.length ? [{
  7949. row: host.data('dt-row'),
  7950. column: host.data('dt-column')
  7951. }] : [];
  7952. };
  7953. return _selector_run('cell', selector, run, settings, opts);
  7954. };
  7955. _api_register('cells()', function (rowSelector, columnSelector, opts) {
  7956. // Argument shifting
  7957. if ($.isPlainObject(rowSelector)) {
  7958. // Indexes
  7959. if (rowSelector.row === undefined) {
  7960. // Selector options in first parameter
  7961. opts = rowSelector;
  7962. rowSelector = null;
  7963. } else {
  7964. // Cell index objects in first parameter
  7965. opts = columnSelector;
  7966. columnSelector = null;
  7967. }
  7968. }
  7969. if ($.isPlainObject(columnSelector)) {
  7970. opts = columnSelector;
  7971. columnSelector = null;
  7972. }
  7973. // Cell selector
  7974. if (columnSelector === null || columnSelector === undefined) {
  7975. return this.iterator('table', function (settings) {
  7976. return __cell_selector(settings, rowSelector, _selector_opts(opts));
  7977. });
  7978. }
  7979. // Row + column selector
  7980. var columns = this.columns(columnSelector, opts);
  7981. var rows = this.rows(rowSelector, opts);
  7982. var a, i, ien, j, jen;
  7983. var cells = this.iterator('table', function (settings, idx) {
  7984. a = [];
  7985. for (i = 0, ien = rows[idx].length; i < ien; i++) {
  7986. for (j = 0, jen = columns[idx].length; j < jen; j++) {
  7987. a.push({
  7988. row: rows[idx][i],
  7989. column: columns[idx][j]
  7990. });
  7991. }
  7992. }
  7993. return a;
  7994. }, 1);
  7995. $.extend(cells.selector, {
  7996. cols: columnSelector,
  7997. rows: rowSelector,
  7998. opts: opts
  7999. });
  8000. return cells;
  8001. });
  8002. _api_registerPlural('cells().nodes()', 'cell().node()', function () {
  8003. return this.iterator('cell', function (settings, row, column) {
  8004. var data = settings.aoData[row];
  8005. return data && data.anCells ? data.anCells[column] : undefined;
  8006. }, 1);
  8007. });
  8008. _api_register('cells().data()', function () {
  8009. return this.iterator('cell', function (settings, row, column) {
  8010. return _fnGetCellData(settings, row, column);
  8011. }, 1);
  8012. });
  8013. _api_registerPlural('cells().cache()', 'cell().cache()', function (type) {
  8014. type = type === 'search' ? '_aFilterData' : '_aSortData';
  8015. return this.iterator('cell', function (settings, row, column) {
  8016. return settings.aoData[row][type][column];
  8017. }, 1);
  8018. });
  8019. _api_registerPlural('cells().render()', 'cell().render()', function (type) {
  8020. return this.iterator('cell', function (settings, row, column) {
  8021. return _fnGetCellData(settings, row, column, type);
  8022. }, 1);
  8023. });
  8024. _api_registerPlural('cells().indexes()', 'cell().index()', function () {
  8025. return this.iterator('cell', function (settings, row, column) {
  8026. return {
  8027. row: row,
  8028. column: column,
  8029. columnVisible: _fnColumnIndexToVisible(settings, column)
  8030. };
  8031. }, 1);
  8032. });
  8033. _api_registerPlural('cells().invalidate()', 'cell().invalidate()', function (src) {
  8034. return this.iterator('cell', function (settings, row, column) {
  8035. _fnInvalidate(settings, row, src, column);
  8036. });
  8037. });
  8038. _api_register('cell()', function (rowSelector, columnSelector, opts) {
  8039. return _selector_first(this.cells(rowSelector, columnSelector, opts));
  8040. });
  8041. _api_register('cell().data()', function (data) {
  8042. var ctx = this.context;
  8043. var cell = this[0];
  8044. if (data === undefined) {
  8045. // Get
  8046. return ctx.length && cell.length ? _fnGetCellData(ctx[0], cell[0].row, cell[0].column) : undefined;
  8047. }
  8048. // Set
  8049. _fnSetCellData(ctx[0], cell[0].row, cell[0].column, data);
  8050. _fnInvalidate(ctx[0], cell[0].row, 'data', cell[0].column);
  8051. return this;
  8052. });
  8053. /**
  8054. * Get current ordering (sorting) that has been applied to the table.
  8055. *
  8056. * @returns {array} 2D array containing the sorting information for the first
  8057. * table in the current context. Each element in the parent array represents
  8058. * a column being sorted upon (i.e. multi-sorting with two columns would have
  8059. * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
  8060. * the column index that the sorting condition applies to, the second is the
  8061. * direction of the sort (`desc` or `asc`) and, optionally, the third is the
  8062. * index of the sorting order from the `column.sorting` initialisation array.
  8063. */ /**
  8064. * Set the ordering for the table.
  8065. *
  8066. * @param {integer} order Column index to sort upon.
  8067. * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
  8068. * @returns {DataTables.Api} this
  8069. */ /**
  8070. * Set the ordering for the table.
  8071. *
  8072. * @param {array} order 1D array of sorting information to be applied.
  8073. * @param {array} [...] Optional additional sorting conditions
  8074. * @returns {DataTables.Api} this
  8075. */ /**
  8076. * Set the ordering for the table.
  8077. *
  8078. * @param {array} order 2D array of sorting information to be applied.
  8079. * @returns {DataTables.Api} this
  8080. */
  8081. _api_register('order()', function (order, dir) {
  8082. var ctx = this.context;
  8083. if (order === undefined) {
  8084. // get
  8085. return ctx.length !== 0 ? ctx[0].aaSorting : undefined;
  8086. }
  8087. // set
  8088. if (typeof order === 'number') {
  8089. // Simple column / direction passed in
  8090. order = [[order, dir]];
  8091. } else if (order.length && !$.isArray(order[0])) {
  8092. // Arguments passed in (list of 1D arrays)
  8093. order = Array.prototype.slice.call(arguments);
  8094. }
  8095. // otherwise a 2D array was passed in
  8096. return this.iterator('table', function (settings) {
  8097. settings.aaSorting = order.slice();
  8098. });
  8099. });
  8100. /**
  8101. * Attach a sort listener to an element for a given column
  8102. *
  8103. * @param {node|jQuery|string} node Identifier for the element(s) to attach the
  8104. * listener to. This can take the form of a single DOM node, a jQuery
  8105. * collection of nodes or a jQuery selector which will identify the node(s).
  8106. * @param {integer} column the column that a click on this node will sort on
  8107. * @param {function} [callback] callback function when sort is run
  8108. * @returns {DataTables.Api} this
  8109. */
  8110. _api_register('order.listener()', function (node, column, callback) {
  8111. return this.iterator('table', function (settings) {
  8112. _fnSortAttachListener(settings, node, column, callback);
  8113. });
  8114. });
  8115. _api_register('order.fixed()', function (set) {
  8116. if (!set) {
  8117. var ctx = this.context;
  8118. var fixed = ctx.length ? ctx[0].aaSortingFixed : undefined;
  8119. return $.isArray(fixed) ? {pre: fixed} : fixed;
  8120. }
  8121. return this.iterator('table', function (settings) {
  8122. settings.aaSortingFixed = $.extend(true, {}, set);
  8123. });
  8124. });
  8125. // Order by the selected column(s)
  8126. _api_register(['columns().order()', 'column().order()'], function (dir) {
  8127. var that = this;
  8128. return this.iterator('table', function (settings, i) {
  8129. var sort = [];
  8130. $.each(that[i], function (j, col) {
  8131. sort.push([col, dir]);
  8132. });
  8133. settings.aaSorting = sort;
  8134. });
  8135. });
  8136. _api_register('search()', function (input, regex, smart, caseInsen) {
  8137. var ctx = this.context;
  8138. if (input === undefined) {
  8139. // get
  8140. return ctx.length !== 0 ? ctx[0].oPreviousSearch.sSearch : undefined;
  8141. }
  8142. // set
  8143. return this.iterator('table', function (settings) {
  8144. if (!settings.oFeatures.bFilter) {
  8145. return;
  8146. }
  8147. _fnFilterComplete(settings, $.extend({}, settings.oPreviousSearch, {
  8148. "sSearch": input + "",
  8149. "bRegex": regex === null ? false : regex,
  8150. "bSmart": smart === null ? true : smart,
  8151. "bCaseInsensitive": caseInsen === null ? true : caseInsen
  8152. }), 1);
  8153. });
  8154. });
  8155. _api_registerPlural('columns().search()', 'column().search()', function (input, regex, smart, caseInsen) {
  8156. return this.iterator('column', function (settings, column) {
  8157. var preSearch = settings.aoPreSearchCols;
  8158. if (input === undefined) {
  8159. // get
  8160. return preSearch[column].sSearch;
  8161. }
  8162. // set
  8163. if (!settings.oFeatures.bFilter) {
  8164. return;
  8165. }
  8166. $.extend(preSearch[column], {
  8167. "sSearch": input + "",
  8168. "bRegex": regex === null ? false : regex,
  8169. "bSmart": smart === null ? true : smart,
  8170. "bCaseInsensitive": caseInsen === null ? true : caseInsen
  8171. });
  8172. _fnFilterComplete(settings, settings.oPreviousSearch, 1);
  8173. });
  8174. });
  8175. /*
  8176. * State API methods
  8177. */
  8178. _api_register('state()', function () {
  8179. return this.context.length ? this.context[0].oSavedState : null;
  8180. });
  8181. _api_register('state.clear()', function () {
  8182. return this.iterator('table', function (settings) {
  8183. // Save an empty object
  8184. settings.fnStateSaveCallback.call(settings.oInstance, settings, {});
  8185. });
  8186. });
  8187. _api_register('state.loaded()', function () {
  8188. return this.context.length ? this.context[0].oLoadedState : null;
  8189. });
  8190. _api_register('state.save()', function () {
  8191. return this.iterator('table', function (settings) {
  8192. _fnSaveState(settings);
  8193. });
  8194. });
  8195. /**
  8196. * Provide a common method for plug-ins to check the version of DataTables being
  8197. * used, in order to ensure compatibility.
  8198. *
  8199. * @param {string} version Version string to check for, in the format "X.Y.Z".
  8200. * Note that the formats "X" and "X.Y" are also acceptable.
  8201. * @returns {boolean} true if this version of DataTables is greater or equal to
  8202. * the required version, or false if this version of DataTales is not
  8203. * suitable
  8204. * @static
  8205. * @dtopt API-Static
  8206. *
  8207. * @example
  8208. * alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
  8209. */
  8210. DataTable.versionCheck = DataTable.fnVersionCheck = function (version) {
  8211. var aThis = DataTable.version.split('.');
  8212. var aThat = version.split('.');
  8213. var iThis, iThat;
  8214. for (var i = 0, iLen = aThat.length; i < iLen; i++) {
  8215. iThis = parseInt(aThis[i], 10) || 0;
  8216. iThat = parseInt(aThat[i], 10) || 0;
  8217. // Parts are the same, keep comparing
  8218. if (iThis === iThat) {
  8219. continue;
  8220. }
  8221. // Parts are different, return immediately
  8222. return iThis > iThat;
  8223. }
  8224. return true;
  8225. };
  8226. /**
  8227. * Check if a `<table>` node is a DataTable table already or not.
  8228. *
  8229. * @param {node|jquery|string} table Table node, jQuery object or jQuery
  8230. * selector for the table to test. Note that if more than more than one
  8231. * table is passed on, only the first will be checked
  8232. * @returns {boolean} true the table given is a DataTable, or false otherwise
  8233. * @static
  8234. * @dtopt API-Static
  8235. *
  8236. * @example
  8237. * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
  8238. * $('#example').dataTable();
  8239. * }
  8240. */
  8241. DataTable.isDataTable = DataTable.fnIsDataTable = function (table) {
  8242. var t = $(table).get(0);
  8243. var is = false;
  8244. if (table instanceof DataTable.Api) {
  8245. return true;
  8246. }
  8247. $.each(DataTable.settings, function (i, o) {
  8248. var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
  8249. var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
  8250. if (o.nTable === t || head === t || foot === t) {
  8251. is = true;
  8252. }
  8253. });
  8254. return is;
  8255. };
  8256. /**
  8257. * Get all DataTable tables that have been initialised - optionally you can
  8258. * select to get only currently visible tables.
  8259. *
  8260. * @param {boolean} [visible=false] Flag to indicate if you want all (default)
  8261. * or visible tables only.
  8262. * @returns {array} Array of `table` nodes (not DataTable instances) which are
  8263. * DataTables
  8264. * @static
  8265. * @dtopt API-Static
  8266. *
  8267. * @example
  8268. * $.each( $.fn.dataTable.tables(true), function () {
  8269. * $(table).DataTable().columns.adjust();
  8270. * } );
  8271. */
  8272. DataTable.tables = DataTable.fnTables = function (visible) {
  8273. var api = false;
  8274. if ($.isPlainObject(visible)) {
  8275. api = visible.api;
  8276. visible = visible.visible;
  8277. }
  8278. var a = $.map(DataTable.settings, function (o) {
  8279. if (!visible || visible && $(o.nTable).is(':visible')) {
  8280. return o.nTable;
  8281. }
  8282. });
  8283. return api ? new _Api2(a) : a;
  8284. };
  8285. /**
  8286. * Convert from camel case parameters to Hungarian notation. This is made public
  8287. * for the extensions to provide the same ability as DataTables core to accept
  8288. * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
  8289. * parameters.
  8290. *
  8291. * @param {object} src The model object which holds all parameters that can be
  8292. * mapped.
  8293. * @param {object} user The object to convert from camel case to Hungarian.
  8294. * @param {boolean} force When set to `true`, properties which already have a
  8295. * Hungarian value in the `user` object will be overwritten. Otherwise they
  8296. * won't be.
  8297. */
  8298. DataTable.camelToHungarian = _fnCamelToHungarian;
  8299. /**
  8300. *
  8301. */
  8302. _api_register('$()', function (selector, opts) {
  8303. var rows = this.rows(opts).nodes(),
  8304. // Get all rows
  8305. jqRows = $(rows);
  8306. return $([].concat(jqRows.filter(selector).toArray(), jqRows.find(selector).toArray()));
  8307. });
  8308. // jQuery functions to operate on the tables
  8309. $.each(['on', 'one', 'off'], function (i, key) {
  8310. _api_register(key + '()', function () /* event, handler */ {
  8311. var args = Array.prototype.slice.call(arguments);
  8312. // Add the `dt` namespace automatically if it isn't already present
  8313. args[0] = $.map(args[0].split(/\s/), function (e) {
  8314. return !e.match(/\.dt\b/) ? e + '.dt' : e;
  8315. }).join(' ');
  8316. var inst = $(this.tables().nodes());
  8317. inst[key].apply(inst, args);
  8318. return this;
  8319. });
  8320. });
  8321. _api_register('clear()', function () {
  8322. return this.iterator('table', function (settings) {
  8323. _fnClearTable(settings);
  8324. });
  8325. });
  8326. _api_register('settings()', function () {
  8327. return new _Api2(this.context, this.context);
  8328. });
  8329. _api_register('init()', function () {
  8330. var ctx = this.context;
  8331. return ctx.length ? ctx[0].oInit : null;
  8332. });
  8333. _api_register('data()', function () {
  8334. return this.iterator('table', function (settings) {
  8335. return _pluck(settings.aoData, '_aData');
  8336. }).flatten();
  8337. });
  8338. _api_register('destroy()', function (remove) {
  8339. remove = remove || false;
  8340. return this.iterator('table', function (settings) {
  8341. var orig = settings.nTableWrapper.parentNode;
  8342. var classes = settings.oClasses;
  8343. var table = settings.nTable;
  8344. var tbody = settings.nTBody;
  8345. var thead = settings.nTHead;
  8346. var tfoot = settings.nTFoot;
  8347. var jqTable = $(table);
  8348. var jqTbody = $(tbody);
  8349. var jqWrapper = $(settings.nTableWrapper);
  8350. var rows = $.map(settings.aoData, function (r) {
  8351. return r.nTr;
  8352. });
  8353. var i, ien;
  8354. // Flag to note that the table is currently being destroyed - no action
  8355. // should be taken
  8356. settings.bDestroying = true;
  8357. // Fire off the destroy callbacks for plug-ins etc
  8358. _fnCallbackFire(settings, "aoDestroyCallback", "destroy", [settings]);
  8359. // If not being removed from the document, make all columns visible
  8360. if (!remove) {
  8361. new _Api2(settings).columns().visible(true);
  8362. }
  8363. // Blitz all `DT` namespaced events (these are internal events, the
  8364. // lowercase, `dt` events are user subscribed and they are responsible
  8365. // for removing them
  8366. jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
  8367. $(window).off('.DT-' + settings.sInstance);
  8368. // When scrolling we had to break the table up - restore it
  8369. if (table != thead.parentNode) {
  8370. jqTable.children('thead').detach();
  8371. jqTable.append(thead);
  8372. }
  8373. if (tfoot && table != tfoot.parentNode) {
  8374. jqTable.children('tfoot').detach();
  8375. jqTable.append(tfoot);
  8376. }
  8377. settings.aaSorting = [];
  8378. settings.aaSortingFixed = [];
  8379. _fnSortingClasses(settings);
  8380. $(rows).removeClass(settings.asStripeClasses.join(' '));
  8381. $('th, td', thead).removeClass(classes.sSortable + ' ' + classes.sSortableAsc + ' ' + classes.sSortableDesc + ' ' + classes.sSortableNone);
  8382. // Add the TR elements back into the table in their original order
  8383. jqTbody.children().detach();
  8384. jqTbody.append(rows);
  8385. // Remove the DataTables generated nodes, events and classes
  8386. var removedMethod = remove ? 'remove' : 'detach';
  8387. jqTable[removedMethod]();
  8388. jqWrapper[removedMethod]();
  8389. // If we need to reattach the table to the document
  8390. if (!remove && orig) {
  8391. // insertBefore acts like appendChild if !arg[1]
  8392. orig.insertBefore(table, settings.nTableReinsertBefore);
  8393. // Restore the width of the original table - was read from the style property,
  8394. // so we can restore directly to that
  8395. jqTable.css('width', settings.sDestroyWidth).removeClass(classes.sTable);
  8396. // If the were originally stripe classes - then we add them back here.
  8397. // Note this is not fool proof (for example if not all rows had stripe
  8398. // classes - but it's a good effort without getting carried away
  8399. ien = settings.asDestroyStripes.length;
  8400. if (ien) {
  8401. jqTbody.children().each(function (i) {
  8402. $(this).addClass(settings.asDestroyStripes[i % ien]);
  8403. });
  8404. }
  8405. }
  8406. /* Remove the settings object from the settings array */
  8407. var idx = $.inArray(settings, DataTable.settings);
  8408. if (idx !== - 1) {
  8409. DataTable.settings.splice(idx, 1);
  8410. }
  8411. });
  8412. });
  8413. // Add the `every()` method for rows, columns and cells in a compact form
  8414. $.each(['column', 'row', 'cell'], function (i, type) {
  8415. _api_register(type + 's().every()', function (fn) {
  8416. var opts = this.selector.opts;
  8417. var api = this;
  8418. return this.iterator(type, function (settings, arg1, arg2, arg3, arg4) {
  8419. // Rows and columns:
  8420. // arg1 - index
  8421. // arg2 - table counter
  8422. // arg3 - loop counter
  8423. // arg4 - undefined
  8424. // Cells:
  8425. // arg1 - row index
  8426. // arg2 - column index
  8427. // arg3 - table counter
  8428. // arg4 - loop counter
  8429. fn.call(api[type](arg1, type === 'cell' ? arg2 : opts, type === 'cell' ? opts : undefined), arg1, arg2, arg3, arg4);
  8430. });
  8431. });
  8432. });
  8433. // i18n method for extensions to be able to use the language object from the
  8434. // DataTable
  8435. _api_register('i18n()', function (token, def, plural) {
  8436. var ctx = this.context[0];
  8437. var resolved = _fnGetObjectDataFn(token)(ctx.oLanguage);
  8438. if (resolved === undefined) {
  8439. resolved = def;
  8440. }
  8441. if (plural !== undefined && $.isPlainObject(resolved)) {
  8442. resolved = resolved[plural] !== undefined ? resolved[plural] : resolved._;
  8443. }
  8444. return resolved.replace('%d', plural); // nb: plural might be undefined,
  8445. });
  8446. /**
  8447. * Version string for plug-ins to check compatibility. Allowed format is
  8448. * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
  8449. * only for non-release builds. See http://semver.org/ for more information.
  8450. * @member
  8451. * @type string
  8452. * @default Version number
  8453. */
  8454. DataTable.version = "1.10.16";
  8455. /**
  8456. * Private data store, containing all of the settings objects that are
  8457. * created for the tables on a given page.
  8458. *
  8459. * Note that the `DataTable.settings` object is aliased to
  8460. * `jQuery.fn.dataTableExt` through which it may be accessed and
  8461. * manipulated, or `jQuery.fn.dataTable.settings`.
  8462. * @member
  8463. * @type array
  8464. * @default []
  8465. * @private
  8466. */
  8467. DataTable.settings = [];
  8468. /**
  8469. * Object models container, for the various models that DataTables has
  8470. * available to it. These models define the objects that are used to hold
  8471. * the active state and configuration of the table.
  8472. * @namespace
  8473. */
  8474. DataTable.models = {};
  8475. /**
  8476. * Template object for the way in which DataTables holds information about
  8477. * search information for the global filter and individual column filters.
  8478. * @namespace
  8479. */
  8480. DataTable.models.oSearch = {
  8481. /**
  8482. * Flag to indicate if the filtering should be case insensitive or not
  8483. * @type boolean
  8484. * @default true
  8485. */
  8486. "bCaseInsensitive": true,
  8487. /**
  8488. * Applied search term
  8489. * @type string
  8490. * @default <i>Empty string</i>
  8491. */
  8492. "sSearch": "",
  8493. /**
  8494. * Flag to indicate if the search term should be interpreted as a
  8495. * regular expression (true) or not (false) and therefore and special
  8496. * regex characters escaped.
  8497. * @type boolean
  8498. * @default false
  8499. */
  8500. "bRegex": false,
  8501. /**
  8502. * Flag to indicate if DataTables is to use its smart filtering or not.
  8503. * @type boolean
  8504. * @default true
  8505. */
  8506. "bSmart": true
  8507. };
  8508. /**
  8509. * Template object for the way in which DataTables holds information about
  8510. * each individual row. This is the object format used for the settings
  8511. * aoData array.
  8512. * @namespace
  8513. */
  8514. DataTable.models.oRow = {
  8515. /**
  8516. * TR element for the row
  8517. * @type node
  8518. * @default null
  8519. */
  8520. "nTr": null,
  8521. /**
  8522. * Array of TD elements for each row. This is null until the row has been
  8523. * created.
  8524. * @type array nodes
  8525. * @default []
  8526. */
  8527. "anCells": null,
  8528. /**
  8529. * Data object from the original data source for the row. This is either
  8530. * an array if using the traditional form of DataTables, or an object if
  8531. * using mData options. The exact type will depend on the passed in
  8532. * data from the data source, or will be an array if using DOM a data
  8533. * source.
  8534. * @type array|object
  8535. * @default []
  8536. */
  8537. "_aData": [],
  8538. /**
  8539. * Sorting data cache - this array is ostensibly the same length as the
  8540. * number of columns (although each index is generated only as it is
  8541. * needed), and holds the data that is used for sorting each column in the
  8542. * row. We do this cache generation at the start of the sort in order that
  8543. * the formatting of the sort data need be done only once for each cell
  8544. * per sort. This array should not be read from or written to by anything
  8545. * other than the master sorting methods.
  8546. * @type array
  8547. * @default null
  8548. * @private
  8549. */
  8550. "_aSortData": null,
  8551. /**
  8552. * Per cell filtering data cache. As per the sort data cache, used to
  8553. * increase the performance of the filtering in DataTables
  8554. * @type array
  8555. * @default null
  8556. * @private
  8557. */
  8558. "_aFilterData": null,
  8559. /**
  8560. * Filtering data cache. This is the same as the cell filtering cache, but
  8561. * in this case a string rather than an array. This is easily computed with
  8562. * a join on `_aFilterData`, but is provided as a cache so the join isn't
  8563. * needed on every search (memory traded for performance)
  8564. * @type array
  8565. * @default null
  8566. * @private
  8567. */
  8568. "_sFilterRow": null,
  8569. /**
  8570. * Cache of the class name that DataTables has applied to the row, so we
  8571. * can quickly look at this variable rather than needing to do a DOM check
  8572. * on className for the nTr property.
  8573. * @type string
  8574. * @default <i>Empty string</i>
  8575. * @private
  8576. */
  8577. "_sRowStripe": "",
  8578. /**
  8579. * Denote if the original data source was from the DOM, or the data source
  8580. * object. This is used for invalidating data, so DataTables can
  8581. * automatically read data from the original source, unless uninstructed
  8582. * otherwise.
  8583. * @type string
  8584. * @default null
  8585. * @private
  8586. */
  8587. "src": null,
  8588. /**
  8589. * Index in the aoData array. This saves an indexOf lookup when we have the
  8590. * object, but want to know the index
  8591. * @type integer
  8592. * @default -1
  8593. * @private
  8594. */
  8595. "idx": - 1
  8596. };
  8597. /**
  8598. * Template object for the column information object in DataTables. This object
  8599. * is held in the settings aoColumns array and contains all the information that
  8600. * DataTables needs about each individual column.
  8601. *
  8602. * Note that this object is related to {@link DataTable.defaults.column}
  8603. * but this one is the internal data store for DataTables's cache of columns.
  8604. * It should NOT be manipulated outside of DataTables. Any configuration should
  8605. * be done through the initialisation options.
  8606. * @namespace
  8607. */
  8608. DataTable.models.oColumn = {
  8609. /**
  8610. * Column index. This could be worked out on-the-fly with $.inArray, but it
  8611. * is faster to just hold it as a variable
  8612. * @type integer
  8613. * @default null
  8614. */
  8615. "idx": null,
  8616. /**
  8617. * A list of the columns that sorting should occur on when this column
  8618. * is sorted. That this property is an array allows multi-column sorting
  8619. * to be defined for a column (for example first name / last name columns
  8620. * would benefit from this). The values are integers pointing to the
  8621. * columns to be sorted on (typically it will be a single integer pointing
  8622. * at itself, but that doesn't need to be the case).
  8623. * @type array
  8624. */
  8625. "aDataSort": null,
  8626. /**
  8627. * Define the sorting directions that are applied to the column, in sequence
  8628. * as the column is repeatedly sorted upon - i.e. the first value is used
  8629. * as the sorting direction when the column if first sorted (clicked on).
  8630. * Sort it again (click again) and it will move on to the next index.
  8631. * Repeat until loop.
  8632. * @type array
  8633. */
  8634. "asSorting": null,
  8635. /**
  8636. * Flag to indicate if the column is searchable, and thus should be included
  8637. * in the filtering or not.
  8638. * @type boolean
  8639. */
  8640. "bSearchable": null,
  8641. /**
  8642. * Flag to indicate if the column is sortable or not.
  8643. * @type boolean
  8644. */
  8645. "bSortable": null,
  8646. /**
  8647. * Flag to indicate if the column is currently visible in the table or not
  8648. * @type boolean
  8649. */
  8650. "bVisible": null,
  8651. /**
  8652. * Store for manual type assignment using the `column.type` option. This
  8653. * is held in store so we can manipulate the column's `sType` property.
  8654. * @type string
  8655. * @default null
  8656. * @private
  8657. */
  8658. "_sManualType": null,
  8659. /**
  8660. * Flag to indicate if HTML5 data attributes should be used as the data
  8661. * source for filtering or sorting. True is either are.
  8662. * @type boolean
  8663. * @default false
  8664. * @private
  8665. */
  8666. "_bAttrSrc": false,
  8667. /**
  8668. * Developer definable function that is called whenever a cell is created (Ajax source,
  8669. * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  8670. * allowing you to modify the DOM element (add background colour for example) when the
  8671. * element is available.
  8672. * @type function
  8673. * @param {element} nTd The TD node that has been created
  8674. * @param {*} sData The Data for the cell
  8675. * @param {array|object} oData The data for the whole row
  8676. * @param {int} iRow The row index for the aoData data store
  8677. * @default null
  8678. */
  8679. "fnCreatedCell": null,
  8680. /**
  8681. * Function to get data from a cell in a column. You should <b>never</b>
  8682. * access data directly through _aData internally in DataTables - always use
  8683. * the method attached to this property. It allows mData to function as
  8684. * required. This function is automatically assigned by the column
  8685. * initialisation method
  8686. * @type function
  8687. * @param {array|object} oData The data array/object for the array
  8688. * (i.e. aoData[]._aData)
  8689. * @param {string} sSpecific The specific data type you want to get -
  8690. * 'display', 'type' 'filter' 'sort'
  8691. * @returns {*} The data for the cell from the given row's data
  8692. * @default null
  8693. */
  8694. "fnGetData": null,
  8695. /**
  8696. * Function to set data for a cell in the column. You should <b>never</b>
  8697. * set the data directly to _aData internally in DataTables - always use
  8698. * this method. It allows mData to function as required. This function
  8699. * is automatically assigned by the column initialisation method
  8700. * @type function
  8701. * @param {array|object} oData The data array/object for the array
  8702. * (i.e. aoData[]._aData)
  8703. * @param {*} sValue Value to set
  8704. * @default null
  8705. */
  8706. "fnSetData": null,
  8707. /**
  8708. * Property to read the value for the cells in the column from the data
  8709. * source array / object. If null, then the default content is used, if a
  8710. * function is given then the return from the function is used.
  8711. * @type function|int|string|null
  8712. * @default null
  8713. */
  8714. "mData": null,
  8715. /**
  8716. * Partner property to mData which is used (only when defined) to get
  8717. * the data - i.e. it is basically the same as mData, but without the
  8718. * 'set' option, and also the data fed to it is the result from mData.
  8719. * This is the rendering method to match the data method of mData.
  8720. * @type function|int|string|null
  8721. * @default null
  8722. */
  8723. "mRender": null,
  8724. /**
  8725. * Unique header TH/TD element for this column - this is what the sorting
  8726. * listener is attached to (if sorting is enabled.)
  8727. * @type node
  8728. * @default null
  8729. */
  8730. "nTh": null,
  8731. /**
  8732. * Unique footer TH/TD element for this column (if there is one). Not used
  8733. * in DataTables as such, but can be used for plug-ins to reference the
  8734. * footer for each column.
  8735. * @type node
  8736. * @default null
  8737. */
  8738. "nTf": null,
  8739. /**
  8740. * The class to apply to all TD elements in the table's TBODY for the column
  8741. * @type string
  8742. * @default null
  8743. */
  8744. "sClass": null,
  8745. /**
  8746. * When DataTables calculates the column widths to assign to each column,
  8747. * it finds the longest string in each column and then constructs a
  8748. * temporary table and reads the widths from that. The problem with this
  8749. * is that "mmm" is much wider then "iiii", but the latter is a longer
  8750. * string - thus the calculation can go wrong (doing it properly and putting
  8751. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  8752. * a "work around" we provide this option. It will append its value to the
  8753. * text that is found to be the longest string for the column - i.e. padding.
  8754. * @type string
  8755. */
  8756. "sContentPadding": null,
  8757. /**
  8758. * Allows a default value to be given for a column's data, and will be used
  8759. * whenever a null data source is encountered (this can be because mData
  8760. * is set to null, or because the data source itself is null).
  8761. * @type string
  8762. * @default null
  8763. */
  8764. "sDefaultContent": null,
  8765. /**
  8766. * Name for the column, allowing reference to the column by name as well as
  8767. * by index (needs a lookup to work by name).
  8768. * @type string
  8769. */
  8770. "sName": null,
  8771. /**
  8772. * Custom sorting data type - defines which of the available plug-ins in
  8773. * afnSortData the custom sorting will use - if any is defined.
  8774. * @type string
  8775. * @default std
  8776. */
  8777. "sSortDataType": 'std',
  8778. /**
  8779. * Class to be applied to the header element when sorting on this column
  8780. * @type string
  8781. * @default null
  8782. */
  8783. "sSortingClass": null,
  8784. /**
  8785. * Class to be applied to the header element when sorting on this column -
  8786. * when jQuery UI theming is used.
  8787. * @type string
  8788. * @default null
  8789. */
  8790. "sSortingClassJUI": null,
  8791. /**
  8792. * Title of the column - what is seen in the TH element (nTh).
  8793. * @type string
  8794. */
  8795. "sTitle": null,
  8796. /**
  8797. * Column sorting and filtering type
  8798. * @type string
  8799. * @default null
  8800. */
  8801. "sType": null,
  8802. /**
  8803. * Width of the column
  8804. * @type string
  8805. * @default null
  8806. */
  8807. "sWidth": null,
  8808. /**
  8809. * Width of the column when it was first "encountered"
  8810. * @type string
  8811. * @default null
  8812. */
  8813. "sWidthOrig": null
  8814. };
  8815. /*
  8816. * Developer note: The properties of the object below are given in Hungarian
  8817. * notation, that was used as the interface for DataTables prior to v1.10, however
  8818. * from v1.10 onwards the primary interface is camel case. In order to avoid
  8819. * breaking backwards compatibility utterly with this change, the Hungarian
  8820. * version is still, internally the primary interface, but is is not documented
  8821. * - hence the @name tags in each doc comment. This allows a Javascript function
  8822. * to create a map from Hungarian notation to camel case (going the other direction
  8823. * would require each property to be listed, which would at around 3K to the size
  8824. * of DataTables, while this method is about a 0.5K hit.
  8825. *
  8826. * Ultimately this does pave the way for Hungarian notation to be dropped
  8827. * completely, but that is a massive amount of work and will break current
  8828. * installs (therefore is on-hold until v2).
  8829. */
  8830. /**
  8831. * Initialisation options that can be given to DataTables at initialisation
  8832. * time.
  8833. * @namespace
  8834. */
  8835. DataTable.defaults = {
  8836. /**
  8837. * An array of data to use for the table, passed in at initialisation which
  8838. * will be used in preference to any data which is already in the DOM. This is
  8839. * particularly useful for constructing tables purely in Javascript, for
  8840. * example with a custom Ajax call.
  8841. * @type array
  8842. * @default null
  8843. *
  8844. * @dtopt Option
  8845. * @name DataTable.defaults.data
  8846. *
  8847. * @example
  8848. * // Using a 2D array data source
  8849. * $(document).ready( function () {
  8850. * $('#example').dataTable( {
  8851. * "data": [
  8852. * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
  8853. * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
  8854. * ],
  8855. * "columns": [
  8856. * { "title": "Engine" },
  8857. * { "title": "Browser" },
  8858. * { "title": "Platform" },
  8859. * { "title": "Version" },
  8860. * { "title": "Grade" }
  8861. * ]
  8862. * } );
  8863. * } );
  8864. *
  8865. * @example
  8866. * // Using an array of objects as a data source (`data`)
  8867. * $(document).ready( function () {
  8868. * $('#example').dataTable( {
  8869. * "data": [
  8870. * {
  8871. * "engine": "Trident",
  8872. * "browser": "Internet Explorer 4.0",
  8873. * "platform": "Win 95+",
  8874. * "version": 4,
  8875. * "grade": "X"
  8876. * },
  8877. * {
  8878. * "engine": "Trident",
  8879. * "browser": "Internet Explorer 5.0",
  8880. * "platform": "Win 95+",
  8881. * "version": 5,
  8882. * "grade": "C"
  8883. * }
  8884. * ],
  8885. * "columns": [
  8886. * { "title": "Engine", "data": "engine" },
  8887. * { "title": "Browser", "data": "browser" },
  8888. * { "title": "Platform", "data": "platform" },
  8889. * { "title": "Version", "data": "version" },
  8890. * { "title": "Grade", "data": "grade" }
  8891. * ]
  8892. * } );
  8893. * } );
  8894. */
  8895. "aaData": null,
  8896. /**
  8897. * If ordering is enabled, then DataTables will perform a first pass sort on
  8898. * initialisation. You can define which column(s) the sort is performed
  8899. * upon, and the sorting direction, with this variable. The `sorting` array
  8900. * should contain an array for each column to be sorted initially containing
  8901. * the column's index and a direction string ('asc' or 'desc').
  8902. * @type array
  8903. * @default [[0,'asc']]
  8904. *
  8905. * @dtopt Option
  8906. * @name DataTable.defaults.order
  8907. *
  8908. * @example
  8909. * // Sort by 3rd column first, and then 4th column
  8910. * $(document).ready( function() {
  8911. * $('#example').dataTable( {
  8912. * "order": [[2,'asc'], [3,'desc']]
  8913. * } );
  8914. * } );
  8915. *
  8916. * // No initial sorting
  8917. * $(document).ready( function() {
  8918. * $('#example').dataTable( {
  8919. * "order": []
  8920. * } );
  8921. * } );
  8922. */
  8923. "aaSorting": [[0, 'asc']],
  8924. /**
  8925. * This parameter is basically identical to the `sorting` parameter, but
  8926. * cannot be overridden by user interaction with the table. What this means
  8927. * is that you could have a column (visible or hidden) which the sorting
  8928. * will always be forced on first - any sorting after that (from the user)
  8929. * will then be performed as required. This can be useful for grouping rows
  8930. * together.
  8931. * @type array
  8932. * @default null
  8933. *
  8934. * @dtopt Option
  8935. * @name DataTable.defaults.orderFixed
  8936. *
  8937. * @example
  8938. * $(document).ready( function() {
  8939. * $('#example').dataTable( {
  8940. * "orderFixed": [[0,'asc']]
  8941. * } );
  8942. * } )
  8943. */
  8944. "aaSortingFixed": [],
  8945. /**
  8946. * DataTables can be instructed to load data to display in the table from a
  8947. * Ajax source. This option defines how that Ajax call is made and where to.
  8948. *
  8949. * The `ajax` property has three different modes of operation, depending on
  8950. * how it is defined. These are:
  8951. *
  8952. * * `string` - Set the URL from where the data should be loaded from.
  8953. * * `object` - Define properties for `jQuery.ajax`.
  8954. * * `function` - Custom data get function
  8955. *
  8956. * `string`
  8957. * --------
  8958. *
  8959. * As a string, the `ajax` property simply defines the URL from which
  8960. * DataTables will load data.
  8961. *
  8962. * `object`
  8963. * --------
  8964. *
  8965. * As an object, the parameters in the object are passed to
  8966. * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
  8967. * of the Ajax request. DataTables has a number of default parameters which
  8968. * you can override using this option. Please refer to the jQuery
  8969. * documentation for a full description of the options available, although
  8970. * the following parameters provide additional options in DataTables or
  8971. * require special consideration:
  8972. *
  8973. * * `data` - As with jQuery, `data` can be provided as an object, but it
  8974. * can also be used as a function to manipulate the data DataTables sends
  8975. * to the server. The function takes a single parameter, an object of
  8976. * parameters with the values that DataTables has readied for sending. An
  8977. * object may be returned which will be merged into the DataTables
  8978. * defaults, or you can add the items to the object that was passed in and
  8979. * not return anything from the function. This supersedes `fnServerParams`
  8980. * from DataTables 1.9-.
  8981. *
  8982. * * `dataSrc` - By default DataTables will look for the property `data` (or
  8983. * `aaData` for compatibility with DataTables 1.9-) when obtaining data
  8984. * from an Ajax source or for server-side processing - this parameter
  8985. * allows that property to be changed. You can use Javascript dotted
  8986. * object notation to get a data source for multiple levels of nesting, or
  8987. * it my be used as a function. As a function it takes a single parameter,
  8988. * the JSON returned from the server, which can be manipulated as
  8989. * required, with the returned value being that used by DataTables as the
  8990. * data source for the table. This supersedes `sAjaxDataProp` from
  8991. * DataTables 1.9-.
  8992. *
  8993. * * `success` - Should not be overridden it is used internally in
  8994. * DataTables. To manipulate / transform the data returned by the server
  8995. * use `ajax.dataSrc`, or use `ajax` as a function (see below).
  8996. *
  8997. * `function`
  8998. * ----------
  8999. *
  9000. * As a function, making the Ajax call is left up to yourself allowing
  9001. * complete control of the Ajax request. Indeed, if desired, a method other
  9002. * than Ajax could be used to obtain the required data, such as Web storage
  9003. * or an AIR database.
  9004. *
  9005. * The function is given four parameters and no return is required. The
  9006. * parameters are:
  9007. *
  9008. * 1. _object_ - Data to send to the server
  9009. * 2. _function_ - Callback function that must be executed when the required
  9010. * data has been obtained. That data should be passed into the callback
  9011. * as the only parameter
  9012. * 3. _object_ - DataTables settings object for the table
  9013. *
  9014. * Note that this supersedes `fnServerData` from DataTables 1.9-.
  9015. *
  9016. * @type string|object|function
  9017. * @default null
  9018. *
  9019. * @dtopt Option
  9020. * @name DataTable.defaults.ajax
  9021. * @since 1.10.0
  9022. *
  9023. * @example
  9024. * // Get JSON data from a file via Ajax.
  9025. * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
  9026. * $('#example').dataTable( {
  9027. * "ajax": "data.json"
  9028. * } );
  9029. *
  9030. * @example
  9031. * // Get JSON data from a file via Ajax, using `dataSrc` to change
  9032. * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
  9033. * $('#example').dataTable( {
  9034. * "ajax": {
  9035. * "url": "data.json",
  9036. * "dataSrc": "tableData"
  9037. * }
  9038. * } );
  9039. *
  9040. * @example
  9041. * // Get JSON data from a file via Ajax, using `dataSrc` to read data
  9042. * // from a plain array rather than an array in an object
  9043. * $('#example').dataTable( {
  9044. * "ajax": {
  9045. * "url": "data.json",
  9046. * "dataSrc": ""
  9047. * }
  9048. * } );
  9049. *
  9050. * @example
  9051. * // Manipulate the data returned from the server - add a link to data
  9052. * // (note this can, should, be done using `render` for the column - this
  9053. * // is just a simple example of how the data can be manipulated).
  9054. * $('#example').dataTable( {
  9055. * "ajax": {
  9056. * "url": "data.json",
  9057. * "dataSrc": function ( json ) {
  9058. * for ( var i=0, ien=json.length ; i<ien ; i++ ) {
  9059. * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
  9060. * }
  9061. * return json;
  9062. * }
  9063. * }
  9064. * } );
  9065. *
  9066. * @example
  9067. * // Add data to the request
  9068. * $('#example').dataTable( {
  9069. * "ajax": {
  9070. * "url": "data.json",
  9071. * "data": function ( d ) {
  9072. * return {
  9073. * "extra_search": $('#extra').val()
  9074. * };
  9075. * }
  9076. * }
  9077. * } );
  9078. *
  9079. * @example
  9080. * // Send request as POST
  9081. * $('#example').dataTable( {
  9082. * "ajax": {
  9083. * "url": "data.json",
  9084. * "type": "POST"
  9085. * }
  9086. * } );
  9087. *
  9088. * @example
  9089. * // Get the data from localStorage (could interface with a form for
  9090. * // adding, editing and removing rows).
  9091. * $('#example').dataTable( {
  9092. * "ajax": function (data, callback, settings) {
  9093. * callback(
  9094. * JSON.parse( localStorage.getItem('dataTablesData') )
  9095. * );
  9096. * }
  9097. * } );
  9098. */
  9099. "ajax": null,
  9100. /**
  9101. * This parameter allows you to readily specify the entries in the length drop
  9102. * down menu that DataTables shows when pagination is enabled. It can be
  9103. * either a 1D array of options which will be used for both the displayed
  9104. * option and the value, or a 2D array which will use the array in the first
  9105. * position as the value, and the array in the second position as the
  9106. * displayed options (useful for language strings such as 'All').
  9107. *
  9108. * Note that the `pageLength` property will be automatically set to the
  9109. * first value given in this array, unless `pageLength` is also provided.
  9110. * @type array
  9111. * @default [ 10, 25, 50, 100 ]
  9112. *
  9113. * @dtopt Option
  9114. * @name DataTable.defaults.lengthMenu
  9115. *
  9116. * @example
  9117. * $(document).ready( function() {
  9118. * $('#example').dataTable( {
  9119. * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
  9120. * } );
  9121. * } );
  9122. */
  9123. "aLengthMenu": [10, 25, 50, 100],
  9124. /**
  9125. * The `columns` option in the initialisation parameter allows you to define
  9126. * details about the way individual columns behave. For a full list of
  9127. * column options that can be set, please see
  9128. * {@link DataTable.defaults.column}. Note that if you use `columns` to
  9129. * define your columns, you must have an entry in the array for every single
  9130. * column that you have in your table (these can be null if you don't which
  9131. * to specify any options).
  9132. * @member
  9133. *
  9134. * @name DataTable.defaults.column
  9135. */
  9136. "aoColumns": null,
  9137. /**
  9138. * Very similar to `columns`, `columnDefs` allows you to target a specific
  9139. * column, multiple columns, or all columns, using the `targets` property of
  9140. * each object in the array. This allows great flexibility when creating
  9141. * tables, as the `columnDefs` arrays can be of any length, targeting the
  9142. * columns you specifically want. `columnDefs` may use any of the column
  9143. * options available: {@link DataTable.defaults.column}, but it _must_
  9144. * have `targets` defined in each object in the array. Values in the `targets`
  9145. * array may be:
  9146. * <ul>
  9147. * <li>a string - class name will be matched on the TH for the column</li>
  9148. * <li>0 or a positive integer - column index counting from the left</li>
  9149. * <li>a negative integer - column index counting from the right</li>
  9150. * <li>the string "_all" - all columns (i.e. assign a default)</li>
  9151. * </ul>
  9152. * @member
  9153. *
  9154. * @name DataTable.defaults.columnDefs
  9155. */
  9156. "aoColumnDefs": null,
  9157. /**
  9158. * Basically the same as `search`, this parameter defines the individual column
  9159. * filtering state at initialisation time. The array must be of the same size
  9160. * as the number of columns, and each element be an object with the parameters
  9161. * `search` and `escapeRegex` (the latter is optional). 'null' is also
  9162. * accepted and the default will be used.
  9163. * @type array
  9164. * @default []
  9165. *
  9166. * @dtopt Option
  9167. * @name DataTable.defaults.searchCols
  9168. *
  9169. * @example
  9170. * $(document).ready( function() {
  9171. * $('#example').dataTable( {
  9172. * "searchCols": [
  9173. * null,
  9174. * { "search": "My filter" },
  9175. * null,
  9176. * { "search": "^[0-9]", "escapeRegex": false }
  9177. * ]
  9178. * } );
  9179. * } )
  9180. */
  9181. "aoSearchCols": [],
  9182. /**
  9183. * An array of CSS classes that should be applied to displayed rows. This
  9184. * array may be of any length, and DataTables will apply each class
  9185. * sequentially, looping when required.
  9186. * @type array
  9187. * @default null <i>Will take the values determined by the `oClasses.stripe*`
  9188. * options</i>
  9189. *
  9190. * @dtopt Option
  9191. * @name DataTable.defaults.stripeClasses
  9192. *
  9193. * @example
  9194. * $(document).ready( function() {
  9195. * $('#example').dataTable( {
  9196. * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
  9197. * } );
  9198. * } )
  9199. */
  9200. "asStripeClasses": null,
  9201. /**
  9202. * Enable or disable automatic column width calculation. This can be disabled
  9203. * as an optimisation (it takes some time to calculate the widths) if the
  9204. * tables widths are passed in using `columns`.
  9205. * @type boolean
  9206. * @default true
  9207. *
  9208. * @dtopt Features
  9209. * @name DataTable.defaults.autoWidth
  9210. *
  9211. * @example
  9212. * $(document).ready( function () {
  9213. * $('#example').dataTable( {
  9214. * "autoWidth": false
  9215. * } );
  9216. * } );
  9217. */
  9218. "bAutoWidth": true,
  9219. /**
  9220. * Deferred rendering can provide DataTables with a huge speed boost when you
  9221. * are using an Ajax or JS data source for the table. This option, when set to
  9222. * true, will cause DataTables to defer the creation of the table elements for
  9223. * each row until they are needed for a draw - saving a significant amount of
  9224. * time.
  9225. * @type boolean
  9226. * @default false
  9227. *
  9228. * @dtopt Features
  9229. * @name DataTable.defaults.deferRender
  9230. *
  9231. * @example
  9232. * $(document).ready( function() {
  9233. * $('#example').dataTable( {
  9234. * "ajax": "sources/arrays.txt",
  9235. * "deferRender": true
  9236. * } );
  9237. * } );
  9238. */
  9239. "bDeferRender": false,
  9240. /**
  9241. * Replace a DataTable which matches the given selector and replace it with
  9242. * one which has the properties of the new initialisation object passed. If no
  9243. * table matches the selector, then the new DataTable will be constructed as
  9244. * per normal.
  9245. * @type boolean
  9246. * @default false
  9247. *
  9248. * @dtopt Options
  9249. * @name DataTable.defaults.destroy
  9250. *
  9251. * @example
  9252. * $(document).ready( function() {
  9253. * $('#example').dataTable( {
  9254. * "srollY": "200px",
  9255. * "paginate": false
  9256. * } );
  9257. *
  9258. * // Some time later....
  9259. * $('#example').dataTable( {
  9260. * "filter": false,
  9261. * "destroy": true
  9262. * } );
  9263. * } );
  9264. */
  9265. "bDestroy": false,
  9266. /**
  9267. * Enable or disable filtering of data. Filtering in DataTables is "smart" in
  9268. * that it allows the end user to input multiple words (space separated) and
  9269. * will match a row containing those words, even if not in the order that was
  9270. * specified (this allow matching across multiple columns). Note that if you
  9271. * wish to use filtering in DataTables this must remain 'true' - to remove the
  9272. * default filtering input box and retain filtering abilities, please use
  9273. * {@link DataTable.defaults.dom}.
  9274. * @type boolean
  9275. * @default true
  9276. *
  9277. * @dtopt Features
  9278. * @name DataTable.defaults.searching
  9279. *
  9280. * @example
  9281. * $(document).ready( function () {
  9282. * $('#example').dataTable( {
  9283. * "searching": false
  9284. * } );
  9285. * } );
  9286. */
  9287. "bFilter": true,
  9288. /**
  9289. * Enable or disable the table information display. This shows information
  9290. * about the data that is currently visible on the page, including information
  9291. * about filtered data if that action is being performed.
  9292. * @type boolean
  9293. * @default true
  9294. *
  9295. * @dtopt Features
  9296. * @name DataTable.defaults.info
  9297. *
  9298. * @example
  9299. * $(document).ready( function () {
  9300. * $('#example').dataTable( {
  9301. * "info": false
  9302. * } );
  9303. * } );
  9304. */
  9305. "bInfo": true,
  9306. /**
  9307. * Allows the end user to select the size of a formatted page from a select
  9308. * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
  9309. * @type boolean
  9310. * @default true
  9311. *
  9312. * @dtopt Features
  9313. * @name DataTable.defaults.lengthChange
  9314. *
  9315. * @example
  9316. * $(document).ready( function () {
  9317. * $('#example').dataTable( {
  9318. * "lengthChange": false
  9319. * } );
  9320. * } );
  9321. */
  9322. "bLengthChange": true,
  9323. /**
  9324. * Enable or disable pagination.
  9325. * @type boolean
  9326. * @default true
  9327. *
  9328. * @dtopt Features
  9329. * @name DataTable.defaults.paging
  9330. *
  9331. * @example
  9332. * $(document).ready( function () {
  9333. * $('#example').dataTable( {
  9334. * "paging": false
  9335. * } );
  9336. * } );
  9337. */
  9338. "bPaginate": true,
  9339. /**
  9340. * Enable or disable the display of a 'processing' indicator when the table is
  9341. * being processed (e.g. a sort). This is particularly useful for tables with
  9342. * large amounts of data where it can take a noticeable amount of time to sort
  9343. * the entries.
  9344. * @type boolean
  9345. * @default false
  9346. *
  9347. * @dtopt Features
  9348. * @name DataTable.defaults.processing
  9349. *
  9350. * @example
  9351. * $(document).ready( function () {
  9352. * $('#example').dataTable( {
  9353. * "processing": true
  9354. * } );
  9355. * } );
  9356. */
  9357. "bProcessing": false,
  9358. /**
  9359. * Retrieve the DataTables object for the given selector. Note that if the
  9360. * table has already been initialised, this parameter will cause DataTables
  9361. * to simply return the object that has already been set up - it will not take
  9362. * account of any changes you might have made to the initialisation object
  9363. * passed to DataTables (setting this parameter to true is an acknowledgement
  9364. * that you understand this). `destroy` can be used to reinitialise a table if
  9365. * you need.
  9366. * @type boolean
  9367. * @default false
  9368. *
  9369. * @dtopt Options
  9370. * @name DataTable.defaults.retrieve
  9371. *
  9372. * @example
  9373. * $(document).ready( function() {
  9374. * initTable();
  9375. * tableActions();
  9376. * } );
  9377. *
  9378. * function initTable ()
  9379. * {
  9380. * return $('#example').dataTable( {
  9381. * "scrollY": "200px",
  9382. * "paginate": false,
  9383. * "retrieve": true
  9384. * } );
  9385. * }
  9386. *
  9387. * function tableActions ()
  9388. * {
  9389. * var table = initTable();
  9390. * // perform API operations with oTable
  9391. * }
  9392. */
  9393. "bRetrieve": false,
  9394. /**
  9395. * When vertical (y) scrolling is enabled, DataTables will force the height of
  9396. * the table's viewport to the given height at all times (useful for layout).
  9397. * However, this can look odd when filtering data down to a small data set,
  9398. * and the footer is left "floating" further down. This parameter (when
  9399. * enabled) will cause DataTables to collapse the table's viewport down when
  9400. * the result set will fit within the given Y height.
  9401. * @type boolean
  9402. * @default false
  9403. *
  9404. * @dtopt Options
  9405. * @name DataTable.defaults.scrollCollapse
  9406. *
  9407. * @example
  9408. * $(document).ready( function() {
  9409. * $('#example').dataTable( {
  9410. * "scrollY": "200",
  9411. * "scrollCollapse": true
  9412. * } );
  9413. * } );
  9414. */
  9415. "bScrollCollapse": false,
  9416. /**
  9417. * Configure DataTables to use server-side processing. Note that the
  9418. * `ajax` parameter must also be given in order to give DataTables a
  9419. * source to obtain the required data for each draw.
  9420. * @type boolean
  9421. * @default false
  9422. *
  9423. * @dtopt Features
  9424. * @dtopt Server-side
  9425. * @name DataTable.defaults.serverSide
  9426. *
  9427. * @example
  9428. * $(document).ready( function () {
  9429. * $('#example').dataTable( {
  9430. * "serverSide": true,
  9431. * "ajax": "xhr.php"
  9432. * } );
  9433. * } );
  9434. */
  9435. "bServerSide": false,
  9436. /**
  9437. * Enable or disable sorting of columns. Sorting of individual columns can be
  9438. * disabled by the `sortable` option for each column.
  9439. * @type boolean
  9440. * @default true
  9441. *
  9442. * @dtopt Features
  9443. * @name DataTable.defaults.ordering
  9444. *
  9445. * @example
  9446. * $(document).ready( function () {
  9447. * $('#example').dataTable( {
  9448. * "ordering": false
  9449. * } );
  9450. * } );
  9451. */
  9452. "bSort": true,
  9453. /**
  9454. * Enable or display DataTables' ability to sort multiple columns at the
  9455. * same time (activated by shift-click by the user).
  9456. * @type boolean
  9457. * @default true
  9458. *
  9459. * @dtopt Options
  9460. * @name DataTable.defaults.orderMulti
  9461. *
  9462. * @example
  9463. * // Disable multiple column sorting ability
  9464. * $(document).ready( function () {
  9465. * $('#example').dataTable( {
  9466. * "orderMulti": false
  9467. * } );
  9468. * } );
  9469. */
  9470. "bSortMulti": true,
  9471. /**
  9472. * Allows control over whether DataTables should use the top (true) unique
  9473. * cell that is found for a single column, or the bottom (false - default).
  9474. * This is useful when using complex headers.
  9475. * @type boolean
  9476. * @default false
  9477. *
  9478. * @dtopt Options
  9479. * @name DataTable.defaults.orderCellsTop
  9480. *
  9481. * @example
  9482. * $(document).ready( function() {
  9483. * $('#example').dataTable( {
  9484. * "orderCellsTop": true
  9485. * } );
  9486. * } );
  9487. */
  9488. "bSortCellsTop": false,
  9489. /**
  9490. * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
  9491. * `sorting\_3` to the columns which are currently being sorted on. This is
  9492. * presented as a feature switch as it can increase processing time (while
  9493. * classes are removed and added) so for large data sets you might want to
  9494. * turn this off.
  9495. * @type boolean
  9496. * @default true
  9497. *
  9498. * @dtopt Features
  9499. * @name DataTable.defaults.orderClasses
  9500. *
  9501. * @example
  9502. * $(document).ready( function () {
  9503. * $('#example').dataTable( {
  9504. * "orderClasses": false
  9505. * } );
  9506. * } );
  9507. */
  9508. "bSortClasses": true,
  9509. /**
  9510. * Enable or disable state saving. When enabled HTML5 `localStorage` will be
  9511. * used to save table display information such as pagination information,
  9512. * display length, filtering and sorting. As such when the end user reloads
  9513. * the page the display display will match what thy had previously set up.
  9514. *
  9515. * Due to the use of `localStorage` the default state saving is not supported
  9516. * in IE6 or 7. If state saving is required in those browsers, use
  9517. * `stateSaveCallback` to provide a storage solution such as cookies.
  9518. * @type boolean
  9519. * @default false
  9520. *
  9521. * @dtopt Features
  9522. * @name DataTable.defaults.stateSave
  9523. *
  9524. * @example
  9525. * $(document).ready( function () {
  9526. * $('#example').dataTable( {
  9527. * "stateSave": true
  9528. * } );
  9529. * } );
  9530. */
  9531. "bStateSave": false,
  9532. /**
  9533. * This function is called when a TR element is created (and all TD child
  9534. * elements have been inserted), or registered if using a DOM source, allowing
  9535. * manipulation of the TR element (adding classes etc).
  9536. * @type function
  9537. * @param {node} row "TR" element for the current row
  9538. * @param {array} data Raw data array for this row
  9539. * @param {int} dataIndex The index of this row in the internal aoData array
  9540. *
  9541. * @dtopt Callbacks
  9542. * @name DataTable.defaults.createdRow
  9543. *
  9544. * @example
  9545. * $(document).ready( function() {
  9546. * $('#example').dataTable( {
  9547. * "createdRow": function( row, data, dataIndex ) {
  9548. * // Bold the grade for all 'A' grade browsers
  9549. * if ( data[4] == "A" )
  9550. * {
  9551. * $('td:eq(4)', row).html( '<b>A</b>' );
  9552. * }
  9553. * }
  9554. * } );
  9555. * } );
  9556. */
  9557. "fnCreatedRow": null,
  9558. /**
  9559. * This function is called on every 'draw' event, and allows you to
  9560. * dynamically modify any aspect you want about the created DOM.
  9561. * @type function
  9562. * @param {object} settings DataTables settings object
  9563. *
  9564. * @dtopt Callbacks
  9565. * @name DataTable.defaults.drawCallback
  9566. *
  9567. * @example
  9568. * $(document).ready( function() {
  9569. * $('#example').dataTable( {
  9570. * "drawCallback": function( settings ) {
  9571. * alert( 'DataTables has redrawn the table' );
  9572. * }
  9573. * } );
  9574. * } );
  9575. */
  9576. "fnDrawCallback": null,
  9577. /**
  9578. * Identical to fnHeaderCallback() but for the table footer this function
  9579. * allows you to modify the table footer on every 'draw' event.
  9580. * @type function
  9581. * @param {node} foot "TR" element for the footer
  9582. * @param {array} data Full table data (as derived from the original HTML)
  9583. * @param {int} start Index for the current display starting point in the
  9584. * display array
  9585. * @param {int} end Index for the current display ending point in the
  9586. * display array
  9587. * @param {array int} display Index array to translate the visual position
  9588. * to the full data array
  9589. *
  9590. * @dtopt Callbacks
  9591. * @name DataTable.defaults.footerCallback
  9592. *
  9593. * @example
  9594. * $(document).ready( function() {
  9595. * $('#example').dataTable( {
  9596. * "footerCallback": function( tfoot, data, start, end, display ) {
  9597. * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
  9598. * }
  9599. * } );
  9600. * } )
  9601. */
  9602. "fnFooterCallback": null,
  9603. /**
  9604. * When rendering large numbers in the information element for the table
  9605. * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
  9606. * to have a comma separator for the 'thousands' units (e.g. 1 million is
  9607. * rendered as "1,000,000") to help readability for the end user. This
  9608. * function will override the default method DataTables uses.
  9609. * @type function
  9610. * @member
  9611. * @param {int} toFormat number to be formatted
  9612. * @returns {string} formatted string for DataTables to show the number
  9613. *
  9614. * @dtopt Callbacks
  9615. * @name DataTable.defaults.formatNumber
  9616. *
  9617. * @example
  9618. * // Format a number using a single quote for the separator (note that
  9619. * // this can also be done with the language.thousands option)
  9620. * $(document).ready( function() {
  9621. * $('#example').dataTable( {
  9622. * "formatNumber": function ( toFormat ) {
  9623. * return toFormat.toString().replace(
  9624. * /\B(?=(\d{3})+(?!\d))/g, "'"
  9625. * );
  9626. * };
  9627. * } );
  9628. * } );
  9629. */
  9630. "fnFormatNumber": function fnFormatNumber(toFormat) {
  9631. return toFormat.toString().replace(/\B(?=(\d{3})+(?!\d))/g, this.oLanguage.sThousands);
  9632. },
  9633. /**
  9634. * This function is called on every 'draw' event, and allows you to
  9635. * dynamically modify the header row. This can be used to calculate and
  9636. * display useful information about the table.
  9637. * @type function
  9638. * @param {node} head "TR" element for the header
  9639. * @param {array} data Full table data (as derived from the original HTML)
  9640. * @param {int} start Index for the current display starting point in the
  9641. * display array
  9642. * @param {int} end Index for the current display ending point in the
  9643. * display array
  9644. * @param {array int} display Index array to translate the visual position
  9645. * to the full data array
  9646. *
  9647. * @dtopt Callbacks
  9648. * @name DataTable.defaults.headerCallback
  9649. *
  9650. * @example
  9651. * $(document).ready( function() {
  9652. * $('#example').dataTable( {
  9653. * "fheaderCallback": function( head, data, start, end, display ) {
  9654. * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
  9655. * }
  9656. * } );
  9657. * } )
  9658. */
  9659. "fnHeaderCallback": null,
  9660. /**
  9661. * The information element can be used to convey information about the current
  9662. * state of the table. Although the internationalisation options presented by
  9663. * DataTables are quite capable of dealing with most customisations, there may
  9664. * be times where you wish to customise the string further. This callback
  9665. * allows you to do exactly that.
  9666. * @type function
  9667. * @param {object} oSettings DataTables settings object
  9668. * @param {int} start Starting position in data for the draw
  9669. * @param {int} end End position in data for the draw
  9670. * @param {int} max Total number of rows in the table (regardless of
  9671. * filtering)
  9672. * @param {int} total Total number of rows in the data set, after filtering
  9673. * @param {string} pre The string that DataTables has formatted using it's
  9674. * own rules
  9675. * @returns {string} The string to be displayed in the information element.
  9676. *
  9677. * @dtopt Callbacks
  9678. * @name DataTable.defaults.infoCallback
  9679. *
  9680. * @example
  9681. * $('#example').dataTable( {
  9682. * "infoCallback": function( settings, start, end, max, total, pre ) {
  9683. * return start +" to "+ end;
  9684. * }
  9685. * } );
  9686. */
  9687. "fnInfoCallback": null,
  9688. /**
  9689. * Called when the table has been initialised. Normally DataTables will
  9690. * initialise sequentially and there will be no need for this function,
  9691. * however, this does not hold true when using external language information
  9692. * since that is obtained using an async XHR call.
  9693. * @type function
  9694. * @param {object} settings DataTables settings object
  9695. * @param {object} json The JSON object request from the server - only
  9696. * present if client-side Ajax sourced data is used
  9697. *
  9698. * @dtopt Callbacks
  9699. * @name DataTable.defaults.initComplete
  9700. *
  9701. * @example
  9702. * $(document).ready( function() {
  9703. * $('#example').dataTable( {
  9704. * "initComplete": function(settings, json) {
  9705. * alert( 'DataTables has finished its initialisation.' );
  9706. * }
  9707. * } );
  9708. * } )
  9709. */
  9710. "fnInitComplete": null,
  9711. /**
  9712. * Called at the very start of each table draw and can be used to cancel the
  9713. * draw by returning false, any other return (including undefined) results in
  9714. * the full draw occurring).
  9715. * @type function
  9716. * @param {object} settings DataTables settings object
  9717. * @returns {boolean} False will cancel the draw, anything else (including no
  9718. * return) will allow it to complete.
  9719. *
  9720. * @dtopt Callbacks
  9721. * @name DataTable.defaults.preDrawCallback
  9722. *
  9723. * @example
  9724. * $(document).ready( function() {
  9725. * $('#example').dataTable( {
  9726. * "preDrawCallback": function( settings ) {
  9727. * if ( $('#test').val() == 1 ) {
  9728. * return false;
  9729. * }
  9730. * }
  9731. * } );
  9732. * } );
  9733. */
  9734. "fnPreDrawCallback": null,
  9735. /**
  9736. * This function allows you to 'post process' each row after it have been
  9737. * generated for each table draw, but before it is rendered on screen. This
  9738. * function might be used for setting the row class name etc.
  9739. * @type function
  9740. * @param {node} row "TR" element for the current row
  9741. * @param {array} data Raw data array for this row
  9742. * @param {int} displayIndex The display index for the current table draw
  9743. * @param {int} displayIndexFull The index of the data in the full list of
  9744. * rows (after filtering)
  9745. *
  9746. * @dtopt Callbacks
  9747. * @name DataTable.defaults.rowCallback
  9748. *
  9749. * @example
  9750. * $(document).ready( function() {
  9751. * $('#example').dataTable( {
  9752. * "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
  9753. * // Bold the grade for all 'A' grade browsers
  9754. * if ( data[4] == "A" ) {
  9755. * $('td:eq(4)', row).html( '<b>A</b>' );
  9756. * }
  9757. * }
  9758. * } );
  9759. * } );
  9760. */
  9761. "fnRowCallback": null,
  9762. /**
  9763. * __Deprecated__ The functionality provided by this parameter has now been
  9764. * superseded by that provided through `ajax`, which should be used instead.
  9765. *
  9766. * This parameter allows you to override the default function which obtains
  9767. * the data from the server so something more suitable for your application.
  9768. * For example you could use POST data, or pull information from a Gears or
  9769. * AIR database.
  9770. * @type function
  9771. * @member
  9772. * @param {string} source HTTP source to obtain the data from (`ajax`)
  9773. * @param {array} data A key/value pair object containing the data to send
  9774. * to the server
  9775. * @param {function} callback to be called on completion of the data get
  9776. * process that will draw the data on the page.
  9777. * @param {object} settings DataTables settings object
  9778. *
  9779. * @dtopt Callbacks
  9780. * @dtopt Server-side
  9781. * @name DataTable.defaults.serverData
  9782. *
  9783. * @deprecated 1.10. Please use `ajax` for this functionality now.
  9784. */
  9785. "fnServerData": null,
  9786. /**
  9787. * __Deprecated__ The functionality provided by this parameter has now been
  9788. * superseded by that provided through `ajax`, which should be used instead.
  9789. *
  9790. * It is often useful to send extra data to the server when making an Ajax
  9791. * request - for example custom filtering information, and this callback
  9792. * function makes it trivial to send extra information to the server. The
  9793. * passed in parameter is the data set that has been constructed by
  9794. * DataTables, and you can add to this or modify it as you require.
  9795. * @type function
  9796. * @param {array} data Data array (array of objects which are name/value
  9797. * pairs) that has been constructed by DataTables and will be sent to the
  9798. * server. In the case of Ajax sourced data with server-side processing
  9799. * this will be an empty array, for server-side processing there will be a
  9800. * significant number of parameters!
  9801. * @returns {undefined} Ensure that you modify the data array passed in,
  9802. * as this is passed by reference.
  9803. *
  9804. * @dtopt Callbacks
  9805. * @dtopt Server-side
  9806. * @name DataTable.defaults.serverParams
  9807. *
  9808. * @deprecated 1.10. Please use `ajax` for this functionality now.
  9809. */
  9810. "fnServerParams": null,
  9811. /**
  9812. * Load the table state. With this function you can define from where, and how, the
  9813. * state of a table is loaded. By default DataTables will load from `localStorage`
  9814. * but you might wish to use a server-side database or cookies.
  9815. * @type function
  9816. * @member
  9817. * @param {object} settings DataTables settings object
  9818. * @param {object} callback Callback that can be executed when done. It
  9819. * should be passed the loaded state object.
  9820. * @return {object} The DataTables state object to be loaded
  9821. *
  9822. * @dtopt Callbacks
  9823. * @name DataTable.defaults.stateLoadCallback
  9824. *
  9825. * @example
  9826. * $(document).ready( function() {
  9827. * $('#example').dataTable( {
  9828. * "stateSave": true,
  9829. * "stateLoadCallback": function (settings, callback) {
  9830. * $.ajax( {
  9831. * "url": "/state_load",
  9832. * "dataType": "json",
  9833. * "success": function (json) {
  9834. * callback( json );
  9835. * }
  9836. * } );
  9837. * }
  9838. * } );
  9839. * } );
  9840. */
  9841. "fnStateLoadCallback": function fnStateLoadCallback(settings) {
  9842. try {
  9843. return JSON.parse((settings.iStateDuration === - 1 ? sessionStorage : localStorage).getItem('DataTables_' + settings.sInstance + '_' + location.pathname));
  9844. } catch (e) {
  9845. }
  9846. },
  9847. /**
  9848. * Callback which allows modification of the saved state prior to loading that state.
  9849. * This callback is called when the table is loading state from the stored data, but
  9850. * prior to the settings object being modified by the saved state. Note that for
  9851. * plug-in authors, you should use the `stateLoadParams` event to load parameters for
  9852. * a plug-in.
  9853. * @type function
  9854. * @param {object} settings DataTables settings object
  9855. * @param {object} data The state object that is to be loaded
  9856. *
  9857. * @dtopt Callbacks
  9858. * @name DataTable.defaults.stateLoadParams
  9859. *
  9860. * @example
  9861. * // Remove a saved filter, so filtering is never loaded
  9862. * $(document).ready( function() {
  9863. * $('#example').dataTable( {
  9864. * "stateSave": true,
  9865. * "stateLoadParams": function (settings, data) {
  9866. * data.oSearch.sSearch = "";
  9867. * }
  9868. * } );
  9869. * } );
  9870. *
  9871. * @example
  9872. * // Disallow state loading by returning false
  9873. * $(document).ready( function() {
  9874. * $('#example').dataTable( {
  9875. * "stateSave": true,
  9876. * "stateLoadParams": function (settings, data) {
  9877. * return false;
  9878. * }
  9879. * } );
  9880. * } );
  9881. */
  9882. "fnStateLoadParams": null,
  9883. /**
  9884. * Callback that is called when the state has been loaded from the state saving method
  9885. * and the DataTables settings object has been modified as a result of the loaded state.
  9886. * @type function
  9887. * @param {object} settings DataTables settings object
  9888. * @param {object} data The state object that was loaded
  9889. *
  9890. * @dtopt Callbacks
  9891. * @name DataTable.defaults.stateLoaded
  9892. *
  9893. * @example
  9894. * // Show an alert with the filtering value that was saved
  9895. * $(document).ready( function() {
  9896. * $('#example').dataTable( {
  9897. * "stateSave": true,
  9898. * "stateLoaded": function (settings, data) {
  9899. * alert( 'Saved filter was: '+data.oSearch.sSearch );
  9900. * }
  9901. * } );
  9902. * } );
  9903. */
  9904. "fnStateLoaded": null,
  9905. /**
  9906. * Save the table state. This function allows you to define where and how the state
  9907. * information for the table is stored By default DataTables will use `localStorage`
  9908. * but you might wish to use a server-side database or cookies.
  9909. * @type function
  9910. * @member
  9911. * @param {object} settings DataTables settings object
  9912. * @param {object} data The state object to be saved
  9913. *
  9914. * @dtopt Callbacks
  9915. * @name DataTable.defaults.stateSaveCallback
  9916. *
  9917. * @example
  9918. * $(document).ready( function() {
  9919. * $('#example').dataTable( {
  9920. * "stateSave": true,
  9921. * "stateSaveCallback": function (settings, data) {
  9922. * // Send an Ajax request to the server with the state object
  9923. * $.ajax( {
  9924. * "url": "/state_save",
  9925. * "data": data,
  9926. * "dataType": "json",
  9927. * "method": "POST"
  9928. * "success": function () {}
  9929. * } );
  9930. * }
  9931. * } );
  9932. * } );
  9933. */
  9934. "fnStateSaveCallback": function fnStateSaveCallback(settings, data) {
  9935. try {
  9936. (settings.iStateDuration === - 1 ? sessionStorage : localStorage).setItem('DataTables_' + settings.sInstance + '_' + location.pathname, JSON.stringify(data));
  9937. } catch (e) {
  9938. }
  9939. },
  9940. /**
  9941. * Callback which allows modification of the state to be saved. Called when the table
  9942. * has changed state a new state save is required. This method allows modification of
  9943. * the state saving object prior to actually doing the save, including addition or
  9944. * other state properties or modification. Note that for plug-in authors, you should
  9945. * use the `stateSaveParams` event to save parameters for a plug-in.
  9946. * @type function
  9947. * @param {object} settings DataTables settings object
  9948. * @param {object} data The state object to be saved
  9949. *
  9950. * @dtopt Callbacks
  9951. * @name DataTable.defaults.stateSaveParams
  9952. *
  9953. * @example
  9954. * // Remove a saved filter, so filtering is never saved
  9955. * $(document).ready( function() {
  9956. * $('#example').dataTable( {
  9957. * "stateSave": true,
  9958. * "stateSaveParams": function (settings, data) {
  9959. * data.oSearch.sSearch = "";
  9960. * }
  9961. * } );
  9962. * } );
  9963. */
  9964. "fnStateSaveParams": null,
  9965. /**
  9966. * Duration for which the saved state information is considered valid. After this period
  9967. * has elapsed the state will be returned to the default.
  9968. * Value is given in seconds.
  9969. * @type int
  9970. * @default 7200 <i>(2 hours)</i>
  9971. *
  9972. * @dtopt Options
  9973. * @name DataTable.defaults.stateDuration
  9974. *
  9975. * @example
  9976. * $(document).ready( function() {
  9977. * $('#example').dataTable( {
  9978. * "stateDuration": 60*60*24; // 1 day
  9979. * } );
  9980. * } )
  9981. */
  9982. "iStateDuration": 7200,
  9983. /**
  9984. * When enabled DataTables will not make a request to the server for the first
  9985. * page draw - rather it will use the data already on the page (no sorting etc
  9986. * will be applied to it), thus saving on an XHR at load time. `deferLoading`
  9987. * is used to indicate that deferred loading is required, but it is also used
  9988. * to tell DataTables how many records there are in the full table (allowing
  9989. * the information element and pagination to be displayed correctly). In the case
  9990. * where a filtering is applied to the table on initial load, this can be
  9991. * indicated by giving the parameter as an array, where the first element is
  9992. * the number of records available after filtering and the second element is the
  9993. * number of records without filtering (allowing the table information element
  9994. * to be shown correctly).
  9995. * @type int | array
  9996. * @default null
  9997. *
  9998. * @dtopt Options
  9999. * @name DataTable.defaults.deferLoading
  10000. *
  10001. * @example
  10002. * // 57 records available in the table, no filtering applied
  10003. * $(document).ready( function() {
  10004. * $('#example').dataTable( {
  10005. * "serverSide": true,
  10006. * "ajax": "scripts/server_processing.php",
  10007. * "deferLoading": 57
  10008. * } );
  10009. * } );
  10010. *
  10011. * @example
  10012. * // 57 records after filtering, 100 without filtering (an initial filter applied)
  10013. * $(document).ready( function() {
  10014. * $('#example').dataTable( {
  10015. * "serverSide": true,
  10016. * "ajax": "scripts/server_processing.php",
  10017. * "deferLoading": [ 57, 100 ],
  10018. * "search": {
  10019. * "search": "my_filter"
  10020. * }
  10021. * } );
  10022. * } );
  10023. */
  10024. "iDeferLoading": null,
  10025. /**
  10026. * Number of rows to display on a single page when using pagination. If
  10027. * feature enabled (`lengthChange`) then the end user will be able to override
  10028. * this to a custom setting using a pop-up menu.
  10029. * @type int
  10030. * @default 10
  10031. *
  10032. * @dtopt Options
  10033. * @name DataTable.defaults.pageLength
  10034. *
  10035. * @example
  10036. * $(document).ready( function() {
  10037. * $('#example').dataTable( {
  10038. * "pageLength": 50
  10039. * } );
  10040. * } )
  10041. */
  10042. "iDisplayLength": 10,
  10043. /**
  10044. * Define the starting point for data display when using DataTables with
  10045. * pagination. Note that this parameter is the number of records, rather than
  10046. * the page number, so if you have 10 records per page and want to start on
  10047. * the third page, it should be "20".
  10048. * @type int
  10049. * @default 0
  10050. *
  10051. * @dtopt Options
  10052. * @name DataTable.defaults.displayStart
  10053. *
  10054. * @example
  10055. * $(document).ready( function() {
  10056. * $('#example').dataTable( {
  10057. * "displayStart": 20
  10058. * } );
  10059. * } )
  10060. */
  10061. "iDisplayStart": 0,
  10062. /**
  10063. * By default DataTables allows keyboard navigation of the table (sorting, paging,
  10064. * and filtering) by adding a `tabindex` attribute to the required elements. This
  10065. * allows you to tab through the controls and press the enter key to activate them.
  10066. * The tabindex is default 0, meaning that the tab follows the flow of the document.
  10067. * You can overrule this using this parameter if you wish. Use a value of -1 to
  10068. * disable built-in keyboard navigation.
  10069. * @type int
  10070. * @default 0
  10071. *
  10072. * @dtopt Options
  10073. * @name DataTable.defaults.tabIndex
  10074. *
  10075. * @example
  10076. * $(document).ready( function() {
  10077. * $('#example').dataTable( {
  10078. * "tabIndex": 1
  10079. * } );
  10080. * } );
  10081. */
  10082. "iTabIndex": 0,
  10083. /**
  10084. * Classes that DataTables assigns to the various components and features
  10085. * that it adds to the HTML table. This allows classes to be configured
  10086. * during initialisation in addition to through the static
  10087. * {@link DataTable.ext.oStdClasses} object).
  10088. * @namespace
  10089. * @name DataTable.defaults.classes
  10090. */
  10091. "oClasses": {},
  10092. /**
  10093. * All strings that DataTables uses in the user interface that it creates
  10094. * are defined in this object, allowing you to modified them individually or
  10095. * completely replace them all as required.
  10096. * @namespace
  10097. * @name DataTable.defaults.language
  10098. */
  10099. "oLanguage": {
  10100. /**
  10101. * Strings that are used for WAI-ARIA labels and controls only (these are not
  10102. * actually visible on the page, but will be read by screenreaders, and thus
  10103. * must be internationalised as well).
  10104. * @namespace
  10105. * @name DataTable.defaults.language.aria
  10106. */
  10107. "oAria": {
  10108. /**
  10109. * ARIA label that is added to the table headers when the column may be
  10110. * sorted ascending by activing the column (click or return when focused).
  10111. * Note that the column header is prefixed to this string.
  10112. * @type string
  10113. * @default : activate to sort column ascending
  10114. *
  10115. * @dtopt Language
  10116. * @name DataTable.defaults.language.aria.sortAscending
  10117. *
  10118. * @example
  10119. * $(document).ready( function() {
  10120. * $('#example').dataTable( {
  10121. * "language": {
  10122. * "aria": {
  10123. * "sortAscending": " - click/return to sort ascending"
  10124. * }
  10125. * }
  10126. * } );
  10127. * } );
  10128. */
  10129. "sSortAscending": ": activate to sort column ascending",
  10130. /**
  10131. * ARIA label that is added to the table headers when the column may be
  10132. * sorted descending by activing the column (click or return when focused).
  10133. * Note that the column header is prefixed to this string.
  10134. * @type string
  10135. * @default : activate to sort column ascending
  10136. *
  10137. * @dtopt Language
  10138. * @name DataTable.defaults.language.aria.sortDescending
  10139. *
  10140. * @example
  10141. * $(document).ready( function() {
  10142. * $('#example').dataTable( {
  10143. * "language": {
  10144. * "aria": {
  10145. * "sortDescending": " - click/return to sort descending"
  10146. * }
  10147. * }
  10148. * } );
  10149. * } );
  10150. */
  10151. "sSortDescending": ": activate to sort column descending"
  10152. },
  10153. /**
  10154. * Pagination string used by DataTables for the built-in pagination
  10155. * control types.
  10156. * @namespace
  10157. * @name DataTable.defaults.language.paginate
  10158. */
  10159. "oPaginate": {
  10160. /**
  10161. * Text to use when using the 'full_numbers' type of pagination for the
  10162. * button to take the user to the first page.
  10163. * @type string
  10164. * @default First
  10165. *
  10166. * @dtopt Language
  10167. * @name DataTable.defaults.language.paginate.first
  10168. *
  10169. * @example
  10170. * $(document).ready( function() {
  10171. * $('#example').dataTable( {
  10172. * "language": {
  10173. * "paginate": {
  10174. * "first": "First page"
  10175. * }
  10176. * }
  10177. * } );
  10178. * } );
  10179. */
  10180. "sFirst": "First",
  10181. /**
  10182. * Text to use when using the 'full_numbers' type of pagination for the
  10183. * button to take the user to the last page.
  10184. * @type string
  10185. * @default Last
  10186. *
  10187. * @dtopt Language
  10188. * @name DataTable.defaults.language.paginate.last
  10189. *
  10190. * @example
  10191. * $(document).ready( function() {
  10192. * $('#example').dataTable( {
  10193. * "language": {
  10194. * "paginate": {
  10195. * "last": "Last page"
  10196. * }
  10197. * }
  10198. * } );
  10199. * } );
  10200. */
  10201. "sLast": "Last",
  10202. /**
  10203. * Text to use for the 'next' pagination button (to take the user to the
  10204. * next page).
  10205. * @type string
  10206. * @default Next
  10207. *
  10208. * @dtopt Language
  10209. * @name DataTable.defaults.language.paginate.next
  10210. *
  10211. * @example
  10212. * $(document).ready( function() {
  10213. * $('#example').dataTable( {
  10214. * "language": {
  10215. * "paginate": {
  10216. * "next": "Next page"
  10217. * }
  10218. * }
  10219. * } );
  10220. * } );
  10221. */
  10222. "sNext": "Next",
  10223. /**
  10224. * Text to use for the 'previous' pagination button (to take the user to
  10225. * the previous page).
  10226. * @type string
  10227. * @default Previous
  10228. *
  10229. * @dtopt Language
  10230. * @name DataTable.defaults.language.paginate.previous
  10231. *
  10232. * @example
  10233. * $(document).ready( function() {
  10234. * $('#example').dataTable( {
  10235. * "language": {
  10236. * "paginate": {
  10237. * "previous": "Previous page"
  10238. * }
  10239. * }
  10240. * } );
  10241. * } );
  10242. */
  10243. "sPrevious": "Previous"
  10244. },
  10245. /**
  10246. * This string is shown in preference to `zeroRecords` when the table is
  10247. * empty of data (regardless of filtering). Note that this is an optional
  10248. * parameter - if it is not given, the value of `zeroRecords` will be used
  10249. * instead (either the default or given value).
  10250. * @type string
  10251. * @default No data available in table
  10252. *
  10253. * @dtopt Language
  10254. * @name DataTable.defaults.language.emptyTable
  10255. *
  10256. * @example
  10257. * $(document).ready( function() {
  10258. * $('#example').dataTable( {
  10259. * "language": {
  10260. * "emptyTable": "No data available in table"
  10261. * }
  10262. * } );
  10263. * } );
  10264. */
  10265. "sEmptyTable": "No data available in table",
  10266. /**
  10267. * This string gives information to the end user about the information
  10268. * that is current on display on the page. The following tokens can be
  10269. * used in the string and will be dynamically replaced as the table
  10270. * display updates. This tokens can be placed anywhere in the string, or
  10271. * removed as needed by the language requires:
  10272. *
  10273. * * `\_START\_` - Display index of the first record on the current page
  10274. * * `\_END\_` - Display index of the last record on the current page
  10275. * * `\_TOTAL\_` - Number of records in the table after filtering
  10276. * * `\_MAX\_` - Number of records in the table without filtering
  10277. * * `\_PAGE\_` - Current page number
  10278. * * `\_PAGES\_` - Total number of pages of data in the table
  10279. *
  10280. * @type string
  10281. * @default Showing _START_ to _END_ of _TOTAL_ entries
  10282. *
  10283. * @dtopt Language
  10284. * @name DataTable.defaults.language.info
  10285. *
  10286. * @example
  10287. * $(document).ready( function() {
  10288. * $('#example').dataTable( {
  10289. * "language": {
  10290. * "info": "Showing page _PAGE_ of _PAGES_"
  10291. * }
  10292. * } );
  10293. * } );
  10294. */
  10295. "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
  10296. /**
  10297. * Display information string for when the table is empty. Typically the
  10298. * format of this string should match `info`.
  10299. * @type string
  10300. * @default Showing 0 to 0 of 0 entries
  10301. *
  10302. * @dtopt Language
  10303. * @name DataTable.defaults.language.infoEmpty
  10304. *
  10305. * @example
  10306. * $(document).ready( function() {
  10307. * $('#example').dataTable( {
  10308. * "language": {
  10309. * "infoEmpty": "No entries to show"
  10310. * }
  10311. * } );
  10312. * } );
  10313. */
  10314. "sInfoEmpty": "Showing 0 to 0 of 0 entries",
  10315. /**
  10316. * When a user filters the information in a table, this string is appended
  10317. * to the information (`info`) to give an idea of how strong the filtering
  10318. * is. The variable _MAX_ is dynamically updated.
  10319. * @type string
  10320. * @default (filtered from _MAX_ total entries)
  10321. *
  10322. * @dtopt Language
  10323. * @name DataTable.defaults.language.infoFiltered
  10324. *
  10325. * @example
  10326. * $(document).ready( function() {
  10327. * $('#example').dataTable( {
  10328. * "language": {
  10329. * "infoFiltered": " - filtering from _MAX_ records"
  10330. * }
  10331. * } );
  10332. * } );
  10333. */
  10334. "sInfoFiltered": "(filtered from _MAX_ total entries)",
  10335. /**
  10336. * If can be useful to append extra information to the info string at times,
  10337. * and this variable does exactly that. This information will be appended to
  10338. * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
  10339. * being used) at all times.
  10340. * @type string
  10341. * @default <i>Empty string</i>
  10342. *
  10343. * @dtopt Language
  10344. * @name DataTable.defaults.language.infoPostFix
  10345. *
  10346. * @example
  10347. * $(document).ready( function() {
  10348. * $('#example').dataTable( {
  10349. * "language": {
  10350. * "infoPostFix": "All records shown are derived from real information."
  10351. * }
  10352. * } );
  10353. * } );
  10354. */
  10355. "sInfoPostFix": "",
  10356. /**
  10357. * This decimal place operator is a little different from the other
  10358. * language options since DataTables doesn't output floating point
  10359. * numbers, so it won't ever use this for display of a number. Rather,
  10360. * what this parameter does is modify the sort methods of the table so
  10361. * that numbers which are in a format which has a character other than
  10362. * a period (`.`) as a decimal place will be sorted numerically.
  10363. *
  10364. * Note that numbers with different decimal places cannot be shown in
  10365. * the same table and still be sortable, the table must be consistent.
  10366. * However, multiple different tables on the page can use different
  10367. * decimal place characters.
  10368. * @type string
  10369. * @default
  10370. *
  10371. * @dtopt Language
  10372. * @name DataTable.defaults.language.decimal
  10373. *
  10374. * @example
  10375. * $(document).ready( function() {
  10376. * $('#example').dataTable( {
  10377. * "language": {
  10378. * "decimal": ","
  10379. * "thousands": "."
  10380. * }
  10381. * } );
  10382. * } );
  10383. */
  10384. "sDecimal": "",
  10385. /**
  10386. * DataTables has a build in number formatter (`formatNumber`) which is
  10387. * used to format large numbers that are used in the table information.
  10388. * By default a comma is used, but this can be trivially changed to any
  10389. * character you wish with this parameter.
  10390. * @type string
  10391. * @default ,
  10392. *
  10393. * @dtopt Language
  10394. * @name DataTable.defaults.language.thousands
  10395. *
  10396. * @example
  10397. * $(document).ready( function() {
  10398. * $('#example').dataTable( {
  10399. * "language": {
  10400. * "thousands": "'"
  10401. * }
  10402. * } );
  10403. * } );
  10404. */
  10405. "sThousands": ",",
  10406. /**
  10407. * Detail the action that will be taken when the drop down menu for the
  10408. * pagination length option is changed. The '_MENU_' variable is replaced
  10409. * with a default select list of 10, 25, 50 and 100, and can be replaced
  10410. * with a custom select box if required.
  10411. * @type string
  10412. * @default Show _MENU_ entries
  10413. *
  10414. * @dtopt Language
  10415. * @name DataTable.defaults.language.lengthMenu
  10416. *
  10417. * @example
  10418. * // Language change only
  10419. * $(document).ready( function() {
  10420. * $('#example').dataTable( {
  10421. * "language": {
  10422. * "lengthMenu": "Display _MENU_ records"
  10423. * }
  10424. * } );
  10425. * } );
  10426. *
  10427. * @example
  10428. * // Language and options change
  10429. * $(document).ready( function() {
  10430. * $('#example').dataTable( {
  10431. * "language": {
  10432. * "lengthMenu": 'Display <select>'+
  10433. * '<option value="10">10</option>'+
  10434. * '<option value="20">20</option>'+
  10435. * '<option value="30">30</option>'+
  10436. * '<option value="40">40</option>'+
  10437. * '<option value="50">50</option>'+
  10438. * '<option value="-1">All</option>'+
  10439. * '</select> records'
  10440. * }
  10441. * } );
  10442. * } );
  10443. */
  10444. "sLengthMenu": "Show _MENU_ entries",
  10445. /**
  10446. * When using Ajax sourced data and during the first draw when DataTables is
  10447. * gathering the data, this message is shown in an empty row in the table to
  10448. * indicate to the end user the the data is being loaded. Note that this
  10449. * parameter is not used when loading data by server-side processing, just
  10450. * Ajax sourced data with client-side processing.
  10451. * @type string
  10452. * @default Loading...
  10453. *
  10454. * @dtopt Language
  10455. * @name DataTable.defaults.language.loadingRecords
  10456. *
  10457. * @example
  10458. * $(document).ready( function() {
  10459. * $('#example').dataTable( {
  10460. * "language": {
  10461. * "loadingRecords": "Please wait - loading..."
  10462. * }
  10463. * } );
  10464. * } );
  10465. */
  10466. "sLoadingRecords": "Loading...",
  10467. /**
  10468. * Text which is displayed when the table is processing a user action
  10469. * (usually a sort command or similar).
  10470. * @type string
  10471. * @default Processing...
  10472. *
  10473. * @dtopt Language
  10474. * @name DataTable.defaults.language.processing
  10475. *
  10476. * @example
  10477. * $(document).ready( function() {
  10478. * $('#example').dataTable( {
  10479. * "language": {
  10480. * "processing": "DataTables is currently busy"
  10481. * }
  10482. * } );
  10483. * } );
  10484. */
  10485. "sProcessing": "Processing...",
  10486. /**
  10487. * Details the actions that will be taken when the user types into the
  10488. * filtering input text box. The variable "_INPUT_", if used in the string,
  10489. * is replaced with the HTML text box for the filtering input allowing
  10490. * control over where it appears in the string. If "_INPUT_" is not given
  10491. * then the input box is appended to the string automatically.
  10492. * @type string
  10493. * @default Search:
  10494. *
  10495. * @dtopt Language
  10496. * @name DataTable.defaults.language.search
  10497. *
  10498. * @example
  10499. * // Input text box will be appended at the end automatically
  10500. * $(document).ready( function() {
  10501. * $('#example').dataTable( {
  10502. * "language": {
  10503. * "search": "Filter records:"
  10504. * }
  10505. * } );
  10506. * } );
  10507. *
  10508. * @example
  10509. * // Specify where the filter should appear
  10510. * $(document).ready( function() {
  10511. * $('#example').dataTable( {
  10512. * "language": {
  10513. * "search": "Apply filter _INPUT_ to table"
  10514. * }
  10515. * } );
  10516. * } );
  10517. */
  10518. "sSearch": "Search:",
  10519. /**
  10520. * Assign a `placeholder` attribute to the search `input` element
  10521. * @type string
  10522. * @default
  10523. *
  10524. * @dtopt Language
  10525. * @name DataTable.defaults.language.searchPlaceholder
  10526. */
  10527. "sSearchPlaceholder": "",
  10528. /**
  10529. * All of the language information can be stored in a file on the
  10530. * server-side, which DataTables will look up if this parameter is passed.
  10531. * It must store the URL of the language file, which is in a JSON format,
  10532. * and the object has the same properties as the oLanguage object in the
  10533. * initialiser object (i.e. the above parameters). Please refer to one of
  10534. * the example language files to see how this works in action.
  10535. * @type string
  10536. * @default <i>Empty string - i.e. disabled</i>
  10537. *
  10538. * @dtopt Language
  10539. * @name DataTable.defaults.language.url
  10540. *
  10541. * @example
  10542. * $(document).ready( function() {
  10543. * $('#example').dataTable( {
  10544. * "language": {
  10545. * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
  10546. * }
  10547. * } );
  10548. * } );
  10549. */
  10550. "sUrl": "",
  10551. /**
  10552. * Text shown inside the table records when the is no information to be
  10553. * displayed after filtering. `emptyTable` is shown when there is simply no
  10554. * information in the table at all (regardless of filtering).
  10555. * @type string
  10556. * @default No matching records found
  10557. *
  10558. * @dtopt Language
  10559. * @name DataTable.defaults.language.zeroRecords
  10560. *
  10561. * @example
  10562. * $(document).ready( function() {
  10563. * $('#example').dataTable( {
  10564. * "language": {
  10565. * "zeroRecords": "No records to display"
  10566. * }
  10567. * } );
  10568. * } );
  10569. */
  10570. "sZeroRecords": "No matching records found"
  10571. },
  10572. /**
  10573. * This parameter allows you to have define the global filtering state at
  10574. * initialisation time. As an object the `search` parameter must be
  10575. * defined, but all other parameters are optional. When `regex` is true,
  10576. * the search string will be treated as a regular expression, when false
  10577. * (default) it will be treated as a straight string. When `smart`
  10578. * DataTables will use it's smart filtering methods (to word match at
  10579. * any point in the data), when false this will not be done.
  10580. * @namespace
  10581. * @extends DataTable.models.oSearch
  10582. *
  10583. * @dtopt Options
  10584. * @name DataTable.defaults.search
  10585. *
  10586. * @example
  10587. * $(document).ready( function() {
  10588. * $('#example').dataTable( {
  10589. * "search": {"search": "Initial search"}
  10590. * } );
  10591. * } )
  10592. */
  10593. "oSearch": $.extend({}, DataTable.models.oSearch),
  10594. /**
  10595. * __Deprecated__ The functionality provided by this parameter has now been
  10596. * superseded by that provided through `ajax`, which should be used instead.
  10597. *
  10598. * By default DataTables will look for the property `data` (or `aaData` for
  10599. * compatibility with DataTables 1.9-) when obtaining data from an Ajax
  10600. * source or for server-side processing - this parameter allows that
  10601. * property to be changed. You can use Javascript dotted object notation to
  10602. * get a data source for multiple levels of nesting.
  10603. * @type string
  10604. * @default data
  10605. *
  10606. * @dtopt Options
  10607. * @dtopt Server-side
  10608. * @name DataTable.defaults.ajaxDataProp
  10609. *
  10610. * @deprecated 1.10. Please use `ajax` for this functionality now.
  10611. */
  10612. "sAjaxDataProp": "data",
  10613. /**
  10614. * __Deprecated__ The functionality provided by this parameter has now been
  10615. * superseded by that provided through `ajax`, which should be used instead.
  10616. *
  10617. * You can instruct DataTables to load data from an external
  10618. * source using this parameter (use aData if you want to pass data in you
  10619. * already have). Simply provide a url a JSON object can be obtained from.
  10620. * @type string
  10621. * @default null
  10622. *
  10623. * @dtopt Options
  10624. * @dtopt Server-side
  10625. * @name DataTable.defaults.ajaxSource
  10626. *
  10627. * @deprecated 1.10. Please use `ajax` for this functionality now.
  10628. */
  10629. "sAjaxSource": null,
  10630. /**
  10631. * This initialisation variable allows you to specify exactly where in the
  10632. * DOM you want DataTables to inject the various controls it adds to the page
  10633. * (for example you might want the pagination controls at the top of the
  10634. * table). DIV elements (with or without a custom class) can also be added to
  10635. * aid styling. The follow syntax is used:
  10636. * <ul>
  10637. * <li>The following options are allowed:
  10638. * <ul>
  10639. * <li>'l' - Length changing</li>
  10640. * <li>'f' - Filtering input</li>
  10641. * <li>'t' - The table!</li>
  10642. * <li>'i' - Information</li>
  10643. * <li>'p' - Pagination</li>
  10644. * <li>'r' - pRocessing</li>
  10645. * </ul>
  10646. * </li>
  10647. * <li>The following constants are allowed:
  10648. * <ul>
  10649. * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
  10650. * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
  10651. * </ul>
  10652. * </li>
  10653. * <li>The following syntax is expected:
  10654. * <ul>
  10655. * <li>'&lt;' and '&gt;' - div elements</li>
  10656. * <li>'&lt;"class" and '&gt;' - div with a class</li>
  10657. * <li>'&lt;"#id" and '&gt;' - div with an ID</li>
  10658. * </ul>
  10659. * </li>
  10660. * <li>Examples:
  10661. * <ul>
  10662. * <li>'&lt;"wrapper"flipt&gt;'</li>
  10663. * <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
  10664. * </ul>
  10665. * </li>
  10666. * </ul>
  10667. * @type string
  10668. * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
  10669. * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
  10670. *
  10671. * @dtopt Options
  10672. * @name DataTable.defaults.dom
  10673. *
  10674. * @example
  10675. * $(document).ready( function() {
  10676. * $('#example').dataTable( {
  10677. * "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
  10678. * } );
  10679. * } );
  10680. */
  10681. "sDom": "lfrtip",
  10682. /**
  10683. * Search delay option. This will throttle full table searches that use the
  10684. * DataTables provided search input element (it does not effect calls to
  10685. * `dt-api search()`, providing a delay before the search is made.
  10686. * @type integer
  10687. * @default 0
  10688. *
  10689. * @dtopt Options
  10690. * @name DataTable.defaults.searchDelay
  10691. *
  10692. * @example
  10693. * $(document).ready( function() {
  10694. * $('#example').dataTable( {
  10695. * "searchDelay": 200
  10696. * } );
  10697. * } )
  10698. */
  10699. "searchDelay": null,
  10700. /**
  10701. * DataTables features six different built-in options for the buttons to
  10702. * display for pagination control:
  10703. *
  10704. * * `numbers` - Page number buttons only
  10705. * * `simple` - 'Previous' and 'Next' buttons only
  10706. * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
  10707. * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
  10708. * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
  10709. * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
  10710. *
  10711. * Further methods can be added using {@link DataTable.ext.oPagination}.
  10712. * @type string
  10713. * @default simple_numbers
  10714. *
  10715. * @dtopt Options
  10716. * @name DataTable.defaults.pagingType
  10717. *
  10718. * @example
  10719. * $(document).ready( function() {
  10720. * $('#example').dataTable( {
  10721. * "pagingType": "full_numbers"
  10722. * } );
  10723. * } )
  10724. */
  10725. "sPaginationType": "simple_numbers",
  10726. /**
  10727. * Enable horizontal scrolling. When a table is too wide to fit into a
  10728. * certain layout, or you have a large number of columns in the table, you
  10729. * can enable x-scrolling to show the table in a viewport, which can be
  10730. * scrolled. This property can be `true` which will allow the table to
  10731. * scroll horizontally when needed, or any CSS unit, or a number (in which
  10732. * case it will be treated as a pixel measurement). Setting as simply `true`
  10733. * is recommended.
  10734. * @type boolean|string
  10735. * @default <i>blank string - i.e. disabled</i>
  10736. *
  10737. * @dtopt Features
  10738. * @name DataTable.defaults.scrollX
  10739. *
  10740. * @example
  10741. * $(document).ready( function() {
  10742. * $('#example').dataTable( {
  10743. * "scrollX": true,
  10744. * "scrollCollapse": true
  10745. * } );
  10746. * } );
  10747. */
  10748. "sScrollX": "",
  10749. /**
  10750. * This property can be used to force a DataTable to use more width than it
  10751. * might otherwise do when x-scrolling is enabled. For example if you have a
  10752. * table which requires to be well spaced, this parameter is useful for
  10753. * "over-sizing" the table, and thus forcing scrolling. This property can by
  10754. * any CSS unit, or a number (in which case it will be treated as a pixel
  10755. * measurement).
  10756. * @type string
  10757. * @default <i>blank string - i.e. disabled</i>
  10758. *
  10759. * @dtopt Options
  10760. * @name DataTable.defaults.scrollXInner
  10761. *
  10762. * @example
  10763. * $(document).ready( function() {
  10764. * $('#example').dataTable( {
  10765. * "scrollX": "100%",
  10766. * "scrollXInner": "110%"
  10767. * } );
  10768. * } );
  10769. */
  10770. "sScrollXInner": "",
  10771. /**
  10772. * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
  10773. * to the given height, and enable scrolling for any data which overflows the
  10774. * current viewport. This can be used as an alternative to paging to display
  10775. * a lot of data in a small area (although paging and scrolling can both be
  10776. * enabled at the same time). This property can be any CSS unit, or a number
  10777. * (in which case it will be treated as a pixel measurement).
  10778. * @type string
  10779. * @default <i>blank string - i.e. disabled</i>
  10780. *
  10781. * @dtopt Features
  10782. * @name DataTable.defaults.scrollY
  10783. *
  10784. * @example
  10785. * $(document).ready( function() {
  10786. * $('#example').dataTable( {
  10787. * "scrollY": "200px",
  10788. * "paginate": false
  10789. * } );
  10790. * } );
  10791. */
  10792. "sScrollY": "",
  10793. /**
  10794. * __Deprecated__ The functionality provided by this parameter has now been
  10795. * superseded by that provided through `ajax`, which should be used instead.
  10796. *
  10797. * Set the HTTP method that is used to make the Ajax call for server-side
  10798. * processing or Ajax sourced data.
  10799. * @type string
  10800. * @default GET
  10801. *
  10802. * @dtopt Options
  10803. * @dtopt Server-side
  10804. * @name DataTable.defaults.serverMethod
  10805. *
  10806. * @deprecated 1.10. Please use `ajax` for this functionality now.
  10807. */
  10808. "sServerMethod": "GET",
  10809. /**
  10810. * DataTables makes use of renderers when displaying HTML elements for
  10811. * a table. These renderers can be added or modified by plug-ins to
  10812. * generate suitable mark-up for a site. For example the Bootstrap
  10813. * integration plug-in for DataTables uses a paging button renderer to
  10814. * display pagination buttons in the mark-up required by Bootstrap.
  10815. *
  10816. * For further information about the renderers available see
  10817. * DataTable.ext.renderer
  10818. * @type string|object
  10819. * @default null
  10820. *
  10821. * @name DataTable.defaults.renderer
  10822. *
  10823. */
  10824. "renderer": null,
  10825. /**
  10826. * Set the data property name that DataTables should use to get a row's id
  10827. * to set as the `id` property in the node.
  10828. * @type string
  10829. * @default DT_RowId
  10830. *
  10831. * @name DataTable.defaults.rowId
  10832. */
  10833. "rowId": "DT_RowId"
  10834. };
  10835. _fnHungarianMap(DataTable.defaults);
  10836. /*
  10837. * Developer note - See note in model.defaults.js about the use of Hungarian
  10838. * notation and camel case.
  10839. */
  10840. /**
  10841. * Column options that can be given to DataTables at initialisation time.
  10842. * @namespace
  10843. */
  10844. DataTable.defaults.column = {
  10845. /**
  10846. * Define which column(s) an order will occur on for this column. This
  10847. * allows a column's ordering to take multiple columns into account when
  10848. * doing a sort or use the data from a different column. For example first
  10849. * name / last name columns make sense to do a multi-column sort over the
  10850. * two columns.
  10851. * @type array|int
  10852. * @default null <i>Takes the value of the column index automatically</i>
  10853. *
  10854. * @name DataTable.defaults.column.orderData
  10855. * @dtopt Columns
  10856. *
  10857. * @example
  10858. * // Using `columnDefs`
  10859. * $(document).ready( function() {
  10860. * $('#example').dataTable( {
  10861. * "columnDefs": [
  10862. * { "orderData": [ 0, 1 ], "targets": [ 0 ] },
  10863. * { "orderData": [ 1, 0 ], "targets": [ 1 ] },
  10864. * { "orderData": 2, "targets": [ 2 ] }
  10865. * ]
  10866. * } );
  10867. * } );
  10868. *
  10869. * @example
  10870. * // Using `columns`
  10871. * $(document).ready( function() {
  10872. * $('#example').dataTable( {
  10873. * "columns": [
  10874. * { "orderData": [ 0, 1 ] },
  10875. * { "orderData": [ 1, 0 ] },
  10876. * { "orderData": 2 },
  10877. * null,
  10878. * null
  10879. * ]
  10880. * } );
  10881. * } );
  10882. */
  10883. "aDataSort": null,
  10884. "iDataSort": - 1,
  10885. /**
  10886. * You can control the default ordering direction, and even alter the
  10887. * behaviour of the sort handler (i.e. only allow ascending ordering etc)
  10888. * using this parameter.
  10889. * @type array
  10890. * @default [ 'asc', 'desc' ]
  10891. *
  10892. * @name DataTable.defaults.column.orderSequence
  10893. * @dtopt Columns
  10894. *
  10895. * @example
  10896. * // Using `columnDefs`
  10897. * $(document).ready( function() {
  10898. * $('#example').dataTable( {
  10899. * "columnDefs": [
  10900. * { "orderSequence": [ "asc" ], "targets": [ 1 ] },
  10901. * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
  10902. * { "orderSequence": [ "desc" ], "targets": [ 3 ] }
  10903. * ]
  10904. * } );
  10905. * } );
  10906. *
  10907. * @example
  10908. * // Using `columns`
  10909. * $(document).ready( function() {
  10910. * $('#example').dataTable( {
  10911. * "columns": [
  10912. * null,
  10913. * { "orderSequence": [ "asc" ] },
  10914. * { "orderSequence": [ "desc", "asc", "asc" ] },
  10915. * { "orderSequence": [ "desc" ] },
  10916. * null
  10917. * ]
  10918. * } );
  10919. * } );
  10920. */
  10921. "asSorting": ['asc', 'desc'],
  10922. /**
  10923. * Enable or disable filtering on the data in this column.
  10924. * @type boolean
  10925. * @default true
  10926. *
  10927. * @name DataTable.defaults.column.searchable
  10928. * @dtopt Columns
  10929. *
  10930. * @example
  10931. * // Using `columnDefs`
  10932. * $(document).ready( function() {
  10933. * $('#example').dataTable( {
  10934. * "columnDefs": [
  10935. * { "searchable": false, "targets": [ 0 ] }
  10936. * ] } );
  10937. * } );
  10938. *
  10939. * @example
  10940. * // Using `columns`
  10941. * $(document).ready( function() {
  10942. * $('#example').dataTable( {
  10943. * "columns": [
  10944. * { "searchable": false },
  10945. * null,
  10946. * null,
  10947. * null,
  10948. * null
  10949. * ] } );
  10950. * } );
  10951. */
  10952. "bSearchable": true,
  10953. /**
  10954. * Enable or disable ordering on this column.
  10955. * @type boolean
  10956. * @default true
  10957. *
  10958. * @name DataTable.defaults.column.orderable
  10959. * @dtopt Columns
  10960. *
  10961. * @example
  10962. * // Using `columnDefs`
  10963. * $(document).ready( function() {
  10964. * $('#example').dataTable( {
  10965. * "columnDefs": [
  10966. * { "orderable": false, "targets": [ 0 ] }
  10967. * ] } );
  10968. * } );
  10969. *
  10970. * @example
  10971. * // Using `columns`
  10972. * $(document).ready( function() {
  10973. * $('#example').dataTable( {
  10974. * "columns": [
  10975. * { "orderable": false },
  10976. * null,
  10977. * null,
  10978. * null,
  10979. * null
  10980. * ] } );
  10981. * } );
  10982. */
  10983. "bSortable": true,
  10984. /**
  10985. * Enable or disable the display of this column.
  10986. * @type boolean
  10987. * @default true
  10988. *
  10989. * @name DataTable.defaults.column.visible
  10990. * @dtopt Columns
  10991. *
  10992. * @example
  10993. * // Using `columnDefs`
  10994. * $(document).ready( function() {
  10995. * $('#example').dataTable( {
  10996. * "columnDefs": [
  10997. * { "visible": false, "targets": [ 0 ] }
  10998. * ] } );
  10999. * } );
  11000. *
  11001. * @example
  11002. * // Using `columns`
  11003. * $(document).ready( function() {
  11004. * $('#example').dataTable( {
  11005. * "columns": [
  11006. * { "visible": false },
  11007. * null,
  11008. * null,
  11009. * null,
  11010. * null
  11011. * ] } );
  11012. * } );
  11013. */
  11014. "bVisible": true,
  11015. /**
  11016. * Developer definable function that is called whenever a cell is created (Ajax source,
  11017. * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  11018. * allowing you to modify the DOM element (add background colour for example) when the
  11019. * element is available.
  11020. * @type function
  11021. * @param {element} td The TD node that has been created
  11022. * @param {*} cellData The Data for the cell
  11023. * @param {array|object} rowData The data for the whole row
  11024. * @param {int} row The row index for the aoData data store
  11025. * @param {int} col The column index for aoColumns
  11026. *
  11027. * @name DataTable.defaults.column.createdCell
  11028. * @dtopt Columns
  11029. *
  11030. * @example
  11031. * $(document).ready( function() {
  11032. * $('#example').dataTable( {
  11033. * "columnDefs": [ {
  11034. * "targets": [3],
  11035. * "createdCell": function (td, cellData, rowData, row, col) {
  11036. * if ( cellData == "1.7" ) {
  11037. * $(td).css('color', 'blue')
  11038. * }
  11039. * }
  11040. * } ]
  11041. * });
  11042. * } );
  11043. */
  11044. "fnCreatedCell": null,
  11045. /**
  11046. * This parameter has been replaced by `data` in DataTables to ensure naming
  11047. * consistency. `dataProp` can still be used, as there is backwards
  11048. * compatibility in DataTables for this option, but it is strongly
  11049. * recommended that you use `data` in preference to `dataProp`.
  11050. * @name DataTable.defaults.column.dataProp
  11051. */
  11052. /**
  11053. * This property can be used to read data from any data source property,
  11054. * including deeply nested objects / properties. `data` can be given in a
  11055. * number of different ways which effect its behaviour:
  11056. *
  11057. * * `integer` - treated as an array index for the data source. This is the
  11058. * default that DataTables uses (incrementally increased for each column).
  11059. * * `string` - read an object property from the data source. There are
  11060. * three 'special' options that can be used in the string to alter how
  11061. * DataTables reads the data from the source object:
  11062. * * `.` - Dotted Javascript notation. Just as you use a `.` in
  11063. * Javascript to read from nested objects, so to can the options
  11064. * specified in `data`. For example: `browser.version` or
  11065. * `browser.name`. If your object parameter name contains a period, use
  11066. * `\\` to escape it - i.e. `first\\.name`.
  11067. * * `[]` - Array notation. DataTables can automatically combine data
  11068. * from and array source, joining the data with the characters provided
  11069. * between the two brackets. For example: `name[, ]` would provide a
  11070. * comma-space separated list from the source array. If no characters
  11071. * are provided between the brackets, the original array source is
  11072. * returned.
  11073. * * `()` - Function notation. Adding `()` to the end of a parameter will
  11074. * execute a function of the name given. For example: `browser()` for a
  11075. * simple function on the data source, `browser.version()` for a
  11076. * function in a nested property or even `browser().version` to get an
  11077. * object property if the function called returns an object. Note that
  11078. * function notation is recommended for use in `render` rather than
  11079. * `data` as it is much simpler to use as a renderer.
  11080. * * `null` - use the original data source for the row rather than plucking
  11081. * data directly from it. This action has effects on two other
  11082. * initialisation options:
  11083. * * `defaultContent` - When null is given as the `data` option and
  11084. * `defaultContent` is specified for the column, the value defined by
  11085. * `defaultContent` will be used for the cell.
  11086. * * `render` - When null is used for the `data` option and the `render`
  11087. * option is specified for the column, the whole data source for the
  11088. * row is used for the renderer.
  11089. * * `function` - the function given will be executed whenever DataTables
  11090. * needs to set or get the data for a cell in the column. The function
  11091. * takes three parameters:
  11092. * * Parameters:
  11093. * * `{array|object}` The data source for the row
  11094. * * `{string}` The type call data requested - this will be 'set' when
  11095. * setting data or 'filter', 'display', 'type', 'sort' or undefined
  11096. * when gathering data. Note that when `undefined` is given for the
  11097. * type DataTables expects to get the raw data for the object back<
  11098. * * `{*}` Data to set when the second parameter is 'set'.
  11099. * * Return:
  11100. * * The return value from the function is not required when 'set' is
  11101. * the type of call, but otherwise the return is what will be used
  11102. * for the data requested.
  11103. *
  11104. * Note that `data` is a getter and setter option. If you just require
  11105. * formatting of data for output, you will likely want to use `render` which
  11106. * is simply a getter and thus simpler to use.
  11107. *
  11108. * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
  11109. * name change reflects the flexibility of this property and is consistent
  11110. * with the naming of mRender. If 'mDataProp' is given, then it will still
  11111. * be used by DataTables, as it automatically maps the old name to the new
  11112. * if required.
  11113. *
  11114. * @type string|int|function|null
  11115. * @default null <i>Use automatically calculated column index</i>
  11116. *
  11117. * @name DataTable.defaults.column.data
  11118. * @dtopt Columns
  11119. *
  11120. * @example
  11121. * // Read table data from objects
  11122. * // JSON structure for each row:
  11123. * // {
  11124. * // "engine": {value},
  11125. * // "browser": {value},
  11126. * // "platform": {value},
  11127. * // "version": {value},
  11128. * // "grade": {value}
  11129. * // }
  11130. * $(document).ready( function() {
  11131. * $('#example').dataTable( {
  11132. * "ajaxSource": "sources/objects.txt",
  11133. * "columns": [
  11134. * { "data": "engine" },
  11135. * { "data": "browser" },
  11136. * { "data": "platform" },
  11137. * { "data": "version" },
  11138. * { "data": "grade" }
  11139. * ]
  11140. * } );
  11141. * } );
  11142. *
  11143. * @example
  11144. * // Read information from deeply nested objects
  11145. * // JSON structure for each row:
  11146. * // {
  11147. * // "engine": {value},
  11148. * // "browser": {value},
  11149. * // "platform": {
  11150. * // "inner": {value}
  11151. * // },
  11152. * // "details": [
  11153. * // {value}, {value}
  11154. * // ]
  11155. * // }
  11156. * $(document).ready( function() {
  11157. * $('#example').dataTable( {
  11158. * "ajaxSource": "sources/deep.txt",
  11159. * "columns": [
  11160. * { "data": "engine" },
  11161. * { "data": "browser" },
  11162. * { "data": "platform.inner" },
  11163. * { "data": "platform.details.0" },
  11164. * { "data": "platform.details.1" }
  11165. * ]
  11166. * } );
  11167. * } );
  11168. *
  11169. * @example
  11170. * // Using `data` as a function to provide different information for
  11171. * // sorting, filtering and display. In this case, currency (price)
  11172. * $(document).ready( function() {
  11173. * $('#example').dataTable( {
  11174. * "columnDefs": [ {
  11175. * "targets": [ 0 ],
  11176. * "data": function ( source, type, val ) {
  11177. * if (type === 'set') {
  11178. * source.price = val;
  11179. * // Store the computed dislay and filter values for efficiency
  11180. * source.price_display = val=="" ? "" : "$"+numberFormat(val);
  11181. * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
  11182. * return;
  11183. * }
  11184. * else if (type === 'display') {
  11185. * return source.price_display;
  11186. * }
  11187. * else if (type === 'filter') {
  11188. * return source.price_filter;
  11189. * }
  11190. * // 'sort', 'type' and undefined all just use the integer
  11191. * return source.price;
  11192. * }
  11193. * } ]
  11194. * } );
  11195. * } );
  11196. *
  11197. * @example
  11198. * // Using default content
  11199. * $(document).ready( function() {
  11200. * $('#example').dataTable( {
  11201. * "columnDefs": [ {
  11202. * "targets": [ 0 ],
  11203. * "data": null,
  11204. * "defaultContent": "Click to edit"
  11205. * } ]
  11206. * } );
  11207. * } );
  11208. *
  11209. * @example
  11210. * // Using array notation - outputting a list from an array
  11211. * $(document).ready( function() {
  11212. * $('#example').dataTable( {
  11213. * "columnDefs": [ {
  11214. * "targets": [ 0 ],
  11215. * "data": "name[, ]"
  11216. * } ]
  11217. * } );
  11218. * } );
  11219. *
  11220. */
  11221. "mData": null,
  11222. /**
  11223. * This property is the rendering partner to `data` and it is suggested that
  11224. * when you want to manipulate data for display (including filtering,
  11225. * sorting etc) without altering the underlying data for the table, use this
  11226. * property. `render` can be considered to be the the read only companion to
  11227. * `data` which is read / write (then as such more complex). Like `data`
  11228. * this option can be given in a number of different ways to effect its
  11229. * behaviour:
  11230. *
  11231. * * `integer` - treated as an array index for the data source. This is the
  11232. * default that DataTables uses (incrementally increased for each column).
  11233. * * `string` - read an object property from the data source. There are
  11234. * three 'special' options that can be used in the string to alter how
  11235. * DataTables reads the data from the source object:
  11236. * * `.` - Dotted Javascript notation. Just as you use a `.` in
  11237. * Javascript to read from nested objects, so to can the options
  11238. * specified in `data`. For example: `browser.version` or
  11239. * `browser.name`. If your object parameter name contains a period, use
  11240. * `\\` to escape it - i.e. `first\\.name`.
  11241. * * `[]` - Array notation. DataTables can automatically combine data
  11242. * from and array source, joining the data with the characters provided
  11243. * between the two brackets. For example: `name[, ]` would provide a
  11244. * comma-space separated list from the source array. If no characters
  11245. * are provided between the brackets, the original array source is
  11246. * returned.
  11247. * * `()` - Function notation. Adding `()` to the end of a parameter will
  11248. * execute a function of the name given. For example: `browser()` for a
  11249. * simple function on the data source, `browser.version()` for a
  11250. * function in a nested property or even `browser().version` to get an
  11251. * object property if the function called returns an object.
  11252. * * `object` - use different data for the different data types requested by
  11253. * DataTables ('filter', 'display', 'type' or 'sort'). The property names
  11254. * of the object is the data type the property refers to and the value can
  11255. * defined using an integer, string or function using the same rules as
  11256. * `render` normally does. Note that an `_` option _must_ be specified.
  11257. * This is the default value to use if you haven't specified a value for
  11258. * the data type requested by DataTables.
  11259. * * `function` - the function given will be executed whenever DataTables
  11260. * needs to set or get the data for a cell in the column. The function
  11261. * takes three parameters:
  11262. * * Parameters:
  11263. * * {array|object} The data source for the row (based on `data`)
  11264. * * {string} The type call data requested - this will be 'filter',
  11265. * 'display', 'type' or 'sort'.
  11266. * * {array|object} The full data source for the row (not based on
  11267. * `data`)
  11268. * * Return:
  11269. * * The return value from the function is what will be used for the
  11270. * data requested.
  11271. *
  11272. * @type string|int|function|object|null
  11273. * @default null Use the data source value.
  11274. *
  11275. * @name DataTable.defaults.column.render
  11276. * @dtopt Columns
  11277. *
  11278. * @example
  11279. * // Create a comma separated list from an array of objects
  11280. * $(document).ready( function() {
  11281. * $('#example').dataTable( {
  11282. * "ajaxSource": "sources/deep.txt",
  11283. * "columns": [
  11284. * { "data": "engine" },
  11285. * { "data": "browser" },
  11286. * {
  11287. * "data": "platform",
  11288. * "render": "[, ].name"
  11289. * }
  11290. * ]
  11291. * } );
  11292. * } );
  11293. *
  11294. * @example
  11295. * // Execute a function to obtain data
  11296. * $(document).ready( function() {
  11297. * $('#example').dataTable( {
  11298. * "columnDefs": [ {
  11299. * "targets": [ 0 ],
  11300. * "data": null, // Use the full data source object for the renderer's source
  11301. * "render": "browserName()"
  11302. * } ]
  11303. * } );
  11304. * } );
  11305. *
  11306. * @example
  11307. * // As an object, extracting different data for the different types
  11308. * // This would be used with a data source such as:
  11309. * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
  11310. * // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
  11311. * // (which has both forms) is used for filtering for if a user inputs either format, while
  11312. * // the formatted phone number is the one that is shown in the table.
  11313. * $(document).ready( function() {
  11314. * $('#example').dataTable( {
  11315. * "columnDefs": [ {
  11316. * "targets": [ 0 ],
  11317. * "data": null, // Use the full data source object for the renderer's source
  11318. * "render": {
  11319. * "_": "phone",
  11320. * "filter": "phone_filter",
  11321. * "display": "phone_display"
  11322. * }
  11323. * } ]
  11324. * } );
  11325. * } );
  11326. *
  11327. * @example
  11328. * // Use as a function to create a link from the data source
  11329. * $(document).ready( function() {
  11330. * $('#example').dataTable( {
  11331. * "columnDefs": [ {
  11332. * "targets": [ 0 ],
  11333. * "data": "download_link",
  11334. * "render": function ( data, type, full ) {
  11335. * return '<a href="'+data+'">Download</a>';
  11336. * }
  11337. * } ]
  11338. * } );
  11339. * } );
  11340. */
  11341. "mRender": null,
  11342. /**
  11343. * Change the cell type created for the column - either TD cells or TH cells. This
  11344. * can be useful as TH cells have semantic meaning in the table body, allowing them
  11345. * to act as a header for a row (you may wish to add scope='row' to the TH elements).
  11346. * @type string
  11347. * @default td
  11348. *
  11349. * @name DataTable.defaults.column.cellType
  11350. * @dtopt Columns
  11351. *
  11352. * @example
  11353. * // Make the first column use TH cells
  11354. * $(document).ready( function() {
  11355. * $('#example').dataTable( {
  11356. * "columnDefs": [ {
  11357. * "targets": [ 0 ],
  11358. * "cellType": "th"
  11359. * } ]
  11360. * } );
  11361. * } );
  11362. */
  11363. "sCellType": "td",
  11364. /**
  11365. * Class to give to each cell in this column.
  11366. * @type string
  11367. * @default <i>Empty string</i>
  11368. *
  11369. * @name DataTable.defaults.column.class
  11370. * @dtopt Columns
  11371. *
  11372. * @example
  11373. * // Using `columnDefs`
  11374. * $(document).ready( function() {
  11375. * $('#example').dataTable( {
  11376. * "columnDefs": [
  11377. * { "class": "my_class", "targets": [ 0 ] }
  11378. * ]
  11379. * } );
  11380. * } );
  11381. *
  11382. * @example
  11383. * // Using `columns`
  11384. * $(document).ready( function() {
  11385. * $('#example').dataTable( {
  11386. * "columns": [
  11387. * { "class": "my_class" },
  11388. * null,
  11389. * null,
  11390. * null,
  11391. * null
  11392. * ]
  11393. * } );
  11394. * } );
  11395. */
  11396. "sClass": "",
  11397. /**
  11398. * When DataTables calculates the column widths to assign to each column,
  11399. * it finds the longest string in each column and then constructs a
  11400. * temporary table and reads the widths from that. The problem with this
  11401. * is that "mmm" is much wider then "iiii", but the latter is a longer
  11402. * string - thus the calculation can go wrong (doing it properly and putting
  11403. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  11404. * a "work around" we provide this option. It will append its value to the
  11405. * text that is found to be the longest string for the column - i.e. padding.
  11406. * Generally you shouldn't need this!
  11407. * @type string
  11408. * @default <i>Empty string<i>
  11409. *
  11410. * @name DataTable.defaults.column.contentPadding
  11411. * @dtopt Columns
  11412. *
  11413. * @example
  11414. * // Using `columns`
  11415. * $(document).ready( function() {
  11416. * $('#example').dataTable( {
  11417. * "columns": [
  11418. * null,
  11419. * null,
  11420. * null,
  11421. * {
  11422. * "contentPadding": "mmm"
  11423. * }
  11424. * ]
  11425. * } );
  11426. * } );
  11427. */
  11428. "sContentPadding": "",
  11429. /**
  11430. * Allows a default value to be given for a column's data, and will be used
  11431. * whenever a null data source is encountered (this can be because `data`
  11432. * is set to null, or because the data source itself is null).
  11433. * @type string
  11434. * @default null
  11435. *
  11436. * @name DataTable.defaults.column.defaultContent
  11437. * @dtopt Columns
  11438. *
  11439. * @example
  11440. * // Using `columnDefs`
  11441. * $(document).ready( function() {
  11442. * $('#example').dataTable( {
  11443. * "columnDefs": [
  11444. * {
  11445. * "data": null,
  11446. * "defaultContent": "Edit",
  11447. * "targets": [ -1 ]
  11448. * }
  11449. * ]
  11450. * } );
  11451. * } );
  11452. *
  11453. * @example
  11454. * // Using `columns`
  11455. * $(document).ready( function() {
  11456. * $('#example').dataTable( {
  11457. * "columns": [
  11458. * null,
  11459. * null,
  11460. * null,
  11461. * {
  11462. * "data": null,
  11463. * "defaultContent": "Edit"
  11464. * }
  11465. * ]
  11466. * } );
  11467. * } );
  11468. */
  11469. "sDefaultContent": null,
  11470. /**
  11471. * This parameter is only used in DataTables' server-side processing. It can
  11472. * be exceptionally useful to know what columns are being displayed on the
  11473. * client side, and to map these to database fields. When defined, the names
  11474. * also allow DataTables to reorder information from the server if it comes
  11475. * back in an unexpected order (i.e. if you switch your columns around on the
  11476. * client-side, your server-side code does not also need updating).
  11477. * @type string
  11478. * @default <i>Empty string</i>
  11479. *
  11480. * @name DataTable.defaults.column.name
  11481. * @dtopt Columns
  11482. *
  11483. * @example
  11484. * // Using `columnDefs`
  11485. * $(document).ready( function() {
  11486. * $('#example').dataTable( {
  11487. * "columnDefs": [
  11488. * { "name": "engine", "targets": [ 0 ] },
  11489. * { "name": "browser", "targets": [ 1 ] },
  11490. * { "name": "platform", "targets": [ 2 ] },
  11491. * { "name": "version", "targets": [ 3 ] },
  11492. * { "name": "grade", "targets": [ 4 ] }
  11493. * ]
  11494. * } );
  11495. * } );
  11496. *
  11497. * @example
  11498. * // Using `columns`
  11499. * $(document).ready( function() {
  11500. * $('#example').dataTable( {
  11501. * "columns": [
  11502. * { "name": "engine" },
  11503. * { "name": "browser" },
  11504. * { "name": "platform" },
  11505. * { "name": "version" },
  11506. * { "name": "grade" }
  11507. * ]
  11508. * } );
  11509. * } );
  11510. */
  11511. "sName": "",
  11512. /**
  11513. * Defines a data source type for the ordering which can be used to read
  11514. * real-time information from the table (updating the internally cached
  11515. * version) prior to ordering. This allows ordering to occur on user
  11516. * editable elements such as form inputs.
  11517. * @type string
  11518. * @default std
  11519. *
  11520. * @name DataTable.defaults.column.orderDataType
  11521. * @dtopt Columns
  11522. *
  11523. * @example
  11524. * // Using `columnDefs`
  11525. * $(document).ready( function() {
  11526. * $('#example').dataTable( {
  11527. * "columnDefs": [
  11528. * { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
  11529. * { "type": "numeric", "targets": [ 3 ] },
  11530. * { "orderDataType": "dom-select", "targets": [ 4 ] },
  11531. * { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
  11532. * ]
  11533. * } );
  11534. * } );
  11535. *
  11536. * @example
  11537. * // Using `columns`
  11538. * $(document).ready( function() {
  11539. * $('#example').dataTable( {
  11540. * "columns": [
  11541. * null,
  11542. * null,
  11543. * { "orderDataType": "dom-text" },
  11544. * { "orderDataType": "dom-text", "type": "numeric" },
  11545. * { "orderDataType": "dom-select" },
  11546. * { "orderDataType": "dom-checkbox" }
  11547. * ]
  11548. * } );
  11549. * } );
  11550. */
  11551. "sSortDataType": "std",
  11552. /**
  11553. * The title of this column.
  11554. * @type string
  11555. * @default null <i>Derived from the 'TH' value for this column in the
  11556. * original HTML table.</i>
  11557. *
  11558. * @name DataTable.defaults.column.title
  11559. * @dtopt Columns
  11560. *
  11561. * @example
  11562. * // Using `columnDefs`
  11563. * $(document).ready( function() {
  11564. * $('#example').dataTable( {
  11565. * "columnDefs": [
  11566. * { "title": "My column title", "targets": [ 0 ] }
  11567. * ]
  11568. * } );
  11569. * } );
  11570. *
  11571. * @example
  11572. * // Using `columns`
  11573. * $(document).ready( function() {
  11574. * $('#example').dataTable( {
  11575. * "columns": [
  11576. * { "title": "My column title" },
  11577. * null,
  11578. * null,
  11579. * null,
  11580. * null
  11581. * ]
  11582. * } );
  11583. * } );
  11584. */
  11585. "sTitle": null,
  11586. /**
  11587. * The type allows you to specify how the data for this column will be
  11588. * ordered. Four types (string, numeric, date and html (which will strip
  11589. * HTML tags before ordering)) are currently available. Note that only date
  11590. * formats understood by Javascript's Date() object will be accepted as type
  11591. * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
  11592. * 'numeric', 'date' or 'html' (by default). Further types can be adding
  11593. * through plug-ins.
  11594. * @type string
  11595. * @default null <i>Auto-detected from raw data</i>
  11596. *
  11597. * @name DataTable.defaults.column.type
  11598. * @dtopt Columns
  11599. *
  11600. * @example
  11601. * // Using `columnDefs`
  11602. * $(document).ready( function() {
  11603. * $('#example').dataTable( {
  11604. * "columnDefs": [
  11605. * { "type": "html", "targets": [ 0 ] }
  11606. * ]
  11607. * } );
  11608. * } );
  11609. *
  11610. * @example
  11611. * // Using `columns`
  11612. * $(document).ready( function() {
  11613. * $('#example').dataTable( {
  11614. * "columns": [
  11615. * { "type": "html" },
  11616. * null,
  11617. * null,
  11618. * null,
  11619. * null
  11620. * ]
  11621. * } );
  11622. * } );
  11623. */
  11624. "sType": null,
  11625. /**
  11626. * Defining the width of the column, this parameter may take any CSS value
  11627. * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
  11628. * been given a specific width through this interface ensuring that the table
  11629. * remains readable.
  11630. * @type string
  11631. * @default null <i>Automatic</i>
  11632. *
  11633. * @name DataTable.defaults.column.width
  11634. * @dtopt Columns
  11635. *
  11636. * @example
  11637. * // Using `columnDefs`
  11638. * $(document).ready( function() {
  11639. * $('#example').dataTable( {
  11640. * "columnDefs": [
  11641. * { "width": "20%", "targets": [ 0 ] }
  11642. * ]
  11643. * } );
  11644. * } );
  11645. *
  11646. * @example
  11647. * // Using `columns`
  11648. * $(document).ready( function() {
  11649. * $('#example').dataTable( {
  11650. * "columns": [
  11651. * { "width": "20%" },
  11652. * null,
  11653. * null,
  11654. * null,
  11655. * null
  11656. * ]
  11657. * } );
  11658. * } );
  11659. */
  11660. "sWidth": null
  11661. };
  11662. _fnHungarianMap(DataTable.defaults.column);
  11663. /**
  11664. * DataTables settings object - this holds all the information needed for a
  11665. * given table, including configuration, data and current application of the
  11666. * table options. DataTables does not have a single instance for each DataTable
  11667. * with the settings attached to that instance, but rather instances of the
  11668. * DataTable "class" are created on-the-fly as needed (typically by a
  11669. * $().dataTable() call) and the settings object is then applied to that
  11670. * instance.
  11671. *
  11672. * Note that this object is related to {@link DataTable.defaults} but this
  11673. * one is the internal data store for DataTables's cache of columns. It should
  11674. * NOT be manipulated outside of DataTables. Any configuration should be done
  11675. * through the initialisation options.
  11676. * @namespace
  11677. * @todo Really should attach the settings object to individual instances so we
  11678. * don't need to create new instances on each $().dataTable() call (if the
  11679. * table already exists). It would also save passing oSettings around and
  11680. * into every single function. However, this is a very significant
  11681. * architecture change for DataTables and will almost certainly break
  11682. * backwards compatibility with older installations. This is something that
  11683. * will be done in 2.0.
  11684. */
  11685. DataTable.models.oSettings = {
  11686. /**
  11687. * Primary features of DataTables and their enablement state.
  11688. * @namespace
  11689. */
  11690. "oFeatures": {
  11691. /**
  11692. * Flag to say if DataTables should automatically try to calculate the
  11693. * optimum table and columns widths (true) or not (false).
  11694. * Note that this parameter will be set by the initialisation routine. To
  11695. * set a default use {@link DataTable.defaults}.
  11696. * @type boolean
  11697. */
  11698. "bAutoWidth": null,
  11699. /**
  11700. * Delay the creation of TR and TD elements until they are actually
  11701. * needed by a driven page draw. This can give a significant speed
  11702. * increase for Ajax source and Javascript source data, but makes no
  11703. * difference at all fro DOM and server-side processing tables.
  11704. * Note that this parameter will be set by the initialisation routine. To
  11705. * set a default use {@link DataTable.defaults}.
  11706. * @type boolean
  11707. */
  11708. "bDeferRender": null,
  11709. /**
  11710. * Enable filtering on the table or not. Note that if this is disabled
  11711. * then there is no filtering at all on the table, including fnFilter.
  11712. * To just remove the filtering input use sDom and remove the 'f' option.
  11713. * Note that this parameter will be set by the initialisation routine. To
  11714. * set a default use {@link DataTable.defaults}.
  11715. * @type boolean
  11716. */
  11717. "bFilter": null,
  11718. /**
  11719. * Table information element (the 'Showing x of y records' div) enable
  11720. * flag.
  11721. * Note that this parameter will be set by the initialisation routine. To
  11722. * set a default use {@link DataTable.defaults}.
  11723. * @type boolean
  11724. */
  11725. "bInfo": null,
  11726. /**
  11727. * Present a user control allowing the end user to change the page size
  11728. * when pagination is enabled.
  11729. * Note that this parameter will be set by the initialisation routine. To
  11730. * set a default use {@link DataTable.defaults}.
  11731. * @type boolean
  11732. */
  11733. "bLengthChange": null,
  11734. /**
  11735. * Pagination enabled or not. Note that if this is disabled then length
  11736. * changing must also be disabled.
  11737. * Note that this parameter will be set by the initialisation routine. To
  11738. * set a default use {@link DataTable.defaults}.
  11739. * @type boolean
  11740. */
  11741. "bPaginate": null,
  11742. /**
  11743. * Processing indicator enable flag whenever DataTables is enacting a
  11744. * user request - typically an Ajax request for server-side processing.
  11745. * Note that this parameter will be set by the initialisation routine. To
  11746. * set a default use {@link DataTable.defaults}.
  11747. * @type boolean
  11748. */
  11749. "bProcessing": null,
  11750. /**
  11751. * Server-side processing enabled flag - when enabled DataTables will
  11752. * get all data from the server for every draw - there is no filtering,
  11753. * sorting or paging done on the client-side.
  11754. * Note that this parameter will be set by the initialisation routine. To
  11755. * set a default use {@link DataTable.defaults}.
  11756. * @type boolean
  11757. */
  11758. "bServerSide": null,
  11759. /**
  11760. * Sorting enablement flag.
  11761. * Note that this parameter will be set by the initialisation routine. To
  11762. * set a default use {@link DataTable.defaults}.
  11763. * @type boolean
  11764. */
  11765. "bSort": null,
  11766. /**
  11767. * Multi-column sorting
  11768. * Note that this parameter will be set by the initialisation routine. To
  11769. * set a default use {@link DataTable.defaults}.
  11770. * @type boolean
  11771. */
  11772. "bSortMulti": null,
  11773. /**
  11774. * Apply a class to the columns which are being sorted to provide a
  11775. * visual highlight or not. This can slow things down when enabled since
  11776. * there is a lot of DOM interaction.
  11777. * Note that this parameter will be set by the initialisation routine. To
  11778. * set a default use {@link DataTable.defaults}.
  11779. * @type boolean
  11780. */
  11781. "bSortClasses": null,
  11782. /**
  11783. * State saving enablement flag.
  11784. * Note that this parameter will be set by the initialisation routine. To
  11785. * set a default use {@link DataTable.defaults}.
  11786. * @type boolean
  11787. */
  11788. "bStateSave": null
  11789. },
  11790. /**
  11791. * Scrolling settings for a table.
  11792. * @namespace
  11793. */
  11794. "oScroll": {
  11795. /**
  11796. * When the table is shorter in height than sScrollY, collapse the
  11797. * table container down to the height of the table (when true).
  11798. * Note that this parameter will be set by the initialisation routine. To
  11799. * set a default use {@link DataTable.defaults}.
  11800. * @type boolean
  11801. */
  11802. "bCollapse": null,
  11803. /**
  11804. * Width of the scrollbar for the web-browser's platform. Calculated
  11805. * during table initialisation.
  11806. * @type int
  11807. * @default 0
  11808. */
  11809. "iBarWidth": 0,
  11810. /**
  11811. * Viewport width for horizontal scrolling. Horizontal scrolling is
  11812. * disabled if an empty string.
  11813. * Note that this parameter will be set by the initialisation routine. To
  11814. * set a default use {@link DataTable.defaults}.
  11815. * @type string
  11816. */
  11817. "sX": null,
  11818. /**
  11819. * Width to expand the table to when using x-scrolling. Typically you
  11820. * should not need to use this.
  11821. * Note that this parameter will be set by the initialisation routine. To
  11822. * set a default use {@link DataTable.defaults}.
  11823. * @type string
  11824. * @deprecated
  11825. */
  11826. "sXInner": null,
  11827. /**
  11828. * Viewport height for vertical scrolling. Vertical scrolling is disabled
  11829. * if an empty string.
  11830. * Note that this parameter will be set by the initialisation routine. To
  11831. * set a default use {@link DataTable.defaults}.
  11832. * @type string
  11833. */
  11834. "sY": null
  11835. },
  11836. /**
  11837. * Language information for the table.
  11838. * @namespace
  11839. * @extends DataTable.defaults.oLanguage
  11840. */
  11841. "oLanguage": {
  11842. /**
  11843. * Information callback function. See
  11844. * {@link DataTable.defaults.fnInfoCallback}
  11845. * @type function
  11846. * @default null
  11847. */
  11848. "fnInfoCallback": null
  11849. },
  11850. /**
  11851. * Browser support parameters
  11852. * @namespace
  11853. */
  11854. "oBrowser": {
  11855. /**
  11856. * Indicate if the browser incorrectly calculates width:100% inside a
  11857. * scrolling element (IE6/7)
  11858. * @type boolean
  11859. * @default false
  11860. */
  11861. "bScrollOversize": false,
  11862. /**
  11863. * Determine if the vertical scrollbar is on the right or left of the
  11864. * scrolling container - needed for rtl language layout, although not
  11865. * all browsers move the scrollbar (Safari).
  11866. * @type boolean
  11867. * @default false
  11868. */
  11869. "bScrollbarLeft": false,
  11870. /**
  11871. * Flag for if `getBoundingClientRect` is fully supported or not
  11872. * @type boolean
  11873. * @default false
  11874. */
  11875. "bBounding": false,
  11876. /**
  11877. * Browser scrollbar width
  11878. * @type integer
  11879. * @default 0
  11880. */
  11881. "barWidth": 0
  11882. },
  11883. "ajax": null,
  11884. /**
  11885. * Array referencing the nodes which are used for the features. The
  11886. * parameters of this object match what is allowed by sDom - i.e.
  11887. * <ul>
  11888. * <li>'l' - Length changing</li>
  11889. * <li>'f' - Filtering input</li>
  11890. * <li>'t' - The table!</li>
  11891. * <li>'i' - Information</li>
  11892. * <li>'p' - Pagination</li>
  11893. * <li>'r' - pRocessing</li>
  11894. * </ul>
  11895. * @type array
  11896. * @default []
  11897. */
  11898. "aanFeatures": [],
  11899. /**
  11900. * Store data information - see {@link DataTable.models.oRow} for detailed
  11901. * information.
  11902. * @type array
  11903. * @default []
  11904. */
  11905. "aoData": [],
  11906. /**
  11907. * Array of indexes which are in the current display (after filtering etc)
  11908. * @type array
  11909. * @default []
  11910. */
  11911. "aiDisplay": [],
  11912. /**
  11913. * Array of indexes for display - no filtering
  11914. * @type array
  11915. * @default []
  11916. */
  11917. "aiDisplayMaster": [],
  11918. /**
  11919. * Map of row ids to data indexes
  11920. * @type object
  11921. * @default {}
  11922. */
  11923. "aIds": {},
  11924. /**
  11925. * Store information about each column that is in use
  11926. * @type array
  11927. * @default []
  11928. */
  11929. "aoColumns": [],
  11930. /**
  11931. * Store information about the table's header
  11932. * @type array
  11933. * @default []
  11934. */
  11935. "aoHeader": [],
  11936. /**
  11937. * Store information about the table's footer
  11938. * @type array
  11939. * @default []
  11940. */
  11941. "aoFooter": [],
  11942. /**
  11943. * Store the applied global search information in case we want to force a
  11944. * research or compare the old search to a new one.
  11945. * Note that this parameter will be set by the initialisation routine. To
  11946. * set a default use {@link DataTable.defaults}.
  11947. * @namespace
  11948. * @extends DataTable.models.oSearch
  11949. */
  11950. "oPreviousSearch": {},
  11951. /**
  11952. * Store the applied search for each column - see
  11953. * {@link DataTable.models.oSearch} for the format that is used for the
  11954. * filtering information for each column.
  11955. * @type array
  11956. * @default []
  11957. */
  11958. "aoPreSearchCols": [],
  11959. /**
  11960. * Sorting that is applied to the table. Note that the inner arrays are
  11961. * used in the following manner:
  11962. * <ul>
  11963. * <li>Index 0 - column number</li>
  11964. * <li>Index 1 - current sorting direction</li>
  11965. * </ul>
  11966. * Note that this parameter will be set by the initialisation routine. To
  11967. * set a default use {@link DataTable.defaults}.
  11968. * @type array
  11969. * @todo These inner arrays should really be objects
  11970. */
  11971. "aaSorting": null,
  11972. /**
  11973. * Sorting that is always applied to the table (i.e. prefixed in front of
  11974. * aaSorting).
  11975. * Note that this parameter will be set by the initialisation routine. To
  11976. * set a default use {@link DataTable.defaults}.
  11977. * @type array
  11978. * @default []
  11979. */
  11980. "aaSortingFixed": [],
  11981. /**
  11982. * Classes to use for the striping of a table.
  11983. * Note that this parameter will be set by the initialisation routine. To
  11984. * set a default use {@link DataTable.defaults}.
  11985. * @type array
  11986. * @default []
  11987. */
  11988. "asStripeClasses": null,
  11989. /**
  11990. * If restoring a table - we should restore its striping classes as well
  11991. * @type array
  11992. * @default []
  11993. */
  11994. "asDestroyStripes": [],
  11995. /**
  11996. * If restoring a table - we should restore its width
  11997. * @type int
  11998. * @default 0
  11999. */
  12000. "sDestroyWidth": 0,
  12001. /**
  12002. * Callback functions array for every time a row is inserted (i.e. on a draw).
  12003. * @type array
  12004. * @default []
  12005. */
  12006. "aoRowCallback": [],
  12007. /**
  12008. * Callback functions for the header on each draw.
  12009. * @type array
  12010. * @default []
  12011. */
  12012. "aoHeaderCallback": [],
  12013. /**
  12014. * Callback function for the footer on each draw.
  12015. * @type array
  12016. * @default []
  12017. */
  12018. "aoFooterCallback": [],
  12019. /**
  12020. * Array of callback functions for draw callback functions
  12021. * @type array
  12022. * @default []
  12023. */
  12024. "aoDrawCallback": [],
  12025. /**
  12026. * Array of callback functions for row created function
  12027. * @type array
  12028. * @default []
  12029. */
  12030. "aoRowCreatedCallback": [],
  12031. /**
  12032. * Callback functions for just before the table is redrawn. A return of
  12033. * false will be used to cancel the draw.
  12034. * @type array
  12035. * @default []
  12036. */
  12037. "aoPreDrawCallback": [],
  12038. /**
  12039. * Callback functions for when the table has been initialised.
  12040. * @type array
  12041. * @default []
  12042. */
  12043. "aoInitComplete": [],
  12044. /**
  12045. * Callbacks for modifying the settings to be stored for state saving, prior to
  12046. * saving state.
  12047. * @type array
  12048. * @default []
  12049. */
  12050. "aoStateSaveParams": [],
  12051. /**
  12052. * Callbacks for modifying the settings that have been stored for state saving
  12053. * prior to using the stored values to restore the state.
  12054. * @type array
  12055. * @default []
  12056. */
  12057. "aoStateLoadParams": [],
  12058. /**
  12059. * Callbacks for operating on the settings object once the saved state has been
  12060. * loaded
  12061. * @type array
  12062. * @default []
  12063. */
  12064. "aoStateLoaded": [],
  12065. /**
  12066. * Cache the table ID for quick access
  12067. * @type string
  12068. * @default <i>Empty string</i>
  12069. */
  12070. "sTableId": "",
  12071. /**
  12072. * The TABLE node for the main table
  12073. * @type node
  12074. * @default null
  12075. */
  12076. "nTable": null,
  12077. /**
  12078. * Permanent ref to the thead element
  12079. * @type node
  12080. * @default null
  12081. */
  12082. "nTHead": null,
  12083. /**
  12084. * Permanent ref to the tfoot element - if it exists
  12085. * @type node
  12086. * @default null
  12087. */
  12088. "nTFoot": null,
  12089. /**
  12090. * Permanent ref to the tbody element
  12091. * @type node
  12092. * @default null
  12093. */
  12094. "nTBody": null,
  12095. /**
  12096. * Cache the wrapper node (contains all DataTables controlled elements)
  12097. * @type node
  12098. * @default null
  12099. */
  12100. "nTableWrapper": null,
  12101. /**
  12102. * Indicate if when using server-side processing the loading of data
  12103. * should be deferred until the second draw.
  12104. * Note that this parameter will be set by the initialisation routine. To
  12105. * set a default use {@link DataTable.defaults}.
  12106. * @type boolean
  12107. * @default false
  12108. */
  12109. "bDeferLoading": false,
  12110. /**
  12111. * Indicate if all required information has been read in
  12112. * @type boolean
  12113. * @default false
  12114. */
  12115. "bInitialised": false,
  12116. /**
  12117. * Information about open rows. Each object in the array has the parameters
  12118. * 'nTr' and 'nParent'
  12119. * @type array
  12120. * @default []
  12121. */
  12122. "aoOpenRows": [],
  12123. /**
  12124. * Dictate the positioning of DataTables' control elements - see
  12125. * {@link DataTable.model.oInit.sDom}.
  12126. * Note that this parameter will be set by the initialisation routine. To
  12127. * set a default use {@link DataTable.defaults}.
  12128. * @type string
  12129. * @default null
  12130. */
  12131. "sDom": null,
  12132. /**
  12133. * Search delay (in mS)
  12134. * @type integer
  12135. * @default null
  12136. */
  12137. "searchDelay": null,
  12138. /**
  12139. * Which type of pagination should be used.
  12140. * Note that this parameter will be set by the initialisation routine. To
  12141. * set a default use {@link DataTable.defaults}.
  12142. * @type string
  12143. * @default two_button
  12144. */
  12145. "sPaginationType": "two_button",
  12146. /**
  12147. * The state duration (for `stateSave`) in seconds.
  12148. * Note that this parameter will be set by the initialisation routine. To
  12149. * set a default use {@link DataTable.defaults}.
  12150. * @type int
  12151. * @default 0
  12152. */
  12153. "iStateDuration": 0,
  12154. /**
  12155. * Array of callback functions for state saving. Each array element is an
  12156. * object with the following parameters:
  12157. * <ul>
  12158. * <li>function:fn - function to call. Takes two parameters, oSettings
  12159. * and the JSON string to save that has been thus far created. Returns
  12160. * a JSON string to be inserted into a json object
  12161. * (i.e. '"param": [ 0, 1, 2]')</li>
  12162. * <li>string:sName - name of callback</li>
  12163. * </ul>
  12164. * @type array
  12165. * @default []
  12166. */
  12167. "aoStateSave": [],
  12168. /**
  12169. * Array of callback functions for state loading. Each array element is an
  12170. * object with the following parameters:
  12171. * <ul>
  12172. * <li>function:fn - function to call. Takes two parameters, oSettings
  12173. * and the object stored. May return false to cancel state loading</li>
  12174. * <li>string:sName - name of callback</li>
  12175. * </ul>
  12176. * @type array
  12177. * @default []
  12178. */
  12179. "aoStateLoad": [],
  12180. /**
  12181. * State that was saved. Useful for back reference
  12182. * @type object
  12183. * @default null
  12184. */
  12185. "oSavedState": null,
  12186. /**
  12187. * State that was loaded. Useful for back reference
  12188. * @type object
  12189. * @default null
  12190. */
  12191. "oLoadedState": null,
  12192. /**
  12193. * Source url for AJAX data for the table.
  12194. * Note that this parameter will be set by the initialisation routine. To
  12195. * set a default use {@link DataTable.defaults}.
  12196. * @type string
  12197. * @default null
  12198. */
  12199. "sAjaxSource": null,
  12200. /**
  12201. * Property from a given object from which to read the table data from. This
  12202. * can be an empty string (when not server-side processing), in which case
  12203. * it is assumed an an array is given directly.
  12204. * Note that this parameter will be set by the initialisation routine. To
  12205. * set a default use {@link DataTable.defaults}.
  12206. * @type string
  12207. */
  12208. "sAjaxDataProp": null,
  12209. /**
  12210. * Note if draw should be blocked while getting data
  12211. * @type boolean
  12212. * @default true
  12213. */
  12214. "bAjaxDataGet": true,
  12215. /**
  12216. * The last jQuery XHR object that was used for server-side data gathering.
  12217. * This can be used for working with the XHR information in one of the
  12218. * callbacks
  12219. * @type object
  12220. * @default null
  12221. */
  12222. "jqXHR": null,
  12223. /**
  12224. * JSON returned from the server in the last Ajax request
  12225. * @type object
  12226. * @default undefined
  12227. */
  12228. "json": undefined,
  12229. /**
  12230. * Data submitted as part of the last Ajax request
  12231. * @type object
  12232. * @default undefined
  12233. */
  12234. "oAjaxData": undefined,
  12235. /**
  12236. * Function to get the server-side data.
  12237. * Note that this parameter will be set by the initialisation routine. To
  12238. * set a default use {@link DataTable.defaults}.
  12239. * @type function
  12240. */
  12241. "fnServerData": null,
  12242. /**
  12243. * Functions which are called prior to sending an Ajax request so extra
  12244. * parameters can easily be sent to the server
  12245. * @type array
  12246. * @default []
  12247. */
  12248. "aoServerParams": [],
  12249. /**
  12250. * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
  12251. * required).
  12252. * Note that this parameter will be set by the initialisation routine. To
  12253. * set a default use {@link DataTable.defaults}.
  12254. * @type string
  12255. */
  12256. "sServerMethod": null,
  12257. /**
  12258. * Format numbers for display.
  12259. * Note that this parameter will be set by the initialisation routine. To
  12260. * set a default use {@link DataTable.defaults}.
  12261. * @type function
  12262. */
  12263. "fnFormatNumber": null,
  12264. /**
  12265. * List of options that can be used for the user selectable length menu.
  12266. * Note that this parameter will be set by the initialisation routine. To
  12267. * set a default use {@link DataTable.defaults}.
  12268. * @type array
  12269. * @default []
  12270. */
  12271. "aLengthMenu": null,
  12272. /**
  12273. * Counter for the draws that the table does. Also used as a tracker for
  12274. * server-side processing
  12275. * @type int
  12276. * @default 0
  12277. */
  12278. "iDraw": 0,
  12279. /**
  12280. * Indicate if a redraw is being done - useful for Ajax
  12281. * @type boolean
  12282. * @default false
  12283. */
  12284. "bDrawing": false,
  12285. /**
  12286. * Draw index (iDraw) of the last error when parsing the returned data
  12287. * @type int
  12288. * @default -1
  12289. */
  12290. "iDrawError": - 1,
  12291. /**
  12292. * Paging display length
  12293. * @type int
  12294. * @default 10
  12295. */
  12296. "_iDisplayLength": 10,
  12297. /**
  12298. * Paging start point - aiDisplay index
  12299. * @type int
  12300. * @default 0
  12301. */
  12302. "_iDisplayStart": 0,
  12303. /**
  12304. * Server-side processing - number of records in the result set
  12305. * (i.e. before filtering), Use fnRecordsTotal rather than
  12306. * this property to get the value of the number of records, regardless of
  12307. * the server-side processing setting.
  12308. * @type int
  12309. * @default 0
  12310. * @private
  12311. */
  12312. "_iRecordsTotal": 0,
  12313. /**
  12314. * Server-side processing - number of records in the current display set
  12315. * (i.e. after filtering). Use fnRecordsDisplay rather than
  12316. * this property to get the value of the number of records, regardless of
  12317. * the server-side processing setting.
  12318. * @type boolean
  12319. * @default 0
  12320. * @private
  12321. */
  12322. "_iRecordsDisplay": 0,
  12323. /**
  12324. * The classes to use for the table
  12325. * @type object
  12326. * @default {}
  12327. */
  12328. "oClasses": {},
  12329. /**
  12330. * Flag attached to the settings object so you can check in the draw
  12331. * callback if filtering has been done in the draw. Deprecated in favour of
  12332. * events.
  12333. * @type boolean
  12334. * @default false
  12335. * @deprecated
  12336. */
  12337. "bFiltered": false,
  12338. /**
  12339. * Flag attached to the settings object so you can check in the draw
  12340. * callback if sorting has been done in the draw. Deprecated in favour of
  12341. * events.
  12342. * @type boolean
  12343. * @default false
  12344. * @deprecated
  12345. */
  12346. "bSorted": false,
  12347. /**
  12348. * Indicate that if multiple rows are in the header and there is more than
  12349. * one unique cell per column, if the top one (true) or bottom one (false)
  12350. * should be used for sorting / title by DataTables.
  12351. * Note that this parameter will be set by the initialisation routine. To
  12352. * set a default use {@link DataTable.defaults}.
  12353. * @type boolean
  12354. */
  12355. "bSortCellsTop": null,
  12356. /**
  12357. * Initialisation object that is used for the table
  12358. * @type object
  12359. * @default null
  12360. */
  12361. "oInit": null,
  12362. /**
  12363. * Destroy callback functions - for plug-ins to attach themselves to the
  12364. * destroy so they can clean up markup and events.
  12365. * @type array
  12366. * @default []
  12367. */
  12368. "aoDestroyCallback": [],
  12369. /**
  12370. * Get the number of records in the current record set, before filtering
  12371. * @type function
  12372. */
  12373. "fnRecordsTotal": function fnRecordsTotal() {
  12374. return _fnDataSource(this) == 'ssp' ? this._iRecordsTotal * 1 : this.aiDisplayMaster.length;
  12375. },
  12376. /**
  12377. * Get the number of records in the current record set, after filtering
  12378. * @type function
  12379. */
  12380. "fnRecordsDisplay": function fnRecordsDisplay() {
  12381. return _fnDataSource(this) == 'ssp' ? this._iRecordsDisplay * 1 : this.aiDisplay.length;
  12382. },
  12383. /**
  12384. * Get the display end point - aiDisplay index
  12385. * @type function
  12386. */
  12387. "fnDisplayEnd": function fnDisplayEnd() {
  12388. var len = this._iDisplayLength,
  12389. start = this._iDisplayStart,
  12390. calc = start + len,
  12391. records = this.aiDisplay.length,
  12392. features = this.oFeatures,
  12393. paginate = features.bPaginate;
  12394. if (features.bServerSide) {
  12395. return paginate === false || len === - 1 ? start + records : Math.min(start + len, this._iRecordsDisplay);
  12396. } else {
  12397. return !paginate || calc > records || len === - 1 ? records : calc;
  12398. }
  12399. },
  12400. /**
  12401. * The DataTables object for this table
  12402. * @type object
  12403. * @default null
  12404. */
  12405. "oInstance": null,
  12406. /**
  12407. * Unique identifier for each instance of the DataTables object. If there
  12408. * is an ID on the table node, then it takes that value, otherwise an
  12409. * incrementing internal counter is used.
  12410. * @type string
  12411. * @default null
  12412. */
  12413. "sInstance": null,
  12414. /**
  12415. * tabindex attribute value that is added to DataTables control elements, allowing
  12416. * keyboard navigation of the table and its controls.
  12417. */
  12418. "iTabIndex": 0,
  12419. /**
  12420. * DIV container for the footer scrolling table if scrolling
  12421. */
  12422. "nScrollHead": null,
  12423. /**
  12424. * DIV container for the footer scrolling table if scrolling
  12425. */
  12426. "nScrollFoot": null,
  12427. /**
  12428. * Last applied sort
  12429. * @type array
  12430. * @default []
  12431. */
  12432. "aLastSort": [],
  12433. /**
  12434. * Stored plug-in instances
  12435. * @type object
  12436. * @default {}
  12437. */
  12438. "oPlugins": {},
  12439. /**
  12440. * Function used to get a row's id from the row's data
  12441. * @type function
  12442. * @default null
  12443. */
  12444. "rowIdFn": null,
  12445. /**
  12446. * Data location where to store a row's id
  12447. * @type string
  12448. * @default null
  12449. */
  12450. "rowId": null
  12451. };
  12452. /**
  12453. * Extension object for DataTables that is used to provide all extension
  12454. * options.
  12455. *
  12456. * Note that the `DataTable.ext` object is available through
  12457. * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
  12458. * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
  12459. * @namespace
  12460. * @extends DataTable.models.ext
  12461. */
  12462. /**
  12463. * DataTables extensions
  12464. *
  12465. * This namespace acts as a collection area for plug-ins that can be used to
  12466. * extend DataTables capabilities. Indeed many of the build in methods
  12467. * use this method to provide their own capabilities (sorting methods for
  12468. * example).
  12469. *
  12470. * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
  12471. * reasons
  12472. *
  12473. * @namespace
  12474. */
  12475. DataTable.ext = _ext = {
  12476. /**
  12477. * Buttons. For use with the Buttons extension for DataTables. This is
  12478. * defined here so other extensions can define buttons regardless of load
  12479. * order. It is _not_ used by DataTables core.
  12480. *
  12481. * @type object
  12482. * @default {}
  12483. */
  12484. buttons: {},
  12485. /**
  12486. * Element class names
  12487. *
  12488. * @type object
  12489. * @default {}
  12490. */
  12491. classes: {},
  12492. /**
  12493. * DataTables build type (expanded by the download builder)
  12494. *
  12495. * @type string
  12496. */
  12497. builder: "-source-",
  12498. /**
  12499. * Error reporting.
  12500. *
  12501. * How should DataTables report an error. Can take the value 'alert',
  12502. * 'throw', 'none' or a function.
  12503. *
  12504. * @type string|function
  12505. * @default alert
  12506. */
  12507. errMode: "alert",
  12508. /**
  12509. * Feature plug-ins.
  12510. *
  12511. * This is an array of objects which describe the feature plug-ins that are
  12512. * available to DataTables. These feature plug-ins are then available for
  12513. * use through the `dom` initialisation option.
  12514. *
  12515. * Each feature plug-in is described by an object which must have the
  12516. * following properties:
  12517. *
  12518. * * `fnInit` - function that is used to initialise the plug-in,
  12519. * * `cFeature` - a character so the feature can be enabled by the `dom`
  12520. * instillation option. This is case sensitive.
  12521. *
  12522. * The `fnInit` function has the following input parameters:
  12523. *
  12524. * 1. `{object}` DataTables settings object: see
  12525. * {@link DataTable.models.oSettings}
  12526. *
  12527. * And the following return is expected:
  12528. *
  12529. * * {node|null} The element which contains your feature. Note that the
  12530. * return may also be void if your plug-in does not require to inject any
  12531. * DOM elements into DataTables control (`dom`) - for example this might
  12532. * be useful when developing a plug-in which allows table control via
  12533. * keyboard entry
  12534. *
  12535. * @type array
  12536. *
  12537. * @example
  12538. * $.fn.dataTable.ext.features.push( {
  12539. * "fnInit": function( oSettings ) {
  12540. * return new TableTools( { "oDTSettings": oSettings } );
  12541. * },
  12542. * "cFeature": "T"
  12543. * } );
  12544. */
  12545. feature: [],
  12546. /**
  12547. * Row searching.
  12548. *
  12549. * This method of searching is complimentary to the default type based
  12550. * searching, and a lot more comprehensive as it allows you complete control
  12551. * over the searching logic. Each element in this array is a function
  12552. * (parameters described below) that is called for every row in the table,
  12553. * and your logic decides if it should be included in the searching data set
  12554. * or not.
  12555. *
  12556. * Searching functions have the following input parameters:
  12557. *
  12558. * 1. `{object}` DataTables settings object: see
  12559. * {@link DataTable.models.oSettings}
  12560. * 2. `{array|object}` Data for the row to be processed (same as the
  12561. * original format that was passed in as the data source, or an array
  12562. * from a DOM data source
  12563. * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
  12564. * can be useful to retrieve the `TR` element if you need DOM interaction.
  12565. *
  12566. * And the following return is expected:
  12567. *
  12568. * * {boolean} Include the row in the searched result set (true) or not
  12569. * (false)
  12570. *
  12571. * Note that as with the main search ability in DataTables, technically this
  12572. * is "filtering", since it is subtractive. However, for consistency in
  12573. * naming we call it searching here.
  12574. *
  12575. * @type array
  12576. * @default []
  12577. *
  12578. * @example
  12579. * // The following example shows custom search being applied to the
  12580. * // fourth column (i.e. the data[3] index) based on two input values
  12581. * // from the end-user, matching the data in a certain range.
  12582. * $.fn.dataTable.ext.search.push(
  12583. * function( settings, data, dataIndex ) {
  12584. * var min = document.getElementById('min').value * 1;
  12585. * var max = document.getElementById('max').value * 1;
  12586. * var version = data[3] == "-" ? 0 : data[3]*1;
  12587. *
  12588. * if ( min == "" && max == "" ) {
  12589. * return true;
  12590. * }
  12591. * else if ( min == "" && version < max ) {
  12592. * return true;
  12593. * }
  12594. * else if ( min < version && "" == max ) {
  12595. * return true;
  12596. * }
  12597. * else if ( min < version && version < max ) {
  12598. * return true;
  12599. * }
  12600. * return false;
  12601. * }
  12602. * );
  12603. */
  12604. search: [],
  12605. /**
  12606. * Selector extensions
  12607. *
  12608. * The `selector` option can be used to extend the options available for the
  12609. * selector modifier options (`selector-modifier` object data type) that
  12610. * each of the three built in selector types offer (row, column and cell +
  12611. * their plural counterparts). For example the Select extension uses this
  12612. * mechanism to provide an option to select only rows, columns and cells
  12613. * that have been marked as selected by the end user (`{selected: true}`),
  12614. * which can be used in conjunction with the existing built in selector
  12615. * options.
  12616. *
  12617. * Each property is an array to which functions can be pushed. The functions
  12618. * take three attributes:
  12619. *
  12620. * * Settings object for the host table
  12621. * * Options object (`selector-modifier` object type)
  12622. * * Array of selected item indexes
  12623. *
  12624. * The return is an array of the resulting item indexes after the custom
  12625. * selector has been applied.
  12626. *
  12627. * @type object
  12628. */
  12629. selector: {
  12630. cell: [],
  12631. column: [],
  12632. row: []
  12633. },
  12634. /**
  12635. * Internal functions, exposed for used in plug-ins.
  12636. *
  12637. * Please note that you should not need to use the internal methods for
  12638. * anything other than a plug-in (and even then, try to avoid if possible).
  12639. * The internal function may change between releases.
  12640. *
  12641. * @type object
  12642. * @default {}
  12643. */
  12644. internal: {},
  12645. /**
  12646. * Legacy configuration options. Enable and disable legacy options that
  12647. * are available in DataTables.
  12648. *
  12649. * @type object
  12650. */
  12651. legacy: {
  12652. /**
  12653. * Enable / disable DataTables 1.9 compatible server-side processing
  12654. * requests
  12655. *
  12656. * @type boolean
  12657. * @default null
  12658. */
  12659. ajax: null
  12660. },
  12661. /**
  12662. * Pagination plug-in methods.
  12663. *
  12664. * Each entry in this object is a function and defines which buttons should
  12665. * be shown by the pagination rendering method that is used for the table:
  12666. * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
  12667. * buttons are displayed in the document, while the functions here tell it
  12668. * what buttons to display. This is done by returning an array of button
  12669. * descriptions (what each button will do).
  12670. *
  12671. * Pagination types (the four built in options and any additional plug-in
  12672. * options defined here) can be used through the `paginationType`
  12673. * initialisation parameter.
  12674. *
  12675. * The functions defined take two parameters:
  12676. *
  12677. * 1. `{int} page` The current page index
  12678. * 2. `{int} pages` The number of pages in the table
  12679. *
  12680. * Each function is expected to return an array where each element of the
  12681. * array can be one of:
  12682. *
  12683. * * `first` - Jump to first page when activated
  12684. * * `last` - Jump to last page when activated
  12685. * * `previous` - Show previous page when activated
  12686. * * `next` - Show next page when activated
  12687. * * `{int}` - Show page of the index given
  12688. * * `{array}` - A nested array containing the above elements to add a
  12689. * containing 'DIV' element (might be useful for styling).
  12690. *
  12691. * Note that DataTables v1.9- used this object slightly differently whereby
  12692. * an object with two functions would be defined for each plug-in. That
  12693. * ability is still supported by DataTables 1.10+ to provide backwards
  12694. * compatibility, but this option of use is now decremented and no longer
  12695. * documented in DataTables 1.10+.
  12696. *
  12697. * @type object
  12698. * @default {}
  12699. *
  12700. * @example
  12701. * // Show previous, next and current page buttons only
  12702. * $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
  12703. * return [ 'previous', page, 'next' ];
  12704. * };
  12705. */
  12706. pager: {},
  12707. renderer: {
  12708. pageButton: {},
  12709. header: {}
  12710. },
  12711. /**
  12712. * Ordering plug-ins - custom data source
  12713. *
  12714. * The extension options for ordering of data available here is complimentary
  12715. * to the default type based ordering that DataTables typically uses. It
  12716. * allows much greater control over the the data that is being used to
  12717. * order a column, but is necessarily therefore more complex.
  12718. *
  12719. * This type of ordering is useful if you want to do ordering based on data
  12720. * live from the DOM (for example the contents of an 'input' element) rather
  12721. * than just the static string that DataTables knows of.
  12722. *
  12723. * The way these plug-ins work is that you create an array of the values you
  12724. * wish to be ordering for the column in question and then return that
  12725. * array. The data in the array much be in the index order of the rows in
  12726. * the table (not the currently ordering order!). Which order data gathering
  12727. * function is run here depends on the `dt-init columns.orderDataType`
  12728. * parameter that is used for the column (if any).
  12729. *
  12730. * The functions defined take two parameters:
  12731. *
  12732. * 1. `{object}` DataTables settings object: see
  12733. * {@link DataTable.models.oSettings}
  12734. * 2. `{int}` Target column index
  12735. *
  12736. * Each function is expected to return an array:
  12737. *
  12738. * * `{array}` Data for the column to be ordering upon
  12739. *
  12740. * @type array
  12741. *
  12742. * @example
  12743. * // Ordering using `input` node values
  12744. * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col )
  12745. * {
  12746. * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
  12747. * return $('input', td).val();
  12748. * } );
  12749. * }
  12750. */
  12751. order: {},
  12752. /**
  12753. * Type based plug-ins.
  12754. *
  12755. * Each column in DataTables has a type assigned to it, either by automatic
  12756. * detection or by direct assignment using the `type` option for the column.
  12757. * The type of a column will effect how it is ordering and search (plug-ins
  12758. * can also make use of the column type if required).
  12759. *
  12760. * @namespace
  12761. */
  12762. type: {
  12763. /**
  12764. * Type detection functions.
  12765. *
  12766. * The functions defined in this object are used to automatically detect
  12767. * a column's type, making initialisation of DataTables super easy, even
  12768. * when complex data is in the table.
  12769. *
  12770. * The functions defined take two parameters:
  12771. *
  12772. * 1. `{*}` Data from the column cell to be analysed
  12773. * 2. `{settings}` DataTables settings object. This can be used to
  12774. * perform context specific type detection - for example detection
  12775. * based on language settings such as using a comma for a decimal
  12776. * place. Generally speaking the options from the settings will not
  12777. * be required
  12778. *
  12779. * Each function is expected to return:
  12780. *
  12781. * * `{string|null}` Data type detected, or null if unknown (and thus
  12782. * pass it on to the other type detection functions.
  12783. *
  12784. * @type array
  12785. *
  12786. * @example
  12787. * // Currency type detection plug-in:
  12788. * $.fn.dataTable.ext.type.detect.push(
  12789. * function ( data, settings ) {
  12790. * // Check the numeric part
  12791. * if ( ! $.isNumeric( data.substring(1) ) ) {
  12792. * return null;
  12793. * }
  12794. *
  12795. * // Check prefixed by currency
  12796. * if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
  12797. * return 'currency';
  12798. * }
  12799. * return null;
  12800. * }
  12801. * );
  12802. */
  12803. detect: [],
  12804. /**
  12805. * Type based search formatting.
  12806. *
  12807. * The type based searching functions can be used to pre-format the
  12808. * data to be search on. For example, it can be used to strip HTML
  12809. * tags or to de-format telephone numbers for numeric only searching.
  12810. *
  12811. * Note that is a search is not defined for a column of a given type,
  12812. * no search formatting will be performed.
  12813. *
  12814. * Pre-processing of searching data plug-ins - When you assign the sType
  12815. * for a column (or have it automatically detected for you by DataTables
  12816. * or a type detection plug-in), you will typically be using this for
  12817. * custom sorting, but it can also be used to provide custom searching
  12818. * by allowing you to pre-processing the data and returning the data in
  12819. * the format that should be searched upon. This is done by adding
  12820. * functions this object with a parameter name which matches the sType
  12821. * for that target column. This is the corollary of <i>afnSortData</i>
  12822. * for searching data.
  12823. *
  12824. * The functions defined take a single parameter:
  12825. *
  12826. * 1. `{*}` Data from the column cell to be prepared for searching
  12827. *
  12828. * Each function is expected to return:
  12829. *
  12830. * * `{string|null}` Formatted string that will be used for the searching.
  12831. *
  12832. * @type object
  12833. * @default {}
  12834. *
  12835. * @example
  12836. * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
  12837. * return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
  12838. * }
  12839. */
  12840. search: {},
  12841. /**
  12842. * Type based ordering.
  12843. *
  12844. * The column type tells DataTables what ordering to apply to the table
  12845. * when a column is sorted upon. The order for each type that is defined,
  12846. * is defined by the functions available in this object.
  12847. *
  12848. * Each ordering option can be described by three properties added to
  12849. * this object:
  12850. *
  12851. * * `{type}-pre` - Pre-formatting function
  12852. * * `{type}-asc` - Ascending order function
  12853. * * `{type}-desc` - Descending order function
  12854. *
  12855. * All three can be used together, only `{type}-pre` or only
  12856. * `{type}-asc` and `{type}-desc` together. It is generally recommended
  12857. * that only `{type}-pre` is used, as this provides the optimal
  12858. * implementation in terms of speed, although the others are provided
  12859. * for compatibility with existing Javascript sort functions.
  12860. *
  12861. * `{type}-pre`: Functions defined take a single parameter:
  12862. *
  12863. * 1. `{*}` Data from the column cell to be prepared for ordering
  12864. *
  12865. * And return:
  12866. *
  12867. * * `{*}` Data to be sorted upon
  12868. *
  12869. * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
  12870. * functions, taking two parameters:
  12871. *
  12872. * 1. `{*}` Data to compare to the second parameter
  12873. * 2. `{*}` Data to compare to the first parameter
  12874. *
  12875. * And returning:
  12876. *
  12877. * * `{*}` Ordering match: <0 if first parameter should be sorted lower
  12878. * than the second parameter, ===0 if the two parameters are equal and
  12879. * >0 if the first parameter should be sorted height than the second
  12880. * parameter.
  12881. *
  12882. * @type object
  12883. * @default {}
  12884. *
  12885. * @example
  12886. * // Numeric ordering of formatted numbers with a pre-formatter
  12887. * $.extend( $.fn.dataTable.ext.type.order, {
  12888. * "string-pre": function(x) {
  12889. * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
  12890. * return parseFloat( a );
  12891. * }
  12892. * } );
  12893. *
  12894. * @example
  12895. * // Case-sensitive string ordering, with no pre-formatting method
  12896. * $.extend( $.fn.dataTable.ext.order, {
  12897. * "string-case-asc": function(x,y) {
  12898. * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  12899. * },
  12900. * "string-case-desc": function(x,y) {
  12901. * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  12902. * }
  12903. * } );
  12904. */
  12905. order: {}
  12906. },
  12907. /**
  12908. * Unique DataTables instance counter
  12909. *
  12910. * @type int
  12911. * @private
  12912. */
  12913. _unique: 0,
  12914. //
  12915. // Depreciated
  12916. // The following properties are retained for backwards compatiblity only.
  12917. // The should not be used in new projects and will be removed in a future
  12918. // version
  12919. //
  12920. /**
  12921. * Version check function.
  12922. * @type function
  12923. * @depreciated Since 1.10
  12924. */
  12925. fnVersionCheck: DataTable.fnVersionCheck,
  12926. /**
  12927. * Index for what 'this' index API functions should use
  12928. * @type int
  12929. * @deprecated Since v1.10
  12930. */
  12931. iApiIndex: 0,
  12932. /**
  12933. * jQuery UI class container
  12934. * @type object
  12935. * @deprecated Since v1.10
  12936. */
  12937. oJUIClasses: {},
  12938. /**
  12939. * Software version
  12940. * @type string
  12941. * @deprecated Since v1.10
  12942. */
  12943. sVersion: DataTable.version
  12944. };
  12945. //
  12946. // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
  12947. //
  12948. $.extend(_ext, {
  12949. afnFiltering: _ext.search,
  12950. aTypes: _ext.type.detect,
  12951. ofnSearch: _ext.type.search,
  12952. oSort: _ext.type.order,
  12953. afnSortData: _ext.order,
  12954. aoFeatures: _ext.feature,
  12955. oApi: _ext.internal,
  12956. oStdClasses: _ext.classes,
  12957. oPagination: _ext.pager
  12958. });
  12959. $.extend(DataTable.ext.classes, {
  12960. "sTable": "dataTable",
  12961. "sNoFooter": "no-footer",
  12962. /* Paging buttons */
  12963. "sPageButton": "paginate_button",
  12964. "sPageButtonActive": "current",
  12965. "sPageButtonDisabled": "disabled",
  12966. /* Striping classes */
  12967. "sStripeOdd": "odd",
  12968. "sStripeEven": "even",
  12969. /* Empty row */
  12970. "sRowEmpty": "dataTables_empty",
  12971. /* Features */
  12972. "sWrapper": "dataTables_wrapper",
  12973. "sFilter": "dataTables_filter",
  12974. "sInfo": "dataTables_info",
  12975. "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
  12976. "sLength": "dataTables_length",
  12977. "sProcessing": "dataTables_processing",
  12978. /* Sorting */
  12979. "sSortAsc": "sorting_asc",
  12980. "sSortDesc": "sorting_desc",
  12981. "sSortable": "sorting", /* Sortable in both directions */
  12982. "sSortableAsc": "sorting_asc_disabled",
  12983. "sSortableDesc": "sorting_desc_disabled",
  12984. "sSortableNone": "sorting_disabled",
  12985. "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
  12986. /* Filtering */
  12987. "sFilterInput": "",
  12988. /* Page length */
  12989. "sLengthSelect": "",
  12990. /* Scrolling */
  12991. "sScrollWrapper": "dataTables_scroll",
  12992. "sScrollHead": "dataTables_scrollHead",
  12993. "sScrollHeadInner": "dataTables_scrollHeadInner",
  12994. "sScrollBody": "dataTables_scrollBody",
  12995. "sScrollFoot": "dataTables_scrollFoot",
  12996. "sScrollFootInner": "dataTables_scrollFootInner",
  12997. /* Misc */
  12998. "sHeaderTH": "",
  12999. "sFooterTH": "",
  13000. // Deprecated
  13001. "sSortJUIAsc": "",
  13002. "sSortJUIDesc": "",
  13003. "sSortJUI": "",
  13004. "sSortJUIAscAllowed": "",
  13005. "sSortJUIDescAllowed": "",
  13006. "sSortJUIWrapper": "",
  13007. "sSortIcon": "",
  13008. "sJUIHeader": "",
  13009. "sJUIFooter": ""
  13010. });
  13011. var extPagination = DataTable.ext.pager;
  13012. function _numbers(page, pages) {
  13013. var numbers = [],
  13014. buttons = extPagination.numbers_length,
  13015. half = Math.floor(buttons / 2),
  13016. i = 1;
  13017. if (pages <= buttons) {
  13018. numbers = _range(0, pages);
  13019. } else if (page <= half) {
  13020. numbers = _range(0, buttons - 2);
  13021. numbers.push('ellipsis');
  13022. numbers.push(pages - 1);
  13023. } else if (page >= pages - 1 - half) {
  13024. numbers = _range(pages - (buttons - 2), pages);
  13025. numbers.splice(0, 0, 'ellipsis'); // no unshift in ie6
  13026. numbers.splice(0, 0, 0);
  13027. } else {
  13028. numbers = _range(page - half + 2, page + half - 1);
  13029. numbers.push('ellipsis');
  13030. numbers.push(pages - 1);
  13031. numbers.splice(0, 0, 'ellipsis');
  13032. numbers.splice(0, 0, 0);
  13033. }
  13034. numbers.DT_el = 'span';
  13035. return numbers;
  13036. }
  13037. $.extend(extPagination, {
  13038. simple: function simple(page, pages) {
  13039. return ['previous', 'next'];
  13040. },
  13041. full: function full(page, pages) {
  13042. return ['first', 'previous', 'next', 'last'];
  13043. },
  13044. numbers: function numbers(page, pages) {
  13045. return [_numbers(page, pages)];
  13046. },
  13047. simple_numbers: function simple_numbers(page, pages) {
  13048. return ['previous', _numbers(page, pages), 'next'];
  13049. },
  13050. full_numbers: function full_numbers(page, pages) {
  13051. return ['first', 'previous', _numbers(page, pages), 'next', 'last'];
  13052. },
  13053. first_last_numbers: function first_last_numbers(page, pages) {
  13054. return ['first', _numbers(page, pages), 'last'];
  13055. },
  13056. // For testing and plug-ins to use
  13057. _numbers: _numbers,
  13058. // Number of number buttons (including ellipsis) to show. _Must be odd!_
  13059. numbers_length: 7
  13060. });
  13061. $.extend(true, DataTable.ext.renderer, {
  13062. pageButton: {
  13063. _: function _(settings, host, idx, buttons, page, pages) {
  13064. var classes = settings.oClasses;
  13065. var lang = settings.oLanguage.oPaginate;
  13066. var aria = settings.oLanguage.oAria.paginate || {};
  13067. var btnDisplay,
  13068. btnClass,
  13069. counter = 0;
  13070. var attach = function attach(container, buttons) {
  13071. var i, ien, node, button;
  13072. var clickHandler = function clickHandler(e) {
  13073. _fnPageChange(settings, e.data.action, true);
  13074. };
  13075. for (i = 0, ien = buttons.length; i < ien; i++) {
  13076. button = buttons[i];
  13077. if ($.isArray(button)) {
  13078. var inner = $('<' + (button.DT_el || 'div') + '/>').appendTo(container);
  13079. attach(inner, button);
  13080. } else {
  13081. btnDisplay = null;
  13082. btnClass = '';
  13083. switch (button) {
  13084. case 'ellipsis':
  13085. container.append('<span class="ellipsis">&#x2026;</span>');
  13086. break;
  13087. case 'first':
  13088. btnDisplay = lang.sFirst;
  13089. btnClass = button + (page > 0 ? '' : ' ' + classes.sPageButtonDisabled);
  13090. break;
  13091. case 'previous':
  13092. btnDisplay = lang.sPrevious;
  13093. btnClass = button + (page > 0 ? '' : ' ' + classes.sPageButtonDisabled);
  13094. break;
  13095. case 'next':
  13096. btnDisplay = lang.sNext;
  13097. btnClass = button + (page < pages - 1 ? '' : ' ' + classes.sPageButtonDisabled);
  13098. break;
  13099. case 'last':
  13100. btnDisplay = lang.sLast;
  13101. btnClass = button + (page < pages - 1 ? '' : ' ' + classes.sPageButtonDisabled);
  13102. break;
  13103. default:
  13104. btnDisplay = button + 1;
  13105. btnClass = page === button ? classes.sPageButtonActive : '';
  13106. break;
  13107. }
  13108. if (btnDisplay !== null) {
  13109. node = $('<a>', {
  13110. 'class': classes.sPageButton + ' ' + btnClass,
  13111. 'aria-controls': settings.sTableId,
  13112. 'aria-label': aria[button],
  13113. 'data-dt-idx': counter,
  13114. 'tabindex': settings.iTabIndex,
  13115. 'id': idx === 0 && typeof button === 'string' ? settings.sTableId + '_' + button : null
  13116. }).html(btnDisplay).appendTo(container);
  13117. _fnBindAction(node, {action: button}, clickHandler);
  13118. counter++;
  13119. }
  13120. }
  13121. }
  13122. };
  13123. // IE9 throws an 'unknown error' if document.activeElement is used
  13124. // inside an iframe or frame. Try / catch the error. Not good for
  13125. // accessibility, but neither are frames.
  13126. var activeEl;
  13127. try {
  13128. // Because this approach is destroying and recreating the paging
  13129. // elements, focus is lost on the select button which is bad for
  13130. // accessibility. So we want to restore focus once the draw has
  13131. // completed
  13132. activeEl = $(host).find(document.activeElement).data('dt-idx');
  13133. } catch (e) {
  13134. }
  13135. attach($(host).empty(), buttons);
  13136. if (activeEl !== undefined) {
  13137. $(host).find('[data-dt-idx=' + activeEl + ']').focus();
  13138. }
  13139. }
  13140. }
  13141. });
  13142. // Built in type detection. See model.ext.aTypes for information about
  13143. // what is required from this methods.
  13144. $.extend(DataTable.ext.type.detect, [
  13145. // Plain numbers - first since V8 detects some plain numbers as dates
  13146. // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
  13147. function (d, settings) {
  13148. var decimal = settings.oLanguage.sDecimal;
  13149. return _isNumber(d, decimal) ? 'num' + decimal : null;
  13150. },
  13151. // Dates (only those recognised by the browser's Date.parse)
  13152. function (d, settings) {
  13153. // V8 tries _very_ hard to make a string passed into `Date.parse()`
  13154. // valid, so we need to use a regex to restrict date formats. Use a
  13155. // plug-in for anything other than ISO8601 style strings
  13156. if (d && !(d instanceof Date) && !_re_date.test(d)) {
  13157. return null;
  13158. }
  13159. var parsed = Date.parse(d);
  13160. return parsed !== null && !isNaN(parsed) || _empty(d) ? 'date' : null;
  13161. },
  13162. // Formatted numbers
  13163. function (d, settings) {
  13164. var decimal = settings.oLanguage.sDecimal;
  13165. return _isNumber(d, decimal, true) ? 'num-fmt' + decimal : null;
  13166. },
  13167. // HTML numeric
  13168. function (d, settings) {
  13169. var decimal = settings.oLanguage.sDecimal;
  13170. return _htmlNumeric(d, decimal) ? 'html-num' + decimal : null;
  13171. },
  13172. // HTML numeric, formatted
  13173. function (d, settings) {
  13174. var decimal = settings.oLanguage.sDecimal;
  13175. return _htmlNumeric(d, decimal, true) ? 'html-num-fmt' + decimal : null;
  13176. },
  13177. // HTML (this is strict checking - there must be html)
  13178. function (d, settings) {
  13179. return _empty(d) || typeof d === 'string' && d.indexOf('<') !== - 1 ? 'html' : null;
  13180. }]);
  13181. // Filter formatting functions. See model.ext.ofnSearch for information about
  13182. // what is required from these methods.
  13183. //
  13184. // Note that additional search methods are added for the html numbers and
  13185. // html formatted numbers by `_addNumericSort()` when we know what the decimal
  13186. // place is
  13187. $.extend(DataTable.ext.type.search, {
  13188. html: function html(data) {
  13189. return _empty(data) ? data : typeof data === 'string' ? data.replace(_re_new_lines, " ").replace(_re_html, "") : '';
  13190. },
  13191. string: function string(data) {
  13192. return _empty(data) ? data : typeof data === 'string' ? data.replace(_re_new_lines, " ") : data;
  13193. }
  13194. });
  13195. var __numericReplace = function __numericReplace(d, decimalPlace, re1, re2) {
  13196. if (d !== 0 && (!d || d === '-')) {
  13197. return - Infinity;
  13198. }
  13199. // If a decimal place other than `.` is used, it needs to be given to the
  13200. // function so we can detect it and replace with a `.` which is the only
  13201. // decimal place Javascript recognises - it is not locale aware.
  13202. if (decimalPlace) {
  13203. d = _numToDecimal(d, decimalPlace);
  13204. }
  13205. if (d.replace) {
  13206. if (re1) {
  13207. d = d.replace(re1, '');
  13208. }
  13209. if (re2) {
  13210. d = d.replace(re2, '');
  13211. }
  13212. }
  13213. return d * 1;
  13214. };
  13215. // Add the numeric 'deformatting' functions for sorting and search. This is done
  13216. // in a function to provide an easy ability for the language options to add
  13217. // additional methods if a non-period decimal place is used.
  13218. function _addNumericSort(decimalPlace) {
  13219. $.each({
  13220. // Plain numbers
  13221. "num": function num(d) {
  13222. return __numericReplace(d, decimalPlace);
  13223. },
  13224. // Formatted numbers
  13225. "num-fmt": function numFmt(d) {
  13226. return __numericReplace(d, decimalPlace, _re_formatted_numeric);
  13227. },
  13228. // HTML numeric
  13229. "html-num": function htmlNum(d) {
  13230. return __numericReplace(d, decimalPlace, _re_html);
  13231. },
  13232. // HTML numeric, formatted
  13233. "html-num-fmt": function htmlNumFmt(d) {
  13234. return __numericReplace(d, decimalPlace, _re_html, _re_formatted_numeric);
  13235. }
  13236. }, function (key, fn) {
  13237. // Add the ordering method
  13238. _ext.type.order[key + decimalPlace + '-pre'] = fn;
  13239. // For HTML types add a search formatter that will strip the HTML
  13240. if (key.match(/^html\-/)) {
  13241. _ext.type.search[key + decimalPlace] = _ext.type.search.html;
  13242. }
  13243. });
  13244. }
  13245. // Default sort methods
  13246. $.extend(_ext.type.order, {
  13247. // Dates
  13248. "date-pre": function datePre(d) {
  13249. return Date.parse(d) || - Infinity;
  13250. },
  13251. // html
  13252. "html-pre": function htmlPre(a) {
  13253. return _empty(a) ? '' : a.replace ? a.replace(/<.*?>/g, "").toLowerCase() : a + '';
  13254. },
  13255. // string
  13256. "string-pre": function stringPre(a) {
  13257. // This is a little complex, but faster than always calling toString,
  13258. // http://jsperf.com/tostring-v-check
  13259. return _empty(a) ? '' : typeof a === 'string' ? a.toLowerCase() : !a.toString ? '' : a.toString();
  13260. },
  13261. // string-asc and -desc are retained only for compatibility with the old
  13262. // sort methods
  13263. "string-asc": function stringAsc(x, y) {
  13264. return x < y ? - 1 : x > y ? 1 : 0;
  13265. },
  13266. "string-desc": function stringDesc(x, y) {
  13267. return x < y ? 1 : x > y ? - 1 : 0;
  13268. }
  13269. });
  13270. // Numeric sorting types - order doesn't matter here
  13271. _addNumericSort('');
  13272. $.extend(true, DataTable.ext.renderer, {
  13273. header: {
  13274. _: function _(settings, cell, column, classes) {
  13275. // No additional mark-up required
  13276. // Attach a sort listener to update on sort - note that using the
  13277. // `DT` namespace will allow the event to be removed automatically
  13278. // on destroy, while the `dt` namespaced event is the one we are
  13279. // listening for
  13280. $(settings.nTable).on('order.dt.DT', function (e, ctx, sorting, columns) {
  13281. if (settings !== ctx) {
  13282. // need to check this this is the host
  13283. return; // table, not a nested one
  13284. }
  13285. var colIdx = column.idx;
  13286. cell.removeClass(column.sSortingClass + ' ' + classes.sSortAsc + ' ' + classes.sSortDesc).addClass(columns[colIdx] == 'asc' ? classes.sSortAsc : columns[colIdx] == 'desc' ? classes.sSortDesc : column.sSortingClass);
  13287. });
  13288. },
  13289. jqueryui: function jqueryui(settings, cell, column, classes) {
  13290. $('<div/>').addClass(classes.sSortJUIWrapper).append(cell.contents()).append($('<span/>').addClass(classes.sSortIcon + ' ' + column.sSortingClassJUI)).appendTo(cell);
  13291. // Attach a sort listener to update on sort
  13292. $(settings.nTable).on('order.dt.DT', function (e, ctx, sorting, columns) {
  13293. if (settings !== ctx) {
  13294. return;
  13295. }
  13296. var colIdx = column.idx;
  13297. cell.removeClass(classes.sSortAsc + " " + classes.sSortDesc).addClass(columns[colIdx] == 'asc' ? classes.sSortAsc : columns[colIdx] == 'desc' ? classes.sSortDesc : column.sSortingClass);
  13298. cell.find('span.' + classes.sSortIcon).removeClass(classes.sSortJUIAsc + " " + classes.sSortJUIDesc + " " + classes.sSortJUI + " " + classes.sSortJUIAscAllowed + " " + classes.sSortJUIDescAllowed).addClass(columns[colIdx] == 'asc' ? classes.sSortJUIAsc : columns[colIdx] == 'desc' ? classes.sSortJUIDesc : column.sSortingClassJUI);
  13299. });
  13300. }
  13301. }
  13302. });
  13303. /*
  13304. * Public helper functions. These aren't used internally by DataTables, or
  13305. * called by any of the options passed into DataTables, but they can be used
  13306. * externally by developers working with DataTables. They are helper functions
  13307. * to make working with DataTables a little bit easier.
  13308. */
  13309. var __htmlEscapeEntities = function __htmlEscapeEntities(d) {
  13310. return typeof d === 'string' ? d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') : d;
  13311. };
  13312. /**
  13313. * Helpers for `columns.render`.
  13314. *
  13315. * The options defined here can be used with the `columns.render` initialisation
  13316. * option to provide a display renderer. The following functions are defined:
  13317. *
  13318. * * `number` - Will format numeric data (defined by `columns.data`) for
  13319. * display, retaining the original unformatted data for sorting and filtering.
  13320. * It takes 5 parameters:
  13321. * * `string` - Thousands grouping separator
  13322. * * `string` - Decimal point indicator
  13323. * * `integer` - Number of decimal points to show
  13324. * * `string` (optional) - Prefix.
  13325. * * `string` (optional) - Postfix (/suffix).
  13326. * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
  13327. * parameters.
  13328. *
  13329. * @example
  13330. * // Column definition using the number renderer
  13331. * {
  13332. * data: "salary",
  13333. * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
  13334. * }
  13335. *
  13336. * @namespace
  13337. */
  13338. DataTable.render = {
  13339. number: function number(thousands, decimal, precision, prefix, postfix) {
  13340. return {
  13341. display: function display(d) {
  13342. if (typeof d !== 'number' && typeof d !== 'string') {
  13343. return d;
  13344. }
  13345. var negative = d < 0 ? '-' : '';
  13346. var flo = parseFloat(d);
  13347. // If NaN then there isn't much formatting that we can do - just
  13348. // return immediately, escaping any HTML (this was supposed to
  13349. // be a number after all)
  13350. if (isNaN(flo)) {
  13351. return __htmlEscapeEntities(d);
  13352. }
  13353. flo = flo.toFixed(precision);
  13354. d = Math.abs(flo);
  13355. var intPart = parseInt(d, 10);
  13356. var floatPart = precision ? decimal + (d - intPart).toFixed(precision).substring(2) : '';
  13357. return negative + (prefix || '') + intPart.toString().replace(/\B(?=(\d{3})+(?!\d))/g, thousands) + floatPart + (postfix || '');
  13358. }
  13359. };
  13360. },
  13361. text: function text() {
  13362. return {
  13363. display: __htmlEscapeEntities
  13364. };
  13365. }
  13366. };
  13367. /*
  13368. * This is really a good bit rubbish this method of exposing the internal methods
  13369. * publicly... - To be fixed in 2.0 using methods on the prototype
  13370. */
  13371. /**
  13372. * Create a wrapper function for exporting an internal functions to an external API.
  13373. * @param {string} fn API function name
  13374. * @returns {function} wrapped function
  13375. * @memberof DataTable#internal
  13376. */
  13377. function _fnExternApiFunc(fn) {
  13378. return function () {
  13379. var args = [_fnSettingsFromNode(this[DataTable.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));
  13380. return DataTable.ext.internal[fn].apply(this, args);
  13381. };
  13382. }
  13383. /**
  13384. * Reference to internal functions for use by plug-in developers. Note that
  13385. * these methods are references to internal functions and are considered to be
  13386. * private. If you use these methods, be aware that they are liable to change
  13387. * between versions.
  13388. * @namespace
  13389. */
  13390. $.extend(DataTable.ext.internal, {
  13391. _fnExternApiFunc: _fnExternApiFunc,
  13392. _fnBuildAjax: _fnBuildAjax,
  13393. _fnAjaxUpdate: _fnAjaxUpdate,
  13394. _fnAjaxParameters: _fnAjaxParameters,
  13395. _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
  13396. _fnAjaxDataSrc: _fnAjaxDataSrc,
  13397. _fnAddColumn: _fnAddColumn,
  13398. _fnColumnOptions: _fnColumnOptions,
  13399. _fnAdjustColumnSizing: _fnAdjustColumnSizing,
  13400. _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
  13401. _fnColumnIndexToVisible: _fnColumnIndexToVisible,
  13402. _fnVisbleColumns: _fnVisbleColumns,
  13403. _fnGetColumns: _fnGetColumns,
  13404. _fnColumnTypes: _fnColumnTypes,
  13405. _fnApplyColumnDefs: _fnApplyColumnDefs,
  13406. _fnHungarianMap: _fnHungarianMap,
  13407. _fnCamelToHungarian: _fnCamelToHungarian,
  13408. _fnLanguageCompat: _fnLanguageCompat,
  13409. _fnBrowserDetect: _fnBrowserDetect,
  13410. _fnAddData: _fnAddData,
  13411. _fnAddTr: _fnAddTr,
  13412. _fnNodeToDataIndex: _fnNodeToDataIndex,
  13413. _fnNodeToColumnIndex: _fnNodeToColumnIndex,
  13414. _fnGetCellData: _fnGetCellData,
  13415. _fnSetCellData: _fnSetCellData,
  13416. _fnSplitObjNotation: _fnSplitObjNotation,
  13417. _fnGetObjectDataFn: _fnGetObjectDataFn,
  13418. _fnSetObjectDataFn: _fnSetObjectDataFn,
  13419. _fnGetDataMaster: _fnGetDataMaster,
  13420. _fnClearTable: _fnClearTable,
  13421. _fnDeleteIndex: _fnDeleteIndex,
  13422. _fnInvalidate: _fnInvalidate,
  13423. _fnGetRowElements: _fnGetRowElements,
  13424. _fnCreateTr: _fnCreateTr,
  13425. _fnBuildHead: _fnBuildHead,
  13426. _fnDrawHead: _fnDrawHead,
  13427. _fnDraw: _fnDraw,
  13428. _fnReDraw: _fnReDraw,
  13429. _fnAddOptionsHtml: _fnAddOptionsHtml,
  13430. _fnDetectHeader: _fnDetectHeader,
  13431. _fnGetUniqueThs: _fnGetUniqueThs,
  13432. _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
  13433. _fnFilterComplete: _fnFilterComplete,
  13434. _fnFilterCustom: _fnFilterCustom,
  13435. _fnFilterColumn: _fnFilterColumn,
  13436. _fnFilter: _fnFilter,
  13437. _fnFilterCreateSearch: _fnFilterCreateSearch,
  13438. _fnEscapeRegex: _fnEscapeRegex,
  13439. _fnFilterData: _fnFilterData,
  13440. _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
  13441. _fnUpdateInfo: _fnUpdateInfo,
  13442. _fnInfoMacros: _fnInfoMacros,
  13443. _fnInitialise: _fnInitialise,
  13444. _fnInitComplete: _fnInitComplete,
  13445. _fnLengthChange: _fnLengthChange,
  13446. _fnFeatureHtmlLength: _fnFeatureHtmlLength,
  13447. _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
  13448. _fnPageChange: _fnPageChange,
  13449. _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
  13450. _fnProcessingDisplay: _fnProcessingDisplay,
  13451. _fnFeatureHtmlTable: _fnFeatureHtmlTable,
  13452. _fnScrollDraw: _fnScrollDraw,
  13453. _fnApplyToChildren: _fnApplyToChildren,
  13454. _fnCalculateColumnWidths: _fnCalculateColumnWidths,
  13455. _fnThrottle: _fnThrottle,
  13456. _fnConvertToWidth: _fnConvertToWidth,
  13457. _fnGetWidestNode: _fnGetWidestNode,
  13458. _fnGetMaxLenString: _fnGetMaxLenString,
  13459. _fnStringToCss: _fnStringToCss,
  13460. _fnSortFlatten: _fnSortFlatten,
  13461. _fnSort: _fnSort,
  13462. _fnSortAria: _fnSortAria,
  13463. _fnSortListener: _fnSortListener,
  13464. _fnSortAttachListener: _fnSortAttachListener,
  13465. _fnSortingClasses: _fnSortingClasses,
  13466. _fnSortData: _fnSortData,
  13467. _fnSaveState: _fnSaveState,
  13468. _fnLoadState: _fnLoadState,
  13469. _fnSettingsFromNode: _fnSettingsFromNode,
  13470. _fnLog: _fnLog,
  13471. _fnMap: _fnMap,
  13472. _fnBindAction: _fnBindAction,
  13473. _fnCallbackReg: _fnCallbackReg,
  13474. _fnCallbackFire: _fnCallbackFire,
  13475. _fnLengthOverflow: _fnLengthOverflow,
  13476. _fnRenderer: _fnRenderer,
  13477. _fnDataSource: _fnDataSource,
  13478. _fnRowAttributes: _fnRowAttributes,
  13479. _fnCalculateEnd: function _fnCalculateEnd() {} // Used by a lot of plug-ins, but redundant
  13480. // in 1.10, so this dead-end function is
  13481. // added to prevent errors
  13482. });
  13483. // jQuery access
  13484. $.fn.dataTable = DataTable;
  13485. // Provide access to the host jQuery object (circular reference)
  13486. DataTable.$ = $;
  13487. // Legacy aliases
  13488. $.fn.dataTableSettings = DataTable.settings;
  13489. $.fn.dataTableExt = DataTable.ext;
  13490. // With a capital `D` we return a DataTables API instance rather than a
  13491. // jQuery object
  13492. $.fn.DataTable = function (opts) {
  13493. return $(this).dataTable(opts).api();
  13494. };
  13495. // All properties that are available to $.fn.dataTable should also be
  13496. // available on $.fn.DataTable
  13497. $.each(DataTable, function (prop, val) {
  13498. $.fn.DataTable[prop] = val;
  13499. });
  13500. // Information about events fired by DataTables - for documentation.
  13501. /**
  13502. * Draw event, fired whenever the table is redrawn on the page, at the same
  13503. * point as fnDrawCallback. This may be useful for binding events or
  13504. * performing calculations when the table is altered at all.
  13505. * @name DataTable#draw.dt
  13506. * @event
  13507. * @param {event} e jQuery event object
  13508. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  13509. */
  13510. /**
  13511. * Search event, fired when the searching applied to the table (using the
  13512. * built-in global search, or column filters) is altered.
  13513. * @name DataTable#search.dt
  13514. * @event
  13515. * @param {event} e jQuery event object
  13516. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  13517. */
  13518. /**
  13519. * Page change event, fired when the paging of the table is altered.
  13520. * @name DataTable#page.dt
  13521. * @event
  13522. * @param {event} e jQuery event object
  13523. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  13524. */
  13525. /**
  13526. * Order event, fired when the ordering applied to the table is altered.
  13527. * @name DataTable#order.dt
  13528. * @event
  13529. * @param {event} e jQuery event object
  13530. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  13531. */
  13532. /**
  13533. * DataTables initialisation complete event, fired when the table is fully
  13534. * drawn, including Ajax data loaded, if Ajax data is required.
  13535. * @name DataTable#init.dt
  13536. * @event
  13537. * @param {event} e jQuery event object
  13538. * @param {object} oSettings DataTables settings object
  13539. * @param {object} json The JSON object request from the server - only
  13540. * present if client-side Ajax sourced data is used</li></ol>
  13541. */
  13542. /**
  13543. * State save event, fired when the table has changed state a new state save
  13544. * is required. This event allows modification of the state saving object
  13545. * prior to actually doing the save, including addition or other state
  13546. * properties (for plug-ins) or modification of a DataTables core property.
  13547. * @name DataTable#stateSaveParams.dt
  13548. * @event
  13549. * @param {event} e jQuery event object
  13550. * @param {object} oSettings DataTables settings object
  13551. * @param {object} json The state information to be saved
  13552. */
  13553. /**
  13554. * State load event, fired when the table is loading state from the stored
  13555. * data, but prior to the settings object being modified by the saved state
  13556. * - allowing modification of the saved state is required or loading of
  13557. * state for a plug-in.
  13558. * @name DataTable#stateLoadParams.dt
  13559. * @event
  13560. * @param {event} e jQuery event object
  13561. * @param {object} oSettings DataTables settings object
  13562. * @param {object} json The saved state information
  13563. */
  13564. /**
  13565. * State loaded event, fired when state has been loaded from stored data and
  13566. * the settings object has been modified by the loaded data.
  13567. * @name DataTable#stateLoaded.dt
  13568. * @event
  13569. * @param {event} e jQuery event object
  13570. * @param {object} oSettings DataTables settings object
  13571. * @param {object} json The saved state information
  13572. */
  13573. /**
  13574. * Processing event, fired when DataTables is doing some kind of processing
  13575. * (be it, order, searcg or anything else). It can be used to indicate to
  13576. * the end user that there is something happening, or that something has
  13577. * finished.
  13578. * @name DataTable#processing.dt
  13579. * @event
  13580. * @param {event} e jQuery event object
  13581. * @param {object} oSettings DataTables settings object
  13582. * @param {boolean} bShow Flag for if DataTables is doing processing or not
  13583. */
  13584. /**
  13585. * Ajax (XHR) event, fired whenever an Ajax request is completed from a
  13586. * request to made to the server for new data. This event is called before
  13587. * DataTables processed the returned data, so it can also be used to pre-
  13588. * process the data returned from the server, if needed.
  13589. *
  13590. * Note that this trigger is called in `fnServerData`, if you override
  13591. * `fnServerData` and which to use this event, you need to trigger it in you
  13592. * success function.
  13593. * @name DataTable#xhr.dt
  13594. * @event
  13595. * @param {event} e jQuery event object
  13596. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  13597. * @param {object} json JSON returned from the server
  13598. *
  13599. * @example
  13600. * // Use a custom property returned from the server in another DOM element
  13601. * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
  13602. * $('#status').html( json.status );
  13603. * } );
  13604. *
  13605. * @example
  13606. * // Pre-process the data returned from the server
  13607. * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
  13608. * for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
  13609. * json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
  13610. * }
  13611. * // Note no return - manipulate the data directly in the JSON object.
  13612. * } );
  13613. */
  13614. /**
  13615. * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
  13616. * or passing the bDestroy:true parameter in the initialisation object. This
  13617. * can be used to remove bound events, added DOM nodes, etc.
  13618. * @name DataTable#destroy.dt
  13619. * @event
  13620. * @param {event} e jQuery event object
  13621. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  13622. */
  13623. /**
  13624. * Page length change event, fired when number of records to show on each
  13625. * page (the length) is changed.
  13626. * @name DataTable#length.dt
  13627. * @event
  13628. * @param {event} e jQuery event object
  13629. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  13630. * @param {integer} len New length
  13631. */
  13632. /**
  13633. * Column sizing has changed.
  13634. * @name DataTable#column-sizing.dt
  13635. * @event
  13636. * @param {event} e jQuery event object
  13637. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  13638. */
  13639. /**
  13640. * Column visibility has changed.
  13641. * @name DataTable#column-visibility.dt
  13642. * @event
  13643. * @param {event} e jQuery event object
  13644. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  13645. * @param {int} column Column index
  13646. * @param {bool} vis `false` if column now hidden, or `true` if visible
  13647. */
  13648. return $.fn.dataTable;
  13649. });
  13650. /***/ }),
  13651. /***/ 40:
  13652. /***/ (function (module, exports, __webpack_require__) {
  13653. module.exports = __webpack_require__(7);
  13654. /***/ }),
  13655. /***/ 7:
  13656. /***/ (function (module, exports, __webpack_require__) {
  13657. "use strict";
  13658. var _createClass = function () {
  13659. function defineProperties(target, props) {
  13660. for (var i = 0; i < props.length; i++) {
  13661. var descriptor = props[i];
  13662. descriptor.enumerable = descriptor.enumerable || false;
  13663. descriptor.configurable = true;
  13664. if ("value" in descriptor)
  13665. descriptor.writable = true;
  13666. Object.defineProperty(target, descriptor.key, descriptor);
  13667. }
  13668. }
  13669. return function (Constructor, protoProps, staticProps) {
  13670. if (protoProps)
  13671. defineProperties(Constructor.prototype, protoProps);
  13672. if (staticProps)
  13673. defineProperties(Constructor, staticProps);
  13674. return Constructor;
  13675. };
  13676. }();
  13677. var _datatables = __webpack_require__(2);
  13678. var _datatables2 = _interopRequireDefault(_datatables);
  13679. __webpack_require__(9);
  13680. __webpack_require__(10);
  13681. var _util = __webpack_require__(0);
  13682. var _util2 = _interopRequireDefault(_util);
  13683. function _interopRequireDefault(obj) {
  13684. return obj && obj.__esModule ? obj : {default: obj};
  13685. }
  13686. function _classCallCheck(instance, Constructor) {
  13687. if (!(instance instanceof Constructor)) {
  13688. throw new TypeError("Cannot call a class as a function");
  13689. }
  13690. }
  13691. var SELECTORS = {
  13692. table: '[data-data-table]',
  13693. container: '[data-table-container]',
  13694. preloader: '[data-table-preloader]',
  13695. showAll: '[data-show-all]',
  13696. showAllIcon: '[data-show-all-icon]'
  13697. };
  13698. var Default = {
  13699. activeElement: 2,
  13700. filterActiveClass: '.is-active',
  13701. transition: 'all 500ms cubic-bezier(.250, .250, .000, 1.015)',
  13702. pageLenght: 10,
  13703. domPattern: '<t><"t-c__footer table-footer"p B>',
  13704. noSortClass: 'no-sort',
  13705. hiddenClass: 'hidden'
  13706. };
  13707. var templates = {};
  13708. var DataTableInit = function () {
  13709. function DataTableInit(table, options) {
  13710. _classCallCheck(this, DataTableInit);
  13711. this.table = $(table);
  13712. this.options = options;
  13713. this.container = this.table.closest(SELECTORS.container);
  13714. this.preloader = this.container.find(SELECTORS.preloader);
  13715. this.getConfig();
  13716. this.initPlugin();
  13717. this.bindEvents();
  13718. }
  13719. _createClass(DataTableInit, [{
  13720. key: 'getConfig',
  13721. value: function getConfig() {
  13722. var dataConfig = this.table.data();
  13723. if (dataConfig.options) {
  13724. this.dataOptions = _util2.default.parseDataOptions(dataConfig.options);
  13725. } else {
  13726. this.dataOptions = {};
  13727. }
  13728. this.config = $.extend({}, Default, dataConfig, this.dataOptions, this.options);
  13729. }
  13730. }, {
  13731. key: 'bindEvents',
  13732. value: function bindEvents() {}
  13733. }, {
  13734. key: 'initPlugin',
  13735. value: function initPlugin() {
  13736. var that = this;
  13737. this.dataTable = this.table.dataTable({
  13738. "dom": this.config.domPattern,
  13739. "order": [[0, "asc"]],
  13740. "autoWidth": false,
  13741. "pageLength": this.config.pageLenght,
  13742. "responsive": {
  13743. details: {
  13744. type: 'column',
  13745. target: '[data-show-all]',
  13746. renderer: function renderer(api, rowIdx, columns) {
  13747. columns.shift();
  13748. columns.pop();
  13749. var data = $.map(columns, function (col, i) {
  13750. return col.hidden ? '\n <li>\n <strong>' + col.title + '</strong>' + col.data + '\n </li> \n ' : '';
  13751. }).join('');
  13752. data = ' \n <ul class="child-table"> \n ' + data + ' \n </ul> \n ';
  13753. return data ? data : false;
  13754. }
  13755. }
  13756. },
  13757. "language": {
  13758. "paginate": {
  13759. "previous": "",
  13760. "next": ""
  13761. }
  13762. },
  13763. "columnDefs": [{
  13764. "targets": 'no-sort',
  13765. "orderable": false
  13766. }, {
  13767. "targets": 'filter',
  13768. "name": 'filter'
  13769. }, {responsivePriority: 0, targets: - 1}],
  13770. buttons: [{
  13771. text: '10',
  13772. action: function action(e, dt, node, config) {
  13773. dt.page.len(10).draw();
  13774. $(node).parent().find('.active').removeClass('active');
  13775. $(node).addClass('active');
  13776. },
  13777. init: function init(dt, node, config) {
  13778. $(node).addClass('active');
  13779. }
  13780. }, {
  13781. text: '25',
  13782. action: function action(e, dt, node, config) {
  13783. dt.page.len(25).draw();
  13784. $(node).parent().find('.active').removeClass('active');
  13785. $(node).addClass('active');
  13786. }
  13787. }, {
  13788. text: '∞',
  13789. action: function action(e, dt, node, config) {
  13790. dt.page.len(1000).draw();
  13791. $(node).parent().find('.active').removeClass('active');
  13792. $(node).addClass('active');
  13793. }
  13794. }],
  13795. 'drawCallback': function drawCallback() {},
  13796. 'initComplete': function initComplete() {
  13797. that.togglePreloader(this.api());
  13798. window.testapi = this.api();
  13799. }
  13800. });
  13801. this.customSearch();
  13802. }
  13803. }, {
  13804. key: 'customSearch',
  13805. value: function customSearch() {
  13806. var _this = this;
  13807. if (!this.config.tableSearch) {
  13808. return;
  13809. }
  13810. var searchInput = $(this.config.tableSearch);
  13811. searchInput.on('keyup', function (event) {
  13812. _this.dataTable.search('\\b' + event.target.value, true).draw();
  13813. });
  13814. }
  13815. }, {
  13816. key: 'togglePreloader',
  13817. value: function togglePreloader(api) {
  13818. setTimeout(function () {
  13819. api.responsive.recalc();
  13820. }, 1000);
  13821. this.preloader.addClass(this.config.hiddenClass);
  13822. this.table.removeClass(this.config.hiddenClass);
  13823. }
  13824. }]);
  13825. return DataTableInit;
  13826. }();
  13827. function initDataSelectors() {
  13828. $(SELECTORS.table).each(function () {
  13829. new DataTableInit($(this));
  13830. });
  13831. }
  13832. function initJqueryPlugin() {
  13833. $.fn.luDataTable = function (options) {
  13834. return this.each(function () {
  13835. new DataTableInit($(this), options);
  13836. });
  13837. };
  13838. }
  13839. var init = {
  13840. initDataSelectors: initDataSelectors,
  13841. initJqueryPlugin: initJqueryPlugin
  13842. };
  13843. $(document).ready(function () {
  13844. init.initDataSelectors();
  13845. init.initJqueryPlugin();
  13846. });
  13847. /***/ }),
  13848. /***/ 9:
  13849. /***/ (function (module, exports, __webpack_require__) {
  13850. "use strict";
  13851. var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;
  13852. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  13853. return typeof obj;
  13854. } : function (obj) {
  13855. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  13856. };
  13857. /*! Buttons for DataTables 1.4.2
  13858. * ©2016-2017 SpryMedia Ltd - datatables.net/license
  13859. */
  13860. (function (factory) {
  13861. if (true) {
  13862. // AMD
  13863. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1), __webpack_require__(2)], __WEBPACK_AMD_DEFINE_RESULT__ = function ($) {
  13864. return factory($, window, document);
  13865. }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
  13866. __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  13867. } else if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
  13868. // CommonJS
  13869. module.exports = function (root, $) {
  13870. if (!root) {
  13871. root = window;
  13872. }
  13873. if (!$ || !$.fn.dataTable) {
  13874. $ = require('datatables.net')(root, $).$;
  13875. }
  13876. return factory($, root, root.document);
  13877. };
  13878. } else {
  13879. // Browser
  13880. factory(jQuery, window, document);
  13881. }
  13882. })(function ($, window, document, undefined) {
  13883. 'use strict';
  13884. var DataTable = $.fn.dataTable;
  13885. // Used for namespacing events added to the document by each instance, so they
  13886. // can be removed on destroy
  13887. var _instCounter = 0;
  13888. // Button namespacing counter for namespacing events on individual buttons
  13889. var _buttonCounter = 0;
  13890. var _dtButtons = DataTable.ext.buttons;
  13891. /**
  13892. * [Buttons description]
  13893. * @param {[type]}
  13894. * @param {[type]}
  13895. */
  13896. var Buttons = function Buttons(dt, config) {
  13897. // If there is no config set it to an empty object
  13898. if (typeof config === 'undefined') {
  13899. config = {};
  13900. }
  13901. // Allow a boolean true for defaults
  13902. if (config === true) {
  13903. config = {};
  13904. }
  13905. // For easy configuration of buttons an array can be given
  13906. if ($.isArray(config)) {
  13907. config = {buttons: config};
  13908. }
  13909. this.c = $.extend(true, {}, Buttons.defaults, config);
  13910. // Don't want a deep copy for the buttons
  13911. if (config.buttons) {
  13912. this.c.buttons = config.buttons;
  13913. }
  13914. this.s = {
  13915. dt: new DataTable.Api(dt),
  13916. buttons: [],
  13917. listenKeys: '',
  13918. namespace: 'dtb' + _instCounter++
  13919. };
  13920. this.dom = {
  13921. container: $('<' + this.c.dom.container.tag + '/>').addClass(this.c.dom.container.className)
  13922. };
  13923. this._constructor();
  13924. };
  13925. $.extend(Buttons.prototype, {
  13926. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  13927. * Public methods
  13928. */
  13929. /**
  13930. * Get the action of a button
  13931. * @param {int|string} Button index
  13932. * @return {function}
  13933. */ /**
  13934. * Set the action of a button
  13935. * @param {node} node Button element
  13936. * @param {function} action Function to set
  13937. * @return {Buttons} Self for chaining
  13938. */
  13939. action: function action(node, _action) {
  13940. var button = this._nodeToButton(node);
  13941. if (_action === undefined) {
  13942. return button.conf.action;
  13943. }
  13944. button.conf.action = _action;
  13945. return this;
  13946. },
  13947. /**
  13948. * Add an active class to the button to make to look active or get current
  13949. * active state.
  13950. * @param {node} node Button element
  13951. * @param {boolean} [flag] Enable / disable flag
  13952. * @return {Buttons} Self for chaining or boolean for getter
  13953. */
  13954. active: function active(node, flag) {
  13955. var button = this._nodeToButton(node);
  13956. var klass = this.c.dom.button.active;
  13957. var jqNode = $(button.node);
  13958. if (flag === undefined) {
  13959. return jqNode.hasClass(klass);
  13960. }
  13961. jqNode.toggleClass(klass, flag === undefined ? true : flag);
  13962. return this;
  13963. },
  13964. /**
  13965. * Add a new button
  13966. * @param {object} config Button configuration object, base string name or function
  13967. * @param {int|string} [idx] Button index for where to insert the button
  13968. * @return {Buttons} Self for chaining
  13969. */
  13970. add: function add(config, idx) {
  13971. var buttons = this.s.buttons;
  13972. if (typeof idx === 'string') {
  13973. var split = idx.split('-');
  13974. var base = this.s;
  13975. for (var i = 0, ien = split.length - 1; i < ien; i++) {
  13976. base = base.buttons[split[i] * 1];
  13977. }
  13978. buttons = base.buttons;
  13979. idx = split[split.length - 1] * 1;
  13980. }
  13981. this._expandButton(buttons, config, false, idx);
  13982. this._draw();
  13983. return this;
  13984. },
  13985. /**
  13986. * Get the container node for the buttons
  13987. * @return {jQuery} Buttons node
  13988. */
  13989. container: function container() {
  13990. return this.dom.container;
  13991. },
  13992. /**
  13993. * Disable a button
  13994. * @param {node} node Button node
  13995. * @return {Buttons} Self for chaining
  13996. */
  13997. disable: function disable(node) {
  13998. var button = this._nodeToButton(node);
  13999. $(button.node).addClass(this.c.dom.button.disabled);
  14000. return this;
  14001. },
  14002. /**
  14003. * Destroy the instance, cleaning up event handlers and removing DOM
  14004. * elements
  14005. * @return {Buttons} Self for chaining
  14006. */
  14007. destroy: function destroy() {
  14008. // Key event listener
  14009. $('body').off('keyup.' + this.s.namespace);
  14010. // Individual button destroy (so they can remove their own events if
  14011. // needed). Take a copy as the array is modified by `remove`
  14012. var buttons = this.s.buttons.slice();
  14013. var i, ien;
  14014. for (i = 0, ien = buttons.length; i < ien; i++) {
  14015. this.remove(buttons[i].node);
  14016. }
  14017. // Container
  14018. this.dom.container.remove();
  14019. // Remove from the settings object collection
  14020. var buttonInsts = this.s.dt.settings()[0];
  14021. for (i = 0, ien = buttonInsts.length; i < ien; i++) {
  14022. if (buttonInsts.inst === this) {
  14023. buttonInsts.splice(i, 1);
  14024. break;
  14025. }
  14026. }
  14027. return this;
  14028. },
  14029. /**
  14030. * Enable / disable a button
  14031. * @param {node} node Button node
  14032. * @param {boolean} [flag=true] Enable / disable flag
  14033. * @return {Buttons} Self for chaining
  14034. */
  14035. enable: function enable(node, flag) {
  14036. if (flag === false) {
  14037. return this.disable(node);
  14038. }
  14039. var button = this._nodeToButton(node);
  14040. $(button.node).removeClass(this.c.dom.button.disabled);
  14041. return this;
  14042. },
  14043. /**
  14044. * Get the instance name for the button set selector
  14045. * @return {string} Instance name
  14046. */
  14047. name: function name() {
  14048. return this.c.name;
  14049. },
  14050. /**
  14051. * Get a button's node
  14052. * @param {node} node Button node
  14053. * @return {jQuery} Button element
  14054. */
  14055. node: function node(_node) {
  14056. var button = this._nodeToButton(_node);
  14057. return $(button.node);
  14058. },
  14059. /**
  14060. * Set / get a processing class on the selected button
  14061. * @param {boolean} flag true to add, false to remove, undefined to get
  14062. * @return {boolean|Buttons} Getter value or this if a setter.
  14063. */
  14064. processing: function processing(node, flag) {
  14065. var button = this._nodeToButton(node);
  14066. if (flag === undefined) {
  14067. return $(button.node).hasClass('processing');
  14068. }
  14069. $(button.node).toggleClass('processing', flag);
  14070. return this;
  14071. },
  14072. /**
  14073. * Remove a button.
  14074. * @param {node} node Button node
  14075. * @return {Buttons} Self for chaining
  14076. */
  14077. remove: function remove(node) {
  14078. var button = this._nodeToButton(node);
  14079. var host = this._nodeToHost(node);
  14080. var dt = this.s.dt;
  14081. // Remove any child buttons first
  14082. if (button.buttons.length) {
  14083. for (var i = button.buttons.length - 1; i >= 0; i--) {
  14084. this.remove(button.buttons[i].node);
  14085. }
  14086. }
  14087. // Allow the button to remove event handlers, etc
  14088. if (button.conf.destroy) {
  14089. button.conf.destroy.call(dt.button(node), dt, $(node), button.conf);
  14090. }
  14091. this._removeKey(button.conf);
  14092. $(button.node).remove();
  14093. var idx = $.inArray(button, host);
  14094. host.splice(idx, 1);
  14095. return this;
  14096. },
  14097. /**
  14098. * Get the text for a button
  14099. * @param {int|string} node Button index
  14100. * @return {string} Button text
  14101. */ /**
  14102. * Set the text for a button
  14103. * @param {int|string|function} node Button index
  14104. * @param {string} label Text
  14105. * @return {Buttons} Self for chaining
  14106. */
  14107. text: function text(node, label) {
  14108. var button = this._nodeToButton(node);
  14109. var buttonLiner = this.c.dom.collection.buttonLiner;
  14110. var linerTag = button.inCollection && buttonLiner && buttonLiner.tag ? buttonLiner.tag : this.c.dom.buttonLiner.tag;
  14111. var dt = this.s.dt;
  14112. var jqNode = $(button.node);
  14113. var text = function text(opt) {
  14114. return typeof opt === 'function' ? opt(dt, jqNode, button.conf) : opt;
  14115. };
  14116. if (label === undefined) {
  14117. return text(button.conf.text);
  14118. }
  14119. button.conf.text = label;
  14120. if (linerTag) {
  14121. jqNode.children(linerTag).html(text(label));
  14122. } else {
  14123. jqNode.html(text(label));
  14124. }
  14125. return this;
  14126. },
  14127. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  14128. * Constructor
  14129. */
  14130. /**
  14131. * Buttons constructor
  14132. * @private
  14133. */
  14134. _constructor: function _constructor() {
  14135. var that = this;
  14136. var dt = this.s.dt;
  14137. var dtSettings = dt.settings()[0];
  14138. var buttons = this.c.buttons;
  14139. if (!dtSettings._buttons) {
  14140. dtSettings._buttons = [];
  14141. }
  14142. dtSettings._buttons.push({
  14143. inst: this,
  14144. name: this.c.name
  14145. });
  14146. for (var i = 0, ien = buttons.length; i < ien; i++) {
  14147. this.add(buttons[i]);
  14148. }
  14149. dt.on('destroy', function () {
  14150. that.destroy();
  14151. });
  14152. // Global key event binding to listen for button keys
  14153. $('body').on('keyup.' + this.s.namespace, function (e) {
  14154. if (!document.activeElement || document.activeElement === document.body) {
  14155. // SUse a string of characters for fast lookup of if we need to
  14156. // handle this
  14157. var character = String.fromCharCode(e.keyCode).toLowerCase();
  14158. if (that.s.listenKeys.toLowerCase().indexOf(character) !== - 1) {
  14159. that._keypress(character, e);
  14160. }
  14161. }
  14162. });
  14163. },
  14164. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  14165. * Private methods
  14166. */
  14167. /**
  14168. * Add a new button to the key press listener
  14169. * @param {object} conf Resolved button configuration object
  14170. * @private
  14171. */
  14172. _addKey: function _addKey(conf) {
  14173. if (conf.key) {
  14174. this.s.listenKeys += $.isPlainObject(conf.key) ? conf.key.key : conf.key;
  14175. }
  14176. },
  14177. /**
  14178. * Insert the buttons into the container. Call without parameters!
  14179. * @param {node} [container] Recursive only - Insert point
  14180. * @param {array} [buttons] Recursive only - Buttons array
  14181. * @private
  14182. */
  14183. _draw: function _draw(container, buttons) {
  14184. if (!container) {
  14185. container = this.dom.container;
  14186. buttons = this.s.buttons;
  14187. }
  14188. container.children().detach();
  14189. for (var i = 0, ien = buttons.length; i < ien; i++) {
  14190. container.append(buttons[i].inserter);
  14191. container.append(' ');
  14192. if (buttons[i].buttons && buttons[i].buttons.length) {
  14193. this._draw(buttons[i].collection, buttons[i].buttons);
  14194. }
  14195. }
  14196. },
  14197. /**
  14198. * Create buttons from an array of buttons
  14199. * @param {array} attachTo Buttons array to attach to
  14200. * @param {object} button Button definition
  14201. * @param {boolean} inCollection true if the button is in a collection
  14202. * @private
  14203. */
  14204. _expandButton: function _expandButton(attachTo, button, inCollection, attachPoint) {
  14205. var dt = this.s.dt;
  14206. var buttonCounter = 0;
  14207. var buttons = !$.isArray(button) ? [button] : button;
  14208. for (var i = 0, ien = buttons.length; i < ien; i++) {
  14209. var conf = this._resolveExtends(buttons[i]);
  14210. if (!conf) {
  14211. continue;
  14212. }
  14213. // If the configuration is an array, then expand the buttons at this
  14214. // point
  14215. if ($.isArray(conf)) {
  14216. this._expandButton(attachTo, conf, inCollection, attachPoint);
  14217. continue;
  14218. }
  14219. var built = this._buildButton(conf, inCollection);
  14220. if (!built) {
  14221. continue;
  14222. }
  14223. if (attachPoint !== undefined) {
  14224. attachTo.splice(attachPoint, 0, built);
  14225. attachPoint++;
  14226. } else {
  14227. attachTo.push(built);
  14228. }
  14229. if (built.conf.buttons) {
  14230. var collectionDom = this.c.dom.collection;
  14231. built.collection = $('<' + collectionDom.tag + '/>').addClass(collectionDom.className).attr('role', 'menu');
  14232. built.conf._collection = built.collection;
  14233. this._expandButton(built.buttons, built.conf.buttons, true, attachPoint);
  14234. }
  14235. // init call is made here, rather than buildButton as it needs to
  14236. // be selectable, and for that it needs to be in the buttons array
  14237. if (conf.init) {
  14238. conf.init.call(dt.button(built.node), dt, $(built.node), conf);
  14239. }
  14240. buttonCounter++;
  14241. }
  14242. },
  14243. /**
  14244. * Create an individual button
  14245. * @param {object} config Resolved button configuration
  14246. * @param {boolean} inCollection `true` if a collection button
  14247. * @return {jQuery} Created button node (jQuery)
  14248. * @private
  14249. */
  14250. _buildButton: function _buildButton(config, inCollection) {
  14251. var buttonDom = this.c.dom.button;
  14252. var linerDom = this.c.dom.buttonLiner;
  14253. var collectionDom = this.c.dom.collection;
  14254. var dt = this.s.dt;
  14255. var text = function text(opt) {
  14256. return typeof opt === 'function' ? opt(dt, button, config) : opt;
  14257. };
  14258. if (inCollection && collectionDom.button) {
  14259. buttonDom = collectionDom.button;
  14260. }
  14261. if (inCollection && collectionDom.buttonLiner) {
  14262. linerDom = collectionDom.buttonLiner;
  14263. }
  14264. // Make sure that the button is available based on whatever requirements
  14265. // it has. For example, Flash buttons require Flash
  14266. if (config.available && !config.available(dt, config)) {
  14267. return false;
  14268. }
  14269. var action = function action(e, dt, button, config) {
  14270. config.action.call(dt.button(button), e, dt, button, config);
  14271. $(dt.table().node()).triggerHandler('buttons-action.dt', [dt.button(button), dt, button, config]);
  14272. };
  14273. var button = $('<' + buttonDom.tag + '/>').addClass(buttonDom.className).attr('tabindex', this.s.dt.settings()[0].iTabIndex).attr('aria-controls', this.s.dt.table().node().id).on('click.dtb', function (e) {
  14274. e.preventDefault();
  14275. if (!button.hasClass(buttonDom.disabled) && config.action) {
  14276. action(e, dt, button, config);
  14277. }
  14278. button.blur();
  14279. }).on('keyup.dtb', function (e) {
  14280. if (e.keyCode === 13) {
  14281. if (!button.hasClass(buttonDom.disabled) && config.action) {
  14282. action(e, dt, button, config);
  14283. }
  14284. }
  14285. });
  14286. // Make `a` tags act like a link
  14287. if (buttonDom.tag.toLowerCase() === 'a') {
  14288. button.attr('href', '#');
  14289. }
  14290. if (linerDom.tag) {
  14291. var liner = $('<' + linerDom.tag + '/>').html(text(config.text)).addClass(linerDom.className);
  14292. if (linerDom.tag.toLowerCase() === 'a') {
  14293. liner.attr('href', '#');
  14294. }
  14295. button.append(liner);
  14296. } else {
  14297. button.html(text(config.text));
  14298. }
  14299. if (config.enabled === false) {
  14300. button.addClass(buttonDom.disabled);
  14301. }
  14302. if (config.className) {
  14303. button.addClass(config.className);
  14304. }
  14305. if (config.titleAttr) {
  14306. button.attr('title', text(config.titleAttr));
  14307. }
  14308. if (!config.namespace) {
  14309. config.namespace = '.dt-button-' + _buttonCounter++;
  14310. }
  14311. var buttonContainer = this.c.dom.buttonContainer;
  14312. var inserter;
  14313. if (buttonContainer && buttonContainer.tag) {
  14314. inserter = $('<' + buttonContainer.tag + '/>').addClass(buttonContainer.className).append(button);
  14315. } else {
  14316. inserter = button;
  14317. }
  14318. this._addKey(config);
  14319. return {
  14320. conf: config,
  14321. node: button.get(0),
  14322. inserter: inserter,
  14323. buttons: [],
  14324. inCollection: inCollection,
  14325. collection: null
  14326. };
  14327. },
  14328. /**
  14329. * Get the button object from a node (recursive)
  14330. * @param {node} node Button node
  14331. * @param {array} [buttons] Button array, uses base if not defined
  14332. * @return {object} Button object
  14333. * @private
  14334. */
  14335. _nodeToButton: function _nodeToButton(node, buttons) {
  14336. if (!buttons) {
  14337. buttons = this.s.buttons;
  14338. }
  14339. for (var i = 0, ien = buttons.length; i < ien; i++) {
  14340. if (buttons[i].node === node) {
  14341. return buttons[i];
  14342. }
  14343. if (buttons[i].buttons.length) {
  14344. var ret = this._nodeToButton(node, buttons[i].buttons);
  14345. if (ret) {
  14346. return ret;
  14347. }
  14348. }
  14349. }
  14350. },
  14351. /**
  14352. * Get container array for a button from a button node (recursive)
  14353. * @param {node} node Button node
  14354. * @param {array} [buttons] Button array, uses base if not defined
  14355. * @return {array} Button's host array
  14356. * @private
  14357. */
  14358. _nodeToHost: function _nodeToHost(node, buttons) {
  14359. if (!buttons) {
  14360. buttons = this.s.buttons;
  14361. }
  14362. for (var i = 0, ien = buttons.length; i < ien; i++) {
  14363. if (buttons[i].node === node) {
  14364. return buttons;
  14365. }
  14366. if (buttons[i].buttons.length) {
  14367. var ret = this._nodeToHost(node, buttons[i].buttons);
  14368. if (ret) {
  14369. return ret;
  14370. }
  14371. }
  14372. }
  14373. },
  14374. /**
  14375. * Handle a key press - determine if any button's key configured matches
  14376. * what was typed and trigger the action if so.
  14377. * @param {string} character The character pressed
  14378. * @param {object} e Key event that triggered this call
  14379. * @private
  14380. */
  14381. _keypress: function _keypress(character, e) {
  14382. var run = function run(conf, node) {
  14383. if (!conf.key) {
  14384. return;
  14385. }
  14386. if (conf.key === character) {
  14387. $(node).click();
  14388. } else if ($.isPlainObject(conf.key)) {
  14389. if (conf.key.key !== character) {
  14390. return;
  14391. }
  14392. if (conf.key.shiftKey && !e.shiftKey) {
  14393. return;
  14394. }
  14395. if (conf.key.altKey && !e.altKey) {
  14396. return;
  14397. }
  14398. if (conf.key.ctrlKey && !e.ctrlKey) {
  14399. return;
  14400. }
  14401. if (conf.key.metaKey && !e.metaKey) {
  14402. return;
  14403. }
  14404. // Made it this far - it is good
  14405. $(node).click();
  14406. }
  14407. };
  14408. var recurse = function recurse(a) {
  14409. for (var i = 0, ien = a.length; i < ien; i++) {
  14410. run(a[i].conf, a[i].node);
  14411. if (a[i].buttons.length) {
  14412. recurse(a[i].buttons);
  14413. }
  14414. }
  14415. };
  14416. recurse(this.s.buttons);
  14417. },
  14418. /**
  14419. * Remove a key from the key listener for this instance (to be used when a
  14420. * button is removed)
  14421. * @param {object} conf Button configuration
  14422. * @private
  14423. */
  14424. _removeKey: function _removeKey(conf) {
  14425. if (conf.key) {
  14426. var character = $.isPlainObject(conf.key) ? conf.key.key : conf.key;
  14427. // Remove only one character, as multiple buttons could have the
  14428. // same listening key
  14429. var a = this.s.listenKeys.split('');
  14430. var idx = $.inArray(character, a);
  14431. a.splice(idx, 1);
  14432. this.s.listenKeys = a.join('');
  14433. }
  14434. },
  14435. /**
  14436. * Resolve a button configuration
  14437. * @param {string|function|object} conf Button config to resolve
  14438. * @return {object} Button configuration
  14439. * @private
  14440. */
  14441. _resolveExtends: function _resolveExtends(conf) {
  14442. var dt = this.s.dt;
  14443. var i, ien;
  14444. var toConfObject = function toConfObject(base) {
  14445. var loop = 0;
  14446. // Loop until we have resolved to a button configuration, or an
  14447. // array of button configurations (which will be iterated
  14448. // separately)
  14449. while (!$.isPlainObject(base) && !$.isArray(base)) {
  14450. if (base === undefined) {
  14451. return;
  14452. }
  14453. if (typeof base === 'function') {
  14454. base = base(dt, conf);
  14455. if (!base) {
  14456. return false;
  14457. }
  14458. } else if (typeof base === 'string') {
  14459. if (!_dtButtons[base]) {
  14460. throw 'Unknown button type: ' + base;
  14461. }
  14462. base = _dtButtons[base];
  14463. }
  14464. loop++;
  14465. if (loop > 30) {
  14466. // Protect against misconfiguration killing the browser
  14467. throw 'Buttons: Too many iterations';
  14468. }
  14469. }
  14470. return $.isArray(base) ? base : $.extend({}, base);
  14471. };
  14472. conf = toConfObject(conf);
  14473. while (conf && conf.extend) {
  14474. // Use `toConfObject` in case the button definition being extended
  14475. // is itself a string or a function
  14476. if (!_dtButtons[conf.extend]) {
  14477. throw 'Cannot extend unknown button type: ' + conf.extend;
  14478. }
  14479. var objArray = toConfObject(_dtButtons[conf.extend]);
  14480. if ($.isArray(objArray)) {
  14481. return objArray;
  14482. } else if (!objArray) {
  14483. // This is a little brutal as it might be possible to have a
  14484. // valid button without the extend, but if there is no extend
  14485. // then the host button would be acting in an undefined state
  14486. return false;
  14487. }
  14488. // Stash the current class name
  14489. var originalClassName = objArray.className;
  14490. conf = $.extend({}, objArray, conf);
  14491. // The extend will have overwritten the original class name if the
  14492. // `conf` object also assigned a class, but we want to concatenate
  14493. // them so they are list that is combined from all extended buttons
  14494. if (originalClassName && conf.className !== originalClassName) {
  14495. conf.className = originalClassName + ' ' + conf.className;
  14496. }
  14497. // Buttons to be added to a collection -gives the ability to define
  14498. // if buttons should be added to the start or end of a collection
  14499. var postfixButtons = conf.postfixButtons;
  14500. if (postfixButtons) {
  14501. if (!conf.buttons) {
  14502. conf.buttons = [];
  14503. }
  14504. for (i = 0, ien = postfixButtons.length; i < ien; i++) {
  14505. conf.buttons.push(postfixButtons[i]);
  14506. }
  14507. conf.postfixButtons = null;
  14508. }
  14509. var prefixButtons = conf.prefixButtons;
  14510. if (prefixButtons) {
  14511. if (!conf.buttons) {
  14512. conf.buttons = [];
  14513. }
  14514. for (i = 0, ien = prefixButtons.length; i < ien; i++) {
  14515. conf.buttons.splice(i, 0, prefixButtons[i]);
  14516. }
  14517. conf.prefixButtons = null;
  14518. }
  14519. // Although we want the `conf` object to overwrite almost all of
  14520. // the properties of the object being extended, the `extend`
  14521. // property should come from the object being extended
  14522. conf.extend = objArray.extend;
  14523. }
  14524. return conf;
  14525. }
  14526. });
  14527. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  14528. * Statics
  14529. */
  14530. /**
  14531. * Show / hide a background layer behind a collection
  14532. * @param {boolean} Flag to indicate if the background should be shown or
  14533. * hidden
  14534. * @param {string} Class to assign to the background
  14535. * @static
  14536. */
  14537. Buttons.background = function (show, className, fade) {
  14538. if (fade === undefined) {
  14539. fade = 400;
  14540. }
  14541. if (show) {
  14542. $('<div/>').addClass(className).css('display', 'none').appendTo('body').fadeIn(fade);
  14543. } else {
  14544. $('body > div.' + className).fadeOut(fade, function () {
  14545. $(this).removeClass(className).remove();
  14546. });
  14547. }
  14548. };
  14549. /**
  14550. * Instance selector - select Buttons instances based on an instance selector
  14551. * value from the buttons assigned to a DataTable. This is only useful if
  14552. * multiple instances are attached to a DataTable.
  14553. * @param {string|int|array} Instance selector - see `instance-selector`
  14554. * documentation on the DataTables site
  14555. * @param {array} Button instance array that was attached to the DataTables
  14556. * settings object
  14557. * @return {array} Buttons instances
  14558. * @static
  14559. */
  14560. Buttons.instanceSelector = function (group, buttons) {
  14561. if (!group) {
  14562. return $.map(buttons, function (v) {
  14563. return v.inst;
  14564. });
  14565. }
  14566. var ret = [];
  14567. var names = $.map(buttons, function (v) {
  14568. return v.name;
  14569. });
  14570. // Flatten the group selector into an array of single options
  14571. var process = function process(input) {
  14572. if ($.isArray(input)) {
  14573. for (var i = 0, ien = input.length; i < ien; i++) {
  14574. process(input[i]);
  14575. }
  14576. return;
  14577. }
  14578. if (typeof input === 'string') {
  14579. if (input.indexOf(',') !== - 1) {
  14580. // String selector, list of names
  14581. process(input.split(','));
  14582. } else {
  14583. // String selector individual name
  14584. var idx = $.inArray($.trim(input), names);
  14585. if (idx !== - 1) {
  14586. ret.push(buttons[idx].inst);
  14587. }
  14588. }
  14589. } else if (typeof input === 'number') {
  14590. // Index selector
  14591. ret.push(buttons[input].inst);
  14592. }
  14593. };
  14594. process(group);
  14595. return ret;
  14596. };
  14597. /**
  14598. * Button selector - select one or more buttons from a selector input so some
  14599. * operation can be performed on them.
  14600. * @param {array} Button instances array that the selector should operate on
  14601. * @param {string|int|node|jQuery|array} Button selector - see
  14602. * `button-selector` documentation on the DataTables site
  14603. * @return {array} Array of objects containing `inst` and `idx` properties of
  14604. * the selected buttons so you know which instance each button belongs to.
  14605. * @static
  14606. */
  14607. Buttons.buttonSelector = function (insts, selector) {
  14608. var ret = [];
  14609. var nodeBuilder = function nodeBuilder(a, buttons, baseIdx) {
  14610. var button;
  14611. var idx;
  14612. for (var i = 0, ien = buttons.length; i < ien; i++) {
  14613. button = buttons[i];
  14614. if (button) {
  14615. idx = baseIdx !== undefined ? baseIdx + i : i + '';
  14616. a.push({
  14617. node: button.node,
  14618. name: button.conf.name,
  14619. idx: idx
  14620. });
  14621. if (button.buttons) {
  14622. nodeBuilder(a, button.buttons, idx + '-');
  14623. }
  14624. }
  14625. }
  14626. };
  14627. var run = function run(selector, inst) {
  14628. var i, ien;
  14629. var buttons = [];
  14630. nodeBuilder(buttons, inst.s.buttons);
  14631. var nodes = $.map(buttons, function (v) {
  14632. return v.node;
  14633. });
  14634. if ($.isArray(selector) || selector instanceof $) {
  14635. for (i = 0, ien = selector.length; i < ien; i++) {
  14636. run(selector[i], inst);
  14637. }
  14638. return;
  14639. }
  14640. if (selector === null || selector === undefined || selector === '*') {
  14641. // Select all
  14642. for (i = 0, ien = buttons.length; i < ien; i++) {
  14643. ret.push({
  14644. inst: inst,
  14645. node: buttons[i].node
  14646. });
  14647. }
  14648. } else if (typeof selector === 'number') {
  14649. // Main button index selector
  14650. ret.push({
  14651. inst: inst,
  14652. node: inst.s.buttons[selector].node
  14653. });
  14654. } else if (typeof selector === 'string') {
  14655. if (selector.indexOf(',') !== - 1) {
  14656. // Split
  14657. var a = selector.split(',');
  14658. for (i = 0, ien = a.length; i < ien; i++) {
  14659. run($.trim(a[i]), inst);
  14660. }
  14661. } else if (selector.match(/^\d+(\-\d+)*$/)) {
  14662. // Sub-button index selector
  14663. var indexes = $.map(buttons, function (v) {
  14664. return v.idx;
  14665. });
  14666. ret.push({
  14667. inst: inst,
  14668. node: buttons[$.inArray(selector, indexes)].node
  14669. });
  14670. } else if (selector.indexOf(':name') !== - 1) {
  14671. // Button name selector
  14672. var name = selector.replace(':name', '');
  14673. for (i = 0, ien = buttons.length; i < ien; i++) {
  14674. if (buttons[i].name === name) {
  14675. ret.push({
  14676. inst: inst,
  14677. node: buttons[i].node
  14678. });
  14679. }
  14680. }
  14681. } else {
  14682. // jQuery selector on the nodes
  14683. $(nodes).filter(selector).each(function () {
  14684. ret.push({
  14685. inst: inst,
  14686. node: this
  14687. });
  14688. });
  14689. }
  14690. } else if ((typeof selector === 'undefined' ? 'undefined' : _typeof(selector)) === 'object' && selector.nodeName) {
  14691. // Node selector
  14692. var idx = $.inArray(selector, nodes);
  14693. if (idx !== - 1) {
  14694. ret.push({
  14695. inst: inst,
  14696. node: nodes[idx]
  14697. });
  14698. }
  14699. }
  14700. };
  14701. for (var i = 0, ien = insts.length; i < ien; i++) {
  14702. var inst = insts[i];
  14703. run(selector, inst);
  14704. }
  14705. return ret;
  14706. };
  14707. /**
  14708. * Buttons defaults. For full documentation, please refer to the docs/option
  14709. * directory or the DataTables site.
  14710. * @type {Object}
  14711. * @static
  14712. */
  14713. Buttons.defaults = {
  14714. buttons: ['copy', 'excel', 'csv', 'pdf', 'print'],
  14715. name: 'main',
  14716. tabIndex: 0,
  14717. dom: {
  14718. container: {
  14719. tag: 'div',
  14720. className: 'dt-buttons'
  14721. },
  14722. collection: {
  14723. tag: 'div',
  14724. className: 'dt-button-collection'
  14725. },
  14726. button: {
  14727. tag: 'a',
  14728. className: 'dt-button',
  14729. active: 'active',
  14730. disabled: 'disabled'
  14731. },
  14732. buttonLiner: {
  14733. tag: 'span',
  14734. className: ''
  14735. }
  14736. }
  14737. };
  14738. /**
  14739. * Version information
  14740. * @type {string}
  14741. * @static
  14742. */
  14743. Buttons.version = '1.4.2';
  14744. $.extend(_dtButtons, {
  14745. collection: {
  14746. text: function text(dt) {
  14747. return dt.i18n('buttons.collection', 'Collection');
  14748. },
  14749. className: 'buttons-collection',
  14750. action: function action(e, dt, button, config) {
  14751. var host = button;
  14752. var hostOffset = host.offset();
  14753. var tableContainer = $(dt.table().container());
  14754. var multiLevel = false;
  14755. // Remove any old collection
  14756. if ($('div.dt-button-background').length) {
  14757. multiLevel = $('.dt-button-collection').offset();
  14758. $('body').trigger('click.dtb-collection');
  14759. }
  14760. config._collection.addClass(config.collectionLayout).css('display', 'none').appendTo('body').fadeIn(config.fade);
  14761. var position = config._collection.css('position');
  14762. if (multiLevel && position === 'absolute') {
  14763. config._collection.css({
  14764. top: multiLevel.top,
  14765. left: multiLevel.left
  14766. });
  14767. } else if (position === 'absolute') {
  14768. config._collection.css({
  14769. top: hostOffset.top + host.outerHeight(),
  14770. left: hostOffset.left
  14771. });
  14772. // calculate overflow when positioned beneath
  14773. var tableBottom = tableContainer.offset().top + tableContainer.height();
  14774. var listBottom = hostOffset.top + host.outerHeight() + config._collection.outerHeight();
  14775. var bottomOverflow = listBottom - tableBottom;
  14776. // calculate overflow when positioned above
  14777. var listTop = hostOffset.top - config._collection.outerHeight();
  14778. var tableTop = tableContainer.offset().top;
  14779. var topOverflow = tableTop - listTop;
  14780. // if bottom overflow is larger, move to the top because it fits better
  14781. if (bottomOverflow > topOverflow) {
  14782. config._collection.css('top', hostOffset.top - config._collection.outerHeight() - 5);
  14783. }
  14784. var listRight = hostOffset.left + config._collection.outerWidth();
  14785. var tableRight = tableContainer.offset().left + tableContainer.width();
  14786. if (listRight > tableRight) {
  14787. config._collection.css('left', hostOffset.left - (listRight - tableRight));
  14788. }
  14789. } else {
  14790. // Fix position - centre on screen
  14791. var top = config._collection.height() / 2;
  14792. if (top > $(window).height() / 2) {
  14793. top = $(window).height() / 2;
  14794. }
  14795. config._collection.css('marginTop', top * - 1);
  14796. }
  14797. if (config.background) {
  14798. Buttons.background(true, config.backgroundClassName, config.fade);
  14799. }
  14800. // Need to break the 'thread' for the collection button being
  14801. // activated by a click - it would also trigger this event
  14802. setTimeout(function () {
  14803. // This is bonkers, but if we don't have a click listener on the
  14804. // background element, iOS Safari will ignore the body click
  14805. // listener below. An empty function here is all that is
  14806. // required to make it work...
  14807. $('div.dt-button-background').on('click.dtb-collection', function () {});
  14808. $('body').on('click.dtb-collection', function (e) {
  14809. // andSelf is deprecated in jQ1.8, but we want 1.7 compat
  14810. var back = $.fn.addBack ? 'addBack' : 'andSelf';
  14811. if (!$(e.target).parents()[back]().filter(config._collection).length) {
  14812. config._collection.fadeOut(config.fade, function () {
  14813. config._collection.detach();
  14814. });
  14815. $('div.dt-button-background').off('click.dtb-collection');
  14816. Buttons.background(false, config.backgroundClassName, config.fade);
  14817. $('body').off('click.dtb-collection');
  14818. dt.off('buttons-action.b-internal');
  14819. }
  14820. });
  14821. }, 10);
  14822. if (config.autoClose) {
  14823. dt.on('buttons-action.b-internal', function () {
  14824. $('div.dt-button-background').click();
  14825. });
  14826. }
  14827. },
  14828. background: true,
  14829. collectionLayout: '',
  14830. backgroundClassName: 'dt-button-background',
  14831. autoClose: false,
  14832. fade: 400
  14833. },
  14834. copy: function copy(dt, conf) {
  14835. if (_dtButtons.copyHtml5) {
  14836. return 'copyHtml5';
  14837. }
  14838. if (_dtButtons.copyFlash && _dtButtons.copyFlash.available(dt, conf)) {
  14839. return 'copyFlash';
  14840. }
  14841. },
  14842. csv: function csv(dt, conf) {
  14843. // Common option that will use the HTML5 or Flash export buttons
  14844. if (_dtButtons.csvHtml5 && _dtButtons.csvHtml5.available(dt, conf)) {
  14845. return 'csvHtml5';
  14846. }
  14847. if (_dtButtons.csvFlash && _dtButtons.csvFlash.available(dt, conf)) {
  14848. return 'csvFlash';
  14849. }
  14850. },
  14851. excel: function excel(dt, conf) {
  14852. // Common option that will use the HTML5 or Flash export buttons
  14853. if (_dtButtons.excelHtml5 && _dtButtons.excelHtml5.available(dt, conf)) {
  14854. return 'excelHtml5';
  14855. }
  14856. if (_dtButtons.excelFlash && _dtButtons.excelFlash.available(dt, conf)) {
  14857. return 'excelFlash';
  14858. }
  14859. },
  14860. pdf: function pdf(dt, conf) {
  14861. // Common option that will use the HTML5 or Flash export buttons
  14862. if (_dtButtons.pdfHtml5 && _dtButtons.pdfHtml5.available(dt, conf)) {
  14863. return 'pdfHtml5';
  14864. }
  14865. if (_dtButtons.pdfFlash && _dtButtons.pdfFlash.available(dt, conf)) {
  14866. return 'pdfFlash';
  14867. }
  14868. },
  14869. pageLength: function pageLength(dt) {
  14870. var lengthMenu = dt.settings()[0].aLengthMenu;
  14871. var vals = $.isArray(lengthMenu[0]) ? lengthMenu[0] : lengthMenu;
  14872. var lang = $.isArray(lengthMenu[0]) ? lengthMenu[1] : lengthMenu;
  14873. var text = function text(dt) {
  14874. return dt.i18n('buttons.pageLength', {
  14875. "-1": 'Show all rows',
  14876. _: 'Show %d rows'
  14877. }, dt.page.len());
  14878. };
  14879. return {
  14880. extend: 'collection',
  14881. text: text,
  14882. className: 'buttons-page-length',
  14883. autoClose: true,
  14884. buttons: $.map(vals, function (val, i) {
  14885. return {
  14886. text: lang[i],
  14887. className: 'button-page-length',
  14888. action: function action(e, dt) {
  14889. dt.page.len(val).draw();
  14890. },
  14891. init: function init(dt, node, conf) {
  14892. var that = this;
  14893. var fn = function fn() {
  14894. that.active(dt.page.len() === val);
  14895. };
  14896. dt.on('length.dt' + conf.namespace, fn);
  14897. fn();
  14898. },
  14899. destroy: function destroy(dt, node, conf) {
  14900. dt.off('length.dt' + conf.namespace);
  14901. }
  14902. };
  14903. }),
  14904. init: function init(dt, node, conf) {
  14905. var that = this;
  14906. dt.on('length.dt' + conf.namespace, function () {
  14907. that.text(text(dt));
  14908. });
  14909. },
  14910. destroy: function destroy(dt, node, conf) {
  14911. dt.off('length.dt' + conf.namespace);
  14912. }
  14913. };
  14914. }
  14915. });
  14916. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  14917. * DataTables API
  14918. *
  14919. * For complete documentation, please refer to the docs/api directory or the
  14920. * DataTables site
  14921. */
  14922. // Buttons group and individual button selector
  14923. DataTable.Api.register('buttons()', function (group, selector) {
  14924. // Argument shifting
  14925. if (selector === undefined) {
  14926. selector = group;
  14927. group = undefined;
  14928. }
  14929. this.selector.buttonGroup = group;
  14930. var res = this.iterator(true, 'table', function (ctx) {
  14931. if (ctx._buttons) {
  14932. return Buttons.buttonSelector(Buttons.instanceSelector(group, ctx._buttons), selector);
  14933. }
  14934. }, true);
  14935. res._groupSelector = group;
  14936. return res;
  14937. });
  14938. // Individual button selector
  14939. DataTable.Api.register('button()', function (group, selector) {
  14940. // just run buttons() and truncate
  14941. var buttons = this.buttons(group, selector);
  14942. if (buttons.length > 1) {
  14943. buttons.splice(1, buttons.length);
  14944. }
  14945. return buttons;
  14946. });
  14947. // Active buttons
  14948. DataTable.Api.registerPlural('buttons().active()', 'button().active()', function (flag) {
  14949. if (flag === undefined) {
  14950. return this.map(function (set) {
  14951. return set.inst.active(set.node);
  14952. });
  14953. }
  14954. return this.each(function (set) {
  14955. set.inst.active(set.node, flag);
  14956. });
  14957. });
  14958. // Get / set button action
  14959. DataTable.Api.registerPlural('buttons().action()', 'button().action()', function (action) {
  14960. if (action === undefined) {
  14961. return this.map(function (set) {
  14962. return set.inst.action(set.node);
  14963. });
  14964. }
  14965. return this.each(function (set) {
  14966. set.inst.action(set.node, action);
  14967. });
  14968. });
  14969. // Enable / disable buttons
  14970. DataTable.Api.register(['buttons().enable()', 'button().enable()'], function (flag) {
  14971. return this.each(function (set) {
  14972. set.inst.enable(set.node, flag);
  14973. });
  14974. });
  14975. // Disable buttons
  14976. DataTable.Api.register(['buttons().disable()', 'button().disable()'], function () {
  14977. return this.each(function (set) {
  14978. set.inst.disable(set.node);
  14979. });
  14980. });
  14981. // Get button nodes
  14982. DataTable.Api.registerPlural('buttons().nodes()', 'button().node()', function () {
  14983. var jq = $();
  14984. // jQuery will automatically reduce duplicates to a single entry
  14985. $(this.each(function (set) {
  14986. jq = jq.add(set.inst.node(set.node));
  14987. }));
  14988. return jq;
  14989. });
  14990. // Get / set button processing state
  14991. DataTable.Api.registerPlural('buttons().processing()', 'button().processing()', function (flag) {
  14992. if (flag === undefined) {
  14993. return this.map(function (set) {
  14994. return set.inst.processing(set.node);
  14995. });
  14996. }
  14997. return this.each(function (set) {
  14998. set.inst.processing(set.node, flag);
  14999. });
  15000. });
  15001. // Get / set button text (i.e. the button labels)
  15002. DataTable.Api.registerPlural('buttons().text()', 'button().text()', function (label) {
  15003. if (label === undefined) {
  15004. return this.map(function (set) {
  15005. return set.inst.text(set.node);
  15006. });
  15007. }
  15008. return this.each(function (set) {
  15009. set.inst.text(set.node, label);
  15010. });
  15011. });
  15012. // Trigger a button's action
  15013. DataTable.Api.registerPlural('buttons().trigger()', 'button().trigger()', function () {
  15014. return this.each(function (set) {
  15015. set.inst.node(set.node).trigger('click');
  15016. });
  15017. });
  15018. // Get the container elements
  15019. DataTable.Api.registerPlural('buttons().containers()', 'buttons().container()', function () {
  15020. var jq = $();
  15021. var groupSelector = this._groupSelector;
  15022. // We need to use the group selector directly, since if there are no buttons
  15023. // the result set will be empty
  15024. this.iterator(true, 'table', function (ctx) {
  15025. if (ctx._buttons) {
  15026. var insts = Buttons.instanceSelector(groupSelector, ctx._buttons);
  15027. for (var i = 0, ien = insts.length; i < ien; i++) {
  15028. jq = jq.add(insts[i].container());
  15029. }
  15030. }
  15031. });
  15032. return jq;
  15033. });
  15034. // Add a new button
  15035. DataTable.Api.register('button().add()', function (idx, conf) {
  15036. var ctx = this.context;
  15037. // Don't use `this` as it could be empty - select the instances directly
  15038. if (ctx.length) {
  15039. var inst = Buttons.instanceSelector(this._groupSelector, ctx[0]._buttons);
  15040. if (inst.length) {
  15041. inst[0].add(conf, idx);
  15042. }
  15043. }
  15044. return this.button(this._groupSelector, idx);
  15045. });
  15046. // Destroy the button sets selected
  15047. DataTable.Api.register('buttons().destroy()', function () {
  15048. this.pluck('inst').unique().each(function (inst) {
  15049. inst.destroy();
  15050. });
  15051. return this;
  15052. });
  15053. // Remove a button
  15054. DataTable.Api.registerPlural('buttons().remove()', 'buttons().remove()', function () {
  15055. this.each(function (set) {
  15056. set.inst.remove(set.node);
  15057. });
  15058. return this;
  15059. });
  15060. // Information box that can be used by buttons
  15061. var _infoTimer;
  15062. DataTable.Api.register('buttons.info()', function (title, message, time) {
  15063. var that = this;
  15064. if (title === false) {
  15065. $('#datatables_buttons_info').fadeOut(function () {
  15066. $(this).remove();
  15067. });
  15068. clearTimeout(_infoTimer);
  15069. _infoTimer = null;
  15070. return this;
  15071. }
  15072. if (_infoTimer) {
  15073. clearTimeout(_infoTimer);
  15074. }
  15075. if ($('#datatables_buttons_info').length) {
  15076. $('#datatables_buttons_info').remove();
  15077. }
  15078. title = title ? '<h2>' + title + '</h2>' : '';
  15079. $('<div id="datatables_buttons_info" class="dt-button-info"/>').html(title).append($('<div/>')[typeof message === 'string' ? 'html' : 'append'](message)).css('display', 'none').appendTo('body').fadeIn();
  15080. if (time !== undefined && time !== 0) {
  15081. _infoTimer = setTimeout(function () {
  15082. that.buttons.info(false);
  15083. }, time);
  15084. }
  15085. return this;
  15086. });
  15087. // Get data from the table for export - this is common to a number of plug-in
  15088. // buttons so it is included in the Buttons core library
  15089. DataTable.Api.register('buttons.exportData()', function (options) {
  15090. if (this.context.length) {
  15091. return _exportData(new DataTable.Api(this.context[0]), options);
  15092. }
  15093. });
  15094. // Get information about the export that is common to many of the export data
  15095. // types (DRY)
  15096. DataTable.Api.register('buttons.exportInfo()', function (conf) {
  15097. if (!conf) {
  15098. conf = {};
  15099. }
  15100. return {
  15101. filename: _filename(conf),
  15102. title: _title(conf),
  15103. messageTop: _message(this, conf.messageTop || conf.message, 'top'),
  15104. messageBottom: _message(this, conf.messageBottom, 'bottom')
  15105. };
  15106. });
  15107. /**
  15108. * Get the file name for an exported file.
  15109. *
  15110. * @param {object} config Button configuration
  15111. * @param {boolean} incExtension Include the file name extension
  15112. */
  15113. var _filename = function _filename(config) {
  15114. // Backwards compatibility
  15115. var filename = config.filename === '*' && config.title !== '*' && config.title !== undefined ? config.title : config.filename;
  15116. if (typeof filename === 'function') {
  15117. filename = filename();
  15118. }
  15119. if (filename === undefined || filename === null) {
  15120. return null;
  15121. }
  15122. if (filename.indexOf('*') !== - 1) {
  15123. filename = $.trim(filename.replace('*', $('title').text()));
  15124. }
  15125. // Strip characters which the OS will object to
  15126. filename = filename.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g, "");
  15127. var extension = _stringOrFunction(config.extension);
  15128. if (!extension) {
  15129. extension = '';
  15130. }
  15131. return filename + extension;
  15132. };
  15133. /**
  15134. * Simply utility method to allow parameters to be given as a function
  15135. *
  15136. * @param {undefined|string|function} option Option
  15137. * @return {null|string} Resolved value
  15138. */
  15139. var _stringOrFunction = function _stringOrFunction(option) {
  15140. if (option === null || option === undefined) {
  15141. return null;
  15142. } else if (typeof option === 'function') {
  15143. return option();
  15144. }
  15145. return option;
  15146. };
  15147. /**
  15148. * Get the title for an exported file.
  15149. *
  15150. * @param {object} config Button configuration
  15151. */
  15152. var _title = function _title(config) {
  15153. var title = _stringOrFunction(config.title);
  15154. return title === null ? null : title.indexOf('*') !== - 1 ? title.replace('*', $('title').text() || 'Exported data') : title;
  15155. };
  15156. var _message = function _message(dt, option, position) {
  15157. var message = _stringOrFunction(option);
  15158. if (message === null) {
  15159. return null;
  15160. }
  15161. var caption = $('caption', dt.table().container()).eq(0);
  15162. if (message === '*') {
  15163. var side = caption.css('caption-side');
  15164. if (side !== position) {
  15165. return null;
  15166. }
  15167. return caption.length ? caption.text() : '';
  15168. }
  15169. return message;
  15170. };
  15171. var _exportTextarea = $('<textarea/>')[0];
  15172. var _exportData = function _exportData(dt, inOpts) {
  15173. var config = $.extend(true, {}, {
  15174. rows: null,
  15175. columns: '',
  15176. modifier: {
  15177. search: 'applied',
  15178. order: 'applied'
  15179. },
  15180. orthogonal: 'display',
  15181. stripHtml: true,
  15182. stripNewlines: true,
  15183. decodeEntities: true,
  15184. trim: true,
  15185. format: {
  15186. header: function header(d) {
  15187. return strip(d);
  15188. },
  15189. footer: function footer(d) {
  15190. return strip(d);
  15191. },
  15192. body: function body(d) {
  15193. return strip(d);
  15194. }
  15195. }
  15196. }, inOpts);
  15197. var strip = function strip(str) {
  15198. if (typeof str !== 'string') {
  15199. return str;
  15200. }
  15201. // Always remove script tags
  15202. str = str.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
  15203. if (config.stripHtml) {
  15204. str = str.replace(/<[^>]*>/g, '');
  15205. }
  15206. if (config.trim) {
  15207. str = str.replace(/^\s+|\s+$/g, '');
  15208. }
  15209. if (config.stripNewlines) {
  15210. str = str.replace(/\n/g, ' ');
  15211. }
  15212. if (config.decodeEntities) {
  15213. _exportTextarea.innerHTML = str;
  15214. str = _exportTextarea.value;
  15215. }
  15216. return str;
  15217. };
  15218. var header = dt.columns(config.columns).indexes().map(function (idx) {
  15219. var el = dt.column(idx).header();
  15220. return config.format.header(el.innerHTML, idx, el);
  15221. }).toArray();
  15222. var footer = dt.table().footer() ? dt.columns(config.columns).indexes().map(function (idx) {
  15223. var el = dt.column(idx).footer();
  15224. return config.format.footer(el ? el.innerHTML : '', idx, el);
  15225. }).toArray() : null;
  15226. var rowIndexes = dt.rows(config.rows, config.modifier).indexes().toArray();
  15227. var selectedCells = dt.cells(rowIndexes, config.columns);
  15228. var cells = selectedCells.render(config.orthogonal).toArray();
  15229. var cellNodes = selectedCells.nodes().toArray();
  15230. var columns = header.length;
  15231. var rows = columns > 0 ? cells.length / columns : 0;
  15232. var body = new Array(rows);
  15233. var cellCounter = 0;
  15234. for (var i = 0, ien = rows; i < ien; i++) {
  15235. var row = new Array(columns);
  15236. for (var j = 0; j < columns; j++) {
  15237. row[j] = config.format.body(cells[cellCounter], i, j, cellNodes[cellCounter]);
  15238. cellCounter++;
  15239. }
  15240. body[i] = row;
  15241. }
  15242. return {
  15243. header: header,
  15244. footer: footer,
  15245. body: body
  15246. };
  15247. };
  15248. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  15249. * DataTables interface
  15250. */
  15251. // Attach to DataTables objects for global access
  15252. $.fn.dataTable.Buttons = Buttons;
  15253. $.fn.DataTable.Buttons = Buttons;
  15254. // DataTables creation - check if the buttons have been defined for this table,
  15255. // they will have been if the `B` option was used in `dom`, otherwise we should
  15256. // create the buttons instance here so they can be inserted into the document
  15257. // using the API. Listen for `init` for compatibility with pre 1.10.10, but to
  15258. // be removed in future.
  15259. $(document).on('init.dt plugin-init.dt', function (e, settings) {
  15260. if (e.namespace !== 'dt') {
  15261. return;
  15262. }
  15263. var opts = settings.oInit.buttons || DataTable.defaults.buttons;
  15264. if (opts && !settings._buttons) {
  15265. new Buttons(settings, opts).container();
  15266. }
  15267. });
  15268. // DataTables `dom` feature option
  15269. DataTable.ext.feature.push({
  15270. fnInit: function fnInit(settings) {
  15271. var api = new DataTable.Api(settings);
  15272. var opts = api.init().buttons || DataTable.defaults.buttons;
  15273. return new Buttons(api, opts).container();
  15274. },
  15275. cFeature: "B"
  15276. });
  15277. return Buttons;
  15278. });
  15279. /***/ })
  15280. /******/});