2
0

004-datatables.js 526 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781
  1. /*
  2. * This combined file was created by the DataTables downloader builder:
  3. * https://datatables.net/download
  4. *
  5. * To rebuild or modify this file with the latest versions of the included
  6. * software please visit:
  7. * https://datatables.net/download/#bs5/dt-1.13.1/r-2.4.0/sl-1.5.0
  8. *
  9. * Included libraries:
  10. * DataTables 1.13.1, Responsive 2.4.0, Select 1.5.0
  11. */
  12. /*! DataTables 1.13.1
  13. * ©2008-2022 SpryMedia Ltd - datatables.net/license
  14. */
  15. /**
  16. * @summary DataTables
  17. * @description Paginate, search and order HTML tables
  18. * @version 1.13.1
  19. * @author SpryMedia Ltd
  20. * @contact www.datatables.net
  21. * @copyright SpryMedia Ltd.
  22. *
  23. * This source file is free software, available under the following license:
  24. * MIT license - http://datatables.net/license
  25. *
  26. * This source file is distributed in the hope that it will be useful, but
  27. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  28. * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  29. *
  30. * For details please refer to: http://www.datatables.net
  31. */
  32. /*jslint evil: true, undef: true, browser: true */
  33. /*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*/
  34. (function( factory ) {
  35. "use strict";
  36. if ( typeof define === 'function' && define.amd ) {
  37. // AMD
  38. define( ['jquery'], function ( $ ) {
  39. return factory( $, window, document );
  40. } );
  41. }
  42. else if ( typeof exports === 'object' ) {
  43. // CommonJS
  44. module.exports = function (root, $) {
  45. if ( ! root ) {
  46. // CommonJS environments without a window global must pass a
  47. // root. This will give an error otherwise
  48. root = window;
  49. }
  50. if ( ! $ ) {
  51. $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
  52. require('jquery') :
  53. require('jquery')( root );
  54. }
  55. return factory( $, root, root.document );
  56. };
  57. }
  58. else {
  59. // Browser
  60. window.DataTable = factory( jQuery, window, document );
  61. }
  62. }
  63. (function( $, window, document, undefined ) {
  64. "use strict";
  65. var DataTable = function ( selector, options )
  66. {
  67. // When creating with `new`, create a new DataTable, returning the API instance
  68. if (this instanceof DataTable) {
  69. return $(selector).DataTable(options);
  70. }
  71. else {
  72. // Argument switching
  73. options = selector;
  74. }
  75. /**
  76. * Perform a jQuery selector action on the table's TR elements (from the tbody) and
  77. * return the resulting jQuery object.
  78. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  79. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  80. * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
  81. * criterion ("applied") or all TR elements (i.e. no filter).
  82. * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
  83. * Can be either 'current', whereby the current sorting of the table is used, or
  84. * 'original' whereby the original order the data was read into the table is used.
  85. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  86. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  87. * 'current' and filter is 'applied', regardless of what they might be given as.
  88. * @returns {object} jQuery object, filtered by the given selector.
  89. * @dtopt API
  90. * @deprecated Since v1.10
  91. *
  92. * @example
  93. * $(document).ready(function() {
  94. * var oTable = $('#example').dataTable();
  95. *
  96. * // Highlight every second row
  97. * oTable.$('tr:odd').css('backgroundColor', 'blue');
  98. * } );
  99. *
  100. * @example
  101. * $(document).ready(function() {
  102. * var oTable = $('#example').dataTable();
  103. *
  104. * // Filter to rows with 'Webkit' in them, add a background colour and then
  105. * // remove the filter, thus highlighting the 'Webkit' rows only.
  106. * oTable.fnFilter('Webkit');
  107. * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
  108. * oTable.fnFilter('');
  109. * } );
  110. */
  111. this.$ = function ( sSelector, oOpts )
  112. {
  113. return this.api(true).$( sSelector, oOpts );
  114. };
  115. /**
  116. * Almost identical to $ in operation, but in this case returns the data for the matched
  117. * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
  118. * rather than any descendants, so the data can be obtained for the row/cell. If matching
  119. * rows are found, the data returned is the original data array/object that was used to
  120. * create the row (or a generated array if from a DOM source).
  121. *
  122. * This method is often useful in-combination with $ where both functions are given the
  123. * same parameters and the array indexes will match identically.
  124. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  125. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  126. * @param {string} [oOpts.filter=none] Select elements that meet the current filter
  127. * criterion ("applied") or all elements (i.e. no filter).
  128. * @param {string} [oOpts.order=current] Order of the data in the processed array.
  129. * Can be either 'current', whereby the current sorting of the table is used, or
  130. * 'original' whereby the original order the data was read into the table is used.
  131. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  132. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  133. * 'current' and filter is 'applied', regardless of what they might be given as.
  134. * @returns {array} Data for the matched elements. If any elements, as a result of the
  135. * selector, were not TR, TD or TH elements in the DataTable, they will have a null
  136. * entry in the array.
  137. * @dtopt API
  138. * @deprecated Since v1.10
  139. *
  140. * @example
  141. * $(document).ready(function() {
  142. * var oTable = $('#example').dataTable();
  143. *
  144. * // Get the data from the first row in the table
  145. * var data = oTable._('tr:first');
  146. *
  147. * // Do something useful with the data
  148. * alert( "First cell is: "+data[0] );
  149. * } );
  150. *
  151. * @example
  152. * $(document).ready(function() {
  153. * var oTable = $('#example').dataTable();
  154. *
  155. * // Filter to 'Webkit' and get all data for
  156. * oTable.fnFilter('Webkit');
  157. * var data = oTable._('tr', {"search": "applied"});
  158. *
  159. * // Do something with the data
  160. * alert( data.length+" rows matched the search" );
  161. * } );
  162. */
  163. this._ = function ( sSelector, oOpts )
  164. {
  165. return this.api(true).rows( sSelector, oOpts ).data();
  166. };
  167. /**
  168. * Create a DataTables Api instance, with the currently selected tables for
  169. * the Api's context.
  170. * @param {boolean} [traditional=false] Set the API instance's context to be
  171. * only the table referred to by the `DataTable.ext.iApiIndex` option, as was
  172. * used in the API presented by DataTables 1.9- (i.e. the traditional mode),
  173. * or if all tables captured in the jQuery object should be used.
  174. * @return {DataTables.Api}
  175. */
  176. this.api = function ( traditional )
  177. {
  178. return traditional ?
  179. new _Api(
  180. _fnSettingsFromNode( this[ _ext.iApiIndex ] )
  181. ) :
  182. new _Api( this );
  183. };
  184. /**
  185. * Add a single new row or multiple rows of data to the table. Please note
  186. * that this is suitable for client-side processing only - if you are using
  187. * server-side processing (i.e. "bServerSide": true), then to add data, you
  188. * must add it to the data source, i.e. the server-side, through an Ajax call.
  189. * @param {array|object} data The data to be added to the table. This can be:
  190. * <ul>
  191. * <li>1D array of data - add a single row with the data provided</li>
  192. * <li>2D array of arrays - add multiple rows in a single call</li>
  193. * <li>object - data object when using <i>mData</i></li>
  194. * <li>array of objects - multiple data objects when using <i>mData</i></li>
  195. * </ul>
  196. * @param {bool} [redraw=true] redraw the table or not
  197. * @returns {array} An array of integers, representing the list of indexes in
  198. * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
  199. * the table.
  200. * @dtopt API
  201. * @deprecated Since v1.10
  202. *
  203. * @example
  204. * // Global var for counter
  205. * var giCount = 2;
  206. *
  207. * $(document).ready(function() {
  208. * $('#example').dataTable();
  209. * } );
  210. *
  211. * function fnClickAddRow() {
  212. * $('#example').dataTable().fnAddData( [
  213. * giCount+".1",
  214. * giCount+".2",
  215. * giCount+".3",
  216. * giCount+".4" ]
  217. * );
  218. *
  219. * giCount++;
  220. * }
  221. */
  222. this.fnAddData = function( data, redraw )
  223. {
  224. var api = this.api( true );
  225. /* Check if we want to add multiple rows or not */
  226. var rows = Array.isArray(data) && ( Array.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
  227. api.rows.add( data ) :
  228. api.row.add( data );
  229. if ( redraw === undefined || redraw ) {
  230. api.draw();
  231. }
  232. return rows.flatten().toArray();
  233. };
  234. /**
  235. * This function will make DataTables recalculate the column sizes, based on the data
  236. * contained in the table and the sizes applied to the columns (in the DOM, CSS or
  237. * through the sWidth parameter). This can be useful when the width of the table's
  238. * parent element changes (for example a window resize).
  239. * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
  240. * @dtopt API
  241. * @deprecated Since v1.10
  242. *
  243. * @example
  244. * $(document).ready(function() {
  245. * var oTable = $('#example').dataTable( {
  246. * "sScrollY": "200px",
  247. * "bPaginate": false
  248. * } );
  249. *
  250. * $(window).on('resize', function () {
  251. * oTable.fnAdjustColumnSizing();
  252. * } );
  253. * } );
  254. */
  255. this.fnAdjustColumnSizing = function ( bRedraw )
  256. {
  257. var api = this.api( true ).columns.adjust();
  258. var settings = api.settings()[0];
  259. var scroll = settings.oScroll;
  260. if ( bRedraw === undefined || bRedraw ) {
  261. api.draw( false );
  262. }
  263. else if ( scroll.sX !== "" || scroll.sY !== "" ) {
  264. /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
  265. _fnScrollDraw( settings );
  266. }
  267. };
  268. /**
  269. * Quickly and simply clear a table
  270. * @param {bool} [bRedraw=true] redraw the table or not
  271. * @dtopt API
  272. * @deprecated Since v1.10
  273. *
  274. * @example
  275. * $(document).ready(function() {
  276. * var oTable = $('#example').dataTable();
  277. *
  278. * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
  279. * oTable.fnClearTable();
  280. * } );
  281. */
  282. this.fnClearTable = function( bRedraw )
  283. {
  284. var api = this.api( true ).clear();
  285. if ( bRedraw === undefined || bRedraw ) {
  286. api.draw();
  287. }
  288. };
  289. /**
  290. * The exact opposite of 'opening' a row, this function will close any rows which
  291. * are currently 'open'.
  292. * @param {node} nTr the table row to 'close'
  293. * @returns {int} 0 on success, or 1 if failed (can't find the row)
  294. * @dtopt API
  295. * @deprecated Since v1.10
  296. *
  297. * @example
  298. * $(document).ready(function() {
  299. * var oTable;
  300. *
  301. * // 'open' an information row when a row is clicked on
  302. * $('#example tbody tr').click( function () {
  303. * if ( oTable.fnIsOpen(this) ) {
  304. * oTable.fnClose( this );
  305. * } else {
  306. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  307. * }
  308. * } );
  309. *
  310. * oTable = $('#example').dataTable();
  311. * } );
  312. */
  313. this.fnClose = function( nTr )
  314. {
  315. this.api( true ).row( nTr ).child.hide();
  316. };
  317. /**
  318. * Remove a row for the table
  319. * @param {mixed} target The index of the row from aoData to be deleted, or
  320. * the TR element you want to delete
  321. * @param {function|null} [callBack] Callback function
  322. * @param {bool} [redraw=true] Redraw the table or not
  323. * @returns {array} The row that was deleted
  324. * @dtopt API
  325. * @deprecated Since v1.10
  326. *
  327. * @example
  328. * $(document).ready(function() {
  329. * var oTable = $('#example').dataTable();
  330. *
  331. * // Immediately remove the first row
  332. * oTable.fnDeleteRow( 0 );
  333. * } );
  334. */
  335. this.fnDeleteRow = function( target, callback, redraw )
  336. {
  337. var api = this.api( true );
  338. var rows = api.rows( target );
  339. var settings = rows.settings()[0];
  340. var data = settings.aoData[ rows[0][0] ];
  341. rows.remove();
  342. if ( callback ) {
  343. callback.call( this, settings, data );
  344. }
  345. if ( redraw === undefined || redraw ) {
  346. api.draw();
  347. }
  348. return data;
  349. };
  350. /**
  351. * Restore the table to it's original state in the DOM by removing all of DataTables
  352. * enhancements, alterations to the DOM structure of the table and event listeners.
  353. * @param {boolean} [remove=false] Completely remove the table from the DOM
  354. * @dtopt API
  355. * @deprecated Since v1.10
  356. *
  357. * @example
  358. * $(document).ready(function() {
  359. * // This example is fairly pointless in reality, but shows how fnDestroy can be used
  360. * var oTable = $('#example').dataTable();
  361. * oTable.fnDestroy();
  362. * } );
  363. */
  364. this.fnDestroy = function ( remove )
  365. {
  366. this.api( true ).destroy( remove );
  367. };
  368. /**
  369. * Redraw the table
  370. * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
  371. * @dtopt API
  372. * @deprecated Since v1.10
  373. *
  374. * @example
  375. * $(document).ready(function() {
  376. * var oTable = $('#example').dataTable();
  377. *
  378. * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
  379. * oTable.fnDraw();
  380. * } );
  381. */
  382. this.fnDraw = function( complete )
  383. {
  384. // Note that this isn't an exact match to the old call to _fnDraw - it takes
  385. // into account the new data, but can hold position.
  386. this.api( true ).draw( complete );
  387. };
  388. /**
  389. * Filter the input based on data
  390. * @param {string} sInput String to filter the table on
  391. * @param {int|null} [iColumn] Column to limit filtering to
  392. * @param {bool} [bRegex=false] Treat as regular expression or not
  393. * @param {bool} [bSmart=true] Perform smart filtering or not
  394. * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
  395. * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
  396. * @dtopt API
  397. * @deprecated Since v1.10
  398. *
  399. * @example
  400. * $(document).ready(function() {
  401. * var oTable = $('#example').dataTable();
  402. *
  403. * // Sometime later - filter...
  404. * oTable.fnFilter( 'test string' );
  405. * } );
  406. */
  407. this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
  408. {
  409. var api = this.api( true );
  410. if ( iColumn === null || iColumn === undefined ) {
  411. api.search( sInput, bRegex, bSmart, bCaseInsensitive );
  412. }
  413. else {
  414. api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
  415. }
  416. api.draw();
  417. };
  418. /**
  419. * Get the data for the whole table, an individual row or an individual cell based on the
  420. * provided parameters.
  421. * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
  422. * a TR node then the data source for the whole row will be returned. If given as a
  423. * TD/TH cell node then iCol will be automatically calculated and the data for the
  424. * cell returned. If given as an integer, then this is treated as the aoData internal
  425. * data index for the row (see fnGetPosition) and the data for that row used.
  426. * @param {int} [col] Optional column index that you want the data of.
  427. * @returns {array|object|string} If mRow is undefined, then the data for all rows is
  428. * returned. If mRow is defined, just data for that row, and is iCol is
  429. * defined, only data for the designated cell is returned.
  430. * @dtopt API
  431. * @deprecated Since v1.10
  432. *
  433. * @example
  434. * // Row data
  435. * $(document).ready(function() {
  436. * oTable = $('#example').dataTable();
  437. *
  438. * oTable.$('tr').click( function () {
  439. * var data = oTable.fnGetData( this );
  440. * // ... do something with the array / object of data for the row
  441. * } );
  442. * } );
  443. *
  444. * @example
  445. * // Individual cell data
  446. * $(document).ready(function() {
  447. * oTable = $('#example').dataTable();
  448. *
  449. * oTable.$('td').click( function () {
  450. * var sData = oTable.fnGetData( this );
  451. * alert( 'The cell clicked on had the value of '+sData );
  452. * } );
  453. * } );
  454. */
  455. this.fnGetData = function( src, col )
  456. {
  457. var api = this.api( true );
  458. if ( src !== undefined ) {
  459. var type = src.nodeName ? src.nodeName.toLowerCase() : '';
  460. return col !== undefined || type == 'td' || type == 'th' ?
  461. api.cell( src, col ).data() :
  462. api.row( src ).data() || null;
  463. }
  464. return api.data().toArray();
  465. };
  466. /**
  467. * Get an array of the TR nodes that are used in the table's body. Note that you will
  468. * typically want to use the '$' API method in preference to this as it is more
  469. * flexible.
  470. * @param {int} [iRow] Optional row index for the TR element you want
  471. * @returns {array|node} If iRow is undefined, returns an array of all TR elements
  472. * in the table's body, or iRow is defined, just the TR element requested.
  473. * @dtopt API
  474. * @deprecated Since v1.10
  475. *
  476. * @example
  477. * $(document).ready(function() {
  478. * var oTable = $('#example').dataTable();
  479. *
  480. * // Get the nodes from the table
  481. * var nNodes = oTable.fnGetNodes( );
  482. * } );
  483. */
  484. this.fnGetNodes = function( iRow )
  485. {
  486. var api = this.api( true );
  487. return iRow !== undefined ?
  488. api.row( iRow ).node() :
  489. api.rows().nodes().flatten().toArray();
  490. };
  491. /**
  492. * Get the array indexes of a particular cell from it's DOM element
  493. * and column index including hidden columns
  494. * @param {node} node this can either be a TR, TD or TH in the table's body
  495. * @returns {int} If nNode is given as a TR, then a single index is returned, or
  496. * if given as a cell, an array of [row index, column index (visible),
  497. * column index (all)] is given.
  498. * @dtopt API
  499. * @deprecated Since v1.10
  500. *
  501. * @example
  502. * $(document).ready(function() {
  503. * $('#example tbody td').click( function () {
  504. * // Get the position of the current data from the node
  505. * var aPos = oTable.fnGetPosition( this );
  506. *
  507. * // Get the data array for this row
  508. * var aData = oTable.fnGetData( aPos[0] );
  509. *
  510. * // Update the data array and return the value
  511. * aData[ aPos[1] ] = 'clicked';
  512. * this.innerHTML = 'clicked';
  513. * } );
  514. *
  515. * // Init DataTables
  516. * oTable = $('#example').dataTable();
  517. * } );
  518. */
  519. this.fnGetPosition = function( node )
  520. {
  521. var api = this.api( true );
  522. var nodeName = node.nodeName.toUpperCase();
  523. if ( nodeName == 'TR' ) {
  524. return api.row( node ).index();
  525. }
  526. else if ( nodeName == 'TD' || nodeName == 'TH' ) {
  527. var cell = api.cell( node ).index();
  528. return [
  529. cell.row,
  530. cell.columnVisible,
  531. cell.column
  532. ];
  533. }
  534. return null;
  535. };
  536. /**
  537. * Check to see if a row is 'open' or not.
  538. * @param {node} nTr the table row to check
  539. * @returns {boolean} true if the row is currently open, false otherwise
  540. * @dtopt API
  541. * @deprecated Since v1.10
  542. *
  543. * @example
  544. * $(document).ready(function() {
  545. * var oTable;
  546. *
  547. * // 'open' an information row when a row is clicked on
  548. * $('#example tbody tr').click( function () {
  549. * if ( oTable.fnIsOpen(this) ) {
  550. * oTable.fnClose( this );
  551. * } else {
  552. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  553. * }
  554. * } );
  555. *
  556. * oTable = $('#example').dataTable();
  557. * } );
  558. */
  559. this.fnIsOpen = function( nTr )
  560. {
  561. return this.api( true ).row( nTr ).child.isShown();
  562. };
  563. /**
  564. * This function will place a new row directly after a row which is currently
  565. * on display on the page, with the HTML contents that is passed into the
  566. * function. This can be used, for example, to ask for confirmation that a
  567. * particular record should be deleted.
  568. * @param {node} nTr The table row to 'open'
  569. * @param {string|node|jQuery} mHtml The HTML to put into the row
  570. * @param {string} sClass Class to give the new TD cell
  571. * @returns {node} The row opened. Note that if the table row passed in as the
  572. * first parameter, is not found in the table, this method will silently
  573. * return.
  574. * @dtopt API
  575. * @deprecated Since v1.10
  576. *
  577. * @example
  578. * $(document).ready(function() {
  579. * var oTable;
  580. *
  581. * // 'open' an information row when a row is clicked on
  582. * $('#example tbody tr').click( function () {
  583. * if ( oTable.fnIsOpen(this) ) {
  584. * oTable.fnClose( this );
  585. * } else {
  586. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  587. * }
  588. * } );
  589. *
  590. * oTable = $('#example').dataTable();
  591. * } );
  592. */
  593. this.fnOpen = function( nTr, mHtml, sClass )
  594. {
  595. return this.api( true )
  596. .row( nTr )
  597. .child( mHtml, sClass )
  598. .show()
  599. .child()[0];
  600. };
  601. /**
  602. * Change the pagination - provides the internal logic for pagination in a simple API
  603. * function. With this function you can have a DataTables table go to the next,
  604. * previous, first or last pages.
  605. * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
  606. * or page number to jump to (integer), note that page 0 is the first page.
  607. * @param {bool} [bRedraw=true] Redraw the table or not
  608. * @dtopt API
  609. * @deprecated Since v1.10
  610. *
  611. * @example
  612. * $(document).ready(function() {
  613. * var oTable = $('#example').dataTable();
  614. * oTable.fnPageChange( 'next' );
  615. * } );
  616. */
  617. this.fnPageChange = function ( mAction, bRedraw )
  618. {
  619. var api = this.api( true ).page( mAction );
  620. if ( bRedraw === undefined || bRedraw ) {
  621. api.draw(false);
  622. }
  623. };
  624. /**
  625. * Show a particular column
  626. * @param {int} iCol The column whose display should be changed
  627. * @param {bool} bShow Show (true) or hide (false) the column
  628. * @param {bool} [bRedraw=true] Redraw the table or not
  629. * @dtopt API
  630. * @deprecated Since v1.10
  631. *
  632. * @example
  633. * $(document).ready(function() {
  634. * var oTable = $('#example').dataTable();
  635. *
  636. * // Hide the second column after initialisation
  637. * oTable.fnSetColumnVis( 1, false );
  638. * } );
  639. */
  640. this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
  641. {
  642. var api = this.api( true ).column( iCol ).visible( bShow );
  643. if ( bRedraw === undefined || bRedraw ) {
  644. api.columns.adjust().draw();
  645. }
  646. };
  647. /**
  648. * Get the settings for a particular table for external manipulation
  649. * @returns {object} DataTables settings object. See
  650. * {@link DataTable.models.oSettings}
  651. * @dtopt API
  652. * @deprecated Since v1.10
  653. *
  654. * @example
  655. * $(document).ready(function() {
  656. * var oTable = $('#example').dataTable();
  657. * var oSettings = oTable.fnSettings();
  658. *
  659. * // Show an example parameter from the settings
  660. * alert( oSettings._iDisplayStart );
  661. * } );
  662. */
  663. this.fnSettings = function()
  664. {
  665. return _fnSettingsFromNode( this[_ext.iApiIndex] );
  666. };
  667. /**
  668. * Sort the table by a particular column
  669. * @param {int} iCol the data index to sort on. Note that this will not match the
  670. * 'display index' if you have hidden data entries
  671. * @dtopt API
  672. * @deprecated Since v1.10
  673. *
  674. * @example
  675. * $(document).ready(function() {
  676. * var oTable = $('#example').dataTable();
  677. *
  678. * // Sort immediately with columns 0 and 1
  679. * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
  680. * } );
  681. */
  682. this.fnSort = function( aaSort )
  683. {
  684. this.api( true ).order( aaSort ).draw();
  685. };
  686. /**
  687. * Attach a sort listener to an element for a given column
  688. * @param {node} nNode the element to attach the sort listener to
  689. * @param {int} iColumn the column that a click on this node will sort on
  690. * @param {function} [fnCallback] callback function when sort is run
  691. * @dtopt API
  692. * @deprecated Since v1.10
  693. *
  694. * @example
  695. * $(document).ready(function() {
  696. * var oTable = $('#example').dataTable();
  697. *
  698. * // Sort on column 1, when 'sorter' is clicked on
  699. * oTable.fnSortListener( document.getElementById('sorter'), 1 );
  700. * } );
  701. */
  702. this.fnSortListener = function( nNode, iColumn, fnCallback )
  703. {
  704. this.api( true ).order.listener( nNode, iColumn, fnCallback );
  705. };
  706. /**
  707. * Update a table cell or row - this method will accept either a single value to
  708. * update the cell with, an array of values with one element for each column or
  709. * an object in the same format as the original data source. The function is
  710. * self-referencing in order to make the multi column updates easier.
  711. * @param {object|array|string} mData Data to update the cell/row with
  712. * @param {node|int} mRow TR element you want to update or the aoData index
  713. * @param {int} [iColumn] The column to update, give as null or undefined to
  714. * update a whole row.
  715. * @param {bool} [bRedraw=true] Redraw the table or not
  716. * @param {bool} [bAction=true] Perform pre-draw actions or not
  717. * @returns {int} 0 on success, 1 on error
  718. * @dtopt API
  719. * @deprecated Since v1.10
  720. *
  721. * @example
  722. * $(document).ready(function() {
  723. * var oTable = $('#example').dataTable();
  724. * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
  725. * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
  726. * } );
  727. */
  728. this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
  729. {
  730. var api = this.api( true );
  731. if ( iColumn === undefined || iColumn === null ) {
  732. api.row( mRow ).data( mData );
  733. }
  734. else {
  735. api.cell( mRow, iColumn ).data( mData );
  736. }
  737. if ( bAction === undefined || bAction ) {
  738. api.columns.adjust();
  739. }
  740. if ( bRedraw === undefined || bRedraw ) {
  741. api.draw();
  742. }
  743. return 0;
  744. };
  745. /**
  746. * Provide a common method for plug-ins to check the version of DataTables being used, in order
  747. * to ensure compatibility.
  748. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
  749. * formats "X" and "X.Y" are also acceptable.
  750. * @returns {boolean} true if this version of DataTables is greater or equal to the required
  751. * version, or false if this version of DataTales is not suitable
  752. * @method
  753. * @dtopt API
  754. * @deprecated Since v1.10
  755. *
  756. * @example
  757. * $(document).ready(function() {
  758. * var oTable = $('#example').dataTable();
  759. * alert( oTable.fnVersionCheck( '1.9.0' ) );
  760. * } );
  761. */
  762. this.fnVersionCheck = _ext.fnVersionCheck;
  763. var _that = this;
  764. var emptyInit = options === undefined;
  765. var len = this.length;
  766. if ( emptyInit ) {
  767. options = {};
  768. }
  769. this.oApi = this.internal = _ext.internal;
  770. // Extend with old style plug-in API methods
  771. for ( var fn in DataTable.ext.internal ) {
  772. if ( fn ) {
  773. this[fn] = _fnExternApiFunc(fn);
  774. }
  775. }
  776. this.each(function() {
  777. // For each initialisation we want to give it a clean initialisation
  778. // object that can be bashed around
  779. var o = {};
  780. var oInit = len > 1 ? // optimisation for single table case
  781. _fnExtend( o, options, true ) :
  782. options;
  783. /*global oInit,_that,emptyInit*/
  784. var i=0, iLen, j, jLen, k, kLen;
  785. var sId = this.getAttribute( 'id' );
  786. var bInitHandedOff = false;
  787. var defaults = DataTable.defaults;
  788. var $this = $(this);
  789. /* Sanity check */
  790. if ( this.nodeName.toLowerCase() != 'table' )
  791. {
  792. _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
  793. return;
  794. }
  795. /* Backwards compatibility for the defaults */
  796. _fnCompatOpts( defaults );
  797. _fnCompatCols( defaults.column );
  798. /* Convert the camel-case defaults to Hungarian */
  799. _fnCamelToHungarian( defaults, defaults, true );
  800. _fnCamelToHungarian( defaults.column, defaults.column, true );
  801. /* Setting up the initialisation object */
  802. _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ), true );
  803. /* Check to see if we are re-initialising a table */
  804. var allSettings = DataTable.settings;
  805. for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
  806. {
  807. var s = allSettings[i];
  808. /* Base check on table node */
  809. if (
  810. s.nTable == this ||
  811. (s.nTHead && s.nTHead.parentNode == this) ||
  812. (s.nTFoot && s.nTFoot.parentNode == this)
  813. ) {
  814. var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
  815. var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
  816. if ( emptyInit || bRetrieve )
  817. {
  818. return s.oInstance;
  819. }
  820. else if ( bDestroy )
  821. {
  822. s.oInstance.fnDestroy();
  823. break;
  824. }
  825. else
  826. {
  827. _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
  828. return;
  829. }
  830. }
  831. /* If the element we are initialising has the same ID as a table which was previously
  832. * initialised, but the table nodes don't match (from before) then we destroy the old
  833. * instance by simply deleting it. This is under the assumption that the table has been
  834. * destroyed by other methods. Anyone using non-id selectors will need to do this manually
  835. */
  836. if ( s.sTableId == this.id )
  837. {
  838. allSettings.splice( i, 1 );
  839. break;
  840. }
  841. }
  842. /* Ensure the table has an ID - required for accessibility */
  843. if ( sId === null || sId === "" )
  844. {
  845. sId = "DataTables_Table_"+(DataTable.ext._unique++);
  846. this.id = sId;
  847. }
  848. /* Create the settings object for this table and set some of the default parameters */
  849. var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
  850. "sDestroyWidth": $this[0].style.width,
  851. "sInstance": sId,
  852. "sTableId": sId
  853. } );
  854. oSettings.nTable = this;
  855. oSettings.oApi = _that.internal;
  856. oSettings.oInit = oInit;
  857. allSettings.push( oSettings );
  858. // Need to add the instance after the instance after the settings object has been added
  859. // to the settings array, so we can self reference the table instance if more than one
  860. oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
  861. // Backwards compatibility, before we apply all the defaults
  862. _fnCompatOpts( oInit );
  863. _fnLanguageCompat( oInit.oLanguage );
  864. // If the length menu is given, but the init display length is not, use the length menu
  865. if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
  866. {
  867. oInit.iDisplayLength = Array.isArray( oInit.aLengthMenu[0] ) ?
  868. oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
  869. }
  870. // Apply the defaults and init options to make a single init object will all
  871. // options defined from defaults and instance options.
  872. oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
  873. // Map the initialisation options onto the settings object
  874. _fnMap( oSettings.oFeatures, oInit, [
  875. "bPaginate",
  876. "bLengthChange",
  877. "bFilter",
  878. "bSort",
  879. "bSortMulti",
  880. "bInfo",
  881. "bProcessing",
  882. "bAutoWidth",
  883. "bSortClasses",
  884. "bServerSide",
  885. "bDeferRender"
  886. ] );
  887. _fnMap( oSettings, oInit, [
  888. "asStripeClasses",
  889. "ajax",
  890. "fnServerData",
  891. "fnFormatNumber",
  892. "sServerMethod",
  893. "aaSorting",
  894. "aaSortingFixed",
  895. "aLengthMenu",
  896. "sPaginationType",
  897. "sAjaxSource",
  898. "sAjaxDataProp",
  899. "iStateDuration",
  900. "sDom",
  901. "bSortCellsTop",
  902. "iTabIndex",
  903. "fnStateLoadCallback",
  904. "fnStateSaveCallback",
  905. "renderer",
  906. "searchDelay",
  907. "rowId",
  908. [ "iCookieDuration", "iStateDuration" ], // backwards compat
  909. [ "oSearch", "oPreviousSearch" ],
  910. [ "aoSearchCols", "aoPreSearchCols" ],
  911. [ "iDisplayLength", "_iDisplayLength" ]
  912. ] );
  913. _fnMap( oSettings.oScroll, oInit, [
  914. [ "sScrollX", "sX" ],
  915. [ "sScrollXInner", "sXInner" ],
  916. [ "sScrollY", "sY" ],
  917. [ "bScrollCollapse", "bCollapse" ]
  918. ] );
  919. _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
  920. /* Callback functions which are array driven */
  921. _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' );
  922. _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' );
  923. _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' );
  924. _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' );
  925. _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' );
  926. _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' );
  927. _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' );
  928. _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' );
  929. _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' );
  930. _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' );
  931. _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' );
  932. oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
  933. /* Browser support detection */
  934. _fnBrowserDetect( oSettings );
  935. var oClasses = oSettings.oClasses;
  936. $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
  937. $this.addClass( oClasses.sTable );
  938. if ( oSettings.iInitDisplayStart === undefined )
  939. {
  940. /* Display start point, taking into account the save saving */
  941. oSettings.iInitDisplayStart = oInit.iDisplayStart;
  942. oSettings._iDisplayStart = oInit.iDisplayStart;
  943. }
  944. if ( oInit.iDeferLoading !== null )
  945. {
  946. oSettings.bDeferLoading = true;
  947. var tmp = Array.isArray( oInit.iDeferLoading );
  948. oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
  949. oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
  950. }
  951. /* Language definitions */
  952. var oLanguage = oSettings.oLanguage;
  953. $.extend( true, oLanguage, oInit.oLanguage );
  954. if ( oLanguage.sUrl )
  955. {
  956. /* Get the language definitions from a file - because this Ajax call makes the language
  957. * get async to the remainder of this function we use bInitHandedOff to indicate that
  958. * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
  959. */
  960. $.ajax( {
  961. dataType: 'json',
  962. url: oLanguage.sUrl,
  963. success: function ( json ) {
  964. _fnCamelToHungarian( defaults.oLanguage, json );
  965. _fnLanguageCompat( json );
  966. $.extend( true, oLanguage, json, oSettings.oInit.oLanguage );
  967. _fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
  968. _fnInitialise( oSettings );
  969. },
  970. error: function () {
  971. // Error occurred loading language file, continue on as best we can
  972. _fnInitialise( oSettings );
  973. }
  974. } );
  975. bInitHandedOff = true;
  976. }
  977. else {
  978. _fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
  979. }
  980. /*
  981. * Stripes
  982. */
  983. if ( oInit.asStripeClasses === null )
  984. {
  985. oSettings.asStripeClasses =[
  986. oClasses.sStripeOdd,
  987. oClasses.sStripeEven
  988. ];
  989. }
  990. /* Remove row stripe classes if they are already on the table row */
  991. var stripeClasses = oSettings.asStripeClasses;
  992. var rowOne = $this.children('tbody').find('tr').eq(0);
  993. if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
  994. return rowOne.hasClass(el);
  995. } ) ) !== -1 ) {
  996. $('tbody tr', this).removeClass( stripeClasses.join(' ') );
  997. oSettings.asDestroyStripes = stripeClasses.slice();
  998. }
  999. /*
  1000. * Columns
  1001. * See if we should load columns automatically or use defined ones
  1002. */
  1003. var anThs = [];
  1004. var aoColumnsInit;
  1005. var nThead = this.getElementsByTagName('thead');
  1006. if ( nThead.length !== 0 )
  1007. {
  1008. _fnDetectHeader( oSettings.aoHeader, nThead[0] );
  1009. anThs = _fnGetUniqueThs( oSettings );
  1010. }
  1011. /* If not given a column array, generate one with nulls */
  1012. if ( oInit.aoColumns === null )
  1013. {
  1014. aoColumnsInit = [];
  1015. for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
  1016. {
  1017. aoColumnsInit.push( null );
  1018. }
  1019. }
  1020. else
  1021. {
  1022. aoColumnsInit = oInit.aoColumns;
  1023. }
  1024. /* Add the columns */
  1025. for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
  1026. {
  1027. _fnAddColumn( oSettings, anThs ? anThs[i] : null );
  1028. }
  1029. /* Apply the column definitions */
  1030. _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
  1031. _fnColumnOptions( oSettings, iCol, oDef );
  1032. } );
  1033. /* HTML5 attribute detection - build an mData object automatically if the
  1034. * attributes are found
  1035. */
  1036. if ( rowOne.length ) {
  1037. var a = function ( cell, name ) {
  1038. return cell.getAttribute( 'data-'+name ) !== null ? name : null;
  1039. };
  1040. $( rowOne[0] ).children('th, td').each( function (i, cell) {
  1041. var col = oSettings.aoColumns[i];
  1042. if (! col) {
  1043. _fnLog( oSettings, 0, 'Incorrect column count', 18 );
  1044. }
  1045. if ( col.mData === i ) {
  1046. var sort = a( cell, 'sort' ) || a( cell, 'order' );
  1047. var filter = a( cell, 'filter' ) || a( cell, 'search' );
  1048. if ( sort !== null || filter !== null ) {
  1049. col.mData = {
  1050. _: i+'.display',
  1051. sort: sort !== null ? i+'.@data-'+sort : undefined,
  1052. type: sort !== null ? i+'.@data-'+sort : undefined,
  1053. filter: filter !== null ? i+'.@data-'+filter : undefined
  1054. };
  1055. _fnColumnOptions( oSettings, i );
  1056. }
  1057. }
  1058. } );
  1059. }
  1060. var features = oSettings.oFeatures;
  1061. var loadedInit = function () {
  1062. /*
  1063. * Sorting
  1064. * @todo For modularisation (1.11) this needs to do into a sort start up handler
  1065. */
  1066. // If aaSorting is not defined, then we use the first indicator in asSorting
  1067. // in case that has been altered, so the default sort reflects that option
  1068. if ( oInit.aaSorting === undefined ) {
  1069. var sorting = oSettings.aaSorting;
  1070. for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
  1071. sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
  1072. }
  1073. }
  1074. /* Do a first pass on the sorting classes (allows any size changes to be taken into
  1075. * account, and also will apply sorting disabled classes if disabled
  1076. */
  1077. _fnSortingClasses( oSettings );
  1078. if ( features.bSort ) {
  1079. _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
  1080. if ( oSettings.bSorted ) {
  1081. var aSort = _fnSortFlatten( oSettings );
  1082. var sortedColumns = {};
  1083. $.each( aSort, function (i, val) {
  1084. sortedColumns[ val.src ] = val.dir;
  1085. } );
  1086. _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
  1087. _fnSortAria( oSettings );
  1088. }
  1089. } );
  1090. }
  1091. _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
  1092. if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
  1093. _fnSortingClasses( oSettings );
  1094. }
  1095. }, 'sc' );
  1096. /*
  1097. * Final init
  1098. * Cache the header, body and footer as required, creating them if needed
  1099. */
  1100. // Work around for Webkit bug 83867 - store the caption-side before removing from doc
  1101. var captions = $this.children('caption').each( function () {
  1102. this._captionSide = $(this).css('caption-side');
  1103. } );
  1104. var thead = $this.children('thead');
  1105. if ( thead.length === 0 ) {
  1106. thead = $('<thead/>').appendTo($this);
  1107. }
  1108. oSettings.nTHead = thead[0];
  1109. var tbody = $this.children('tbody');
  1110. if ( tbody.length === 0 ) {
  1111. tbody = $('<tbody/>').insertAfter(thead);
  1112. }
  1113. oSettings.nTBody = tbody[0];
  1114. var tfoot = $this.children('tfoot');
  1115. if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
  1116. // If we are a scrolling table, and no footer has been given, then we need to create
  1117. // a tfoot element for the caption element to be appended to
  1118. tfoot = $('<tfoot/>').appendTo($this);
  1119. }
  1120. if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
  1121. $this.addClass( oClasses.sNoFooter );
  1122. }
  1123. else if ( tfoot.length > 0 ) {
  1124. oSettings.nTFoot = tfoot[0];
  1125. _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
  1126. }
  1127. /* Check if there is data passing into the constructor */
  1128. if ( oInit.aaData ) {
  1129. for ( i=0 ; i<oInit.aaData.length ; i++ ) {
  1130. _fnAddData( oSettings, oInit.aaData[ i ] );
  1131. }
  1132. }
  1133. else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
  1134. /* Grab the data from the page - only do this when deferred loading or no Ajax
  1135. * source since there is no point in reading the DOM data if we are then going
  1136. * to replace it with Ajax data
  1137. */
  1138. _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
  1139. }
  1140. /* Copy the data index array */
  1141. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  1142. /* Initialisation complete - table can be drawn */
  1143. oSettings.bInitialised = true;
  1144. /* Check if we need to initialise the table (it might not have been handed off to the
  1145. * language processor)
  1146. */
  1147. if ( bInitHandedOff === false ) {
  1148. _fnInitialise( oSettings );
  1149. }
  1150. };
  1151. /* Must be done after everything which can be overridden by the state saving! */
  1152. _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
  1153. if ( oInit.bStateSave )
  1154. {
  1155. features.bStateSave = true;
  1156. _fnLoadState( oSettings, oInit, loadedInit );
  1157. }
  1158. else {
  1159. loadedInit();
  1160. }
  1161. } );
  1162. _that = null;
  1163. return this;
  1164. };
  1165. /*
  1166. * It is useful to have variables which are scoped locally so only the
  1167. * DataTables functions can access them and they don't leak into global space.
  1168. * At the same time these functions are often useful over multiple files in the
  1169. * core and API, so we list, or at least document, all variables which are used
  1170. * by DataTables as private variables here. This also ensures that there is no
  1171. * clashing of variable names and that they can easily referenced for reuse.
  1172. */
  1173. // Defined else where
  1174. // _selector_run
  1175. // _selector_opts
  1176. // _selector_first
  1177. // _selector_row_indexes
  1178. var _ext; // DataTable.ext
  1179. var _Api; // DataTable.Api
  1180. var _api_register; // DataTable.Api.register
  1181. var _api_registerPlural; // DataTable.Api.registerPlural
  1182. var _re_dic = {};
  1183. var _re_new_lines = /[\r\n\u2028]/g;
  1184. var _re_html = /<.*?>/g;
  1185. // This is not strict ISO8601 - Date.parse() is quite lax, although
  1186. // implementations differ between browsers.
  1187. var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
  1188. // Escape regular expression special characters
  1189. var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
  1190. // http://en.wikipedia.org/wiki/Foreign_exchange_market
  1191. // - \u20BD - Russian ruble.
  1192. // - \u20a9 - South Korean Won
  1193. // - \u20BA - Turkish Lira
  1194. // - \u20B9 - Indian Rupee
  1195. // - R - Brazil (R$) and South Africa
  1196. // - fr - Swiss Franc
  1197. // - kr - Swedish krona, Norwegian krone and Danish krone
  1198. // - \u2009 is thin space and \u202F is narrow no-break space, both used in many
  1199. // - Ƀ - Bitcoin
  1200. // - Ξ - Ethereum
  1201. // standards as thousands separators.
  1202. var _re_formatted_numeric = /['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;
  1203. var _empty = function ( d ) {
  1204. return !d || d === true || d === '-' ? true : false;
  1205. };
  1206. var _intVal = function ( s ) {
  1207. var integer = parseInt( s, 10 );
  1208. return !isNaN(integer) && isFinite(s) ? integer : null;
  1209. };
  1210. // Convert from a formatted number with characters other than `.` as the
  1211. // decimal place, to a Javascript number
  1212. var _numToDecimal = function ( num, decimalPoint ) {
  1213. // Cache created regular expressions for speed as this function is called often
  1214. if ( ! _re_dic[ decimalPoint ] ) {
  1215. _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
  1216. }
  1217. return typeof num === 'string' && decimalPoint !== '.' ?
  1218. num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
  1219. num;
  1220. };
  1221. var _isNumber = function ( d, decimalPoint, formatted ) {
  1222. var strType = typeof d === 'string';
  1223. // If empty return immediately so there must be a number if it is a
  1224. // formatted string (this stops the string "k", or "kr", etc being detected
  1225. // as a formatted number for currency
  1226. if ( _empty( d ) ) {
  1227. return true;
  1228. }
  1229. if ( decimalPoint && strType ) {
  1230. d = _numToDecimal( d, decimalPoint );
  1231. }
  1232. if ( formatted && strType ) {
  1233. d = d.replace( _re_formatted_numeric, '' );
  1234. }
  1235. return !isNaN( parseFloat(d) ) && isFinite( d );
  1236. };
  1237. // A string without HTML in it can be considered to be HTML still
  1238. var _isHtml = function ( d ) {
  1239. return _empty( d ) || typeof d === 'string';
  1240. };
  1241. var _htmlNumeric = function ( d, decimalPoint, formatted ) {
  1242. if ( _empty( d ) ) {
  1243. return true;
  1244. }
  1245. var html = _isHtml( d );
  1246. return ! html ?
  1247. null :
  1248. _isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
  1249. true :
  1250. null;
  1251. };
  1252. var _pluck = function ( a, prop, prop2 ) {
  1253. var out = [];
  1254. var i=0, ien=a.length;
  1255. // Could have the test in the loop for slightly smaller code, but speed
  1256. // is essential here
  1257. if ( prop2 !== undefined ) {
  1258. for ( ; i<ien ; i++ ) {
  1259. if ( a[i] && a[i][ prop ] ) {
  1260. out.push( a[i][ prop ][ prop2 ] );
  1261. }
  1262. }
  1263. }
  1264. else {
  1265. for ( ; i<ien ; i++ ) {
  1266. if ( a[i] ) {
  1267. out.push( a[i][ prop ] );
  1268. }
  1269. }
  1270. }
  1271. return out;
  1272. };
  1273. // Basically the same as _pluck, but rather than looping over `a` we use `order`
  1274. // as the indexes to pick from `a`
  1275. var _pluck_order = function ( a, order, prop, prop2 )
  1276. {
  1277. var out = [];
  1278. var i=0, ien=order.length;
  1279. // Could have the test in the loop for slightly smaller code, but speed
  1280. // is essential here
  1281. if ( prop2 !== undefined ) {
  1282. for ( ; i<ien ; i++ ) {
  1283. if ( a[ order[i] ][ prop ] ) {
  1284. out.push( a[ order[i] ][ prop ][ prop2 ] );
  1285. }
  1286. }
  1287. }
  1288. else {
  1289. for ( ; i<ien ; i++ ) {
  1290. out.push( a[ order[i] ][ prop ] );
  1291. }
  1292. }
  1293. return out;
  1294. };
  1295. var _range = function ( len, start )
  1296. {
  1297. var out = [];
  1298. var end;
  1299. if ( start === undefined ) {
  1300. start = 0;
  1301. end = len;
  1302. }
  1303. else {
  1304. end = start;
  1305. start = len;
  1306. }
  1307. for ( var i=start ; i<end ; i++ ) {
  1308. out.push( i );
  1309. }
  1310. return out;
  1311. };
  1312. var _removeEmpty = function ( a )
  1313. {
  1314. var out = [];
  1315. for ( var i=0, ien=a.length ; i<ien ; i++ ) {
  1316. if ( a[i] ) { // careful - will remove all falsy values!
  1317. out.push( a[i] );
  1318. }
  1319. }
  1320. return out;
  1321. };
  1322. var _stripHtml = function ( d ) {
  1323. return d.replace( _re_html, '' );
  1324. };
  1325. /**
  1326. * Determine if all values in the array are unique. This means we can short
  1327. * cut the _unique method at the cost of a single loop. A sorted array is used
  1328. * to easily check the values.
  1329. *
  1330. * @param {array} src Source array
  1331. * @return {boolean} true if all unique, false otherwise
  1332. * @ignore
  1333. */
  1334. var _areAllUnique = function ( src ) {
  1335. if ( src.length < 2 ) {
  1336. return true;
  1337. }
  1338. var sorted = src.slice().sort();
  1339. var last = sorted[0];
  1340. for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
  1341. if ( sorted[i] === last ) {
  1342. return false;
  1343. }
  1344. last = sorted[i];
  1345. }
  1346. return true;
  1347. };
  1348. /**
  1349. * Find the unique elements in a source array.
  1350. *
  1351. * @param {array} src Source array
  1352. * @return {array} Array of unique items
  1353. * @ignore
  1354. */
  1355. var _unique = function ( src )
  1356. {
  1357. if ( _areAllUnique( src ) ) {
  1358. return src.slice();
  1359. }
  1360. // A faster unique method is to use object keys to identify used values,
  1361. // but this doesn't work with arrays or objects, which we must also
  1362. // consider. See jsperf.com/compare-array-unique-versions/4 for more
  1363. // information.
  1364. var
  1365. out = [],
  1366. val,
  1367. i, ien=src.length,
  1368. j, k=0;
  1369. again: for ( i=0 ; i<ien ; i++ ) {
  1370. val = src[i];
  1371. for ( j=0 ; j<k ; j++ ) {
  1372. if ( out[j] === val ) {
  1373. continue again;
  1374. }
  1375. }
  1376. out.push( val );
  1377. k++;
  1378. }
  1379. return out;
  1380. };
  1381. // Surprisingly this is faster than [].concat.apply
  1382. // https://jsperf.com/flatten-an-array-loop-vs-reduce/2
  1383. var _flatten = function (out, val) {
  1384. if (Array.isArray(val)) {
  1385. for (var i=0 ; i<val.length ; i++) {
  1386. _flatten(out, val[i]);
  1387. }
  1388. }
  1389. else {
  1390. out.push(val);
  1391. }
  1392. return out;
  1393. }
  1394. var _includes = function (search, start) {
  1395. if (start === undefined) {
  1396. start = 0;
  1397. }
  1398. return this.indexOf(search, start) !== -1;
  1399. };
  1400. // Array.isArray polyfill.
  1401. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
  1402. if (! Array.isArray) {
  1403. Array.isArray = function(arg) {
  1404. return Object.prototype.toString.call(arg) === '[object Array]';
  1405. };
  1406. }
  1407. if (! Array.prototype.includes) {
  1408. Array.prototype.includes = _includes;
  1409. }
  1410. // .trim() polyfill
  1411. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
  1412. if (!String.prototype.trim) {
  1413. String.prototype.trim = function () {
  1414. return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  1415. };
  1416. }
  1417. if (! String.prototype.includes) {
  1418. String.prototype.includes = _includes;
  1419. }
  1420. /**
  1421. * DataTables utility methods
  1422. *
  1423. * This namespace provides helper methods that DataTables uses internally to
  1424. * create a DataTable, but which are not exclusively used only for DataTables.
  1425. * These methods can be used by extension authors to save the duplication of
  1426. * code.
  1427. *
  1428. * @namespace
  1429. */
  1430. DataTable.util = {
  1431. /**
  1432. * Throttle the calls to a function. Arguments and context are maintained
  1433. * for the throttled function.
  1434. *
  1435. * @param {function} fn Function to be called
  1436. * @param {integer} freq Call frequency in mS
  1437. * @return {function} Wrapped function
  1438. */
  1439. throttle: function ( fn, freq ) {
  1440. var
  1441. frequency = freq !== undefined ? freq : 200,
  1442. last,
  1443. timer;
  1444. return function () {
  1445. var
  1446. that = this,
  1447. now = +new Date(),
  1448. args = arguments;
  1449. if ( last && now < last + frequency ) {
  1450. clearTimeout( timer );
  1451. timer = setTimeout( function () {
  1452. last = undefined;
  1453. fn.apply( that, args );
  1454. }, frequency );
  1455. }
  1456. else {
  1457. last = now;
  1458. fn.apply( that, args );
  1459. }
  1460. };
  1461. },
  1462. /**
  1463. * Escape a string such that it can be used in a regular expression
  1464. *
  1465. * @param {string} val string to escape
  1466. * @returns {string} escaped string
  1467. */
  1468. escapeRegex: function ( val ) {
  1469. return val.replace( _re_escape_regex, '\\$1' );
  1470. },
  1471. /**
  1472. * Create a function that will write to a nested object or array
  1473. * @param {*} source JSON notation string
  1474. * @returns Write function
  1475. */
  1476. set: function ( source ) {
  1477. if ( $.isPlainObject( source ) ) {
  1478. /* Unlike get, only the underscore (global) option is used for for
  1479. * setting data since we don't know the type here. This is why an object
  1480. * option is not documented for `mData` (which is read/write), but it is
  1481. * for `mRender` which is read only.
  1482. */
  1483. return DataTable.util.set( source._ );
  1484. }
  1485. else if ( source === null ) {
  1486. // Nothing to do when the data source is null
  1487. return function () {};
  1488. }
  1489. else if ( typeof source === 'function' ) {
  1490. return function (data, val, meta) {
  1491. source( data, 'set', val, meta );
  1492. };
  1493. }
  1494. else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
  1495. source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
  1496. {
  1497. // Like the get, we need to get data from a nested object
  1498. var setData = function (data, val, src) {
  1499. var a = _fnSplitObjNotation( src ), b;
  1500. var aLast = a[a.length-1];
  1501. var arrayNotation, funcNotation, o, innerSrc;
  1502. for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) {
  1503. // Protect against prototype pollution
  1504. if (a[i] === '__proto__' || a[i] === 'constructor') {
  1505. throw new Error('Cannot set prototype values');
  1506. }
  1507. // Check if we are dealing with an array notation request
  1508. arrayNotation = a[i].match(__reArray);
  1509. funcNotation = a[i].match(__reFn);
  1510. if ( arrayNotation ) {
  1511. a[i] = a[i].replace(__reArray, '');
  1512. data[ a[i] ] = [];
  1513. // Get the remainder of the nested object to set so we can recurse
  1514. b = a.slice();
  1515. b.splice( 0, i+1 );
  1516. innerSrc = b.join('.');
  1517. // Traverse each entry in the array setting the properties requested
  1518. if ( Array.isArray( val ) ) {
  1519. for ( var j=0, jLen=val.length ; j<jLen ; j++ ) {
  1520. o = {};
  1521. setData( o, val[j], innerSrc );
  1522. data[ a[i] ].push( o );
  1523. }
  1524. }
  1525. else {
  1526. // We've been asked to save data to an array, but it
  1527. // isn't array data to be saved. Best that can be done
  1528. // is to just save the value.
  1529. data[ a[i] ] = val;
  1530. }
  1531. // The inner call to setData has already traversed through the remainder
  1532. // of the source and has set the data, thus we can exit here
  1533. return;
  1534. }
  1535. else if ( funcNotation ) {
  1536. // Function call
  1537. a[i] = a[i].replace(__reFn, '');
  1538. data = data[ a[i] ]( val );
  1539. }
  1540. // If the nested object doesn't currently exist - since we are
  1541. // trying to set the value - create it
  1542. if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) {
  1543. data[ a[i] ] = {};
  1544. }
  1545. data = data[ a[i] ];
  1546. }
  1547. // Last item in the input - i.e, the actual set
  1548. if ( aLast.match(__reFn ) ) {
  1549. // Function call
  1550. data = data[ aLast.replace(__reFn, '') ]( val );
  1551. }
  1552. else {
  1553. // If array notation is used, we just want to strip it and use the property name
  1554. // and assign the value. If it isn't used, then we get the result we want anyway
  1555. data[ aLast.replace(__reArray, '') ] = val;
  1556. }
  1557. };
  1558. return function (data, val) { // meta is also passed in, but not used
  1559. return setData( data, val, source );
  1560. };
  1561. }
  1562. else {
  1563. // Array or flat object mapping
  1564. return function (data, val) { // meta is also passed in, but not used
  1565. data[source] = val;
  1566. };
  1567. }
  1568. },
  1569. /**
  1570. * Create a function that will read nested objects from arrays, based on JSON notation
  1571. * @param {*} source JSON notation string
  1572. * @returns Value read
  1573. */
  1574. get: function ( source ) {
  1575. if ( $.isPlainObject( source ) ) {
  1576. // Build an object of get functions, and wrap them in a single call
  1577. var o = {};
  1578. $.each( source, function (key, val) {
  1579. if ( val ) {
  1580. o[key] = DataTable.util.get( val );
  1581. }
  1582. } );
  1583. return function (data, type, row, meta) {
  1584. var t = o[type] || o._;
  1585. return t !== undefined ?
  1586. t(data, type, row, meta) :
  1587. data;
  1588. };
  1589. }
  1590. else if ( source === null ) {
  1591. // Give an empty string for rendering / sorting etc
  1592. return function (data) { // type, row and meta also passed, but not used
  1593. return data;
  1594. };
  1595. }
  1596. else if ( typeof source === 'function' ) {
  1597. return function (data, type, row, meta) {
  1598. return source( data, type, row, meta );
  1599. };
  1600. }
  1601. else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
  1602. source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
  1603. {
  1604. /* If there is a . in the source string then the data source is in a
  1605. * nested object so we loop over the data for each level to get the next
  1606. * level down. On each loop we test for undefined, and if found immediately
  1607. * return. This allows entire objects to be missing and sDefaultContent to
  1608. * be used if defined, rather than throwing an error
  1609. */
  1610. var fetchData = function (data, type, src) {
  1611. var arrayNotation, funcNotation, out, innerSrc;
  1612. if ( src !== "" ) {
  1613. var a = _fnSplitObjNotation( src );
  1614. for ( var i=0, iLen=a.length ; i<iLen ; i++ ) {
  1615. // Check if we are dealing with special notation
  1616. arrayNotation = a[i].match(__reArray);
  1617. funcNotation = a[i].match(__reFn);
  1618. if ( arrayNotation ) {
  1619. // Array notation
  1620. a[i] = a[i].replace(__reArray, '');
  1621. // Condition allows simply [] to be passed in
  1622. if ( a[i] !== "" ) {
  1623. data = data[ a[i] ];
  1624. }
  1625. out = [];
  1626. // Get the remainder of the nested object to get
  1627. a.splice( 0, i+1 );
  1628. innerSrc = a.join('.');
  1629. // Traverse each entry in the array getting the properties requested
  1630. if ( Array.isArray( data ) ) {
  1631. for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
  1632. out.push( fetchData( data[j], type, innerSrc ) );
  1633. }
  1634. }
  1635. // If a string is given in between the array notation indicators, that
  1636. // is used to join the strings together, otherwise an array is returned
  1637. var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
  1638. data = (join==="") ? out : out.join(join);
  1639. // The inner call to fetchData has already traversed through the remainder
  1640. // of the source requested, so we exit from the loop
  1641. break;
  1642. }
  1643. else if ( funcNotation ) {
  1644. // Function call
  1645. a[i] = a[i].replace(__reFn, '');
  1646. data = data[ a[i] ]();
  1647. continue;
  1648. }
  1649. if ( data === null || data[ a[i] ] === undefined ) {
  1650. return undefined;
  1651. }
  1652. data = data[ a[i] ];
  1653. }
  1654. }
  1655. return data;
  1656. };
  1657. return function (data, type) { // row and meta also passed, but not used
  1658. return fetchData( data, type, source );
  1659. };
  1660. }
  1661. else {
  1662. // Array or flat object mapping
  1663. return function (data, type) { // row and meta also passed, but not used
  1664. return data[source];
  1665. };
  1666. }
  1667. }
  1668. };
  1669. /**
  1670. * Create a mapping object that allows camel case parameters to be looked up
  1671. * for their Hungarian counterparts. The mapping is stored in a private
  1672. * parameter called `_hungarianMap` which can be accessed on the source object.
  1673. * @param {object} o
  1674. * @memberof DataTable#oApi
  1675. */
  1676. function _fnHungarianMap ( o )
  1677. {
  1678. var
  1679. hungarian = 'a aa ai ao as b fn i m o s ',
  1680. match,
  1681. newKey,
  1682. map = {};
  1683. $.each( o, function (key, val) {
  1684. match = key.match(/^([^A-Z]+?)([A-Z])/);
  1685. if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
  1686. {
  1687. newKey = key.replace( match[0], match[2].toLowerCase() );
  1688. map[ newKey ] = key;
  1689. if ( match[1] === 'o' )
  1690. {
  1691. _fnHungarianMap( o[key] );
  1692. }
  1693. }
  1694. } );
  1695. o._hungarianMap = map;
  1696. }
  1697. /**
  1698. * Convert from camel case parameters to Hungarian, based on a Hungarian map
  1699. * created by _fnHungarianMap.
  1700. * @param {object} src The model object which holds all parameters that can be
  1701. * mapped.
  1702. * @param {object} user The object to convert from camel case to Hungarian.
  1703. * @param {boolean} force When set to `true`, properties which already have a
  1704. * Hungarian value in the `user` object will be overwritten. Otherwise they
  1705. * won't be.
  1706. * @memberof DataTable#oApi
  1707. */
  1708. function _fnCamelToHungarian ( src, user, force )
  1709. {
  1710. if ( ! src._hungarianMap ) {
  1711. _fnHungarianMap( src );
  1712. }
  1713. var hungarianKey;
  1714. $.each( user, function (key, val) {
  1715. hungarianKey = src._hungarianMap[ key ];
  1716. if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
  1717. {
  1718. // For objects, we need to buzz down into the object to copy parameters
  1719. if ( hungarianKey.charAt(0) === 'o' )
  1720. {
  1721. // Copy the camelCase options over to the hungarian
  1722. if ( ! user[ hungarianKey ] ) {
  1723. user[ hungarianKey ] = {};
  1724. }
  1725. $.extend( true, user[hungarianKey], user[key] );
  1726. _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
  1727. }
  1728. else {
  1729. user[hungarianKey] = user[ key ];
  1730. }
  1731. }
  1732. } );
  1733. }
  1734. /**
  1735. * Language compatibility - when certain options are given, and others aren't, we
  1736. * need to duplicate the values over, in order to provide backwards compatibility
  1737. * with older language files.
  1738. * @param {object} oSettings dataTables settings object
  1739. * @memberof DataTable#oApi
  1740. */
  1741. function _fnLanguageCompat( lang )
  1742. {
  1743. // Note the use of the Hungarian notation for the parameters in this method as
  1744. // this is called after the mapping of camelCase to Hungarian
  1745. var defaults = DataTable.defaults.oLanguage;
  1746. // Default mapping
  1747. var defaultDecimal = defaults.sDecimal;
  1748. if ( defaultDecimal ) {
  1749. _addNumericSort( defaultDecimal );
  1750. }
  1751. if ( lang ) {
  1752. var zeroRecords = lang.sZeroRecords;
  1753. // Backwards compatibility - if there is no sEmptyTable given, then use the same as
  1754. // sZeroRecords - assuming that is given.
  1755. if ( ! lang.sEmptyTable && zeroRecords &&
  1756. defaults.sEmptyTable === "No data available in table" )
  1757. {
  1758. _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
  1759. }
  1760. // Likewise with loading records
  1761. if ( ! lang.sLoadingRecords && zeroRecords &&
  1762. defaults.sLoadingRecords === "Loading..." )
  1763. {
  1764. _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
  1765. }
  1766. // Old parameter name of the thousands separator mapped onto the new
  1767. if ( lang.sInfoThousands ) {
  1768. lang.sThousands = lang.sInfoThousands;
  1769. }
  1770. var decimal = lang.sDecimal;
  1771. if ( decimal && defaultDecimal !== decimal ) {
  1772. _addNumericSort( decimal );
  1773. }
  1774. }
  1775. }
  1776. /**
  1777. * Map one parameter onto another
  1778. * @param {object} o Object to map
  1779. * @param {*} knew The new parameter name
  1780. * @param {*} old The old parameter name
  1781. */
  1782. var _fnCompatMap = function ( o, knew, old ) {
  1783. if ( o[ knew ] !== undefined ) {
  1784. o[ old ] = o[ knew ];
  1785. }
  1786. };
  1787. /**
  1788. * Provide backwards compatibility for the main DT options. Note that the new
  1789. * options are mapped onto the old parameters, so this is an external interface
  1790. * change only.
  1791. * @param {object} init Object to map
  1792. */
  1793. function _fnCompatOpts ( init )
  1794. {
  1795. _fnCompatMap( init, 'ordering', 'bSort' );
  1796. _fnCompatMap( init, 'orderMulti', 'bSortMulti' );
  1797. _fnCompatMap( init, 'orderClasses', 'bSortClasses' );
  1798. _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
  1799. _fnCompatMap( init, 'order', 'aaSorting' );
  1800. _fnCompatMap( init, 'orderFixed', 'aaSortingFixed' );
  1801. _fnCompatMap( init, 'paging', 'bPaginate' );
  1802. _fnCompatMap( init, 'pagingType', 'sPaginationType' );
  1803. _fnCompatMap( init, 'pageLength', 'iDisplayLength' );
  1804. _fnCompatMap( init, 'searching', 'bFilter' );
  1805. // Boolean initialisation of x-scrolling
  1806. if ( typeof init.sScrollX === 'boolean' ) {
  1807. init.sScrollX = init.sScrollX ? '100%' : '';
  1808. }
  1809. if ( typeof init.scrollX === 'boolean' ) {
  1810. init.scrollX = init.scrollX ? '100%' : '';
  1811. }
  1812. // Column search objects are in an array, so it needs to be converted
  1813. // element by element
  1814. var searchCols = init.aoSearchCols;
  1815. if ( searchCols ) {
  1816. for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
  1817. if ( searchCols[i] ) {
  1818. _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
  1819. }
  1820. }
  1821. }
  1822. }
  1823. /**
  1824. * Provide backwards compatibility for column options. Note that the new options
  1825. * are mapped onto the old parameters, so this is an external interface change
  1826. * only.
  1827. * @param {object} init Object to map
  1828. */
  1829. function _fnCompatCols ( init )
  1830. {
  1831. _fnCompatMap( init, 'orderable', 'bSortable' );
  1832. _fnCompatMap( init, 'orderData', 'aDataSort' );
  1833. _fnCompatMap( init, 'orderSequence', 'asSorting' );
  1834. _fnCompatMap( init, 'orderDataType', 'sortDataType' );
  1835. // orderData can be given as an integer
  1836. var dataSort = init.aDataSort;
  1837. if ( typeof dataSort === 'number' && ! Array.isArray( dataSort ) ) {
  1838. init.aDataSort = [ dataSort ];
  1839. }
  1840. }
  1841. /**
  1842. * Browser feature detection for capabilities, quirks
  1843. * @param {object} settings dataTables settings object
  1844. * @memberof DataTable#oApi
  1845. */
  1846. function _fnBrowserDetect( settings )
  1847. {
  1848. // We don't need to do this every time DataTables is constructed, the values
  1849. // calculated are specific to the browser and OS configuration which we
  1850. // don't expect to change between initialisations
  1851. if ( ! DataTable.__browser ) {
  1852. var browser = {};
  1853. DataTable.__browser = browser;
  1854. // Scrolling feature / quirks detection
  1855. var n = $('<div/>')
  1856. .css( {
  1857. position: 'fixed',
  1858. top: 0,
  1859. left: $(window).scrollLeft()*-1, // allow for scrolling
  1860. height: 1,
  1861. width: 1,
  1862. overflow: 'hidden'
  1863. } )
  1864. .append(
  1865. $('<div/>')
  1866. .css( {
  1867. position: 'absolute',
  1868. top: 1,
  1869. left: 1,
  1870. width: 100,
  1871. overflow: 'scroll'
  1872. } )
  1873. .append(
  1874. $('<div/>')
  1875. .css( {
  1876. width: '100%',
  1877. height: 10
  1878. } )
  1879. )
  1880. )
  1881. .appendTo( 'body' );
  1882. var outer = n.children();
  1883. var inner = outer.children();
  1884. // Numbers below, in order, are:
  1885. // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
  1886. //
  1887. // IE6 XP: 100 100 100 83
  1888. // IE7 Vista: 100 100 100 83
  1889. // IE 8+ Windows: 83 83 100 83
  1890. // Evergreen Windows: 83 83 100 83
  1891. // Evergreen Mac with scrollbars: 85 85 100 85
  1892. // Evergreen Mac without scrollbars: 100 100 100 100
  1893. // Get scrollbar width
  1894. browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
  1895. // IE6/7 will oversize a width 100% element inside a scrolling element, to
  1896. // include the width of the scrollbar, while other browsers ensure the inner
  1897. // element is contained without forcing scrolling
  1898. browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
  1899. // In rtl text layout, some browsers (most, but not all) will place the
  1900. // scrollbar on the left, rather than the right.
  1901. browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
  1902. // IE8- don't provide height and width for getBoundingClientRect
  1903. browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
  1904. n.remove();
  1905. }
  1906. $.extend( settings.oBrowser, DataTable.__browser );
  1907. settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
  1908. }
  1909. /**
  1910. * Array.prototype reduce[Right] method, used for browsers which don't support
  1911. * JS 1.6. Done this way to reduce code size, since we iterate either way
  1912. * @param {object} settings dataTables settings object
  1913. * @memberof DataTable#oApi
  1914. */
  1915. function _fnReduce ( that, fn, init, start, end, inc )
  1916. {
  1917. var
  1918. i = start,
  1919. value,
  1920. isSet = false;
  1921. if ( init !== undefined ) {
  1922. value = init;
  1923. isSet = true;
  1924. }
  1925. while ( i !== end ) {
  1926. if ( ! that.hasOwnProperty(i) ) {
  1927. continue;
  1928. }
  1929. value = isSet ?
  1930. fn( value, that[i], i, that ) :
  1931. that[i];
  1932. isSet = true;
  1933. i += inc;
  1934. }
  1935. return value;
  1936. }
  1937. /**
  1938. * Add a column to the list used for the table with default values
  1939. * @param {object} oSettings dataTables settings object
  1940. * @param {node} nTh The th element for this column
  1941. * @memberof DataTable#oApi
  1942. */
  1943. function _fnAddColumn( oSettings, nTh )
  1944. {
  1945. // Add column to aoColumns array
  1946. var oDefaults = DataTable.defaults.column;
  1947. var iCol = oSettings.aoColumns.length;
  1948. var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
  1949. "nTh": nTh ? nTh : document.createElement('th'),
  1950. "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',
  1951. "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
  1952. "mData": oDefaults.mData ? oDefaults.mData : iCol,
  1953. idx: iCol
  1954. } );
  1955. oSettings.aoColumns.push( oCol );
  1956. // Add search object for column specific search. Note that the `searchCols[ iCol ]`
  1957. // passed into extend can be undefined. This allows the user to give a default
  1958. // with only some of the parameters defined, and also not give a default
  1959. var searchCols = oSettings.aoPreSearchCols;
  1960. searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
  1961. // Use the default column options function to initialise classes etc
  1962. _fnColumnOptions( oSettings, iCol, $(nTh).data() );
  1963. }
  1964. /**
  1965. * Apply options for a column
  1966. * @param {object} oSettings dataTables settings object
  1967. * @param {int} iCol column index to consider
  1968. * @param {object} oOptions object with sType, bVisible and bSearchable etc
  1969. * @memberof DataTable#oApi
  1970. */
  1971. function _fnColumnOptions( oSettings, iCol, oOptions )
  1972. {
  1973. var oCol = oSettings.aoColumns[ iCol ];
  1974. var oClasses = oSettings.oClasses;
  1975. var th = $(oCol.nTh);
  1976. // Try to get width information from the DOM. We can't get it from CSS
  1977. // as we'd need to parse the CSS stylesheet. `width` option can override
  1978. if ( ! oCol.sWidthOrig ) {
  1979. // Width attribute
  1980. oCol.sWidthOrig = th.attr('width') || null;
  1981. // Style attribute
  1982. var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
  1983. if ( t ) {
  1984. oCol.sWidthOrig = t[1];
  1985. }
  1986. }
  1987. /* User specified column options */
  1988. if ( oOptions !== undefined && oOptions !== null )
  1989. {
  1990. // Backwards compatibility
  1991. _fnCompatCols( oOptions );
  1992. // Map camel case parameters to their Hungarian counterparts
  1993. _fnCamelToHungarian( DataTable.defaults.column, oOptions, true );
  1994. /* Backwards compatibility for mDataProp */
  1995. if ( oOptions.mDataProp !== undefined && !oOptions.mData )
  1996. {
  1997. oOptions.mData = oOptions.mDataProp;
  1998. }
  1999. if ( oOptions.sType )
  2000. {
  2001. oCol._sManualType = oOptions.sType;
  2002. }
  2003. // `class` is a reserved word in Javascript, so we need to provide
  2004. // the ability to use a valid name for the camel case input
  2005. if ( oOptions.className && ! oOptions.sClass )
  2006. {
  2007. oOptions.sClass = oOptions.className;
  2008. }
  2009. if ( oOptions.sClass ) {
  2010. th.addClass( oOptions.sClass );
  2011. }
  2012. var origClass = oCol.sClass;
  2013. $.extend( oCol, oOptions );
  2014. _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
  2015. // Merge class from previously defined classes with this one, rather than just
  2016. // overwriting it in the extend above
  2017. if (origClass !== oCol.sClass) {
  2018. oCol.sClass = origClass + ' ' + oCol.sClass;
  2019. }
  2020. /* iDataSort to be applied (backwards compatibility), but aDataSort will take
  2021. * priority if defined
  2022. */
  2023. if ( oOptions.iDataSort !== undefined )
  2024. {
  2025. oCol.aDataSort = [ oOptions.iDataSort ];
  2026. }
  2027. _fnMap( oCol, oOptions, "aDataSort" );
  2028. }
  2029. /* Cache the data get and set functions for speed */
  2030. var mDataSrc = oCol.mData;
  2031. var mData = _fnGetObjectDataFn( mDataSrc );
  2032. var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
  2033. var attrTest = function( src ) {
  2034. return typeof src === 'string' && src.indexOf('@') !== -1;
  2035. };
  2036. oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
  2037. attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
  2038. );
  2039. oCol._setter = null;
  2040. oCol.fnGetData = function (rowData, type, meta) {
  2041. var innerData = mData( rowData, type, undefined, meta );
  2042. return mRender && type ?
  2043. mRender( innerData, type, rowData, meta ) :
  2044. innerData;
  2045. };
  2046. oCol.fnSetData = function ( rowData, val, meta ) {
  2047. return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
  2048. };
  2049. // Indicate if DataTables should read DOM data as an object or array
  2050. // Used in _fnGetRowElements
  2051. if ( typeof mDataSrc !== 'number' ) {
  2052. oSettings._rowReadObject = true;
  2053. }
  2054. /* Feature sorting overrides column specific when off */
  2055. if ( !oSettings.oFeatures.bSort )
  2056. {
  2057. oCol.bSortable = false;
  2058. th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
  2059. }
  2060. /* Check that the class assignment is correct for sorting */
  2061. var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
  2062. var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
  2063. if ( !oCol.bSortable || (!bAsc && !bDesc) )
  2064. {
  2065. oCol.sSortingClass = oClasses.sSortableNone;
  2066. oCol.sSortingClassJUI = "";
  2067. }
  2068. else if ( bAsc && !bDesc )
  2069. {
  2070. oCol.sSortingClass = oClasses.sSortableAsc;
  2071. oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
  2072. }
  2073. else if ( !bAsc && bDesc )
  2074. {
  2075. oCol.sSortingClass = oClasses.sSortableDesc;
  2076. oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
  2077. }
  2078. else
  2079. {
  2080. oCol.sSortingClass = oClasses.sSortable;
  2081. oCol.sSortingClassJUI = oClasses.sSortJUI;
  2082. }
  2083. }
  2084. /**
  2085. * Adjust the table column widths for new data. Note: you would probably want to
  2086. * do a redraw after calling this function!
  2087. * @param {object} settings dataTables settings object
  2088. * @memberof DataTable#oApi
  2089. */
  2090. function _fnAdjustColumnSizing ( settings )
  2091. {
  2092. /* Not interested in doing column width calculation if auto-width is disabled */
  2093. if ( settings.oFeatures.bAutoWidth !== false )
  2094. {
  2095. var columns = settings.aoColumns;
  2096. _fnCalculateColumnWidths( settings );
  2097. for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
  2098. {
  2099. columns[i].nTh.style.width = columns[i].sWidth;
  2100. }
  2101. }
  2102. var scroll = settings.oScroll;
  2103. if ( scroll.sY !== '' || scroll.sX !== '')
  2104. {
  2105. _fnScrollDraw( settings );
  2106. }
  2107. _fnCallbackFire( settings, null, 'column-sizing', [settings] );
  2108. }
  2109. /**
  2110. * Convert the index of a visible column to the index in the data array (take account
  2111. * of hidden columns)
  2112. * @param {object} oSettings dataTables settings object
  2113. * @param {int} iMatch Visible column index to lookup
  2114. * @returns {int} i the data index
  2115. * @memberof DataTable#oApi
  2116. */
  2117. function _fnVisibleToColumnIndex( oSettings, iMatch )
  2118. {
  2119. var aiVis = _fnGetColumns( oSettings, 'bVisible' );
  2120. return typeof aiVis[iMatch] === 'number' ?
  2121. aiVis[iMatch] :
  2122. null;
  2123. }
  2124. /**
  2125. * Convert the index of an index in the data array and convert it to the visible
  2126. * column index (take account of hidden columns)
  2127. * @param {int} iMatch Column index to lookup
  2128. * @param {object} oSettings dataTables settings object
  2129. * @returns {int} i the data index
  2130. * @memberof DataTable#oApi
  2131. */
  2132. function _fnColumnIndexToVisible( oSettings, iMatch )
  2133. {
  2134. var aiVis = _fnGetColumns( oSettings, 'bVisible' );
  2135. var iPos = $.inArray( iMatch, aiVis );
  2136. return iPos !== -1 ? iPos : null;
  2137. }
  2138. /**
  2139. * Get the number of visible columns
  2140. * @param {object} oSettings dataTables settings object
  2141. * @returns {int} i the number of visible columns
  2142. * @memberof DataTable#oApi
  2143. */
  2144. function _fnVisbleColumns( oSettings )
  2145. {
  2146. var vis = 0;
  2147. // No reduce in IE8, use a loop for now
  2148. $.each( oSettings.aoColumns, function ( i, col ) {
  2149. if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
  2150. vis++;
  2151. }
  2152. } );
  2153. return vis;
  2154. }
  2155. /**
  2156. * Get an array of column indexes that match a given property
  2157. * @param {object} oSettings dataTables settings object
  2158. * @param {string} sParam Parameter in aoColumns to look for - typically
  2159. * bVisible or bSearchable
  2160. * @returns {array} Array of indexes with matched properties
  2161. * @memberof DataTable#oApi
  2162. */
  2163. function _fnGetColumns( oSettings, sParam )
  2164. {
  2165. var a = [];
  2166. $.map( oSettings.aoColumns, function(val, i) {
  2167. if ( val[sParam] ) {
  2168. a.push( i );
  2169. }
  2170. } );
  2171. return a;
  2172. }
  2173. /**
  2174. * Calculate the 'type' of a column
  2175. * @param {object} settings dataTables settings object
  2176. * @memberof DataTable#oApi
  2177. */
  2178. function _fnColumnTypes ( settings )
  2179. {
  2180. var columns = settings.aoColumns;
  2181. var data = settings.aoData;
  2182. var types = DataTable.ext.type.detect;
  2183. var i, ien, j, jen, k, ken;
  2184. var col, cell, detectedType, cache;
  2185. // For each column, spin over the
  2186. for ( i=0, ien=columns.length ; i<ien ; i++ ) {
  2187. col = columns[i];
  2188. cache = [];
  2189. if ( ! col.sType && col._sManualType ) {
  2190. col.sType = col._sManualType;
  2191. }
  2192. else if ( ! col.sType ) {
  2193. for ( j=0, jen=types.length ; j<jen ; j++ ) {
  2194. for ( k=0, ken=data.length ; k<ken ; k++ ) {
  2195. // Use a cache array so we only need to get the type data
  2196. // from the formatter once (when using multiple detectors)
  2197. if ( cache[k] === undefined ) {
  2198. cache[k] = _fnGetCellData( settings, k, i, 'type' );
  2199. }
  2200. detectedType = types[j]( cache[k], settings );
  2201. // If null, then this type can't apply to this column, so
  2202. // rather than testing all cells, break out. There is an
  2203. // exception for the last type which is `html`. We need to
  2204. // scan all rows since it is possible to mix string and HTML
  2205. // types
  2206. if ( ! detectedType && j !== types.length-1 ) {
  2207. break;
  2208. }
  2209. // Only a single match is needed for html type since it is
  2210. // bottom of the pile and very similar to string - but it
  2211. // must not be empty
  2212. if ( detectedType === 'html' && ! _empty(cache[k]) ) {
  2213. break;
  2214. }
  2215. }
  2216. // Type is valid for all data points in the column - use this
  2217. // type
  2218. if ( detectedType ) {
  2219. col.sType = detectedType;
  2220. break;
  2221. }
  2222. }
  2223. // Fall back - if no type was detected, always use string
  2224. if ( ! col.sType ) {
  2225. col.sType = 'string';
  2226. }
  2227. }
  2228. }
  2229. }
  2230. /**
  2231. * Take the column definitions and static columns arrays and calculate how
  2232. * they relate to column indexes. The callback function will then apply the
  2233. * definition found for a column to a suitable configuration object.
  2234. * @param {object} oSettings dataTables settings object
  2235. * @param {array} aoColDefs The aoColumnDefs array that is to be applied
  2236. * @param {array} aoCols The aoColumns array that defines columns individually
  2237. * @param {function} fn Callback function - takes two parameters, the calculated
  2238. * column index and the definition for that column.
  2239. * @memberof DataTable#oApi
  2240. */
  2241. function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
  2242. {
  2243. var i, iLen, j, jLen, k, kLen, def;
  2244. var columns = oSettings.aoColumns;
  2245. // Column definitions with aTargets
  2246. if ( aoColDefs )
  2247. {
  2248. /* Loop over the definitions array - loop in reverse so first instance has priority */
  2249. for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
  2250. {
  2251. def = aoColDefs[i];
  2252. /* Each definition can target multiple columns, as it is an array */
  2253. var aTargets = def.target !== undefined
  2254. ? def.target
  2255. : def.targets !== undefined
  2256. ? def.targets
  2257. : def.aTargets;
  2258. if ( ! Array.isArray( aTargets ) )
  2259. {
  2260. aTargets = [ aTargets ];
  2261. }
  2262. for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
  2263. {
  2264. if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
  2265. {
  2266. /* Add columns that we don't yet know about */
  2267. while( columns.length <= aTargets[j] )
  2268. {
  2269. _fnAddColumn( oSettings );
  2270. }
  2271. /* Integer, basic index */
  2272. fn( aTargets[j], def );
  2273. }
  2274. else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
  2275. {
  2276. /* Negative integer, right to left column counting */
  2277. fn( columns.length+aTargets[j], def );
  2278. }
  2279. else if ( typeof aTargets[j] === 'string' )
  2280. {
  2281. /* Class name matching on TH element */
  2282. for ( k=0, kLen=columns.length ; k<kLen ; k++ )
  2283. {
  2284. if ( aTargets[j] == "_all" ||
  2285. $(columns[k].nTh).hasClass( aTargets[j] ) )
  2286. {
  2287. fn( k, def );
  2288. }
  2289. }
  2290. }
  2291. }
  2292. }
  2293. }
  2294. // Statically defined columns array
  2295. if ( aoCols )
  2296. {
  2297. for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
  2298. {
  2299. fn( i, aoCols[i] );
  2300. }
  2301. }
  2302. }
  2303. /**
  2304. * Add a data array to the table, creating DOM node etc. This is the parallel to
  2305. * _fnGatherData, but for adding rows from a Javascript source, rather than a
  2306. * DOM source.
  2307. * @param {object} oSettings dataTables settings object
  2308. * @param {array} aData data array to be added
  2309. * @param {node} [nTr] TR element to add to the table - optional. If not given,
  2310. * DataTables will create a row automatically
  2311. * @param {array} [anTds] Array of TD|TH elements for the row - must be given
  2312. * if nTr is.
  2313. * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
  2314. * @memberof DataTable#oApi
  2315. */
  2316. function _fnAddData ( oSettings, aDataIn, nTr, anTds )
  2317. {
  2318. /* Create the object for storing information about this new row */
  2319. var iRow = oSettings.aoData.length;
  2320. var oData = $.extend( true, {}, DataTable.models.oRow, {
  2321. src: nTr ? 'dom' : 'data',
  2322. idx: iRow
  2323. } );
  2324. oData._aData = aDataIn;
  2325. oSettings.aoData.push( oData );
  2326. /* Create the cells */
  2327. var nTd, sThisType;
  2328. var columns = oSettings.aoColumns;
  2329. // Invalidate the column types as the new data needs to be revalidated
  2330. for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
  2331. {
  2332. columns[i].sType = null;
  2333. }
  2334. /* Add to the display array */
  2335. oSettings.aiDisplayMaster.push( iRow );
  2336. var id = oSettings.rowIdFn( aDataIn );
  2337. if ( id !== undefined ) {
  2338. oSettings.aIds[ id ] = oData;
  2339. }
  2340. /* Create the DOM information, or register it if already present */
  2341. if ( nTr || ! oSettings.oFeatures.bDeferRender )
  2342. {
  2343. _fnCreateTr( oSettings, iRow, nTr, anTds );
  2344. }
  2345. return iRow;
  2346. }
  2347. /**
  2348. * Add one or more TR elements to the table. Generally we'd expect to
  2349. * use this for reading data from a DOM sourced table, but it could be
  2350. * used for an TR element. Note that if a TR is given, it is used (i.e.
  2351. * it is not cloned).
  2352. * @param {object} settings dataTables settings object
  2353. * @param {array|node|jQuery} trs The TR element(s) to add to the table
  2354. * @returns {array} Array of indexes for the added rows
  2355. * @memberof DataTable#oApi
  2356. */
  2357. function _fnAddTr( settings, trs )
  2358. {
  2359. var row;
  2360. // Allow an individual node to be passed in
  2361. if ( ! (trs instanceof $) ) {
  2362. trs = $(trs);
  2363. }
  2364. return trs.map( function (i, el) {
  2365. row = _fnGetRowElements( settings, el );
  2366. return _fnAddData( settings, row.data, el, row.cells );
  2367. } );
  2368. }
  2369. /**
  2370. * Take a TR element and convert it to an index in aoData
  2371. * @param {object} oSettings dataTables settings object
  2372. * @param {node} n the TR element to find
  2373. * @returns {int} index if the node is found, null if not
  2374. * @memberof DataTable#oApi
  2375. */
  2376. function _fnNodeToDataIndex( oSettings, n )
  2377. {
  2378. return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
  2379. }
  2380. /**
  2381. * Take a TD element and convert it into a column data index (not the visible index)
  2382. * @param {object} oSettings dataTables settings object
  2383. * @param {int} iRow The row number the TD/TH can be found in
  2384. * @param {node} n The TD/TH element to find
  2385. * @returns {int} index if the node is found, -1 if not
  2386. * @memberof DataTable#oApi
  2387. */
  2388. function _fnNodeToColumnIndex( oSettings, iRow, n )
  2389. {
  2390. return $.inArray( n, oSettings.aoData[ iRow ].anCells );
  2391. }
  2392. /**
  2393. * Get the data for a given cell from the internal cache, taking into account data mapping
  2394. * @param {object} settings dataTables settings object
  2395. * @param {int} rowIdx aoData row id
  2396. * @param {int} colIdx Column index
  2397. * @param {string} type data get type ('display', 'type' 'filter|search' 'sort|order')
  2398. * @returns {*} Cell data
  2399. * @memberof DataTable#oApi
  2400. */
  2401. function _fnGetCellData( settings, rowIdx, colIdx, type )
  2402. {
  2403. if (type === 'search') {
  2404. type = 'filter';
  2405. }
  2406. else if (type === 'order') {
  2407. type = 'sort';
  2408. }
  2409. var draw = settings.iDraw;
  2410. var col = settings.aoColumns[colIdx];
  2411. var rowData = settings.aoData[rowIdx]._aData;
  2412. var defaultContent = col.sDefaultContent;
  2413. var cellData = col.fnGetData( rowData, type, {
  2414. settings: settings,
  2415. row: rowIdx,
  2416. col: colIdx
  2417. } );
  2418. if ( cellData === undefined ) {
  2419. if ( settings.iDrawError != draw && defaultContent === null ) {
  2420. _fnLog( settings, 0, "Requested unknown parameter "+
  2421. (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
  2422. " for row "+rowIdx+", column "+colIdx, 4 );
  2423. settings.iDrawError = draw;
  2424. }
  2425. return defaultContent;
  2426. }
  2427. // When the data source is null and a specific data type is requested (i.e.
  2428. // not the original data), we can use default column data
  2429. if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
  2430. cellData = defaultContent;
  2431. }
  2432. else if ( typeof cellData === 'function' ) {
  2433. // If the data source is a function, then we run it and use the return,
  2434. // executing in the scope of the data object (for instances)
  2435. return cellData.call( rowData );
  2436. }
  2437. if ( cellData === null && type === 'display' ) {
  2438. return '';
  2439. }
  2440. if ( type === 'filter' ) {
  2441. var fomatters = DataTable.ext.type.search;
  2442. if ( fomatters[ col.sType ] ) {
  2443. cellData = fomatters[ col.sType ]( cellData );
  2444. }
  2445. }
  2446. return cellData;
  2447. }
  2448. /**
  2449. * Set the value for a specific cell, into the internal data cache
  2450. * @param {object} settings dataTables settings object
  2451. * @param {int} rowIdx aoData row id
  2452. * @param {int} colIdx Column index
  2453. * @param {*} val Value to set
  2454. * @memberof DataTable#oApi
  2455. */
  2456. function _fnSetCellData( settings, rowIdx, colIdx, val )
  2457. {
  2458. var col = settings.aoColumns[colIdx];
  2459. var rowData = settings.aoData[rowIdx]._aData;
  2460. col.fnSetData( rowData, val, {
  2461. settings: settings,
  2462. row: rowIdx,
  2463. col: colIdx
  2464. } );
  2465. }
  2466. // Private variable that is used to match action syntax in the data property object
  2467. var __reArray = /\[.*?\]$/;
  2468. var __reFn = /\(\)$/;
  2469. /**
  2470. * Split string on periods, taking into account escaped periods
  2471. * @param {string} str String to split
  2472. * @return {array} Split string
  2473. */
  2474. function _fnSplitObjNotation( str )
  2475. {
  2476. return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
  2477. return s.replace(/\\\./g, '.');
  2478. } );
  2479. }
  2480. /**
  2481. * Return a function that can be used to get data from a source object, taking
  2482. * into account the ability to use nested objects as a source
  2483. * @param {string|int|function} mSource The data source for the object
  2484. * @returns {function} Data get function
  2485. * @memberof DataTable#oApi
  2486. */
  2487. var _fnGetObjectDataFn = DataTable.util.get;
  2488. /**
  2489. * Return a function that can be used to set data from a source object, taking
  2490. * into account the ability to use nested objects as a source
  2491. * @param {string|int|function} mSource The data source for the object
  2492. * @returns {function} Data set function
  2493. * @memberof DataTable#oApi
  2494. */
  2495. var _fnSetObjectDataFn = DataTable.util.set;
  2496. /**
  2497. * Return an array with the full table data
  2498. * @param {object} oSettings dataTables settings object
  2499. * @returns array {array} aData Master data array
  2500. * @memberof DataTable#oApi
  2501. */
  2502. function _fnGetDataMaster ( settings )
  2503. {
  2504. return _pluck( settings.aoData, '_aData' );
  2505. }
  2506. /**
  2507. * Nuke the table
  2508. * @param {object} oSettings dataTables settings object
  2509. * @memberof DataTable#oApi
  2510. */
  2511. function _fnClearTable( settings )
  2512. {
  2513. settings.aoData.length = 0;
  2514. settings.aiDisplayMaster.length = 0;
  2515. settings.aiDisplay.length = 0;
  2516. settings.aIds = {};
  2517. }
  2518. /**
  2519. * Take an array of integers (index array) and remove a target integer (value - not
  2520. * the key!)
  2521. * @param {array} a Index array to target
  2522. * @param {int} iTarget value to find
  2523. * @memberof DataTable#oApi
  2524. */
  2525. function _fnDeleteIndex( a, iTarget, splice )
  2526. {
  2527. var iTargetIndex = -1;
  2528. for ( var i=0, iLen=a.length ; i<iLen ; i++ )
  2529. {
  2530. if ( a[i] == iTarget )
  2531. {
  2532. iTargetIndex = i;
  2533. }
  2534. else if ( a[i] > iTarget )
  2535. {
  2536. a[i]--;
  2537. }
  2538. }
  2539. if ( iTargetIndex != -1 && splice === undefined )
  2540. {
  2541. a.splice( iTargetIndex, 1 );
  2542. }
  2543. }
  2544. /**
  2545. * Mark cached data as invalid such that a re-read of the data will occur when
  2546. * the cached data is next requested. Also update from the data source object.
  2547. *
  2548. * @param {object} settings DataTables settings object
  2549. * @param {int} rowIdx Row index to invalidate
  2550. * @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom'
  2551. * or 'data'
  2552. * @param {int} [colIdx] Column index to invalidate. If undefined the whole
  2553. * row will be invalidated
  2554. * @memberof DataTable#oApi
  2555. *
  2556. * @todo For the modularisation of v1.11 this will need to become a callback, so
  2557. * the sort and filter methods can subscribe to it. That will required
  2558. * initialisation options for sorting, which is why it is not already baked in
  2559. */
  2560. function _fnInvalidate( settings, rowIdx, src, colIdx )
  2561. {
  2562. var row = settings.aoData[ rowIdx ];
  2563. var i, ien;
  2564. var cellWrite = function ( cell, col ) {
  2565. // This is very frustrating, but in IE if you just write directly
  2566. // to innerHTML, and elements that are overwritten are GC'ed,
  2567. // even if there is a reference to them elsewhere
  2568. while ( cell.childNodes.length ) {
  2569. cell.removeChild( cell.firstChild );
  2570. }
  2571. cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
  2572. };
  2573. // Are we reading last data from DOM or the data object?
  2574. if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
  2575. // Read the data from the DOM
  2576. row._aData = _fnGetRowElements(
  2577. settings, row, colIdx, colIdx === undefined ? undefined : row._aData
  2578. )
  2579. .data;
  2580. }
  2581. else {
  2582. // Reading from data object, update the DOM
  2583. var cells = row.anCells;
  2584. if ( cells ) {
  2585. if ( colIdx !== undefined ) {
  2586. cellWrite( cells[colIdx], colIdx );
  2587. }
  2588. else {
  2589. for ( i=0, ien=cells.length ; i<ien ; i++ ) {
  2590. cellWrite( cells[i], i );
  2591. }
  2592. }
  2593. }
  2594. }
  2595. // For both row and cell invalidation, the cached data for sorting and
  2596. // filtering is nulled out
  2597. row._aSortData = null;
  2598. row._aFilterData = null;
  2599. // Invalidate the type for a specific column (if given) or all columns since
  2600. // the data might have changed
  2601. var cols = settings.aoColumns;
  2602. if ( colIdx !== undefined ) {
  2603. cols[ colIdx ].sType = null;
  2604. }
  2605. else {
  2606. for ( i=0, ien=cols.length ; i<ien ; i++ ) {
  2607. cols[i].sType = null;
  2608. }
  2609. // Update DataTables special `DT_*` attributes for the row
  2610. _fnRowAttributes( settings, row );
  2611. }
  2612. }
  2613. /**
  2614. * Build a data source object from an HTML row, reading the contents of the
  2615. * cells that are in the row.
  2616. *
  2617. * @param {object} settings DataTables settings object
  2618. * @param {node|object} TR element from which to read data or existing row
  2619. * object from which to re-read the data from the cells
  2620. * @param {int} [colIdx] Optional column index
  2621. * @param {array|object} [d] Data source object. If `colIdx` is given then this
  2622. * parameter should also be given and will be used to write the data into.
  2623. * Only the column in question will be written
  2624. * @returns {object} Object with two parameters: `data` the data read, in
  2625. * document order, and `cells` and array of nodes (they can be useful to the
  2626. * caller, so rather than needing a second traversal to get them, just return
  2627. * them from here).
  2628. * @memberof DataTable#oApi
  2629. */
  2630. function _fnGetRowElements( settings, row, colIdx, d )
  2631. {
  2632. var
  2633. tds = [],
  2634. td = row.firstChild,
  2635. name, col, o, i=0, contents,
  2636. columns = settings.aoColumns,
  2637. objectRead = settings._rowReadObject;
  2638. // Allow the data object to be passed in, or construct
  2639. d = d !== undefined ?
  2640. d :
  2641. objectRead ?
  2642. {} :
  2643. [];
  2644. var attr = function ( str, td ) {
  2645. if ( typeof str === 'string' ) {
  2646. var idx = str.indexOf('@');
  2647. if ( idx !== -1 ) {
  2648. var attr = str.substring( idx+1 );
  2649. var setter = _fnSetObjectDataFn( str );
  2650. setter( d, td.getAttribute( attr ) );
  2651. }
  2652. }
  2653. };
  2654. // Read data from a cell and store into the data object
  2655. var cellProcess = function ( cell ) {
  2656. if ( colIdx === undefined || colIdx === i ) {
  2657. col = columns[i];
  2658. contents = (cell.innerHTML).trim();
  2659. if ( col && col._bAttrSrc ) {
  2660. var setter = _fnSetObjectDataFn( col.mData._ );
  2661. setter( d, contents );
  2662. attr( col.mData.sort, cell );
  2663. attr( col.mData.type, cell );
  2664. attr( col.mData.filter, cell );
  2665. }
  2666. else {
  2667. // Depending on the `data` option for the columns the data can
  2668. // be read to either an object or an array.
  2669. if ( objectRead ) {
  2670. if ( ! col._setter ) {
  2671. // Cache the setter function
  2672. col._setter = _fnSetObjectDataFn( col.mData );
  2673. }
  2674. col._setter( d, contents );
  2675. }
  2676. else {
  2677. d[i] = contents;
  2678. }
  2679. }
  2680. }
  2681. i++;
  2682. };
  2683. if ( td ) {
  2684. // `tr` element was passed in
  2685. while ( td ) {
  2686. name = td.nodeName.toUpperCase();
  2687. if ( name == "TD" || name == "TH" ) {
  2688. cellProcess( td );
  2689. tds.push( td );
  2690. }
  2691. td = td.nextSibling;
  2692. }
  2693. }
  2694. else {
  2695. // Existing row object passed in
  2696. tds = row.anCells;
  2697. for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
  2698. cellProcess( tds[j] );
  2699. }
  2700. }
  2701. // Read the ID from the DOM if present
  2702. var rowNode = row.firstChild ? row : row.nTr;
  2703. if ( rowNode ) {
  2704. var id = rowNode.getAttribute( 'id' );
  2705. if ( id ) {
  2706. _fnSetObjectDataFn( settings.rowId )( d, id );
  2707. }
  2708. }
  2709. return {
  2710. data: d,
  2711. cells: tds
  2712. };
  2713. }
  2714. /**
  2715. * Create a new TR element (and it's TD children) for a row
  2716. * @param {object} oSettings dataTables settings object
  2717. * @param {int} iRow Row to consider
  2718. * @param {node} [nTrIn] TR element to add to the table - optional. If not given,
  2719. * DataTables will create a row automatically
  2720. * @param {array} [anTds] Array of TD|TH elements for the row - must be given
  2721. * if nTr is.
  2722. * @memberof DataTable#oApi
  2723. */
  2724. function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
  2725. {
  2726. var
  2727. row = oSettings.aoData[iRow],
  2728. rowData = row._aData,
  2729. cells = [],
  2730. nTr, nTd, oCol,
  2731. i, iLen, create;
  2732. if ( row.nTr === null )
  2733. {
  2734. nTr = nTrIn || document.createElement('tr');
  2735. row.nTr = nTr;
  2736. row.anCells = cells;
  2737. /* Use a private property on the node to allow reserve mapping from the node
  2738. * to the aoData array for fast look up
  2739. */
  2740. nTr._DT_RowIndex = iRow;
  2741. /* Special parameters can be given by the data source to be used on the row */
  2742. _fnRowAttributes( oSettings, row );
  2743. /* Process each column */
  2744. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  2745. {
  2746. oCol = oSettings.aoColumns[i];
  2747. create = nTrIn ? false : true;
  2748. nTd = create ? document.createElement( oCol.sCellType ) : anTds[i];
  2749. if (! nTd) {
  2750. _fnLog( oSettings, 0, 'Incorrect column count', 18 );
  2751. }
  2752. nTd._DT_CellIndex = {
  2753. row: iRow,
  2754. column: i
  2755. };
  2756. cells.push( nTd );
  2757. // Need to create the HTML if new, or if a rendering function is defined
  2758. if ( create || ((oCol.mRender || oCol.mData !== i) &&
  2759. (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
  2760. )) {
  2761. nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
  2762. }
  2763. /* Add user defined class */
  2764. if ( oCol.sClass )
  2765. {
  2766. nTd.className += ' '+oCol.sClass;
  2767. }
  2768. // Visibility - add or remove as required
  2769. if ( oCol.bVisible && ! nTrIn )
  2770. {
  2771. nTr.appendChild( nTd );
  2772. }
  2773. else if ( ! oCol.bVisible && nTrIn )
  2774. {
  2775. nTd.parentNode.removeChild( nTd );
  2776. }
  2777. if ( oCol.fnCreatedCell )
  2778. {
  2779. oCol.fnCreatedCell.call( oSettings.oInstance,
  2780. nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
  2781. );
  2782. }
  2783. }
  2784. _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
  2785. }
  2786. }
  2787. /**
  2788. * Add attributes to a row based on the special `DT_*` parameters in a data
  2789. * source object.
  2790. * @param {object} settings DataTables settings object
  2791. * @param {object} DataTables row object for the row to be modified
  2792. * @memberof DataTable#oApi
  2793. */
  2794. function _fnRowAttributes( settings, row )
  2795. {
  2796. var tr = row.nTr;
  2797. var data = row._aData;
  2798. if ( tr ) {
  2799. var id = settings.rowIdFn( data );
  2800. if ( id ) {
  2801. tr.id = id;
  2802. }
  2803. if ( data.DT_RowClass ) {
  2804. // Remove any classes added by DT_RowClass before
  2805. var a = data.DT_RowClass.split(' ');
  2806. row.__rowc = row.__rowc ?
  2807. _unique( row.__rowc.concat( a ) ) :
  2808. a;
  2809. $(tr)
  2810. .removeClass( row.__rowc.join(' ') )
  2811. .addClass( data.DT_RowClass );
  2812. }
  2813. if ( data.DT_RowAttr ) {
  2814. $(tr).attr( data.DT_RowAttr );
  2815. }
  2816. if ( data.DT_RowData ) {
  2817. $(tr).data( data.DT_RowData );
  2818. }
  2819. }
  2820. }
  2821. /**
  2822. * Create the HTML header for the table
  2823. * @param {object} oSettings dataTables settings object
  2824. * @memberof DataTable#oApi
  2825. */
  2826. function _fnBuildHead( oSettings )
  2827. {
  2828. var i, ien, cell, row, column;
  2829. var thead = oSettings.nTHead;
  2830. var tfoot = oSettings.nTFoot;
  2831. var createHeader = $('th, td', thead).length === 0;
  2832. var classes = oSettings.oClasses;
  2833. var columns = oSettings.aoColumns;
  2834. if ( createHeader ) {
  2835. row = $('<tr/>').appendTo( thead );
  2836. }
  2837. for ( i=0, ien=columns.length ; i<ien ; i++ ) {
  2838. column = columns[i];
  2839. cell = $( column.nTh ).addClass( column.sClass );
  2840. if ( createHeader ) {
  2841. cell.appendTo( row );
  2842. }
  2843. // 1.11 move into sorting
  2844. if ( oSettings.oFeatures.bSort ) {
  2845. cell.addClass( column.sSortingClass );
  2846. if ( column.bSortable !== false ) {
  2847. cell
  2848. .attr( 'tabindex', oSettings.iTabIndex )
  2849. .attr( 'aria-controls', oSettings.sTableId );
  2850. _fnSortAttachListener( oSettings, column.nTh, i );
  2851. }
  2852. }
  2853. if ( column.sTitle != cell[0].innerHTML ) {
  2854. cell.html( column.sTitle );
  2855. }
  2856. _fnRenderer( oSettings, 'header' )(
  2857. oSettings, cell, column, classes
  2858. );
  2859. }
  2860. if ( createHeader ) {
  2861. _fnDetectHeader( oSettings.aoHeader, thead );
  2862. }
  2863. /* Deal with the footer - add classes if required */
  2864. $(thead).children('tr').children('th, td').addClass( classes.sHeaderTH );
  2865. $(tfoot).children('tr').children('th, td').addClass( classes.sFooterTH );
  2866. // Cache the footer cells. Note that we only take the cells from the first
  2867. // row in the footer. If there is more than one row the user wants to
  2868. // interact with, they need to use the table().foot() method. Note also this
  2869. // allows cells to be used for multiple columns using colspan
  2870. if ( tfoot !== null ) {
  2871. var cells = oSettings.aoFooter[0];
  2872. for ( i=0, ien=cells.length ; i<ien ; i++ ) {
  2873. column = columns[i];
  2874. if (column) {
  2875. column.nTf = cells[i].cell;
  2876. if ( column.sClass ) {
  2877. $(column.nTf).addClass( column.sClass );
  2878. }
  2879. }
  2880. else {
  2881. _fnLog( oSettings, 0, 'Incorrect column count', 18 );
  2882. }
  2883. }
  2884. }
  2885. }
  2886. /**
  2887. * Draw the header (or footer) element based on the column visibility states. The
  2888. * methodology here is to use the layout array from _fnDetectHeader, modified for
  2889. * the instantaneous column visibility, to construct the new layout. The grid is
  2890. * traversed over cell at a time in a rows x columns grid fashion, although each
  2891. * cell insert can cover multiple elements in the grid - which is tracks using the
  2892. * aApplied array. Cell inserts in the grid will only occur where there isn't
  2893. * already a cell in that position.
  2894. * @param {object} oSettings dataTables settings object
  2895. * @param array {objects} aoSource Layout array from _fnDetectHeader
  2896. * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
  2897. * @memberof DataTable#oApi
  2898. */
  2899. function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
  2900. {
  2901. var i, iLen, j, jLen, k, kLen, n, nLocalTr;
  2902. var aoLocal = [];
  2903. var aApplied = [];
  2904. var iColumns = oSettings.aoColumns.length;
  2905. var iRowspan, iColspan;
  2906. if ( ! aoSource )
  2907. {
  2908. return;
  2909. }
  2910. if ( bIncludeHidden === undefined )
  2911. {
  2912. bIncludeHidden = false;
  2913. }
  2914. /* Make a copy of the master layout array, but without the visible columns in it */
  2915. for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
  2916. {
  2917. aoLocal[i] = aoSource[i].slice();
  2918. aoLocal[i].nTr = aoSource[i].nTr;
  2919. /* Remove any columns which are currently hidden */
  2920. for ( j=iColumns-1 ; j>=0 ; j-- )
  2921. {
  2922. if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
  2923. {
  2924. aoLocal[i].splice( j, 1 );
  2925. }
  2926. }
  2927. /* Prep the applied array - it needs an element for each row */
  2928. aApplied.push( [] );
  2929. }
  2930. for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
  2931. {
  2932. nLocalTr = aoLocal[i].nTr;
  2933. /* All cells are going to be replaced, so empty out the row */
  2934. if ( nLocalTr )
  2935. {
  2936. while( (n = nLocalTr.firstChild) )
  2937. {
  2938. nLocalTr.removeChild( n );
  2939. }
  2940. }
  2941. for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
  2942. {
  2943. iRowspan = 1;
  2944. iColspan = 1;
  2945. /* Check to see if there is already a cell (row/colspan) covering our target
  2946. * insert point. If there is, then there is nothing to do.
  2947. */
  2948. if ( aApplied[i][j] === undefined )
  2949. {
  2950. nLocalTr.appendChild( aoLocal[i][j].cell );
  2951. aApplied[i][j] = 1;
  2952. /* Expand the cell to cover as many rows as needed */
  2953. while ( aoLocal[i+iRowspan] !== undefined &&
  2954. aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
  2955. {
  2956. aApplied[i+iRowspan][j] = 1;
  2957. iRowspan++;
  2958. }
  2959. /* Expand the cell to cover as many columns as needed */
  2960. while ( aoLocal[i][j+iColspan] !== undefined &&
  2961. aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
  2962. {
  2963. /* Must update the applied array over the rows for the columns */
  2964. for ( k=0 ; k<iRowspan ; k++ )
  2965. {
  2966. aApplied[i+k][j+iColspan] = 1;
  2967. }
  2968. iColspan++;
  2969. }
  2970. /* Do the actual expansion in the DOM */
  2971. $(aoLocal[i][j].cell)
  2972. .attr('rowspan', iRowspan)
  2973. .attr('colspan', iColspan);
  2974. }
  2975. }
  2976. }
  2977. }
  2978. /**
  2979. * Insert the required TR nodes into the table for display
  2980. * @param {object} oSettings dataTables settings object
  2981. * @param ajaxComplete true after ajax call to complete rendering
  2982. * @memberof DataTable#oApi
  2983. */
  2984. function _fnDraw( oSettings, ajaxComplete )
  2985. {
  2986. // Allow for state saving and a custom start position
  2987. _fnStart( oSettings );
  2988. /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
  2989. var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
  2990. if ( $.inArray( false, aPreDraw ) !== -1 )
  2991. {
  2992. _fnProcessingDisplay( oSettings, false );
  2993. return;
  2994. }
  2995. var anRows = [];
  2996. var iRowCount = 0;
  2997. var asStripeClasses = oSettings.asStripeClasses;
  2998. var iStripes = asStripeClasses.length;
  2999. var oLang = oSettings.oLanguage;
  3000. var bServerSide = _fnDataSource( oSettings ) == 'ssp';
  3001. var aiDisplay = oSettings.aiDisplay;
  3002. var iDisplayStart = oSettings._iDisplayStart;
  3003. var iDisplayEnd = oSettings.fnDisplayEnd();
  3004. oSettings.bDrawing = true;
  3005. /* Server-side processing draw intercept */
  3006. if ( oSettings.bDeferLoading )
  3007. {
  3008. oSettings.bDeferLoading = false;
  3009. oSettings.iDraw++;
  3010. _fnProcessingDisplay( oSettings, false );
  3011. }
  3012. else if ( !bServerSide )
  3013. {
  3014. oSettings.iDraw++;
  3015. }
  3016. else if ( !oSettings.bDestroying && !ajaxComplete)
  3017. {
  3018. _fnAjaxUpdate( oSettings );
  3019. return;
  3020. }
  3021. if ( aiDisplay.length !== 0 )
  3022. {
  3023. var iStart = bServerSide ? 0 : iDisplayStart;
  3024. var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
  3025. for ( var j=iStart ; j<iEnd ; j++ )
  3026. {
  3027. var iDataIndex = aiDisplay[j];
  3028. var aoData = oSettings.aoData[ iDataIndex ];
  3029. if ( aoData.nTr === null )
  3030. {
  3031. _fnCreateTr( oSettings, iDataIndex );
  3032. }
  3033. var nRow = aoData.nTr;
  3034. /* Remove the old striping classes and then add the new one */
  3035. if ( iStripes !== 0 )
  3036. {
  3037. var sStripe = asStripeClasses[ iRowCount % iStripes ];
  3038. if ( aoData._sRowStripe != sStripe )
  3039. {
  3040. $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
  3041. aoData._sRowStripe = sStripe;
  3042. }
  3043. }
  3044. // Row callback functions - might want to manipulate the row
  3045. // iRowCount and j are not currently documented. Are they at all
  3046. // useful?
  3047. _fnCallbackFire( oSettings, 'aoRowCallback', null,
  3048. [nRow, aoData._aData, iRowCount, j, iDataIndex] );
  3049. anRows.push( nRow );
  3050. iRowCount++;
  3051. }
  3052. }
  3053. else
  3054. {
  3055. /* Table is empty - create a row with an empty message in it */
  3056. var sZero = oLang.sZeroRecords;
  3057. if ( oSettings.iDraw == 1 && _fnDataSource( oSettings ) == 'ajax' )
  3058. {
  3059. sZero = oLang.sLoadingRecords;
  3060. }
  3061. else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
  3062. {
  3063. sZero = oLang.sEmptyTable;
  3064. }
  3065. anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
  3066. .append( $('<td />', {
  3067. 'valign': 'top',
  3068. 'colSpan': _fnVisbleColumns( oSettings ),
  3069. 'class': oSettings.oClasses.sRowEmpty
  3070. } ).html( sZero ) )[0];
  3071. }
  3072. /* Header and footer callbacks */
  3073. _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
  3074. _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
  3075. _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
  3076. _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
  3077. var body = $(oSettings.nTBody);
  3078. body.children().detach();
  3079. body.append( $(anRows) );
  3080. /* Call all required callback functions for the end of a draw */
  3081. _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
  3082. /* Draw is complete, sorting and filtering must be as well */
  3083. oSettings.bSorted = false;
  3084. oSettings.bFiltered = false;
  3085. oSettings.bDrawing = false;
  3086. }
  3087. /**
  3088. * Redraw the table - taking account of the various features which are enabled
  3089. * @param {object} oSettings dataTables settings object
  3090. * @param {boolean} [holdPosition] Keep the current paging position. By default
  3091. * the paging is reset to the first page
  3092. * @memberof DataTable#oApi
  3093. */
  3094. function _fnReDraw( settings, holdPosition )
  3095. {
  3096. var
  3097. features = settings.oFeatures,
  3098. sort = features.bSort,
  3099. filter = features.bFilter;
  3100. if ( sort ) {
  3101. _fnSort( settings );
  3102. }
  3103. if ( filter ) {
  3104. _fnFilterComplete( settings, settings.oPreviousSearch );
  3105. }
  3106. else {
  3107. // No filtering, so we want to just use the display master
  3108. settings.aiDisplay = settings.aiDisplayMaster.slice();
  3109. }
  3110. if ( holdPosition !== true ) {
  3111. settings._iDisplayStart = 0;
  3112. }
  3113. // Let any modules know about the draw hold position state (used by
  3114. // scrolling internally)
  3115. settings._drawHold = holdPosition;
  3116. _fnDraw( settings );
  3117. settings._drawHold = false;
  3118. }
  3119. /**
  3120. * Add the options to the page HTML for the table
  3121. * @param {object} oSettings dataTables settings object
  3122. * @memberof DataTable#oApi
  3123. */
  3124. function _fnAddOptionsHtml ( oSettings )
  3125. {
  3126. var classes = oSettings.oClasses;
  3127. var table = $(oSettings.nTable);
  3128. var holding = $('<div/>').insertBefore( table ); // Holding element for speed
  3129. var features = oSettings.oFeatures;
  3130. // All DataTables are wrapped in a div
  3131. var insert = $('<div/>', {
  3132. id: oSettings.sTableId+'_wrapper',
  3133. 'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
  3134. } );
  3135. oSettings.nHolding = holding[0];
  3136. oSettings.nTableWrapper = insert[0];
  3137. oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
  3138. /* Loop over the user set positioning and place the elements as needed */
  3139. var aDom = oSettings.sDom.split('');
  3140. var featureNode, cOption, nNewNode, cNext, sAttr, j;
  3141. for ( var i=0 ; i<aDom.length ; i++ )
  3142. {
  3143. featureNode = null;
  3144. cOption = aDom[i];
  3145. if ( cOption == '<' )
  3146. {
  3147. /* New container div */
  3148. nNewNode = $('<div/>')[0];
  3149. /* Check to see if we should append an id and/or a class name to the container */
  3150. cNext = aDom[i+1];
  3151. if ( cNext == "'" || cNext == '"' )
  3152. {
  3153. sAttr = "";
  3154. j = 2;
  3155. while ( aDom[i+j] != cNext )
  3156. {
  3157. sAttr += aDom[i+j];
  3158. j++;
  3159. }
  3160. /* Replace jQuery UI constants @todo depreciated */
  3161. if ( sAttr == "H" )
  3162. {
  3163. sAttr = classes.sJUIHeader;
  3164. }
  3165. else if ( sAttr == "F" )
  3166. {
  3167. sAttr = classes.sJUIFooter;
  3168. }
  3169. /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
  3170. * breaks the string into parts and applies them as needed
  3171. */
  3172. if ( sAttr.indexOf('.') != -1 )
  3173. {
  3174. var aSplit = sAttr.split('.');
  3175. nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
  3176. nNewNode.className = aSplit[1];
  3177. }
  3178. else if ( sAttr.charAt(0) == "#" )
  3179. {
  3180. nNewNode.id = sAttr.substr(1, sAttr.length-1);
  3181. }
  3182. else
  3183. {
  3184. nNewNode.className = sAttr;
  3185. }
  3186. i += j; /* Move along the position array */
  3187. }
  3188. insert.append( nNewNode );
  3189. insert = $(nNewNode);
  3190. }
  3191. else if ( cOption == '>' )
  3192. {
  3193. /* End container div */
  3194. insert = insert.parent();
  3195. }
  3196. // @todo Move options into their own plugins?
  3197. else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
  3198. {
  3199. /* Length */
  3200. featureNode = _fnFeatureHtmlLength( oSettings );
  3201. }
  3202. else if ( cOption == 'f' && features.bFilter )
  3203. {
  3204. /* Filter */
  3205. featureNode = _fnFeatureHtmlFilter( oSettings );
  3206. }
  3207. else if ( cOption == 'r' && features.bProcessing )
  3208. {
  3209. /* pRocessing */
  3210. featureNode = _fnFeatureHtmlProcessing( oSettings );
  3211. }
  3212. else if ( cOption == 't' )
  3213. {
  3214. /* Table */
  3215. featureNode = _fnFeatureHtmlTable( oSettings );
  3216. }
  3217. else if ( cOption == 'i' && features.bInfo )
  3218. {
  3219. /* Info */
  3220. featureNode = _fnFeatureHtmlInfo( oSettings );
  3221. }
  3222. else if ( cOption == 'p' && features.bPaginate )
  3223. {
  3224. /* Pagination */
  3225. featureNode = _fnFeatureHtmlPaginate( oSettings );
  3226. }
  3227. else if ( DataTable.ext.feature.length !== 0 )
  3228. {
  3229. /* Plug-in features */
  3230. var aoFeatures = DataTable.ext.feature;
  3231. for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
  3232. {
  3233. if ( cOption == aoFeatures[k].cFeature )
  3234. {
  3235. featureNode = aoFeatures[k].fnInit( oSettings );
  3236. break;
  3237. }
  3238. }
  3239. }
  3240. /* Add to the 2D features array */
  3241. if ( featureNode )
  3242. {
  3243. var aanFeatures = oSettings.aanFeatures;
  3244. if ( ! aanFeatures[cOption] )
  3245. {
  3246. aanFeatures[cOption] = [];
  3247. }
  3248. aanFeatures[cOption].push( featureNode );
  3249. insert.append( featureNode );
  3250. }
  3251. }
  3252. /* Built our DOM structure - replace the holding div with what we want */
  3253. holding.replaceWith( insert );
  3254. oSettings.nHolding = null;
  3255. }
  3256. /**
  3257. * Use the DOM source to create up an array of header cells. The idea here is to
  3258. * create a layout grid (array) of rows x columns, which contains a reference
  3259. * to the cell that that point in the grid (regardless of col/rowspan), such that
  3260. * any column / row could be removed and the new grid constructed
  3261. * @param array {object} aLayout Array to store the calculated layout in
  3262. * @param {node} nThead The header/footer element for the table
  3263. * @memberof DataTable#oApi
  3264. */
  3265. function _fnDetectHeader ( aLayout, nThead )
  3266. {
  3267. var nTrs = $(nThead).children('tr');
  3268. var nTr, nCell;
  3269. var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
  3270. var bUnique;
  3271. var fnShiftCol = function ( a, i, j ) {
  3272. var k = a[i];
  3273. while ( k[j] ) {
  3274. j++;
  3275. }
  3276. return j;
  3277. };
  3278. aLayout.splice( 0, aLayout.length );
  3279. /* We know how many rows there are in the layout - so prep it */
  3280. for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  3281. {
  3282. aLayout.push( [] );
  3283. }
  3284. /* Calculate a layout array */
  3285. for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  3286. {
  3287. nTr = nTrs[i];
  3288. iColumn = 0;
  3289. /* For every cell in the row... */
  3290. nCell = nTr.firstChild;
  3291. while ( nCell ) {
  3292. if ( nCell.nodeName.toUpperCase() == "TD" ||
  3293. nCell.nodeName.toUpperCase() == "TH" )
  3294. {
  3295. /* Get the col and rowspan attributes from the DOM and sanitise them */
  3296. iColspan = nCell.getAttribute('colspan') * 1;
  3297. iRowspan = nCell.getAttribute('rowspan') * 1;
  3298. iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
  3299. iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
  3300. /* There might be colspan cells already in this row, so shift our target
  3301. * accordingly
  3302. */
  3303. iColShifted = fnShiftCol( aLayout, i, iColumn );
  3304. /* Cache calculation for unique columns */
  3305. bUnique = iColspan === 1 ? true : false;
  3306. /* If there is col / rowspan, copy the information into the layout grid */
  3307. for ( l=0 ; l<iColspan ; l++ )
  3308. {
  3309. for ( k=0 ; k<iRowspan ; k++ )
  3310. {
  3311. aLayout[i+k][iColShifted+l] = {
  3312. "cell": nCell,
  3313. "unique": bUnique
  3314. };
  3315. aLayout[i+k].nTr = nTr;
  3316. }
  3317. }
  3318. }
  3319. nCell = nCell.nextSibling;
  3320. }
  3321. }
  3322. }
  3323. /**
  3324. * Get an array of unique th elements, one for each column
  3325. * @param {object} oSettings dataTables settings object
  3326. * @param {node} nHeader automatically detect the layout from this node - optional
  3327. * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
  3328. * @returns array {node} aReturn list of unique th's
  3329. * @memberof DataTable#oApi
  3330. */
  3331. function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
  3332. {
  3333. var aReturn = [];
  3334. if ( !aLayout )
  3335. {
  3336. aLayout = oSettings.aoHeader;
  3337. if ( nHeader )
  3338. {
  3339. aLayout = [];
  3340. _fnDetectHeader( aLayout, nHeader );
  3341. }
  3342. }
  3343. for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
  3344. {
  3345. for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
  3346. {
  3347. if ( aLayout[i][j].unique &&
  3348. (!aReturn[j] || !oSettings.bSortCellsTop) )
  3349. {
  3350. aReturn[j] = aLayout[i][j].cell;
  3351. }
  3352. }
  3353. }
  3354. return aReturn;
  3355. }
  3356. /**
  3357. * Set the start position for draw
  3358. * @param {object} oSettings dataTables settings object
  3359. */
  3360. function _fnStart( oSettings )
  3361. {
  3362. var bServerSide = _fnDataSource( oSettings ) == 'ssp';
  3363. var iInitDisplayStart = oSettings.iInitDisplayStart;
  3364. // Check and see if we have an initial draw position from state saving
  3365. if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
  3366. {
  3367. oSettings._iDisplayStart = bServerSide ?
  3368. iInitDisplayStart :
  3369. iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
  3370. 0 :
  3371. iInitDisplayStart;
  3372. oSettings.iInitDisplayStart = -1;
  3373. }
  3374. }
  3375. /**
  3376. * Create an Ajax call based on the table's settings, taking into account that
  3377. * parameters can have multiple forms, and backwards compatibility.
  3378. *
  3379. * @param {object} oSettings dataTables settings object
  3380. * @param {array} data Data to send to the server, required by
  3381. * DataTables - may be augmented by developer callbacks
  3382. * @param {function} fn Callback function to run when data is obtained
  3383. */
  3384. function _fnBuildAjax( oSettings, data, fn )
  3385. {
  3386. // Compatibility with 1.9-, allow fnServerData and event to manipulate
  3387. _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
  3388. // Convert to object based for 1.10+ if using the old array scheme which can
  3389. // come from server-side processing or serverParams
  3390. if ( data && Array.isArray(data) ) {
  3391. var tmp = {};
  3392. var rbracket = /(.*?)\[\]$/;
  3393. $.each( data, function (key, val) {
  3394. var match = val.name.match(rbracket);
  3395. if ( match ) {
  3396. // Support for arrays
  3397. var name = match[0];
  3398. if ( ! tmp[ name ] ) {
  3399. tmp[ name ] = [];
  3400. }
  3401. tmp[ name ].push( val.value );
  3402. }
  3403. else {
  3404. tmp[val.name] = val.value;
  3405. }
  3406. } );
  3407. data = tmp;
  3408. }
  3409. var ajaxData;
  3410. var ajax = oSettings.ajax;
  3411. var instance = oSettings.oInstance;
  3412. var callback = function ( json ) {
  3413. var status = oSettings.jqXHR
  3414. ? oSettings.jqXHR.status
  3415. : null;
  3416. if ( json === null || (typeof status === 'number' && status == 204 ) ) {
  3417. json = {};
  3418. _fnAjaxDataSrc( oSettings, json, [] );
  3419. }
  3420. var error = json.error || json.sError;
  3421. if ( error ) {
  3422. _fnLog( oSettings, 0, error );
  3423. }
  3424. oSettings.json = json;
  3425. _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
  3426. fn( json );
  3427. };
  3428. if ( $.isPlainObject( ajax ) && ajax.data )
  3429. {
  3430. ajaxData = ajax.data;
  3431. var newData = typeof ajaxData === 'function' ?
  3432. ajaxData( data, oSettings ) : // fn can manipulate data or return
  3433. ajaxData; // an object object or array to merge
  3434. // If the function returned something, use that alone
  3435. data = typeof ajaxData === 'function' && newData ?
  3436. newData :
  3437. $.extend( true, data, newData );
  3438. // Remove the data property as we've resolved it already and don't want
  3439. // jQuery to do it again (it is restored at the end of the function)
  3440. delete ajax.data;
  3441. }
  3442. var baseAjax = {
  3443. "data": data,
  3444. "success": callback,
  3445. "dataType": "json",
  3446. "cache": false,
  3447. "type": oSettings.sServerMethod,
  3448. "error": function (xhr, error, thrown) {
  3449. var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
  3450. if ( $.inArray( true, ret ) === -1 ) {
  3451. if ( error == "parsererror" ) {
  3452. _fnLog( oSettings, 0, 'Invalid JSON response', 1 );
  3453. }
  3454. else if ( xhr.readyState === 4 ) {
  3455. _fnLog( oSettings, 0, 'Ajax error', 7 );
  3456. }
  3457. }
  3458. _fnProcessingDisplay( oSettings, false );
  3459. }
  3460. };
  3461. // Store the data submitted for the API
  3462. oSettings.oAjaxData = data;
  3463. // Allow plug-ins and external processes to modify the data
  3464. _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
  3465. if ( oSettings.fnServerData )
  3466. {
  3467. // DataTables 1.9- compatibility
  3468. oSettings.fnServerData.call( instance,
  3469. oSettings.sAjaxSource,
  3470. $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
  3471. return { name: key, value: val };
  3472. } ),
  3473. callback,
  3474. oSettings
  3475. );
  3476. }
  3477. else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
  3478. {
  3479. // DataTables 1.9- compatibility
  3480. oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
  3481. url: ajax || oSettings.sAjaxSource
  3482. } ) );
  3483. }
  3484. else if ( typeof ajax === 'function' )
  3485. {
  3486. // Is a function - let the caller define what needs to be done
  3487. oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
  3488. }
  3489. else
  3490. {
  3491. // Object to extend the base settings
  3492. oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
  3493. // Restore for next time around
  3494. ajax.data = ajaxData;
  3495. }
  3496. }
  3497. /**
  3498. * Update the table using an Ajax call
  3499. * @param {object} settings dataTables settings object
  3500. * @returns {boolean} Block the table drawing or not
  3501. * @memberof DataTable#oApi
  3502. */
  3503. function _fnAjaxUpdate( settings )
  3504. {
  3505. settings.iDraw++;
  3506. _fnProcessingDisplay( settings, true );
  3507. _fnBuildAjax(
  3508. settings,
  3509. _fnAjaxParameters( settings ),
  3510. function(json) {
  3511. _fnAjaxUpdateDraw( settings, json );
  3512. }
  3513. );
  3514. }
  3515. /**
  3516. * Build up the parameters in an object needed for a server-side processing
  3517. * request. Note that this is basically done twice, is different ways - a modern
  3518. * method which is used by default in DataTables 1.10 which uses objects and
  3519. * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
  3520. * the sAjaxSource option is used in the initialisation, or the legacyAjax
  3521. * option is set.
  3522. * @param {object} oSettings dataTables settings object
  3523. * @returns {bool} block the table drawing or not
  3524. * @memberof DataTable#oApi
  3525. */
  3526. function _fnAjaxParameters( settings )
  3527. {
  3528. var
  3529. columns = settings.aoColumns,
  3530. columnCount = columns.length,
  3531. features = settings.oFeatures,
  3532. preSearch = settings.oPreviousSearch,
  3533. preColSearch = settings.aoPreSearchCols,
  3534. i, data = [], dataProp, column, columnSearch,
  3535. sort = _fnSortFlatten( settings ),
  3536. displayStart = settings._iDisplayStart,
  3537. displayLength = features.bPaginate !== false ?
  3538. settings._iDisplayLength :
  3539. -1;
  3540. var param = function ( name, value ) {
  3541. data.push( { 'name': name, 'value': value } );
  3542. };
  3543. // DataTables 1.9- compatible method
  3544. param( 'sEcho', settings.iDraw );
  3545. param( 'iColumns', columnCount );
  3546. param( 'sColumns', _pluck( columns, 'sName' ).join(',') );
  3547. param( 'iDisplayStart', displayStart );
  3548. param( 'iDisplayLength', displayLength );
  3549. // DataTables 1.10+ method
  3550. var d = {
  3551. draw: settings.iDraw,
  3552. columns: [],
  3553. order: [],
  3554. start: displayStart,
  3555. length: displayLength,
  3556. search: {
  3557. value: preSearch.sSearch,
  3558. regex: preSearch.bRegex
  3559. }
  3560. };
  3561. for ( i=0 ; i<columnCount ; i++ ) {
  3562. column = columns[i];
  3563. columnSearch = preColSearch[i];
  3564. dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
  3565. d.columns.push( {
  3566. data: dataProp,
  3567. name: column.sName,
  3568. searchable: column.bSearchable,
  3569. orderable: column.bSortable,
  3570. search: {
  3571. value: columnSearch.sSearch,
  3572. regex: columnSearch.bRegex
  3573. }
  3574. } );
  3575. param( "mDataProp_"+i, dataProp );
  3576. if ( features.bFilter ) {
  3577. param( 'sSearch_'+i, columnSearch.sSearch );
  3578. param( 'bRegex_'+i, columnSearch.bRegex );
  3579. param( 'bSearchable_'+i, column.bSearchable );
  3580. }
  3581. if ( features.bSort ) {
  3582. param( 'bSortable_'+i, column.bSortable );
  3583. }
  3584. }
  3585. if ( features.bFilter ) {
  3586. param( 'sSearch', preSearch.sSearch );
  3587. param( 'bRegex', preSearch.bRegex );
  3588. }
  3589. if ( features.bSort ) {
  3590. $.each( sort, function ( i, val ) {
  3591. d.order.push( { column: val.col, dir: val.dir } );
  3592. param( 'iSortCol_'+i, val.col );
  3593. param( 'sSortDir_'+i, val.dir );
  3594. } );
  3595. param( 'iSortingCols', sort.length );
  3596. }
  3597. // If the legacy.ajax parameter is null, then we automatically decide which
  3598. // form to use, based on sAjaxSource
  3599. var legacy = DataTable.ext.legacy.ajax;
  3600. if ( legacy === null ) {
  3601. return settings.sAjaxSource ? data : d;
  3602. }
  3603. // Otherwise, if legacy has been specified then we use that to decide on the
  3604. // form
  3605. return legacy ? data : d;
  3606. }
  3607. /**
  3608. * Data the data from the server (nuking the old) and redraw the table
  3609. * @param {object} oSettings dataTables settings object
  3610. * @param {object} json json data return from the server.
  3611. * @param {string} json.sEcho Tracking flag for DataTables to match requests
  3612. * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
  3613. * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
  3614. * @param {array} json.aaData The data to display on this page
  3615. * @param {string} [json.sColumns] Column ordering (sName, comma separated)
  3616. * @memberof DataTable#oApi
  3617. */
  3618. function _fnAjaxUpdateDraw ( settings, json )
  3619. {
  3620. // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
  3621. // Support both
  3622. var compat = function ( old, modern ) {
  3623. return json[old] !== undefined ? json[old] : json[modern];
  3624. };
  3625. var data = _fnAjaxDataSrc( settings, json );
  3626. var draw = compat( 'sEcho', 'draw' );
  3627. var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' );
  3628. var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
  3629. if ( draw !== undefined ) {
  3630. // Protect against out of sequence returns
  3631. if ( draw*1 < settings.iDraw ) {
  3632. return;
  3633. }
  3634. settings.iDraw = draw * 1;
  3635. }
  3636. // No data in returned object, so rather than an array, we show an empty table
  3637. if ( ! data ) {
  3638. data = [];
  3639. }
  3640. _fnClearTable( settings );
  3641. settings._iRecordsTotal = parseInt(recordsTotal, 10);
  3642. settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
  3643. for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  3644. _fnAddData( settings, data[i] );
  3645. }
  3646. settings.aiDisplay = settings.aiDisplayMaster.slice();
  3647. _fnDraw( settings, true );
  3648. if ( ! settings._bInitComplete ) {
  3649. _fnInitComplete( settings, json );
  3650. }
  3651. _fnProcessingDisplay( settings, false );
  3652. }
  3653. /**
  3654. * Get the data from the JSON data source to use for drawing a table. Using
  3655. * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
  3656. * source object, or from a processing function.
  3657. * @param {object} oSettings dataTables settings object
  3658. * @param {object} json Data source object / array from the server
  3659. * @return {array} Array of data to use
  3660. */
  3661. function _fnAjaxDataSrc ( oSettings, json, write )
  3662. {
  3663. var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
  3664. oSettings.ajax.dataSrc :
  3665. oSettings.sAjaxDataProp; // Compatibility with 1.9-.
  3666. if ( ! write ) {
  3667. if ( dataSrc === 'data' ) {
  3668. // If the default, then we still want to support the old style, and safely ignore
  3669. // it if possible
  3670. return json.aaData || json[dataSrc];
  3671. }
  3672. return dataSrc !== "" ?
  3673. _fnGetObjectDataFn( dataSrc )( json ) :
  3674. json;
  3675. }
  3676. // set
  3677. _fnSetObjectDataFn( dataSrc )( json, write );
  3678. }
  3679. /**
  3680. * Generate the node required for filtering text
  3681. * @returns {node} Filter control element
  3682. * @param {object} oSettings dataTables settings object
  3683. * @memberof DataTable#oApi
  3684. */
  3685. function _fnFeatureHtmlFilter ( settings )
  3686. {
  3687. var classes = settings.oClasses;
  3688. var tableId = settings.sTableId;
  3689. var language = settings.oLanguage;
  3690. var previousSearch = settings.oPreviousSearch;
  3691. var features = settings.aanFeatures;
  3692. var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
  3693. var str = language.sSearch;
  3694. str = str.match(/_INPUT_/) ?
  3695. str.replace('_INPUT_', input) :
  3696. str+input;
  3697. var filter = $('<div/>', {
  3698. 'id': ! features.f ? tableId+'_filter' : null,
  3699. 'class': classes.sFilter
  3700. } )
  3701. .append( $('<label/>' ).append( str ) );
  3702. var searchFn = function(event) {
  3703. /* Update all other filter input elements for the new display */
  3704. var n = features.f;
  3705. var val = !this.value ? "" : this.value; // mental IE8 fix :-(
  3706. if(previousSearch.return && event.key !== "Enter") {
  3707. return;
  3708. }
  3709. /* Now do the filter */
  3710. if ( val != previousSearch.sSearch ) {
  3711. _fnFilterComplete( settings, {
  3712. "sSearch": val,
  3713. "bRegex": previousSearch.bRegex,
  3714. "bSmart": previousSearch.bSmart ,
  3715. "bCaseInsensitive": previousSearch.bCaseInsensitive,
  3716. "return": previousSearch.return
  3717. } );
  3718. // Need to redraw, without resorting
  3719. settings._iDisplayStart = 0;
  3720. _fnDraw( settings );
  3721. }
  3722. };
  3723. var searchDelay = settings.searchDelay !== null ?
  3724. settings.searchDelay :
  3725. _fnDataSource( settings ) === 'ssp' ?
  3726. 400 :
  3727. 0;
  3728. var jqFilter = $('input', filter)
  3729. .val( previousSearch.sSearch )
  3730. .attr( 'placeholder', language.sSearchPlaceholder )
  3731. .on(
  3732. 'keyup.DT search.DT input.DT paste.DT cut.DT',
  3733. searchDelay ?
  3734. _fnThrottle( searchFn, searchDelay ) :
  3735. searchFn
  3736. )
  3737. .on( 'mouseup', function(e) {
  3738. // Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
  3739. // on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
  3740. // checks the value to see if it has changed. In other browsers it won't have.
  3741. setTimeout( function () {
  3742. searchFn.call(jqFilter[0], e);
  3743. }, 10);
  3744. } )
  3745. .on( 'keypress.DT', function(e) {
  3746. /* Prevent form submission */
  3747. if ( e.keyCode == 13 ) {
  3748. return false;
  3749. }
  3750. } )
  3751. .attr('aria-controls', tableId);
  3752. // Update the input elements whenever the table is filtered
  3753. $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
  3754. if ( settings === s ) {
  3755. // IE9 throws an 'unknown error' if document.activeElement is used
  3756. // inside an iframe or frame...
  3757. try {
  3758. if ( jqFilter[0] !== document.activeElement ) {
  3759. jqFilter.val( previousSearch.sSearch );
  3760. }
  3761. }
  3762. catch ( e ) {}
  3763. }
  3764. } );
  3765. return filter[0];
  3766. }
  3767. /**
  3768. * Filter the table using both the global filter and column based filtering
  3769. * @param {object} oSettings dataTables settings object
  3770. * @param {object} oSearch search information
  3771. * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
  3772. * @memberof DataTable#oApi
  3773. */
  3774. function _fnFilterComplete ( oSettings, oInput, iForce )
  3775. {
  3776. var oPrevSearch = oSettings.oPreviousSearch;
  3777. var aoPrevSearch = oSettings.aoPreSearchCols;
  3778. var fnSaveFilter = function ( oFilter ) {
  3779. /* Save the filtering values */
  3780. oPrevSearch.sSearch = oFilter.sSearch;
  3781. oPrevSearch.bRegex = oFilter.bRegex;
  3782. oPrevSearch.bSmart = oFilter.bSmart;
  3783. oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
  3784. oPrevSearch.return = oFilter.return;
  3785. };
  3786. var fnRegex = function ( o ) {
  3787. // Backwards compatibility with the bEscapeRegex option
  3788. return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
  3789. };
  3790. // Resolve any column types that are unknown due to addition or invalidation
  3791. // @todo As per sort - can this be moved into an event handler?
  3792. _fnColumnTypes( oSettings );
  3793. /* In server-side processing all filtering is done by the server, so no point hanging around here */
  3794. if ( _fnDataSource( oSettings ) != 'ssp' )
  3795. {
  3796. /* Global filter */
  3797. _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive, oInput.return );
  3798. fnSaveFilter( oInput );
  3799. /* Now do the individual column filter */
  3800. for ( var i=0 ; i<aoPrevSearch.length ; i++ )
  3801. {
  3802. _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
  3803. aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
  3804. }
  3805. /* Custom filtering */
  3806. _fnFilterCustom( oSettings );
  3807. }
  3808. else
  3809. {
  3810. fnSaveFilter( oInput );
  3811. }
  3812. /* Tell the draw function we have been filtering */
  3813. oSettings.bFiltered = true;
  3814. _fnCallbackFire( oSettings, null, 'search', [oSettings] );
  3815. }
  3816. /**
  3817. * Apply custom filtering functions
  3818. * @param {object} oSettings dataTables settings object
  3819. * @memberof DataTable#oApi
  3820. */
  3821. function _fnFilterCustom( settings )
  3822. {
  3823. var filters = DataTable.ext.search;
  3824. var displayRows = settings.aiDisplay;
  3825. var row, rowIdx;
  3826. for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
  3827. var rows = [];
  3828. // Loop over each row and see if it should be included
  3829. for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
  3830. rowIdx = displayRows[ j ];
  3831. row = settings.aoData[ rowIdx ];
  3832. if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
  3833. rows.push( rowIdx );
  3834. }
  3835. }
  3836. // So the array reference doesn't break set the results into the
  3837. // existing array
  3838. displayRows.length = 0;
  3839. $.merge( displayRows, rows );
  3840. }
  3841. }
  3842. /**
  3843. * Filter the table on a per-column basis
  3844. * @param {object} oSettings dataTables settings object
  3845. * @param {string} sInput string to filter on
  3846. * @param {int} iColumn column to filter
  3847. * @param {bool} bRegex treat search string as a regular expression or not
  3848. * @param {bool} bSmart use smart filtering or not
  3849. * @param {bool} bCaseInsensitive Do case insensitive matching or not
  3850. * @memberof DataTable#oApi
  3851. */
  3852. function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
  3853. {
  3854. if ( searchStr === '' ) {
  3855. return;
  3856. }
  3857. var data;
  3858. var out = [];
  3859. var display = settings.aiDisplay;
  3860. var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
  3861. for ( var i=0 ; i<display.length ; i++ ) {
  3862. data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
  3863. if ( rpSearch.test( data ) ) {
  3864. out.push( display[i] );
  3865. }
  3866. }
  3867. settings.aiDisplay = out;
  3868. }
  3869. /**
  3870. * Filter the data table based on user input and draw the table
  3871. * @param {object} settings dataTables settings object
  3872. * @param {string} input string to filter on
  3873. * @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
  3874. * @param {bool} regex treat as a regular expression or not
  3875. * @param {bool} smart perform smart filtering or not
  3876. * @param {bool} caseInsensitive Do case insensitive matching or not
  3877. * @memberof DataTable#oApi
  3878. */
  3879. function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
  3880. {
  3881. var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
  3882. var prevSearch = settings.oPreviousSearch.sSearch;
  3883. var displayMaster = settings.aiDisplayMaster;
  3884. var display, invalidated, i;
  3885. var filtered = [];
  3886. // Need to take account of custom filtering functions - always filter
  3887. if ( DataTable.ext.search.length !== 0 ) {
  3888. force = true;
  3889. }
  3890. // Check if any of the rows were invalidated
  3891. invalidated = _fnFilterData( settings );
  3892. // If the input is blank - we just want the full data set
  3893. if ( input.length <= 0 ) {
  3894. settings.aiDisplay = displayMaster.slice();
  3895. }
  3896. else {
  3897. // New search - start from the master array
  3898. if ( invalidated ||
  3899. force ||
  3900. regex ||
  3901. prevSearch.length > input.length ||
  3902. input.indexOf(prevSearch) !== 0 ||
  3903. settings.bSorted // On resort, the display master needs to be
  3904. // re-filtered since indexes will have changed
  3905. ) {
  3906. settings.aiDisplay = displayMaster.slice();
  3907. }
  3908. // Search the display array
  3909. display = settings.aiDisplay;
  3910. for ( i=0 ; i<display.length ; i++ ) {
  3911. if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
  3912. filtered.push( display[i] );
  3913. }
  3914. }
  3915. settings.aiDisplay = filtered;
  3916. }
  3917. }
  3918. /**
  3919. * Build a regular expression object suitable for searching a table
  3920. * @param {string} sSearch string to search for
  3921. * @param {bool} bRegex treat as a regular expression or not
  3922. * @param {bool} bSmart perform smart filtering or not
  3923. * @param {bool} bCaseInsensitive Do case insensitive matching or not
  3924. * @returns {RegExp} constructed object
  3925. * @memberof DataTable#oApi
  3926. */
  3927. function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
  3928. {
  3929. search = regex ?
  3930. search :
  3931. _fnEscapeRegex( search );
  3932. if ( smart ) {
  3933. /* For smart filtering we want to allow the search to work regardless of
  3934. * word order. We also want double quoted text to be preserved, so word
  3935. * order is important - a la google. So this is what we want to
  3936. * generate:
  3937. *
  3938. * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
  3939. */
  3940. var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
  3941. if ( word.charAt(0) === '"' ) {
  3942. var m = word.match( /^"(.*)"$/ );
  3943. word = m ? m[1] : word;
  3944. }
  3945. return word.replace('"', '');
  3946. } );
  3947. search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
  3948. }
  3949. return new RegExp( search, caseInsensitive ? 'i' : '' );
  3950. }
  3951. /**
  3952. * Escape a string such that it can be used in a regular expression
  3953. * @param {string} sVal string to escape
  3954. * @returns {string} escaped string
  3955. * @memberof DataTable#oApi
  3956. */
  3957. var _fnEscapeRegex = DataTable.util.escapeRegex;
  3958. var __filter_div = $('<div>')[0];
  3959. var __filter_div_textContent = __filter_div.textContent !== undefined;
  3960. // Update the filtering data for each row if needed (by invalidation or first run)
  3961. function _fnFilterData ( settings )
  3962. {
  3963. var columns = settings.aoColumns;
  3964. var column;
  3965. var i, j, ien, jen, filterData, cellData, row;
  3966. var wasInvalidated = false;
  3967. for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  3968. row = settings.aoData[i];
  3969. if ( ! row._aFilterData ) {
  3970. filterData = [];
  3971. for ( j=0, jen=columns.length ; j<jen ; j++ ) {
  3972. column = columns[j];
  3973. if ( column.bSearchable ) {
  3974. cellData = _fnGetCellData( settings, i, j, 'filter' );
  3975. // Search in DataTables 1.10 is string based. In 1.11 this
  3976. // should be altered to also allow strict type checking.
  3977. if ( cellData === null ) {
  3978. cellData = '';
  3979. }
  3980. if ( typeof cellData !== 'string' && cellData.toString ) {
  3981. cellData = cellData.toString();
  3982. }
  3983. }
  3984. else {
  3985. cellData = '';
  3986. }
  3987. // If it looks like there is an HTML entity in the string,
  3988. // attempt to decode it so sorting works as expected. Note that
  3989. // we could use a single line of jQuery to do this, but the DOM
  3990. // method used here is much faster http://jsperf.com/html-decode
  3991. if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
  3992. __filter_div.innerHTML = cellData;
  3993. cellData = __filter_div_textContent ?
  3994. __filter_div.textContent :
  3995. __filter_div.innerText;
  3996. }
  3997. if ( cellData.replace ) {
  3998. cellData = cellData.replace(/[\r\n\u2028]/g, '');
  3999. }
  4000. filterData.push( cellData );
  4001. }
  4002. row._aFilterData = filterData;
  4003. row._sFilterRow = filterData.join(' ');
  4004. wasInvalidated = true;
  4005. }
  4006. }
  4007. return wasInvalidated;
  4008. }
  4009. /**
  4010. * Convert from the internal Hungarian notation to camelCase for external
  4011. * interaction
  4012. * @param {object} obj Object to convert
  4013. * @returns {object} Inverted object
  4014. * @memberof DataTable#oApi
  4015. */
  4016. function _fnSearchToCamel ( obj )
  4017. {
  4018. return {
  4019. search: obj.sSearch,
  4020. smart: obj.bSmart,
  4021. regex: obj.bRegex,
  4022. caseInsensitive: obj.bCaseInsensitive
  4023. };
  4024. }
  4025. /**
  4026. * Convert from camelCase notation to the internal Hungarian. We could use the
  4027. * Hungarian convert function here, but this is cleaner
  4028. * @param {object} obj Object to convert
  4029. * @returns {object} Inverted object
  4030. * @memberof DataTable#oApi
  4031. */
  4032. function _fnSearchToHung ( obj )
  4033. {
  4034. return {
  4035. sSearch: obj.search,
  4036. bSmart: obj.smart,
  4037. bRegex: obj.regex,
  4038. bCaseInsensitive: obj.caseInsensitive
  4039. };
  4040. }
  4041. /**
  4042. * Generate the node required for the info display
  4043. * @param {object} oSettings dataTables settings object
  4044. * @returns {node} Information element
  4045. * @memberof DataTable#oApi
  4046. */
  4047. function _fnFeatureHtmlInfo ( settings )
  4048. {
  4049. var
  4050. tid = settings.sTableId,
  4051. nodes = settings.aanFeatures.i,
  4052. n = $('<div/>', {
  4053. 'class': settings.oClasses.sInfo,
  4054. 'id': ! nodes ? tid+'_info' : null
  4055. } );
  4056. if ( ! nodes ) {
  4057. // Update display on each draw
  4058. settings.aoDrawCallback.push( {
  4059. "fn": _fnUpdateInfo,
  4060. "sName": "information"
  4061. } );
  4062. n
  4063. .attr( 'role', 'status' )
  4064. .attr( 'aria-live', 'polite' );
  4065. // Table is described by our info div
  4066. $(settings.nTable).attr( 'aria-describedby', tid+'_info' );
  4067. }
  4068. return n[0];
  4069. }
  4070. /**
  4071. * Update the information elements in the display
  4072. * @param {object} settings dataTables settings object
  4073. * @memberof DataTable#oApi
  4074. */
  4075. function _fnUpdateInfo ( settings )
  4076. {
  4077. /* Show information about the table */
  4078. var nodes = settings.aanFeatures.i;
  4079. if ( nodes.length === 0 ) {
  4080. return;
  4081. }
  4082. var
  4083. lang = settings.oLanguage,
  4084. start = settings._iDisplayStart+1,
  4085. end = settings.fnDisplayEnd(),
  4086. max = settings.fnRecordsTotal(),
  4087. total = settings.fnRecordsDisplay(),
  4088. out = total ?
  4089. lang.sInfo :
  4090. lang.sInfoEmpty;
  4091. if ( total !== max ) {
  4092. /* Record set after filtering */
  4093. out += ' ' + lang.sInfoFiltered;
  4094. }
  4095. // Convert the macros
  4096. out += lang.sInfoPostFix;
  4097. out = _fnInfoMacros( settings, out );
  4098. var callback = lang.fnInfoCallback;
  4099. if ( callback !== null ) {
  4100. out = callback.call( settings.oInstance,
  4101. settings, start, end, max, total, out
  4102. );
  4103. }
  4104. $(nodes).html( out );
  4105. }
  4106. function _fnInfoMacros ( settings, str )
  4107. {
  4108. // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
  4109. // internally
  4110. var
  4111. formatter = settings.fnFormatNumber,
  4112. start = settings._iDisplayStart+1,
  4113. len = settings._iDisplayLength,
  4114. vis = settings.fnRecordsDisplay(),
  4115. all = len === -1;
  4116. return str.
  4117. replace(/_START_/g, formatter.call( settings, start ) ).
  4118. replace(/_END_/g, formatter.call( settings, settings.fnDisplayEnd() ) ).
  4119. replace(/_MAX_/g, formatter.call( settings, settings.fnRecordsTotal() ) ).
  4120. replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
  4121. replace(/_PAGE_/g, formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
  4122. replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
  4123. }
  4124. /**
  4125. * Draw the table for the first time, adding all required features
  4126. * @param {object} settings dataTables settings object
  4127. * @memberof DataTable#oApi
  4128. */
  4129. function _fnInitialise ( settings )
  4130. {
  4131. var i, iLen, iAjaxStart=settings.iInitDisplayStart;
  4132. var columns = settings.aoColumns, column;
  4133. var features = settings.oFeatures;
  4134. var deferLoading = settings.bDeferLoading; // value modified by the draw
  4135. /* Ensure that the table data is fully initialised */
  4136. if ( ! settings.bInitialised ) {
  4137. setTimeout( function(){ _fnInitialise( settings ); }, 200 );
  4138. return;
  4139. }
  4140. /* Show the display HTML options */
  4141. _fnAddOptionsHtml( settings );
  4142. /* Build and draw the header / footer for the table */
  4143. _fnBuildHead( settings );
  4144. _fnDrawHead( settings, settings.aoHeader );
  4145. _fnDrawHead( settings, settings.aoFooter );
  4146. /* Okay to show that something is going on now */
  4147. _fnProcessingDisplay( settings, true );
  4148. /* Calculate sizes for columns */
  4149. if ( features.bAutoWidth ) {
  4150. _fnCalculateColumnWidths( settings );
  4151. }
  4152. for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
  4153. column = columns[i];
  4154. if ( column.sWidth ) {
  4155. column.nTh.style.width = _fnStringToCss( column.sWidth );
  4156. }
  4157. }
  4158. _fnCallbackFire( settings, null, 'preInit', [settings] );
  4159. // If there is default sorting required - let's do it. The sort function
  4160. // will do the drawing for us. Otherwise we draw the table regardless of the
  4161. // Ajax source - this allows the table to look initialised for Ajax sourcing
  4162. // data (show 'loading' message possibly)
  4163. _fnReDraw( settings );
  4164. // Server-side processing init complete is done by _fnAjaxUpdateDraw
  4165. var dataSrc = _fnDataSource( settings );
  4166. if ( dataSrc != 'ssp' || deferLoading ) {
  4167. // if there is an ajax source load the data
  4168. if ( dataSrc == 'ajax' ) {
  4169. _fnBuildAjax( settings, [], function(json) {
  4170. var aData = _fnAjaxDataSrc( settings, json );
  4171. // Got the data - add it to the table
  4172. for ( i=0 ; i<aData.length ; i++ ) {
  4173. _fnAddData( settings, aData[i] );
  4174. }
  4175. // Reset the init display for cookie saving. We've already done
  4176. // a filter, and therefore cleared it before. So we need to make
  4177. // it appear 'fresh'
  4178. settings.iInitDisplayStart = iAjaxStart;
  4179. _fnReDraw( settings );
  4180. _fnProcessingDisplay( settings, false );
  4181. _fnInitComplete( settings, json );
  4182. }, settings );
  4183. }
  4184. else {
  4185. _fnProcessingDisplay( settings, false );
  4186. _fnInitComplete( settings );
  4187. }
  4188. }
  4189. }
  4190. /**
  4191. * Draw the table for the first time, adding all required features
  4192. * @param {object} oSettings dataTables settings object
  4193. * @param {object} [json] JSON from the server that completed the table, if using Ajax source
  4194. * with client-side processing (optional)
  4195. * @memberof DataTable#oApi
  4196. */
  4197. function _fnInitComplete ( settings, json )
  4198. {
  4199. settings._bInitComplete = true;
  4200. // When data was added after the initialisation (data or Ajax) we need to
  4201. // calculate the column sizing
  4202. if ( json || settings.oInit.aaData ) {
  4203. _fnAdjustColumnSizing( settings );
  4204. }
  4205. _fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
  4206. _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
  4207. }
  4208. function _fnLengthChange ( settings, val )
  4209. {
  4210. var len = parseInt( val, 10 );
  4211. settings._iDisplayLength = len;
  4212. _fnLengthOverflow( settings );
  4213. // Fire length change event
  4214. _fnCallbackFire( settings, null, 'length', [settings, len] );
  4215. }
  4216. /**
  4217. * Generate the node required for user display length changing
  4218. * @param {object} settings dataTables settings object
  4219. * @returns {node} Display length feature node
  4220. * @memberof DataTable#oApi
  4221. */
  4222. function _fnFeatureHtmlLength ( settings )
  4223. {
  4224. var
  4225. classes = settings.oClasses,
  4226. tableId = settings.sTableId,
  4227. menu = settings.aLengthMenu,
  4228. d2 = Array.isArray( menu[0] ),
  4229. lengths = d2 ? menu[0] : menu,
  4230. language = d2 ? menu[1] : menu;
  4231. var select = $('<select/>', {
  4232. 'name': tableId+'_length',
  4233. 'aria-controls': tableId,
  4234. 'class': classes.sLengthSelect
  4235. } );
  4236. for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
  4237. select[0][ i ] = new Option(
  4238. typeof language[i] === 'number' ?
  4239. settings.fnFormatNumber( language[i] ) :
  4240. language[i],
  4241. lengths[i]
  4242. );
  4243. }
  4244. var div = $('<div><label/></div>').addClass( classes.sLength );
  4245. if ( ! settings.aanFeatures.l ) {
  4246. div[0].id = tableId+'_length';
  4247. }
  4248. div.children().append(
  4249. settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
  4250. );
  4251. // Can't use `select` variable as user might provide their own and the
  4252. // reference is broken by the use of outerHTML
  4253. $('select', div)
  4254. .val( settings._iDisplayLength )
  4255. .on( 'change.DT', function(e) {
  4256. _fnLengthChange( settings, $(this).val() );
  4257. _fnDraw( settings );
  4258. } );
  4259. // Update node value whenever anything changes the table's length
  4260. $(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
  4261. if ( settings === s ) {
  4262. $('select', div).val( len );
  4263. }
  4264. } );
  4265. return div[0];
  4266. }
  4267. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  4268. * Note that most of the paging logic is done in
  4269. * DataTable.ext.pager
  4270. */
  4271. /**
  4272. * Generate the node required for default pagination
  4273. * @param {object} oSettings dataTables settings object
  4274. * @returns {node} Pagination feature node
  4275. * @memberof DataTable#oApi
  4276. */
  4277. function _fnFeatureHtmlPaginate ( settings )
  4278. {
  4279. var
  4280. type = settings.sPaginationType,
  4281. plugin = DataTable.ext.pager[ type ],
  4282. modern = typeof plugin === 'function',
  4283. redraw = function( settings ) {
  4284. _fnDraw( settings );
  4285. },
  4286. node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
  4287. features = settings.aanFeatures;
  4288. if ( ! modern ) {
  4289. plugin.fnInit( settings, node, redraw );
  4290. }
  4291. /* Add a draw callback for the pagination on first instance, to update the paging display */
  4292. if ( ! features.p )
  4293. {
  4294. node.id = settings.sTableId+'_paginate';
  4295. settings.aoDrawCallback.push( {
  4296. "fn": function( settings ) {
  4297. if ( modern ) {
  4298. var
  4299. start = settings._iDisplayStart,
  4300. len = settings._iDisplayLength,
  4301. visRecords = settings.fnRecordsDisplay(),
  4302. all = len === -1,
  4303. page = all ? 0 : Math.ceil( start / len ),
  4304. pages = all ? 1 : Math.ceil( visRecords / len ),
  4305. buttons = plugin(page, pages),
  4306. i, ien;
  4307. for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
  4308. _fnRenderer( settings, 'pageButton' )(
  4309. settings, features.p[i], i, buttons, page, pages
  4310. );
  4311. }
  4312. }
  4313. else {
  4314. plugin.fnUpdate( settings, redraw );
  4315. }
  4316. },
  4317. "sName": "pagination"
  4318. } );
  4319. }
  4320. return node;
  4321. }
  4322. /**
  4323. * Alter the display settings to change the page
  4324. * @param {object} settings DataTables settings object
  4325. * @param {string|int} action Paging action to take: "first", "previous",
  4326. * "next" or "last" or page number to jump to (integer)
  4327. * @param [bool] redraw Automatically draw the update or not
  4328. * @returns {bool} true page has changed, false - no change
  4329. * @memberof DataTable#oApi
  4330. */
  4331. function _fnPageChange ( settings, action, redraw )
  4332. {
  4333. var
  4334. start = settings._iDisplayStart,
  4335. len = settings._iDisplayLength,
  4336. records = settings.fnRecordsDisplay();
  4337. if ( records === 0 || len === -1 )
  4338. {
  4339. start = 0;
  4340. }
  4341. else if ( typeof action === "number" )
  4342. {
  4343. start = action * len;
  4344. if ( start > records )
  4345. {
  4346. start = 0;
  4347. }
  4348. }
  4349. else if ( action == "first" )
  4350. {
  4351. start = 0;
  4352. }
  4353. else if ( action == "previous" )
  4354. {
  4355. start = len >= 0 ?
  4356. start - len :
  4357. 0;
  4358. if ( start < 0 )
  4359. {
  4360. start = 0;
  4361. }
  4362. }
  4363. else if ( action == "next" )
  4364. {
  4365. if ( start + len < records )
  4366. {
  4367. start += len;
  4368. }
  4369. }
  4370. else if ( action == "last" )
  4371. {
  4372. start = Math.floor( (records-1) / len) * len;
  4373. }
  4374. else
  4375. {
  4376. _fnLog( settings, 0, "Unknown paging action: "+action, 5 );
  4377. }
  4378. var changed = settings._iDisplayStart !== start;
  4379. settings._iDisplayStart = start;
  4380. if ( changed ) {
  4381. _fnCallbackFire( settings, null, 'page', [settings] );
  4382. if ( redraw ) {
  4383. _fnDraw( settings );
  4384. }
  4385. }
  4386. else {
  4387. // No change event - paging was called, but no change
  4388. _fnCallbackFire( settings, null, 'page-nc', [settings] );
  4389. }
  4390. return changed;
  4391. }
  4392. /**
  4393. * Generate the node required for the processing node
  4394. * @param {object} settings dataTables settings object
  4395. * @returns {node} Processing element
  4396. * @memberof DataTable#oApi
  4397. */
  4398. function _fnFeatureHtmlProcessing ( settings )
  4399. {
  4400. return $('<div/>', {
  4401. 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
  4402. 'class': settings.oClasses.sProcessing
  4403. } )
  4404. .html( settings.oLanguage.sProcessing )
  4405. .append('<div><div></div><div></div><div></div><div></div></div>')
  4406. .insertBefore( settings.nTable )[0];
  4407. }
  4408. /**
  4409. * Display or hide the processing indicator
  4410. * @param {object} settings dataTables settings object
  4411. * @param {bool} show Show the processing indicator (true) or not (false)
  4412. * @memberof DataTable#oApi
  4413. */
  4414. function _fnProcessingDisplay ( settings, show )
  4415. {
  4416. if ( settings.oFeatures.bProcessing ) {
  4417. $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
  4418. }
  4419. _fnCallbackFire( settings, null, 'processing', [settings, show] );
  4420. }
  4421. /**
  4422. * Add any control elements for the table - specifically scrolling
  4423. * @param {object} settings dataTables settings object
  4424. * @returns {node} Node to add to the DOM
  4425. * @memberof DataTable#oApi
  4426. */
  4427. function _fnFeatureHtmlTable ( settings )
  4428. {
  4429. var table = $(settings.nTable);
  4430. // Scrolling from here on in
  4431. var scroll = settings.oScroll;
  4432. if ( scroll.sX === '' && scroll.sY === '' ) {
  4433. return settings.nTable;
  4434. }
  4435. var scrollX = scroll.sX;
  4436. var scrollY = scroll.sY;
  4437. var classes = settings.oClasses;
  4438. var caption = table.children('caption');
  4439. var captionSide = caption.length ? caption[0]._captionSide : null;
  4440. var headerClone = $( table[0].cloneNode(false) );
  4441. var footerClone = $( table[0].cloneNode(false) );
  4442. var footer = table.children('tfoot');
  4443. var _div = '<div/>';
  4444. var size = function ( s ) {
  4445. return !s ? null : _fnStringToCss( s );
  4446. };
  4447. if ( ! footer.length ) {
  4448. footer = null;
  4449. }
  4450. /*
  4451. * The HTML structure that we want to generate in this function is:
  4452. * div - scroller
  4453. * div - scroll head
  4454. * div - scroll head inner
  4455. * table - scroll head table
  4456. * thead - thead
  4457. * div - scroll body
  4458. * table - table (master table)
  4459. * thead - thead clone for sizing
  4460. * tbody - tbody
  4461. * div - scroll foot
  4462. * div - scroll foot inner
  4463. * table - scroll foot table
  4464. * tfoot - tfoot
  4465. */
  4466. var scroller = $( _div, { 'class': classes.sScrollWrapper } )
  4467. .append(
  4468. $(_div, { 'class': classes.sScrollHead } )
  4469. .css( {
  4470. overflow: 'hidden',
  4471. position: 'relative',
  4472. border: 0,
  4473. width: scrollX ? size(scrollX) : '100%'
  4474. } )
  4475. .append(
  4476. $(_div, { 'class': classes.sScrollHeadInner } )
  4477. .css( {
  4478. 'box-sizing': 'content-box',
  4479. width: scroll.sXInner || '100%'
  4480. } )
  4481. .append(
  4482. headerClone
  4483. .removeAttr('id')
  4484. .css( 'margin-left', 0 )
  4485. .append( captionSide === 'top' ? caption : null )
  4486. .append(
  4487. table.children('thead')
  4488. )
  4489. )
  4490. )
  4491. )
  4492. .append(
  4493. $(_div, { 'class': classes.sScrollBody } )
  4494. .css( {
  4495. position: 'relative',
  4496. overflow: 'auto',
  4497. width: size( scrollX )
  4498. } )
  4499. .append( table )
  4500. );
  4501. if ( footer ) {
  4502. scroller.append(
  4503. $(_div, { 'class': classes.sScrollFoot } )
  4504. .css( {
  4505. overflow: 'hidden',
  4506. border: 0,
  4507. width: scrollX ? size(scrollX) : '100%'
  4508. } )
  4509. .append(
  4510. $(_div, { 'class': classes.sScrollFootInner } )
  4511. .append(
  4512. footerClone
  4513. .removeAttr('id')
  4514. .css( 'margin-left', 0 )
  4515. .append( captionSide === 'bottom' ? caption : null )
  4516. .append(
  4517. table.children('tfoot')
  4518. )
  4519. )
  4520. )
  4521. );
  4522. }
  4523. var children = scroller.children();
  4524. var scrollHead = children[0];
  4525. var scrollBody = children[1];
  4526. var scrollFoot = footer ? children[2] : null;
  4527. // When the body is scrolled, then we also want to scroll the headers
  4528. if ( scrollX ) {
  4529. $(scrollBody).on( 'scroll.DT', function (e) {
  4530. var scrollLeft = this.scrollLeft;
  4531. scrollHead.scrollLeft = scrollLeft;
  4532. if ( footer ) {
  4533. scrollFoot.scrollLeft = scrollLeft;
  4534. }
  4535. } );
  4536. }
  4537. $(scrollBody).css('max-height', scrollY);
  4538. if (! scroll.bCollapse) {
  4539. $(scrollBody).css('height', scrollY);
  4540. }
  4541. settings.nScrollHead = scrollHead;
  4542. settings.nScrollBody = scrollBody;
  4543. settings.nScrollFoot = scrollFoot;
  4544. // On redraw - align columns
  4545. settings.aoDrawCallback.push( {
  4546. "fn": _fnScrollDraw,
  4547. "sName": "scrolling"
  4548. } );
  4549. return scroller[0];
  4550. }
  4551. /**
  4552. * Update the header, footer and body tables for resizing - i.e. column
  4553. * alignment.
  4554. *
  4555. * Welcome to the most horrible function DataTables. The process that this
  4556. * function follows is basically:
  4557. * 1. Re-create the table inside the scrolling div
  4558. * 2. Take live measurements from the DOM
  4559. * 3. Apply the measurements to align the columns
  4560. * 4. Clean up
  4561. *
  4562. * @param {object} settings dataTables settings object
  4563. * @memberof DataTable#oApi
  4564. */
  4565. function _fnScrollDraw ( settings )
  4566. {
  4567. // Given that this is such a monster function, a lot of variables are use
  4568. // to try and keep the minimised size as small as possible
  4569. var
  4570. scroll = settings.oScroll,
  4571. scrollX = scroll.sX,
  4572. scrollXInner = scroll.sXInner,
  4573. scrollY = scroll.sY,
  4574. barWidth = scroll.iBarWidth,
  4575. divHeader = $(settings.nScrollHead),
  4576. divHeaderStyle = divHeader[0].style,
  4577. divHeaderInner = divHeader.children('div'),
  4578. divHeaderInnerStyle = divHeaderInner[0].style,
  4579. divHeaderTable = divHeaderInner.children('table'),
  4580. divBodyEl = settings.nScrollBody,
  4581. divBody = $(divBodyEl),
  4582. divBodyStyle = divBodyEl.style,
  4583. divFooter = $(settings.nScrollFoot),
  4584. divFooterInner = divFooter.children('div'),
  4585. divFooterTable = divFooterInner.children('table'),
  4586. header = $(settings.nTHead),
  4587. table = $(settings.nTable),
  4588. tableEl = table[0],
  4589. tableStyle = tableEl.style,
  4590. footer = settings.nTFoot ? $(settings.nTFoot) : null,
  4591. browser = settings.oBrowser,
  4592. ie67 = browser.bScrollOversize,
  4593. dtHeaderCells = _pluck( settings.aoColumns, 'nTh' ),
  4594. headerTrgEls, footerTrgEls,
  4595. headerSrcEls, footerSrcEls,
  4596. headerCopy, footerCopy,
  4597. headerWidths=[], footerWidths=[],
  4598. headerContent=[], footerContent=[],
  4599. idx, correction, sanityWidth,
  4600. zeroOut = function(nSizer) {
  4601. var style = nSizer.style;
  4602. style.paddingTop = "0";
  4603. style.paddingBottom = "0";
  4604. style.borderTopWidth = "0";
  4605. style.borderBottomWidth = "0";
  4606. style.height = 0;
  4607. };
  4608. // If the scrollbar visibility has changed from the last draw, we need to
  4609. // adjust the column sizes as the table width will have changed to account
  4610. // for the scrollbar
  4611. var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
  4612. if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
  4613. settings.scrollBarVis = scrollBarVis;
  4614. _fnAdjustColumnSizing( settings );
  4615. return; // adjust column sizing will call this function again
  4616. }
  4617. else {
  4618. settings.scrollBarVis = scrollBarVis;
  4619. }
  4620. /*
  4621. * 1. Re-create the table inside the scrolling div
  4622. */
  4623. // Remove the old minimised thead and tfoot elements in the inner table
  4624. table.children('thead, tfoot').remove();
  4625. if ( footer ) {
  4626. footerCopy = footer.clone().prependTo( table );
  4627. footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
  4628. footerSrcEls = footerCopy.find('tr');
  4629. footerCopy.find('[id]').removeAttr('id');
  4630. }
  4631. // Clone the current header and footer elements and then place it into the inner table
  4632. headerCopy = header.clone().prependTo( table );
  4633. headerTrgEls = header.find('tr'); // original header is in its own table
  4634. headerSrcEls = headerCopy.find('tr');
  4635. headerCopy.find('th, td').removeAttr('tabindex');
  4636. headerCopy.find('[id]').removeAttr('id');
  4637. /*
  4638. * 2. Take live measurements from the DOM - do not alter the DOM itself!
  4639. */
  4640. // Remove old sizing and apply the calculated column widths
  4641. // Get the unique column headers in the newly created (cloned) header. We want to apply the
  4642. // calculated sizes to this header
  4643. if ( ! scrollX )
  4644. {
  4645. divBodyStyle.width = '100%';
  4646. divHeader[0].style.width = '100%';
  4647. }
  4648. $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
  4649. idx = _fnVisibleToColumnIndex( settings, i );
  4650. el.style.width = settings.aoColumns[idx].sWidth;
  4651. } );
  4652. if ( footer ) {
  4653. _fnApplyToChildren( function(n) {
  4654. n.style.width = "";
  4655. }, footerSrcEls );
  4656. }
  4657. // Size the table as a whole
  4658. sanityWidth = table.outerWidth();
  4659. if ( scrollX === "" ) {
  4660. // No x scrolling
  4661. tableStyle.width = "100%";
  4662. // IE7 will make the width of the table when 100% include the scrollbar
  4663. // - which is shouldn't. When there is a scrollbar we need to take this
  4664. // into account.
  4665. if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
  4666. divBody.css('overflow-y') == "scroll")
  4667. ) {
  4668. tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
  4669. }
  4670. // Recalculate the sanity width
  4671. sanityWidth = table.outerWidth();
  4672. }
  4673. else if ( scrollXInner !== "" ) {
  4674. // legacy x scroll inner has been given - use it
  4675. tableStyle.width = _fnStringToCss(scrollXInner);
  4676. // Recalculate the sanity width
  4677. sanityWidth = table.outerWidth();
  4678. }
  4679. // Hidden header should have zero height, so remove padding and borders. Then
  4680. // set the width based on the real headers
  4681. // Apply all styles in one pass
  4682. _fnApplyToChildren( zeroOut, headerSrcEls );
  4683. // Read all widths in next pass
  4684. _fnApplyToChildren( function(nSizer) {
  4685. var style = window.getComputedStyle ?
  4686. window.getComputedStyle(nSizer).width :
  4687. _fnStringToCss( $(nSizer).width() );
  4688. headerContent.push( nSizer.innerHTML );
  4689. headerWidths.push( style );
  4690. }, headerSrcEls );
  4691. // Apply all widths in final pass
  4692. _fnApplyToChildren( function(nToSize, i) {
  4693. nToSize.style.width = headerWidths[i];
  4694. }, headerTrgEls );
  4695. $(headerSrcEls).css('height', 0);
  4696. /* Same again with the footer if we have one */
  4697. if ( footer )
  4698. {
  4699. _fnApplyToChildren( zeroOut, footerSrcEls );
  4700. _fnApplyToChildren( function(nSizer) {
  4701. footerContent.push( nSizer.innerHTML );
  4702. footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
  4703. }, footerSrcEls );
  4704. _fnApplyToChildren( function(nToSize, i) {
  4705. nToSize.style.width = footerWidths[i];
  4706. }, footerTrgEls );
  4707. $(footerSrcEls).height(0);
  4708. }
  4709. /*
  4710. * 3. Apply the measurements
  4711. */
  4712. // "Hide" the header and footer that we used for the sizing. We need to keep
  4713. // the content of the cell so that the width applied to the header and body
  4714. // both match, but we want to hide it completely. We want to also fix their
  4715. // width to what they currently are
  4716. _fnApplyToChildren( function(nSizer, i) {
  4717. nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
  4718. nSizer.childNodes[0].style.height = "0";
  4719. nSizer.childNodes[0].style.overflow = "hidden";
  4720. nSizer.style.width = headerWidths[i];
  4721. }, headerSrcEls );
  4722. if ( footer )
  4723. {
  4724. _fnApplyToChildren( function(nSizer, i) {
  4725. nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
  4726. nSizer.childNodes[0].style.height = "0";
  4727. nSizer.childNodes[0].style.overflow = "hidden";
  4728. nSizer.style.width = footerWidths[i];
  4729. }, footerSrcEls );
  4730. }
  4731. // Sanity check that the table is of a sensible width. If not then we are going to get
  4732. // misalignment - try to prevent this by not allowing the table to shrink below its min width
  4733. if ( Math.round(table.outerWidth()) < Math.round(sanityWidth) )
  4734. {
  4735. // The min width depends upon if we have a vertical scrollbar visible or not */
  4736. correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
  4737. divBody.css('overflow-y') == "scroll")) ?
  4738. sanityWidth+barWidth :
  4739. sanityWidth;
  4740. // IE6/7 are a law unto themselves...
  4741. if ( ie67 && (divBodyEl.scrollHeight >
  4742. divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
  4743. ) {
  4744. tableStyle.width = _fnStringToCss( correction-barWidth );
  4745. }
  4746. // And give the user a warning that we've stopped the table getting too small
  4747. if ( scrollX === "" || scrollXInner !== "" ) {
  4748. _fnLog( settings, 1, 'Possible column misalignment', 6 );
  4749. }
  4750. }
  4751. else
  4752. {
  4753. correction = '100%';
  4754. }
  4755. // Apply to the container elements
  4756. divBodyStyle.width = _fnStringToCss( correction );
  4757. divHeaderStyle.width = _fnStringToCss( correction );
  4758. if ( footer ) {
  4759. settings.nScrollFoot.style.width = _fnStringToCss( correction );
  4760. }
  4761. /*
  4762. * 4. Clean up
  4763. */
  4764. if ( ! scrollY ) {
  4765. /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
  4766. * the scrollbar height from the visible display, rather than adding it on. We need to
  4767. * set the height in order to sort this. Don't want to do it in any other browsers.
  4768. */
  4769. if ( ie67 ) {
  4770. divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
  4771. }
  4772. }
  4773. /* Finally set the width's of the header and footer tables */
  4774. var iOuterWidth = table.outerWidth();
  4775. divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
  4776. divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
  4777. // Figure out if there are scrollbar present - if so then we need a the header and footer to
  4778. // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
  4779. var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
  4780. var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
  4781. divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
  4782. if ( footer ) {
  4783. divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
  4784. divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
  4785. divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
  4786. }
  4787. // Correct DOM ordering for colgroup - comes before the thead
  4788. table.children('colgroup').insertBefore( table.children('thead') );
  4789. /* Adjust the position of the header in case we loose the y-scrollbar */
  4790. divBody.trigger('scroll');
  4791. // If sorting or filtering has occurred, jump the scrolling back to the top
  4792. // only if we aren't holding the position
  4793. if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
  4794. divBodyEl.scrollTop = 0;
  4795. }
  4796. }
  4797. /**
  4798. * Apply a given function to the display child nodes of an element array (typically
  4799. * TD children of TR rows
  4800. * @param {function} fn Method to apply to the objects
  4801. * @param array {nodes} an1 List of elements to look through for display children
  4802. * @param array {nodes} an2 Another list (identical structure to the first) - optional
  4803. * @memberof DataTable#oApi
  4804. */
  4805. function _fnApplyToChildren( fn, an1, an2 )
  4806. {
  4807. var index=0, i=0, iLen=an1.length;
  4808. var nNode1, nNode2;
  4809. while ( i < iLen ) {
  4810. nNode1 = an1[i].firstChild;
  4811. nNode2 = an2 ? an2[i].firstChild : null;
  4812. while ( nNode1 ) {
  4813. if ( nNode1.nodeType === 1 ) {
  4814. if ( an2 ) {
  4815. fn( nNode1, nNode2, index );
  4816. }
  4817. else {
  4818. fn( nNode1, index );
  4819. }
  4820. index++;
  4821. }
  4822. nNode1 = nNode1.nextSibling;
  4823. nNode2 = an2 ? nNode2.nextSibling : null;
  4824. }
  4825. i++;
  4826. }
  4827. }
  4828. var __re_html_remove = /<.*?>/g;
  4829. /**
  4830. * Calculate the width of columns for the table
  4831. * @param {object} oSettings dataTables settings object
  4832. * @memberof DataTable#oApi
  4833. */
  4834. function _fnCalculateColumnWidths ( oSettings )
  4835. {
  4836. var
  4837. table = oSettings.nTable,
  4838. columns = oSettings.aoColumns,
  4839. scroll = oSettings.oScroll,
  4840. scrollY = scroll.sY,
  4841. scrollX = scroll.sX,
  4842. scrollXInner = scroll.sXInner,
  4843. columnCount = columns.length,
  4844. visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
  4845. headerCells = $('th', oSettings.nTHead),
  4846. tableWidthAttr = table.getAttribute('width'), // from DOM element
  4847. tableContainer = table.parentNode,
  4848. userInputs = false,
  4849. i, column, columnIdx, width, outerWidth,
  4850. browser = oSettings.oBrowser,
  4851. ie67 = browser.bScrollOversize;
  4852. var styleWidth = table.style.width;
  4853. if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
  4854. tableWidthAttr = styleWidth;
  4855. }
  4856. /* Convert any user input sizes into pixel sizes */
  4857. for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4858. column = columns[ visibleColumns[i] ];
  4859. if ( column.sWidth !== null ) {
  4860. column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
  4861. userInputs = true;
  4862. }
  4863. }
  4864. /* If the number of columns in the DOM equals the number that we have to
  4865. * process in DataTables, then we can use the offsets that are created by
  4866. * the web- browser. No custom sizes can be set in order for this to happen,
  4867. * nor scrolling used
  4868. */
  4869. if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
  4870. columnCount == _fnVisbleColumns( oSettings ) &&
  4871. columnCount == headerCells.length
  4872. ) {
  4873. for ( i=0 ; i<columnCount ; i++ ) {
  4874. var colIdx = _fnVisibleToColumnIndex( oSettings, i );
  4875. if ( colIdx !== null ) {
  4876. columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
  4877. }
  4878. }
  4879. }
  4880. else
  4881. {
  4882. // Otherwise construct a single row, worst case, table with the widest
  4883. // node in the data, assign any user defined widths, then insert it into
  4884. // the DOM and allow the browser to do all the hard work of calculating
  4885. // table widths
  4886. var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
  4887. .css( 'visibility', 'hidden' )
  4888. .removeAttr( 'id' );
  4889. // Clean up the table body
  4890. tmpTable.find('tbody tr').remove();
  4891. var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
  4892. // Clone the table header and footer - we can't use the header / footer
  4893. // from the cloned table, since if scrolling is active, the table's
  4894. // real header and footer are contained in different table tags
  4895. tmpTable.find('thead, tfoot').remove();
  4896. tmpTable
  4897. .append( $(oSettings.nTHead).clone() )
  4898. .append( $(oSettings.nTFoot).clone() );
  4899. // Remove any assigned widths from the footer (from scrolling)
  4900. tmpTable.find('tfoot th, tfoot td').css('width', '');
  4901. // Apply custom sizing to the cloned header
  4902. headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
  4903. for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4904. column = columns[ visibleColumns[i] ];
  4905. headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
  4906. _fnStringToCss( column.sWidthOrig ) :
  4907. '';
  4908. // For scrollX we need to force the column width otherwise the
  4909. // browser will collapse it. If this width is smaller than the
  4910. // width the column requires, then it will have no effect
  4911. if ( column.sWidthOrig && scrollX ) {
  4912. $( headerCells[i] ).append( $('<div/>').css( {
  4913. width: column.sWidthOrig,
  4914. margin: 0,
  4915. padding: 0,
  4916. border: 0,
  4917. height: 1
  4918. } ) );
  4919. }
  4920. }
  4921. // Find the widest cell for each column and put it into the table
  4922. if ( oSettings.aoData.length ) {
  4923. for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4924. columnIdx = visibleColumns[i];
  4925. column = columns[ columnIdx ];
  4926. $( _fnGetWidestNode( oSettings, columnIdx ) )
  4927. .clone( false )
  4928. .append( column.sContentPadding )
  4929. .appendTo( tr );
  4930. }
  4931. }
  4932. // Tidy the temporary table - remove name attributes so there aren't
  4933. // duplicated in the dom (radio elements for example)
  4934. $('[name]', tmpTable).removeAttr('name');
  4935. // Table has been built, attach to the document so we can work with it.
  4936. // A holding element is used, positioned at the top of the container
  4937. // with minimal height, so it has no effect on if the container scrolls
  4938. // or not. Otherwise it might trigger scrolling when it actually isn't
  4939. // needed
  4940. var holder = $('<div/>').css( scrollX || scrollY ?
  4941. {
  4942. position: 'absolute',
  4943. top: 0,
  4944. left: 0,
  4945. height: 1,
  4946. right: 0,
  4947. overflow: 'hidden'
  4948. } :
  4949. {}
  4950. )
  4951. .append( tmpTable )
  4952. .appendTo( tableContainer );
  4953. // When scrolling (X or Y) we want to set the width of the table as
  4954. // appropriate. However, when not scrolling leave the table width as it
  4955. // is. This results in slightly different, but I think correct behaviour
  4956. if ( scrollX && scrollXInner ) {
  4957. tmpTable.width( scrollXInner );
  4958. }
  4959. else if ( scrollX ) {
  4960. tmpTable.css( 'width', 'auto' );
  4961. tmpTable.removeAttr('width');
  4962. // If there is no width attribute or style, then allow the table to
  4963. // collapse
  4964. if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
  4965. tmpTable.width( tableContainer.clientWidth );
  4966. }
  4967. }
  4968. else if ( scrollY ) {
  4969. tmpTable.width( tableContainer.clientWidth );
  4970. }
  4971. else if ( tableWidthAttr ) {
  4972. tmpTable.width( tableWidthAttr );
  4973. }
  4974. // Get the width of each column in the constructed table - we need to
  4975. // know the inner width (so it can be assigned to the other table's
  4976. // cells) and the outer width so we can calculate the full width of the
  4977. // table. This is safe since DataTables requires a unique cell for each
  4978. // column, but if ever a header can span multiple columns, this will
  4979. // need to be modified.
  4980. var total = 0;
  4981. for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4982. var cell = $(headerCells[i]);
  4983. var border = cell.outerWidth() - cell.width();
  4984. // Use getBounding... where possible (not IE8-) because it can give
  4985. // sub-pixel accuracy, which we then want to round up!
  4986. var bounding = browser.bBounding ?
  4987. Math.ceil( headerCells[i].getBoundingClientRect().width ) :
  4988. cell.outerWidth();
  4989. // Total is tracked to remove any sub-pixel errors as the outerWidth
  4990. // of the table might not equal the total given here (IE!).
  4991. total += bounding;
  4992. // Width for each column to use
  4993. columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
  4994. }
  4995. table.style.width = _fnStringToCss( total );
  4996. // Finished with the table - ditch it
  4997. holder.remove();
  4998. }
  4999. // If there is a width attr, we want to attach an event listener which
  5000. // allows the table sizing to automatically adjust when the window is
  5001. // resized. Use the width attr rather than CSS, since we can't know if the
  5002. // CSS is a relative value or absolute - DOM read is always px.
  5003. if ( tableWidthAttr ) {
  5004. table.style.width = _fnStringToCss( tableWidthAttr );
  5005. }
  5006. if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
  5007. var bindResize = function () {
  5008. $(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
  5009. _fnAdjustColumnSizing( oSettings );
  5010. } ) );
  5011. };
  5012. // IE6/7 will crash if we bind a resize event handler on page load.
  5013. // To be removed in 1.11 which drops IE6/7 support
  5014. if ( ie67 ) {
  5015. setTimeout( bindResize, 1000 );
  5016. }
  5017. else {
  5018. bindResize();
  5019. }
  5020. oSettings._reszEvt = true;
  5021. }
  5022. }
  5023. /**
  5024. * Throttle the calls to a function. Arguments and context are maintained for
  5025. * the throttled function
  5026. * @param {function} fn Function to be called
  5027. * @param {int} [freq=200] call frequency in mS
  5028. * @returns {function} wrapped function
  5029. * @memberof DataTable#oApi
  5030. */
  5031. var _fnThrottle = DataTable.util.throttle;
  5032. /**
  5033. * Convert a CSS unit width to pixels (e.g. 2em)
  5034. * @param {string} width width to be converted
  5035. * @param {node} parent parent to get the with for (required for relative widths) - optional
  5036. * @returns {int} width in pixels
  5037. * @memberof DataTable#oApi
  5038. */
  5039. function _fnConvertToWidth ( width, parent )
  5040. {
  5041. if ( ! width ) {
  5042. return 0;
  5043. }
  5044. var n = $('<div/>')
  5045. .css( 'width', _fnStringToCss( width ) )
  5046. .appendTo( parent || document.body );
  5047. var val = n[0].offsetWidth;
  5048. n.remove();
  5049. return val;
  5050. }
  5051. /**
  5052. * Get the widest node
  5053. * @param {object} settings dataTables settings object
  5054. * @param {int} colIdx column of interest
  5055. * @returns {node} widest table node
  5056. * @memberof DataTable#oApi
  5057. */
  5058. function _fnGetWidestNode( settings, colIdx )
  5059. {
  5060. var idx = _fnGetMaxLenString( settings, colIdx );
  5061. if ( idx < 0 ) {
  5062. return null;
  5063. }
  5064. var data = settings.aoData[ idx ];
  5065. return ! data.nTr ? // Might not have been created when deferred rendering
  5066. $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
  5067. data.anCells[ colIdx ];
  5068. }
  5069. /**
  5070. * Get the maximum strlen for each data column
  5071. * @param {object} settings dataTables settings object
  5072. * @param {int} colIdx column of interest
  5073. * @returns {string} max string length for each column
  5074. * @memberof DataTable#oApi
  5075. */
  5076. function _fnGetMaxLenString( settings, colIdx )
  5077. {
  5078. var s, max=-1, maxIdx = -1;
  5079. for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  5080. s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
  5081. s = s.replace( __re_html_remove, '' );
  5082. s = s.replace( /&nbsp;/g, ' ' );
  5083. if ( s.length > max ) {
  5084. max = s.length;
  5085. maxIdx = i;
  5086. }
  5087. }
  5088. return maxIdx;
  5089. }
  5090. /**
  5091. * Append a CSS unit (only if required) to a string
  5092. * @param {string} value to css-ify
  5093. * @returns {string} value with css unit
  5094. * @memberof DataTable#oApi
  5095. */
  5096. function _fnStringToCss( s )
  5097. {
  5098. if ( s === null ) {
  5099. return '0px';
  5100. }
  5101. if ( typeof s == 'number' ) {
  5102. return s < 0 ?
  5103. '0px' :
  5104. s+'px';
  5105. }
  5106. // Check it has a unit character already
  5107. return s.match(/\d$/) ?
  5108. s+'px' :
  5109. s;
  5110. }
  5111. function _fnSortFlatten ( settings )
  5112. {
  5113. var
  5114. i, iLen, k, kLen,
  5115. aSort = [],
  5116. aiOrig = [],
  5117. aoColumns = settings.aoColumns,
  5118. aDataSort, iCol, sType, srcCol,
  5119. fixed = settings.aaSortingFixed,
  5120. fixedObj = $.isPlainObject( fixed ),
  5121. nestedSort = [],
  5122. add = function ( a ) {
  5123. if ( a.length && ! Array.isArray( a[0] ) ) {
  5124. // 1D array
  5125. nestedSort.push( a );
  5126. }
  5127. else {
  5128. // 2D array
  5129. $.merge( nestedSort, a );
  5130. }
  5131. };
  5132. // Build the sort array, with pre-fix and post-fix options if they have been
  5133. // specified
  5134. if ( Array.isArray( fixed ) ) {
  5135. add( fixed );
  5136. }
  5137. if ( fixedObj && fixed.pre ) {
  5138. add( fixed.pre );
  5139. }
  5140. add( settings.aaSorting );
  5141. if (fixedObj && fixed.post ) {
  5142. add( fixed.post );
  5143. }
  5144. for ( i=0 ; i<nestedSort.length ; i++ )
  5145. {
  5146. srcCol = nestedSort[i][0];
  5147. aDataSort = aoColumns[ srcCol ].aDataSort;
  5148. for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
  5149. {
  5150. iCol = aDataSort[k];
  5151. sType = aoColumns[ iCol ].sType || 'string';
  5152. if ( nestedSort[i]._idx === undefined ) {
  5153. nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
  5154. }
  5155. aSort.push( {
  5156. src: srcCol,
  5157. col: iCol,
  5158. dir: nestedSort[i][1],
  5159. index: nestedSort[i]._idx,
  5160. type: sType,
  5161. formatter: DataTable.ext.type.order[ sType+"-pre" ]
  5162. } );
  5163. }
  5164. }
  5165. return aSort;
  5166. }
  5167. /**
  5168. * Change the order of the table
  5169. * @param {object} oSettings dataTables settings object
  5170. * @memberof DataTable#oApi
  5171. * @todo This really needs split up!
  5172. */
  5173. function _fnSort ( oSettings )
  5174. {
  5175. var
  5176. i, ien, iLen, j, jLen, k, kLen,
  5177. sDataType, nTh,
  5178. aiOrig = [],
  5179. oExtSort = DataTable.ext.type.order,
  5180. aoData = oSettings.aoData,
  5181. aoColumns = oSettings.aoColumns,
  5182. aDataSort, data, iCol, sType, oSort,
  5183. formatters = 0,
  5184. sortCol,
  5185. displayMaster = oSettings.aiDisplayMaster,
  5186. aSort;
  5187. // Resolve any column types that are unknown due to addition or invalidation
  5188. // @todo Can this be moved into a 'data-ready' handler which is called when
  5189. // data is going to be used in the table?
  5190. _fnColumnTypes( oSettings );
  5191. aSort = _fnSortFlatten( oSettings );
  5192. for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
  5193. sortCol = aSort[i];
  5194. // Track if we can use the fast sort algorithm
  5195. if ( sortCol.formatter ) {
  5196. formatters++;
  5197. }
  5198. // Load the data needed for the sort, for each cell
  5199. _fnSortData( oSettings, sortCol.col );
  5200. }
  5201. /* No sorting required if server-side or no sorting array */
  5202. if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
  5203. {
  5204. // Create a value - key array of the current row positions such that we can use their
  5205. // current position during the sort, if values match, in order to perform stable sorting
  5206. for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
  5207. aiOrig[ displayMaster[i] ] = i;
  5208. }
  5209. /* Do the sort - here we want multi-column sorting based on a given data source (column)
  5210. * and sorting function (from oSort) in a certain direction. It's reasonably complex to
  5211. * follow on it's own, but this is what we want (example two column sorting):
  5212. * fnLocalSorting = function(a,b){
  5213. * var iTest;
  5214. * iTest = oSort['string-asc']('data11', 'data12');
  5215. * if (iTest !== 0)
  5216. * return iTest;
  5217. * iTest = oSort['numeric-desc']('data21', 'data22');
  5218. * if (iTest !== 0)
  5219. * return iTest;
  5220. * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
  5221. * }
  5222. * Basically we have a test for each sorting column, if the data in that column is equal,
  5223. * test the next column. If all columns match, then we use a numeric sort on the row
  5224. * positions in the original data array to provide a stable sort.
  5225. *
  5226. * Note - I know it seems excessive to have two sorting methods, but the first is around
  5227. * 15% faster, so the second is only maintained for backwards compatibility with sorting
  5228. * methods which do not have a pre-sort formatting function.
  5229. */
  5230. if ( formatters === aSort.length ) {
  5231. // All sort types have formatting functions
  5232. displayMaster.sort( function ( a, b ) {
  5233. var
  5234. x, y, k, test, sort,
  5235. len=aSort.length,
  5236. dataA = aoData[a]._aSortData,
  5237. dataB = aoData[b]._aSortData;
  5238. for ( k=0 ; k<len ; k++ ) {
  5239. sort = aSort[k];
  5240. x = dataA[ sort.col ];
  5241. y = dataB[ sort.col ];
  5242. test = x<y ? -1 : x>y ? 1 : 0;
  5243. if ( test !== 0 ) {
  5244. return sort.dir === 'asc' ? test : -test;
  5245. }
  5246. }
  5247. x = aiOrig[a];
  5248. y = aiOrig[b];
  5249. return x<y ? -1 : x>y ? 1 : 0;
  5250. } );
  5251. }
  5252. else {
  5253. // Depreciated - remove in 1.11 (providing a plug-in option)
  5254. // Not all sort types have formatting methods, so we have to call their sorting
  5255. // methods.
  5256. displayMaster.sort( function ( a, b ) {
  5257. var
  5258. x, y, k, l, test, sort, fn,
  5259. len=aSort.length,
  5260. dataA = aoData[a]._aSortData,
  5261. dataB = aoData[b]._aSortData;
  5262. for ( k=0 ; k<len ; k++ ) {
  5263. sort = aSort[k];
  5264. x = dataA[ sort.col ];
  5265. y = dataB[ sort.col ];
  5266. fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
  5267. test = fn( x, y );
  5268. if ( test !== 0 ) {
  5269. return test;
  5270. }
  5271. }
  5272. x = aiOrig[a];
  5273. y = aiOrig[b];
  5274. return x<y ? -1 : x>y ? 1 : 0;
  5275. } );
  5276. }
  5277. }
  5278. /* Tell the draw function that we have sorted the data */
  5279. oSettings.bSorted = true;
  5280. }
  5281. function _fnSortAria ( settings )
  5282. {
  5283. var label;
  5284. var nextSort;
  5285. var columns = settings.aoColumns;
  5286. var aSort = _fnSortFlatten( settings );
  5287. var oAria = settings.oLanguage.oAria;
  5288. // ARIA attributes - need to loop all columns, to update all (removing old
  5289. // attributes as needed)
  5290. for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
  5291. {
  5292. var col = columns[i];
  5293. var asSorting = col.asSorting;
  5294. var sTitle = col.ariaTitle || col.sTitle.replace( /<.*?>/g, "" );
  5295. var th = col.nTh;
  5296. // IE7 is throwing an error when setting these properties with jQuery's
  5297. // attr() and removeAttr() methods...
  5298. th.removeAttribute('aria-sort');
  5299. /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
  5300. if ( col.bSortable ) {
  5301. if ( aSort.length > 0 && aSort[0].col == i ) {
  5302. th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
  5303. nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
  5304. }
  5305. else {
  5306. nextSort = asSorting[0];
  5307. }
  5308. label = sTitle + ( nextSort === "asc" ?
  5309. oAria.sSortAscending :
  5310. oAria.sSortDescending
  5311. );
  5312. }
  5313. else {
  5314. label = sTitle;
  5315. }
  5316. th.setAttribute('aria-label', label);
  5317. }
  5318. }
  5319. /**
  5320. * Function to run on user sort request
  5321. * @param {object} settings dataTables settings object
  5322. * @param {node} attachTo node to attach the handler to
  5323. * @param {int} colIdx column sorting index
  5324. * @param {boolean} [append=false] Append the requested sort to the existing
  5325. * sort if true (i.e. multi-column sort)
  5326. * @param {function} [callback] callback function
  5327. * @memberof DataTable#oApi
  5328. */
  5329. function _fnSortListener ( settings, colIdx, append, callback )
  5330. {
  5331. var col = settings.aoColumns[ colIdx ];
  5332. var sorting = settings.aaSorting;
  5333. var asSorting = col.asSorting;
  5334. var nextSortIdx;
  5335. var next = function ( a, overflow ) {
  5336. var idx = a._idx;
  5337. if ( idx === undefined ) {
  5338. idx = $.inArray( a[1], asSorting );
  5339. }
  5340. return idx+1 < asSorting.length ?
  5341. idx+1 :
  5342. overflow ?
  5343. null :
  5344. 0;
  5345. };
  5346. // Convert to 2D array if needed
  5347. if ( typeof sorting[0] === 'number' ) {
  5348. sorting = settings.aaSorting = [ sorting ];
  5349. }
  5350. // If appending the sort then we are multi-column sorting
  5351. if ( append && settings.oFeatures.bSortMulti ) {
  5352. // Are we already doing some kind of sort on this column?
  5353. var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
  5354. if ( sortIdx !== -1 ) {
  5355. // Yes, modify the sort
  5356. nextSortIdx = next( sorting[sortIdx], true );
  5357. if ( nextSortIdx === null && sorting.length === 1 ) {
  5358. nextSortIdx = 0; // can't remove sorting completely
  5359. }
  5360. if ( nextSortIdx === null ) {
  5361. sorting.splice( sortIdx, 1 );
  5362. }
  5363. else {
  5364. sorting[sortIdx][1] = asSorting[ nextSortIdx ];
  5365. sorting[sortIdx]._idx = nextSortIdx;
  5366. }
  5367. }
  5368. else {
  5369. // No sort on this column yet
  5370. sorting.push( [ colIdx, asSorting[0], 0 ] );
  5371. sorting[sorting.length-1]._idx = 0;
  5372. }
  5373. }
  5374. else if ( sorting.length && sorting[0][0] == colIdx ) {
  5375. // Single column - already sorting on this column, modify the sort
  5376. nextSortIdx = next( sorting[0] );
  5377. sorting.length = 1;
  5378. sorting[0][1] = asSorting[ nextSortIdx ];
  5379. sorting[0]._idx = nextSortIdx;
  5380. }
  5381. else {
  5382. // Single column - sort only on this column
  5383. sorting.length = 0;
  5384. sorting.push( [ colIdx, asSorting[0] ] );
  5385. sorting[0]._idx = 0;
  5386. }
  5387. // Run the sort by calling a full redraw
  5388. _fnReDraw( settings );
  5389. // callback used for async user interaction
  5390. if ( typeof callback == 'function' ) {
  5391. callback( settings );
  5392. }
  5393. }
  5394. /**
  5395. * Attach a sort handler (click) to a node
  5396. * @param {object} settings dataTables settings object
  5397. * @param {node} attachTo node to attach the handler to
  5398. * @param {int} colIdx column sorting index
  5399. * @param {function} [callback] callback function
  5400. * @memberof DataTable#oApi
  5401. */
  5402. function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
  5403. {
  5404. var col = settings.aoColumns[ colIdx ];
  5405. _fnBindAction( attachTo, {}, function (e) {
  5406. /* If the column is not sortable - don't to anything */
  5407. if ( col.bSortable === false ) {
  5408. return;
  5409. }
  5410. // If processing is enabled use a timeout to allow the processing
  5411. // display to be shown - otherwise to it synchronously
  5412. if ( settings.oFeatures.bProcessing ) {
  5413. _fnProcessingDisplay( settings, true );
  5414. setTimeout( function() {
  5415. _fnSortListener( settings, colIdx, e.shiftKey, callback );
  5416. // In server-side processing, the draw callback will remove the
  5417. // processing display
  5418. if ( _fnDataSource( settings ) !== 'ssp' ) {
  5419. _fnProcessingDisplay( settings, false );
  5420. }
  5421. }, 0 );
  5422. }
  5423. else {
  5424. _fnSortListener( settings, colIdx, e.shiftKey, callback );
  5425. }
  5426. } );
  5427. }
  5428. /**
  5429. * Set the sorting classes on table's body, Note: it is safe to call this function
  5430. * when bSort and bSortClasses are false
  5431. * @param {object} oSettings dataTables settings object
  5432. * @memberof DataTable#oApi
  5433. */
  5434. function _fnSortingClasses( settings )
  5435. {
  5436. var oldSort = settings.aLastSort;
  5437. var sortClass = settings.oClasses.sSortColumn;
  5438. var sort = _fnSortFlatten( settings );
  5439. var features = settings.oFeatures;
  5440. var i, ien, colIdx;
  5441. if ( features.bSort && features.bSortClasses ) {
  5442. // Remove old sorting classes
  5443. for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
  5444. colIdx = oldSort[i].src;
  5445. // Remove column sorting
  5446. $( _pluck( settings.aoData, 'anCells', colIdx ) )
  5447. .removeClass( sortClass + (i<2 ? i+1 : 3) );
  5448. }
  5449. // Add new column sorting
  5450. for ( i=0, ien=sort.length ; i<ien ; i++ ) {
  5451. colIdx = sort[i].src;
  5452. $( _pluck( settings.aoData, 'anCells', colIdx ) )
  5453. .addClass( sortClass + (i<2 ? i+1 : 3) );
  5454. }
  5455. }
  5456. settings.aLastSort = sort;
  5457. }
  5458. // Get the data to sort a column, be it from cache, fresh (populating the
  5459. // cache), or from a sort formatter
  5460. function _fnSortData( settings, idx )
  5461. {
  5462. // Custom sorting function - provided by the sort data type
  5463. var column = settings.aoColumns[ idx ];
  5464. var customSort = DataTable.ext.order[ column.sSortDataType ];
  5465. var customData;
  5466. if ( customSort ) {
  5467. customData = customSort.call( settings.oInstance, settings, idx,
  5468. _fnColumnIndexToVisible( settings, idx )
  5469. );
  5470. }
  5471. // Use / populate cache
  5472. var row, cellData;
  5473. var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
  5474. for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  5475. row = settings.aoData[i];
  5476. if ( ! row._aSortData ) {
  5477. row._aSortData = [];
  5478. }
  5479. if ( ! row._aSortData[idx] || customSort ) {
  5480. cellData = customSort ?
  5481. customData[i] : // If there was a custom sort function, use data from there
  5482. _fnGetCellData( settings, i, idx, 'sort' );
  5483. row._aSortData[ idx ] = formatter ?
  5484. formatter( cellData ) :
  5485. cellData;
  5486. }
  5487. }
  5488. }
  5489. /**
  5490. * Save the state of a table
  5491. * @param {object} oSettings dataTables settings object
  5492. * @memberof DataTable#oApi
  5493. */
  5494. function _fnSaveState ( settings )
  5495. {
  5496. if (settings._bLoadingState) {
  5497. return;
  5498. }
  5499. /* Store the interesting variables */
  5500. var state = {
  5501. time: +new Date(),
  5502. start: settings._iDisplayStart,
  5503. length: settings._iDisplayLength,
  5504. order: $.extend( true, [], settings.aaSorting ),
  5505. search: _fnSearchToCamel( settings.oPreviousSearch ),
  5506. columns: $.map( settings.aoColumns, function ( col, i ) {
  5507. return {
  5508. visible: col.bVisible,
  5509. search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
  5510. };
  5511. } )
  5512. };
  5513. settings.oSavedState = state;
  5514. _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
  5515. if ( settings.oFeatures.bStateSave && !settings.bDestroying )
  5516. {
  5517. settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
  5518. }
  5519. }
  5520. /**
  5521. * Attempt to load a saved table state
  5522. * @param {object} oSettings dataTables settings object
  5523. * @param {object} oInit DataTables init object so we can override settings
  5524. * @param {function} callback Callback to execute when the state has been loaded
  5525. * @memberof DataTable#oApi
  5526. */
  5527. function _fnLoadState ( settings, oInit, callback )
  5528. {
  5529. if ( ! settings.oFeatures.bStateSave ) {
  5530. callback();
  5531. return;
  5532. }
  5533. var loaded = function(state) {
  5534. _fnImplementState(settings, state, callback);
  5535. }
  5536. var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
  5537. if ( state !== undefined ) {
  5538. _fnImplementState( settings, state, callback );
  5539. }
  5540. // otherwise, wait for the loaded callback to be executed
  5541. return true;
  5542. }
  5543. function _fnImplementState ( settings, s, callback) {
  5544. var i, ien;
  5545. var columns = settings.aoColumns;
  5546. settings._bLoadingState = true;
  5547. // When StateRestore was introduced the state could now be implemented at any time
  5548. // Not just initialisation. To do this an api instance is required in some places
  5549. var api = settings._bInitComplete ? new DataTable.Api(settings) : null;
  5550. if ( ! s || ! s.time ) {
  5551. settings._bLoadingState = false;
  5552. callback();
  5553. return;
  5554. }
  5555. // Allow custom and plug-in manipulation functions to alter the saved data set and
  5556. // cancelling of loading by returning false
  5557. var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
  5558. if ( $.inArray( false, abStateLoad ) !== -1 ) {
  5559. settings._bLoadingState = false;
  5560. callback();
  5561. return;
  5562. }
  5563. // Reject old data
  5564. var duration = settings.iStateDuration;
  5565. if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
  5566. settings._bLoadingState = false;
  5567. callback();
  5568. return;
  5569. }
  5570. // Number of columns have changed - all bets are off, no restore of settings
  5571. if ( s.columns && columns.length !== s.columns.length ) {
  5572. settings._bLoadingState = false;
  5573. callback();
  5574. return;
  5575. }
  5576. // Store the saved state so it might be accessed at any time
  5577. settings.oLoadedState = $.extend( true, {}, s );
  5578. // Page Length
  5579. if ( s.length !== undefined ) {
  5580. // If already initialised just set the value directly so that the select element is also updated
  5581. if (api) {
  5582. api.page.len(s.length)
  5583. }
  5584. else {
  5585. settings._iDisplayLength = s.length;
  5586. }
  5587. }
  5588. // Restore key features - todo - for 1.11 this needs to be done by
  5589. // subscribed events
  5590. if ( s.start !== undefined ) {
  5591. if(api === null) {
  5592. settings._iDisplayStart = s.start;
  5593. settings.iInitDisplayStart = s.start;
  5594. }
  5595. else {
  5596. _fnPageChange(settings, s.start/settings._iDisplayLength);
  5597. }
  5598. }
  5599. // Order
  5600. if ( s.order !== undefined ) {
  5601. settings.aaSorting = [];
  5602. $.each( s.order, function ( i, col ) {
  5603. settings.aaSorting.push( col[0] >= columns.length ?
  5604. [ 0, col[1] ] :
  5605. col
  5606. );
  5607. } );
  5608. }
  5609. // Search
  5610. if ( s.search !== undefined ) {
  5611. $.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
  5612. }
  5613. // Columns
  5614. if ( s.columns ) {
  5615. for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
  5616. var col = s.columns[i];
  5617. // Visibility
  5618. if ( col.visible !== undefined ) {
  5619. // If the api is defined, the table has been initialised so we need to use it rather than internal settings
  5620. if (api) {
  5621. // Don't redraw the columns on every iteration of this loop, we will do this at the end instead
  5622. api.column(i).visible(col.visible, false);
  5623. }
  5624. else {
  5625. columns[i].bVisible = col.visible;
  5626. }
  5627. }
  5628. // Search
  5629. if ( col.search !== undefined ) {
  5630. $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
  5631. }
  5632. }
  5633. // If the api is defined then we need to adjust the columns once the visibility has been changed
  5634. if (api) {
  5635. api.columns.adjust();
  5636. }
  5637. }
  5638. settings._bLoadingState = false;
  5639. _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
  5640. callback();
  5641. };
  5642. /**
  5643. * Return the settings object for a particular table
  5644. * @param {node} table table we are using as a dataTable
  5645. * @returns {object} Settings object - or null if not found
  5646. * @memberof DataTable#oApi
  5647. */
  5648. function _fnSettingsFromNode ( table )
  5649. {
  5650. var settings = DataTable.settings;
  5651. var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
  5652. return idx !== -1 ?
  5653. settings[ idx ] :
  5654. null;
  5655. }
  5656. /**
  5657. * Log an error message
  5658. * @param {object} settings dataTables settings object
  5659. * @param {int} level log error messages, or display them to the user
  5660. * @param {string} msg error message
  5661. * @param {int} tn Technical note id to get more information about the error.
  5662. * @memberof DataTable#oApi
  5663. */
  5664. function _fnLog( settings, level, msg, tn )
  5665. {
  5666. msg = 'DataTables warning: '+
  5667. (settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
  5668. if ( tn ) {
  5669. msg += '. For more information about this error, please see '+
  5670. 'http://datatables.net/tn/'+tn;
  5671. }
  5672. if ( ! level ) {
  5673. // Backwards compatibility pre 1.10
  5674. var ext = DataTable.ext;
  5675. var type = ext.sErrMode || ext.errMode;
  5676. if ( settings ) {
  5677. _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
  5678. }
  5679. if ( type == 'alert' ) {
  5680. alert( msg );
  5681. }
  5682. else if ( type == 'throw' ) {
  5683. throw new Error(msg);
  5684. }
  5685. else if ( typeof type == 'function' ) {
  5686. type( settings, tn, msg );
  5687. }
  5688. }
  5689. else if ( window.console && console.log ) {
  5690. console.log( msg );
  5691. }
  5692. }
  5693. /**
  5694. * See if a property is defined on one object, if so assign it to the other object
  5695. * @param {object} ret target object
  5696. * @param {object} src source object
  5697. * @param {string} name property
  5698. * @param {string} [mappedName] name to map too - optional, name used if not given
  5699. * @memberof DataTable#oApi
  5700. */
  5701. function _fnMap( ret, src, name, mappedName )
  5702. {
  5703. if ( Array.isArray( name ) ) {
  5704. $.each( name, function (i, val) {
  5705. if ( Array.isArray( val ) ) {
  5706. _fnMap( ret, src, val[0], val[1] );
  5707. }
  5708. else {
  5709. _fnMap( ret, src, val );
  5710. }
  5711. } );
  5712. return;
  5713. }
  5714. if ( mappedName === undefined ) {
  5715. mappedName = name;
  5716. }
  5717. if ( src[name] !== undefined ) {
  5718. ret[mappedName] = src[name];
  5719. }
  5720. }
  5721. /**
  5722. * Extend objects - very similar to jQuery.extend, but deep copy objects, and
  5723. * shallow copy arrays. The reason we need to do this, is that we don't want to
  5724. * deep copy array init values (such as aaSorting) since the dev wouldn't be
  5725. * able to override them, but we do want to deep copy arrays.
  5726. * @param {object} out Object to extend
  5727. * @param {object} extender Object from which the properties will be applied to
  5728. * out
  5729. * @param {boolean} breakRefs If true, then arrays will be sliced to take an
  5730. * independent copy with the exception of the `data` or `aaData` parameters
  5731. * if they are present. This is so you can pass in a collection to
  5732. * DataTables and have that used as your data source without breaking the
  5733. * references
  5734. * @returns {object} out Reference, just for convenience - out === the return.
  5735. * @memberof DataTable#oApi
  5736. * @todo This doesn't take account of arrays inside the deep copied objects.
  5737. */
  5738. function _fnExtend( out, extender, breakRefs )
  5739. {
  5740. var val;
  5741. for ( var prop in extender ) {
  5742. if ( extender.hasOwnProperty(prop) ) {
  5743. val = extender[prop];
  5744. if ( $.isPlainObject( val ) ) {
  5745. if ( ! $.isPlainObject( out[prop] ) ) {
  5746. out[prop] = {};
  5747. }
  5748. $.extend( true, out[prop], val );
  5749. }
  5750. else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && Array.isArray(val) ) {
  5751. out[prop] = val.slice();
  5752. }
  5753. else {
  5754. out[prop] = val;
  5755. }
  5756. }
  5757. }
  5758. return out;
  5759. }
  5760. /**
  5761. * Bind an event handers to allow a click or return key to activate the callback.
  5762. * This is good for accessibility since a return on the keyboard will have the
  5763. * same effect as a click, if the element has focus.
  5764. * @param {element} n Element to bind the action to
  5765. * @param {object} oData Data object to pass to the triggered function
  5766. * @param {function} fn Callback function for when the event is triggered
  5767. * @memberof DataTable#oApi
  5768. */
  5769. function _fnBindAction( n, oData, fn )
  5770. {
  5771. $(n)
  5772. .on( 'click.DT', oData, function (e) {
  5773. $(n).trigger('blur'); // Remove focus outline for mouse users
  5774. fn(e);
  5775. } )
  5776. .on( 'keypress.DT', oData, function (e){
  5777. if ( e.which === 13 ) {
  5778. e.preventDefault();
  5779. fn(e);
  5780. }
  5781. } )
  5782. .on( 'selectstart.DT', function () {
  5783. /* Take the brutal approach to cancelling text selection */
  5784. return false;
  5785. } );
  5786. }
  5787. /**
  5788. * Register a callback function. Easily allows a callback function to be added to
  5789. * an array store of callback functions that can then all be called together.
  5790. * @param {object} oSettings dataTables settings object
  5791. * @param {string} sStore Name of the array storage for the callbacks in oSettings
  5792. * @param {function} fn Function to be called back
  5793. * @param {string} sName Identifying name for the callback (i.e. a label)
  5794. * @memberof DataTable#oApi
  5795. */
  5796. function _fnCallbackReg( oSettings, sStore, fn, sName )
  5797. {
  5798. if ( fn )
  5799. {
  5800. oSettings[sStore].push( {
  5801. "fn": fn,
  5802. "sName": sName
  5803. } );
  5804. }
  5805. }
  5806. /**
  5807. * Fire callback functions and trigger events. Note that the loop over the
  5808. * callback array store is done backwards! Further note that you do not want to
  5809. * fire off triggers in time sensitive applications (for example cell creation)
  5810. * as its slow.
  5811. * @param {object} settings dataTables settings object
  5812. * @param {string} callbackArr Name of the array storage for the callbacks in
  5813. * oSettings
  5814. * @param {string} eventName Name of the jQuery custom event to trigger. If
  5815. * null no trigger is fired
  5816. * @param {array} args Array of arguments to pass to the callback function /
  5817. * trigger
  5818. * @memberof DataTable#oApi
  5819. */
  5820. function _fnCallbackFire( settings, callbackArr, eventName, args )
  5821. {
  5822. var ret = [];
  5823. if ( callbackArr ) {
  5824. ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
  5825. return val.fn.apply( settings.oInstance, args );
  5826. } );
  5827. }
  5828. if ( eventName !== null ) {
  5829. var e = $.Event( eventName+'.dt' );
  5830. $(settings.nTable).trigger( e, args );
  5831. ret.push( e.result );
  5832. }
  5833. return ret;
  5834. }
  5835. function _fnLengthOverflow ( settings )
  5836. {
  5837. var
  5838. start = settings._iDisplayStart,
  5839. end = settings.fnDisplayEnd(),
  5840. len = settings._iDisplayLength;
  5841. /* If we have space to show extra rows (backing up from the end point - then do so */
  5842. if ( start >= end )
  5843. {
  5844. start = end - len;
  5845. }
  5846. // Keep the start record on the current page
  5847. start -= (start % len);
  5848. if ( len === -1 || start < 0 )
  5849. {
  5850. start = 0;
  5851. }
  5852. settings._iDisplayStart = start;
  5853. }
  5854. function _fnRenderer( settings, type )
  5855. {
  5856. var renderer = settings.renderer;
  5857. var host = DataTable.ext.renderer[type];
  5858. if ( $.isPlainObject( renderer ) && renderer[type] ) {
  5859. // Specific renderer for this type. If available use it, otherwise use
  5860. // the default.
  5861. return host[renderer[type]] || host._;
  5862. }
  5863. else if ( typeof renderer === 'string' ) {
  5864. // Common renderer - if there is one available for this type use it,
  5865. // otherwise use the default
  5866. return host[renderer] || host._;
  5867. }
  5868. // Use the default
  5869. return host._;
  5870. }
  5871. /**
  5872. * Detect the data source being used for the table. Used to simplify the code
  5873. * a little (ajax) and to make it compress a little smaller.
  5874. *
  5875. * @param {object} settings dataTables settings object
  5876. * @returns {string} Data source
  5877. * @memberof DataTable#oApi
  5878. */
  5879. function _fnDataSource ( settings )
  5880. {
  5881. if ( settings.oFeatures.bServerSide ) {
  5882. return 'ssp';
  5883. }
  5884. else if ( settings.ajax || settings.sAjaxSource ) {
  5885. return 'ajax';
  5886. }
  5887. return 'dom';
  5888. }
  5889. /**
  5890. * Computed structure of the DataTables API, defined by the options passed to
  5891. * `DataTable.Api.register()` when building the API.
  5892. *
  5893. * The structure is built in order to speed creation and extension of the Api
  5894. * objects since the extensions are effectively pre-parsed.
  5895. *
  5896. * The array is an array of objects with the following structure, where this
  5897. * base array represents the Api prototype base:
  5898. *
  5899. * [
  5900. * {
  5901. * name: 'data' -- string - Property name
  5902. * val: function () {}, -- function - Api method (or undefined if just an object
  5903. * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
  5904. * propExt: [ ... ] -- array - Array of Api object definitions to extend the property
  5905. * },
  5906. * {
  5907. * name: 'row'
  5908. * val: {},
  5909. * methodExt: [ ... ],
  5910. * propExt: [
  5911. * {
  5912. * name: 'data'
  5913. * val: function () {},
  5914. * methodExt: [ ... ],
  5915. * propExt: [ ... ]
  5916. * },
  5917. * ...
  5918. * ]
  5919. * }
  5920. * ]
  5921. *
  5922. * @type {Array}
  5923. * @ignore
  5924. */
  5925. var __apiStruct = [];
  5926. /**
  5927. * `Array.prototype` reference.
  5928. *
  5929. * @type object
  5930. * @ignore
  5931. */
  5932. var __arrayProto = Array.prototype;
  5933. /**
  5934. * Abstraction for `context` parameter of the `Api` constructor to allow it to
  5935. * take several different forms for ease of use.
  5936. *
  5937. * Each of the input parameter types will be converted to a DataTables settings
  5938. * object where possible.
  5939. *
  5940. * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one
  5941. * of:
  5942. *
  5943. * * `string` - jQuery selector. Any DataTables' matching the given selector
  5944. * with be found and used.
  5945. * * `node` - `TABLE` node which has already been formed into a DataTable.
  5946. * * `jQuery` - A jQuery object of `TABLE` nodes.
  5947. * * `object` - DataTables settings object
  5948. * * `DataTables.Api` - API instance
  5949. * @return {array|null} Matching DataTables settings objects. `null` or
  5950. * `undefined` is returned if no matching DataTable is found.
  5951. * @ignore
  5952. */
  5953. var _toSettings = function ( mixed )
  5954. {
  5955. var idx, jq;
  5956. var settings = DataTable.settings;
  5957. var tables = $.map( settings, function (el, i) {
  5958. return el.nTable;
  5959. } );
  5960. if ( ! mixed ) {
  5961. return [];
  5962. }
  5963. else if ( mixed.nTable && mixed.oApi ) {
  5964. // DataTables settings object
  5965. return [ mixed ];
  5966. }
  5967. else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
  5968. // Table node
  5969. idx = $.inArray( mixed, tables );
  5970. return idx !== -1 ? [ settings[idx] ] : null;
  5971. }
  5972. else if ( mixed && typeof mixed.settings === 'function' ) {
  5973. return mixed.settings().toArray();
  5974. }
  5975. else if ( typeof mixed === 'string' ) {
  5976. // jQuery selector
  5977. jq = $(mixed);
  5978. }
  5979. else if ( mixed instanceof $ ) {
  5980. // jQuery object (also DataTables instance)
  5981. jq = mixed;
  5982. }
  5983. if ( jq ) {
  5984. return jq.map( function(i) {
  5985. idx = $.inArray( this, tables );
  5986. return idx !== -1 ? settings[idx] : null;
  5987. } ).toArray();
  5988. }
  5989. };
  5990. /**
  5991. * DataTables API class - used to control and interface with one or more
  5992. * DataTables enhanced tables.
  5993. *
  5994. * The API class is heavily based on jQuery, presenting a chainable interface
  5995. * that you can use to interact with tables. Each instance of the API class has
  5996. * a "context" - i.e. the tables that it will operate on. This could be a single
  5997. * table, all tables on a page or a sub-set thereof.
  5998. *
  5999. * Additionally the API is designed to allow you to easily work with the data in
  6000. * the tables, retrieving and manipulating it as required. This is done by
  6001. * presenting the API class as an array like interface. The contents of the
  6002. * array depend upon the actions requested by each method (for example
  6003. * `rows().nodes()` will return an array of nodes, while `rows().data()` will
  6004. * return an array of objects or arrays depending upon your table's
  6005. * configuration). The API object has a number of array like methods (`push`,
  6006. * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
  6007. * `unique` etc) to assist your working with the data held in a table.
  6008. *
  6009. * Most methods (those which return an Api instance) are chainable, which means
  6010. * the return from a method call also has all of the methods available that the
  6011. * top level object had. For example, these two calls are equivalent:
  6012. *
  6013. * // Not chained
  6014. * api.row.add( {...} );
  6015. * api.draw();
  6016. *
  6017. * // Chained
  6018. * api.row.add( {...} ).draw();
  6019. *
  6020. * @class DataTable.Api
  6021. * @param {array|object|string|jQuery} context DataTable identifier. This is
  6022. * used to define which DataTables enhanced tables this API will operate on.
  6023. * Can be one of:
  6024. *
  6025. * * `string` - jQuery selector. Any DataTables' matching the given selector
  6026. * with be found and used.
  6027. * * `node` - `TABLE` node which has already been formed into a DataTable.
  6028. * * `jQuery` - A jQuery object of `TABLE` nodes.
  6029. * * `object` - DataTables settings object
  6030. * @param {array} [data] Data to initialise the Api instance with.
  6031. *
  6032. * @example
  6033. * // Direct initialisation during DataTables construction
  6034. * var api = $('#example').DataTable();
  6035. *
  6036. * @example
  6037. * // Initialisation using a DataTables jQuery object
  6038. * var api = $('#example').dataTable().api();
  6039. *
  6040. * @example
  6041. * // Initialisation as a constructor
  6042. * var api = new $.fn.DataTable.Api( 'table.dataTable' );
  6043. */
  6044. _Api = function ( context, data )
  6045. {
  6046. if ( ! (this instanceof _Api) ) {
  6047. return new _Api( context, data );
  6048. }
  6049. var settings = [];
  6050. var ctxSettings = function ( o ) {
  6051. var a = _toSettings( o );
  6052. if ( a ) {
  6053. settings.push.apply( settings, a );
  6054. }
  6055. };
  6056. if ( Array.isArray( context ) ) {
  6057. for ( var i=0, ien=context.length ; i<ien ; i++ ) {
  6058. ctxSettings( context[i] );
  6059. }
  6060. }
  6061. else {
  6062. ctxSettings( context );
  6063. }
  6064. // Remove duplicates
  6065. this.context = _unique( settings );
  6066. // Initial data
  6067. if ( data ) {
  6068. $.merge( this, data );
  6069. }
  6070. // selector
  6071. this.selector = {
  6072. rows: null,
  6073. cols: null,
  6074. opts: null
  6075. };
  6076. _Api.extend( this, this, __apiStruct );
  6077. };
  6078. DataTable.Api = _Api;
  6079. // Don't destroy the existing prototype, just extend it. Required for jQuery 2's
  6080. // isPlainObject.
  6081. $.extend( _Api.prototype, {
  6082. any: function ()
  6083. {
  6084. return this.count() !== 0;
  6085. },
  6086. concat: __arrayProto.concat,
  6087. context: [], // array of table settings objects
  6088. count: function ()
  6089. {
  6090. return this.flatten().length;
  6091. },
  6092. each: function ( fn )
  6093. {
  6094. for ( var i=0, ien=this.length ; i<ien; i++ ) {
  6095. fn.call( this, this[i], i, this );
  6096. }
  6097. return this;
  6098. },
  6099. eq: function ( idx )
  6100. {
  6101. var ctx = this.context;
  6102. return ctx.length > idx ?
  6103. new _Api( ctx[idx], this[idx] ) :
  6104. null;
  6105. },
  6106. filter: function ( fn )
  6107. {
  6108. var a = [];
  6109. if ( __arrayProto.filter ) {
  6110. a = __arrayProto.filter.call( this, fn, this );
  6111. }
  6112. else {
  6113. // Compatibility for browsers without EMCA-252-5 (JS 1.6)
  6114. for ( var i=0, ien=this.length ; i<ien ; i++ ) {
  6115. if ( fn.call( this, this[i], i, this ) ) {
  6116. a.push( this[i] );
  6117. }
  6118. }
  6119. }
  6120. return new _Api( this.context, a );
  6121. },
  6122. flatten: function ()
  6123. {
  6124. var a = [];
  6125. return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
  6126. },
  6127. join: __arrayProto.join,
  6128. indexOf: __arrayProto.indexOf || function (obj, start)
  6129. {
  6130. for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
  6131. if ( this[i] === obj ) {
  6132. return i;
  6133. }
  6134. }
  6135. return -1;
  6136. },
  6137. iterator: function ( flatten, type, fn, alwaysNew ) {
  6138. var
  6139. a = [], ret,
  6140. i, ien, j, jen,
  6141. context = this.context,
  6142. rows, items, item,
  6143. selector = this.selector;
  6144. // Argument shifting
  6145. if ( typeof flatten === 'string' ) {
  6146. alwaysNew = fn;
  6147. fn = type;
  6148. type = flatten;
  6149. flatten = false;
  6150. }
  6151. for ( i=0, ien=context.length ; i<ien ; i++ ) {
  6152. var apiInst = new _Api( context[i] );
  6153. if ( type === 'table' ) {
  6154. ret = fn.call( apiInst, context[i], i );
  6155. if ( ret !== undefined ) {
  6156. a.push( ret );
  6157. }
  6158. }
  6159. else if ( type === 'columns' || type === 'rows' ) {
  6160. // this has same length as context - one entry for each table
  6161. ret = fn.call( apiInst, context[i], this[i], i );
  6162. if ( ret !== undefined ) {
  6163. a.push( ret );
  6164. }
  6165. }
  6166. else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
  6167. // columns and rows share the same structure.
  6168. // 'this' is an array of column indexes for each context
  6169. items = this[i];
  6170. if ( type === 'column-rows' ) {
  6171. rows = _selector_row_indexes( context[i], selector.opts );
  6172. }
  6173. for ( j=0, jen=items.length ; j<jen ; j++ ) {
  6174. item = items[j];
  6175. if ( type === 'cell' ) {
  6176. ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
  6177. }
  6178. else {
  6179. ret = fn.call( apiInst, context[i], item, i, j, rows );
  6180. }
  6181. if ( ret !== undefined ) {
  6182. a.push( ret );
  6183. }
  6184. }
  6185. }
  6186. }
  6187. if ( a.length || alwaysNew ) {
  6188. var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
  6189. var apiSelector = api.selector;
  6190. apiSelector.rows = selector.rows;
  6191. apiSelector.cols = selector.cols;
  6192. apiSelector.opts = selector.opts;
  6193. return api;
  6194. }
  6195. return this;
  6196. },
  6197. lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
  6198. {
  6199. // Bit cheeky...
  6200. return this.indexOf.apply( this.toArray.reverse(), arguments );
  6201. },
  6202. length: 0,
  6203. map: function ( fn )
  6204. {
  6205. var a = [];
  6206. if ( __arrayProto.map ) {
  6207. a = __arrayProto.map.call( this, fn, this );
  6208. }
  6209. else {
  6210. // Compatibility for browsers without EMCA-252-5 (JS 1.6)
  6211. for ( var i=0, ien=this.length ; i<ien ; i++ ) {
  6212. a.push( fn.call( this, this[i], i ) );
  6213. }
  6214. }
  6215. return new _Api( this.context, a );
  6216. },
  6217. pluck: function ( prop )
  6218. {
  6219. let fn = DataTable.util.get(prop);
  6220. return this.map( function ( el ) {
  6221. return fn(el);
  6222. } );
  6223. },
  6224. pop: __arrayProto.pop,
  6225. push: __arrayProto.push,
  6226. // Does not return an API instance
  6227. reduce: __arrayProto.reduce || function ( fn, init )
  6228. {
  6229. return _fnReduce( this, fn, init, 0, this.length, 1 );
  6230. },
  6231. reduceRight: __arrayProto.reduceRight || function ( fn, init )
  6232. {
  6233. return _fnReduce( this, fn, init, this.length-1, -1, -1 );
  6234. },
  6235. reverse: __arrayProto.reverse,
  6236. // Object with rows, columns and opts
  6237. selector: null,
  6238. shift: __arrayProto.shift,
  6239. slice: function () {
  6240. return new _Api( this.context, this );
  6241. },
  6242. sort: __arrayProto.sort, // ? name - order?
  6243. splice: __arrayProto.splice,
  6244. toArray: function ()
  6245. {
  6246. return __arrayProto.slice.call( this );
  6247. },
  6248. to$: function ()
  6249. {
  6250. return $( this );
  6251. },
  6252. toJQuery: function ()
  6253. {
  6254. return $( this );
  6255. },
  6256. unique: function ()
  6257. {
  6258. return new _Api( this.context, _unique(this) );
  6259. },
  6260. unshift: __arrayProto.unshift
  6261. } );
  6262. _Api.extend = function ( scope, obj, ext )
  6263. {
  6264. // Only extend API instances and static properties of the API
  6265. if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
  6266. return;
  6267. }
  6268. var
  6269. i, ien,
  6270. struct,
  6271. methodScoping = function ( scope, fn, struc ) {
  6272. return function () {
  6273. var ret = fn.apply( scope, arguments );
  6274. // Method extension
  6275. _Api.extend( ret, ret, struc.methodExt );
  6276. return ret;
  6277. };
  6278. };
  6279. for ( i=0, ien=ext.length ; i<ien ; i++ ) {
  6280. struct = ext[i];
  6281. // Value
  6282. obj[ struct.name ] = struct.type === 'function' ?
  6283. methodScoping( scope, struct.val, struct ) :
  6284. struct.type === 'object' ?
  6285. {} :
  6286. struct.val;
  6287. obj[ struct.name ].__dt_wrapper = true;
  6288. // Property extension
  6289. _Api.extend( scope, obj[ struct.name ], struct.propExt );
  6290. }
  6291. };
  6292. // @todo - Is there need for an augment function?
  6293. // _Api.augment = function ( inst, name )
  6294. // {
  6295. // // Find src object in the structure from the name
  6296. // var parts = name.split('.');
  6297. // _Api.extend( inst, obj );
  6298. // };
  6299. // [
  6300. // {
  6301. // name: 'data' -- string - Property name
  6302. // val: function () {}, -- function - Api method (or undefined if just an object
  6303. // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
  6304. // propExt: [ ... ] -- array - Array of Api object definitions to extend the property
  6305. // },
  6306. // {
  6307. // name: 'row'
  6308. // val: {},
  6309. // methodExt: [ ... ],
  6310. // propExt: [
  6311. // {
  6312. // name: 'data'
  6313. // val: function () {},
  6314. // methodExt: [ ... ],
  6315. // propExt: [ ... ]
  6316. // },
  6317. // ...
  6318. // ]
  6319. // }
  6320. // ]
  6321. _Api.register = _api_register = function ( name, val )
  6322. {
  6323. if ( Array.isArray( name ) ) {
  6324. for ( var j=0, jen=name.length ; j<jen ; j++ ) {
  6325. _Api.register( name[j], val );
  6326. }
  6327. return;
  6328. }
  6329. var
  6330. i, ien,
  6331. heir = name.split('.'),
  6332. struct = __apiStruct,
  6333. key, method;
  6334. var find = function ( src, name ) {
  6335. for ( var i=0, ien=src.length ; i<ien ; i++ ) {
  6336. if ( src[i].name === name ) {
  6337. return src[i];
  6338. }
  6339. }
  6340. return null;
  6341. };
  6342. for ( i=0, ien=heir.length ; i<ien ; i++ ) {
  6343. method = heir[i].indexOf('()') !== -1;
  6344. key = method ?
  6345. heir[i].replace('()', '') :
  6346. heir[i];
  6347. var src = find( struct, key );
  6348. if ( ! src ) {
  6349. src = {
  6350. name: key,
  6351. val: {},
  6352. methodExt: [],
  6353. propExt: [],
  6354. type: 'object'
  6355. };
  6356. struct.push( src );
  6357. }
  6358. if ( i === ien-1 ) {
  6359. src.val = val;
  6360. src.type = typeof val === 'function' ?
  6361. 'function' :
  6362. $.isPlainObject( val ) ?
  6363. 'object' :
  6364. 'other';
  6365. }
  6366. else {
  6367. struct = method ?
  6368. src.methodExt :
  6369. src.propExt;
  6370. }
  6371. }
  6372. };
  6373. _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
  6374. _Api.register( pluralName, val );
  6375. _Api.register( singularName, function () {
  6376. var ret = val.apply( this, arguments );
  6377. if ( ret === this ) {
  6378. // Returned item is the API instance that was passed in, return it
  6379. return this;
  6380. }
  6381. else if ( ret instanceof _Api ) {
  6382. // New API instance returned, want the value from the first item
  6383. // in the returned array for the singular result.
  6384. return ret.length ?
  6385. Array.isArray( ret[0] ) ?
  6386. new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
  6387. ret[0] :
  6388. undefined;
  6389. }
  6390. // Non-API return - just fire it back
  6391. return ret;
  6392. } );
  6393. };
  6394. /**
  6395. * Selector for HTML tables. Apply the given selector to the give array of
  6396. * DataTables settings objects.
  6397. *
  6398. * @param {string|integer} [selector] jQuery selector string or integer
  6399. * @param {array} Array of DataTables settings objects to be filtered
  6400. * @return {array}
  6401. * @ignore
  6402. */
  6403. var __table_selector = function ( selector, a )
  6404. {
  6405. if ( Array.isArray(selector) ) {
  6406. return $.map( selector, function (item) {
  6407. return __table_selector(item, a);
  6408. } );
  6409. }
  6410. // Integer is used to pick out a table by index
  6411. if ( typeof selector === 'number' ) {
  6412. return [ a[ selector ] ];
  6413. }
  6414. // Perform a jQuery selector on the table nodes
  6415. var nodes = $.map( a, function (el, i) {
  6416. return el.nTable;
  6417. } );
  6418. return $(nodes)
  6419. .filter( selector )
  6420. .map( function (i) {
  6421. // Need to translate back from the table node to the settings
  6422. var idx = $.inArray( this, nodes );
  6423. return a[ idx ];
  6424. } )
  6425. .toArray();
  6426. };
  6427. /**
  6428. * Context selector for the API's context (i.e. the tables the API instance
  6429. * refers to.
  6430. *
  6431. * @name DataTable.Api#tables
  6432. * @param {string|integer} [selector] Selector to pick which tables the iterator
  6433. * should operate on. If not given, all tables in the current context are
  6434. * used. This can be given as a jQuery selector (for example `':gt(0)'`) to
  6435. * select multiple tables or as an integer to select a single table.
  6436. * @returns {DataTable.Api} Returns a new API instance if a selector is given.
  6437. */
  6438. _api_register( 'tables()', function ( selector ) {
  6439. // A new instance is created if there was a selector specified
  6440. return selector !== undefined && selector !== null ?
  6441. new _Api( __table_selector( selector, this.context ) ) :
  6442. this;
  6443. } );
  6444. _api_register( 'table()', function ( selector ) {
  6445. var tables = this.tables( selector );
  6446. var ctx = tables.context;
  6447. // Truncate to the first matched table
  6448. return ctx.length ?
  6449. new _Api( ctx[0] ) :
  6450. tables;
  6451. } );
  6452. _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
  6453. return this.iterator( 'table', function ( ctx ) {
  6454. return ctx.nTable;
  6455. }, 1 );
  6456. } );
  6457. _api_registerPlural( 'tables().body()', 'table().body()' , function () {
  6458. return this.iterator( 'table', function ( ctx ) {
  6459. return ctx.nTBody;
  6460. }, 1 );
  6461. } );
  6462. _api_registerPlural( 'tables().header()', 'table().header()' , function () {
  6463. return this.iterator( 'table', function ( ctx ) {
  6464. return ctx.nTHead;
  6465. }, 1 );
  6466. } );
  6467. _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
  6468. return this.iterator( 'table', function ( ctx ) {
  6469. return ctx.nTFoot;
  6470. }, 1 );
  6471. } );
  6472. _api_registerPlural( 'tables().containers()', 'table().container()' , function () {
  6473. return this.iterator( 'table', function ( ctx ) {
  6474. return ctx.nTableWrapper;
  6475. }, 1 );
  6476. } );
  6477. /**
  6478. * Redraw the tables in the current context.
  6479. */
  6480. _api_register( 'draw()', function ( paging ) {
  6481. return this.iterator( 'table', function ( settings ) {
  6482. if ( paging === 'page' ) {
  6483. _fnDraw( settings );
  6484. }
  6485. else {
  6486. if ( typeof paging === 'string' ) {
  6487. paging = paging === 'full-hold' ?
  6488. false :
  6489. true;
  6490. }
  6491. _fnReDraw( settings, paging===false );
  6492. }
  6493. } );
  6494. } );
  6495. /**
  6496. * Get the current page index.
  6497. *
  6498. * @return {integer} Current page index (zero based)
  6499. *//**
  6500. * Set the current page.
  6501. *
  6502. * Note that if you attempt to show a page which does not exist, DataTables will
  6503. * not throw an error, but rather reset the paging.
  6504. *
  6505. * @param {integer|string} action The paging action to take. This can be one of:
  6506. * * `integer` - The page index to jump to
  6507. * * `string` - An action to take:
  6508. * * `first` - Jump to first page.
  6509. * * `next` - Jump to the next page
  6510. * * `previous` - Jump to previous page
  6511. * * `last` - Jump to the last page.
  6512. * @returns {DataTables.Api} this
  6513. */
  6514. _api_register( 'page()', function ( action ) {
  6515. if ( action === undefined ) {
  6516. return this.page.info().page; // not an expensive call
  6517. }
  6518. // else, have an action to take on all tables
  6519. return this.iterator( 'table', function ( settings ) {
  6520. _fnPageChange( settings, action );
  6521. } );
  6522. } );
  6523. /**
  6524. * Paging information for the first table in the current context.
  6525. *
  6526. * If you require paging information for another table, use the `table()` method
  6527. * with a suitable selector.
  6528. *
  6529. * @return {object} Object with the following properties set:
  6530. * * `page` - Current page index (zero based - i.e. the first page is `0`)
  6531. * * `pages` - Total number of pages
  6532. * * `start` - Display index for the first record shown on the current page
  6533. * * `end` - Display index for the last record shown on the current page
  6534. * * `length` - Display length (number of records). Note that generally `start
  6535. * + length = end`, but this is not always true, for example if there are
  6536. * only 2 records to show on the final page, with a length of 10.
  6537. * * `recordsTotal` - Full data set length
  6538. * * `recordsDisplay` - Data set length once the current filtering criterion
  6539. * are applied.
  6540. */
  6541. _api_register( 'page.info()', function ( action ) {
  6542. if ( this.context.length === 0 ) {
  6543. return undefined;
  6544. }
  6545. var
  6546. settings = this.context[0],
  6547. start = settings._iDisplayStart,
  6548. len = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
  6549. visRecords = settings.fnRecordsDisplay(),
  6550. all = len === -1;
  6551. return {
  6552. "page": all ? 0 : Math.floor( start / len ),
  6553. "pages": all ? 1 : Math.ceil( visRecords / len ),
  6554. "start": start,
  6555. "end": settings.fnDisplayEnd(),
  6556. "length": len,
  6557. "recordsTotal": settings.fnRecordsTotal(),
  6558. "recordsDisplay": visRecords,
  6559. "serverSide": _fnDataSource( settings ) === 'ssp'
  6560. };
  6561. } );
  6562. /**
  6563. * Get the current page length.
  6564. *
  6565. * @return {integer} Current page length. Note `-1` indicates that all records
  6566. * are to be shown.
  6567. *//**
  6568. * Set the current page length.
  6569. *
  6570. * @param {integer} Page length to set. Use `-1` to show all records.
  6571. * @returns {DataTables.Api} this
  6572. */
  6573. _api_register( 'page.len()', function ( len ) {
  6574. // Note that we can't call this function 'length()' because `length`
  6575. // is a Javascript property of functions which defines how many arguments
  6576. // the function expects.
  6577. if ( len === undefined ) {
  6578. return this.context.length !== 0 ?
  6579. this.context[0]._iDisplayLength :
  6580. undefined;
  6581. }
  6582. // else, set the page length
  6583. return this.iterator( 'table', function ( settings ) {
  6584. _fnLengthChange( settings, len );
  6585. } );
  6586. } );
  6587. var __reload = function ( settings, holdPosition, callback ) {
  6588. // Use the draw event to trigger a callback
  6589. if ( callback ) {
  6590. var api = new _Api( settings );
  6591. api.one( 'draw', function () {
  6592. callback( api.ajax.json() );
  6593. } );
  6594. }
  6595. if ( _fnDataSource( settings ) == 'ssp' ) {
  6596. _fnReDraw( settings, holdPosition );
  6597. }
  6598. else {
  6599. _fnProcessingDisplay( settings, true );
  6600. // Cancel an existing request
  6601. var xhr = settings.jqXHR;
  6602. if ( xhr && xhr.readyState !== 4 ) {
  6603. xhr.abort();
  6604. }
  6605. // Trigger xhr
  6606. _fnBuildAjax( settings, [], function( json ) {
  6607. _fnClearTable( settings );
  6608. var data = _fnAjaxDataSrc( settings, json );
  6609. for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  6610. _fnAddData( settings, data[i] );
  6611. }
  6612. _fnReDraw( settings, holdPosition );
  6613. _fnProcessingDisplay( settings, false );
  6614. } );
  6615. }
  6616. };
  6617. /**
  6618. * Get the JSON response from the last Ajax request that DataTables made to the
  6619. * server. Note that this returns the JSON from the first table in the current
  6620. * context.
  6621. *
  6622. * @return {object} JSON received from the server.
  6623. */
  6624. _api_register( 'ajax.json()', function () {
  6625. var ctx = this.context;
  6626. if ( ctx.length > 0 ) {
  6627. return ctx[0].json;
  6628. }
  6629. // else return undefined;
  6630. } );
  6631. /**
  6632. * Get the data submitted in the last Ajax request
  6633. */
  6634. _api_register( 'ajax.params()', function () {
  6635. var ctx = this.context;
  6636. if ( ctx.length > 0 ) {
  6637. return ctx[0].oAjaxData;
  6638. }
  6639. // else return undefined;
  6640. } );
  6641. /**
  6642. * Reload tables from the Ajax data source. Note that this function will
  6643. * automatically re-draw the table when the remote data has been loaded.
  6644. *
  6645. * @param {boolean} [reset=true] Reset (default) or hold the current paging
  6646. * position. A full re-sort and re-filter is performed when this method is
  6647. * called, which is why the pagination reset is the default action.
  6648. * @returns {DataTables.Api} this
  6649. */
  6650. _api_register( 'ajax.reload()', function ( callback, resetPaging ) {
  6651. return this.iterator( 'table', function (settings) {
  6652. __reload( settings, resetPaging===false, callback );
  6653. } );
  6654. } );
  6655. /**
  6656. * Get the current Ajax URL. Note that this returns the URL from the first
  6657. * table in the current context.
  6658. *
  6659. * @return {string} Current Ajax source URL
  6660. *//**
  6661. * Set the Ajax URL. Note that this will set the URL for all tables in the
  6662. * current context.
  6663. *
  6664. * @param {string} url URL to set.
  6665. * @returns {DataTables.Api} this
  6666. */
  6667. _api_register( 'ajax.url()', function ( url ) {
  6668. var ctx = this.context;
  6669. if ( url === undefined ) {
  6670. // get
  6671. if ( ctx.length === 0 ) {
  6672. return undefined;
  6673. }
  6674. ctx = ctx[0];
  6675. return ctx.ajax ?
  6676. $.isPlainObject( ctx.ajax ) ?
  6677. ctx.ajax.url :
  6678. ctx.ajax :
  6679. ctx.sAjaxSource;
  6680. }
  6681. // set
  6682. return this.iterator( 'table', function ( settings ) {
  6683. if ( $.isPlainObject( settings.ajax ) ) {
  6684. settings.ajax.url = url;
  6685. }
  6686. else {
  6687. settings.ajax = url;
  6688. }
  6689. // No need to consider sAjaxSource here since DataTables gives priority
  6690. // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
  6691. // value of `sAjaxSource` redundant.
  6692. } );
  6693. } );
  6694. /**
  6695. * Load data from the newly set Ajax URL. Note that this method is only
  6696. * available when `ajax.url()` is used to set a URL. Additionally, this method
  6697. * has the same effect as calling `ajax.reload()` but is provided for
  6698. * convenience when setting a new URL. Like `ajax.reload()` it will
  6699. * automatically redraw the table once the remote data has been loaded.
  6700. *
  6701. * @returns {DataTables.Api} this
  6702. */
  6703. _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
  6704. // Same as a reload, but makes sense to present it for easy access after a
  6705. // url change
  6706. return this.iterator( 'table', function ( ctx ) {
  6707. __reload( ctx, resetPaging===false, callback );
  6708. } );
  6709. } );
  6710. var _selector_run = function ( type, selector, selectFn, settings, opts )
  6711. {
  6712. var
  6713. out = [], res,
  6714. a, i, ien, j, jen,
  6715. selectorType = typeof selector;
  6716. // Can't just check for isArray here, as an API or jQuery instance might be
  6717. // given with their array like look
  6718. if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
  6719. selector = [ selector ];
  6720. }
  6721. for ( i=0, ien=selector.length ; i<ien ; i++ ) {
  6722. // Only split on simple strings - complex expressions will be jQuery selectors
  6723. a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
  6724. selector[i].split(',') :
  6725. [ selector[i] ];
  6726. for ( j=0, jen=a.length ; j<jen ; j++ ) {
  6727. res = selectFn( typeof a[j] === 'string' ? (a[j]).trim() : a[j] );
  6728. if ( res && res.length ) {
  6729. out = out.concat( res );
  6730. }
  6731. }
  6732. }
  6733. // selector extensions
  6734. var ext = _ext.selector[ type ];
  6735. if ( ext.length ) {
  6736. for ( i=0, ien=ext.length ; i<ien ; i++ ) {
  6737. out = ext[i]( settings, opts, out );
  6738. }
  6739. }
  6740. return _unique( out );
  6741. };
  6742. var _selector_opts = function ( opts )
  6743. {
  6744. if ( ! opts ) {
  6745. opts = {};
  6746. }
  6747. // Backwards compatibility for 1.9- which used the terminology filter rather
  6748. // than search
  6749. if ( opts.filter && opts.search === undefined ) {
  6750. opts.search = opts.filter;
  6751. }
  6752. return $.extend( {
  6753. search: 'none',
  6754. order: 'current',
  6755. page: 'all'
  6756. }, opts );
  6757. };
  6758. var _selector_first = function ( inst )
  6759. {
  6760. // Reduce the API instance to the first item found
  6761. for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
  6762. if ( inst[i].length > 0 ) {
  6763. // Assign the first element to the first item in the instance
  6764. // and truncate the instance and context
  6765. inst[0] = inst[i];
  6766. inst[0].length = 1;
  6767. inst.length = 1;
  6768. inst.context = [ inst.context[i] ];
  6769. return inst;
  6770. }
  6771. }
  6772. // Not found - return an empty instance
  6773. inst.length = 0;
  6774. return inst;
  6775. };
  6776. var _selector_row_indexes = function ( settings, opts )
  6777. {
  6778. var
  6779. i, ien, tmp, a=[],
  6780. displayFiltered = settings.aiDisplay,
  6781. displayMaster = settings.aiDisplayMaster;
  6782. var
  6783. search = opts.search, // none, applied, removed
  6784. order = opts.order, // applied, current, index (original - compatibility with 1.9)
  6785. page = opts.page; // all, current
  6786. if ( _fnDataSource( settings ) == 'ssp' ) {
  6787. // In server-side processing mode, most options are irrelevant since
  6788. // rows not shown don't exist and the index order is the applied order
  6789. // Removed is a special case - for consistency just return an empty
  6790. // array
  6791. return search === 'removed' ?
  6792. [] :
  6793. _range( 0, displayMaster.length );
  6794. }
  6795. else if ( page == 'current' ) {
  6796. // Current page implies that order=current and filter=applied, since it is
  6797. // fairly senseless otherwise, regardless of what order and search actually
  6798. // are
  6799. for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
  6800. a.push( displayFiltered[i] );
  6801. }
  6802. }
  6803. else if ( order == 'current' || order == 'applied' ) {
  6804. if ( search == 'none') {
  6805. a = displayMaster.slice();
  6806. }
  6807. else if ( search == 'applied' ) {
  6808. a = displayFiltered.slice();
  6809. }
  6810. else if ( search == 'removed' ) {
  6811. // O(n+m) solution by creating a hash map
  6812. var displayFilteredMap = {};
  6813. for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
  6814. displayFilteredMap[displayFiltered[i]] = null;
  6815. }
  6816. a = $.map( displayMaster, function (el) {
  6817. return ! displayFilteredMap.hasOwnProperty(el) ?
  6818. el :
  6819. null;
  6820. } );
  6821. }
  6822. }
  6823. else if ( order == 'index' || order == 'original' ) {
  6824. for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  6825. if ( search == 'none' ) {
  6826. a.push( i );
  6827. }
  6828. else { // applied | removed
  6829. tmp = $.inArray( i, displayFiltered );
  6830. if ((tmp === -1 && search == 'removed') ||
  6831. (tmp >= 0 && search == 'applied') )
  6832. {
  6833. a.push( i );
  6834. }
  6835. }
  6836. }
  6837. }
  6838. return a;
  6839. };
  6840. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  6841. * Rows
  6842. *
  6843. * {} - no selector - use all available rows
  6844. * {integer} - row aoData index
  6845. * {node} - TR node
  6846. * {string} - jQuery selector to apply to the TR elements
  6847. * {array} - jQuery array of nodes, or simply an array of TR nodes
  6848. *
  6849. */
  6850. var __row_selector = function ( settings, selector, opts )
  6851. {
  6852. var rows;
  6853. var run = function ( sel ) {
  6854. var selInt = _intVal( sel );
  6855. var i, ien;
  6856. var aoData = settings.aoData;
  6857. // Short cut - selector is a number and no options provided (default is
  6858. // all records, so no need to check if the index is in there, since it
  6859. // must be - dev error if the index doesn't exist).
  6860. if ( selInt !== null && ! opts ) {
  6861. return [ selInt ];
  6862. }
  6863. if ( ! rows ) {
  6864. rows = _selector_row_indexes( settings, opts );
  6865. }
  6866. if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
  6867. // Selector - integer
  6868. return [ selInt ];
  6869. }
  6870. else if ( sel === null || sel === undefined || sel === '' ) {
  6871. // Selector - none
  6872. return rows;
  6873. }
  6874. // Selector - function
  6875. if ( typeof sel === 'function' ) {
  6876. return $.map( rows, function (idx) {
  6877. var row = aoData[ idx ];
  6878. return sel( idx, row._aData, row.nTr ) ? idx : null;
  6879. } );
  6880. }
  6881. // Selector - node
  6882. if ( sel.nodeName ) {
  6883. var rowIdx = sel._DT_RowIndex; // Property added by DT for fast lookup
  6884. var cellIdx = sel._DT_CellIndex;
  6885. if ( rowIdx !== undefined ) {
  6886. // Make sure that the row is actually still present in the table
  6887. return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
  6888. [ rowIdx ] :
  6889. [];
  6890. }
  6891. else if ( cellIdx ) {
  6892. return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel.parentNode ?
  6893. [ cellIdx.row ] :
  6894. [];
  6895. }
  6896. else {
  6897. var host = $(sel).closest('*[data-dt-row]');
  6898. return host.length ?
  6899. [ host.data('dt-row') ] :
  6900. [];
  6901. }
  6902. }
  6903. // ID selector. Want to always be able to select rows by id, regardless
  6904. // of if the tr element has been created or not, so can't rely upon
  6905. // jQuery here - hence a custom implementation. This does not match
  6906. // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
  6907. // but to select it using a CSS selector engine (like Sizzle or
  6908. // querySelect) it would need to need to be escaped for some characters.
  6909. // DataTables simplifies this for row selectors since you can select
  6910. // only a row. A # indicates an id any anything that follows is the id -
  6911. // unescaped.
  6912. if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
  6913. // get row index from id
  6914. var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
  6915. if ( rowObj !== undefined ) {
  6916. return [ rowObj.idx ];
  6917. }
  6918. // need to fall through to jQuery in case there is DOM id that
  6919. // matches
  6920. }
  6921. // Get nodes in the order from the `rows` array with null values removed
  6922. var nodes = _removeEmpty(
  6923. _pluck_order( settings.aoData, rows, 'nTr' )
  6924. );
  6925. // Selector - jQuery selector string, array of nodes or jQuery object/
  6926. // As jQuery's .filter() allows jQuery objects to be passed in filter,
  6927. // it also allows arrays, so this will cope with all three options
  6928. return $(nodes)
  6929. .filter( sel )
  6930. .map( function () {
  6931. return this._DT_RowIndex;
  6932. } )
  6933. .toArray();
  6934. };
  6935. return _selector_run( 'row', selector, run, settings, opts );
  6936. };
  6937. _api_register( 'rows()', function ( selector, opts ) {
  6938. // argument shifting
  6939. if ( selector === undefined ) {
  6940. selector = '';
  6941. }
  6942. else if ( $.isPlainObject( selector ) ) {
  6943. opts = selector;
  6944. selector = '';
  6945. }
  6946. opts = _selector_opts( opts );
  6947. var inst = this.iterator( 'table', function ( settings ) {
  6948. return __row_selector( settings, selector, opts );
  6949. }, 1 );
  6950. // Want argument shifting here and in __row_selector?
  6951. inst.selector.rows = selector;
  6952. inst.selector.opts = opts;
  6953. return inst;
  6954. } );
  6955. _api_register( 'rows().nodes()', function () {
  6956. return this.iterator( 'row', function ( settings, row ) {
  6957. return settings.aoData[ row ].nTr || undefined;
  6958. }, 1 );
  6959. } );
  6960. _api_register( 'rows().data()', function () {
  6961. return this.iterator( true, 'rows', function ( settings, rows ) {
  6962. return _pluck_order( settings.aoData, rows, '_aData' );
  6963. }, 1 );
  6964. } );
  6965. _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
  6966. return this.iterator( 'row', function ( settings, row ) {
  6967. var r = settings.aoData[ row ];
  6968. return type === 'search' ? r._aFilterData : r._aSortData;
  6969. }, 1 );
  6970. } );
  6971. _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
  6972. return this.iterator( 'row', function ( settings, row ) {
  6973. _fnInvalidate( settings, row, src );
  6974. } );
  6975. } );
  6976. _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
  6977. return this.iterator( 'row', function ( settings, row ) {
  6978. return row;
  6979. }, 1 );
  6980. } );
  6981. _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
  6982. var a = [];
  6983. var context = this.context;
  6984. // `iterator` will drop undefined values, but in this case we want them
  6985. for ( var i=0, ien=context.length ; i<ien ; i++ ) {
  6986. for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
  6987. var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
  6988. a.push( (hash === true ? '#' : '' )+ id );
  6989. }
  6990. }
  6991. return new _Api( context, a );
  6992. } );
  6993. _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
  6994. var that = this;
  6995. this.iterator( 'row', function ( settings, row, thatIdx ) {
  6996. var data = settings.aoData;
  6997. var rowData = data[ row ];
  6998. var i, ien, j, jen;
  6999. var loopRow, loopCells;
  7000. data.splice( row, 1 );
  7001. // Update the cached indexes
  7002. for ( i=0, ien=data.length ; i<ien ; i++ ) {
  7003. loopRow = data[i];
  7004. loopCells = loopRow.anCells;
  7005. // Rows
  7006. if ( loopRow.nTr !== null ) {
  7007. loopRow.nTr._DT_RowIndex = i;
  7008. }
  7009. // Cells
  7010. if ( loopCells !== null ) {
  7011. for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
  7012. loopCells[j]._DT_CellIndex.row = i;
  7013. }
  7014. }
  7015. }
  7016. // Delete from the display arrays
  7017. _fnDeleteIndex( settings.aiDisplayMaster, row );
  7018. _fnDeleteIndex( settings.aiDisplay, row );
  7019. _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
  7020. // For server-side processing tables - subtract the deleted row from the count
  7021. if ( settings._iRecordsDisplay > 0 ) {
  7022. settings._iRecordsDisplay--;
  7023. }
  7024. // Check for an 'overflow' they case for displaying the table
  7025. _fnLengthOverflow( settings );
  7026. // Remove the row's ID reference if there is one
  7027. var id = settings.rowIdFn( rowData._aData );
  7028. if ( id !== undefined ) {
  7029. delete settings.aIds[ id ];
  7030. }
  7031. } );
  7032. this.iterator( 'table', function ( settings ) {
  7033. for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  7034. settings.aoData[i].idx = i;
  7035. }
  7036. } );
  7037. return this;
  7038. } );
  7039. _api_register( 'rows.add()', function ( rows ) {
  7040. var newRows = this.iterator( 'table', function ( settings ) {
  7041. var row, i, ien;
  7042. var out = [];
  7043. for ( i=0, ien=rows.length ; i<ien ; i++ ) {
  7044. row = rows[i];
  7045. if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
  7046. out.push( _fnAddTr( settings, row )[0] );
  7047. }
  7048. else {
  7049. out.push( _fnAddData( settings, row ) );
  7050. }
  7051. }
  7052. return out;
  7053. }, 1 );
  7054. // Return an Api.rows() extended instance, so rows().nodes() etc can be used
  7055. var modRows = this.rows( -1 );
  7056. modRows.pop();
  7057. $.merge( modRows, newRows );
  7058. return modRows;
  7059. } );
  7060. /**
  7061. *
  7062. */
  7063. _api_register( 'row()', function ( selector, opts ) {
  7064. return _selector_first( this.rows( selector, opts ) );
  7065. } );
  7066. _api_register( 'row().data()', function ( data ) {
  7067. var ctx = this.context;
  7068. if ( data === undefined ) {
  7069. // Get
  7070. return ctx.length && this.length ?
  7071. ctx[0].aoData[ this[0] ]._aData :
  7072. undefined;
  7073. }
  7074. // Set
  7075. var row = ctx[0].aoData[ this[0] ];
  7076. row._aData = data;
  7077. // If the DOM has an id, and the data source is an array
  7078. if ( Array.isArray( data ) && row.nTr && row.nTr.id ) {
  7079. _fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
  7080. }
  7081. // Automatically invalidate
  7082. _fnInvalidate( ctx[0], this[0], 'data' );
  7083. return this;
  7084. } );
  7085. _api_register( 'row().node()', function () {
  7086. var ctx = this.context;
  7087. return ctx.length && this.length ?
  7088. ctx[0].aoData[ this[0] ].nTr || null :
  7089. null;
  7090. } );
  7091. _api_register( 'row.add()', function ( row ) {
  7092. // Allow a jQuery object to be passed in - only a single row is added from
  7093. // it though - the first element in the set
  7094. if ( row instanceof $ && row.length ) {
  7095. row = row[0];
  7096. }
  7097. var rows = this.iterator( 'table', function ( settings ) {
  7098. if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
  7099. return _fnAddTr( settings, row )[0];
  7100. }
  7101. return _fnAddData( settings, row );
  7102. } );
  7103. // Return an Api.rows() extended instance, with the newly added row selected
  7104. return this.row( rows[0] );
  7105. } );
  7106. $(document).on('plugin-init.dt', function (e, context) {
  7107. var api = new _Api( context );
  7108. const namespace = 'on-plugin-init';
  7109. const stateSaveParamsEvent = `stateSaveParams.${namespace}`;
  7110. const destroyEvent = `destroy.${namespace}`;
  7111. api.on( stateSaveParamsEvent, function ( e, settings, d ) {
  7112. // This could be more compact with the API, but it is a lot faster as a simple
  7113. // internal loop
  7114. var idFn = settings.rowIdFn;
  7115. var data = settings.aoData;
  7116. var ids = [];
  7117. for (var i=0 ; i<data.length ; i++) {
  7118. if (data[i]._detailsShow) {
  7119. ids.push( '#' + idFn(data[i]._aData) );
  7120. }
  7121. }
  7122. d.childRows = ids;
  7123. });
  7124. api.on( destroyEvent, function () {
  7125. api.off(`${stateSaveParamsEvent} ${destroyEvent}`);
  7126. });
  7127. var loaded = api.state.loaded();
  7128. if ( loaded && loaded.childRows ) {
  7129. api
  7130. .rows( $.map(loaded.childRows, function (id){
  7131. return id.replace(/:/g, '\\:')
  7132. }) )
  7133. .every( function () {
  7134. _fnCallbackFire( context, null, 'requestChild', [ this ] )
  7135. });
  7136. }
  7137. });
  7138. var __details_add = function ( ctx, row, data, klass )
  7139. {
  7140. // Convert to array of TR elements
  7141. var rows = [];
  7142. var addRow = function ( r, k ) {
  7143. // Recursion to allow for arrays of jQuery objects
  7144. if ( Array.isArray( r ) || r instanceof $ ) {
  7145. for ( var i=0, ien=r.length ; i<ien ; i++ ) {
  7146. addRow( r[i], k );
  7147. }
  7148. return;
  7149. }
  7150. // If we get a TR element, then just add it directly - up to the dev
  7151. // to add the correct number of columns etc
  7152. if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
  7153. rows.push( r );
  7154. }
  7155. else {
  7156. // Otherwise create a row with a wrapper
  7157. var created = $('<tr><td></td></tr>').addClass( k );
  7158. $('td', created)
  7159. .addClass( k )
  7160. .html( r )
  7161. [0].colSpan = _fnVisbleColumns( ctx );
  7162. rows.push( created[0] );
  7163. }
  7164. };
  7165. addRow( data, klass );
  7166. if ( row._details ) {
  7167. row._details.detach();
  7168. }
  7169. row._details = $(rows);
  7170. // If the children were already shown, that state should be retained
  7171. if ( row._detailsShow ) {
  7172. row._details.insertAfter( row.nTr );
  7173. }
  7174. };
  7175. // Make state saving of child row details async to allow them to be batch processed
  7176. var __details_state = DataTable.util.throttle(
  7177. function (ctx) {
  7178. _fnSaveState( ctx[0] )
  7179. },
  7180. 500
  7181. );
  7182. var __details_remove = function ( api, idx )
  7183. {
  7184. var ctx = api.context;
  7185. if ( ctx.length ) {
  7186. var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
  7187. if ( row && row._details ) {
  7188. row._details.remove();
  7189. row._detailsShow = undefined;
  7190. row._details = undefined;
  7191. $( row.nTr ).removeClass( 'dt-hasChild' );
  7192. __details_state( ctx );
  7193. }
  7194. }
  7195. };
  7196. var __details_display = function ( api, show ) {
  7197. var ctx = api.context;
  7198. if ( ctx.length && api.length ) {
  7199. var row = ctx[0].aoData[ api[0] ];
  7200. if ( row._details ) {
  7201. row._detailsShow = show;
  7202. if ( show ) {
  7203. row._details.insertAfter( row.nTr );
  7204. $( row.nTr ).addClass( 'dt-hasChild' );
  7205. }
  7206. else {
  7207. row._details.detach();
  7208. $( row.nTr ).removeClass( 'dt-hasChild' );
  7209. }
  7210. _fnCallbackFire( ctx[0], null, 'childRow', [ show, api.row( api[0] ) ] )
  7211. __details_events( ctx[0] );
  7212. __details_state( ctx );
  7213. }
  7214. }
  7215. };
  7216. var __details_events = function ( settings )
  7217. {
  7218. var api = new _Api( settings );
  7219. var namespace = '.dt.DT_details';
  7220. var drawEvent = 'draw'+namespace;
  7221. var colvisEvent = 'column-sizing'+namespace;
  7222. var destroyEvent = 'destroy'+namespace;
  7223. var data = settings.aoData;
  7224. api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
  7225. if ( _pluck( data, '_details' ).length > 0 ) {
  7226. // On each draw, insert the required elements into the document
  7227. api.on( drawEvent, function ( e, ctx ) {
  7228. if ( settings !== ctx ) {
  7229. return;
  7230. }
  7231. api.rows( {page:'current'} ).eq(0).each( function (idx) {
  7232. // Internal data grab
  7233. var row = data[ idx ];
  7234. if ( row._detailsShow ) {
  7235. row._details.insertAfter( row.nTr );
  7236. }
  7237. } );
  7238. } );
  7239. // Column visibility change - update the colspan
  7240. api.on( colvisEvent, function ( e, ctx, idx, vis ) {
  7241. if ( settings !== ctx ) {
  7242. return;
  7243. }
  7244. // Update the colspan for the details rows (note, only if it already has
  7245. // a colspan)
  7246. var row, visible = _fnVisbleColumns( ctx );
  7247. for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  7248. row = data[i];
  7249. if ( row._details ) {
  7250. row._details.children('td[colspan]').attr('colspan', visible );
  7251. }
  7252. }
  7253. } );
  7254. // Table destroyed - nuke any child rows
  7255. api.on( destroyEvent, function ( e, ctx ) {
  7256. if ( settings !== ctx ) {
  7257. return;
  7258. }
  7259. for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  7260. if ( data[i]._details ) {
  7261. __details_remove( api, i );
  7262. }
  7263. }
  7264. } );
  7265. }
  7266. };
  7267. // Strings for the method names to help minification
  7268. var _emp = '';
  7269. var _child_obj = _emp+'row().child';
  7270. var _child_mth = _child_obj+'()';
  7271. // data can be:
  7272. // tr
  7273. // string
  7274. // jQuery or array of any of the above
  7275. _api_register( _child_mth, function ( data, klass ) {
  7276. var ctx = this.context;
  7277. if ( data === undefined ) {
  7278. // get
  7279. return ctx.length && this.length ?
  7280. ctx[0].aoData[ this[0] ]._details :
  7281. undefined;
  7282. }
  7283. else if ( data === true ) {
  7284. // show
  7285. this.child.show();
  7286. }
  7287. else if ( data === false ) {
  7288. // remove
  7289. __details_remove( this );
  7290. }
  7291. else if ( ctx.length && this.length ) {
  7292. // set
  7293. __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
  7294. }
  7295. return this;
  7296. } );
  7297. _api_register( [
  7298. _child_obj+'.show()',
  7299. _child_mth+'.show()' // only when `child()` was called with parameters (without
  7300. ], function ( show ) { // it returns an object and this method is not executed)
  7301. __details_display( this, true );
  7302. return this;
  7303. } );
  7304. _api_register( [
  7305. _child_obj+'.hide()',
  7306. _child_mth+'.hide()' // only when `child()` was called with parameters (without
  7307. ], function () { // it returns an object and this method is not executed)
  7308. __details_display( this, false );
  7309. return this;
  7310. } );
  7311. _api_register( [
  7312. _child_obj+'.remove()',
  7313. _child_mth+'.remove()' // only when `child()` was called with parameters (without
  7314. ], function () { // it returns an object and this method is not executed)
  7315. __details_remove( this );
  7316. return this;
  7317. } );
  7318. _api_register( _child_obj+'.isShown()', function () {
  7319. var ctx = this.context;
  7320. if ( ctx.length && this.length ) {
  7321. // _detailsShown as false or undefined will fall through to return false
  7322. return ctx[0].aoData[ this[0] ]._detailsShow || false;
  7323. }
  7324. return false;
  7325. } );
  7326. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  7327. * Columns
  7328. *
  7329. * {integer} - column index (>=0 count from left, <0 count from right)
  7330. * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right)
  7331. * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right)
  7332. * "{string}:name" - column name
  7333. * "{string}" - jQuery selector on column header nodes
  7334. *
  7335. */
  7336. // can be an array of these items, comma separated list, or an array of comma
  7337. // separated lists
  7338. var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
  7339. // r1 and r2 are redundant - but it means that the parameters match for the
  7340. // iterator callback in columns().data()
  7341. var __columnData = function ( settings, column, r1, r2, rows ) {
  7342. var a = [];
  7343. for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
  7344. a.push( _fnGetCellData( settings, rows[row], column ) );
  7345. }
  7346. return a;
  7347. };
  7348. var __column_selector = function ( settings, selector, opts )
  7349. {
  7350. var
  7351. columns = settings.aoColumns,
  7352. names = _pluck( columns, 'sName' ),
  7353. nodes = _pluck( columns, 'nTh' );
  7354. var run = function ( s ) {
  7355. var selInt = _intVal( s );
  7356. // Selector - all
  7357. if ( s === '' ) {
  7358. return _range( columns.length );
  7359. }
  7360. // Selector - index
  7361. if ( selInt !== null ) {
  7362. return [ selInt >= 0 ?
  7363. selInt : // Count from left
  7364. columns.length + selInt // Count from right (+ because its a negative value)
  7365. ];
  7366. }
  7367. // Selector = function
  7368. if ( typeof s === 'function' ) {
  7369. var rows = _selector_row_indexes( settings, opts );
  7370. return $.map( columns, function (col, idx) {
  7371. return s(
  7372. idx,
  7373. __columnData( settings, idx, 0, 0, rows ),
  7374. nodes[ idx ]
  7375. ) ? idx : null;
  7376. } );
  7377. }
  7378. // jQuery or string selector
  7379. var match = typeof s === 'string' ?
  7380. s.match( __re_column_selector ) :
  7381. '';
  7382. if ( match ) {
  7383. switch( match[2] ) {
  7384. case 'visIdx':
  7385. case 'visible':
  7386. var idx = parseInt( match[1], 10 );
  7387. // Visible index given, convert to column index
  7388. if ( idx < 0 ) {
  7389. // Counting from the right
  7390. var visColumns = $.map( columns, function (col,i) {
  7391. return col.bVisible ? i : null;
  7392. } );
  7393. return [ visColumns[ visColumns.length + idx ] ];
  7394. }
  7395. // Counting from the left
  7396. return [ _fnVisibleToColumnIndex( settings, idx ) ];
  7397. case 'name':
  7398. // match by name. `names` is column index complete and in order
  7399. return $.map( names, function (name, i) {
  7400. return name === match[1] ? i : null;
  7401. } );
  7402. default:
  7403. return [];
  7404. }
  7405. }
  7406. // Cell in the table body
  7407. if ( s.nodeName && s._DT_CellIndex ) {
  7408. return [ s._DT_CellIndex.column ];
  7409. }
  7410. // jQuery selector on the TH elements for the columns
  7411. var jqResult = $( nodes )
  7412. .filter( s )
  7413. .map( function () {
  7414. return $.inArray( this, nodes ); // `nodes` is column index complete and in order
  7415. } )
  7416. .toArray();
  7417. if ( jqResult.length || ! s.nodeName ) {
  7418. return jqResult;
  7419. }
  7420. // Otherwise a node which might have a `dt-column` data attribute, or be
  7421. // a child or such an element
  7422. var host = $(s).closest('*[data-dt-column]');
  7423. return host.length ?
  7424. [ host.data('dt-column') ] :
  7425. [];
  7426. };
  7427. return _selector_run( 'column', selector, run, settings, opts );
  7428. };
  7429. var __setColumnVis = function ( settings, column, vis ) {
  7430. var
  7431. cols = settings.aoColumns,
  7432. col = cols[ column ],
  7433. data = settings.aoData,
  7434. row, cells, i, ien, tr;
  7435. // Get
  7436. if ( vis === undefined ) {
  7437. return col.bVisible;
  7438. }
  7439. // Set
  7440. // No change
  7441. if ( col.bVisible === vis ) {
  7442. return;
  7443. }
  7444. if ( vis ) {
  7445. // Insert column
  7446. // Need to decide if we should use appendChild or insertBefore
  7447. var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
  7448. for ( i=0, ien=data.length ; i<ien ; i++ ) {
  7449. tr = data[i].nTr;
  7450. cells = data[i].anCells;
  7451. if ( tr ) {
  7452. // insertBefore can act like appendChild if 2nd arg is null
  7453. tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
  7454. }
  7455. }
  7456. }
  7457. else {
  7458. // Remove column
  7459. $( _pluck( settings.aoData, 'anCells', column ) ).detach();
  7460. }
  7461. // Common actions
  7462. col.bVisible = vis;
  7463. };
  7464. _api_register( 'columns()', function ( selector, opts ) {
  7465. // argument shifting
  7466. if ( selector === undefined ) {
  7467. selector = '';
  7468. }
  7469. else if ( $.isPlainObject( selector ) ) {
  7470. opts = selector;
  7471. selector = '';
  7472. }
  7473. opts = _selector_opts( opts );
  7474. var inst = this.iterator( 'table', function ( settings ) {
  7475. return __column_selector( settings, selector, opts );
  7476. }, 1 );
  7477. // Want argument shifting here and in _row_selector?
  7478. inst.selector.cols = selector;
  7479. inst.selector.opts = opts;
  7480. return inst;
  7481. } );
  7482. _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
  7483. return this.iterator( 'column', function ( settings, column ) {
  7484. return settings.aoColumns[column].nTh;
  7485. }, 1 );
  7486. } );
  7487. _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
  7488. return this.iterator( 'column', function ( settings, column ) {
  7489. return settings.aoColumns[column].nTf;
  7490. }, 1 );
  7491. } );
  7492. _api_registerPlural( 'columns().data()', 'column().data()', function () {
  7493. return this.iterator( 'column-rows', __columnData, 1 );
  7494. } );
  7495. _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
  7496. return this.iterator( 'column', function ( settings, column ) {
  7497. return settings.aoColumns[column].mData;
  7498. }, 1 );
  7499. } );
  7500. _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
  7501. return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
  7502. return _pluck_order( settings.aoData, rows,
  7503. type === 'search' ? '_aFilterData' : '_aSortData', column
  7504. );
  7505. }, 1 );
  7506. } );
  7507. _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
  7508. return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
  7509. return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
  7510. }, 1 );
  7511. } );
  7512. _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
  7513. var that = this;
  7514. var ret = this.iterator( 'column', function ( settings, column ) {
  7515. if ( vis === undefined ) {
  7516. return settings.aoColumns[ column ].bVisible;
  7517. } // else
  7518. __setColumnVis( settings, column, vis );
  7519. } );
  7520. // Group the column visibility changes
  7521. if ( vis !== undefined ) {
  7522. this.iterator( 'table', function ( settings ) {
  7523. // Redraw the header after changes
  7524. _fnDrawHead( settings, settings.aoHeader );
  7525. _fnDrawHead( settings, settings.aoFooter );
  7526. // Update colspan for no records display. Child rows and extensions will use their own
  7527. // listeners to do this - only need to update the empty table item here
  7528. if ( ! settings.aiDisplay.length ) {
  7529. $(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
  7530. }
  7531. _fnSaveState( settings );
  7532. // Second loop once the first is done for events
  7533. that.iterator( 'column', function ( settings, column ) {
  7534. _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
  7535. } );
  7536. if ( calc === undefined || calc ) {
  7537. that.columns.adjust();
  7538. }
  7539. });
  7540. }
  7541. return ret;
  7542. } );
  7543. _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
  7544. return this.iterator( 'column', function ( settings, column ) {
  7545. return type === 'visible' ?
  7546. _fnColumnIndexToVisible( settings, column ) :
  7547. column;
  7548. }, 1 );
  7549. } );
  7550. _api_register( 'columns.adjust()', function () {
  7551. return this.iterator( 'table', function ( settings ) {
  7552. _fnAdjustColumnSizing( settings );
  7553. }, 1 );
  7554. } );
  7555. _api_register( 'column.index()', function ( type, idx ) {
  7556. if ( this.context.length !== 0 ) {
  7557. var ctx = this.context[0];
  7558. if ( type === 'fromVisible' || type === 'toData' ) {
  7559. return _fnVisibleToColumnIndex( ctx, idx );
  7560. }
  7561. else if ( type === 'fromData' || type === 'toVisible' ) {
  7562. return _fnColumnIndexToVisible( ctx, idx );
  7563. }
  7564. }
  7565. } );
  7566. _api_register( 'column()', function ( selector, opts ) {
  7567. return _selector_first( this.columns( selector, opts ) );
  7568. } );
  7569. var __cell_selector = function ( settings, selector, opts )
  7570. {
  7571. var data = settings.aoData;
  7572. var rows = _selector_row_indexes( settings, opts );
  7573. var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
  7574. var allCells = $(_flatten( [], cells ));
  7575. var row;
  7576. var columns = settings.aoColumns.length;
  7577. var a, i, ien, j, o, host;
  7578. var run = function ( s ) {
  7579. var fnSelector = typeof s === 'function';
  7580. if ( s === null || s === undefined || fnSelector ) {
  7581. // All cells and function selectors
  7582. a = [];
  7583. for ( i=0, ien=rows.length ; i<ien ; i++ ) {
  7584. row = rows[i];
  7585. for ( j=0 ; j<columns ; j++ ) {
  7586. o = {
  7587. row: row,
  7588. column: j
  7589. };
  7590. if ( fnSelector ) {
  7591. // Selector - function
  7592. host = data[ row ];
  7593. if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
  7594. a.push( o );
  7595. }
  7596. }
  7597. else {
  7598. // Selector - all
  7599. a.push( o );
  7600. }
  7601. }
  7602. }
  7603. return a;
  7604. }
  7605. // Selector - index
  7606. if ( $.isPlainObject( s ) ) {
  7607. // Valid cell index and its in the array of selectable rows
  7608. return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
  7609. [s] :
  7610. [];
  7611. }
  7612. // Selector - jQuery filtered cells
  7613. var jqResult = allCells
  7614. .filter( s )
  7615. .map( function (i, el) {
  7616. return { // use a new object, in case someone changes the values
  7617. row: el._DT_CellIndex.row,
  7618. column: el._DT_CellIndex.column
  7619. };
  7620. } )
  7621. .toArray();
  7622. if ( jqResult.length || ! s.nodeName ) {
  7623. return jqResult;
  7624. }
  7625. // Otherwise the selector is a node, and there is one last option - the
  7626. // element might be a child of an element which has dt-row and dt-column
  7627. // data attributes
  7628. host = $(s).closest('*[data-dt-row]');
  7629. return host.length ?
  7630. [ {
  7631. row: host.data('dt-row'),
  7632. column: host.data('dt-column')
  7633. } ] :
  7634. [];
  7635. };
  7636. return _selector_run( 'cell', selector, run, settings, opts );
  7637. };
  7638. _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
  7639. // Argument shifting
  7640. if ( $.isPlainObject( rowSelector ) ) {
  7641. // Indexes
  7642. if ( rowSelector.row === undefined ) {
  7643. // Selector options in first parameter
  7644. opts = rowSelector;
  7645. rowSelector = null;
  7646. }
  7647. else {
  7648. // Cell index objects in first parameter
  7649. opts = columnSelector;
  7650. columnSelector = null;
  7651. }
  7652. }
  7653. if ( $.isPlainObject( columnSelector ) ) {
  7654. opts = columnSelector;
  7655. columnSelector = null;
  7656. }
  7657. // Cell selector
  7658. if ( columnSelector === null || columnSelector === undefined ) {
  7659. return this.iterator( 'table', function ( settings ) {
  7660. return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
  7661. } );
  7662. }
  7663. // The default built in options need to apply to row and columns
  7664. var internalOpts = opts ? {
  7665. page: opts.page,
  7666. order: opts.order,
  7667. search: opts.search
  7668. } : {};
  7669. // Row + column selector
  7670. var columns = this.columns( columnSelector, internalOpts );
  7671. var rows = this.rows( rowSelector, internalOpts );
  7672. var i, ien, j, jen;
  7673. var cellsNoOpts = this.iterator( 'table', function ( settings, idx ) {
  7674. var a = [];
  7675. for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
  7676. for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
  7677. a.push( {
  7678. row: rows[idx][i],
  7679. column: columns[idx][j]
  7680. } );
  7681. }
  7682. }
  7683. return a;
  7684. }, 1 );
  7685. // There is currently only one extension which uses a cell selector extension
  7686. // It is a _major_ performance drag to run this if it isn't needed, so this is
  7687. // an extension specific check at the moment
  7688. var cells = opts && opts.selected ?
  7689. this.cells( cellsNoOpts, opts ) :
  7690. cellsNoOpts;
  7691. $.extend( cells.selector, {
  7692. cols: columnSelector,
  7693. rows: rowSelector,
  7694. opts: opts
  7695. } );
  7696. return cells;
  7697. } );
  7698. _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
  7699. return this.iterator( 'cell', function ( settings, row, column ) {
  7700. var data = settings.aoData[ row ];
  7701. return data && data.anCells ?
  7702. data.anCells[ column ] :
  7703. undefined;
  7704. }, 1 );
  7705. } );
  7706. _api_register( 'cells().data()', function () {
  7707. return this.iterator( 'cell', function ( settings, row, column ) {
  7708. return _fnGetCellData( settings, row, column );
  7709. }, 1 );
  7710. } );
  7711. _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
  7712. type = type === 'search' ? '_aFilterData' : '_aSortData';
  7713. return this.iterator( 'cell', function ( settings, row, column ) {
  7714. return settings.aoData[ row ][ type ][ column ];
  7715. }, 1 );
  7716. } );
  7717. _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
  7718. return this.iterator( 'cell', function ( settings, row, column ) {
  7719. return _fnGetCellData( settings, row, column, type );
  7720. }, 1 );
  7721. } );
  7722. _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
  7723. return this.iterator( 'cell', function ( settings, row, column ) {
  7724. return {
  7725. row: row,
  7726. column: column,
  7727. columnVisible: _fnColumnIndexToVisible( settings, column )
  7728. };
  7729. }, 1 );
  7730. } );
  7731. _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
  7732. return this.iterator( 'cell', function ( settings, row, column ) {
  7733. _fnInvalidate( settings, row, src, column );
  7734. } );
  7735. } );
  7736. _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
  7737. return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
  7738. } );
  7739. _api_register( 'cell().data()', function ( data ) {
  7740. var ctx = this.context;
  7741. var cell = this[0];
  7742. if ( data === undefined ) {
  7743. // Get
  7744. return ctx.length && cell.length ?
  7745. _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
  7746. undefined;
  7747. }
  7748. // Set
  7749. _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
  7750. _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
  7751. return this;
  7752. } );
  7753. /**
  7754. * Get current ordering (sorting) that has been applied to the table.
  7755. *
  7756. * @returns {array} 2D array containing the sorting information for the first
  7757. * table in the current context. Each element in the parent array represents
  7758. * a column being sorted upon (i.e. multi-sorting with two columns would have
  7759. * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
  7760. * the column index that the sorting condition applies to, the second is the
  7761. * direction of the sort (`desc` or `asc`) and, optionally, the third is the
  7762. * index of the sorting order from the `column.sorting` initialisation array.
  7763. *//**
  7764. * Set the ordering for the table.
  7765. *
  7766. * @param {integer} order Column index to sort upon.
  7767. * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
  7768. * @returns {DataTables.Api} this
  7769. *//**
  7770. * Set the ordering for the table.
  7771. *
  7772. * @param {array} order 1D array of sorting information to be applied.
  7773. * @param {array} [...] Optional additional sorting conditions
  7774. * @returns {DataTables.Api} this
  7775. *//**
  7776. * Set the ordering for the table.
  7777. *
  7778. * @param {array} order 2D array of sorting information to be applied.
  7779. * @returns {DataTables.Api} this
  7780. */
  7781. _api_register( 'order()', function ( order, dir ) {
  7782. var ctx = this.context;
  7783. if ( order === undefined ) {
  7784. // get
  7785. return ctx.length !== 0 ?
  7786. ctx[0].aaSorting :
  7787. undefined;
  7788. }
  7789. // set
  7790. if ( typeof order === 'number' ) {
  7791. // Simple column / direction passed in
  7792. order = [ [ order, dir ] ];
  7793. }
  7794. else if ( order.length && ! Array.isArray( order[0] ) ) {
  7795. // Arguments passed in (list of 1D arrays)
  7796. order = Array.prototype.slice.call( arguments );
  7797. }
  7798. // otherwise a 2D array was passed in
  7799. return this.iterator( 'table', function ( settings ) {
  7800. settings.aaSorting = order.slice();
  7801. } );
  7802. } );
  7803. /**
  7804. * Attach a sort listener to an element for a given column
  7805. *
  7806. * @param {node|jQuery|string} node Identifier for the element(s) to attach the
  7807. * listener to. This can take the form of a single DOM node, a jQuery
  7808. * collection of nodes or a jQuery selector which will identify the node(s).
  7809. * @param {integer} column the column that a click on this node will sort on
  7810. * @param {function} [callback] callback function when sort is run
  7811. * @returns {DataTables.Api} this
  7812. */
  7813. _api_register( 'order.listener()', function ( node, column, callback ) {
  7814. return this.iterator( 'table', function ( settings ) {
  7815. _fnSortAttachListener( settings, node, column, callback );
  7816. } );
  7817. } );
  7818. _api_register( 'order.fixed()', function ( set ) {
  7819. if ( ! set ) {
  7820. var ctx = this.context;
  7821. var fixed = ctx.length ?
  7822. ctx[0].aaSortingFixed :
  7823. undefined;
  7824. return Array.isArray( fixed ) ?
  7825. { pre: fixed } :
  7826. fixed;
  7827. }
  7828. return this.iterator( 'table', function ( settings ) {
  7829. settings.aaSortingFixed = $.extend( true, {}, set );
  7830. } );
  7831. } );
  7832. // Order by the selected column(s)
  7833. _api_register( [
  7834. 'columns().order()',
  7835. 'column().order()'
  7836. ], function ( dir ) {
  7837. var that = this;
  7838. return this.iterator( 'table', function ( settings, i ) {
  7839. var sort = [];
  7840. $.each( that[i], function (j, col) {
  7841. sort.push( [ col, dir ] );
  7842. } );
  7843. settings.aaSorting = sort;
  7844. } );
  7845. } );
  7846. _api_register( 'search()', function ( input, regex, smart, caseInsen ) {
  7847. var ctx = this.context;
  7848. if ( input === undefined ) {
  7849. // get
  7850. return ctx.length !== 0 ?
  7851. ctx[0].oPreviousSearch.sSearch :
  7852. undefined;
  7853. }
  7854. // set
  7855. return this.iterator( 'table', function ( settings ) {
  7856. if ( ! settings.oFeatures.bFilter ) {
  7857. return;
  7858. }
  7859. _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
  7860. "sSearch": input+"",
  7861. "bRegex": regex === null ? false : regex,
  7862. "bSmart": smart === null ? true : smart,
  7863. "bCaseInsensitive": caseInsen === null ? true : caseInsen
  7864. } ), 1 );
  7865. } );
  7866. } );
  7867. _api_registerPlural(
  7868. 'columns().search()',
  7869. 'column().search()',
  7870. function ( input, regex, smart, caseInsen ) {
  7871. return this.iterator( 'column', function ( settings, column ) {
  7872. var preSearch = settings.aoPreSearchCols;
  7873. if ( input === undefined ) {
  7874. // get
  7875. return preSearch[ column ].sSearch;
  7876. }
  7877. // set
  7878. if ( ! settings.oFeatures.bFilter ) {
  7879. return;
  7880. }
  7881. $.extend( preSearch[ column ], {
  7882. "sSearch": input+"",
  7883. "bRegex": regex === null ? false : regex,
  7884. "bSmart": smart === null ? true : smart,
  7885. "bCaseInsensitive": caseInsen === null ? true : caseInsen
  7886. } );
  7887. _fnFilterComplete( settings, settings.oPreviousSearch, 1 );
  7888. } );
  7889. }
  7890. );
  7891. /*
  7892. * State API methods
  7893. */
  7894. _api_register( 'state()', function () {
  7895. return this.context.length ?
  7896. this.context[0].oSavedState :
  7897. null;
  7898. } );
  7899. _api_register( 'state.clear()', function () {
  7900. return this.iterator( 'table', function ( settings ) {
  7901. // Save an empty object
  7902. settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
  7903. } );
  7904. } );
  7905. _api_register( 'state.loaded()', function () {
  7906. return this.context.length ?
  7907. this.context[0].oLoadedState :
  7908. null;
  7909. } );
  7910. _api_register( 'state.save()', function () {
  7911. return this.iterator( 'table', function ( settings ) {
  7912. _fnSaveState( settings );
  7913. } );
  7914. } );
  7915. /**
  7916. * Provide a common method for plug-ins to check the version of DataTables being
  7917. * used, in order to ensure compatibility.
  7918. *
  7919. * @param {string} version Version string to check for, in the format "X.Y.Z".
  7920. * Note that the formats "X" and "X.Y" are also acceptable.
  7921. * @returns {boolean} true if this version of DataTables is greater or equal to
  7922. * the required version, or false if this version of DataTales is not
  7923. * suitable
  7924. * @static
  7925. * @dtopt API-Static
  7926. *
  7927. * @example
  7928. * alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
  7929. */
  7930. DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
  7931. {
  7932. var aThis = DataTable.version.split('.');
  7933. var aThat = version.split('.');
  7934. var iThis, iThat;
  7935. for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
  7936. iThis = parseInt( aThis[i], 10 ) || 0;
  7937. iThat = parseInt( aThat[i], 10 ) || 0;
  7938. // Parts are the same, keep comparing
  7939. if (iThis === iThat) {
  7940. continue;
  7941. }
  7942. // Parts are different, return immediately
  7943. return iThis > iThat;
  7944. }
  7945. return true;
  7946. };
  7947. /**
  7948. * Check if a `<table>` node is a DataTable table already or not.
  7949. *
  7950. * @param {node|jquery|string} table Table node, jQuery object or jQuery
  7951. * selector for the table to test. Note that if more than more than one
  7952. * table is passed on, only the first will be checked
  7953. * @returns {boolean} true the table given is a DataTable, or false otherwise
  7954. * @static
  7955. * @dtopt API-Static
  7956. *
  7957. * @example
  7958. * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
  7959. * $('#example').dataTable();
  7960. * }
  7961. */
  7962. DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
  7963. {
  7964. var t = $(table).get(0);
  7965. var is = false;
  7966. if ( table instanceof DataTable.Api ) {
  7967. return true;
  7968. }
  7969. $.each( DataTable.settings, function (i, o) {
  7970. var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
  7971. var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
  7972. if ( o.nTable === t || head === t || foot === t ) {
  7973. is = true;
  7974. }
  7975. } );
  7976. return is;
  7977. };
  7978. /**
  7979. * Get all DataTable tables that have been initialised - optionally you can
  7980. * select to get only currently visible tables.
  7981. *
  7982. * @param {boolean} [visible=false] Flag to indicate if you want all (default)
  7983. * or visible tables only.
  7984. * @returns {array} Array of `table` nodes (not DataTable instances) which are
  7985. * DataTables
  7986. * @static
  7987. * @dtopt API-Static
  7988. *
  7989. * @example
  7990. * $.each( $.fn.dataTable.tables(true), function () {
  7991. * $(table).DataTable().columns.adjust();
  7992. * } );
  7993. */
  7994. DataTable.tables = DataTable.fnTables = function ( visible )
  7995. {
  7996. var api = false;
  7997. if ( $.isPlainObject( visible ) ) {
  7998. api = visible.api;
  7999. visible = visible.visible;
  8000. }
  8001. var a = $.map( DataTable.settings, function (o) {
  8002. if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
  8003. return o.nTable;
  8004. }
  8005. } );
  8006. return api ?
  8007. new _Api( a ) :
  8008. a;
  8009. };
  8010. /**
  8011. * Convert from camel case parameters to Hungarian notation. This is made public
  8012. * for the extensions to provide the same ability as DataTables core to accept
  8013. * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
  8014. * parameters.
  8015. *
  8016. * @param {object} src The model object which holds all parameters that can be
  8017. * mapped.
  8018. * @param {object} user The object to convert from camel case to Hungarian.
  8019. * @param {boolean} force When set to `true`, properties which already have a
  8020. * Hungarian value in the `user` object will be overwritten. Otherwise they
  8021. * won't be.
  8022. */
  8023. DataTable.camelToHungarian = _fnCamelToHungarian;
  8024. /**
  8025. *
  8026. */
  8027. _api_register( '$()', function ( selector, opts ) {
  8028. var
  8029. rows = this.rows( opts ).nodes(), // Get all rows
  8030. jqRows = $(rows);
  8031. return $( [].concat(
  8032. jqRows.filter( selector ).toArray(),
  8033. jqRows.find( selector ).toArray()
  8034. ) );
  8035. } );
  8036. // jQuery functions to operate on the tables
  8037. $.each( [ 'on', 'one', 'off' ], function (i, key) {
  8038. _api_register( key+'()', function ( /* event, handler */ ) {
  8039. var args = Array.prototype.slice.call(arguments);
  8040. // Add the `dt` namespace automatically if it isn't already present
  8041. args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
  8042. return ! e.match(/\.dt\b/) ?
  8043. e+'.dt' :
  8044. e;
  8045. } ).join( ' ' );
  8046. var inst = $( this.tables().nodes() );
  8047. inst[key].apply( inst, args );
  8048. return this;
  8049. } );
  8050. } );
  8051. _api_register( 'clear()', function () {
  8052. return this.iterator( 'table', function ( settings ) {
  8053. _fnClearTable( settings );
  8054. } );
  8055. } );
  8056. _api_register( 'settings()', function () {
  8057. return new _Api( this.context, this.context );
  8058. } );
  8059. _api_register( 'init()', function () {
  8060. var ctx = this.context;
  8061. return ctx.length ? ctx[0].oInit : null;
  8062. } );
  8063. _api_register( 'data()', function () {
  8064. return this.iterator( 'table', function ( settings ) {
  8065. return _pluck( settings.aoData, '_aData' );
  8066. } ).flatten();
  8067. } );
  8068. _api_register( 'destroy()', function ( remove ) {
  8069. remove = remove || false;
  8070. return this.iterator( 'table', function ( settings ) {
  8071. var classes = settings.oClasses;
  8072. var table = settings.nTable;
  8073. var tbody = settings.nTBody;
  8074. var thead = settings.nTHead;
  8075. var tfoot = settings.nTFoot;
  8076. var jqTable = $(table);
  8077. var jqTbody = $(tbody);
  8078. var jqWrapper = $(settings.nTableWrapper);
  8079. var rows = $.map( settings.aoData, function (r) { return r.nTr; } );
  8080. var i, ien;
  8081. // Flag to note that the table is currently being destroyed - no action
  8082. // should be taken
  8083. settings.bDestroying = true;
  8084. // Fire off the destroy callbacks for plug-ins etc
  8085. _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
  8086. // If not being removed from the document, make all columns visible
  8087. if ( ! remove ) {
  8088. new _Api( settings ).columns().visible( true );
  8089. }
  8090. // Blitz all `DT` namespaced events (these are internal events, the
  8091. // lowercase, `dt` events are user subscribed and they are responsible
  8092. // for removing them
  8093. jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
  8094. $(window).off('.DT-'+settings.sInstance);
  8095. // When scrolling we had to break the table up - restore it
  8096. if ( table != thead.parentNode ) {
  8097. jqTable.children('thead').detach();
  8098. jqTable.append( thead );
  8099. }
  8100. if ( tfoot && table != tfoot.parentNode ) {
  8101. jqTable.children('tfoot').detach();
  8102. jqTable.append( tfoot );
  8103. }
  8104. settings.aaSorting = [];
  8105. settings.aaSortingFixed = [];
  8106. _fnSortingClasses( settings );
  8107. $( rows ).removeClass( settings.asStripeClasses.join(' ') );
  8108. $('th, td', thead).removeClass( classes.sSortable+' '+
  8109. classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
  8110. );
  8111. // Add the TR elements back into the table in their original order
  8112. jqTbody.children().detach();
  8113. jqTbody.append( rows );
  8114. var orig = settings.nTableWrapper.parentNode;
  8115. // Remove the DataTables generated nodes, events and classes
  8116. var removedMethod = remove ? 'remove' : 'detach';
  8117. jqTable[ removedMethod ]();
  8118. jqWrapper[ removedMethod ]();
  8119. // If we need to reattach the table to the document
  8120. if ( ! remove && orig ) {
  8121. // insertBefore acts like appendChild if !arg[1]
  8122. orig.insertBefore( table, settings.nTableReinsertBefore );
  8123. // Restore the width of the original table - was read from the style property,
  8124. // so we can restore directly to that
  8125. jqTable
  8126. .css( 'width', settings.sDestroyWidth )
  8127. .removeClass( classes.sTable );
  8128. // If the were originally stripe classes - then we add them back here.
  8129. // Note this is not fool proof (for example if not all rows had stripe
  8130. // classes - but it's a good effort without getting carried away
  8131. ien = settings.asDestroyStripes.length;
  8132. if ( ien ) {
  8133. jqTbody.children().each( function (i) {
  8134. $(this).addClass( settings.asDestroyStripes[i % ien] );
  8135. } );
  8136. }
  8137. }
  8138. /* Remove the settings object from the settings array */
  8139. var idx = $.inArray( settings, DataTable.settings );
  8140. if ( idx !== -1 ) {
  8141. DataTable.settings.splice( idx, 1 );
  8142. }
  8143. } );
  8144. } );
  8145. // Add the `every()` method for rows, columns and cells in a compact form
  8146. $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
  8147. _api_register( type+'s().every()', function ( fn ) {
  8148. var opts = this.selector.opts;
  8149. var api = this;
  8150. return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
  8151. // Rows and columns:
  8152. // arg1 - index
  8153. // arg2 - table counter
  8154. // arg3 - loop counter
  8155. // arg4 - undefined
  8156. // Cells:
  8157. // arg1 - row index
  8158. // arg2 - column index
  8159. // arg3 - table counter
  8160. // arg4 - loop counter
  8161. fn.call(
  8162. api[ type ](
  8163. arg1,
  8164. type==='cell' ? arg2 : opts,
  8165. type==='cell' ? opts : undefined
  8166. ),
  8167. arg1, arg2, arg3, arg4
  8168. );
  8169. } );
  8170. } );
  8171. } );
  8172. // i18n method for extensions to be able to use the language object from the
  8173. // DataTable
  8174. _api_register( 'i18n()', function ( token, def, plural ) {
  8175. var ctx = this.context[0];
  8176. var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
  8177. if ( resolved === undefined ) {
  8178. resolved = def;
  8179. }
  8180. if ( plural !== undefined && $.isPlainObject( resolved ) ) {
  8181. resolved = resolved[ plural ] !== undefined ?
  8182. resolved[ plural ] :
  8183. resolved._;
  8184. }
  8185. return resolved.replace( '%d', plural ); // nb: plural might be undefined,
  8186. } );
  8187. /**
  8188. * Version string for plug-ins to check compatibility. Allowed format is
  8189. * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
  8190. * only for non-release builds. See http://semver.org/ for more information.
  8191. * @member
  8192. * @type string
  8193. * @default Version number
  8194. */
  8195. DataTable.version = "1.13.1";
  8196. /**
  8197. * Private data store, containing all of the settings objects that are
  8198. * created for the tables on a given page.
  8199. *
  8200. * Note that the `DataTable.settings` object is aliased to
  8201. * `jQuery.fn.dataTableExt` through which it may be accessed and
  8202. * manipulated, or `jQuery.fn.dataTable.settings`.
  8203. * @member
  8204. * @type array
  8205. * @default []
  8206. * @private
  8207. */
  8208. DataTable.settings = [];
  8209. /**
  8210. * Object models container, for the various models that DataTables has
  8211. * available to it. These models define the objects that are used to hold
  8212. * the active state and configuration of the table.
  8213. * @namespace
  8214. */
  8215. DataTable.models = {};
  8216. /**
  8217. * Template object for the way in which DataTables holds information about
  8218. * search information for the global filter and individual column filters.
  8219. * @namespace
  8220. */
  8221. DataTable.models.oSearch = {
  8222. /**
  8223. * Flag to indicate if the filtering should be case insensitive or not
  8224. * @type boolean
  8225. * @default true
  8226. */
  8227. "bCaseInsensitive": true,
  8228. /**
  8229. * Applied search term
  8230. * @type string
  8231. * @default <i>Empty string</i>
  8232. */
  8233. "sSearch": "",
  8234. /**
  8235. * Flag to indicate if the search term should be interpreted as a
  8236. * regular expression (true) or not (false) and therefore and special
  8237. * regex characters escaped.
  8238. * @type boolean
  8239. * @default false
  8240. */
  8241. "bRegex": false,
  8242. /**
  8243. * Flag to indicate if DataTables is to use its smart filtering or not.
  8244. * @type boolean
  8245. * @default true
  8246. */
  8247. "bSmart": true,
  8248. /**
  8249. * Flag to indicate if DataTables should only trigger a search when
  8250. * the return key is pressed.
  8251. * @type boolean
  8252. * @default false
  8253. */
  8254. "return": false
  8255. };
  8256. /**
  8257. * Template object for the way in which DataTables holds information about
  8258. * each individual row. This is the object format used for the settings
  8259. * aoData array.
  8260. * @namespace
  8261. */
  8262. DataTable.models.oRow = {
  8263. /**
  8264. * TR element for the row
  8265. * @type node
  8266. * @default null
  8267. */
  8268. "nTr": null,
  8269. /**
  8270. * Array of TD elements for each row. This is null until the row has been
  8271. * created.
  8272. * @type array nodes
  8273. * @default []
  8274. */
  8275. "anCells": null,
  8276. /**
  8277. * Data object from the original data source for the row. This is either
  8278. * an array if using the traditional form of DataTables, or an object if
  8279. * using mData options. The exact type will depend on the passed in
  8280. * data from the data source, or will be an array if using DOM a data
  8281. * source.
  8282. * @type array|object
  8283. * @default []
  8284. */
  8285. "_aData": [],
  8286. /**
  8287. * Sorting data cache - this array is ostensibly the same length as the
  8288. * number of columns (although each index is generated only as it is
  8289. * needed), and holds the data that is used for sorting each column in the
  8290. * row. We do this cache generation at the start of the sort in order that
  8291. * the formatting of the sort data need be done only once for each cell
  8292. * per sort. This array should not be read from or written to by anything
  8293. * other than the master sorting methods.
  8294. * @type array
  8295. * @default null
  8296. * @private
  8297. */
  8298. "_aSortData": null,
  8299. /**
  8300. * Per cell filtering data cache. As per the sort data cache, used to
  8301. * increase the performance of the filtering in DataTables
  8302. * @type array
  8303. * @default null
  8304. * @private
  8305. */
  8306. "_aFilterData": null,
  8307. /**
  8308. * Filtering data cache. This is the same as the cell filtering cache, but
  8309. * in this case a string rather than an array. This is easily computed with
  8310. * a join on `_aFilterData`, but is provided as a cache so the join isn't
  8311. * needed on every search (memory traded for performance)
  8312. * @type array
  8313. * @default null
  8314. * @private
  8315. */
  8316. "_sFilterRow": null,
  8317. /**
  8318. * Cache of the class name that DataTables has applied to the row, so we
  8319. * can quickly look at this variable rather than needing to do a DOM check
  8320. * on className for the nTr property.
  8321. * @type string
  8322. * @default <i>Empty string</i>
  8323. * @private
  8324. */
  8325. "_sRowStripe": "",
  8326. /**
  8327. * Denote if the original data source was from the DOM, or the data source
  8328. * object. This is used for invalidating data, so DataTables can
  8329. * automatically read data from the original source, unless uninstructed
  8330. * otherwise.
  8331. * @type string
  8332. * @default null
  8333. * @private
  8334. */
  8335. "src": null,
  8336. /**
  8337. * Index in the aoData array. This saves an indexOf lookup when we have the
  8338. * object, but want to know the index
  8339. * @type integer
  8340. * @default -1
  8341. * @private
  8342. */
  8343. "idx": -1
  8344. };
  8345. /**
  8346. * Template object for the column information object in DataTables. This object
  8347. * is held in the settings aoColumns array and contains all the information that
  8348. * DataTables needs about each individual column.
  8349. *
  8350. * Note that this object is related to {@link DataTable.defaults.column}
  8351. * but this one is the internal data store for DataTables's cache of columns.
  8352. * It should NOT be manipulated outside of DataTables. Any configuration should
  8353. * be done through the initialisation options.
  8354. * @namespace
  8355. */
  8356. DataTable.models.oColumn = {
  8357. /**
  8358. * Column index. This could be worked out on-the-fly with $.inArray, but it
  8359. * is faster to just hold it as a variable
  8360. * @type integer
  8361. * @default null
  8362. */
  8363. "idx": null,
  8364. /**
  8365. * A list of the columns that sorting should occur on when this column
  8366. * is sorted. That this property is an array allows multi-column sorting
  8367. * to be defined for a column (for example first name / last name columns
  8368. * would benefit from this). The values are integers pointing to the
  8369. * columns to be sorted on (typically it will be a single integer pointing
  8370. * at itself, but that doesn't need to be the case).
  8371. * @type array
  8372. */
  8373. "aDataSort": null,
  8374. /**
  8375. * Define the sorting directions that are applied to the column, in sequence
  8376. * as the column is repeatedly sorted upon - i.e. the first value is used
  8377. * as the sorting direction when the column if first sorted (clicked on).
  8378. * Sort it again (click again) and it will move on to the next index.
  8379. * Repeat until loop.
  8380. * @type array
  8381. */
  8382. "asSorting": null,
  8383. /**
  8384. * Flag to indicate if the column is searchable, and thus should be included
  8385. * in the filtering or not.
  8386. * @type boolean
  8387. */
  8388. "bSearchable": null,
  8389. /**
  8390. * Flag to indicate if the column is sortable or not.
  8391. * @type boolean
  8392. */
  8393. "bSortable": null,
  8394. /**
  8395. * Flag to indicate if the column is currently visible in the table or not
  8396. * @type boolean
  8397. */
  8398. "bVisible": null,
  8399. /**
  8400. * Store for manual type assignment using the `column.type` option. This
  8401. * is held in store so we can manipulate the column's `sType` property.
  8402. * @type string
  8403. * @default null
  8404. * @private
  8405. */
  8406. "_sManualType": null,
  8407. /**
  8408. * Flag to indicate if HTML5 data attributes should be used as the data
  8409. * source for filtering or sorting. True is either are.
  8410. * @type boolean
  8411. * @default false
  8412. * @private
  8413. */
  8414. "_bAttrSrc": false,
  8415. /**
  8416. * Developer definable function that is called whenever a cell is created (Ajax source,
  8417. * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  8418. * allowing you to modify the DOM element (add background colour for example) when the
  8419. * element is available.
  8420. * @type function
  8421. * @param {element} nTd The TD node that has been created
  8422. * @param {*} sData The Data for the cell
  8423. * @param {array|object} oData The data for the whole row
  8424. * @param {int} iRow The row index for the aoData data store
  8425. * @default null
  8426. */
  8427. "fnCreatedCell": null,
  8428. /**
  8429. * Function to get data from a cell in a column. You should <b>never</b>
  8430. * access data directly through _aData internally in DataTables - always use
  8431. * the method attached to this property. It allows mData to function as
  8432. * required. This function is automatically assigned by the column
  8433. * initialisation method
  8434. * @type function
  8435. * @param {array|object} oData The data array/object for the array
  8436. * (i.e. aoData[]._aData)
  8437. * @param {string} sSpecific The specific data type you want to get -
  8438. * 'display', 'type' 'filter' 'sort'
  8439. * @returns {*} The data for the cell from the given row's data
  8440. * @default null
  8441. */
  8442. "fnGetData": null,
  8443. /**
  8444. * Function to set data for a cell in the column. You should <b>never</b>
  8445. * set the data directly to _aData internally in DataTables - always use
  8446. * this method. It allows mData to function as required. This function
  8447. * is automatically assigned by the column initialisation method
  8448. * @type function
  8449. * @param {array|object} oData The data array/object for the array
  8450. * (i.e. aoData[]._aData)
  8451. * @param {*} sValue Value to set
  8452. * @default null
  8453. */
  8454. "fnSetData": null,
  8455. /**
  8456. * Property to read the value for the cells in the column from the data
  8457. * source array / object. If null, then the default content is used, if a
  8458. * function is given then the return from the function is used.
  8459. * @type function|int|string|null
  8460. * @default null
  8461. */
  8462. "mData": null,
  8463. /**
  8464. * Partner property to mData which is used (only when defined) to get
  8465. * the data - i.e. it is basically the same as mData, but without the
  8466. * 'set' option, and also the data fed to it is the result from mData.
  8467. * This is the rendering method to match the data method of mData.
  8468. * @type function|int|string|null
  8469. * @default null
  8470. */
  8471. "mRender": null,
  8472. /**
  8473. * Unique header TH/TD element for this column - this is what the sorting
  8474. * listener is attached to (if sorting is enabled.)
  8475. * @type node
  8476. * @default null
  8477. */
  8478. "nTh": null,
  8479. /**
  8480. * Unique footer TH/TD element for this column (if there is one). Not used
  8481. * in DataTables as such, but can be used for plug-ins to reference the
  8482. * footer for each column.
  8483. * @type node
  8484. * @default null
  8485. */
  8486. "nTf": null,
  8487. /**
  8488. * The class to apply to all TD elements in the table's TBODY for the column
  8489. * @type string
  8490. * @default null
  8491. */
  8492. "sClass": null,
  8493. /**
  8494. * When DataTables calculates the column widths to assign to each column,
  8495. * it finds the longest string in each column and then constructs a
  8496. * temporary table and reads the widths from that. The problem with this
  8497. * is that "mmm" is much wider then "iiii", but the latter is a longer
  8498. * string - thus the calculation can go wrong (doing it properly and putting
  8499. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  8500. * a "work around" we provide this option. It will append its value to the
  8501. * text that is found to be the longest string for the column - i.e. padding.
  8502. * @type string
  8503. */
  8504. "sContentPadding": null,
  8505. /**
  8506. * Allows a default value to be given for a column's data, and will be used
  8507. * whenever a null data source is encountered (this can be because mData
  8508. * is set to null, or because the data source itself is null).
  8509. * @type string
  8510. * @default null
  8511. */
  8512. "sDefaultContent": null,
  8513. /**
  8514. * Name for the column, allowing reference to the column by name as well as
  8515. * by index (needs a lookup to work by name).
  8516. * @type string
  8517. */
  8518. "sName": null,
  8519. /**
  8520. * Custom sorting data type - defines which of the available plug-ins in
  8521. * afnSortData the custom sorting will use - if any is defined.
  8522. * @type string
  8523. * @default std
  8524. */
  8525. "sSortDataType": 'std',
  8526. /**
  8527. * Class to be applied to the header element when sorting on this column
  8528. * @type string
  8529. * @default null
  8530. */
  8531. "sSortingClass": null,
  8532. /**
  8533. * Class to be applied to the header element when sorting on this column -
  8534. * when jQuery UI theming is used.
  8535. * @type string
  8536. * @default null
  8537. */
  8538. "sSortingClassJUI": null,
  8539. /**
  8540. * Title of the column - what is seen in the TH element (nTh).
  8541. * @type string
  8542. */
  8543. "sTitle": null,
  8544. /**
  8545. * Column sorting and filtering type
  8546. * @type string
  8547. * @default null
  8548. */
  8549. "sType": null,
  8550. /**
  8551. * Width of the column
  8552. * @type string
  8553. * @default null
  8554. */
  8555. "sWidth": null,
  8556. /**
  8557. * Width of the column when it was first "encountered"
  8558. * @type string
  8559. * @default null
  8560. */
  8561. "sWidthOrig": null
  8562. };
  8563. /*
  8564. * Developer note: The properties of the object below are given in Hungarian
  8565. * notation, that was used as the interface for DataTables prior to v1.10, however
  8566. * from v1.10 onwards the primary interface is camel case. In order to avoid
  8567. * breaking backwards compatibility utterly with this change, the Hungarian
  8568. * version is still, internally the primary interface, but is is not documented
  8569. * - hence the @name tags in each doc comment. This allows a Javascript function
  8570. * to create a map from Hungarian notation to camel case (going the other direction
  8571. * would require each property to be listed, which would add around 3K to the size
  8572. * of DataTables, while this method is about a 0.5K hit).
  8573. *
  8574. * Ultimately this does pave the way for Hungarian notation to be dropped
  8575. * completely, but that is a massive amount of work and will break current
  8576. * installs (therefore is on-hold until v2).
  8577. */
  8578. /**
  8579. * Initialisation options that can be given to DataTables at initialisation
  8580. * time.
  8581. * @namespace
  8582. */
  8583. DataTable.defaults = {
  8584. /**
  8585. * An array of data to use for the table, passed in at initialisation which
  8586. * will be used in preference to any data which is already in the DOM. This is
  8587. * particularly useful for constructing tables purely in Javascript, for
  8588. * example with a custom Ajax call.
  8589. * @type array
  8590. * @default null
  8591. *
  8592. * @dtopt Option
  8593. * @name DataTable.defaults.data
  8594. *
  8595. * @example
  8596. * // Using a 2D array data source
  8597. * $(document).ready( function () {
  8598. * $('#example').dataTable( {
  8599. * "data": [
  8600. * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
  8601. * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
  8602. * ],
  8603. * "columns": [
  8604. * { "title": "Engine" },
  8605. * { "title": "Browser" },
  8606. * { "title": "Platform" },
  8607. * { "title": "Version" },
  8608. * { "title": "Grade" }
  8609. * ]
  8610. * } );
  8611. * } );
  8612. *
  8613. * @example
  8614. * // Using an array of objects as a data source (`data`)
  8615. * $(document).ready( function () {
  8616. * $('#example').dataTable( {
  8617. * "data": [
  8618. * {
  8619. * "engine": "Trident",
  8620. * "browser": "Internet Explorer 4.0",
  8621. * "platform": "Win 95+",
  8622. * "version": 4,
  8623. * "grade": "X"
  8624. * },
  8625. * {
  8626. * "engine": "Trident",
  8627. * "browser": "Internet Explorer 5.0",
  8628. * "platform": "Win 95+",
  8629. * "version": 5,
  8630. * "grade": "C"
  8631. * }
  8632. * ],
  8633. * "columns": [
  8634. * { "title": "Engine", "data": "engine" },
  8635. * { "title": "Browser", "data": "browser" },
  8636. * { "title": "Platform", "data": "platform" },
  8637. * { "title": "Version", "data": "version" },
  8638. * { "title": "Grade", "data": "grade" }
  8639. * ]
  8640. * } );
  8641. * } );
  8642. */
  8643. "aaData": null,
  8644. /**
  8645. * If ordering is enabled, then DataTables will perform a first pass sort on
  8646. * initialisation. You can define which column(s) the sort is performed
  8647. * upon, and the sorting direction, with this variable. The `sorting` array
  8648. * should contain an array for each column to be sorted initially containing
  8649. * the column's index and a direction string ('asc' or 'desc').
  8650. * @type array
  8651. * @default [[0,'asc']]
  8652. *
  8653. * @dtopt Option
  8654. * @name DataTable.defaults.order
  8655. *
  8656. * @example
  8657. * // Sort by 3rd column first, and then 4th column
  8658. * $(document).ready( function() {
  8659. * $('#example').dataTable( {
  8660. * "order": [[2,'asc'], [3,'desc']]
  8661. * } );
  8662. * } );
  8663. *
  8664. * // No initial sorting
  8665. * $(document).ready( function() {
  8666. * $('#example').dataTable( {
  8667. * "order": []
  8668. * } );
  8669. * } );
  8670. */
  8671. "aaSorting": [[0,'asc']],
  8672. /**
  8673. * This parameter is basically identical to the `sorting` parameter, but
  8674. * cannot be overridden by user interaction with the table. What this means
  8675. * is that you could have a column (visible or hidden) which the sorting
  8676. * will always be forced on first - any sorting after that (from the user)
  8677. * will then be performed as required. This can be useful for grouping rows
  8678. * together.
  8679. * @type array
  8680. * @default null
  8681. *
  8682. * @dtopt Option
  8683. * @name DataTable.defaults.orderFixed
  8684. *
  8685. * @example
  8686. * $(document).ready( function() {
  8687. * $('#example').dataTable( {
  8688. * "orderFixed": [[0,'asc']]
  8689. * } );
  8690. * } )
  8691. */
  8692. "aaSortingFixed": [],
  8693. /**
  8694. * DataTables can be instructed to load data to display in the table from a
  8695. * Ajax source. This option defines how that Ajax call is made and where to.
  8696. *
  8697. * The `ajax` property has three different modes of operation, depending on
  8698. * how it is defined. These are:
  8699. *
  8700. * * `string` - Set the URL from where the data should be loaded from.
  8701. * * `object` - Define properties for `jQuery.ajax`.
  8702. * * `function` - Custom data get function
  8703. *
  8704. * `string`
  8705. * --------
  8706. *
  8707. * As a string, the `ajax` property simply defines the URL from which
  8708. * DataTables will load data.
  8709. *
  8710. * `object`
  8711. * --------
  8712. *
  8713. * As an object, the parameters in the object are passed to
  8714. * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
  8715. * of the Ajax request. DataTables has a number of default parameters which
  8716. * you can override using this option. Please refer to the jQuery
  8717. * documentation for a full description of the options available, although
  8718. * the following parameters provide additional options in DataTables or
  8719. * require special consideration:
  8720. *
  8721. * * `data` - As with jQuery, `data` can be provided as an object, but it
  8722. * can also be used as a function to manipulate the data DataTables sends
  8723. * to the server. The function takes a single parameter, an object of
  8724. * parameters with the values that DataTables has readied for sending. An
  8725. * object may be returned which will be merged into the DataTables
  8726. * defaults, or you can add the items to the object that was passed in and
  8727. * not return anything from the function. This supersedes `fnServerParams`
  8728. * from DataTables 1.9-.
  8729. *
  8730. * * `dataSrc` - By default DataTables will look for the property `data` (or
  8731. * `aaData` for compatibility with DataTables 1.9-) when obtaining data
  8732. * from an Ajax source or for server-side processing - this parameter
  8733. * allows that property to be changed. You can use Javascript dotted
  8734. * object notation to get a data source for multiple levels of nesting, or
  8735. * it my be used as a function. As a function it takes a single parameter,
  8736. * the JSON returned from the server, which can be manipulated as
  8737. * required, with the returned value being that used by DataTables as the
  8738. * data source for the table. This supersedes `sAjaxDataProp` from
  8739. * DataTables 1.9-.
  8740. *
  8741. * * `success` - Should not be overridden it is used internally in
  8742. * DataTables. To manipulate / transform the data returned by the server
  8743. * use `ajax.dataSrc`, or use `ajax` as a function (see below).
  8744. *
  8745. * `function`
  8746. * ----------
  8747. *
  8748. * As a function, making the Ajax call is left up to yourself allowing
  8749. * complete control of the Ajax request. Indeed, if desired, a method other
  8750. * than Ajax could be used to obtain the required data, such as Web storage
  8751. * or an AIR database.
  8752. *
  8753. * The function is given four parameters and no return is required. The
  8754. * parameters are:
  8755. *
  8756. * 1. _object_ - Data to send to the server
  8757. * 2. _function_ - Callback function that must be executed when the required
  8758. * data has been obtained. That data should be passed into the callback
  8759. * as the only parameter
  8760. * 3. _object_ - DataTables settings object for the table
  8761. *
  8762. * Note that this supersedes `fnServerData` from DataTables 1.9-.
  8763. *
  8764. * @type string|object|function
  8765. * @default null
  8766. *
  8767. * @dtopt Option
  8768. * @name DataTable.defaults.ajax
  8769. * @since 1.10.0
  8770. *
  8771. * @example
  8772. * // Get JSON data from a file via Ajax.
  8773. * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
  8774. * $('#example').dataTable( {
  8775. * "ajax": "data.json"
  8776. * } );
  8777. *
  8778. * @example
  8779. * // Get JSON data from a file via Ajax, using `dataSrc` to change
  8780. * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
  8781. * $('#example').dataTable( {
  8782. * "ajax": {
  8783. * "url": "data.json",
  8784. * "dataSrc": "tableData"
  8785. * }
  8786. * } );
  8787. *
  8788. * @example
  8789. * // Get JSON data from a file via Ajax, using `dataSrc` to read data
  8790. * // from a plain array rather than an array in an object
  8791. * $('#example').dataTable( {
  8792. * "ajax": {
  8793. * "url": "data.json",
  8794. * "dataSrc": ""
  8795. * }
  8796. * } );
  8797. *
  8798. * @example
  8799. * // Manipulate the data returned from the server - add a link to data
  8800. * // (note this can, should, be done using `render` for the column - this
  8801. * // is just a simple example of how the data can be manipulated).
  8802. * $('#example').dataTable( {
  8803. * "ajax": {
  8804. * "url": "data.json",
  8805. * "dataSrc": function ( json ) {
  8806. * for ( var i=0, ien=json.length ; i<ien ; i++ ) {
  8807. * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
  8808. * }
  8809. * return json;
  8810. * }
  8811. * }
  8812. * } );
  8813. *
  8814. * @example
  8815. * // Add data to the request
  8816. * $('#example').dataTable( {
  8817. * "ajax": {
  8818. * "url": "data.json",
  8819. * "data": function ( d ) {
  8820. * return {
  8821. * "extra_search": $('#extra').val()
  8822. * };
  8823. * }
  8824. * }
  8825. * } );
  8826. *
  8827. * @example
  8828. * // Send request as POST
  8829. * $('#example').dataTable( {
  8830. * "ajax": {
  8831. * "url": "data.json",
  8832. * "type": "POST"
  8833. * }
  8834. * } );
  8835. *
  8836. * @example
  8837. * // Get the data from localStorage (could interface with a form for
  8838. * // adding, editing and removing rows).
  8839. * $('#example').dataTable( {
  8840. * "ajax": function (data, callback, settings) {
  8841. * callback(
  8842. * JSON.parse( localStorage.getItem('dataTablesData') )
  8843. * );
  8844. * }
  8845. * } );
  8846. */
  8847. "ajax": null,
  8848. /**
  8849. * This parameter allows you to readily specify the entries in the length drop
  8850. * down menu that DataTables shows when pagination is enabled. It can be
  8851. * either a 1D array of options which will be used for both the displayed
  8852. * option and the value, or a 2D array which will use the array in the first
  8853. * position as the value, and the array in the second position as the
  8854. * displayed options (useful for language strings such as 'All').
  8855. *
  8856. * Note that the `pageLength` property will be automatically set to the
  8857. * first value given in this array, unless `pageLength` is also provided.
  8858. * @type array
  8859. * @default [ 10, 25, 50, 100 ]
  8860. *
  8861. * @dtopt Option
  8862. * @name DataTable.defaults.lengthMenu
  8863. *
  8864. * @example
  8865. * $(document).ready( function() {
  8866. * $('#example').dataTable( {
  8867. * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
  8868. * } );
  8869. * } );
  8870. */
  8871. "aLengthMenu": [ 10, 25, 50, 100 ],
  8872. /**
  8873. * The `columns` option in the initialisation parameter allows you to define
  8874. * details about the way individual columns behave. For a full list of
  8875. * column options that can be set, please see
  8876. * {@link DataTable.defaults.column}. Note that if you use `columns` to
  8877. * define your columns, you must have an entry in the array for every single
  8878. * column that you have in your table (these can be null if you don't which
  8879. * to specify any options).
  8880. * @member
  8881. *
  8882. * @name DataTable.defaults.column
  8883. */
  8884. "aoColumns": null,
  8885. /**
  8886. * Very similar to `columns`, `columnDefs` allows you to target a specific
  8887. * column, multiple columns, or all columns, using the `targets` property of
  8888. * each object in the array. This allows great flexibility when creating
  8889. * tables, as the `columnDefs` arrays can be of any length, targeting the
  8890. * columns you specifically want. `columnDefs` may use any of the column
  8891. * options available: {@link DataTable.defaults.column}, but it _must_
  8892. * have `targets` defined in each object in the array. Values in the `targets`
  8893. * array may be:
  8894. * <ul>
  8895. * <li>a string - class name will be matched on the TH for the column</li>
  8896. * <li>0 or a positive integer - column index counting from the left</li>
  8897. * <li>a negative integer - column index counting from the right</li>
  8898. * <li>the string "_all" - all columns (i.e. assign a default)</li>
  8899. * </ul>
  8900. * @member
  8901. *
  8902. * @name DataTable.defaults.columnDefs
  8903. */
  8904. "aoColumnDefs": null,
  8905. /**
  8906. * Basically the same as `search`, this parameter defines the individual column
  8907. * filtering state at initialisation time. The array must be of the same size
  8908. * as the number of columns, and each element be an object with the parameters
  8909. * `search` and `escapeRegex` (the latter is optional). 'null' is also
  8910. * accepted and the default will be used.
  8911. * @type array
  8912. * @default []
  8913. *
  8914. * @dtopt Option
  8915. * @name DataTable.defaults.searchCols
  8916. *
  8917. * @example
  8918. * $(document).ready( function() {
  8919. * $('#example').dataTable( {
  8920. * "searchCols": [
  8921. * null,
  8922. * { "search": "My filter" },
  8923. * null,
  8924. * { "search": "^[0-9]", "escapeRegex": false }
  8925. * ]
  8926. * } );
  8927. * } )
  8928. */
  8929. "aoSearchCols": [],
  8930. /**
  8931. * An array of CSS classes that should be applied to displayed rows. This
  8932. * array may be of any length, and DataTables will apply each class
  8933. * sequentially, looping when required.
  8934. * @type array
  8935. * @default null <i>Will take the values determined by the `oClasses.stripe*`
  8936. * options</i>
  8937. *
  8938. * @dtopt Option
  8939. * @name DataTable.defaults.stripeClasses
  8940. *
  8941. * @example
  8942. * $(document).ready( function() {
  8943. * $('#example').dataTable( {
  8944. * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
  8945. * } );
  8946. * } )
  8947. */
  8948. "asStripeClasses": null,
  8949. /**
  8950. * Enable or disable automatic column width calculation. This can be disabled
  8951. * as an optimisation (it takes some time to calculate the widths) if the
  8952. * tables widths are passed in using `columns`.
  8953. * @type boolean
  8954. * @default true
  8955. *
  8956. * @dtopt Features
  8957. * @name DataTable.defaults.autoWidth
  8958. *
  8959. * @example
  8960. * $(document).ready( function () {
  8961. * $('#example').dataTable( {
  8962. * "autoWidth": false
  8963. * } );
  8964. * } );
  8965. */
  8966. "bAutoWidth": true,
  8967. /**
  8968. * Deferred rendering can provide DataTables with a huge speed boost when you
  8969. * are using an Ajax or JS data source for the table. This option, when set to
  8970. * true, will cause DataTables to defer the creation of the table elements for
  8971. * each row until they are needed for a draw - saving a significant amount of
  8972. * time.
  8973. * @type boolean
  8974. * @default false
  8975. *
  8976. * @dtopt Features
  8977. * @name DataTable.defaults.deferRender
  8978. *
  8979. * @example
  8980. * $(document).ready( function() {
  8981. * $('#example').dataTable( {
  8982. * "ajax": "sources/arrays.txt",
  8983. * "deferRender": true
  8984. * } );
  8985. * } );
  8986. */
  8987. "bDeferRender": false,
  8988. /**
  8989. * Replace a DataTable which matches the given selector and replace it with
  8990. * one which has the properties of the new initialisation object passed. If no
  8991. * table matches the selector, then the new DataTable will be constructed as
  8992. * per normal.
  8993. * @type boolean
  8994. * @default false
  8995. *
  8996. * @dtopt Options
  8997. * @name DataTable.defaults.destroy
  8998. *
  8999. * @example
  9000. * $(document).ready( function() {
  9001. * $('#example').dataTable( {
  9002. * "srollY": "200px",
  9003. * "paginate": false
  9004. * } );
  9005. *
  9006. * // Some time later....
  9007. * $('#example').dataTable( {
  9008. * "filter": false,
  9009. * "destroy": true
  9010. * } );
  9011. * } );
  9012. */
  9013. "bDestroy": false,
  9014. /**
  9015. * Enable or disable filtering of data. Filtering in DataTables is "smart" in
  9016. * that it allows the end user to input multiple words (space separated) and
  9017. * will match a row containing those words, even if not in the order that was
  9018. * specified (this allow matching across multiple columns). Note that if you
  9019. * wish to use filtering in DataTables this must remain 'true' - to remove the
  9020. * default filtering input box and retain filtering abilities, please use
  9021. * {@link DataTable.defaults.dom}.
  9022. * @type boolean
  9023. * @default true
  9024. *
  9025. * @dtopt Features
  9026. * @name DataTable.defaults.searching
  9027. *
  9028. * @example
  9029. * $(document).ready( function () {
  9030. * $('#example').dataTable( {
  9031. * "searching": false
  9032. * } );
  9033. * } );
  9034. */
  9035. "bFilter": true,
  9036. /**
  9037. * Enable or disable the table information display. This shows information
  9038. * about the data that is currently visible on the page, including information
  9039. * about filtered data if that action is being performed.
  9040. * @type boolean
  9041. * @default true
  9042. *
  9043. * @dtopt Features
  9044. * @name DataTable.defaults.info
  9045. *
  9046. * @example
  9047. * $(document).ready( function () {
  9048. * $('#example').dataTable( {
  9049. * "info": false
  9050. * } );
  9051. * } );
  9052. */
  9053. "bInfo": true,
  9054. /**
  9055. * Allows the end user to select the size of a formatted page from a select
  9056. * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
  9057. * @type boolean
  9058. * @default true
  9059. *
  9060. * @dtopt Features
  9061. * @name DataTable.defaults.lengthChange
  9062. *
  9063. * @example
  9064. * $(document).ready( function () {
  9065. * $('#example').dataTable( {
  9066. * "lengthChange": false
  9067. * } );
  9068. * } );
  9069. */
  9070. "bLengthChange": true,
  9071. /**
  9072. * Enable or disable pagination.
  9073. * @type boolean
  9074. * @default true
  9075. *
  9076. * @dtopt Features
  9077. * @name DataTable.defaults.paging
  9078. *
  9079. * @example
  9080. * $(document).ready( function () {
  9081. * $('#example').dataTable( {
  9082. * "paging": false
  9083. * } );
  9084. * } );
  9085. */
  9086. "bPaginate": true,
  9087. /**
  9088. * Enable or disable the display of a 'processing' indicator when the table is
  9089. * being processed (e.g. a sort). This is particularly useful for tables with
  9090. * large amounts of data where it can take a noticeable amount of time to sort
  9091. * the entries.
  9092. * @type boolean
  9093. * @default false
  9094. *
  9095. * @dtopt Features
  9096. * @name DataTable.defaults.processing
  9097. *
  9098. * @example
  9099. * $(document).ready( function () {
  9100. * $('#example').dataTable( {
  9101. * "processing": true
  9102. * } );
  9103. * } );
  9104. */
  9105. "bProcessing": false,
  9106. /**
  9107. * Retrieve the DataTables object for the given selector. Note that if the
  9108. * table has already been initialised, this parameter will cause DataTables
  9109. * to simply return the object that has already been set up - it will not take
  9110. * account of any changes you might have made to the initialisation object
  9111. * passed to DataTables (setting this parameter to true is an acknowledgement
  9112. * that you understand this). `destroy` can be used to reinitialise a table if
  9113. * you need.
  9114. * @type boolean
  9115. * @default false
  9116. *
  9117. * @dtopt Options
  9118. * @name DataTable.defaults.retrieve
  9119. *
  9120. * @example
  9121. * $(document).ready( function() {
  9122. * initTable();
  9123. * tableActions();
  9124. * } );
  9125. *
  9126. * function initTable ()
  9127. * {
  9128. * return $('#example').dataTable( {
  9129. * "scrollY": "200px",
  9130. * "paginate": false,
  9131. * "retrieve": true
  9132. * } );
  9133. * }
  9134. *
  9135. * function tableActions ()
  9136. * {
  9137. * var table = initTable();
  9138. * // perform API operations with oTable
  9139. * }
  9140. */
  9141. "bRetrieve": false,
  9142. /**
  9143. * When vertical (y) scrolling is enabled, DataTables will force the height of
  9144. * the table's viewport to the given height at all times (useful for layout).
  9145. * However, this can look odd when filtering data down to a small data set,
  9146. * and the footer is left "floating" further down. This parameter (when
  9147. * enabled) will cause DataTables to collapse the table's viewport down when
  9148. * the result set will fit within the given Y height.
  9149. * @type boolean
  9150. * @default false
  9151. *
  9152. * @dtopt Options
  9153. * @name DataTable.defaults.scrollCollapse
  9154. *
  9155. * @example
  9156. * $(document).ready( function() {
  9157. * $('#example').dataTable( {
  9158. * "scrollY": "200",
  9159. * "scrollCollapse": true
  9160. * } );
  9161. * } );
  9162. */
  9163. "bScrollCollapse": false,
  9164. /**
  9165. * Configure DataTables to use server-side processing. Note that the
  9166. * `ajax` parameter must also be given in order to give DataTables a
  9167. * source to obtain the required data for each draw.
  9168. * @type boolean
  9169. * @default false
  9170. *
  9171. * @dtopt Features
  9172. * @dtopt Server-side
  9173. * @name DataTable.defaults.serverSide
  9174. *
  9175. * @example
  9176. * $(document).ready( function () {
  9177. * $('#example').dataTable( {
  9178. * "serverSide": true,
  9179. * "ajax": "xhr.php"
  9180. * } );
  9181. * } );
  9182. */
  9183. "bServerSide": false,
  9184. /**
  9185. * Enable or disable sorting of columns. Sorting of individual columns can be
  9186. * disabled by the `sortable` option for each column.
  9187. * @type boolean
  9188. * @default true
  9189. *
  9190. * @dtopt Features
  9191. * @name DataTable.defaults.ordering
  9192. *
  9193. * @example
  9194. * $(document).ready( function () {
  9195. * $('#example').dataTable( {
  9196. * "ordering": false
  9197. * } );
  9198. * } );
  9199. */
  9200. "bSort": true,
  9201. /**
  9202. * Enable or display DataTables' ability to sort multiple columns at the
  9203. * same time (activated by shift-click by the user).
  9204. * @type boolean
  9205. * @default true
  9206. *
  9207. * @dtopt Options
  9208. * @name DataTable.defaults.orderMulti
  9209. *
  9210. * @example
  9211. * // Disable multiple column sorting ability
  9212. * $(document).ready( function () {
  9213. * $('#example').dataTable( {
  9214. * "orderMulti": false
  9215. * } );
  9216. * } );
  9217. */
  9218. "bSortMulti": true,
  9219. /**
  9220. * Allows control over whether DataTables should use the top (true) unique
  9221. * cell that is found for a single column, or the bottom (false - default).
  9222. * This is useful when using complex headers.
  9223. * @type boolean
  9224. * @default false
  9225. *
  9226. * @dtopt Options
  9227. * @name DataTable.defaults.orderCellsTop
  9228. *
  9229. * @example
  9230. * $(document).ready( function() {
  9231. * $('#example').dataTable( {
  9232. * "orderCellsTop": true
  9233. * } );
  9234. * } );
  9235. */
  9236. "bSortCellsTop": false,
  9237. /**
  9238. * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
  9239. * `sorting\_3` to the columns which are currently being sorted on. This is
  9240. * presented as a feature switch as it can increase processing time (while
  9241. * classes are removed and added) so for large data sets you might want to
  9242. * turn this off.
  9243. * @type boolean
  9244. * @default true
  9245. *
  9246. * @dtopt Features
  9247. * @name DataTable.defaults.orderClasses
  9248. *
  9249. * @example
  9250. * $(document).ready( function () {
  9251. * $('#example').dataTable( {
  9252. * "orderClasses": false
  9253. * } );
  9254. * } );
  9255. */
  9256. "bSortClasses": true,
  9257. /**
  9258. * Enable or disable state saving. When enabled HTML5 `localStorage` will be
  9259. * used to save table display information such as pagination information,
  9260. * display length, filtering and sorting. As such when the end user reloads
  9261. * the page the display display will match what thy had previously set up.
  9262. *
  9263. * Due to the use of `localStorage` the default state saving is not supported
  9264. * in IE6 or 7. If state saving is required in those browsers, use
  9265. * `stateSaveCallback` to provide a storage solution such as cookies.
  9266. * @type boolean
  9267. * @default false
  9268. *
  9269. * @dtopt Features
  9270. * @name DataTable.defaults.stateSave
  9271. *
  9272. * @example
  9273. * $(document).ready( function () {
  9274. * $('#example').dataTable( {
  9275. * "stateSave": true
  9276. * } );
  9277. * } );
  9278. */
  9279. "bStateSave": false,
  9280. /**
  9281. * This function is called when a TR element is created (and all TD child
  9282. * elements have been inserted), or registered if using a DOM source, allowing
  9283. * manipulation of the TR element (adding classes etc).
  9284. * @type function
  9285. * @param {node} row "TR" element for the current row
  9286. * @param {array} data Raw data array for this row
  9287. * @param {int} dataIndex The index of this row in the internal aoData array
  9288. *
  9289. * @dtopt Callbacks
  9290. * @name DataTable.defaults.createdRow
  9291. *
  9292. * @example
  9293. * $(document).ready( function() {
  9294. * $('#example').dataTable( {
  9295. * "createdRow": function( row, data, dataIndex ) {
  9296. * // Bold the grade for all 'A' grade browsers
  9297. * if ( data[4] == "A" )
  9298. * {
  9299. * $('td:eq(4)', row).html( '<b>A</b>' );
  9300. * }
  9301. * }
  9302. * } );
  9303. * } );
  9304. */
  9305. "fnCreatedRow": null,
  9306. /**
  9307. * This function is called on every 'draw' event, and allows you to
  9308. * dynamically modify any aspect you want about the created DOM.
  9309. * @type function
  9310. * @param {object} settings DataTables settings object
  9311. *
  9312. * @dtopt Callbacks
  9313. * @name DataTable.defaults.drawCallback
  9314. *
  9315. * @example
  9316. * $(document).ready( function() {
  9317. * $('#example').dataTable( {
  9318. * "drawCallback": function( settings ) {
  9319. * alert( 'DataTables has redrawn the table' );
  9320. * }
  9321. * } );
  9322. * } );
  9323. */
  9324. "fnDrawCallback": null,
  9325. /**
  9326. * Identical to fnHeaderCallback() but for the table footer this function
  9327. * allows you to modify the table footer on every 'draw' event.
  9328. * @type function
  9329. * @param {node} foot "TR" element for the footer
  9330. * @param {array} data Full table data (as derived from the original HTML)
  9331. * @param {int} start Index for the current display starting point in the
  9332. * display array
  9333. * @param {int} end Index for the current display ending point in the
  9334. * display array
  9335. * @param {array int} display Index array to translate the visual position
  9336. * to the full data array
  9337. *
  9338. * @dtopt Callbacks
  9339. * @name DataTable.defaults.footerCallback
  9340. *
  9341. * @example
  9342. * $(document).ready( function() {
  9343. * $('#example').dataTable( {
  9344. * "footerCallback": function( tfoot, data, start, end, display ) {
  9345. * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
  9346. * }
  9347. * } );
  9348. * } )
  9349. */
  9350. "fnFooterCallback": null,
  9351. /**
  9352. * When rendering large numbers in the information element for the table
  9353. * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
  9354. * to have a comma separator for the 'thousands' units (e.g. 1 million is
  9355. * rendered as "1,000,000") to help readability for the end user. This
  9356. * function will override the default method DataTables uses.
  9357. * @type function
  9358. * @member
  9359. * @param {int} toFormat number to be formatted
  9360. * @returns {string} formatted string for DataTables to show the number
  9361. *
  9362. * @dtopt Callbacks
  9363. * @name DataTable.defaults.formatNumber
  9364. *
  9365. * @example
  9366. * // Format a number using a single quote for the separator (note that
  9367. * // this can also be done with the language.thousands option)
  9368. * $(document).ready( function() {
  9369. * $('#example').dataTable( {
  9370. * "formatNumber": function ( toFormat ) {
  9371. * return toFormat.toString().replace(
  9372. * /\B(?=(\d{3})+(?!\d))/g, "'"
  9373. * );
  9374. * };
  9375. * } );
  9376. * } );
  9377. */
  9378. "fnFormatNumber": function ( toFormat ) {
  9379. return toFormat.toString().replace(
  9380. /\B(?=(\d{3})+(?!\d))/g,
  9381. this.oLanguage.sThousands
  9382. );
  9383. },
  9384. /**
  9385. * This function is called on every 'draw' event, and allows you to
  9386. * dynamically modify the header row. This can be used to calculate and
  9387. * display useful information about the table.
  9388. * @type function
  9389. * @param {node} head "TR" element for the header
  9390. * @param {array} data Full table data (as derived from the original HTML)
  9391. * @param {int} start Index for the current display starting point in the
  9392. * display array
  9393. * @param {int} end Index for the current display ending point in the
  9394. * display array
  9395. * @param {array int} display Index array to translate the visual position
  9396. * to the full data array
  9397. *
  9398. * @dtopt Callbacks
  9399. * @name DataTable.defaults.headerCallback
  9400. *
  9401. * @example
  9402. * $(document).ready( function() {
  9403. * $('#example').dataTable( {
  9404. * "fheaderCallback": function( head, data, start, end, display ) {
  9405. * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
  9406. * }
  9407. * } );
  9408. * } )
  9409. */
  9410. "fnHeaderCallback": null,
  9411. /**
  9412. * The information element can be used to convey information about the current
  9413. * state of the table. Although the internationalisation options presented by
  9414. * DataTables are quite capable of dealing with most customisations, there may
  9415. * be times where you wish to customise the string further. This callback
  9416. * allows you to do exactly that.
  9417. * @type function
  9418. * @param {object} oSettings DataTables settings object
  9419. * @param {int} start Starting position in data for the draw
  9420. * @param {int} end End position in data for the draw
  9421. * @param {int} max Total number of rows in the table (regardless of
  9422. * filtering)
  9423. * @param {int} total Total number of rows in the data set, after filtering
  9424. * @param {string} pre The string that DataTables has formatted using it's
  9425. * own rules
  9426. * @returns {string} The string to be displayed in the information element.
  9427. *
  9428. * @dtopt Callbacks
  9429. * @name DataTable.defaults.infoCallback
  9430. *
  9431. * @example
  9432. * $('#example').dataTable( {
  9433. * "infoCallback": function( settings, start, end, max, total, pre ) {
  9434. * return start +" to "+ end;
  9435. * }
  9436. * } );
  9437. */
  9438. "fnInfoCallback": null,
  9439. /**
  9440. * Called when the table has been initialised. Normally DataTables will
  9441. * initialise sequentially and there will be no need for this function,
  9442. * however, this does not hold true when using external language information
  9443. * since that is obtained using an async XHR call.
  9444. * @type function
  9445. * @param {object} settings DataTables settings object
  9446. * @param {object} json The JSON object request from the server - only
  9447. * present if client-side Ajax sourced data is used
  9448. *
  9449. * @dtopt Callbacks
  9450. * @name DataTable.defaults.initComplete
  9451. *
  9452. * @example
  9453. * $(document).ready( function() {
  9454. * $('#example').dataTable( {
  9455. * "initComplete": function(settings, json) {
  9456. * alert( 'DataTables has finished its initialisation.' );
  9457. * }
  9458. * } );
  9459. * } )
  9460. */
  9461. "fnInitComplete": null,
  9462. /**
  9463. * Called at the very start of each table draw and can be used to cancel the
  9464. * draw by returning false, any other return (including undefined) results in
  9465. * the full draw occurring).
  9466. * @type function
  9467. * @param {object} settings DataTables settings object
  9468. * @returns {boolean} False will cancel the draw, anything else (including no
  9469. * return) will allow it to complete.
  9470. *
  9471. * @dtopt Callbacks
  9472. * @name DataTable.defaults.preDrawCallback
  9473. *
  9474. * @example
  9475. * $(document).ready( function() {
  9476. * $('#example').dataTable( {
  9477. * "preDrawCallback": function( settings ) {
  9478. * if ( $('#test').val() == 1 ) {
  9479. * return false;
  9480. * }
  9481. * }
  9482. * } );
  9483. * } );
  9484. */
  9485. "fnPreDrawCallback": null,
  9486. /**
  9487. * This function allows you to 'post process' each row after it have been
  9488. * generated for each table draw, but before it is rendered on screen. This
  9489. * function might be used for setting the row class name etc.
  9490. * @type function
  9491. * @param {node} row "TR" element for the current row
  9492. * @param {array} data Raw data array for this row
  9493. * @param {int} displayIndex The display index for the current table draw
  9494. * @param {int} displayIndexFull The index of the data in the full list of
  9495. * rows (after filtering)
  9496. *
  9497. * @dtopt Callbacks
  9498. * @name DataTable.defaults.rowCallback
  9499. *
  9500. * @example
  9501. * $(document).ready( function() {
  9502. * $('#example').dataTable( {
  9503. * "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
  9504. * // Bold the grade for all 'A' grade browsers
  9505. * if ( data[4] == "A" ) {
  9506. * $('td:eq(4)', row).html( '<b>A</b>' );
  9507. * }
  9508. * }
  9509. * } );
  9510. * } );
  9511. */
  9512. "fnRowCallback": null,
  9513. /**
  9514. * __Deprecated__ The functionality provided by this parameter has now been
  9515. * superseded by that provided through `ajax`, which should be used instead.
  9516. *
  9517. * This parameter allows you to override the default function which obtains
  9518. * the data from the server so something more suitable for your application.
  9519. * For example you could use POST data, or pull information from a Gears or
  9520. * AIR database.
  9521. * @type function
  9522. * @member
  9523. * @param {string} source HTTP source to obtain the data from (`ajax`)
  9524. * @param {array} data A key/value pair object containing the data to send
  9525. * to the server
  9526. * @param {function} callback to be called on completion of the data get
  9527. * process that will draw the data on the page.
  9528. * @param {object} settings DataTables settings object
  9529. *
  9530. * @dtopt Callbacks
  9531. * @dtopt Server-side
  9532. * @name DataTable.defaults.serverData
  9533. *
  9534. * @deprecated 1.10. Please use `ajax` for this functionality now.
  9535. */
  9536. "fnServerData": null,
  9537. /**
  9538. * __Deprecated__ The functionality provided by this parameter has now been
  9539. * superseded by that provided through `ajax`, which should be used instead.
  9540. *
  9541. * It is often useful to send extra data to the server when making an Ajax
  9542. * request - for example custom filtering information, and this callback
  9543. * function makes it trivial to send extra information to the server. The
  9544. * passed in parameter is the data set that has been constructed by
  9545. * DataTables, and you can add to this or modify it as you require.
  9546. * @type function
  9547. * @param {array} data Data array (array of objects which are name/value
  9548. * pairs) that has been constructed by DataTables and will be sent to the
  9549. * server. In the case of Ajax sourced data with server-side processing
  9550. * this will be an empty array, for server-side processing there will be a
  9551. * significant number of parameters!
  9552. * @returns {undefined} Ensure that you modify the data array passed in,
  9553. * as this is passed by reference.
  9554. *
  9555. * @dtopt Callbacks
  9556. * @dtopt Server-side
  9557. * @name DataTable.defaults.serverParams
  9558. *
  9559. * @deprecated 1.10. Please use `ajax` for this functionality now.
  9560. */
  9561. "fnServerParams": null,
  9562. /**
  9563. * Load the table state. With this function you can define from where, and how, the
  9564. * state of a table is loaded. By default DataTables will load from `localStorage`
  9565. * but you might wish to use a server-side database or cookies.
  9566. * @type function
  9567. * @member
  9568. * @param {object} settings DataTables settings object
  9569. * @param {object} callback Callback that can be executed when done. It
  9570. * should be passed the loaded state object.
  9571. * @return {object} The DataTables state object to be loaded
  9572. *
  9573. * @dtopt Callbacks
  9574. * @name DataTable.defaults.stateLoadCallback
  9575. *
  9576. * @example
  9577. * $(document).ready( function() {
  9578. * $('#example').dataTable( {
  9579. * "stateSave": true,
  9580. * "stateLoadCallback": function (settings, callback) {
  9581. * $.ajax( {
  9582. * "url": "/state_load",
  9583. * "dataType": "json",
  9584. * "success": function (json) {
  9585. * callback( json );
  9586. * }
  9587. * } );
  9588. * }
  9589. * } );
  9590. * } );
  9591. */
  9592. "fnStateLoadCallback": function ( settings ) {
  9593. try {
  9594. return JSON.parse(
  9595. (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
  9596. 'DataTables_'+settings.sInstance+'_'+location.pathname
  9597. )
  9598. );
  9599. } catch (e) {
  9600. return {};
  9601. }
  9602. },
  9603. /**
  9604. * Callback which allows modification of the saved state prior to loading that state.
  9605. * This callback is called when the table is loading state from the stored data, but
  9606. * prior to the settings object being modified by the saved state. Note that for
  9607. * plug-in authors, you should use the `stateLoadParams` event to load parameters for
  9608. * a plug-in.
  9609. * @type function
  9610. * @param {object} settings DataTables settings object
  9611. * @param {object} data The state object that is to be loaded
  9612. *
  9613. * @dtopt Callbacks
  9614. * @name DataTable.defaults.stateLoadParams
  9615. *
  9616. * @example
  9617. * // Remove a saved filter, so filtering is never loaded
  9618. * $(document).ready( function() {
  9619. * $('#example').dataTable( {
  9620. * "stateSave": true,
  9621. * "stateLoadParams": function (settings, data) {
  9622. * data.oSearch.sSearch = "";
  9623. * }
  9624. * } );
  9625. * } );
  9626. *
  9627. * @example
  9628. * // Disallow state loading by returning false
  9629. * $(document).ready( function() {
  9630. * $('#example').dataTable( {
  9631. * "stateSave": true,
  9632. * "stateLoadParams": function (settings, data) {
  9633. * return false;
  9634. * }
  9635. * } );
  9636. * } );
  9637. */
  9638. "fnStateLoadParams": null,
  9639. /**
  9640. * Callback that is called when the state has been loaded from the state saving method
  9641. * and the DataTables settings object has been modified as a result of the loaded state.
  9642. * @type function
  9643. * @param {object} settings DataTables settings object
  9644. * @param {object} data The state object that was loaded
  9645. *
  9646. * @dtopt Callbacks
  9647. * @name DataTable.defaults.stateLoaded
  9648. *
  9649. * @example
  9650. * // Show an alert with the filtering value that was saved
  9651. * $(document).ready( function() {
  9652. * $('#example').dataTable( {
  9653. * "stateSave": true,
  9654. * "stateLoaded": function (settings, data) {
  9655. * alert( 'Saved filter was: '+data.oSearch.sSearch );
  9656. * }
  9657. * } );
  9658. * } );
  9659. */
  9660. "fnStateLoaded": null,
  9661. /**
  9662. * Save the table state. This function allows you to define where and how the state
  9663. * information for the table is stored By default DataTables will use `localStorage`
  9664. * but you might wish to use a server-side database or cookies.
  9665. * @type function
  9666. * @member
  9667. * @param {object} settings DataTables settings object
  9668. * @param {object} data The state object to be saved
  9669. *
  9670. * @dtopt Callbacks
  9671. * @name DataTable.defaults.stateSaveCallback
  9672. *
  9673. * @example
  9674. * $(document).ready( function() {
  9675. * $('#example').dataTable( {
  9676. * "stateSave": true,
  9677. * "stateSaveCallback": function (settings, data) {
  9678. * // Send an Ajax request to the server with the state object
  9679. * $.ajax( {
  9680. * "url": "/state_save",
  9681. * "data": data,
  9682. * "dataType": "json",
  9683. * "method": "POST"
  9684. * "success": function () {}
  9685. * } );
  9686. * }
  9687. * } );
  9688. * } );
  9689. */
  9690. "fnStateSaveCallback": function ( settings, data ) {
  9691. try {
  9692. (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
  9693. 'DataTables_'+settings.sInstance+'_'+location.pathname,
  9694. JSON.stringify( data )
  9695. );
  9696. } catch (e) {}
  9697. },
  9698. /**
  9699. * Callback which allows modification of the state to be saved. Called when the table
  9700. * has changed state a new state save is required. This method allows modification of
  9701. * the state saving object prior to actually doing the save, including addition or
  9702. * other state properties or modification. Note that for plug-in authors, you should
  9703. * use the `stateSaveParams` event to save parameters for a plug-in.
  9704. * @type function
  9705. * @param {object} settings DataTables settings object
  9706. * @param {object} data The state object to be saved
  9707. *
  9708. * @dtopt Callbacks
  9709. * @name DataTable.defaults.stateSaveParams
  9710. *
  9711. * @example
  9712. * // Remove a saved filter, so filtering is never saved
  9713. * $(document).ready( function() {
  9714. * $('#example').dataTable( {
  9715. * "stateSave": true,
  9716. * "stateSaveParams": function (settings, data) {
  9717. * data.oSearch.sSearch = "";
  9718. * }
  9719. * } );
  9720. * } );
  9721. */
  9722. "fnStateSaveParams": null,
  9723. /**
  9724. * Duration for which the saved state information is considered valid. After this period
  9725. * has elapsed the state will be returned to the default.
  9726. * Value is given in seconds.
  9727. * @type int
  9728. * @default 7200 <i>(2 hours)</i>
  9729. *
  9730. * @dtopt Options
  9731. * @name DataTable.defaults.stateDuration
  9732. *
  9733. * @example
  9734. * $(document).ready( function() {
  9735. * $('#example').dataTable( {
  9736. * "stateDuration": 60*60*24; // 1 day
  9737. * } );
  9738. * } )
  9739. */
  9740. "iStateDuration": 7200,
  9741. /**
  9742. * When enabled DataTables will not make a request to the server for the first
  9743. * page draw - rather it will use the data already on the page (no sorting etc
  9744. * will be applied to it), thus saving on an XHR at load time. `deferLoading`
  9745. * is used to indicate that deferred loading is required, but it is also used
  9746. * to tell DataTables how many records there are in the full table (allowing
  9747. * the information element and pagination to be displayed correctly). In the case
  9748. * where a filtering is applied to the table on initial load, this can be
  9749. * indicated by giving the parameter as an array, where the first element is
  9750. * the number of records available after filtering and the second element is the
  9751. * number of records without filtering (allowing the table information element
  9752. * to be shown correctly).
  9753. * @type int | array
  9754. * @default null
  9755. *
  9756. * @dtopt Options
  9757. * @name DataTable.defaults.deferLoading
  9758. *
  9759. * @example
  9760. * // 57 records available in the table, no filtering applied
  9761. * $(document).ready( function() {
  9762. * $('#example').dataTable( {
  9763. * "serverSide": true,
  9764. * "ajax": "scripts/server_processing.php",
  9765. * "deferLoading": 57
  9766. * } );
  9767. * } );
  9768. *
  9769. * @example
  9770. * // 57 records after filtering, 100 without filtering (an initial filter applied)
  9771. * $(document).ready( function() {
  9772. * $('#example').dataTable( {
  9773. * "serverSide": true,
  9774. * "ajax": "scripts/server_processing.php",
  9775. * "deferLoading": [ 57, 100 ],
  9776. * "search": {
  9777. * "search": "my_filter"
  9778. * }
  9779. * } );
  9780. * } );
  9781. */
  9782. "iDeferLoading": null,
  9783. /**
  9784. * Number of rows to display on a single page when using pagination. If
  9785. * feature enabled (`lengthChange`) then the end user will be able to override
  9786. * this to a custom setting using a pop-up menu.
  9787. * @type int
  9788. * @default 10
  9789. *
  9790. * @dtopt Options
  9791. * @name DataTable.defaults.pageLength
  9792. *
  9793. * @example
  9794. * $(document).ready( function() {
  9795. * $('#example').dataTable( {
  9796. * "pageLength": 50
  9797. * } );
  9798. * } )
  9799. */
  9800. "iDisplayLength": 10,
  9801. /**
  9802. * Define the starting point for data display when using DataTables with
  9803. * pagination. Note that this parameter is the number of records, rather than
  9804. * the page number, so if you have 10 records per page and want to start on
  9805. * the third page, it should be "20".
  9806. * @type int
  9807. * @default 0
  9808. *
  9809. * @dtopt Options
  9810. * @name DataTable.defaults.displayStart
  9811. *
  9812. * @example
  9813. * $(document).ready( function() {
  9814. * $('#example').dataTable( {
  9815. * "displayStart": 20
  9816. * } );
  9817. * } )
  9818. */
  9819. "iDisplayStart": 0,
  9820. /**
  9821. * By default DataTables allows keyboard navigation of the table (sorting, paging,
  9822. * and filtering) by adding a `tabindex` attribute to the required elements. This
  9823. * allows you to tab through the controls and press the enter key to activate them.
  9824. * The tabindex is default 0, meaning that the tab follows the flow of the document.
  9825. * You can overrule this using this parameter if you wish. Use a value of -1 to
  9826. * disable built-in keyboard navigation.
  9827. * @type int
  9828. * @default 0
  9829. *
  9830. * @dtopt Options
  9831. * @name DataTable.defaults.tabIndex
  9832. *
  9833. * @example
  9834. * $(document).ready( function() {
  9835. * $('#example').dataTable( {
  9836. * "tabIndex": 1
  9837. * } );
  9838. * } );
  9839. */
  9840. "iTabIndex": 0,
  9841. /**
  9842. * Classes that DataTables assigns to the various components and features
  9843. * that it adds to the HTML table. This allows classes to be configured
  9844. * during initialisation in addition to through the static
  9845. * {@link DataTable.ext.oStdClasses} object).
  9846. * @namespace
  9847. * @name DataTable.defaults.classes
  9848. */
  9849. "oClasses": {},
  9850. /**
  9851. * All strings that DataTables uses in the user interface that it creates
  9852. * are defined in this object, allowing you to modified them individually or
  9853. * completely replace them all as required.
  9854. * @namespace
  9855. * @name DataTable.defaults.language
  9856. */
  9857. "oLanguage": {
  9858. /**
  9859. * Strings that are used for WAI-ARIA labels and controls only (these are not
  9860. * actually visible on the page, but will be read by screenreaders, and thus
  9861. * must be internationalised as well).
  9862. * @namespace
  9863. * @name DataTable.defaults.language.aria
  9864. */
  9865. "oAria": {
  9866. /**
  9867. * ARIA label that is added to the table headers when the column may be
  9868. * sorted ascending by activing the column (click or return when focused).
  9869. * Note that the column header is prefixed to this string.
  9870. * @type string
  9871. * @default : activate to sort column ascending
  9872. *
  9873. * @dtopt Language
  9874. * @name DataTable.defaults.language.aria.sortAscending
  9875. *
  9876. * @example
  9877. * $(document).ready( function() {
  9878. * $('#example').dataTable( {
  9879. * "language": {
  9880. * "aria": {
  9881. * "sortAscending": " - click/return to sort ascending"
  9882. * }
  9883. * }
  9884. * } );
  9885. * } );
  9886. */
  9887. "sSortAscending": ": activate to sort column ascending",
  9888. /**
  9889. * ARIA label that is added to the table headers when the column may be
  9890. * sorted descending by activing the column (click or return when focused).
  9891. * Note that the column header is prefixed to this string.
  9892. * @type string
  9893. * @default : activate to sort column ascending
  9894. *
  9895. * @dtopt Language
  9896. * @name DataTable.defaults.language.aria.sortDescending
  9897. *
  9898. * @example
  9899. * $(document).ready( function() {
  9900. * $('#example').dataTable( {
  9901. * "language": {
  9902. * "aria": {
  9903. * "sortDescending": " - click/return to sort descending"
  9904. * }
  9905. * }
  9906. * } );
  9907. * } );
  9908. */
  9909. "sSortDescending": ": activate to sort column descending"
  9910. },
  9911. /**
  9912. * Pagination string used by DataTables for the built-in pagination
  9913. * control types.
  9914. * @namespace
  9915. * @name DataTable.defaults.language.paginate
  9916. */
  9917. "oPaginate": {
  9918. /**
  9919. * Text to use when using the 'full_numbers' type of pagination for the
  9920. * button to take the user to the first page.
  9921. * @type string
  9922. * @default First
  9923. *
  9924. * @dtopt Language
  9925. * @name DataTable.defaults.language.paginate.first
  9926. *
  9927. * @example
  9928. * $(document).ready( function() {
  9929. * $('#example').dataTable( {
  9930. * "language": {
  9931. * "paginate": {
  9932. * "first": "First page"
  9933. * }
  9934. * }
  9935. * } );
  9936. * } );
  9937. */
  9938. "sFirst": "First",
  9939. /**
  9940. * Text to use when using the 'full_numbers' type of pagination for the
  9941. * button to take the user to the last page.
  9942. * @type string
  9943. * @default Last
  9944. *
  9945. * @dtopt Language
  9946. * @name DataTable.defaults.language.paginate.last
  9947. *
  9948. * @example
  9949. * $(document).ready( function() {
  9950. * $('#example').dataTable( {
  9951. * "language": {
  9952. * "paginate": {
  9953. * "last": "Last page"
  9954. * }
  9955. * }
  9956. * } );
  9957. * } );
  9958. */
  9959. "sLast": "Last",
  9960. /**
  9961. * Text to use for the 'next' pagination button (to take the user to the
  9962. * next page).
  9963. * @type string
  9964. * @default Next
  9965. *
  9966. * @dtopt Language
  9967. * @name DataTable.defaults.language.paginate.next
  9968. *
  9969. * @example
  9970. * $(document).ready( function() {
  9971. * $('#example').dataTable( {
  9972. * "language": {
  9973. * "paginate": {
  9974. * "next": "Next page"
  9975. * }
  9976. * }
  9977. * } );
  9978. * } );
  9979. */
  9980. "sNext": "Next",
  9981. /**
  9982. * Text to use for the 'previous' pagination button (to take the user to
  9983. * the previous page).
  9984. * @type string
  9985. * @default Previous
  9986. *
  9987. * @dtopt Language
  9988. * @name DataTable.defaults.language.paginate.previous
  9989. *
  9990. * @example
  9991. * $(document).ready( function() {
  9992. * $('#example').dataTable( {
  9993. * "language": {
  9994. * "paginate": {
  9995. * "previous": "Previous page"
  9996. * }
  9997. * }
  9998. * } );
  9999. * } );
  10000. */
  10001. "sPrevious": "Previous"
  10002. },
  10003. /**
  10004. * This string is shown in preference to `zeroRecords` when the table is
  10005. * empty of data (regardless of filtering). Note that this is an optional
  10006. * parameter - if it is not given, the value of `zeroRecords` will be used
  10007. * instead (either the default or given value).
  10008. * @type string
  10009. * @default No data available in table
  10010. *
  10011. * @dtopt Language
  10012. * @name DataTable.defaults.language.emptyTable
  10013. *
  10014. * @example
  10015. * $(document).ready( function() {
  10016. * $('#example').dataTable( {
  10017. * "language": {
  10018. * "emptyTable": "No data available in table"
  10019. * }
  10020. * } );
  10021. * } );
  10022. */
  10023. "sEmptyTable": "No data available in table",
  10024. /**
  10025. * This string gives information to the end user about the information
  10026. * that is current on display on the page. The following tokens can be
  10027. * used in the string and will be dynamically replaced as the table
  10028. * display updates. This tokens can be placed anywhere in the string, or
  10029. * removed as needed by the language requires:
  10030. *
  10031. * * `\_START\_` - Display index of the first record on the current page
  10032. * * `\_END\_` - Display index of the last record on the current page
  10033. * * `\_TOTAL\_` - Number of records in the table after filtering
  10034. * * `\_MAX\_` - Number of records in the table without filtering
  10035. * * `\_PAGE\_` - Current page number
  10036. * * `\_PAGES\_` - Total number of pages of data in the table
  10037. *
  10038. * @type string
  10039. * @default Showing _START_ to _END_ of _TOTAL_ entries
  10040. *
  10041. * @dtopt Language
  10042. * @name DataTable.defaults.language.info
  10043. *
  10044. * @example
  10045. * $(document).ready( function() {
  10046. * $('#example').dataTable( {
  10047. * "language": {
  10048. * "info": "Showing page _PAGE_ of _PAGES_"
  10049. * }
  10050. * } );
  10051. * } );
  10052. */
  10053. "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
  10054. /**
  10055. * Display information string for when the table is empty. Typically the
  10056. * format of this string should match `info`.
  10057. * @type string
  10058. * @default Showing 0 to 0 of 0 entries
  10059. *
  10060. * @dtopt Language
  10061. * @name DataTable.defaults.language.infoEmpty
  10062. *
  10063. * @example
  10064. * $(document).ready( function() {
  10065. * $('#example').dataTable( {
  10066. * "language": {
  10067. * "infoEmpty": "No entries to show"
  10068. * }
  10069. * } );
  10070. * } );
  10071. */
  10072. "sInfoEmpty": "Showing 0 to 0 of 0 entries",
  10073. /**
  10074. * When a user filters the information in a table, this string is appended
  10075. * to the information (`info`) to give an idea of how strong the filtering
  10076. * is. The variable _MAX_ is dynamically updated.
  10077. * @type string
  10078. * @default (filtered from _MAX_ total entries)
  10079. *
  10080. * @dtopt Language
  10081. * @name DataTable.defaults.language.infoFiltered
  10082. *
  10083. * @example
  10084. * $(document).ready( function() {
  10085. * $('#example').dataTable( {
  10086. * "language": {
  10087. * "infoFiltered": " - filtering from _MAX_ records"
  10088. * }
  10089. * } );
  10090. * } );
  10091. */
  10092. "sInfoFiltered": "(filtered from _MAX_ total entries)",
  10093. /**
  10094. * If can be useful to append extra information to the info string at times,
  10095. * and this variable does exactly that. This information will be appended to
  10096. * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
  10097. * being used) at all times.
  10098. * @type string
  10099. * @default <i>Empty string</i>
  10100. *
  10101. * @dtopt Language
  10102. * @name DataTable.defaults.language.infoPostFix
  10103. *
  10104. * @example
  10105. * $(document).ready( function() {
  10106. * $('#example').dataTable( {
  10107. * "language": {
  10108. * "infoPostFix": "All records shown are derived from real information."
  10109. * }
  10110. * } );
  10111. * } );
  10112. */
  10113. "sInfoPostFix": "",
  10114. /**
  10115. * This decimal place operator is a little different from the other
  10116. * language options since DataTables doesn't output floating point
  10117. * numbers, so it won't ever use this for display of a number. Rather,
  10118. * what this parameter does is modify the sort methods of the table so
  10119. * that numbers which are in a format which has a character other than
  10120. * a period (`.`) as a decimal place will be sorted numerically.
  10121. *
  10122. * Note that numbers with different decimal places cannot be shown in
  10123. * the same table and still be sortable, the table must be consistent.
  10124. * However, multiple different tables on the page can use different
  10125. * decimal place characters.
  10126. * @type string
  10127. * @default
  10128. *
  10129. * @dtopt Language
  10130. * @name DataTable.defaults.language.decimal
  10131. *
  10132. * @example
  10133. * $(document).ready( function() {
  10134. * $('#example').dataTable( {
  10135. * "language": {
  10136. * "decimal": ","
  10137. * "thousands": "."
  10138. * }
  10139. * } );
  10140. * } );
  10141. */
  10142. "sDecimal": "",
  10143. /**
  10144. * DataTables has a build in number formatter (`formatNumber`) which is
  10145. * used to format large numbers that are used in the table information.
  10146. * By default a comma is used, but this can be trivially changed to any
  10147. * character you wish with this parameter.
  10148. * @type string
  10149. * @default ,
  10150. *
  10151. * @dtopt Language
  10152. * @name DataTable.defaults.language.thousands
  10153. *
  10154. * @example
  10155. * $(document).ready( function() {
  10156. * $('#example').dataTable( {
  10157. * "language": {
  10158. * "thousands": "'"
  10159. * }
  10160. * } );
  10161. * } );
  10162. */
  10163. "sThousands": ",",
  10164. /**
  10165. * Detail the action that will be taken when the drop down menu for the
  10166. * pagination length option is changed. The '_MENU_' variable is replaced
  10167. * with a default select list of 10, 25, 50 and 100, and can be replaced
  10168. * with a custom select box if required.
  10169. * @type string
  10170. * @default Show _MENU_ entries
  10171. *
  10172. * @dtopt Language
  10173. * @name DataTable.defaults.language.lengthMenu
  10174. *
  10175. * @example
  10176. * // Language change only
  10177. * $(document).ready( function() {
  10178. * $('#example').dataTable( {
  10179. * "language": {
  10180. * "lengthMenu": "Display _MENU_ records"
  10181. * }
  10182. * } );
  10183. * } );
  10184. *
  10185. * @example
  10186. * // Language and options change
  10187. * $(document).ready( function() {
  10188. * $('#example').dataTable( {
  10189. * "language": {
  10190. * "lengthMenu": 'Display <select>'+
  10191. * '<option value="10">10</option>'+
  10192. * '<option value="20">20</option>'+
  10193. * '<option value="30">30</option>'+
  10194. * '<option value="40">40</option>'+
  10195. * '<option value="50">50</option>'+
  10196. * '<option value="-1">All</option>'+
  10197. * '</select> records'
  10198. * }
  10199. * } );
  10200. * } );
  10201. */
  10202. "sLengthMenu": "Show _MENU_ entries",
  10203. /**
  10204. * When using Ajax sourced data and during the first draw when DataTables is
  10205. * gathering the data, this message is shown in an empty row in the table to
  10206. * indicate to the end user the the data is being loaded. Note that this
  10207. * parameter is not used when loading data by server-side processing, just
  10208. * Ajax sourced data with client-side processing.
  10209. * @type string
  10210. * @default Loading...
  10211. *
  10212. * @dtopt Language
  10213. * @name DataTable.defaults.language.loadingRecords
  10214. *
  10215. * @example
  10216. * $(document).ready( function() {
  10217. * $('#example').dataTable( {
  10218. * "language": {
  10219. * "loadingRecords": "Please wait - loading..."
  10220. * }
  10221. * } );
  10222. * } );
  10223. */
  10224. "sLoadingRecords": "Loading...",
  10225. /**
  10226. * Text which is displayed when the table is processing a user action
  10227. * (usually a sort command or similar).
  10228. * @type string
  10229. *
  10230. * @dtopt Language
  10231. * @name DataTable.defaults.language.processing
  10232. *
  10233. * @example
  10234. * $(document).ready( function() {
  10235. * $('#example').dataTable( {
  10236. * "language": {
  10237. * "processing": "DataTables is currently busy"
  10238. * }
  10239. * } );
  10240. * } );
  10241. */
  10242. "sProcessing": "",
  10243. /**
  10244. * Details the actions that will be taken when the user types into the
  10245. * filtering input text box. The variable "_INPUT_", if used in the string,
  10246. * is replaced with the HTML text box for the filtering input allowing
  10247. * control over where it appears in the string. If "_INPUT_" is not given
  10248. * then the input box is appended to the string automatically.
  10249. * @type string
  10250. * @default Search:
  10251. *
  10252. * @dtopt Language
  10253. * @name DataTable.defaults.language.search
  10254. *
  10255. * @example
  10256. * // Input text box will be appended at the end automatically
  10257. * $(document).ready( function() {
  10258. * $('#example').dataTable( {
  10259. * "language": {
  10260. * "search": "Filter records:"
  10261. * }
  10262. * } );
  10263. * } );
  10264. *
  10265. * @example
  10266. * // Specify where the filter should appear
  10267. * $(document).ready( function() {
  10268. * $('#example').dataTable( {
  10269. * "language": {
  10270. * "search": "Apply filter _INPUT_ to table"
  10271. * }
  10272. * } );
  10273. * } );
  10274. */
  10275. "sSearch": "Search:",
  10276. /**
  10277. * Assign a `placeholder` attribute to the search `input` element
  10278. * @type string
  10279. * @default
  10280. *
  10281. * @dtopt Language
  10282. * @name DataTable.defaults.language.searchPlaceholder
  10283. */
  10284. "sSearchPlaceholder": "",
  10285. /**
  10286. * All of the language information can be stored in a file on the
  10287. * server-side, which DataTables will look up if this parameter is passed.
  10288. * It must store the URL of the language file, which is in a JSON format,
  10289. * and the object has the same properties as the oLanguage object in the
  10290. * initialiser object (i.e. the above parameters). Please refer to one of
  10291. * the example language files to see how this works in action.
  10292. * @type string
  10293. * @default <i>Empty string - i.e. disabled</i>
  10294. *
  10295. * @dtopt Language
  10296. * @name DataTable.defaults.language.url
  10297. *
  10298. * @example
  10299. * $(document).ready( function() {
  10300. * $('#example').dataTable( {
  10301. * "language": {
  10302. * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
  10303. * }
  10304. * } );
  10305. * } );
  10306. */
  10307. "sUrl": "",
  10308. /**
  10309. * Text shown inside the table records when the is no information to be
  10310. * displayed after filtering. `emptyTable` is shown when there is simply no
  10311. * information in the table at all (regardless of filtering).
  10312. * @type string
  10313. * @default No matching records found
  10314. *
  10315. * @dtopt Language
  10316. * @name DataTable.defaults.language.zeroRecords
  10317. *
  10318. * @example
  10319. * $(document).ready( function() {
  10320. * $('#example').dataTable( {
  10321. * "language": {
  10322. * "zeroRecords": "No records to display"
  10323. * }
  10324. * } );
  10325. * } );
  10326. */
  10327. "sZeroRecords": "No matching records found"
  10328. },
  10329. /**
  10330. * This parameter allows you to have define the global filtering state at
  10331. * initialisation time. As an object the `search` parameter must be
  10332. * defined, but all other parameters are optional. When `regex` is true,
  10333. * the search string will be treated as a regular expression, when false
  10334. * (default) it will be treated as a straight string. When `smart`
  10335. * DataTables will use it's smart filtering methods (to word match at
  10336. * any point in the data), when false this will not be done.
  10337. * @namespace
  10338. * @extends DataTable.models.oSearch
  10339. *
  10340. * @dtopt Options
  10341. * @name DataTable.defaults.search
  10342. *
  10343. * @example
  10344. * $(document).ready( function() {
  10345. * $('#example').dataTable( {
  10346. * "search": {"search": "Initial search"}
  10347. * } );
  10348. * } )
  10349. */
  10350. "oSearch": $.extend( {}, DataTable.models.oSearch ),
  10351. /**
  10352. * __Deprecated__ The functionality provided by this parameter has now been
  10353. * superseded by that provided through `ajax`, which should be used instead.
  10354. *
  10355. * By default DataTables will look for the property `data` (or `aaData` for
  10356. * compatibility with DataTables 1.9-) when obtaining data from an Ajax
  10357. * source or for server-side processing - this parameter allows that
  10358. * property to be changed. You can use Javascript dotted object notation to
  10359. * get a data source for multiple levels of nesting.
  10360. * @type string
  10361. * @default data
  10362. *
  10363. * @dtopt Options
  10364. * @dtopt Server-side
  10365. * @name DataTable.defaults.ajaxDataProp
  10366. *
  10367. * @deprecated 1.10. Please use `ajax` for this functionality now.
  10368. */
  10369. "sAjaxDataProp": "data",
  10370. /**
  10371. * __Deprecated__ The functionality provided by this parameter has now been
  10372. * superseded by that provided through `ajax`, which should be used instead.
  10373. *
  10374. * You can instruct DataTables to load data from an external
  10375. * source using this parameter (use aData if you want to pass data in you
  10376. * already have). Simply provide a url a JSON object can be obtained from.
  10377. * @type string
  10378. * @default null
  10379. *
  10380. * @dtopt Options
  10381. * @dtopt Server-side
  10382. * @name DataTable.defaults.ajaxSource
  10383. *
  10384. * @deprecated 1.10. Please use `ajax` for this functionality now.
  10385. */
  10386. "sAjaxSource": null,
  10387. /**
  10388. * This initialisation variable allows you to specify exactly where in the
  10389. * DOM you want DataTables to inject the various controls it adds to the page
  10390. * (for example you might want the pagination controls at the top of the
  10391. * table). DIV elements (with or without a custom class) can also be added to
  10392. * aid styling. The follow syntax is used:
  10393. * <ul>
  10394. * <li>The following options are allowed:
  10395. * <ul>
  10396. * <li>'l' - Length changing</li>
  10397. * <li>'f' - Filtering input</li>
  10398. * <li>'t' - The table!</li>
  10399. * <li>'i' - Information</li>
  10400. * <li>'p' - Pagination</li>
  10401. * <li>'r' - pRocessing</li>
  10402. * </ul>
  10403. * </li>
  10404. * <li>The following constants are allowed:
  10405. * <ul>
  10406. * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
  10407. * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
  10408. * </ul>
  10409. * </li>
  10410. * <li>The following syntax is expected:
  10411. * <ul>
  10412. * <li>'&lt;' and '&gt;' - div elements</li>
  10413. * <li>'&lt;"class" and '&gt;' - div with a class</li>
  10414. * <li>'&lt;"#id" and '&gt;' - div with an ID</li>
  10415. * </ul>
  10416. * </li>
  10417. * <li>Examples:
  10418. * <ul>
  10419. * <li>'&lt;"wrapper"flipt&gt;'</li>
  10420. * <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
  10421. * </ul>
  10422. * </li>
  10423. * </ul>
  10424. * @type string
  10425. * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
  10426. * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
  10427. *
  10428. * @dtopt Options
  10429. * @name DataTable.defaults.dom
  10430. *
  10431. * @example
  10432. * $(document).ready( function() {
  10433. * $('#example').dataTable( {
  10434. * "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
  10435. * } );
  10436. * } );
  10437. */
  10438. "sDom": "lfrtip",
  10439. /**
  10440. * Search delay option. This will throttle full table searches that use the
  10441. * DataTables provided search input element (it does not effect calls to
  10442. * `dt-api search()`, providing a delay before the search is made.
  10443. * @type integer
  10444. * @default 0
  10445. *
  10446. * @dtopt Options
  10447. * @name DataTable.defaults.searchDelay
  10448. *
  10449. * @example
  10450. * $(document).ready( function() {
  10451. * $('#example').dataTable( {
  10452. * "searchDelay": 200
  10453. * } );
  10454. * } )
  10455. */
  10456. "searchDelay": null,
  10457. /**
  10458. * DataTables features six different built-in options for the buttons to
  10459. * display for pagination control:
  10460. *
  10461. * * `numbers` - Page number buttons only
  10462. * * `simple` - 'Previous' and 'Next' buttons only
  10463. * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
  10464. * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
  10465. * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
  10466. * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
  10467. *
  10468. * Further methods can be added using {@link DataTable.ext.oPagination}.
  10469. * @type string
  10470. * @default simple_numbers
  10471. *
  10472. * @dtopt Options
  10473. * @name DataTable.defaults.pagingType
  10474. *
  10475. * @example
  10476. * $(document).ready( function() {
  10477. * $('#example').dataTable( {
  10478. * "pagingType": "full_numbers"
  10479. * } );
  10480. * } )
  10481. */
  10482. "sPaginationType": "simple_numbers",
  10483. /**
  10484. * Enable horizontal scrolling. When a table is too wide to fit into a
  10485. * certain layout, or you have a large number of columns in the table, you
  10486. * can enable x-scrolling to show the table in a viewport, which can be
  10487. * scrolled. This property can be `true` which will allow the table to
  10488. * scroll horizontally when needed, or any CSS unit, or a number (in which
  10489. * case it will be treated as a pixel measurement). Setting as simply `true`
  10490. * is recommended.
  10491. * @type boolean|string
  10492. * @default <i>blank string - i.e. disabled</i>
  10493. *
  10494. * @dtopt Features
  10495. * @name DataTable.defaults.scrollX
  10496. *
  10497. * @example
  10498. * $(document).ready( function() {
  10499. * $('#example').dataTable( {
  10500. * "scrollX": true,
  10501. * "scrollCollapse": true
  10502. * } );
  10503. * } );
  10504. */
  10505. "sScrollX": "",
  10506. /**
  10507. * This property can be used to force a DataTable to use more width than it
  10508. * might otherwise do when x-scrolling is enabled. For example if you have a
  10509. * table which requires to be well spaced, this parameter is useful for
  10510. * "over-sizing" the table, and thus forcing scrolling. This property can by
  10511. * any CSS unit, or a number (in which case it will be treated as a pixel
  10512. * measurement).
  10513. * @type string
  10514. * @default <i>blank string - i.e. disabled</i>
  10515. *
  10516. * @dtopt Options
  10517. * @name DataTable.defaults.scrollXInner
  10518. *
  10519. * @example
  10520. * $(document).ready( function() {
  10521. * $('#example').dataTable( {
  10522. * "scrollX": "100%",
  10523. * "scrollXInner": "110%"
  10524. * } );
  10525. * } );
  10526. */
  10527. "sScrollXInner": "",
  10528. /**
  10529. * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
  10530. * to the given height, and enable scrolling for any data which overflows the
  10531. * current viewport. This can be used as an alternative to paging to display
  10532. * a lot of data in a small area (although paging and scrolling can both be
  10533. * enabled at the same time). This property can be any CSS unit, or a number
  10534. * (in which case it will be treated as a pixel measurement).
  10535. * @type string
  10536. * @default <i>blank string - i.e. disabled</i>
  10537. *
  10538. * @dtopt Features
  10539. * @name DataTable.defaults.scrollY
  10540. *
  10541. * @example
  10542. * $(document).ready( function() {
  10543. * $('#example').dataTable( {
  10544. * "scrollY": "200px",
  10545. * "paginate": false
  10546. * } );
  10547. * } );
  10548. */
  10549. "sScrollY": "",
  10550. /**
  10551. * __Deprecated__ The functionality provided by this parameter has now been
  10552. * superseded by that provided through `ajax`, which should be used instead.
  10553. *
  10554. * Set the HTTP method that is used to make the Ajax call for server-side
  10555. * processing or Ajax sourced data.
  10556. * @type string
  10557. * @default GET
  10558. *
  10559. * @dtopt Options
  10560. * @dtopt Server-side
  10561. * @name DataTable.defaults.serverMethod
  10562. *
  10563. * @deprecated 1.10. Please use `ajax` for this functionality now.
  10564. */
  10565. "sServerMethod": "GET",
  10566. /**
  10567. * DataTables makes use of renderers when displaying HTML elements for
  10568. * a table. These renderers can be added or modified by plug-ins to
  10569. * generate suitable mark-up for a site. For example the Bootstrap
  10570. * integration plug-in for DataTables uses a paging button renderer to
  10571. * display pagination buttons in the mark-up required by Bootstrap.
  10572. *
  10573. * For further information about the renderers available see
  10574. * DataTable.ext.renderer
  10575. * @type string|object
  10576. * @default null
  10577. *
  10578. * @name DataTable.defaults.renderer
  10579. *
  10580. */
  10581. "renderer": null,
  10582. /**
  10583. * Set the data property name that DataTables should use to get a row's id
  10584. * to set as the `id` property in the node.
  10585. * @type string
  10586. * @default DT_RowId
  10587. *
  10588. * @name DataTable.defaults.rowId
  10589. */
  10590. "rowId": "DT_RowId"
  10591. };
  10592. _fnHungarianMap( DataTable.defaults );
  10593. /*
  10594. * Developer note - See note in model.defaults.js about the use of Hungarian
  10595. * notation and camel case.
  10596. */
  10597. /**
  10598. * Column options that can be given to DataTables at initialisation time.
  10599. * @namespace
  10600. */
  10601. DataTable.defaults.column = {
  10602. /**
  10603. * Define which column(s) an order will occur on for this column. This
  10604. * allows a column's ordering to take multiple columns into account when
  10605. * doing a sort or use the data from a different column. For example first
  10606. * name / last name columns make sense to do a multi-column sort over the
  10607. * two columns.
  10608. * @type array|int
  10609. * @default null <i>Takes the value of the column index automatically</i>
  10610. *
  10611. * @name DataTable.defaults.column.orderData
  10612. * @dtopt Columns
  10613. *
  10614. * @example
  10615. * // Using `columnDefs`
  10616. * $(document).ready( function() {
  10617. * $('#example').dataTable( {
  10618. * "columnDefs": [
  10619. * { "orderData": [ 0, 1 ], "targets": [ 0 ] },
  10620. * { "orderData": [ 1, 0 ], "targets": [ 1 ] },
  10621. * { "orderData": 2, "targets": [ 2 ] }
  10622. * ]
  10623. * } );
  10624. * } );
  10625. *
  10626. * @example
  10627. * // Using `columns`
  10628. * $(document).ready( function() {
  10629. * $('#example').dataTable( {
  10630. * "columns": [
  10631. * { "orderData": [ 0, 1 ] },
  10632. * { "orderData": [ 1, 0 ] },
  10633. * { "orderData": 2 },
  10634. * null,
  10635. * null
  10636. * ]
  10637. * } );
  10638. * } );
  10639. */
  10640. "aDataSort": null,
  10641. "iDataSort": -1,
  10642. /**
  10643. * You can control the default ordering direction, and even alter the
  10644. * behaviour of the sort handler (i.e. only allow ascending ordering etc)
  10645. * using this parameter.
  10646. * @type array
  10647. * @default [ 'asc', 'desc' ]
  10648. *
  10649. * @name DataTable.defaults.column.orderSequence
  10650. * @dtopt Columns
  10651. *
  10652. * @example
  10653. * // Using `columnDefs`
  10654. * $(document).ready( function() {
  10655. * $('#example').dataTable( {
  10656. * "columnDefs": [
  10657. * { "orderSequence": [ "asc" ], "targets": [ 1 ] },
  10658. * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
  10659. * { "orderSequence": [ "desc" ], "targets": [ 3 ] }
  10660. * ]
  10661. * } );
  10662. * } );
  10663. *
  10664. * @example
  10665. * // Using `columns`
  10666. * $(document).ready( function() {
  10667. * $('#example').dataTable( {
  10668. * "columns": [
  10669. * null,
  10670. * { "orderSequence": [ "asc" ] },
  10671. * { "orderSequence": [ "desc", "asc", "asc" ] },
  10672. * { "orderSequence": [ "desc" ] },
  10673. * null
  10674. * ]
  10675. * } );
  10676. * } );
  10677. */
  10678. "asSorting": [ 'asc', 'desc' ],
  10679. /**
  10680. * Enable or disable filtering on the data in this column.
  10681. * @type boolean
  10682. * @default true
  10683. *
  10684. * @name DataTable.defaults.column.searchable
  10685. * @dtopt Columns
  10686. *
  10687. * @example
  10688. * // Using `columnDefs`
  10689. * $(document).ready( function() {
  10690. * $('#example').dataTable( {
  10691. * "columnDefs": [
  10692. * { "searchable": false, "targets": [ 0 ] }
  10693. * ] } );
  10694. * } );
  10695. *
  10696. * @example
  10697. * // Using `columns`
  10698. * $(document).ready( function() {
  10699. * $('#example').dataTable( {
  10700. * "columns": [
  10701. * { "searchable": false },
  10702. * null,
  10703. * null,
  10704. * null,
  10705. * null
  10706. * ] } );
  10707. * } );
  10708. */
  10709. "bSearchable": true,
  10710. /**
  10711. * Enable or disable ordering on this column.
  10712. * @type boolean
  10713. * @default true
  10714. *
  10715. * @name DataTable.defaults.column.orderable
  10716. * @dtopt Columns
  10717. *
  10718. * @example
  10719. * // Using `columnDefs`
  10720. * $(document).ready( function() {
  10721. * $('#example').dataTable( {
  10722. * "columnDefs": [
  10723. * { "orderable": false, "targets": [ 0 ] }
  10724. * ] } );
  10725. * } );
  10726. *
  10727. * @example
  10728. * // Using `columns`
  10729. * $(document).ready( function() {
  10730. * $('#example').dataTable( {
  10731. * "columns": [
  10732. * { "orderable": false },
  10733. * null,
  10734. * null,
  10735. * null,
  10736. * null
  10737. * ] } );
  10738. * } );
  10739. */
  10740. "bSortable": true,
  10741. /**
  10742. * Enable or disable the display of this column.
  10743. * @type boolean
  10744. * @default true
  10745. *
  10746. * @name DataTable.defaults.column.visible
  10747. * @dtopt Columns
  10748. *
  10749. * @example
  10750. * // Using `columnDefs`
  10751. * $(document).ready( function() {
  10752. * $('#example').dataTable( {
  10753. * "columnDefs": [
  10754. * { "visible": false, "targets": [ 0 ] }
  10755. * ] } );
  10756. * } );
  10757. *
  10758. * @example
  10759. * // Using `columns`
  10760. * $(document).ready( function() {
  10761. * $('#example').dataTable( {
  10762. * "columns": [
  10763. * { "visible": false },
  10764. * null,
  10765. * null,
  10766. * null,
  10767. * null
  10768. * ] } );
  10769. * } );
  10770. */
  10771. "bVisible": true,
  10772. /**
  10773. * Developer definable function that is called whenever a cell is created (Ajax source,
  10774. * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  10775. * allowing you to modify the DOM element (add background colour for example) when the
  10776. * element is available.
  10777. * @type function
  10778. * @param {element} td The TD node that has been created
  10779. * @param {*} cellData The Data for the cell
  10780. * @param {array|object} rowData The data for the whole row
  10781. * @param {int} row The row index for the aoData data store
  10782. * @param {int} col The column index for aoColumns
  10783. *
  10784. * @name DataTable.defaults.column.createdCell
  10785. * @dtopt Columns
  10786. *
  10787. * @example
  10788. * $(document).ready( function() {
  10789. * $('#example').dataTable( {
  10790. * "columnDefs": [ {
  10791. * "targets": [3],
  10792. * "createdCell": function (td, cellData, rowData, row, col) {
  10793. * if ( cellData == "1.7" ) {
  10794. * $(td).css('color', 'blue')
  10795. * }
  10796. * }
  10797. * } ]
  10798. * });
  10799. * } );
  10800. */
  10801. "fnCreatedCell": null,
  10802. /**
  10803. * This parameter has been replaced by `data` in DataTables to ensure naming
  10804. * consistency. `dataProp` can still be used, as there is backwards
  10805. * compatibility in DataTables for this option, but it is strongly
  10806. * recommended that you use `data` in preference to `dataProp`.
  10807. * @name DataTable.defaults.column.dataProp
  10808. */
  10809. /**
  10810. * This property can be used to read data from any data source property,
  10811. * including deeply nested objects / properties. `data` can be given in a
  10812. * number of different ways which effect its behaviour:
  10813. *
  10814. * * `integer` - treated as an array index for the data source. This is the
  10815. * default that DataTables uses (incrementally increased for each column).
  10816. * * `string` - read an object property from the data source. There are
  10817. * three 'special' options that can be used in the string to alter how
  10818. * DataTables reads the data from the source object:
  10819. * * `.` - Dotted Javascript notation. Just as you use a `.` in
  10820. * Javascript to read from nested objects, so to can the options
  10821. * specified in `data`. For example: `browser.version` or
  10822. * `browser.name`. If your object parameter name contains a period, use
  10823. * `\\` to escape it - i.e. `first\\.name`.
  10824. * * `[]` - Array notation. DataTables can automatically combine data
  10825. * from and array source, joining the data with the characters provided
  10826. * between the two brackets. For example: `name[, ]` would provide a
  10827. * comma-space separated list from the source array. If no characters
  10828. * are provided between the brackets, the original array source is
  10829. * returned.
  10830. * * `()` - Function notation. Adding `()` to the end of a parameter will
  10831. * execute a function of the name given. For example: `browser()` for a
  10832. * simple function on the data source, `browser.version()` for a
  10833. * function in a nested property or even `browser().version` to get an
  10834. * object property if the function called returns an object. Note that
  10835. * function notation is recommended for use in `render` rather than
  10836. * `data` as it is much simpler to use as a renderer.
  10837. * * `null` - use the original data source for the row rather than plucking
  10838. * data directly from it. This action has effects on two other
  10839. * initialisation options:
  10840. * * `defaultContent` - When null is given as the `data` option and
  10841. * `defaultContent` is specified for the column, the value defined by
  10842. * `defaultContent` will be used for the cell.
  10843. * * `render` - When null is used for the `data` option and the `render`
  10844. * option is specified for the column, the whole data source for the
  10845. * row is used for the renderer.
  10846. * * `function` - the function given will be executed whenever DataTables
  10847. * needs to set or get the data for a cell in the column. The function
  10848. * takes three parameters:
  10849. * * Parameters:
  10850. * * `{array|object}` The data source for the row
  10851. * * `{string}` The type call data requested - this will be 'set' when
  10852. * setting data or 'filter', 'display', 'type', 'sort' or undefined
  10853. * when gathering data. Note that when `undefined` is given for the
  10854. * type DataTables expects to get the raw data for the object back<
  10855. * * `{*}` Data to set when the second parameter is 'set'.
  10856. * * Return:
  10857. * * The return value from the function is not required when 'set' is
  10858. * the type of call, but otherwise the return is what will be used
  10859. * for the data requested.
  10860. *
  10861. * Note that `data` is a getter and setter option. If you just require
  10862. * formatting of data for output, you will likely want to use `render` which
  10863. * is simply a getter and thus simpler to use.
  10864. *
  10865. * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
  10866. * name change reflects the flexibility of this property and is consistent
  10867. * with the naming of mRender. If 'mDataProp' is given, then it will still
  10868. * be used by DataTables, as it automatically maps the old name to the new
  10869. * if required.
  10870. *
  10871. * @type string|int|function|null
  10872. * @default null <i>Use automatically calculated column index</i>
  10873. *
  10874. * @name DataTable.defaults.column.data
  10875. * @dtopt Columns
  10876. *
  10877. * @example
  10878. * // Read table data from objects
  10879. * // JSON structure for each row:
  10880. * // {
  10881. * // "engine": {value},
  10882. * // "browser": {value},
  10883. * // "platform": {value},
  10884. * // "version": {value},
  10885. * // "grade": {value}
  10886. * // }
  10887. * $(document).ready( function() {
  10888. * $('#example').dataTable( {
  10889. * "ajaxSource": "sources/objects.txt",
  10890. * "columns": [
  10891. * { "data": "engine" },
  10892. * { "data": "browser" },
  10893. * { "data": "platform" },
  10894. * { "data": "version" },
  10895. * { "data": "grade" }
  10896. * ]
  10897. * } );
  10898. * } );
  10899. *
  10900. * @example
  10901. * // Read information from deeply nested objects
  10902. * // JSON structure for each row:
  10903. * // {
  10904. * // "engine": {value},
  10905. * // "browser": {value},
  10906. * // "platform": {
  10907. * // "inner": {value}
  10908. * // },
  10909. * // "details": [
  10910. * // {value}, {value}
  10911. * // ]
  10912. * // }
  10913. * $(document).ready( function() {
  10914. * $('#example').dataTable( {
  10915. * "ajaxSource": "sources/deep.txt",
  10916. * "columns": [
  10917. * { "data": "engine" },
  10918. * { "data": "browser" },
  10919. * { "data": "platform.inner" },
  10920. * { "data": "details.0" },
  10921. * { "data": "details.1" }
  10922. * ]
  10923. * } );
  10924. * } );
  10925. *
  10926. * @example
  10927. * // Using `data` as a function to provide different information for
  10928. * // sorting, filtering and display. In this case, currency (price)
  10929. * $(document).ready( function() {
  10930. * $('#example').dataTable( {
  10931. * "columnDefs": [ {
  10932. * "targets": [ 0 ],
  10933. * "data": function ( source, type, val ) {
  10934. * if (type === 'set') {
  10935. * source.price = val;
  10936. * // Store the computed display and filter values for efficiency
  10937. * source.price_display = val=="" ? "" : "$"+numberFormat(val);
  10938. * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
  10939. * return;
  10940. * }
  10941. * else if (type === 'display') {
  10942. * return source.price_display;
  10943. * }
  10944. * else if (type === 'filter') {
  10945. * return source.price_filter;
  10946. * }
  10947. * // 'sort', 'type' and undefined all just use the integer
  10948. * return source.price;
  10949. * }
  10950. * } ]
  10951. * } );
  10952. * } );
  10953. *
  10954. * @example
  10955. * // Using default content
  10956. * $(document).ready( function() {
  10957. * $('#example').dataTable( {
  10958. * "columnDefs": [ {
  10959. * "targets": [ 0 ],
  10960. * "data": null,
  10961. * "defaultContent": "Click to edit"
  10962. * } ]
  10963. * } );
  10964. * } );
  10965. *
  10966. * @example
  10967. * // Using array notation - outputting a list from an array
  10968. * $(document).ready( function() {
  10969. * $('#example').dataTable( {
  10970. * "columnDefs": [ {
  10971. * "targets": [ 0 ],
  10972. * "data": "name[, ]"
  10973. * } ]
  10974. * } );
  10975. * } );
  10976. *
  10977. */
  10978. "mData": null,
  10979. /**
  10980. * This property is the rendering partner to `data` and it is suggested that
  10981. * when you want to manipulate data for display (including filtering,
  10982. * sorting etc) without altering the underlying data for the table, use this
  10983. * property. `render` can be considered to be the the read only companion to
  10984. * `data` which is read / write (then as such more complex). Like `data`
  10985. * this option can be given in a number of different ways to effect its
  10986. * behaviour:
  10987. *
  10988. * * `integer` - treated as an array index for the data source. This is the
  10989. * default that DataTables uses (incrementally increased for each column).
  10990. * * `string` - read an object property from the data source. There are
  10991. * three 'special' options that can be used in the string to alter how
  10992. * DataTables reads the data from the source object:
  10993. * * `.` - Dotted Javascript notation. Just as you use a `.` in
  10994. * Javascript to read from nested objects, so to can the options
  10995. * specified in `data`. For example: `browser.version` or
  10996. * `browser.name`. If your object parameter name contains a period, use
  10997. * `\\` to escape it - i.e. `first\\.name`.
  10998. * * `[]` - Array notation. DataTables can automatically combine data
  10999. * from and array source, joining the data with the characters provided
  11000. * between the two brackets. For example: `name[, ]` would provide a
  11001. * comma-space separated list from the source array. If no characters
  11002. * are provided between the brackets, the original array source is
  11003. * returned.
  11004. * * `()` - Function notation. Adding `()` to the end of a parameter will
  11005. * execute a function of the name given. For example: `browser()` for a
  11006. * simple function on the data source, `browser.version()` for a
  11007. * function in a nested property or even `browser().version` to get an
  11008. * object property if the function called returns an object.
  11009. * * `object` - use different data for the different data types requested by
  11010. * DataTables ('filter', 'display', 'type' or 'sort'). The property names
  11011. * of the object is the data type the property refers to and the value can
  11012. * defined using an integer, string or function using the same rules as
  11013. * `render` normally does. Note that an `_` option _must_ be specified.
  11014. * This is the default value to use if you haven't specified a value for
  11015. * the data type requested by DataTables.
  11016. * * `function` - the function given will be executed whenever DataTables
  11017. * needs to set or get the data for a cell in the column. The function
  11018. * takes three parameters:
  11019. * * Parameters:
  11020. * * {array|object} The data source for the row (based on `data`)
  11021. * * {string} The type call data requested - this will be 'filter',
  11022. * 'display', 'type' or 'sort'.
  11023. * * {array|object} The full data source for the row (not based on
  11024. * `data`)
  11025. * * Return:
  11026. * * The return value from the function is what will be used for the
  11027. * data requested.
  11028. *
  11029. * @type string|int|function|object|null
  11030. * @default null Use the data source value.
  11031. *
  11032. * @name DataTable.defaults.column.render
  11033. * @dtopt Columns
  11034. *
  11035. * @example
  11036. * // Create a comma separated list from an array of objects
  11037. * $(document).ready( function() {
  11038. * $('#example').dataTable( {
  11039. * "ajaxSource": "sources/deep.txt",
  11040. * "columns": [
  11041. * { "data": "engine" },
  11042. * { "data": "browser" },
  11043. * {
  11044. * "data": "platform",
  11045. * "render": "[, ].name"
  11046. * }
  11047. * ]
  11048. * } );
  11049. * } );
  11050. *
  11051. * @example
  11052. * // Execute a function to obtain data
  11053. * $(document).ready( function() {
  11054. * $('#example').dataTable( {
  11055. * "columnDefs": [ {
  11056. * "targets": [ 0 ],
  11057. * "data": null, // Use the full data source object for the renderer's source
  11058. * "render": "browserName()"
  11059. * } ]
  11060. * } );
  11061. * } );
  11062. *
  11063. * @example
  11064. * // As an object, extracting different data for the different types
  11065. * // This would be used with a data source such as:
  11066. * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
  11067. * // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
  11068. * // (which has both forms) is used for filtering for if a user inputs either format, while
  11069. * // the formatted phone number is the one that is shown in the table.
  11070. * $(document).ready( function() {
  11071. * $('#example').dataTable( {
  11072. * "columnDefs": [ {
  11073. * "targets": [ 0 ],
  11074. * "data": null, // Use the full data source object for the renderer's source
  11075. * "render": {
  11076. * "_": "phone",
  11077. * "filter": "phone_filter",
  11078. * "display": "phone_display"
  11079. * }
  11080. * } ]
  11081. * } );
  11082. * } );
  11083. *
  11084. * @example
  11085. * // Use as a function to create a link from the data source
  11086. * $(document).ready( function() {
  11087. * $('#example').dataTable( {
  11088. * "columnDefs": [ {
  11089. * "targets": [ 0 ],
  11090. * "data": "download_link",
  11091. * "render": function ( data, type, full ) {
  11092. * return '<a href="'+data+'">Download</a>';
  11093. * }
  11094. * } ]
  11095. * } );
  11096. * } );
  11097. */
  11098. "mRender": null,
  11099. /**
  11100. * Change the cell type created for the column - either TD cells or TH cells. This
  11101. * can be useful as TH cells have semantic meaning in the table body, allowing them
  11102. * to act as a header for a row (you may wish to add scope='row' to the TH elements).
  11103. * @type string
  11104. * @default td
  11105. *
  11106. * @name DataTable.defaults.column.cellType
  11107. * @dtopt Columns
  11108. *
  11109. * @example
  11110. * // Make the first column use TH cells
  11111. * $(document).ready( function() {
  11112. * $('#example').dataTable( {
  11113. * "columnDefs": [ {
  11114. * "targets": [ 0 ],
  11115. * "cellType": "th"
  11116. * } ]
  11117. * } );
  11118. * } );
  11119. */
  11120. "sCellType": "td",
  11121. /**
  11122. * Class to give to each cell in this column.
  11123. * @type string
  11124. * @default <i>Empty string</i>
  11125. *
  11126. * @name DataTable.defaults.column.class
  11127. * @dtopt Columns
  11128. *
  11129. * @example
  11130. * // Using `columnDefs`
  11131. * $(document).ready( function() {
  11132. * $('#example').dataTable( {
  11133. * "columnDefs": [
  11134. * { "class": "my_class", "targets": [ 0 ] }
  11135. * ]
  11136. * } );
  11137. * } );
  11138. *
  11139. * @example
  11140. * // Using `columns`
  11141. * $(document).ready( function() {
  11142. * $('#example').dataTable( {
  11143. * "columns": [
  11144. * { "class": "my_class" },
  11145. * null,
  11146. * null,
  11147. * null,
  11148. * null
  11149. * ]
  11150. * } );
  11151. * } );
  11152. */
  11153. "sClass": "",
  11154. /**
  11155. * When DataTables calculates the column widths to assign to each column,
  11156. * it finds the longest string in each column and then constructs a
  11157. * temporary table and reads the widths from that. The problem with this
  11158. * is that "mmm" is much wider then "iiii", but the latter is a longer
  11159. * string - thus the calculation can go wrong (doing it properly and putting
  11160. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  11161. * a "work around" we provide this option. It will append its value to the
  11162. * text that is found to be the longest string for the column - i.e. padding.
  11163. * Generally you shouldn't need this!
  11164. * @type string
  11165. * @default <i>Empty string<i>
  11166. *
  11167. * @name DataTable.defaults.column.contentPadding
  11168. * @dtopt Columns
  11169. *
  11170. * @example
  11171. * // Using `columns`
  11172. * $(document).ready( function() {
  11173. * $('#example').dataTable( {
  11174. * "columns": [
  11175. * null,
  11176. * null,
  11177. * null,
  11178. * {
  11179. * "contentPadding": "mmm"
  11180. * }
  11181. * ]
  11182. * } );
  11183. * } );
  11184. */
  11185. "sContentPadding": "",
  11186. /**
  11187. * Allows a default value to be given for a column's data, and will be used
  11188. * whenever a null data source is encountered (this can be because `data`
  11189. * is set to null, or because the data source itself is null).
  11190. * @type string
  11191. * @default null
  11192. *
  11193. * @name DataTable.defaults.column.defaultContent
  11194. * @dtopt Columns
  11195. *
  11196. * @example
  11197. * // Using `columnDefs`
  11198. * $(document).ready( function() {
  11199. * $('#example').dataTable( {
  11200. * "columnDefs": [
  11201. * {
  11202. * "data": null,
  11203. * "defaultContent": "Edit",
  11204. * "targets": [ -1 ]
  11205. * }
  11206. * ]
  11207. * } );
  11208. * } );
  11209. *
  11210. * @example
  11211. * // Using `columns`
  11212. * $(document).ready( function() {
  11213. * $('#example').dataTable( {
  11214. * "columns": [
  11215. * null,
  11216. * null,
  11217. * null,
  11218. * {
  11219. * "data": null,
  11220. * "defaultContent": "Edit"
  11221. * }
  11222. * ]
  11223. * } );
  11224. * } );
  11225. */
  11226. "sDefaultContent": null,
  11227. /**
  11228. * This parameter is only used in DataTables' server-side processing. It can
  11229. * be exceptionally useful to know what columns are being displayed on the
  11230. * client side, and to map these to database fields. When defined, the names
  11231. * also allow DataTables to reorder information from the server if it comes
  11232. * back in an unexpected order (i.e. if you switch your columns around on the
  11233. * client-side, your server-side code does not also need updating).
  11234. * @type string
  11235. * @default <i>Empty string</i>
  11236. *
  11237. * @name DataTable.defaults.column.name
  11238. * @dtopt Columns
  11239. *
  11240. * @example
  11241. * // Using `columnDefs`
  11242. * $(document).ready( function() {
  11243. * $('#example').dataTable( {
  11244. * "columnDefs": [
  11245. * { "name": "engine", "targets": [ 0 ] },
  11246. * { "name": "browser", "targets": [ 1 ] },
  11247. * { "name": "platform", "targets": [ 2 ] },
  11248. * { "name": "version", "targets": [ 3 ] },
  11249. * { "name": "grade", "targets": [ 4 ] }
  11250. * ]
  11251. * } );
  11252. * } );
  11253. *
  11254. * @example
  11255. * // Using `columns`
  11256. * $(document).ready( function() {
  11257. * $('#example').dataTable( {
  11258. * "columns": [
  11259. * { "name": "engine" },
  11260. * { "name": "browser" },
  11261. * { "name": "platform" },
  11262. * { "name": "version" },
  11263. * { "name": "grade" }
  11264. * ]
  11265. * } );
  11266. * } );
  11267. */
  11268. "sName": "",
  11269. /**
  11270. * Defines a data source type for the ordering which can be used to read
  11271. * real-time information from the table (updating the internally cached
  11272. * version) prior to ordering. This allows ordering to occur on user
  11273. * editable elements such as form inputs.
  11274. * @type string
  11275. * @default std
  11276. *
  11277. * @name DataTable.defaults.column.orderDataType
  11278. * @dtopt Columns
  11279. *
  11280. * @example
  11281. * // Using `columnDefs`
  11282. * $(document).ready( function() {
  11283. * $('#example').dataTable( {
  11284. * "columnDefs": [
  11285. * { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
  11286. * { "type": "numeric", "targets": [ 3 ] },
  11287. * { "orderDataType": "dom-select", "targets": [ 4 ] },
  11288. * { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
  11289. * ]
  11290. * } );
  11291. * } );
  11292. *
  11293. * @example
  11294. * // Using `columns`
  11295. * $(document).ready( function() {
  11296. * $('#example').dataTable( {
  11297. * "columns": [
  11298. * null,
  11299. * null,
  11300. * { "orderDataType": "dom-text" },
  11301. * { "orderDataType": "dom-text", "type": "numeric" },
  11302. * { "orderDataType": "dom-select" },
  11303. * { "orderDataType": "dom-checkbox" }
  11304. * ]
  11305. * } );
  11306. * } );
  11307. */
  11308. "sSortDataType": "std",
  11309. /**
  11310. * The title of this column.
  11311. * @type string
  11312. * @default null <i>Derived from the 'TH' value for this column in the
  11313. * original HTML table.</i>
  11314. *
  11315. * @name DataTable.defaults.column.title
  11316. * @dtopt Columns
  11317. *
  11318. * @example
  11319. * // Using `columnDefs`
  11320. * $(document).ready( function() {
  11321. * $('#example').dataTable( {
  11322. * "columnDefs": [
  11323. * { "title": "My column title", "targets": [ 0 ] }
  11324. * ]
  11325. * } );
  11326. * } );
  11327. *
  11328. * @example
  11329. * // Using `columns`
  11330. * $(document).ready( function() {
  11331. * $('#example').dataTable( {
  11332. * "columns": [
  11333. * { "title": "My column title" },
  11334. * null,
  11335. * null,
  11336. * null,
  11337. * null
  11338. * ]
  11339. * } );
  11340. * } );
  11341. */
  11342. "sTitle": null,
  11343. /**
  11344. * The type allows you to specify how the data for this column will be
  11345. * ordered. Four types (string, numeric, date and html (which will strip
  11346. * HTML tags before ordering)) are currently available. Note that only date
  11347. * formats understood by Javascript's Date() object will be accepted as type
  11348. * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
  11349. * 'numeric', 'date' or 'html' (by default). Further types can be adding
  11350. * through plug-ins.
  11351. * @type string
  11352. * @default null <i>Auto-detected from raw data</i>
  11353. *
  11354. * @name DataTable.defaults.column.type
  11355. * @dtopt Columns
  11356. *
  11357. * @example
  11358. * // Using `columnDefs`
  11359. * $(document).ready( function() {
  11360. * $('#example').dataTable( {
  11361. * "columnDefs": [
  11362. * { "type": "html", "targets": [ 0 ] }
  11363. * ]
  11364. * } );
  11365. * } );
  11366. *
  11367. * @example
  11368. * // Using `columns`
  11369. * $(document).ready( function() {
  11370. * $('#example').dataTable( {
  11371. * "columns": [
  11372. * { "type": "html" },
  11373. * null,
  11374. * null,
  11375. * null,
  11376. * null
  11377. * ]
  11378. * } );
  11379. * } );
  11380. */
  11381. "sType": null,
  11382. /**
  11383. * Defining the width of the column, this parameter may take any CSS value
  11384. * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
  11385. * been given a specific width through this interface ensuring that the table
  11386. * remains readable.
  11387. * @type string
  11388. * @default null <i>Automatic</i>
  11389. *
  11390. * @name DataTable.defaults.column.width
  11391. * @dtopt Columns
  11392. *
  11393. * @example
  11394. * // Using `columnDefs`
  11395. * $(document).ready( function() {
  11396. * $('#example').dataTable( {
  11397. * "columnDefs": [
  11398. * { "width": "20%", "targets": [ 0 ] }
  11399. * ]
  11400. * } );
  11401. * } );
  11402. *
  11403. * @example
  11404. * // Using `columns`
  11405. * $(document).ready( function() {
  11406. * $('#example').dataTable( {
  11407. * "columns": [
  11408. * { "width": "20%" },
  11409. * null,
  11410. * null,
  11411. * null,
  11412. * null
  11413. * ]
  11414. * } );
  11415. * } );
  11416. */
  11417. "sWidth": null
  11418. };
  11419. _fnHungarianMap( DataTable.defaults.column );
  11420. /**
  11421. * DataTables settings object - this holds all the information needed for a
  11422. * given table, including configuration, data and current application of the
  11423. * table options. DataTables does not have a single instance for each DataTable
  11424. * with the settings attached to that instance, but rather instances of the
  11425. * DataTable "class" are created on-the-fly as needed (typically by a
  11426. * $().dataTable() call) and the settings object is then applied to that
  11427. * instance.
  11428. *
  11429. * Note that this object is related to {@link DataTable.defaults} but this
  11430. * one is the internal data store for DataTables's cache of columns. It should
  11431. * NOT be manipulated outside of DataTables. Any configuration should be done
  11432. * through the initialisation options.
  11433. * @namespace
  11434. * @todo Really should attach the settings object to individual instances so we
  11435. * don't need to create new instances on each $().dataTable() call (if the
  11436. * table already exists). It would also save passing oSettings around and
  11437. * into every single function. However, this is a very significant
  11438. * architecture change for DataTables and will almost certainly break
  11439. * backwards compatibility with older installations. This is something that
  11440. * will be done in 2.0.
  11441. */
  11442. DataTable.models.oSettings = {
  11443. /**
  11444. * Primary features of DataTables and their enablement state.
  11445. * @namespace
  11446. */
  11447. "oFeatures": {
  11448. /**
  11449. * Flag to say if DataTables should automatically try to calculate the
  11450. * optimum table and columns widths (true) or not (false).
  11451. * Note that this parameter will be set by the initialisation routine. To
  11452. * set a default use {@link DataTable.defaults}.
  11453. * @type boolean
  11454. */
  11455. "bAutoWidth": null,
  11456. /**
  11457. * Delay the creation of TR and TD elements until they are actually
  11458. * needed by a driven page draw. This can give a significant speed
  11459. * increase for Ajax source and Javascript source data, but makes no
  11460. * difference at all for DOM and server-side processing tables.
  11461. * Note that this parameter will be set by the initialisation routine. To
  11462. * set a default use {@link DataTable.defaults}.
  11463. * @type boolean
  11464. */
  11465. "bDeferRender": null,
  11466. /**
  11467. * Enable filtering on the table or not. Note that if this is disabled
  11468. * then there is no filtering at all on the table, including fnFilter.
  11469. * To just remove the filtering input use sDom and remove the 'f' option.
  11470. * Note that this parameter will be set by the initialisation routine. To
  11471. * set a default use {@link DataTable.defaults}.
  11472. * @type boolean
  11473. */
  11474. "bFilter": null,
  11475. /**
  11476. * Table information element (the 'Showing x of y records' div) enable
  11477. * flag.
  11478. * Note that this parameter will be set by the initialisation routine. To
  11479. * set a default use {@link DataTable.defaults}.
  11480. * @type boolean
  11481. */
  11482. "bInfo": null,
  11483. /**
  11484. * Present a user control allowing the end user to change the page size
  11485. * when pagination is enabled.
  11486. * Note that this parameter will be set by the initialisation routine. To
  11487. * set a default use {@link DataTable.defaults}.
  11488. * @type boolean
  11489. */
  11490. "bLengthChange": null,
  11491. /**
  11492. * Pagination enabled or not. Note that if this is disabled then length
  11493. * changing must also be disabled.
  11494. * Note that this parameter will be set by the initialisation routine. To
  11495. * set a default use {@link DataTable.defaults}.
  11496. * @type boolean
  11497. */
  11498. "bPaginate": null,
  11499. /**
  11500. * Processing indicator enable flag whenever DataTables is enacting a
  11501. * user request - typically an Ajax request for server-side processing.
  11502. * Note that this parameter will be set by the initialisation routine. To
  11503. * set a default use {@link DataTable.defaults}.
  11504. * @type boolean
  11505. */
  11506. "bProcessing": null,
  11507. /**
  11508. * Server-side processing enabled flag - when enabled DataTables will
  11509. * get all data from the server for every draw - there is no filtering,
  11510. * sorting or paging done on the client-side.
  11511. * Note that this parameter will be set by the initialisation routine. To
  11512. * set a default use {@link DataTable.defaults}.
  11513. * @type boolean
  11514. */
  11515. "bServerSide": null,
  11516. /**
  11517. * Sorting enablement flag.
  11518. * Note that this parameter will be set by the initialisation routine. To
  11519. * set a default use {@link DataTable.defaults}.
  11520. * @type boolean
  11521. */
  11522. "bSort": null,
  11523. /**
  11524. * Multi-column sorting
  11525. * Note that this parameter will be set by the initialisation routine. To
  11526. * set a default use {@link DataTable.defaults}.
  11527. * @type boolean
  11528. */
  11529. "bSortMulti": null,
  11530. /**
  11531. * Apply a class to the columns which are being sorted to provide a
  11532. * visual highlight or not. This can slow things down when enabled since
  11533. * there is a lot of DOM interaction.
  11534. * Note that this parameter will be set by the initialisation routine. To
  11535. * set a default use {@link DataTable.defaults}.
  11536. * @type boolean
  11537. */
  11538. "bSortClasses": null,
  11539. /**
  11540. * State saving enablement flag.
  11541. * Note that this parameter will be set by the initialisation routine. To
  11542. * set a default use {@link DataTable.defaults}.
  11543. * @type boolean
  11544. */
  11545. "bStateSave": null
  11546. },
  11547. /**
  11548. * Scrolling settings for a table.
  11549. * @namespace
  11550. */
  11551. "oScroll": {
  11552. /**
  11553. * When the table is shorter in height than sScrollY, collapse the
  11554. * table container down to the height of the table (when true).
  11555. * Note that this parameter will be set by the initialisation routine. To
  11556. * set a default use {@link DataTable.defaults}.
  11557. * @type boolean
  11558. */
  11559. "bCollapse": null,
  11560. /**
  11561. * Width of the scrollbar for the web-browser's platform. Calculated
  11562. * during table initialisation.
  11563. * @type int
  11564. * @default 0
  11565. */
  11566. "iBarWidth": 0,
  11567. /**
  11568. * Viewport width for horizontal scrolling. Horizontal scrolling is
  11569. * disabled if an empty string.
  11570. * Note that this parameter will be set by the initialisation routine. To
  11571. * set a default use {@link DataTable.defaults}.
  11572. * @type string
  11573. */
  11574. "sX": null,
  11575. /**
  11576. * Width to expand the table to when using x-scrolling. Typically you
  11577. * should not need to use this.
  11578. * Note that this parameter will be set by the initialisation routine. To
  11579. * set a default use {@link DataTable.defaults}.
  11580. * @type string
  11581. * @deprecated
  11582. */
  11583. "sXInner": null,
  11584. /**
  11585. * Viewport height for vertical scrolling. Vertical scrolling is disabled
  11586. * if an empty string.
  11587. * Note that this parameter will be set by the initialisation routine. To
  11588. * set a default use {@link DataTable.defaults}.
  11589. * @type string
  11590. */
  11591. "sY": null
  11592. },
  11593. /**
  11594. * Language information for the table.
  11595. * @namespace
  11596. * @extends DataTable.defaults.oLanguage
  11597. */
  11598. "oLanguage": {
  11599. /**
  11600. * Information callback function. See
  11601. * {@link DataTable.defaults.fnInfoCallback}
  11602. * @type function
  11603. * @default null
  11604. */
  11605. "fnInfoCallback": null
  11606. },
  11607. /**
  11608. * Browser support parameters
  11609. * @namespace
  11610. */
  11611. "oBrowser": {
  11612. /**
  11613. * Indicate if the browser incorrectly calculates width:100% inside a
  11614. * scrolling element (IE6/7)
  11615. * @type boolean
  11616. * @default false
  11617. */
  11618. "bScrollOversize": false,
  11619. /**
  11620. * Determine if the vertical scrollbar is on the right or left of the
  11621. * scrolling container - needed for rtl language layout, although not
  11622. * all browsers move the scrollbar (Safari).
  11623. * @type boolean
  11624. * @default false
  11625. */
  11626. "bScrollbarLeft": false,
  11627. /**
  11628. * Flag for if `getBoundingClientRect` is fully supported or not
  11629. * @type boolean
  11630. * @default false
  11631. */
  11632. "bBounding": false,
  11633. /**
  11634. * Browser scrollbar width
  11635. * @type integer
  11636. * @default 0
  11637. */
  11638. "barWidth": 0
  11639. },
  11640. "ajax": null,
  11641. /**
  11642. * Array referencing the nodes which are used for the features. The
  11643. * parameters of this object match what is allowed by sDom - i.e.
  11644. * <ul>
  11645. * <li>'l' - Length changing</li>
  11646. * <li>'f' - Filtering input</li>
  11647. * <li>'t' - The table!</li>
  11648. * <li>'i' - Information</li>
  11649. * <li>'p' - Pagination</li>
  11650. * <li>'r' - pRocessing</li>
  11651. * </ul>
  11652. * @type array
  11653. * @default []
  11654. */
  11655. "aanFeatures": [],
  11656. /**
  11657. * Store data information - see {@link DataTable.models.oRow} for detailed
  11658. * information.
  11659. * @type array
  11660. * @default []
  11661. */
  11662. "aoData": [],
  11663. /**
  11664. * Array of indexes which are in the current display (after filtering etc)
  11665. * @type array
  11666. * @default []
  11667. */
  11668. "aiDisplay": [],
  11669. /**
  11670. * Array of indexes for display - no filtering
  11671. * @type array
  11672. * @default []
  11673. */
  11674. "aiDisplayMaster": [],
  11675. /**
  11676. * Map of row ids to data indexes
  11677. * @type object
  11678. * @default {}
  11679. */
  11680. "aIds": {},
  11681. /**
  11682. * Store information about each column that is in use
  11683. * @type array
  11684. * @default []
  11685. */
  11686. "aoColumns": [],
  11687. /**
  11688. * Store information about the table's header
  11689. * @type array
  11690. * @default []
  11691. */
  11692. "aoHeader": [],
  11693. /**
  11694. * Store information about the table's footer
  11695. * @type array
  11696. * @default []
  11697. */
  11698. "aoFooter": [],
  11699. /**
  11700. * Store the applied global search information in case we want to force a
  11701. * research or compare the old search to a new one.
  11702. * Note that this parameter will be set by the initialisation routine. To
  11703. * set a default use {@link DataTable.defaults}.
  11704. * @namespace
  11705. * @extends DataTable.models.oSearch
  11706. */
  11707. "oPreviousSearch": {},
  11708. /**
  11709. * Store the applied search for each column - see
  11710. * {@link DataTable.models.oSearch} for the format that is used for the
  11711. * filtering information for each column.
  11712. * @type array
  11713. * @default []
  11714. */
  11715. "aoPreSearchCols": [],
  11716. /**
  11717. * Sorting that is applied to the table. Note that the inner arrays are
  11718. * used in the following manner:
  11719. * <ul>
  11720. * <li>Index 0 - column number</li>
  11721. * <li>Index 1 - current sorting direction</li>
  11722. * </ul>
  11723. * Note that this parameter will be set by the initialisation routine. To
  11724. * set a default use {@link DataTable.defaults}.
  11725. * @type array
  11726. * @todo These inner arrays should really be objects
  11727. */
  11728. "aaSorting": null,
  11729. /**
  11730. * Sorting that is always applied to the table (i.e. prefixed in front of
  11731. * aaSorting).
  11732. * Note that this parameter will be set by the initialisation routine. To
  11733. * set a default use {@link DataTable.defaults}.
  11734. * @type array
  11735. * @default []
  11736. */
  11737. "aaSortingFixed": [],
  11738. /**
  11739. * Classes to use for the striping of a table.
  11740. * Note that this parameter will be set by the initialisation routine. To
  11741. * set a default use {@link DataTable.defaults}.
  11742. * @type array
  11743. * @default []
  11744. */
  11745. "asStripeClasses": null,
  11746. /**
  11747. * If restoring a table - we should restore its striping classes as well
  11748. * @type array
  11749. * @default []
  11750. */
  11751. "asDestroyStripes": [],
  11752. /**
  11753. * If restoring a table - we should restore its width
  11754. * @type int
  11755. * @default 0
  11756. */
  11757. "sDestroyWidth": 0,
  11758. /**
  11759. * Callback functions array for every time a row is inserted (i.e. on a draw).
  11760. * @type array
  11761. * @default []
  11762. */
  11763. "aoRowCallback": [],
  11764. /**
  11765. * Callback functions for the header on each draw.
  11766. * @type array
  11767. * @default []
  11768. */
  11769. "aoHeaderCallback": [],
  11770. /**
  11771. * Callback function for the footer on each draw.
  11772. * @type array
  11773. * @default []
  11774. */
  11775. "aoFooterCallback": [],
  11776. /**
  11777. * Array of callback functions for draw callback functions
  11778. * @type array
  11779. * @default []
  11780. */
  11781. "aoDrawCallback": [],
  11782. /**
  11783. * Array of callback functions for row created function
  11784. * @type array
  11785. * @default []
  11786. */
  11787. "aoRowCreatedCallback": [],
  11788. /**
  11789. * Callback functions for just before the table is redrawn. A return of
  11790. * false will be used to cancel the draw.
  11791. * @type array
  11792. * @default []
  11793. */
  11794. "aoPreDrawCallback": [],
  11795. /**
  11796. * Callback functions for when the table has been initialised.
  11797. * @type array
  11798. * @default []
  11799. */
  11800. "aoInitComplete": [],
  11801. /**
  11802. * Callbacks for modifying the settings to be stored for state saving, prior to
  11803. * saving state.
  11804. * @type array
  11805. * @default []
  11806. */
  11807. "aoStateSaveParams": [],
  11808. /**
  11809. * Callbacks for modifying the settings that have been stored for state saving
  11810. * prior to using the stored values to restore the state.
  11811. * @type array
  11812. * @default []
  11813. */
  11814. "aoStateLoadParams": [],
  11815. /**
  11816. * Callbacks for operating on the settings object once the saved state has been
  11817. * loaded
  11818. * @type array
  11819. * @default []
  11820. */
  11821. "aoStateLoaded": [],
  11822. /**
  11823. * Cache the table ID for quick access
  11824. * @type string
  11825. * @default <i>Empty string</i>
  11826. */
  11827. "sTableId": "",
  11828. /**
  11829. * The TABLE node for the main table
  11830. * @type node
  11831. * @default null
  11832. */
  11833. "nTable": null,
  11834. /**
  11835. * Permanent ref to the thead element
  11836. * @type node
  11837. * @default null
  11838. */
  11839. "nTHead": null,
  11840. /**
  11841. * Permanent ref to the tfoot element - if it exists
  11842. * @type node
  11843. * @default null
  11844. */
  11845. "nTFoot": null,
  11846. /**
  11847. * Permanent ref to the tbody element
  11848. * @type node
  11849. * @default null
  11850. */
  11851. "nTBody": null,
  11852. /**
  11853. * Cache the wrapper node (contains all DataTables controlled elements)
  11854. * @type node
  11855. * @default null
  11856. */
  11857. "nTableWrapper": null,
  11858. /**
  11859. * Indicate if when using server-side processing the loading of data
  11860. * should be deferred until the second draw.
  11861. * Note that this parameter will be set by the initialisation routine. To
  11862. * set a default use {@link DataTable.defaults}.
  11863. * @type boolean
  11864. * @default false
  11865. */
  11866. "bDeferLoading": false,
  11867. /**
  11868. * Indicate if all required information has been read in
  11869. * @type boolean
  11870. * @default false
  11871. */
  11872. "bInitialised": false,
  11873. /**
  11874. * Information about open rows. Each object in the array has the parameters
  11875. * 'nTr' and 'nParent'
  11876. * @type array
  11877. * @default []
  11878. */
  11879. "aoOpenRows": [],
  11880. /**
  11881. * Dictate the positioning of DataTables' control elements - see
  11882. * {@link DataTable.model.oInit.sDom}.
  11883. * Note that this parameter will be set by the initialisation routine. To
  11884. * set a default use {@link DataTable.defaults}.
  11885. * @type string
  11886. * @default null
  11887. */
  11888. "sDom": null,
  11889. /**
  11890. * Search delay (in mS)
  11891. * @type integer
  11892. * @default null
  11893. */
  11894. "searchDelay": null,
  11895. /**
  11896. * Which type of pagination should be used.
  11897. * Note that this parameter will be set by the initialisation routine. To
  11898. * set a default use {@link DataTable.defaults}.
  11899. * @type string
  11900. * @default two_button
  11901. */
  11902. "sPaginationType": "two_button",
  11903. /**
  11904. * The state duration (for `stateSave`) in seconds.
  11905. * Note that this parameter will be set by the initialisation routine. To
  11906. * set a default use {@link DataTable.defaults}.
  11907. * @type int
  11908. * @default 0
  11909. */
  11910. "iStateDuration": 0,
  11911. /**
  11912. * Array of callback functions for state saving. Each array element is an
  11913. * object with the following parameters:
  11914. * <ul>
  11915. * <li>function:fn - function to call. Takes two parameters, oSettings
  11916. * and the JSON string to save that has been thus far created. Returns
  11917. * a JSON string to be inserted into a json object
  11918. * (i.e. '"param": [ 0, 1, 2]')</li>
  11919. * <li>string:sName - name of callback</li>
  11920. * </ul>
  11921. * @type array
  11922. * @default []
  11923. */
  11924. "aoStateSave": [],
  11925. /**
  11926. * Array of callback functions for state loading. Each array element is an
  11927. * object with the following parameters:
  11928. * <ul>
  11929. * <li>function:fn - function to call. Takes two parameters, oSettings
  11930. * and the object stored. May return false to cancel state loading</li>
  11931. * <li>string:sName - name of callback</li>
  11932. * </ul>
  11933. * @type array
  11934. * @default []
  11935. */
  11936. "aoStateLoad": [],
  11937. /**
  11938. * State that was saved. Useful for back reference
  11939. * @type object
  11940. * @default null
  11941. */
  11942. "oSavedState": null,
  11943. /**
  11944. * State that was loaded. Useful for back reference
  11945. * @type object
  11946. * @default null
  11947. */
  11948. "oLoadedState": null,
  11949. /**
  11950. * Source url for AJAX data for the table.
  11951. * Note that this parameter will be set by the initialisation routine. To
  11952. * set a default use {@link DataTable.defaults}.
  11953. * @type string
  11954. * @default null
  11955. */
  11956. "sAjaxSource": null,
  11957. /**
  11958. * Property from a given object from which to read the table data from. This
  11959. * can be an empty string (when not server-side processing), in which case
  11960. * it is assumed an an array is given directly.
  11961. * Note that this parameter will be set by the initialisation routine. To
  11962. * set a default use {@link DataTable.defaults}.
  11963. * @type string
  11964. */
  11965. "sAjaxDataProp": null,
  11966. /**
  11967. * The last jQuery XHR object that was used for server-side data gathering.
  11968. * This can be used for working with the XHR information in one of the
  11969. * callbacks
  11970. * @type object
  11971. * @default null
  11972. */
  11973. "jqXHR": null,
  11974. /**
  11975. * JSON returned from the server in the last Ajax request
  11976. * @type object
  11977. * @default undefined
  11978. */
  11979. "json": undefined,
  11980. /**
  11981. * Data submitted as part of the last Ajax request
  11982. * @type object
  11983. * @default undefined
  11984. */
  11985. "oAjaxData": undefined,
  11986. /**
  11987. * Function to get the server-side data.
  11988. * Note that this parameter will be set by the initialisation routine. To
  11989. * set a default use {@link DataTable.defaults}.
  11990. * @type function
  11991. */
  11992. "fnServerData": null,
  11993. /**
  11994. * Functions which are called prior to sending an Ajax request so extra
  11995. * parameters can easily be sent to the server
  11996. * @type array
  11997. * @default []
  11998. */
  11999. "aoServerParams": [],
  12000. /**
  12001. * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
  12002. * required).
  12003. * Note that this parameter will be set by the initialisation routine. To
  12004. * set a default use {@link DataTable.defaults}.
  12005. * @type string
  12006. */
  12007. "sServerMethod": null,
  12008. /**
  12009. * Format numbers for display.
  12010. * Note that this parameter will be set by the initialisation routine. To
  12011. * set a default use {@link DataTable.defaults}.
  12012. * @type function
  12013. */
  12014. "fnFormatNumber": null,
  12015. /**
  12016. * List of options that can be used for the user selectable length menu.
  12017. * Note that this parameter will be set by the initialisation routine. To
  12018. * set a default use {@link DataTable.defaults}.
  12019. * @type array
  12020. * @default []
  12021. */
  12022. "aLengthMenu": null,
  12023. /**
  12024. * Counter for the draws that the table does. Also used as a tracker for
  12025. * server-side processing
  12026. * @type int
  12027. * @default 0
  12028. */
  12029. "iDraw": 0,
  12030. /**
  12031. * Indicate if a redraw is being done - useful for Ajax
  12032. * @type boolean
  12033. * @default false
  12034. */
  12035. "bDrawing": false,
  12036. /**
  12037. * Draw index (iDraw) of the last error when parsing the returned data
  12038. * @type int
  12039. * @default -1
  12040. */
  12041. "iDrawError": -1,
  12042. /**
  12043. * Paging display length
  12044. * @type int
  12045. * @default 10
  12046. */
  12047. "_iDisplayLength": 10,
  12048. /**
  12049. * Paging start point - aiDisplay index
  12050. * @type int
  12051. * @default 0
  12052. */
  12053. "_iDisplayStart": 0,
  12054. /**
  12055. * Server-side processing - number of records in the result set
  12056. * (i.e. before filtering), Use fnRecordsTotal rather than
  12057. * this property to get the value of the number of records, regardless of
  12058. * the server-side processing setting.
  12059. * @type int
  12060. * @default 0
  12061. * @private
  12062. */
  12063. "_iRecordsTotal": 0,
  12064. /**
  12065. * Server-side processing - number of records in the current display set
  12066. * (i.e. after filtering). Use fnRecordsDisplay rather than
  12067. * this property to get the value of the number of records, regardless of
  12068. * the server-side processing setting.
  12069. * @type boolean
  12070. * @default 0
  12071. * @private
  12072. */
  12073. "_iRecordsDisplay": 0,
  12074. /**
  12075. * The classes to use for the table
  12076. * @type object
  12077. * @default {}
  12078. */
  12079. "oClasses": {},
  12080. /**
  12081. * Flag attached to the settings object so you can check in the draw
  12082. * callback if filtering has been done in the draw. Deprecated in favour of
  12083. * events.
  12084. * @type boolean
  12085. * @default false
  12086. * @deprecated
  12087. */
  12088. "bFiltered": false,
  12089. /**
  12090. * Flag attached to the settings object so you can check in the draw
  12091. * callback if sorting has been done in the draw. Deprecated in favour of
  12092. * events.
  12093. * @type boolean
  12094. * @default false
  12095. * @deprecated
  12096. */
  12097. "bSorted": false,
  12098. /**
  12099. * Indicate that if multiple rows are in the header and there is more than
  12100. * one unique cell per column, if the top one (true) or bottom one (false)
  12101. * should be used for sorting / title by DataTables.
  12102. * Note that this parameter will be set by the initialisation routine. To
  12103. * set a default use {@link DataTable.defaults}.
  12104. * @type boolean
  12105. */
  12106. "bSortCellsTop": null,
  12107. /**
  12108. * Initialisation object that is used for the table
  12109. * @type object
  12110. * @default null
  12111. */
  12112. "oInit": null,
  12113. /**
  12114. * Destroy callback functions - for plug-ins to attach themselves to the
  12115. * destroy so they can clean up markup and events.
  12116. * @type array
  12117. * @default []
  12118. */
  12119. "aoDestroyCallback": [],
  12120. /**
  12121. * Get the number of records in the current record set, before filtering
  12122. * @type function
  12123. */
  12124. "fnRecordsTotal": function ()
  12125. {
  12126. return _fnDataSource( this ) == 'ssp' ?
  12127. this._iRecordsTotal * 1 :
  12128. this.aiDisplayMaster.length;
  12129. },
  12130. /**
  12131. * Get the number of records in the current record set, after filtering
  12132. * @type function
  12133. */
  12134. "fnRecordsDisplay": function ()
  12135. {
  12136. return _fnDataSource( this ) == 'ssp' ?
  12137. this._iRecordsDisplay * 1 :
  12138. this.aiDisplay.length;
  12139. },
  12140. /**
  12141. * Get the display end point - aiDisplay index
  12142. * @type function
  12143. */
  12144. "fnDisplayEnd": function ()
  12145. {
  12146. var
  12147. len = this._iDisplayLength,
  12148. start = this._iDisplayStart,
  12149. calc = start + len,
  12150. records = this.aiDisplay.length,
  12151. features = this.oFeatures,
  12152. paginate = features.bPaginate;
  12153. if ( features.bServerSide ) {
  12154. return paginate === false || len === -1 ?
  12155. start + records :
  12156. Math.min( start+len, this._iRecordsDisplay );
  12157. }
  12158. else {
  12159. return ! paginate || calc>records || len===-1 ?
  12160. records :
  12161. calc;
  12162. }
  12163. },
  12164. /**
  12165. * The DataTables object for this table
  12166. * @type object
  12167. * @default null
  12168. */
  12169. "oInstance": null,
  12170. /**
  12171. * Unique identifier for each instance of the DataTables object. If there
  12172. * is an ID on the table node, then it takes that value, otherwise an
  12173. * incrementing internal counter is used.
  12174. * @type string
  12175. * @default null
  12176. */
  12177. "sInstance": null,
  12178. /**
  12179. * tabindex attribute value that is added to DataTables control elements, allowing
  12180. * keyboard navigation of the table and its controls.
  12181. */
  12182. "iTabIndex": 0,
  12183. /**
  12184. * DIV container for the footer scrolling table if scrolling
  12185. */
  12186. "nScrollHead": null,
  12187. /**
  12188. * DIV container for the footer scrolling table if scrolling
  12189. */
  12190. "nScrollFoot": null,
  12191. /**
  12192. * Last applied sort
  12193. * @type array
  12194. * @default []
  12195. */
  12196. "aLastSort": [],
  12197. /**
  12198. * Stored plug-in instances
  12199. * @type object
  12200. * @default {}
  12201. */
  12202. "oPlugins": {},
  12203. /**
  12204. * Function used to get a row's id from the row's data
  12205. * @type function
  12206. * @default null
  12207. */
  12208. "rowIdFn": null,
  12209. /**
  12210. * Data location where to store a row's id
  12211. * @type string
  12212. * @default null
  12213. */
  12214. "rowId": null
  12215. };
  12216. /**
  12217. * Extension object for DataTables that is used to provide all extension
  12218. * options.
  12219. *
  12220. * Note that the `DataTable.ext` object is available through
  12221. * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
  12222. * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
  12223. * @namespace
  12224. * @extends DataTable.models.ext
  12225. */
  12226. /**
  12227. * DataTables extensions
  12228. *
  12229. * This namespace acts as a collection area for plug-ins that can be used to
  12230. * extend DataTables capabilities. Indeed many of the build in methods
  12231. * use this method to provide their own capabilities (sorting methods for
  12232. * example).
  12233. *
  12234. * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
  12235. * reasons
  12236. *
  12237. * @namespace
  12238. */
  12239. DataTable.ext = _ext = {
  12240. /**
  12241. * Buttons. For use with the Buttons extension for DataTables. This is
  12242. * defined here so other extensions can define buttons regardless of load
  12243. * order. It is _not_ used by DataTables core.
  12244. *
  12245. * @type object
  12246. * @default {}
  12247. */
  12248. buttons: {},
  12249. /**
  12250. * Element class names
  12251. *
  12252. * @type object
  12253. * @default {}
  12254. */
  12255. classes: {},
  12256. /**
  12257. * DataTables build type (expanded by the download builder)
  12258. *
  12259. * @type string
  12260. */
  12261. build:"bs5/dt-1.13.1/r-2.4.0/sl-1.5.0",
  12262. /**
  12263. * Error reporting.
  12264. *
  12265. * How should DataTables report an error. Can take the value 'alert',
  12266. * 'throw', 'none' or a function.
  12267. *
  12268. * @type string|function
  12269. * @default alert
  12270. */
  12271. errMode: "alert",
  12272. /**
  12273. * Feature plug-ins.
  12274. *
  12275. * This is an array of objects which describe the feature plug-ins that are
  12276. * available to DataTables. These feature plug-ins are then available for
  12277. * use through the `dom` initialisation option.
  12278. *
  12279. * Each feature plug-in is described by an object which must have the
  12280. * following properties:
  12281. *
  12282. * * `fnInit` - function that is used to initialise the plug-in,
  12283. * * `cFeature` - a character so the feature can be enabled by the `dom`
  12284. * instillation option. This is case sensitive.
  12285. *
  12286. * The `fnInit` function has the following input parameters:
  12287. *
  12288. * 1. `{object}` DataTables settings object: see
  12289. * {@link DataTable.models.oSettings}
  12290. *
  12291. * And the following return is expected:
  12292. *
  12293. * * {node|null} The element which contains your feature. Note that the
  12294. * return may also be void if your plug-in does not require to inject any
  12295. * DOM elements into DataTables control (`dom`) - for example this might
  12296. * be useful when developing a plug-in which allows table control via
  12297. * keyboard entry
  12298. *
  12299. * @type array
  12300. *
  12301. * @example
  12302. * $.fn.dataTable.ext.features.push( {
  12303. * "fnInit": function( oSettings ) {
  12304. * return new TableTools( { "oDTSettings": oSettings } );
  12305. * },
  12306. * "cFeature": "T"
  12307. * } );
  12308. */
  12309. feature: [],
  12310. /**
  12311. * Row searching.
  12312. *
  12313. * This method of searching is complimentary to the default type based
  12314. * searching, and a lot more comprehensive as it allows you complete control
  12315. * over the searching logic. Each element in this array is a function
  12316. * (parameters described below) that is called for every row in the table,
  12317. * and your logic decides if it should be included in the searching data set
  12318. * or not.
  12319. *
  12320. * Searching functions have the following input parameters:
  12321. *
  12322. * 1. `{object}` DataTables settings object: see
  12323. * {@link DataTable.models.oSettings}
  12324. * 2. `{array|object}` Data for the row to be processed (same as the
  12325. * original format that was passed in as the data source, or an array
  12326. * from a DOM data source
  12327. * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
  12328. * can be useful to retrieve the `TR` element if you need DOM interaction.
  12329. *
  12330. * And the following return is expected:
  12331. *
  12332. * * {boolean} Include the row in the searched result set (true) or not
  12333. * (false)
  12334. *
  12335. * Note that as with the main search ability in DataTables, technically this
  12336. * is "filtering", since it is subtractive. However, for consistency in
  12337. * naming we call it searching here.
  12338. *
  12339. * @type array
  12340. * @default []
  12341. *
  12342. * @example
  12343. * // The following example shows custom search being applied to the
  12344. * // fourth column (i.e. the data[3] index) based on two input values
  12345. * // from the end-user, matching the data in a certain range.
  12346. * $.fn.dataTable.ext.search.push(
  12347. * function( settings, data, dataIndex ) {
  12348. * var min = document.getElementById('min').value * 1;
  12349. * var max = document.getElementById('max').value * 1;
  12350. * var version = data[3] == "-" ? 0 : data[3]*1;
  12351. *
  12352. * if ( min == "" && max == "" ) {
  12353. * return true;
  12354. * }
  12355. * else if ( min == "" && version < max ) {
  12356. * return true;
  12357. * }
  12358. * else if ( min < version && "" == max ) {
  12359. * return true;
  12360. * }
  12361. * else if ( min < version && version < max ) {
  12362. * return true;
  12363. * }
  12364. * return false;
  12365. * }
  12366. * );
  12367. */
  12368. search: [],
  12369. /**
  12370. * Selector extensions
  12371. *
  12372. * The `selector` option can be used to extend the options available for the
  12373. * selector modifier options (`selector-modifier` object data type) that
  12374. * each of the three built in selector types offer (row, column and cell +
  12375. * their plural counterparts). For example the Select extension uses this
  12376. * mechanism to provide an option to select only rows, columns and cells
  12377. * that have been marked as selected by the end user (`{selected: true}`),
  12378. * which can be used in conjunction with the existing built in selector
  12379. * options.
  12380. *
  12381. * Each property is an array to which functions can be pushed. The functions
  12382. * take three attributes:
  12383. *
  12384. * * Settings object for the host table
  12385. * * Options object (`selector-modifier` object type)
  12386. * * Array of selected item indexes
  12387. *
  12388. * The return is an array of the resulting item indexes after the custom
  12389. * selector has been applied.
  12390. *
  12391. * @type object
  12392. */
  12393. selector: {
  12394. cell: [],
  12395. column: [],
  12396. row: []
  12397. },
  12398. /**
  12399. * Internal functions, exposed for used in plug-ins.
  12400. *
  12401. * Please note that you should not need to use the internal methods for
  12402. * anything other than a plug-in (and even then, try to avoid if possible).
  12403. * The internal function may change between releases.
  12404. *
  12405. * @type object
  12406. * @default {}
  12407. */
  12408. internal: {},
  12409. /**
  12410. * Legacy configuration options. Enable and disable legacy options that
  12411. * are available in DataTables.
  12412. *
  12413. * @type object
  12414. */
  12415. legacy: {
  12416. /**
  12417. * Enable / disable DataTables 1.9 compatible server-side processing
  12418. * requests
  12419. *
  12420. * @type boolean
  12421. * @default null
  12422. */
  12423. ajax: null
  12424. },
  12425. /**
  12426. * Pagination plug-in methods.
  12427. *
  12428. * Each entry in this object is a function and defines which buttons should
  12429. * be shown by the pagination rendering method that is used for the table:
  12430. * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
  12431. * buttons are displayed in the document, while the functions here tell it
  12432. * what buttons to display. This is done by returning an array of button
  12433. * descriptions (what each button will do).
  12434. *
  12435. * Pagination types (the four built in options and any additional plug-in
  12436. * options defined here) can be used through the `paginationType`
  12437. * initialisation parameter.
  12438. *
  12439. * The functions defined take two parameters:
  12440. *
  12441. * 1. `{int} page` The current page index
  12442. * 2. `{int} pages` The number of pages in the table
  12443. *
  12444. * Each function is expected to return an array where each element of the
  12445. * array can be one of:
  12446. *
  12447. * * `first` - Jump to first page when activated
  12448. * * `last` - Jump to last page when activated
  12449. * * `previous` - Show previous page when activated
  12450. * * `next` - Show next page when activated
  12451. * * `{int}` - Show page of the index given
  12452. * * `{array}` - A nested array containing the above elements to add a
  12453. * containing 'DIV' element (might be useful for styling).
  12454. *
  12455. * Note that DataTables v1.9- used this object slightly differently whereby
  12456. * an object with two functions would be defined for each plug-in. That
  12457. * ability is still supported by DataTables 1.10+ to provide backwards
  12458. * compatibility, but this option of use is now decremented and no longer
  12459. * documented in DataTables 1.10+.
  12460. *
  12461. * @type object
  12462. * @default {}
  12463. *
  12464. * @example
  12465. * // Show previous, next and current page buttons only
  12466. * $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
  12467. * return [ 'previous', page, 'next' ];
  12468. * };
  12469. */
  12470. pager: {},
  12471. renderer: {
  12472. pageButton: {},
  12473. header: {}
  12474. },
  12475. /**
  12476. * Ordering plug-ins - custom data source
  12477. *
  12478. * The extension options for ordering of data available here is complimentary
  12479. * to the default type based ordering that DataTables typically uses. It
  12480. * allows much greater control over the the data that is being used to
  12481. * order a column, but is necessarily therefore more complex.
  12482. *
  12483. * This type of ordering is useful if you want to do ordering based on data
  12484. * live from the DOM (for example the contents of an 'input' element) rather
  12485. * than just the static string that DataTables knows of.
  12486. *
  12487. * The way these plug-ins work is that you create an array of the values you
  12488. * wish to be ordering for the column in question and then return that
  12489. * array. The data in the array much be in the index order of the rows in
  12490. * the table (not the currently ordering order!). Which order data gathering
  12491. * function is run here depends on the `dt-init columns.orderDataType`
  12492. * parameter that is used for the column (if any).
  12493. *
  12494. * The functions defined take two parameters:
  12495. *
  12496. * 1. `{object}` DataTables settings object: see
  12497. * {@link DataTable.models.oSettings}
  12498. * 2. `{int}` Target column index
  12499. *
  12500. * Each function is expected to return an array:
  12501. *
  12502. * * `{array}` Data for the column to be ordering upon
  12503. *
  12504. * @type array
  12505. *
  12506. * @example
  12507. * // Ordering using `input` node values
  12508. * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col )
  12509. * {
  12510. * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
  12511. * return $('input', td).val();
  12512. * } );
  12513. * }
  12514. */
  12515. order: {},
  12516. /**
  12517. * Type based plug-ins.
  12518. *
  12519. * Each column in DataTables has a type assigned to it, either by automatic
  12520. * detection or by direct assignment using the `type` option for the column.
  12521. * The type of a column will effect how it is ordering and search (plug-ins
  12522. * can also make use of the column type if required).
  12523. *
  12524. * @namespace
  12525. */
  12526. type: {
  12527. /**
  12528. * Type detection functions.
  12529. *
  12530. * The functions defined in this object are used to automatically detect
  12531. * a column's type, making initialisation of DataTables super easy, even
  12532. * when complex data is in the table.
  12533. *
  12534. * The functions defined take two parameters:
  12535. *
  12536. * 1. `{*}` Data from the column cell to be analysed
  12537. * 2. `{settings}` DataTables settings object. This can be used to
  12538. * perform context specific type detection - for example detection
  12539. * based on language settings such as using a comma for a decimal
  12540. * place. Generally speaking the options from the settings will not
  12541. * be required
  12542. *
  12543. * Each function is expected to return:
  12544. *
  12545. * * `{string|null}` Data type detected, or null if unknown (and thus
  12546. * pass it on to the other type detection functions.
  12547. *
  12548. * @type array
  12549. *
  12550. * @example
  12551. * // Currency type detection plug-in:
  12552. * $.fn.dataTable.ext.type.detect.push(
  12553. * function ( data, settings ) {
  12554. * // Check the numeric part
  12555. * if ( ! data.substring(1).match(/[0-9]/) ) {
  12556. * return null;
  12557. * }
  12558. *
  12559. * // Check prefixed by currency
  12560. * if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
  12561. * return 'currency';
  12562. * }
  12563. * return null;
  12564. * }
  12565. * );
  12566. */
  12567. detect: [],
  12568. /**
  12569. * Type based search formatting.
  12570. *
  12571. * The type based searching functions can be used to pre-format the
  12572. * data to be search on. For example, it can be used to strip HTML
  12573. * tags or to de-format telephone numbers for numeric only searching.
  12574. *
  12575. * Note that is a search is not defined for a column of a given type,
  12576. * no search formatting will be performed.
  12577. *
  12578. * Pre-processing of searching data plug-ins - When you assign the sType
  12579. * for a column (or have it automatically detected for you by DataTables
  12580. * or a type detection plug-in), you will typically be using this for
  12581. * custom sorting, but it can also be used to provide custom searching
  12582. * by allowing you to pre-processing the data and returning the data in
  12583. * the format that should be searched upon. This is done by adding
  12584. * functions this object with a parameter name which matches the sType
  12585. * for that target column. This is the corollary of <i>afnSortData</i>
  12586. * for searching data.
  12587. *
  12588. * The functions defined take a single parameter:
  12589. *
  12590. * 1. `{*}` Data from the column cell to be prepared for searching
  12591. *
  12592. * Each function is expected to return:
  12593. *
  12594. * * `{string|null}` Formatted string that will be used for the searching.
  12595. *
  12596. * @type object
  12597. * @default {}
  12598. *
  12599. * @example
  12600. * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
  12601. * return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
  12602. * }
  12603. */
  12604. search: {},
  12605. /**
  12606. * Type based ordering.
  12607. *
  12608. * The column type tells DataTables what ordering to apply to the table
  12609. * when a column is sorted upon. The order for each type that is defined,
  12610. * is defined by the functions available in this object.
  12611. *
  12612. * Each ordering option can be described by three properties added to
  12613. * this object:
  12614. *
  12615. * * `{type}-pre` - Pre-formatting function
  12616. * * `{type}-asc` - Ascending order function
  12617. * * `{type}-desc` - Descending order function
  12618. *
  12619. * All three can be used together, only `{type}-pre` or only
  12620. * `{type}-asc` and `{type}-desc` together. It is generally recommended
  12621. * that only `{type}-pre` is used, as this provides the optimal
  12622. * implementation in terms of speed, although the others are provided
  12623. * for compatibility with existing Javascript sort functions.
  12624. *
  12625. * `{type}-pre`: Functions defined take a single parameter:
  12626. *
  12627. * 1. `{*}` Data from the column cell to be prepared for ordering
  12628. *
  12629. * And return:
  12630. *
  12631. * * `{*}` Data to be sorted upon
  12632. *
  12633. * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
  12634. * functions, taking two parameters:
  12635. *
  12636. * 1. `{*}` Data to compare to the second parameter
  12637. * 2. `{*}` Data to compare to the first parameter
  12638. *
  12639. * And returning:
  12640. *
  12641. * * `{*}` Ordering match: <0 if first parameter should be sorted lower
  12642. * than the second parameter, ===0 if the two parameters are equal and
  12643. * >0 if the first parameter should be sorted height than the second
  12644. * parameter.
  12645. *
  12646. * @type object
  12647. * @default {}
  12648. *
  12649. * @example
  12650. * // Numeric ordering of formatted numbers with a pre-formatter
  12651. * $.extend( $.fn.dataTable.ext.type.order, {
  12652. * "string-pre": function(x) {
  12653. * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
  12654. * return parseFloat( a );
  12655. * }
  12656. * } );
  12657. *
  12658. * @example
  12659. * // Case-sensitive string ordering, with no pre-formatting method
  12660. * $.extend( $.fn.dataTable.ext.order, {
  12661. * "string-case-asc": function(x,y) {
  12662. * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  12663. * },
  12664. * "string-case-desc": function(x,y) {
  12665. * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  12666. * }
  12667. * } );
  12668. */
  12669. order: {}
  12670. },
  12671. /**
  12672. * Unique DataTables instance counter
  12673. *
  12674. * @type int
  12675. * @private
  12676. */
  12677. _unique: 0,
  12678. //
  12679. // Depreciated
  12680. // The following properties are retained for backwards compatibility only.
  12681. // The should not be used in new projects and will be removed in a future
  12682. // version
  12683. //
  12684. /**
  12685. * Version check function.
  12686. * @type function
  12687. * @depreciated Since 1.10
  12688. */
  12689. fnVersionCheck: DataTable.fnVersionCheck,
  12690. /**
  12691. * Index for what 'this' index API functions should use
  12692. * @type int
  12693. * @deprecated Since v1.10
  12694. */
  12695. iApiIndex: 0,
  12696. /**
  12697. * jQuery UI class container
  12698. * @type object
  12699. * @deprecated Since v1.10
  12700. */
  12701. oJUIClasses: {},
  12702. /**
  12703. * Software version
  12704. * @type string
  12705. * @deprecated Since v1.10
  12706. */
  12707. sVersion: DataTable.version
  12708. };
  12709. //
  12710. // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
  12711. //
  12712. $.extend( _ext, {
  12713. afnFiltering: _ext.search,
  12714. aTypes: _ext.type.detect,
  12715. ofnSearch: _ext.type.search,
  12716. oSort: _ext.type.order,
  12717. afnSortData: _ext.order,
  12718. aoFeatures: _ext.feature,
  12719. oApi: _ext.internal,
  12720. oStdClasses: _ext.classes,
  12721. oPagination: _ext.pager
  12722. } );
  12723. $.extend( DataTable.ext.classes, {
  12724. "sTable": "dataTable",
  12725. "sNoFooter": "no-footer",
  12726. /* Paging buttons */
  12727. "sPageButton": "paginate_button",
  12728. "sPageButtonActive": "current",
  12729. "sPageButtonDisabled": "disabled",
  12730. /* Striping classes */
  12731. "sStripeOdd": "odd",
  12732. "sStripeEven": "even",
  12733. /* Empty row */
  12734. "sRowEmpty": "dataTables_empty",
  12735. /* Features */
  12736. "sWrapper": "dataTables_wrapper",
  12737. "sFilter": "dataTables_filter",
  12738. "sInfo": "dataTables_info",
  12739. "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
  12740. "sLength": "dataTables_length",
  12741. "sProcessing": "dataTables_processing",
  12742. /* Sorting */
  12743. "sSortAsc": "sorting_asc",
  12744. "sSortDesc": "sorting_desc",
  12745. "sSortable": "sorting", /* Sortable in both directions */
  12746. "sSortableAsc": "sorting_desc_disabled",
  12747. "sSortableDesc": "sorting_asc_disabled",
  12748. "sSortableNone": "sorting_disabled",
  12749. "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
  12750. /* Filtering */
  12751. "sFilterInput": "",
  12752. /* Page length */
  12753. "sLengthSelect": "",
  12754. /* Scrolling */
  12755. "sScrollWrapper": "dataTables_scroll",
  12756. "sScrollHead": "dataTables_scrollHead",
  12757. "sScrollHeadInner": "dataTables_scrollHeadInner",
  12758. "sScrollBody": "dataTables_scrollBody",
  12759. "sScrollFoot": "dataTables_scrollFoot",
  12760. "sScrollFootInner": "dataTables_scrollFootInner",
  12761. /* Misc */
  12762. "sHeaderTH": "",
  12763. "sFooterTH": "",
  12764. // Deprecated
  12765. "sSortJUIAsc": "",
  12766. "sSortJUIDesc": "",
  12767. "sSortJUI": "",
  12768. "sSortJUIAscAllowed": "",
  12769. "sSortJUIDescAllowed": "",
  12770. "sSortJUIWrapper": "",
  12771. "sSortIcon": "",
  12772. "sJUIHeader": "",
  12773. "sJUIFooter": ""
  12774. } );
  12775. var extPagination = DataTable.ext.pager;
  12776. function _numbers ( page, pages ) {
  12777. var
  12778. numbers = [],
  12779. buttons = extPagination.numbers_length,
  12780. half = Math.floor( buttons / 2 ),
  12781. i = 1;
  12782. if ( pages <= buttons ) {
  12783. numbers = _range( 0, pages );
  12784. }
  12785. else if ( page <= half ) {
  12786. numbers = _range( 0, buttons-2 );
  12787. numbers.push( 'ellipsis' );
  12788. numbers.push( pages-1 );
  12789. }
  12790. else if ( page >= pages - 1 - half ) {
  12791. numbers = _range( pages-(buttons-2), pages );
  12792. numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
  12793. numbers.splice( 0, 0, 0 );
  12794. }
  12795. else {
  12796. numbers = _range( page-half+2, page+half-1 );
  12797. numbers.push( 'ellipsis' );
  12798. numbers.push( pages-1 );
  12799. numbers.splice( 0, 0, 'ellipsis' );
  12800. numbers.splice( 0, 0, 0 );
  12801. }
  12802. numbers.DT_el = 'span';
  12803. return numbers;
  12804. }
  12805. $.extend( extPagination, {
  12806. simple: function ( page, pages ) {
  12807. return [ 'previous', 'next' ];
  12808. },
  12809. full: function ( page, pages ) {
  12810. return [ 'first', 'previous', 'next', 'last' ];
  12811. },
  12812. numbers: function ( page, pages ) {
  12813. return [ _numbers(page, pages) ];
  12814. },
  12815. simple_numbers: function ( page, pages ) {
  12816. return [ 'previous', _numbers(page, pages), 'next' ];
  12817. },
  12818. full_numbers: function ( page, pages ) {
  12819. return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
  12820. },
  12821. first_last_numbers: function (page, pages) {
  12822. return ['first', _numbers(page, pages), 'last'];
  12823. },
  12824. // For testing and plug-ins to use
  12825. _numbers: _numbers,
  12826. // Number of number buttons (including ellipsis) to show. _Must be odd!_
  12827. numbers_length: 7
  12828. } );
  12829. $.extend( true, DataTable.ext.renderer, {
  12830. pageButton: {
  12831. _: function ( settings, host, idx, buttons, page, pages ) {
  12832. var classes = settings.oClasses;
  12833. var lang = settings.oLanguage.oPaginate;
  12834. var aria = settings.oLanguage.oAria.paginate || {};
  12835. var btnDisplay, btnClass;
  12836. var attach = function( container, buttons ) {
  12837. var i, ien, node, button, tabIndex;
  12838. var disabledClass = classes.sPageButtonDisabled;
  12839. var clickHandler = function ( e ) {
  12840. _fnPageChange( settings, e.data.action, true );
  12841. };
  12842. for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
  12843. button = buttons[i];
  12844. if ( Array.isArray( button ) ) {
  12845. var inner = $( '<'+(button.DT_el || 'div')+'/>' )
  12846. .appendTo( container );
  12847. attach( inner, button );
  12848. }
  12849. else {
  12850. btnDisplay = null;
  12851. btnClass = button;
  12852. tabIndex = settings.iTabIndex;
  12853. switch ( button ) {
  12854. case 'ellipsis':
  12855. container.append('<span class="ellipsis">&#x2026;</span>');
  12856. break;
  12857. case 'first':
  12858. btnDisplay = lang.sFirst;
  12859. if ( page === 0 ) {
  12860. tabIndex = -1;
  12861. btnClass += ' ' + disabledClass;
  12862. }
  12863. break;
  12864. case 'previous':
  12865. btnDisplay = lang.sPrevious;
  12866. if ( page === 0 ) {
  12867. tabIndex = -1;
  12868. btnClass += ' ' + disabledClass;
  12869. }
  12870. break;
  12871. case 'next':
  12872. btnDisplay = lang.sNext;
  12873. if ( pages === 0 || page === pages-1 ) {
  12874. tabIndex = -1;
  12875. btnClass += ' ' + disabledClass;
  12876. }
  12877. break;
  12878. case 'last':
  12879. btnDisplay = lang.sLast;
  12880. if ( pages === 0 || page === pages-1 ) {
  12881. tabIndex = -1;
  12882. btnClass += ' ' + disabledClass;
  12883. }
  12884. break;
  12885. default:
  12886. btnDisplay = settings.fnFormatNumber( button + 1 );
  12887. btnClass = page === button ?
  12888. classes.sPageButtonActive : '';
  12889. break;
  12890. }
  12891. if ( btnDisplay !== null ) {
  12892. node = $('<a>', {
  12893. 'class': classes.sPageButton+' '+btnClass,
  12894. 'aria-controls': settings.sTableId,
  12895. 'aria-label': aria[ button ],
  12896. 'data-dt-idx': button,
  12897. 'tabindex': tabIndex,
  12898. 'id': idx === 0 && typeof button === 'string' ?
  12899. settings.sTableId +'_'+ button :
  12900. null
  12901. } )
  12902. .html( btnDisplay )
  12903. .appendTo( container );
  12904. _fnBindAction(
  12905. node, {action: button}, clickHandler
  12906. );
  12907. }
  12908. }
  12909. }
  12910. };
  12911. // IE9 throws an 'unknown error' if document.activeElement is used
  12912. // inside an iframe or frame. Try / catch the error. Not good for
  12913. // accessibility, but neither are frames.
  12914. var activeEl;
  12915. try {
  12916. // Because this approach is destroying and recreating the paging
  12917. // elements, focus is lost on the select button which is bad for
  12918. // accessibility. So we want to restore focus once the draw has
  12919. // completed
  12920. activeEl = $(host).find(document.activeElement).data('dt-idx');
  12921. }
  12922. catch (e) {}
  12923. attach( $(host).empty(), buttons );
  12924. if ( activeEl !== undefined ) {
  12925. $(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');
  12926. }
  12927. }
  12928. }
  12929. } );
  12930. // Built in type detection. See model.ext.aTypes for information about
  12931. // what is required from this methods.
  12932. $.extend( DataTable.ext.type.detect, [
  12933. // Plain numbers - first since V8 detects some plain numbers as dates
  12934. // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
  12935. function ( d, settings )
  12936. {
  12937. var decimal = settings.oLanguage.sDecimal;
  12938. return _isNumber( d, decimal ) ? 'num'+decimal : null;
  12939. },
  12940. // Dates (only those recognised by the browser's Date.parse)
  12941. function ( d, settings )
  12942. {
  12943. // V8 tries _very_ hard to make a string passed into `Date.parse()`
  12944. // valid, so we need to use a regex to restrict date formats. Use a
  12945. // plug-in for anything other than ISO8601 style strings
  12946. if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
  12947. return null;
  12948. }
  12949. var parsed = Date.parse(d);
  12950. return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
  12951. },
  12952. // Formatted numbers
  12953. function ( d, settings )
  12954. {
  12955. var decimal = settings.oLanguage.sDecimal;
  12956. return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
  12957. },
  12958. // HTML numeric
  12959. function ( d, settings )
  12960. {
  12961. var decimal = settings.oLanguage.sDecimal;
  12962. return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
  12963. },
  12964. // HTML numeric, formatted
  12965. function ( d, settings )
  12966. {
  12967. var decimal = settings.oLanguage.sDecimal;
  12968. return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
  12969. },
  12970. // HTML (this is strict checking - there must be html)
  12971. function ( d, settings )
  12972. {
  12973. return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
  12974. 'html' : null;
  12975. }
  12976. ] );
  12977. // Filter formatting functions. See model.ext.ofnSearch for information about
  12978. // what is required from these methods.
  12979. //
  12980. // Note that additional search methods are added for the html numbers and
  12981. // html formatted numbers by `_addNumericSort()` when we know what the decimal
  12982. // place is
  12983. $.extend( DataTable.ext.type.search, {
  12984. html: function ( data ) {
  12985. return _empty(data) ?
  12986. data :
  12987. typeof data === 'string' ?
  12988. data
  12989. .replace( _re_new_lines, " " )
  12990. .replace( _re_html, "" ) :
  12991. '';
  12992. },
  12993. string: function ( data ) {
  12994. return _empty(data) ?
  12995. data :
  12996. typeof data === 'string' ?
  12997. data.replace( _re_new_lines, " " ) :
  12998. data;
  12999. }
  13000. } );
  13001. var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
  13002. if ( d !== 0 && (!d || d === '-') ) {
  13003. return -Infinity;
  13004. }
  13005. // If a decimal place other than `.` is used, it needs to be given to the
  13006. // function so we can detect it and replace with a `.` which is the only
  13007. // decimal place Javascript recognises - it is not locale aware.
  13008. if ( decimalPlace ) {
  13009. d = _numToDecimal( d, decimalPlace );
  13010. }
  13011. if ( d.replace ) {
  13012. if ( re1 ) {
  13013. d = d.replace( re1, '' );
  13014. }
  13015. if ( re2 ) {
  13016. d = d.replace( re2, '' );
  13017. }
  13018. }
  13019. return d * 1;
  13020. };
  13021. // Add the numeric 'deformatting' functions for sorting and search. This is done
  13022. // in a function to provide an easy ability for the language options to add
  13023. // additional methods if a non-period decimal place is used.
  13024. function _addNumericSort ( decimalPlace ) {
  13025. $.each(
  13026. {
  13027. // Plain numbers
  13028. "num": function ( d ) {
  13029. return __numericReplace( d, decimalPlace );
  13030. },
  13031. // Formatted numbers
  13032. "num-fmt": function ( d ) {
  13033. return __numericReplace( d, decimalPlace, _re_formatted_numeric );
  13034. },
  13035. // HTML numeric
  13036. "html-num": function ( d ) {
  13037. return __numericReplace( d, decimalPlace, _re_html );
  13038. },
  13039. // HTML numeric, formatted
  13040. "html-num-fmt": function ( d ) {
  13041. return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
  13042. }
  13043. },
  13044. function ( key, fn ) {
  13045. // Add the ordering method
  13046. _ext.type.order[ key+decimalPlace+'-pre' ] = fn;
  13047. // For HTML types add a search formatter that will strip the HTML
  13048. if ( key.match(/^html\-/) ) {
  13049. _ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
  13050. }
  13051. }
  13052. );
  13053. }
  13054. // Default sort methods
  13055. $.extend( _ext.type.order, {
  13056. // Dates
  13057. "date-pre": function ( d ) {
  13058. var ts = Date.parse( d );
  13059. return isNaN(ts) ? -Infinity : ts;
  13060. },
  13061. // html
  13062. "html-pre": function ( a ) {
  13063. return _empty(a) ?
  13064. '' :
  13065. a.replace ?
  13066. a.replace( /<.*?>/g, "" ).toLowerCase() :
  13067. a+'';
  13068. },
  13069. // string
  13070. "string-pre": function ( a ) {
  13071. // This is a little complex, but faster than always calling toString,
  13072. // http://jsperf.com/tostring-v-check
  13073. return _empty(a) ?
  13074. '' :
  13075. typeof a === 'string' ?
  13076. a.toLowerCase() :
  13077. ! a.toString ?
  13078. '' :
  13079. a.toString();
  13080. },
  13081. // string-asc and -desc are retained only for compatibility with the old
  13082. // sort methods
  13083. "string-asc": function ( x, y ) {
  13084. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  13085. },
  13086. "string-desc": function ( x, y ) {
  13087. return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  13088. }
  13089. } );
  13090. // Numeric sorting types - order doesn't matter here
  13091. _addNumericSort( '' );
  13092. $.extend( true, DataTable.ext.renderer, {
  13093. header: {
  13094. _: function ( settings, cell, column, classes ) {
  13095. // No additional mark-up required
  13096. // Attach a sort listener to update on sort - note that using the
  13097. // `DT` namespace will allow the event to be removed automatically
  13098. // on destroy, while the `dt` namespaced event is the one we are
  13099. // listening for
  13100. $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
  13101. if ( settings !== ctx ) { // need to check this this is the host
  13102. return; // table, not a nested one
  13103. }
  13104. var colIdx = column.idx;
  13105. cell
  13106. .removeClass(
  13107. classes.sSortAsc +' '+
  13108. classes.sSortDesc
  13109. )
  13110. .addClass( columns[ colIdx ] == 'asc' ?
  13111. classes.sSortAsc : columns[ colIdx ] == 'desc' ?
  13112. classes.sSortDesc :
  13113. column.sSortingClass
  13114. );
  13115. } );
  13116. },
  13117. jqueryui: function ( settings, cell, column, classes ) {
  13118. $('<div/>')
  13119. .addClass( classes.sSortJUIWrapper )
  13120. .append( cell.contents() )
  13121. .append( $('<span/>')
  13122. .addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
  13123. )
  13124. .appendTo( cell );
  13125. // Attach a sort listener to update on sort
  13126. $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
  13127. if ( settings !== ctx ) {
  13128. return;
  13129. }
  13130. var colIdx = column.idx;
  13131. cell
  13132. .removeClass( classes.sSortAsc +" "+classes.sSortDesc )
  13133. .addClass( columns[ colIdx ] == 'asc' ?
  13134. classes.sSortAsc : columns[ colIdx ] == 'desc' ?
  13135. classes.sSortDesc :
  13136. column.sSortingClass
  13137. );
  13138. cell
  13139. .find( 'span.'+classes.sSortIcon )
  13140. .removeClass(
  13141. classes.sSortJUIAsc +" "+
  13142. classes.sSortJUIDesc +" "+
  13143. classes.sSortJUI +" "+
  13144. classes.sSortJUIAscAllowed +" "+
  13145. classes.sSortJUIDescAllowed
  13146. )
  13147. .addClass( columns[ colIdx ] == 'asc' ?
  13148. classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
  13149. classes.sSortJUIDesc :
  13150. column.sSortingClassJUI
  13151. );
  13152. } );
  13153. }
  13154. }
  13155. } );
  13156. /*
  13157. * Public helper functions. These aren't used internally by DataTables, or
  13158. * called by any of the options passed into DataTables, but they can be used
  13159. * externally by developers working with DataTables. They are helper functions
  13160. * to make working with DataTables a little bit easier.
  13161. */
  13162. var __htmlEscapeEntities = function ( d ) {
  13163. if (Array.isArray(d)) {
  13164. d = d.join(',');
  13165. }
  13166. return typeof d === 'string' ?
  13167. d
  13168. .replace(/&/g, '&amp;')
  13169. .replace(/</g, '&lt;')
  13170. .replace(/>/g, '&gt;')
  13171. .replace(/"/g, '&quot;') :
  13172. d;
  13173. };
  13174. // Common logic for moment, luxon or a date action
  13175. function __mld( dt, momentFn, luxonFn, dateFn, arg1 ) {
  13176. if (window.moment) {
  13177. return dt[momentFn]( arg1 );
  13178. }
  13179. else if (window.luxon) {
  13180. return dt[luxonFn]( arg1 );
  13181. }
  13182. return dateFn ? dt[dateFn]( arg1 ) : dt;
  13183. }
  13184. var __mlWarning = false;
  13185. function __mldObj (d, format, locale) {
  13186. var dt;
  13187. if (window.moment) {
  13188. dt = window.moment.utc( d, format, locale, true );
  13189. if (! dt.isValid()) {
  13190. return null;
  13191. }
  13192. }
  13193. else if (window.luxon) {
  13194. dt = format && typeof d === 'string'
  13195. ? window.luxon.DateTime.fromFormat( d, format )
  13196. : window.luxon.DateTime.fromISO( d );
  13197. if (! dt.isValid) {
  13198. return null;
  13199. }
  13200. dt.setLocale(locale);
  13201. }
  13202. else if (! format) {
  13203. // No format given, must be ISO
  13204. dt = new Date(d);
  13205. }
  13206. else {
  13207. if (! __mlWarning) {
  13208. alert('DataTables warning: Formatted date without Moment.js or Luxon - https://datatables.net/tn/17');
  13209. }
  13210. __mlWarning = true;
  13211. }
  13212. return dt;
  13213. }
  13214. // Wrapper for date, datetime and time which all operate the same way with the exception of
  13215. // the output string for auto locale support
  13216. function __mlHelper (localeString) {
  13217. return function ( from, to, locale, def ) {
  13218. // Luxon and Moment support
  13219. // Argument shifting
  13220. if ( arguments.length === 0 ) {
  13221. locale = 'en';
  13222. to = null; // means toLocaleString
  13223. from = null; // means iso8601
  13224. }
  13225. else if ( arguments.length === 1 ) {
  13226. locale = 'en';
  13227. to = from;
  13228. from = null;
  13229. }
  13230. else if ( arguments.length === 2 ) {
  13231. locale = to;
  13232. to = from;
  13233. from = null;
  13234. }
  13235. var typeName = 'datetime-' + to;
  13236. // Add type detection and sorting specific to this date format - we need to be able to identify
  13237. // date type columns as such, rather than as numbers in extensions. Hence the need for this.
  13238. if (! DataTable.ext.type.order[typeName]) {
  13239. // The renderer will give the value to type detect as the type!
  13240. DataTable.ext.type.detect.unshift(function (d) {
  13241. return d === typeName ? typeName : false;
  13242. });
  13243. // The renderer gives us Moment, Luxon or Date obects for the sorting, all of which have a
  13244. // `valueOf` which gives milliseconds epoch
  13245. DataTable.ext.type.order[typeName + '-asc'] = function (a, b) {
  13246. var x = a.valueOf();
  13247. var y = b.valueOf();
  13248. return x === y
  13249. ? 0
  13250. : x < y
  13251. ? -1
  13252. : 1;
  13253. }
  13254. DataTable.ext.type.order[typeName + '-desc'] = function (a, b) {
  13255. var x = a.valueOf();
  13256. var y = b.valueOf();
  13257. return x === y
  13258. ? 0
  13259. : x > y
  13260. ? -1
  13261. : 1;
  13262. }
  13263. }
  13264. return function ( d, type ) {
  13265. // Allow for a default value
  13266. if (d === null || d === undefined) {
  13267. if (def === '--now') {
  13268. // We treat everything as UTC further down, so no changes are
  13269. // made, as such need to get the local date / time as if it were
  13270. // UTC
  13271. var local = new Date();
  13272. d = new Date( Date.UTC(
  13273. local.getFullYear(), local.getMonth(), local.getDate(),
  13274. local.getHours(), local.getMinutes(), local.getSeconds()
  13275. ) );
  13276. }
  13277. else {
  13278. d = '';
  13279. }
  13280. }
  13281. if (type === 'type') {
  13282. // Typing uses the type name for fast matching
  13283. return typeName;
  13284. }
  13285. if (d === '') {
  13286. return type !== 'sort'
  13287. ? ''
  13288. : __mldObj('0000-01-01 00:00:00', null, locale);
  13289. }
  13290. // Shortcut. If `from` and `to` are the same, we are using the renderer to
  13291. // format for ordering, not display - its already in the display format.
  13292. if ( to !== null && from === to && type !== 'sort' && type !== 'type' && ! (d instanceof Date) ) {
  13293. return d;
  13294. }
  13295. var dt = __mldObj(d, from, locale);
  13296. if (dt === null) {
  13297. return d;
  13298. }
  13299. if (type === 'sort') {
  13300. return dt;
  13301. }
  13302. var formatted = to === null
  13303. ? __mld(dt, 'toDate', 'toJSDate', '')[localeString]()
  13304. : __mld(dt, 'format', 'toFormat', 'toISOString', to);
  13305. // XSS protection
  13306. return type === 'display' ?
  13307. __htmlEscapeEntities( formatted ) :
  13308. formatted;
  13309. };
  13310. }
  13311. }
  13312. // Based on locale, determine standard number formatting
  13313. // Fallback for legacy browsers is US English
  13314. var __thousands = ',';
  13315. var __decimal = '.';
  13316. if (Intl) {
  13317. try {
  13318. var num = new Intl.NumberFormat().formatToParts(100000.1);
  13319. for (var i=0 ; i<num.length ; i++) {
  13320. if (num[i].type === 'group') {
  13321. __thousands = num[i].value;
  13322. }
  13323. else if (num[i].type === 'decimal') {
  13324. __decimal = num[i].value;
  13325. }
  13326. }
  13327. }
  13328. catch (e) {
  13329. // noop
  13330. }
  13331. }
  13332. // Formatted date time detection - use by declaring the formats you are going to use
  13333. DataTable.datetime = function ( format, locale ) {
  13334. var typeName = 'datetime-detect-' + format;
  13335. if (! locale) {
  13336. locale = 'en';
  13337. }
  13338. if (! DataTable.ext.type.order[typeName]) {
  13339. DataTable.ext.type.detect.unshift(function (d) {
  13340. var dt = __mldObj(d, format, locale);
  13341. return d === '' || dt ? typeName : false;
  13342. });
  13343. DataTable.ext.type.order[typeName + '-pre'] = function (d) {
  13344. return __mldObj(d, format, locale) || 0;
  13345. }
  13346. }
  13347. }
  13348. /**
  13349. * Helpers for `columns.render`.
  13350. *
  13351. * The options defined here can be used with the `columns.render` initialisation
  13352. * option to provide a display renderer. The following functions are defined:
  13353. *
  13354. * * `number` - Will format numeric data (defined by `columns.data`) for
  13355. * display, retaining the original unformatted data for sorting and filtering.
  13356. * It takes 5 parameters:
  13357. * * `string` - Thousands grouping separator
  13358. * * `string` - Decimal point indicator
  13359. * * `integer` - Number of decimal points to show
  13360. * * `string` (optional) - Prefix.
  13361. * * `string` (optional) - Postfix (/suffix).
  13362. * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
  13363. * parameters.
  13364. *
  13365. * @example
  13366. * // Column definition using the number renderer
  13367. * {
  13368. * data: "salary",
  13369. * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
  13370. * }
  13371. *
  13372. * @namespace
  13373. */
  13374. DataTable.render = {
  13375. date: __mlHelper('toLocaleDateString'),
  13376. datetime: __mlHelper('toLocaleString'),
  13377. time: __mlHelper('toLocaleTimeString'),
  13378. number: function ( thousands, decimal, precision, prefix, postfix ) {
  13379. // Auto locale detection
  13380. if (thousands === null || thousands === undefined) {
  13381. thousands = __thousands;
  13382. }
  13383. if (decimal === null || decimal === undefined) {
  13384. decimal = __decimal;
  13385. }
  13386. return {
  13387. display: function ( d ) {
  13388. if ( typeof d !== 'number' && typeof d !== 'string' ) {
  13389. return d;
  13390. }
  13391. if (d === '' || d === null) {
  13392. return d;
  13393. }
  13394. var negative = d < 0 ? '-' : '';
  13395. var flo = parseFloat( d );
  13396. // If NaN then there isn't much formatting that we can do - just
  13397. // return immediately, escaping any HTML (this was supposed to
  13398. // be a number after all)
  13399. if ( isNaN( flo ) ) {
  13400. return __htmlEscapeEntities( d );
  13401. }
  13402. flo = flo.toFixed( precision );
  13403. d = Math.abs( flo );
  13404. var intPart = parseInt( d, 10 );
  13405. var floatPart = precision ?
  13406. decimal+(d - intPart).toFixed( precision ).substring( 2 ):
  13407. '';
  13408. // If zero, then can't have a negative prefix
  13409. if (intPart === 0 && parseFloat(floatPart) === 0) {
  13410. negative = '';
  13411. }
  13412. return negative + (prefix||'') +
  13413. intPart.toString().replace(
  13414. /\B(?=(\d{3})+(?!\d))/g, thousands
  13415. ) +
  13416. floatPart +
  13417. (postfix||'');
  13418. }
  13419. };
  13420. },
  13421. text: function () {
  13422. return {
  13423. display: __htmlEscapeEntities,
  13424. filter: __htmlEscapeEntities
  13425. };
  13426. }
  13427. };
  13428. /*
  13429. * This is really a good bit rubbish this method of exposing the internal methods
  13430. * publicly... - To be fixed in 2.0 using methods on the prototype
  13431. */
  13432. /**
  13433. * Create a wrapper function for exporting an internal functions to an external API.
  13434. * @param {string} fn API function name
  13435. * @returns {function} wrapped function
  13436. * @memberof DataTable#internal
  13437. */
  13438. function _fnExternApiFunc (fn)
  13439. {
  13440. return function() {
  13441. var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
  13442. Array.prototype.slice.call(arguments)
  13443. );
  13444. return DataTable.ext.internal[fn].apply( this, args );
  13445. };
  13446. }
  13447. /**
  13448. * Reference to internal functions for use by plug-in developers. Note that
  13449. * these methods are references to internal functions and are considered to be
  13450. * private. If you use these methods, be aware that they are liable to change
  13451. * between versions.
  13452. * @namespace
  13453. */
  13454. $.extend( DataTable.ext.internal, {
  13455. _fnExternApiFunc: _fnExternApiFunc,
  13456. _fnBuildAjax: _fnBuildAjax,
  13457. _fnAjaxUpdate: _fnAjaxUpdate,
  13458. _fnAjaxParameters: _fnAjaxParameters,
  13459. _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
  13460. _fnAjaxDataSrc: _fnAjaxDataSrc,
  13461. _fnAddColumn: _fnAddColumn,
  13462. _fnColumnOptions: _fnColumnOptions,
  13463. _fnAdjustColumnSizing: _fnAdjustColumnSizing,
  13464. _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
  13465. _fnColumnIndexToVisible: _fnColumnIndexToVisible,
  13466. _fnVisbleColumns: _fnVisbleColumns,
  13467. _fnGetColumns: _fnGetColumns,
  13468. _fnColumnTypes: _fnColumnTypes,
  13469. _fnApplyColumnDefs: _fnApplyColumnDefs,
  13470. _fnHungarianMap: _fnHungarianMap,
  13471. _fnCamelToHungarian: _fnCamelToHungarian,
  13472. _fnLanguageCompat: _fnLanguageCompat,
  13473. _fnBrowserDetect: _fnBrowserDetect,
  13474. _fnAddData: _fnAddData,
  13475. _fnAddTr: _fnAddTr,
  13476. _fnNodeToDataIndex: _fnNodeToDataIndex,
  13477. _fnNodeToColumnIndex: _fnNodeToColumnIndex,
  13478. _fnGetCellData: _fnGetCellData,
  13479. _fnSetCellData: _fnSetCellData,
  13480. _fnSplitObjNotation: _fnSplitObjNotation,
  13481. _fnGetObjectDataFn: _fnGetObjectDataFn,
  13482. _fnSetObjectDataFn: _fnSetObjectDataFn,
  13483. _fnGetDataMaster: _fnGetDataMaster,
  13484. _fnClearTable: _fnClearTable,
  13485. _fnDeleteIndex: _fnDeleteIndex,
  13486. _fnInvalidate: _fnInvalidate,
  13487. _fnGetRowElements: _fnGetRowElements,
  13488. _fnCreateTr: _fnCreateTr,
  13489. _fnBuildHead: _fnBuildHead,
  13490. _fnDrawHead: _fnDrawHead,
  13491. _fnDraw: _fnDraw,
  13492. _fnReDraw: _fnReDraw,
  13493. _fnAddOptionsHtml: _fnAddOptionsHtml,
  13494. _fnDetectHeader: _fnDetectHeader,
  13495. _fnGetUniqueThs: _fnGetUniqueThs,
  13496. _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
  13497. _fnFilterComplete: _fnFilterComplete,
  13498. _fnFilterCustom: _fnFilterCustom,
  13499. _fnFilterColumn: _fnFilterColumn,
  13500. _fnFilter: _fnFilter,
  13501. _fnFilterCreateSearch: _fnFilterCreateSearch,
  13502. _fnEscapeRegex: _fnEscapeRegex,
  13503. _fnFilterData: _fnFilterData,
  13504. _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
  13505. _fnUpdateInfo: _fnUpdateInfo,
  13506. _fnInfoMacros: _fnInfoMacros,
  13507. _fnInitialise: _fnInitialise,
  13508. _fnInitComplete: _fnInitComplete,
  13509. _fnLengthChange: _fnLengthChange,
  13510. _fnFeatureHtmlLength: _fnFeatureHtmlLength,
  13511. _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
  13512. _fnPageChange: _fnPageChange,
  13513. _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
  13514. _fnProcessingDisplay: _fnProcessingDisplay,
  13515. _fnFeatureHtmlTable: _fnFeatureHtmlTable,
  13516. _fnScrollDraw: _fnScrollDraw,
  13517. _fnApplyToChildren: _fnApplyToChildren,
  13518. _fnCalculateColumnWidths: _fnCalculateColumnWidths,
  13519. _fnThrottle: _fnThrottle,
  13520. _fnConvertToWidth: _fnConvertToWidth,
  13521. _fnGetWidestNode: _fnGetWidestNode,
  13522. _fnGetMaxLenString: _fnGetMaxLenString,
  13523. _fnStringToCss: _fnStringToCss,
  13524. _fnSortFlatten: _fnSortFlatten,
  13525. _fnSort: _fnSort,
  13526. _fnSortAria: _fnSortAria,
  13527. _fnSortListener: _fnSortListener,
  13528. _fnSortAttachListener: _fnSortAttachListener,
  13529. _fnSortingClasses: _fnSortingClasses,
  13530. _fnSortData: _fnSortData,
  13531. _fnSaveState: _fnSaveState,
  13532. _fnLoadState: _fnLoadState,
  13533. _fnImplementState: _fnImplementState,
  13534. _fnSettingsFromNode: _fnSettingsFromNode,
  13535. _fnLog: _fnLog,
  13536. _fnMap: _fnMap,
  13537. _fnBindAction: _fnBindAction,
  13538. _fnCallbackReg: _fnCallbackReg,
  13539. _fnCallbackFire: _fnCallbackFire,
  13540. _fnLengthOverflow: _fnLengthOverflow,
  13541. _fnRenderer: _fnRenderer,
  13542. _fnDataSource: _fnDataSource,
  13543. _fnRowAttributes: _fnRowAttributes,
  13544. _fnExtend: _fnExtend,
  13545. _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
  13546. // in 1.10, so this dead-end function is
  13547. // added to prevent errors
  13548. } );
  13549. // jQuery access
  13550. $.fn.dataTable = DataTable;
  13551. // Provide access to the host jQuery object (circular reference)
  13552. DataTable.$ = $;
  13553. // Legacy aliases
  13554. $.fn.dataTableSettings = DataTable.settings;
  13555. $.fn.dataTableExt = DataTable.ext;
  13556. // With a capital `D` we return a DataTables API instance rather than a
  13557. // jQuery object
  13558. $.fn.DataTable = function ( opts ) {
  13559. return $(this).dataTable( opts ).api();
  13560. };
  13561. // All properties that are available to $.fn.dataTable should also be
  13562. // available on $.fn.DataTable
  13563. $.each( DataTable, function ( prop, val ) {
  13564. $.fn.DataTable[ prop ] = val;
  13565. } );
  13566. return DataTable;
  13567. }));
  13568. /*! DataTables Bootstrap 5 integration
  13569. * 2020 SpryMedia Ltd - datatables.net/license
  13570. */
  13571. (function( factory ){
  13572. if ( typeof define === 'function' && define.amd ) {
  13573. // AMD
  13574. define( ['jquery', 'datatables.net'], function ( $ ) {
  13575. return factory( $, window, document );
  13576. } );
  13577. }
  13578. else if ( typeof exports === 'object' ) {
  13579. // CommonJS
  13580. module.exports = function (root, $) {
  13581. if ( ! root ) {
  13582. // CommonJS environments without a window global must pass a
  13583. // root. This will give an error otherwise
  13584. root = window;
  13585. }
  13586. if ( ! $ ) {
  13587. $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
  13588. require('jquery') :
  13589. require('jquery')( root );
  13590. }
  13591. if ( ! $.fn.dataTable ) {
  13592. require('datatables.net')(root, $);
  13593. }
  13594. return factory( $, root, root.document );
  13595. };
  13596. }
  13597. else {
  13598. // Browser
  13599. factory( jQuery, window, document );
  13600. }
  13601. }(function( $, window, document, undefined ) {
  13602. 'use strict';
  13603. var DataTable = $.fn.dataTable;
  13604. /**
  13605. * DataTables integration for Bootstrap 5. This requires Bootstrap 5 and
  13606. * DataTables 1.10 or newer.
  13607. *
  13608. * This file sets the defaults and adds options to DataTables to style its
  13609. * controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
  13610. * for further information.
  13611. */
  13612. /* Set the defaults for DataTables initialisation */
  13613. $.extend( true, DataTable.defaults, {
  13614. dom:
  13615. "<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>>" +
  13616. "<'row dt-row'<'col-sm-12'tr>>" +
  13617. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  13618. renderer: 'bootstrap'
  13619. } );
  13620. /* Default class modification */
  13621. $.extend( DataTable.ext.classes, {
  13622. sWrapper: "dataTables_wrapper dt-bootstrap5",
  13623. sFilterInput: "form-control form-control-sm",
  13624. sLengthSelect: "form-select form-select-sm",
  13625. sProcessing: "dataTables_processing card",
  13626. sPageButton: "paginate_button page-item"
  13627. } );
  13628. /* Bootstrap paging button renderer */
  13629. DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
  13630. var api = new DataTable.Api( settings );
  13631. var classes = settings.oClasses;
  13632. var lang = settings.oLanguage.oPaginate;
  13633. var aria = settings.oLanguage.oAria.paginate || {};
  13634. var btnDisplay, btnClass;
  13635. var attach = function( container, buttons ) {
  13636. var i, ien, node, button;
  13637. var clickHandler = function ( e ) {
  13638. e.preventDefault();
  13639. if ( !$(e.currentTarget).hasClass('disabled') && api.page() != e.data.action ) {
  13640. api.page( e.data.action ).draw( 'page' );
  13641. }
  13642. };
  13643. for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
  13644. button = buttons[i];
  13645. if ( Array.isArray( button ) ) {
  13646. attach( container, button );
  13647. }
  13648. else {
  13649. btnDisplay = '';
  13650. btnClass = '';
  13651. switch ( button ) {
  13652. case 'ellipsis':
  13653. btnDisplay = '&#x2026;';
  13654. btnClass = 'disabled';
  13655. break;
  13656. case 'first':
  13657. btnDisplay = lang.sFirst;
  13658. btnClass = button + (page > 0 ?
  13659. '' : ' disabled');
  13660. break;
  13661. case 'previous':
  13662. btnDisplay = lang.sPrevious;
  13663. btnClass = button + (page > 0 ?
  13664. '' : ' disabled');
  13665. break;
  13666. case 'next':
  13667. btnDisplay = lang.sNext;
  13668. btnClass = button + (page < pages-1 ?
  13669. '' : ' disabled');
  13670. break;
  13671. case 'last':
  13672. btnDisplay = lang.sLast;
  13673. btnClass = button + (page < pages-1 ?
  13674. '' : ' disabled');
  13675. break;
  13676. default:
  13677. btnDisplay = button + 1;
  13678. btnClass = page === button ?
  13679. 'active' : '';
  13680. break;
  13681. }
  13682. if ( btnDisplay ) {
  13683. node = $('<li>', {
  13684. 'class': classes.sPageButton+' '+btnClass,
  13685. 'id': idx === 0 && typeof button === 'string' ?
  13686. settings.sTableId +'_'+ button :
  13687. null
  13688. } )
  13689. .append( $('<a>', {
  13690. 'href': '#',
  13691. 'aria-controls': settings.sTableId,
  13692. 'aria-label': aria[ button ],
  13693. 'data-dt-idx': button,
  13694. 'tabindex': settings.iTabIndex,
  13695. 'class': 'page-link'
  13696. } )
  13697. .html( btnDisplay )
  13698. )
  13699. .appendTo( container );
  13700. settings.oApi._fnBindAction(
  13701. node, {action: button}, clickHandler
  13702. );
  13703. }
  13704. }
  13705. }
  13706. };
  13707. var hostEl = $(host);
  13708. // IE9 throws an 'unknown error' if document.activeElement is used
  13709. // inside an iframe or frame.
  13710. var activeEl;
  13711. try {
  13712. // Because this approach is destroying and recreating the paging
  13713. // elements, focus is lost on the select button which is bad for
  13714. // accessibility. So we want to restore focus once the draw has
  13715. // completed
  13716. activeEl = hostEl.find(document.activeElement).data('dt-idx');
  13717. }
  13718. catch (e) {}
  13719. var paginationEl = hostEl.children('ul.pagination');
  13720. if (paginationEl.length) {
  13721. paginationEl.empty();
  13722. }
  13723. else {
  13724. paginationEl = hostEl.html('<ul/>').children('ul').addClass('pagination pagination-sm');
  13725. }
  13726. attach(
  13727. paginationEl,
  13728. buttons
  13729. );
  13730. if ( activeEl !== undefined ) {
  13731. hostEl.find('[data-dt-idx='+activeEl+']').trigger('focus');
  13732. }
  13733. };
  13734. return DataTable;
  13735. }));
  13736. /*! Responsive 2.4.0
  13737. * 2014-2022 SpryMedia Ltd - datatables.net/license
  13738. */
  13739. (function( factory ){
  13740. if ( typeof define === 'function' && define.amd ) {
  13741. // AMD
  13742. define( ['jquery', 'datatables.net'], function ( $ ) {
  13743. return factory( $, window, document );
  13744. } );
  13745. }
  13746. else if ( typeof exports === 'object' ) {
  13747. // CommonJS
  13748. module.exports = function (root, $) {
  13749. if ( ! root ) {
  13750. // CommonJS environments without a window global must pass a
  13751. // root. This will give an error otherwise
  13752. root = window;
  13753. }
  13754. if ( ! $ ) {
  13755. $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
  13756. require('jquery') :
  13757. require('jquery')( root );
  13758. }
  13759. if ( ! $.fn.dataTable ) {
  13760. require('datatables.net')(root, $);
  13761. }
  13762. return factory( $, root, root.document );
  13763. };
  13764. }
  13765. else {
  13766. // Browser
  13767. factory( jQuery, window, document );
  13768. }
  13769. }(function( $, window, document, undefined ) {
  13770. 'use strict';
  13771. var DataTable = $.fn.dataTable;
  13772. /**
  13773. * @summary Responsive
  13774. * @description Responsive tables plug-in for DataTables
  13775. * @version 2.4.0
  13776. * @author SpryMedia Ltd (www.sprymedia.co.uk)
  13777. * @contact www.sprymedia.co.uk/contact
  13778. * @copyright SpryMedia Ltd.
  13779. *
  13780. * This source file is free software, available under the following license:
  13781. * MIT license - http://datatables.net/license/mit
  13782. *
  13783. * This source file is distributed in the hope that it will be useful, but
  13784. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  13785. * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  13786. *
  13787. * For details please refer to: http://www.datatables.net
  13788. */
  13789. /**
  13790. * Responsive is a plug-in for the DataTables library that makes use of
  13791. * DataTables' ability to change the visibility of columns, changing the
  13792. * visibility of columns so the displayed columns fit into the table container.
  13793. * The end result is that complex tables will be dynamically adjusted to fit
  13794. * into the viewport, be it on a desktop, tablet or mobile browser.
  13795. *
  13796. * Responsive for DataTables has two modes of operation, which can used
  13797. * individually or combined:
  13798. *
  13799. * * Class name based control - columns assigned class names that match the
  13800. * breakpoint logic can be shown / hidden as required for each breakpoint.
  13801. * * Automatic control - columns are automatically hidden when there is no
  13802. * room left to display them. Columns removed from the right.
  13803. *
  13804. * In additional to column visibility control, Responsive also has built into
  13805. * options to use DataTables' child row display to show / hide the information
  13806. * from the table that has been hidden. There are also two modes of operation
  13807. * for this child row display:
  13808. *
  13809. * * Inline - when the control element that the user can use to show / hide
  13810. * child rows is displayed inside the first column of the table.
  13811. * * Column - where a whole column is dedicated to be the show / hide control.
  13812. *
  13813. * Initialisation of Responsive is performed by:
  13814. *
  13815. * * Adding the class `responsive` or `dt-responsive` to the table. In this case
  13816. * Responsive will automatically be initialised with the default configuration
  13817. * options when the DataTable is created.
  13818. * * Using the `responsive` option in the DataTables configuration options. This
  13819. * can also be used to specify the configuration options, or simply set to
  13820. * `true` to use the defaults.
  13821. *
  13822. * @class
  13823. * @param {object} settings DataTables settings object for the host table
  13824. * @param {object} [opts] Configuration options
  13825. * @requires jQuery 1.7+
  13826. * @requires DataTables 1.10.3+
  13827. *
  13828. * @example
  13829. * $('#example').DataTable( {
  13830. * responsive: true
  13831. * } );
  13832. * } );
  13833. */
  13834. var Responsive = function ( settings, opts ) {
  13835. // Sanity check that we are using DataTables 1.10 or newer
  13836. if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.10' ) ) {
  13837. throw 'DataTables Responsive requires DataTables 1.10.10 or newer';
  13838. }
  13839. this.s = {
  13840. childNodeStore: {},
  13841. columns: [],
  13842. current: [],
  13843. dt: new DataTable.Api( settings )
  13844. };
  13845. // Check if responsive has already been initialised on this table
  13846. if ( this.s.dt.settings()[0].responsive ) {
  13847. return;
  13848. }
  13849. // details is an object, but for simplicity the user can give it as a string
  13850. // or a boolean
  13851. if ( opts && typeof opts.details === 'string' ) {
  13852. opts.details = { type: opts.details };
  13853. }
  13854. else if ( opts && opts.details === false ) {
  13855. opts.details = { type: false };
  13856. }
  13857. else if ( opts && opts.details === true ) {
  13858. opts.details = { type: 'inline' };
  13859. }
  13860. this.c = $.extend( true, {}, Responsive.defaults, DataTable.defaults.responsive, opts );
  13861. settings.responsive = this;
  13862. this._constructor();
  13863. };
  13864. $.extend( Responsive.prototype, {
  13865. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  13866. * Constructor
  13867. */
  13868. /**
  13869. * Initialise the Responsive instance
  13870. *
  13871. * @private
  13872. */
  13873. _constructor: function ()
  13874. {
  13875. var that = this;
  13876. var dt = this.s.dt;
  13877. var dtPrivateSettings = dt.settings()[0];
  13878. var oldWindowWidth = $(window).innerWidth();
  13879. dt.settings()[0]._responsive = this;
  13880. // Use DataTables' throttle function to avoid processor thrashing on
  13881. // resize
  13882. $(window).on( 'resize.dtr orientationchange.dtr', DataTable.util.throttle( function () {
  13883. // iOS has a bug whereby resize can fire when only scrolling
  13884. // See: http://stackoverflow.com/questions/8898412
  13885. var width = $(window).innerWidth();
  13886. if ( width !== oldWindowWidth ) {
  13887. that._resize();
  13888. oldWindowWidth = width;
  13889. }
  13890. } ) );
  13891. // DataTables doesn't currently trigger an event when a row is added, so
  13892. // we need to hook into its private API to enforce the hidden rows when
  13893. // new data is added
  13894. dtPrivateSettings.oApi._fnCallbackReg( dtPrivateSettings, 'aoRowCreatedCallback', function (tr, data, idx) {
  13895. if ( $.inArray( false, that.s.current ) !== -1 ) {
  13896. $('>td, >th', tr).each( function ( i ) {
  13897. var idx = dt.column.index( 'toData', i );
  13898. if ( that.s.current[idx] === false ) {
  13899. $(this).css('display', 'none');
  13900. }
  13901. } );
  13902. }
  13903. } );
  13904. // Destroy event handler
  13905. dt.on( 'destroy.dtr', function () {
  13906. dt.off( '.dtr' );
  13907. $( dt.table().body() ).off( '.dtr' );
  13908. $(window).off( 'resize.dtr orientationchange.dtr' );
  13909. dt.cells('.dtr-control').nodes().to$().removeClass('dtr-control');
  13910. // Restore the columns that we've hidden
  13911. $.each( that.s.current, function ( i, val ) {
  13912. if ( val === false ) {
  13913. that._setColumnVis( i, true );
  13914. }
  13915. } );
  13916. } );
  13917. // Reorder the breakpoints array here in case they have been added out
  13918. // of order
  13919. this.c.breakpoints.sort( function (a, b) {
  13920. return a.width < b.width ? 1 :
  13921. a.width > b.width ? -1 : 0;
  13922. } );
  13923. this._classLogic();
  13924. this._resizeAuto();
  13925. // Details handler
  13926. var details = this.c.details;
  13927. if ( details.type !== false ) {
  13928. that._detailsInit();
  13929. // DataTables will trigger this event on every column it shows and
  13930. // hides individually
  13931. dt.on( 'column-visibility.dtr', function () {
  13932. // Use a small debounce to allow multiple columns to be set together
  13933. if ( that._timer ) {
  13934. clearTimeout( that._timer );
  13935. }
  13936. that._timer = setTimeout( function () {
  13937. that._timer = null;
  13938. that._classLogic();
  13939. that._resizeAuto();
  13940. that._resize(true);
  13941. that._redrawChildren();
  13942. }, 100 );
  13943. } );
  13944. // Redraw the details box on each draw which will happen if the data
  13945. // has changed. This is used until DataTables implements a native
  13946. // `updated` event for rows
  13947. dt.on( 'draw.dtr', function () {
  13948. that._redrawChildren();
  13949. } );
  13950. $(dt.table().node()).addClass( 'dtr-'+details.type );
  13951. }
  13952. dt.on( 'column-reorder.dtr', function (e, settings, details) {
  13953. that._classLogic();
  13954. that._resizeAuto();
  13955. that._resize(true);
  13956. } );
  13957. // Change in column sizes means we need to calc
  13958. dt.on( 'column-sizing.dtr', function () {
  13959. that._resizeAuto();
  13960. that._resize();
  13961. });
  13962. // DT2 let's us tell it if we are hiding columns
  13963. dt.on( 'column-calc.dt', function (e, d) {
  13964. var curr = that.s.current;
  13965. for (var i=0 ; i<curr.length ; i++) {
  13966. var idx = d.visible.indexOf(i);
  13967. if (curr[i] === false && idx >= 0) {
  13968. d.visible.splice(idx, 1);
  13969. }
  13970. }
  13971. } );
  13972. // On Ajax reload we want to reopen any child rows which are displayed
  13973. // by responsive
  13974. dt.on( 'preXhr.dtr', function () {
  13975. var rowIds = [];
  13976. dt.rows().every( function () {
  13977. if ( this.child.isShown() ) {
  13978. rowIds.push( this.id(true) );
  13979. }
  13980. } );
  13981. dt.one( 'draw.dtr', function () {
  13982. that._resizeAuto();
  13983. that._resize();
  13984. dt.rows( rowIds ).every( function () {
  13985. that._detailsDisplay( this, false );
  13986. } );
  13987. } );
  13988. });
  13989. dt
  13990. .on( 'draw.dtr', function () {
  13991. that._controlClass();
  13992. })
  13993. .on( 'init.dtr', function (e, settings, details) {
  13994. if ( e.namespace !== 'dt' ) {
  13995. return;
  13996. }
  13997. that._resizeAuto();
  13998. that._resize();
  13999. // If columns were hidden, then DataTables needs to adjust the
  14000. // column sizing
  14001. if ( $.inArray( false, that.s.current ) ) {
  14002. dt.columns.adjust();
  14003. }
  14004. } );
  14005. // First pass - draw the table for the current viewport size
  14006. this._resize();
  14007. },
  14008. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  14009. * Private methods
  14010. */
  14011. /**
  14012. * Get and store nodes from a cell - use for node moving renderers
  14013. *
  14014. * @param {*} dt DT instance
  14015. * @param {*} row Row index
  14016. * @param {*} col Column index
  14017. */
  14018. _childNodes: function( dt, row, col ) {
  14019. var name = row+'-'+col;
  14020. if ( this.s.childNodeStore[ name ] ) {
  14021. return this.s.childNodeStore[ name ];
  14022. }
  14023. // https://jsperf.com/childnodes-array-slice-vs-loop
  14024. var nodes = [];
  14025. var children = dt.cell( row, col ).node().childNodes;
  14026. for ( var i=0, ien=children.length ; i<ien ; i++ ) {
  14027. nodes.push( children[i] );
  14028. }
  14029. this.s.childNodeStore[ name ] = nodes;
  14030. return nodes;
  14031. },
  14032. /**
  14033. * Restore nodes from the cache to a table cell
  14034. *
  14035. * @param {*} dt DT instance
  14036. * @param {*} row Row index
  14037. * @param {*} col Column index
  14038. */
  14039. _childNodesRestore: function( dt, row, col ) {
  14040. var name = row+'-'+col;
  14041. if ( ! this.s.childNodeStore[ name ] ) {
  14042. return;
  14043. }
  14044. var node = dt.cell( row, col ).node();
  14045. var store = this.s.childNodeStore[ name ];
  14046. var parent = store[0].parentNode;
  14047. var parentChildren = parent.childNodes;
  14048. var a = [];
  14049. for ( var i=0, ien=parentChildren.length ; i<ien ; i++ ) {
  14050. a.push( parentChildren[i] );
  14051. }
  14052. for ( var j=0, jen=a.length ; j<jen ; j++ ) {
  14053. node.appendChild( a[j] );
  14054. }
  14055. this.s.childNodeStore[ name ] = undefined;
  14056. },
  14057. /**
  14058. * Calculate the visibility for the columns in a table for a given
  14059. * breakpoint. The result is pre-determined based on the class logic if
  14060. * class names are used to control all columns, but the width of the table
  14061. * is also used if there are columns which are to be automatically shown
  14062. * and hidden.
  14063. *
  14064. * @param {string} breakpoint Breakpoint name to use for the calculation
  14065. * @return {array} Array of boolean values initiating the visibility of each
  14066. * column.
  14067. * @private
  14068. */
  14069. _columnsVisiblity: function ( breakpoint )
  14070. {
  14071. var dt = this.s.dt;
  14072. var columns = this.s.columns;
  14073. var i, ien;
  14074. // Create an array that defines the column ordering based first on the
  14075. // column's priority, and secondly the column index. This allows the
  14076. // columns to be removed from the right if the priority matches
  14077. var order = columns
  14078. .map( function ( col, idx ) {
  14079. return {
  14080. columnIdx: idx,
  14081. priority: col.priority
  14082. };
  14083. } )
  14084. .sort( function ( a, b ) {
  14085. if ( a.priority !== b.priority ) {
  14086. return a.priority - b.priority;
  14087. }
  14088. return a.columnIdx - b.columnIdx;
  14089. } );
  14090. // Class logic - determine which columns are in this breakpoint based
  14091. // on the classes. If no class control (i.e. `auto`) then `-` is used
  14092. // to indicate this to the rest of the function
  14093. var display = $.map( columns, function ( col, i ) {
  14094. if ( dt.column(i).visible() === false ) {
  14095. return 'not-visible';
  14096. }
  14097. return col.auto && col.minWidth === null ?
  14098. false :
  14099. col.auto === true ?
  14100. '-' :
  14101. $.inArray( breakpoint, col.includeIn ) !== -1;
  14102. } );
  14103. // Auto column control - first pass: how much width is taken by the
  14104. // ones that must be included from the non-auto columns
  14105. var requiredWidth = 0;
  14106. for ( i=0, ien=display.length ; i<ien ; i++ ) {
  14107. if ( display[i] === true ) {
  14108. requiredWidth += columns[i].minWidth;
  14109. }
  14110. }
  14111. // Second pass, use up any remaining width for other columns. For
  14112. // scrolling tables we need to subtract the width of the scrollbar. It
  14113. // may not be requires which makes this sub-optimal, but it would
  14114. // require another full redraw to make complete use of those extra few
  14115. // pixels
  14116. var scrolling = dt.settings()[0].oScroll;
  14117. var bar = scrolling.sY || scrolling.sX ? scrolling.iBarWidth : 0;
  14118. var widthAvailable = dt.table().container().offsetWidth - bar;
  14119. var usedWidth = widthAvailable - requiredWidth;
  14120. // Control column needs to always be included. This makes it sub-
  14121. // optimal in terms of using the available with, but to stop layout
  14122. // thrashing or overflow. Also we need to account for the control column
  14123. // width first so we know how much width is available for the other
  14124. // columns, since the control column might not be the first one shown
  14125. for ( i=0, ien=display.length ; i<ien ; i++ ) {
  14126. if ( columns[i].control ) {
  14127. usedWidth -= columns[i].minWidth;
  14128. }
  14129. }
  14130. // Allow columns to be shown (counting by priority and then right to
  14131. // left) until we run out of room
  14132. var empty = false;
  14133. for ( i=0, ien=order.length ; i<ien ; i++ ) {
  14134. var colIdx = order[i].columnIdx;
  14135. if ( display[colIdx] === '-' && ! columns[colIdx].control && columns[colIdx].minWidth ) {
  14136. // Once we've found a column that won't fit we don't let any
  14137. // others display either, or columns might disappear in the
  14138. // middle of the table
  14139. if ( empty || usedWidth - columns[colIdx].minWidth < 0 ) {
  14140. empty = true;
  14141. display[colIdx] = false;
  14142. }
  14143. else {
  14144. display[colIdx] = true;
  14145. }
  14146. usedWidth -= columns[colIdx].minWidth;
  14147. }
  14148. }
  14149. // Determine if the 'control' column should be shown (if there is one).
  14150. // This is the case when there is a hidden column (that is not the
  14151. // control column). The two loops look inefficient here, but they are
  14152. // trivial and will fly through. We need to know the outcome from the
  14153. // first , before the action in the second can be taken
  14154. var showControl = false;
  14155. for ( i=0, ien=columns.length ; i<ien ; i++ ) {
  14156. if ( ! columns[i].control && ! columns[i].never && display[i] === false ) {
  14157. showControl = true;
  14158. break;
  14159. }
  14160. }
  14161. for ( i=0, ien=columns.length ; i<ien ; i++ ) {
  14162. if ( columns[i].control ) {
  14163. display[i] = showControl;
  14164. }
  14165. // Replace not visible string with false from the control column detection above
  14166. if ( display[i] === 'not-visible' ) {
  14167. display[i] = false;
  14168. }
  14169. }
  14170. // Finally we need to make sure that there is at least one column that
  14171. // is visible
  14172. if ( $.inArray( true, display ) === -1 ) {
  14173. display[0] = true;
  14174. }
  14175. return display;
  14176. },
  14177. /**
  14178. * Create the internal `columns` array with information about the columns
  14179. * for the table. This includes determining which breakpoints the column
  14180. * will appear in, based upon class names in the column, which makes up the
  14181. * vast majority of this method.
  14182. *
  14183. * @private
  14184. */
  14185. _classLogic: function ()
  14186. {
  14187. var that = this;
  14188. var calc = {};
  14189. var breakpoints = this.c.breakpoints;
  14190. var dt = this.s.dt;
  14191. var columns = dt.columns().eq(0).map( function (i) {
  14192. var column = this.column(i);
  14193. var className = column.header().className;
  14194. var priority = dt.settings()[0].aoColumns[i].responsivePriority;
  14195. var dataPriority = column.header().getAttribute('data-priority');
  14196. if ( priority === undefined ) {
  14197. priority = dataPriority === undefined || dataPriority === null?
  14198. 10000 :
  14199. dataPriority * 1;
  14200. }
  14201. return {
  14202. className: className,
  14203. includeIn: [],
  14204. auto: false,
  14205. control: false,
  14206. never: className.match(/\b(dtr\-)?never\b/) ? true : false,
  14207. priority: priority
  14208. };
  14209. } );
  14210. // Simply add a breakpoint to `includeIn` array, ensuring that there are
  14211. // no duplicates
  14212. var add = function ( colIdx, name ) {
  14213. var includeIn = columns[ colIdx ].includeIn;
  14214. if ( $.inArray( name, includeIn ) === -1 ) {
  14215. includeIn.push( name );
  14216. }
  14217. };
  14218. var column = function ( colIdx, name, operator, matched ) {
  14219. var size, i, ien;
  14220. if ( ! operator ) {
  14221. columns[ colIdx ].includeIn.push( name );
  14222. }
  14223. else if ( operator === 'max-' ) {
  14224. // Add this breakpoint and all smaller
  14225. size = that._find( name ).width;
  14226. for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
  14227. if ( breakpoints[i].width <= size ) {
  14228. add( colIdx, breakpoints[i].name );
  14229. }
  14230. }
  14231. }
  14232. else if ( operator === 'min-' ) {
  14233. // Add this breakpoint and all larger
  14234. size = that._find( name ).width;
  14235. for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
  14236. if ( breakpoints[i].width >= size ) {
  14237. add( colIdx, breakpoints[i].name );
  14238. }
  14239. }
  14240. }
  14241. else if ( operator === 'not-' ) {
  14242. // Add all but this breakpoint
  14243. for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
  14244. if ( breakpoints[i].name.indexOf( matched ) === -1 ) {
  14245. add( colIdx, breakpoints[i].name );
  14246. }
  14247. }
  14248. }
  14249. };
  14250. // Loop over each column and determine if it has a responsive control
  14251. // class
  14252. columns.each( function ( col, i ) {
  14253. var classNames = col.className.split(' ');
  14254. var hasClass = false;
  14255. // Split the class name up so multiple rules can be applied if needed
  14256. for ( var k=0, ken=classNames.length ; k<ken ; k++ ) {
  14257. var className = classNames[k].trim();
  14258. if ( className === 'all' || className === 'dtr-all' ) {
  14259. // Include in all
  14260. hasClass = true;
  14261. col.includeIn = $.map( breakpoints, function (a) {
  14262. return a.name;
  14263. } );
  14264. return;
  14265. }
  14266. else if ( className === 'none' || className === 'dtr-none' || col.never ) {
  14267. // Include in none (default) and no auto
  14268. hasClass = true;
  14269. return;
  14270. }
  14271. else if ( className === 'control' || className === 'dtr-control' ) {
  14272. // Special column that is only visible, when one of the other
  14273. // columns is hidden. This is used for the details control
  14274. hasClass = true;
  14275. col.control = true;
  14276. return;
  14277. }
  14278. $.each( breakpoints, function ( j, breakpoint ) {
  14279. // Does this column have a class that matches this breakpoint?
  14280. var brokenPoint = breakpoint.name.split('-');
  14281. var re = new RegExp( '(min\\-|max\\-|not\\-)?('+brokenPoint[0]+')(\\-[_a-zA-Z0-9])?' );
  14282. var match = className.match( re );
  14283. if ( match ) {
  14284. hasClass = true;
  14285. if ( match[2] === brokenPoint[0] && match[3] === '-'+brokenPoint[1] ) {
  14286. // Class name matches breakpoint name fully
  14287. column( i, breakpoint.name, match[1], match[2]+match[3] );
  14288. }
  14289. else if ( match[2] === brokenPoint[0] && ! match[3] ) {
  14290. // Class name matched primary breakpoint name with no qualifier
  14291. column( i, breakpoint.name, match[1], match[2] );
  14292. }
  14293. }
  14294. } );
  14295. }
  14296. // If there was no control class, then automatic sizing is used
  14297. if ( ! hasClass ) {
  14298. col.auto = true;
  14299. }
  14300. } );
  14301. this.s.columns = columns;
  14302. },
  14303. /**
  14304. * Update the cells to show the correct control class / button
  14305. * @private
  14306. */
  14307. _controlClass: function ()
  14308. {
  14309. if ( this.c.details.type === 'inline' ) {
  14310. var dt = this.s.dt;
  14311. var columnsVis = this.s.current;
  14312. var firstVisible = $.inArray(true, columnsVis);
  14313. // Remove from any cells which shouldn't have it
  14314. dt.cells(
  14315. null,
  14316. function(idx) {
  14317. return idx !== firstVisible;
  14318. },
  14319. {page: 'current'}
  14320. )
  14321. .nodes()
  14322. .to$()
  14323. .filter('.dtr-control')
  14324. .removeClass('dtr-control');
  14325. dt.cells(null, firstVisible, {page: 'current'})
  14326. .nodes()
  14327. .to$()
  14328. .addClass('dtr-control');
  14329. }
  14330. },
  14331. /**
  14332. * Show the details for the child row
  14333. *
  14334. * @param {DataTables.Api} row API instance for the row
  14335. * @param {boolean} update Update flag
  14336. * @private
  14337. */
  14338. _detailsDisplay: function ( row, update )
  14339. {
  14340. var that = this;
  14341. var dt = this.s.dt;
  14342. var details = this.c.details;
  14343. if ( details && details.type !== false ) {
  14344. var renderer = typeof details.renderer === 'string'
  14345. ? Responsive.renderer[details.renderer]()
  14346. : details.renderer;
  14347. var res = details.display( row, update, function () {
  14348. return renderer.call(
  14349. that, dt, row[0], that._detailsObj(row[0])
  14350. );
  14351. } );
  14352. if ( res === true || res === false ) {
  14353. $(dt.table().node()).triggerHandler( 'responsive-display.dt', [dt, row, res, update] );
  14354. }
  14355. }
  14356. },
  14357. /**
  14358. * Initialisation for the details handler
  14359. *
  14360. * @private
  14361. */
  14362. _detailsInit: function ()
  14363. {
  14364. var that = this;
  14365. var dt = this.s.dt;
  14366. var details = this.c.details;
  14367. // The inline type always uses the first child as the target
  14368. if ( details.type === 'inline' ) {
  14369. details.target = 'td.dtr-control, th.dtr-control';
  14370. }
  14371. // Keyboard accessibility
  14372. dt.on( 'draw.dtr', function () {
  14373. that._tabIndexes();
  14374. } );
  14375. that._tabIndexes(); // Initial draw has already happened
  14376. $( dt.table().body() ).on( 'keyup.dtr', 'td, th', function (e) {
  14377. if ( e.keyCode === 13 && $(this).data('dtr-keyboard') ) {
  14378. $(this).click();
  14379. }
  14380. } );
  14381. // type.target can be a string jQuery selector or a column index
  14382. var target = details.target;
  14383. var selector = typeof target === 'string' ? target : 'td, th';
  14384. if ( target !== undefined || target !== null ) {
  14385. // Click handler to show / hide the details rows when they are available
  14386. $( dt.table().body() )
  14387. .on( 'click.dtr mousedown.dtr mouseup.dtr', selector, function (e) {
  14388. // If the table is not collapsed (i.e. there is no hidden columns)
  14389. // then take no action
  14390. if ( ! $(dt.table().node()).hasClass('collapsed' ) ) {
  14391. return;
  14392. }
  14393. // Check that the row is actually a DataTable's controlled node
  14394. if ( $.inArray( $(this).closest('tr').get(0), dt.rows().nodes().toArray() ) === -1 ) {
  14395. return;
  14396. }
  14397. // For column index, we determine if we should act or not in the
  14398. // handler - otherwise it is already okay
  14399. if ( typeof target === 'number' ) {
  14400. var targetIdx = target < 0 ?
  14401. dt.columns().eq(0).length + target :
  14402. target;
  14403. if ( dt.cell( this ).index().column !== targetIdx ) {
  14404. return;
  14405. }
  14406. }
  14407. // $().closest() includes itself in its check
  14408. var row = dt.row( $(this).closest('tr') );
  14409. // Check event type to do an action
  14410. if ( e.type === 'click' ) {
  14411. // The renderer is given as a function so the caller can execute it
  14412. // only when they need (i.e. if hiding there is no point is running
  14413. // the renderer)
  14414. that._detailsDisplay( row, false );
  14415. }
  14416. else if ( e.type === 'mousedown' ) {
  14417. // For mouse users, prevent the focus ring from showing
  14418. $(this).css('outline', 'none');
  14419. }
  14420. else if ( e.type === 'mouseup' ) {
  14421. // And then re-allow at the end of the click
  14422. $(this).trigger('blur').css('outline', '');
  14423. }
  14424. } );
  14425. }
  14426. },
  14427. /**
  14428. * Get the details to pass to a renderer for a row
  14429. * @param {int} rowIdx Row index
  14430. * @private
  14431. */
  14432. _detailsObj: function ( rowIdx )
  14433. {
  14434. var that = this;
  14435. var dt = this.s.dt;
  14436. return $.map( this.s.columns, function( col, i ) {
  14437. // Never and control columns should not be passed to the renderer
  14438. if ( col.never || col.control ) {
  14439. return;
  14440. }
  14441. var dtCol = dt.settings()[0].aoColumns[ i ];
  14442. return {
  14443. className: dtCol.sClass,
  14444. columnIndex: i,
  14445. data: dt.cell( rowIdx, i ).render( that.c.orthogonal ),
  14446. hidden: dt.column( i ).visible() && !that.s.current[ i ],
  14447. rowIndex: rowIdx,
  14448. title: dtCol.sTitle !== null ?
  14449. dtCol.sTitle :
  14450. $(dt.column(i).header()).text()
  14451. };
  14452. } );
  14453. },
  14454. /**
  14455. * Find a breakpoint object from a name
  14456. *
  14457. * @param {string} name Breakpoint name to find
  14458. * @return {object} Breakpoint description object
  14459. * @private
  14460. */
  14461. _find: function ( name )
  14462. {
  14463. var breakpoints = this.c.breakpoints;
  14464. for ( var i=0, ien=breakpoints.length ; i<ien ; i++ ) {
  14465. if ( breakpoints[i].name === name ) {
  14466. return breakpoints[i];
  14467. }
  14468. }
  14469. },
  14470. /**
  14471. * Re-create the contents of the child rows as the display has changed in
  14472. * some way.
  14473. *
  14474. * @private
  14475. */
  14476. _redrawChildren: function ()
  14477. {
  14478. var that = this;
  14479. var dt = this.s.dt;
  14480. dt.rows( {page: 'current'} ).iterator( 'row', function ( settings, idx ) {
  14481. var row = dt.row( idx );
  14482. that._detailsDisplay( dt.row( idx ), true );
  14483. } );
  14484. },
  14485. /**
  14486. * Alter the table display for a resized viewport. This involves first
  14487. * determining what breakpoint the window currently is in, getting the
  14488. * column visibilities to apply and then setting them.
  14489. *
  14490. * @param {boolean} forceRedraw Force a redraw
  14491. * @private
  14492. */
  14493. _resize: function (forceRedraw)
  14494. {
  14495. var that = this;
  14496. var dt = this.s.dt;
  14497. var width = $(window).innerWidth();
  14498. var breakpoints = this.c.breakpoints;
  14499. var breakpoint = breakpoints[0].name;
  14500. var columns = this.s.columns;
  14501. var i, ien;
  14502. var oldVis = this.s.current.slice();
  14503. // Determine what breakpoint we are currently at
  14504. for ( i=breakpoints.length-1 ; i>=0 ; i-- ) {
  14505. if ( width <= breakpoints[i].width ) {
  14506. breakpoint = breakpoints[i].name;
  14507. break;
  14508. }
  14509. }
  14510. // Show the columns for that break point
  14511. var columnsVis = this._columnsVisiblity( breakpoint );
  14512. this.s.current = columnsVis;
  14513. // Set the class before the column visibility is changed so event
  14514. // listeners know what the state is. Need to determine if there are
  14515. // any columns that are not visible but can be shown
  14516. var collapsedClass = false;
  14517. for ( i=0, ien=columns.length ; i<ien ; i++ ) {
  14518. if ( columnsVis[i] === false && ! columns[i].never && ! columns[i].control && ! dt.column(i).visible() === false ) {
  14519. collapsedClass = true;
  14520. break;
  14521. }
  14522. }
  14523. $( dt.table().node() ).toggleClass( 'collapsed', collapsedClass );
  14524. var changed = false;
  14525. var visible = 0;
  14526. dt.columns().eq(0).each( function ( colIdx, i ) {
  14527. if ( columnsVis[i] === true ) {
  14528. visible++;
  14529. }
  14530. if ( forceRedraw || columnsVis[i] !== oldVis[i] ) {
  14531. changed = true;
  14532. that._setColumnVis( colIdx, columnsVis[i] );
  14533. }
  14534. } );
  14535. // Always need to update the display, regardless of if it has changed or not, so nodes
  14536. // can be re-inserted for listHiddenNodes
  14537. this._redrawChildren();
  14538. if ( changed ) {
  14539. // Inform listeners of the change
  14540. $(dt.table().node()).trigger( 'responsive-resize.dt', [dt, this.s.current] );
  14541. // If no records, update the "No records" display element
  14542. if ( dt.page.info().recordsDisplay === 0 ) {
  14543. $('td', dt.table().body()).eq(0).attr('colspan', visible);
  14544. }
  14545. }
  14546. that._controlClass();
  14547. },
  14548. /**
  14549. * Determine the width of each column in the table so the auto column hiding
  14550. * has that information to work with. This method is never going to be 100%
  14551. * perfect since column widths can change slightly per page, but without
  14552. * seriously compromising performance this is quite effective.
  14553. *
  14554. * @private
  14555. */
  14556. _resizeAuto: function ()
  14557. {
  14558. var dt = this.s.dt;
  14559. var columns = this.s.columns;
  14560. var that = this;
  14561. // Are we allowed to do auto sizing?
  14562. if ( ! this.c.auto ) {
  14563. return;
  14564. }
  14565. // Are there any columns that actually need auto-sizing, or do they all
  14566. // have classes defined
  14567. if ( $.inArray( true, $.map( columns, function (c) { return c.auto; } ) ) === -1 ) {
  14568. return;
  14569. }
  14570. // Need to restore all children. They will be reinstated by a re-render
  14571. if ( ! $.isEmptyObject( this.s.childNodeStore ) ) {
  14572. $.each( this.s.childNodeStore, function ( key ) {
  14573. var idx = key.split('-');
  14574. that._childNodesRestore( dt, idx[0]*1, idx[1]*1 );
  14575. } );
  14576. }
  14577. // Clone the table with the current data in it
  14578. var tableWidth = dt.table().node().offsetWidth;
  14579. var columnWidths = dt.columns;
  14580. var clonedTable = dt.table().node().cloneNode( false );
  14581. var clonedHeader = $( dt.table().header().cloneNode( false ) ).appendTo( clonedTable );
  14582. var clonedBody = $( dt.table().body() ).clone( false, false ).empty().appendTo( clonedTable ); // use jQuery because of IE8
  14583. clonedTable.style.width = 'auto';
  14584. // Header
  14585. var headerCells = dt.columns()
  14586. .header()
  14587. .filter( function (idx) {
  14588. return dt.column(idx).visible();
  14589. } )
  14590. .to$()
  14591. .clone( false )
  14592. .css( 'display', 'table-cell' )
  14593. .css( 'width', 'auto' )
  14594. .css( 'min-width', 0 );
  14595. // Body rows - we don't need to take account of DataTables' column
  14596. // visibility since we implement our own here (hence the `display` set)
  14597. $(clonedBody)
  14598. .append( $(dt.rows( { page: 'current' } ).nodes()).clone( false ) )
  14599. .find( 'th, td' ).css( 'display', '' );
  14600. // Footer
  14601. var footer = dt.table().footer();
  14602. if ( footer ) {
  14603. var clonedFooter = $( footer.cloneNode( false ) ).appendTo( clonedTable );
  14604. var footerCells = dt.columns()
  14605. .footer()
  14606. .filter( function (idx) {
  14607. return dt.column(idx).visible();
  14608. } )
  14609. .to$()
  14610. .clone( false )
  14611. .css( 'display', 'table-cell' );
  14612. $('<tr/>')
  14613. .append( footerCells )
  14614. .appendTo( clonedFooter );
  14615. }
  14616. $('<tr/>')
  14617. .append( headerCells )
  14618. .appendTo( clonedHeader );
  14619. // In the inline case extra padding is applied to the first column to
  14620. // give space for the show / hide icon. We need to use this in the
  14621. // calculation
  14622. if ( this.c.details.type === 'inline' ) {
  14623. $(clonedTable).addClass( 'dtr-inline collapsed' );
  14624. }
  14625. // It is unsafe to insert elements with the same name into the DOM
  14626. // multiple times. For example, cloning and inserting a checked radio
  14627. // clears the chcecked state of the original radio.
  14628. $( clonedTable ).find( '[name]' ).removeAttr( 'name' );
  14629. // A position absolute table would take the table out of the flow of
  14630. // our container element, bypassing the height and width (Scroller)
  14631. $( clonedTable ).css( 'position', 'relative' )
  14632. var inserted = $('<div/>')
  14633. .css( {
  14634. width: 1,
  14635. height: 1,
  14636. overflow: 'hidden',
  14637. clear: 'both'
  14638. } )
  14639. .append( clonedTable );
  14640. inserted.insertBefore( dt.table().node() );
  14641. // The cloned header now contains the smallest that each column can be
  14642. headerCells.each( function (i) {
  14643. var idx = dt.column.index( 'fromVisible', i );
  14644. columns[ idx ].minWidth = this.offsetWidth || 0;
  14645. } );
  14646. inserted.remove();
  14647. },
  14648. /**
  14649. * Get the state of the current hidden columns - controlled by Responsive only
  14650. */
  14651. _responsiveOnlyHidden: function ()
  14652. {
  14653. var dt = this.s.dt;
  14654. return $.map( this.s.current, function (v, i) {
  14655. // If the column is hidden by DataTables then it can't be hidden by
  14656. // Responsive!
  14657. if ( dt.column(i).visible() === false ) {
  14658. return true;
  14659. }
  14660. return v;
  14661. } );
  14662. },
  14663. /**
  14664. * Set a column's visibility.
  14665. *
  14666. * We don't use DataTables' column visibility controls in order to ensure
  14667. * that column visibility can Responsive can no-exist. Since only IE8+ is
  14668. * supported (and all evergreen browsers of course) the control of the
  14669. * display attribute works well.
  14670. *
  14671. * @param {integer} col Column index
  14672. * @param {boolean} showHide Show or hide (true or false)
  14673. * @private
  14674. */
  14675. _setColumnVis: function ( col, showHide )
  14676. {
  14677. var that = this;
  14678. var dt = this.s.dt;
  14679. var display = showHide ? '' : 'none'; // empty string will remove the attr
  14680. $( dt.column( col ).header() )
  14681. .css( 'display', display )
  14682. .toggleClass('dtr-hidden', !showHide);
  14683. $( dt.column( col ).footer() )
  14684. .css( 'display', display )
  14685. .toggleClass('dtr-hidden', !showHide);
  14686. dt.column( col ).nodes().to$()
  14687. .css( 'display', display )
  14688. .toggleClass('dtr-hidden', !showHide);
  14689. // If the are child nodes stored, we might need to reinsert them
  14690. if ( ! $.isEmptyObject( this.s.childNodeStore ) ) {
  14691. dt.cells( null, col ).indexes().each( function (idx) {
  14692. that._childNodesRestore( dt, idx.row, idx.column );
  14693. } );
  14694. }
  14695. },
  14696. /**
  14697. * Update the cell tab indexes for keyboard accessibility. This is called on
  14698. * every table draw - that is potentially inefficient, but also the least
  14699. * complex option given that column visibility can change on the fly. Its a
  14700. * shame user-focus was removed from CSS 3 UI, as it would have solved this
  14701. * issue with a single CSS statement.
  14702. *
  14703. * @private
  14704. */
  14705. _tabIndexes: function ()
  14706. {
  14707. var dt = this.s.dt;
  14708. var cells = dt.cells( { page: 'current' } ).nodes().to$();
  14709. var ctx = dt.settings()[0];
  14710. var target = this.c.details.target;
  14711. cells.filter( '[data-dtr-keyboard]' ).removeData( '[data-dtr-keyboard]' );
  14712. if ( typeof target === 'number' ) {
  14713. dt.cells( null, target, { page: 'current' } ).nodes().to$()
  14714. .attr( 'tabIndex', ctx.iTabIndex )
  14715. .data( 'dtr-keyboard', 1 );
  14716. }
  14717. else {
  14718. // This is a bit of a hack - we need to limit the selected nodes to just
  14719. // those of this table
  14720. if ( target === 'td:first-child, th:first-child' ) {
  14721. target = '>td:first-child, >th:first-child';
  14722. }
  14723. $( target, dt.rows( { page: 'current' } ).nodes() )
  14724. .attr( 'tabIndex', ctx.iTabIndex )
  14725. .data( 'dtr-keyboard', 1 );
  14726. }
  14727. }
  14728. } );
  14729. /**
  14730. * List of default breakpoints. Each item in the array is an object with two
  14731. * properties:
  14732. *
  14733. * * `name` - the breakpoint name.
  14734. * * `width` - the breakpoint width
  14735. *
  14736. * @name Responsive.breakpoints
  14737. * @static
  14738. */
  14739. Responsive.breakpoints = [
  14740. { name: 'desktop', width: Infinity },
  14741. { name: 'tablet-l', width: 1024 },
  14742. { name: 'tablet-p', width: 768 },
  14743. { name: 'mobile-l', width: 480 },
  14744. { name: 'mobile-p', width: 320 }
  14745. ];
  14746. /**
  14747. * Display methods - functions which define how the hidden data should be shown
  14748. * in the table.
  14749. *
  14750. * @namespace
  14751. * @name Responsive.defaults
  14752. * @static
  14753. */
  14754. Responsive.display = {
  14755. childRow: function ( row, update, render ) {
  14756. if ( update ) {
  14757. if ( $(row.node()).hasClass('parent') ) {
  14758. row.child( render(), 'child' ).show();
  14759. return true;
  14760. }
  14761. }
  14762. else {
  14763. if ( ! row.child.isShown() ) {
  14764. row.child( render(), 'child' ).show();
  14765. $( row.node() ).addClass( 'parent' );
  14766. return true;
  14767. }
  14768. else {
  14769. row.child( false );
  14770. $( row.node() ).removeClass( 'parent' );
  14771. return false;
  14772. }
  14773. }
  14774. },
  14775. childRowImmediate: function ( row, update, render ) {
  14776. if ( (! update && row.child.isShown()) || ! row.responsive.hasHidden() ) {
  14777. // User interaction and the row is show, or nothing to show
  14778. row.child( false );
  14779. $( row.node() ).removeClass( 'parent' );
  14780. return false;
  14781. }
  14782. else {
  14783. // Display
  14784. row.child( render(), 'child' ).show();
  14785. $( row.node() ).addClass( 'parent' );
  14786. return true;
  14787. }
  14788. },
  14789. // This is a wrapper so the modal options for Bootstrap and jQuery UI can
  14790. // have options passed into them. This specific one doesn't need to be a
  14791. // function but it is for consistency in the `modal` name
  14792. modal: function ( options ) {
  14793. return function ( row, update, render ) {
  14794. if ( ! update ) {
  14795. // Show a modal
  14796. var close = function () {
  14797. modal.remove(); // will tidy events for us
  14798. $(document).off( 'keypress.dtr' );
  14799. };
  14800. var modal = $('<div class="dtr-modal"/>')
  14801. .append( $('<div class="dtr-modal-display"/>')
  14802. .append( $('<div class="dtr-modal-content"/>')
  14803. .append( render() )
  14804. )
  14805. .append( $('<div class="dtr-modal-close">&times;</div>' )
  14806. .click( function () {
  14807. close();
  14808. } )
  14809. )
  14810. )
  14811. .append( $('<div class="dtr-modal-background"/>')
  14812. .click( function () {
  14813. close();
  14814. } )
  14815. )
  14816. .appendTo( 'body' );
  14817. $(document).on( 'keyup.dtr', function (e) {
  14818. if ( e.keyCode === 27 ) {
  14819. e.stopPropagation();
  14820. close();
  14821. }
  14822. } );
  14823. }
  14824. else {
  14825. $('div.dtr-modal-content')
  14826. .empty()
  14827. .append( render() );
  14828. }
  14829. if ( options && options.header ) {
  14830. $('div.dtr-modal-content').prepend(
  14831. '<h2>'+options.header( row )+'</h2>'
  14832. );
  14833. }
  14834. };
  14835. }
  14836. };
  14837. /**
  14838. * Display methods - functions which define how the hidden data should be shown
  14839. * in the table.
  14840. *
  14841. * @namespace
  14842. * @name Responsive.defaults
  14843. * @static
  14844. */
  14845. Responsive.renderer = {
  14846. listHiddenNodes: function () {
  14847. return function ( api, rowIdx, columns ) {
  14848. var that = this;
  14849. var ul = $('<ul data-dtr-index="'+rowIdx+'" class="dtr-details"/>');
  14850. var found = false;
  14851. var data = $.each( columns, function ( i, col ) {
  14852. if ( col.hidden ) {
  14853. var klass = col.className ?
  14854. 'class="'+ col.className +'"' :
  14855. '';
  14856. $(
  14857. '<li '+klass+' data-dtr-index="'+col.columnIndex+'" data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
  14858. '<span class="dtr-title">'+
  14859. col.title+
  14860. '</span> '+
  14861. '</li>'
  14862. )
  14863. .append( $('<span class="dtr-data"/>').append( that._childNodes( api, col.rowIndex, col.columnIndex ) ) )// api.cell( col.rowIndex, col.columnIndex ).node().childNodes ) )
  14864. .appendTo( ul );
  14865. found = true;
  14866. }
  14867. } );
  14868. return found ?
  14869. ul :
  14870. false;
  14871. };
  14872. },
  14873. listHidden: function () {
  14874. return function ( api, rowIdx, columns ) {
  14875. var data = $.map( columns, function ( col ) {
  14876. var klass = col.className ?
  14877. 'class="'+ col.className +'"' :
  14878. '';
  14879. return col.hidden ?
  14880. '<li '+klass+' data-dtr-index="'+col.columnIndex+'" data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
  14881. '<span class="dtr-title">'+
  14882. col.title+
  14883. '</span> '+
  14884. '<span class="dtr-data">'+
  14885. col.data+
  14886. '</span>'+
  14887. '</li>' :
  14888. '';
  14889. } ).join('');
  14890. return data ?
  14891. $('<ul data-dtr-index="'+rowIdx+'" class="dtr-details"/>').append( data ) :
  14892. false;
  14893. }
  14894. },
  14895. tableAll: function ( options ) {
  14896. options = $.extend( {
  14897. tableClass: ''
  14898. }, options );
  14899. return function ( api, rowIdx, columns ) {
  14900. var data = $.map( columns, function ( col ) {
  14901. var klass = col.className ?
  14902. 'class="'+ col.className +'"' :
  14903. '';
  14904. return '<tr '+klass+' data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
  14905. '<td>'+col.title+':'+'</td> '+
  14906. '<td>'+col.data+'</td>'+
  14907. '</tr>';
  14908. } ).join('');
  14909. return $('<table class="'+options.tableClass+' dtr-details" width="100%"/>').append( data );
  14910. }
  14911. }
  14912. };
  14913. /**
  14914. * Responsive default settings for initialisation
  14915. *
  14916. * @namespace
  14917. * @name Responsive.defaults
  14918. * @static
  14919. */
  14920. Responsive.defaults = {
  14921. /**
  14922. * List of breakpoints for the instance. Note that this means that each
  14923. * instance can have its own breakpoints. Additionally, the breakpoints
  14924. * cannot be changed once an instance has been creased.
  14925. *
  14926. * @type {Array}
  14927. * @default Takes the value of `Responsive.breakpoints`
  14928. */
  14929. breakpoints: Responsive.breakpoints,
  14930. /**
  14931. * Enable / disable auto hiding calculations. It can help to increase
  14932. * performance slightly if you disable this option, but all columns would
  14933. * need to have breakpoint classes assigned to them
  14934. *
  14935. * @type {Boolean}
  14936. * @default `true`
  14937. */
  14938. auto: true,
  14939. /**
  14940. * Details control. If given as a string value, the `type` property of the
  14941. * default object is set to that value, and the defaults used for the rest
  14942. * of the object - this is for ease of implementation.
  14943. *
  14944. * The object consists of the following properties:
  14945. *
  14946. * * `display` - A function that is used to show and hide the hidden details
  14947. * * `renderer` - function that is called for display of the child row data.
  14948. * The default function will show the data from the hidden columns
  14949. * * `target` - Used as the selector for what objects to attach the child
  14950. * open / close to
  14951. * * `type` - `false` to disable the details display, `inline` or `column`
  14952. * for the two control types
  14953. *
  14954. * @type {Object|string}
  14955. */
  14956. details: {
  14957. display: Responsive.display.childRow,
  14958. renderer: Responsive.renderer.listHidden(),
  14959. target: 0,
  14960. type: 'inline'
  14961. },
  14962. /**
  14963. * Orthogonal data request option. This is used to define the data type
  14964. * requested when Responsive gets the data to show in the child row.
  14965. *
  14966. * @type {String}
  14967. */
  14968. orthogonal: 'display'
  14969. };
  14970. /*
  14971. * API
  14972. */
  14973. var Api = $.fn.dataTable.Api;
  14974. // Doesn't do anything - work around for a bug in DT... Not documented
  14975. Api.register( 'responsive()', function () {
  14976. return this;
  14977. } );
  14978. Api.register( 'responsive.index()', function ( li ) {
  14979. li = $(li);
  14980. return {
  14981. column: li.data('dtr-index'),
  14982. row: li.parent().data('dtr-index')
  14983. };
  14984. } );
  14985. Api.register( 'responsive.rebuild()', function () {
  14986. return this.iterator( 'table', function ( ctx ) {
  14987. if ( ctx._responsive ) {
  14988. ctx._responsive._classLogic();
  14989. }
  14990. } );
  14991. } );
  14992. Api.register( 'responsive.recalc()', function () {
  14993. return this.iterator( 'table', function ( ctx ) {
  14994. if ( ctx._responsive ) {
  14995. ctx._responsive._resizeAuto();
  14996. ctx._responsive._resize();
  14997. }
  14998. } );
  14999. } );
  15000. Api.register( 'responsive.hasHidden()', function () {
  15001. var ctx = this.context[0];
  15002. return ctx._responsive ?
  15003. $.inArray( false, ctx._responsive._responsiveOnlyHidden() ) !== -1 :
  15004. false;
  15005. } );
  15006. Api.registerPlural( 'columns().responsiveHidden()', 'column().responsiveHidden()', function () {
  15007. return this.iterator( 'column', function ( settings, column ) {
  15008. return settings._responsive ?
  15009. settings._responsive._responsiveOnlyHidden()[ column ] :
  15010. false;
  15011. }, 1 );
  15012. } );
  15013. /**
  15014. * Version information
  15015. *
  15016. * @name Responsive.version
  15017. * @static
  15018. */
  15019. Responsive.version = '2.4.0';
  15020. $.fn.dataTable.Responsive = Responsive;
  15021. $.fn.DataTable.Responsive = Responsive;
  15022. // Attach a listener to the document which listens for DataTables initialisation
  15023. // events so we can automatically initialise
  15024. $(document).on( 'preInit.dt.dtr', function (e, settings, json) {
  15025. if ( e.namespace !== 'dt' ) {
  15026. return;
  15027. }
  15028. if ( $(settings.nTable).hasClass( 'responsive' ) ||
  15029. $(settings.nTable).hasClass( 'dt-responsive' ) ||
  15030. settings.oInit.responsive ||
  15031. DataTable.defaults.responsive
  15032. ) {
  15033. var init = settings.oInit.responsive;
  15034. if ( init !== false ) {
  15035. new Responsive( settings, $.isPlainObject( init ) ? init : {} );
  15036. }
  15037. }
  15038. } );
  15039. return DataTable;
  15040. }));
  15041. /*! Bootstrap 5 integration for DataTables' Responsive
  15042. * © SpryMedia Ltd - datatables.net/license
  15043. */
  15044. (function( factory ){
  15045. if ( typeof define === 'function' && define.amd ) {
  15046. // AMD
  15047. define( ['jquery', 'datatables.net-bs5', 'datatables.net-responsive'], function ( $ ) {
  15048. return factory( $, window, document );
  15049. } );
  15050. }
  15051. else if ( typeof exports === 'object' ) {
  15052. // CommonJS
  15053. module.exports = function (root, $) {
  15054. if ( ! root ) {
  15055. // CommonJS environments without a window global must pass a
  15056. // root. This will give an error otherwise
  15057. root = window;
  15058. }
  15059. if ( ! $ ) {
  15060. $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
  15061. require('jquery') :
  15062. require('jquery')( root );
  15063. }
  15064. if ( ! $.fn.dataTable ) {
  15065. require('datatables.net-bs5')(root, $);
  15066. }
  15067. if ( ! $.fn.dataTable ) {
  15068. require('datatables.net-responsive')(root, $);
  15069. }
  15070. return factory( $, root, root.document );
  15071. };
  15072. }
  15073. else {
  15074. // Browser
  15075. factory( jQuery, window, document );
  15076. }
  15077. }(function( $, window, document, undefined ) {
  15078. 'use strict';
  15079. var DataTable = $.fn.dataTable;
  15080. var _display = DataTable.Responsive.display;
  15081. var _original = _display.modal;
  15082. var _modal = $(
  15083. '<div class="modal fade dtr-bs-modal" role="dialog">'+
  15084. '<div class="modal-dialog" role="document">'+
  15085. '<div class="modal-content">'+
  15086. '<div class="modal-header">'+
  15087. '<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>'+
  15088. '</div>'+
  15089. '<div class="modal-body"/>'+
  15090. '</div>'+
  15091. '</div>'+
  15092. '</div>'
  15093. );
  15094. var modal;
  15095. // Note this could be undefined at the time of initialisation - the
  15096. // DataTable.Responsive.bootstrap function can be used to set a different
  15097. // bootstrap object
  15098. var _bs = window.bootstrap;
  15099. DataTable.Responsive.bootstrap = function (bs) {
  15100. _bs = bs;
  15101. }
  15102. _display.modal = function ( options ) {
  15103. if (! modal) {
  15104. modal = new _bs.Modal(_modal[0]);
  15105. }
  15106. return function ( row, update, render ) {
  15107. if ( ! $.fn.modal ) {
  15108. _original( row, update, render );
  15109. }
  15110. else {
  15111. if ( ! update ) {
  15112. if ( options && options.header ) {
  15113. var header = _modal.find('div.modal-header');
  15114. var button = header.find('button').detach();
  15115. header
  15116. .empty()
  15117. .append( '<h4 class="modal-title">'+options.header( row )+'</h4>' )
  15118. .append( button );
  15119. }
  15120. _modal.find( 'div.modal-body' )
  15121. .empty()
  15122. .append( render() );
  15123. _modal
  15124. .appendTo( 'body' )
  15125. .modal();
  15126. modal.show();
  15127. }
  15128. }
  15129. };
  15130. };
  15131. return DataTable;
  15132. }));
  15133. /*! Select for DataTables 1.5.0
  15134. * 2015-2021 SpryMedia Ltd - datatables.net/license/mit
  15135. */
  15136. (function( factory ){
  15137. if ( typeof define === 'function' && define.amd ) {
  15138. // AMD
  15139. define( ['jquery', 'datatables.net'], function ( $ ) {
  15140. return factory( $, window, document );
  15141. } );
  15142. }
  15143. else if ( typeof exports === 'object' ) {
  15144. // CommonJS
  15145. module.exports = function (root, $) {
  15146. if ( ! root ) {
  15147. // CommonJS environments without a window global must pass a
  15148. // root. This will give an error otherwise
  15149. root = window;
  15150. }
  15151. if ( ! $ ) {
  15152. $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
  15153. require('jquery') :
  15154. require('jquery')( root );
  15155. }
  15156. if ( ! $.fn.dataTable ) {
  15157. require('datatables.net')(root, $);
  15158. }
  15159. return factory( $, root, root.document );
  15160. };
  15161. }
  15162. else {
  15163. // Browser
  15164. factory( jQuery, window, document );
  15165. }
  15166. }(function( $, window, document, undefined ) {
  15167. 'use strict';
  15168. var DataTable = $.fn.dataTable;
  15169. // Version information for debugger
  15170. DataTable.select = {};
  15171. DataTable.select.version = '1.5.0';
  15172. DataTable.select.init = function ( dt ) {
  15173. var ctx = dt.settings()[0];
  15174. if (ctx._select) {
  15175. return;
  15176. }
  15177. var savedSelected = dt.state.loaded();
  15178. var selectAndSave = function(e, settings, data) {
  15179. if(data === null || data.select === undefined) {
  15180. return;
  15181. }
  15182. // Clear any currently selected rows, before restoring state
  15183. // None will be selected on first initialisation
  15184. if (dt.rows({selected: true}).any()) {
  15185. dt.rows().deselect();
  15186. }
  15187. if (data.select.rows !== undefined) {
  15188. dt.rows(data.select.rows).select();
  15189. }
  15190. if (dt.columns({selected: true}).any()) {
  15191. dt.columns().deselect();
  15192. }
  15193. if (data.select.columns !== undefined) {
  15194. dt.columns(data.select.columns).select();
  15195. }
  15196. if (dt.cells({selected: true}).any()) {
  15197. dt.cells().deselect();
  15198. }
  15199. if (data.select.cells !== undefined) {
  15200. for(var i = 0; i < data.select.cells.length; i++) {
  15201. dt.cell(data.select.cells[i].row, data.select.cells[i].column).select();
  15202. }
  15203. }
  15204. dt.state.save();
  15205. }
  15206. dt.one('init', function() {
  15207. dt.on('stateSaveParams', function(e, settings, data) {
  15208. data.select = {};
  15209. data.select.rows = dt.rows({selected:true}).ids(true).toArray();
  15210. data.select.columns = dt.columns({selected:true})[0];
  15211. data.select.cells = dt.cells({selected:true})[0].map(function(coords) {
  15212. return {row: dt.row(coords.row).id(true), column: coords.column}
  15213. });
  15214. })
  15215. selectAndSave(undefined, undefined, savedSelected)
  15216. dt.on('stateLoaded stateLoadParams', selectAndSave)
  15217. })
  15218. var init = ctx.oInit.select;
  15219. var defaults = DataTable.defaults.select;
  15220. var opts = init === undefined ?
  15221. defaults :
  15222. init;
  15223. // Set defaults
  15224. var items = 'row';
  15225. var style = 'api';
  15226. var blurable = false;
  15227. var toggleable = true;
  15228. var info = true;
  15229. var selector = 'td, th';
  15230. var className = 'selected';
  15231. var setStyle = false;
  15232. ctx._select = {};
  15233. // Initialisation customisations
  15234. if ( opts === true ) {
  15235. style = 'os';
  15236. setStyle = true;
  15237. }
  15238. else if ( typeof opts === 'string' ) {
  15239. style = opts;
  15240. setStyle = true;
  15241. }
  15242. else if ( $.isPlainObject( opts ) ) {
  15243. if ( opts.blurable !== undefined ) {
  15244. blurable = opts.blurable;
  15245. }
  15246. if ( opts.toggleable !== undefined ) {
  15247. toggleable = opts.toggleable;
  15248. }
  15249. if ( opts.info !== undefined ) {
  15250. info = opts.info;
  15251. }
  15252. if ( opts.items !== undefined ) {
  15253. items = opts.items;
  15254. }
  15255. if ( opts.style !== undefined ) {
  15256. style = opts.style;
  15257. setStyle = true;
  15258. }
  15259. else {
  15260. style = 'os';
  15261. setStyle = true;
  15262. }
  15263. if ( opts.selector !== undefined ) {
  15264. selector = opts.selector;
  15265. }
  15266. if ( opts.className !== undefined ) {
  15267. className = opts.className;
  15268. }
  15269. }
  15270. dt.select.selector( selector );
  15271. dt.select.items( items );
  15272. dt.select.style( style );
  15273. dt.select.blurable( blurable );
  15274. dt.select.toggleable( toggleable );
  15275. dt.select.info( info );
  15276. ctx._select.className = className;
  15277. // Sort table based on selected rows. Requires Select Datatables extension
  15278. $.fn.dataTable.ext.order['select-checkbox'] = function ( settings, col ) {
  15279. return this.api().column( col, {order: 'index'} ).nodes().map( function ( td ) {
  15280. if ( settings._select.items === 'row' ) {
  15281. return $( td ).parent().hasClass( settings._select.className );
  15282. } else if ( settings._select.items === 'cell' ) {
  15283. return $( td ).hasClass( settings._select.className );
  15284. }
  15285. return false;
  15286. });
  15287. };
  15288. // If the init options haven't enabled select, but there is a selectable
  15289. // class name, then enable
  15290. if ( ! setStyle && $( dt.table().node() ).hasClass( 'selectable' ) ) {
  15291. dt.select.style( 'os' );
  15292. }
  15293. };
  15294. /*
  15295. Select is a collection of API methods, event handlers, event emitters and
  15296. buttons (for the `Buttons` extension) for DataTables. It provides the following
  15297. features, with an overview of how they are implemented:
  15298. ## Selection of rows, columns and cells. Whether an item is selected or not is
  15299. stored in:
  15300. * rows: a `_select_selected` property which contains a boolean value of the
  15301. DataTables' `aoData` object for each row
  15302. * columns: a `_select_selected` property which contains a boolean value of the
  15303. DataTables' `aoColumns` object for each column
  15304. * cells: a `_selected_cells` property which contains an array of boolean values
  15305. of the `aoData` object for each row. The array is the same length as the
  15306. columns array, with each element of it representing a cell.
  15307. This method of using boolean flags allows Select to operate when nodes have not
  15308. been created for rows / cells (DataTables' defer rendering feature).
  15309. ## API methods
  15310. A range of API methods are available for triggering selection and de-selection
  15311. of rows. Methods are also available to configure the selection events that can
  15312. be triggered by an end user (such as which items are to be selected). To a large
  15313. extent, these of API methods *is* Select. It is basically a collection of helper
  15314. functions that can be used to select items in a DataTable.
  15315. Configuration of select is held in the object `_select` which is attached to the
  15316. DataTables settings object on initialisation. Select being available on a table
  15317. is not optional when Select is loaded, but its default is for selection only to
  15318. be available via the API - so the end user wouldn't be able to select rows
  15319. without additional configuration.
  15320. The `_select` object contains the following properties:
  15321. ```
  15322. {
  15323. items:string - Can be `rows`, `columns` or `cells`. Defines what item
  15324. will be selected if the user is allowed to activate row
  15325. selection using the mouse.
  15326. style:string - Can be `none`, `single`, `multi` or `os`. Defines the
  15327. interaction style when selecting items
  15328. blurable:boolean - If row selection can be cleared by clicking outside of
  15329. the table
  15330. toggleable:boolean - If row selection can be cancelled by repeated clicking
  15331. on the row
  15332. info:boolean - If the selection summary should be shown in the table
  15333. information elements
  15334. }
  15335. ```
  15336. In addition to the API methods, Select also extends the DataTables selector
  15337. options for rows, columns and cells adding a `selected` option to the selector
  15338. options object, allowing the developer to select only selected items or
  15339. unselected items.
  15340. ## Mouse selection of items
  15341. Clicking on items can be used to select items. This is done by a simple event
  15342. handler that will select the items using the API methods.
  15343. */
  15344. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  15345. * Local functions
  15346. */
  15347. /**
  15348. * Add one or more cells to the selection when shift clicking in OS selection
  15349. * style cell selection.
  15350. *
  15351. * Cell range is more complicated than row and column as we want to select
  15352. * in the visible grid rather than by index in sequence. For example, if you
  15353. * click first in cell 1-1 and then shift click in 2-2 - cells 1-2 and 2-1
  15354. * should also be selected (and not 1-3, 1-4. etc)
  15355. *
  15356. * @param {DataTable.Api} dt DataTable
  15357. * @param {object} idx Cell index to select to
  15358. * @param {object} last Cell index to select from
  15359. * @private
  15360. */
  15361. function cellRange( dt, idx, last )
  15362. {
  15363. var indexes;
  15364. var columnIndexes;
  15365. var rowIndexes;
  15366. var selectColumns = function ( start, end ) {
  15367. if ( start > end ) {
  15368. var tmp = end;
  15369. end = start;
  15370. start = tmp;
  15371. }
  15372. var record = false;
  15373. return dt.columns( ':visible' ).indexes().filter( function (i) {
  15374. if ( i === start ) {
  15375. record = true;
  15376. }
  15377. if ( i === end ) { // not else if, as start might === end
  15378. record = false;
  15379. return true;
  15380. }
  15381. return record;
  15382. } );
  15383. };
  15384. var selectRows = function ( start, end ) {
  15385. var indexes = dt.rows( { search: 'applied' } ).indexes();
  15386. // Which comes first - might need to swap
  15387. if ( indexes.indexOf( start ) > indexes.indexOf( end ) ) {
  15388. var tmp = end;
  15389. end = start;
  15390. start = tmp;
  15391. }
  15392. var record = false;
  15393. return indexes.filter( function (i) {
  15394. if ( i === start ) {
  15395. record = true;
  15396. }
  15397. if ( i === end ) {
  15398. record = false;
  15399. return true;
  15400. }
  15401. return record;
  15402. } );
  15403. };
  15404. if ( ! dt.cells( { selected: true } ).any() && ! last ) {
  15405. // select from the top left cell to this one
  15406. columnIndexes = selectColumns( 0, idx.column );
  15407. rowIndexes = selectRows( 0 , idx.row );
  15408. }
  15409. else {
  15410. // Get column indexes between old and new
  15411. columnIndexes = selectColumns( last.column, idx.column );
  15412. rowIndexes = selectRows( last.row , idx.row );
  15413. }
  15414. indexes = dt.cells( rowIndexes, columnIndexes ).flatten();
  15415. if ( ! dt.cells( idx, { selected: true } ).any() ) {
  15416. // Select range
  15417. dt.cells( indexes ).select();
  15418. }
  15419. else {
  15420. // Deselect range
  15421. dt.cells( indexes ).deselect();
  15422. }
  15423. }
  15424. /**
  15425. * Disable mouse selection by removing the selectors
  15426. *
  15427. * @param {DataTable.Api} dt DataTable to remove events from
  15428. * @private
  15429. */
  15430. function disableMouseSelection( dt )
  15431. {
  15432. var ctx = dt.settings()[0];
  15433. var selector = ctx._select.selector;
  15434. $( dt.table().container() )
  15435. .off( 'mousedown.dtSelect', selector )
  15436. .off( 'mouseup.dtSelect', selector )
  15437. .off( 'click.dtSelect', selector );
  15438. $('body').off( 'click.dtSelect' + _safeId(dt.table().node()) );
  15439. }
  15440. /**
  15441. * Attach mouse listeners to the table to allow mouse selection of items
  15442. *
  15443. * @param {DataTable.Api} dt DataTable to remove events from
  15444. * @private
  15445. */
  15446. function enableMouseSelection ( dt )
  15447. {
  15448. var container = $( dt.table().container() );
  15449. var ctx = dt.settings()[0];
  15450. var selector = ctx._select.selector;
  15451. var matchSelection;
  15452. container
  15453. .on( 'mousedown.dtSelect', selector, function(e) {
  15454. // Disallow text selection for shift clicking on the table so multi
  15455. // element selection doesn't look terrible!
  15456. if ( e.shiftKey || e.metaKey || e.ctrlKey ) {
  15457. container
  15458. .css( '-moz-user-select', 'none' )
  15459. .one('selectstart.dtSelect', selector, function () {
  15460. return false;
  15461. } );
  15462. }
  15463. if ( window.getSelection ) {
  15464. matchSelection = window.getSelection();
  15465. }
  15466. } )
  15467. .on( 'mouseup.dtSelect', selector, function() {
  15468. // Allow text selection to occur again, Mozilla style (tested in FF
  15469. // 35.0.1 - still required)
  15470. container.css( '-moz-user-select', '' );
  15471. } )
  15472. .on( 'click.dtSelect', selector, function ( e ) {
  15473. var items = dt.select.items();
  15474. var idx;
  15475. // If text was selected (click and drag), then we shouldn't change
  15476. // the row's selected state
  15477. if ( matchSelection ) {
  15478. var selection = window.getSelection();
  15479. // If the element that contains the selection is not in the table, we can ignore it
  15480. // This can happen if the developer selects text from the click event
  15481. if ( ! selection.anchorNode || $(selection.anchorNode).closest('table')[0] === dt.table().node() ) {
  15482. if ( selection !== matchSelection ) {
  15483. return;
  15484. }
  15485. }
  15486. }
  15487. var ctx = dt.settings()[0];
  15488. var wrapperClass = dt.settings()[0].oClasses.sWrapper.trim().replace(/ +/g, '.');
  15489. // Ignore clicks inside a sub-table
  15490. if ( $(e.target).closest('div.'+wrapperClass)[0] != dt.table().container() ) {
  15491. return;
  15492. }
  15493. var cell = dt.cell( $(e.target).closest('td, th') );
  15494. // Check the cell actually belongs to the host DataTable (so child
  15495. // rows, etc, are ignored)
  15496. if ( ! cell.any() ) {
  15497. return;
  15498. }
  15499. var event = $.Event('user-select.dt');
  15500. eventTrigger( dt, event, [ items, cell, e ] );
  15501. if ( event.isDefaultPrevented() ) {
  15502. return;
  15503. }
  15504. var cellIndex = cell.index();
  15505. if ( items === 'row' ) {
  15506. idx = cellIndex.row;
  15507. typeSelect( e, dt, ctx, 'row', idx );
  15508. }
  15509. else if ( items === 'column' ) {
  15510. idx = cell.index().column;
  15511. typeSelect( e, dt, ctx, 'column', idx );
  15512. }
  15513. else if ( items === 'cell' ) {
  15514. idx = cell.index();
  15515. typeSelect( e, dt, ctx, 'cell', idx );
  15516. }
  15517. ctx._select_lastCell = cellIndex;
  15518. } );
  15519. // Blurable
  15520. $('body').on( 'click.dtSelect' + _safeId(dt.table().node()), function ( e ) {
  15521. if ( ctx._select.blurable ) {
  15522. // If the click was inside the DataTables container, don't blur
  15523. if ( $(e.target).parents().filter( dt.table().container() ).length ) {
  15524. return;
  15525. }
  15526. // Ignore elements which have been removed from the DOM (i.e. paging
  15527. // buttons)
  15528. if ( $(e.target).parents('html').length === 0 ) {
  15529. return;
  15530. }
  15531. // Don't blur in Editor form
  15532. if ( $(e.target).parents('div.DTE').length ) {
  15533. return;
  15534. }
  15535. var event = $.Event('select-blur.dt');
  15536. eventTrigger( dt, event, [ e.target, e ] );
  15537. if ( event.isDefaultPrevented() ) {
  15538. return;
  15539. }
  15540. clear( ctx, true );
  15541. }
  15542. } );
  15543. }
  15544. /**
  15545. * Trigger an event on a DataTable
  15546. *
  15547. * @param {DataTable.Api} api DataTable to trigger events on
  15548. * @param {boolean} selected true if selected, false if deselected
  15549. * @param {string} type Item type acting on
  15550. * @param {boolean} any Require that there are values before
  15551. * triggering
  15552. * @private
  15553. */
  15554. function eventTrigger ( api, type, args, any )
  15555. {
  15556. if ( any && ! api.flatten().length ) {
  15557. return;
  15558. }
  15559. if ( typeof type === 'string' ) {
  15560. type = type +'.dt';
  15561. }
  15562. args.unshift( api );
  15563. $(api.table().node()).trigger( type, args );
  15564. }
  15565. /**
  15566. * Update the information element of the DataTable showing information about the
  15567. * items selected. This is done by adding tags to the existing text
  15568. *
  15569. * @param {DataTable.Api} api DataTable to update
  15570. * @private
  15571. */
  15572. function info ( api )
  15573. {
  15574. var ctx = api.settings()[0];
  15575. if ( ! ctx._select.info || ! ctx.aanFeatures.i ) {
  15576. return;
  15577. }
  15578. if ( api.select.style() === 'api' ) {
  15579. return;
  15580. }
  15581. var rows = api.rows( { selected: true } ).flatten().length;
  15582. var columns = api.columns( { selected: true } ).flatten().length;
  15583. var cells = api.cells( { selected: true } ).flatten().length;
  15584. var add = function ( el, name, num ) {
  15585. el.append( $('<span class="select-item"/>').append( api.i18n(
  15586. 'select.'+name+'s',
  15587. { _: '%d '+name+'s selected', 0: '', 1: '1 '+name+' selected' },
  15588. num
  15589. ) ) );
  15590. };
  15591. // Internal knowledge of DataTables to loop over all information elements
  15592. $.each( ctx.aanFeatures.i, function ( i, el ) {
  15593. el = $(el);
  15594. var output = $('<span class="select-info"/>');
  15595. add( output, 'row', rows );
  15596. add( output, 'column', columns );
  15597. add( output, 'cell', cells );
  15598. var exisiting = el.children('span.select-info');
  15599. if ( exisiting.length ) {
  15600. exisiting.remove();
  15601. }
  15602. if ( output.text() !== '' ) {
  15603. el.append( output );
  15604. }
  15605. } );
  15606. }
  15607. /**
  15608. * Initialisation of a new table. Attach event handlers and callbacks to allow
  15609. * Select to operate correctly.
  15610. *
  15611. * This will occur _after_ the initial DataTables initialisation, although
  15612. * before Ajax data is rendered, if there is ajax data
  15613. *
  15614. * @param {DataTable.settings} ctx Settings object to operate on
  15615. * @private
  15616. */
  15617. function init ( ctx ) {
  15618. var api = new DataTable.Api( ctx );
  15619. ctx._select_init = true;
  15620. // Row callback so that classes can be added to rows and cells if the item
  15621. // was selected before the element was created. This will happen with the
  15622. // `deferRender` option enabled.
  15623. //
  15624. // This method of attaching to `aoRowCreatedCallback` is a hack until
  15625. // DataTables has proper events for row manipulation If you are reviewing
  15626. // this code to create your own plug-ins, please do not do this!
  15627. ctx.aoRowCreatedCallback.push( {
  15628. fn: function ( row, data, index ) {
  15629. var i, ien;
  15630. var d = ctx.aoData[ index ];
  15631. // Row
  15632. if ( d._select_selected ) {
  15633. $( row ).addClass( ctx._select.className );
  15634. }
  15635. // Cells and columns - if separated out, we would need to do two
  15636. // loops, so it makes sense to combine them into a single one
  15637. for ( i=0, ien=ctx.aoColumns.length ; i<ien ; i++ ) {
  15638. if ( ctx.aoColumns[i]._select_selected || (d._selected_cells && d._selected_cells[i]) ) {
  15639. $(d.anCells[i]).addClass( ctx._select.className );
  15640. }
  15641. }
  15642. },
  15643. sName: 'select-deferRender'
  15644. } );
  15645. // On Ajax reload we want to reselect all rows which are currently selected,
  15646. // if there is an rowId (i.e. a unique value to identify each row with)
  15647. api.on( 'preXhr.dt.dtSelect', function (e, settings) {
  15648. if (settings !== api.settings()[0]) {
  15649. // Not triggered by our DataTable!
  15650. return;
  15651. }
  15652. // note that column selection doesn't need to be cached and then
  15653. // reselected, as they are already selected
  15654. var rows = api.rows( { selected: true } ).ids( true ).filter( function ( d ) {
  15655. return d !== undefined;
  15656. } );
  15657. var cells = api.cells( { selected: true } ).eq(0).map( function ( cellIdx ) {
  15658. var id = api.row( cellIdx.row ).id( true );
  15659. return id ?
  15660. { row: id, column: cellIdx.column } :
  15661. undefined;
  15662. } ).filter( function ( d ) {
  15663. return d !== undefined;
  15664. } );
  15665. // On the next draw, reselect the currently selected items
  15666. api.one( 'draw.dt.dtSelect', function () {
  15667. api.rows( rows ).select();
  15668. // `cells` is not a cell index selector, so it needs a loop
  15669. if ( cells.any() ) {
  15670. cells.each( function ( id ) {
  15671. api.cells( id.row, id.column ).select();
  15672. } );
  15673. }
  15674. } );
  15675. } );
  15676. // Update the table information element with selected item summary
  15677. api.on( 'draw.dtSelect.dt select.dtSelect.dt deselect.dtSelect.dt info.dt', function () {
  15678. info( api );
  15679. api.state.save();
  15680. } );
  15681. // Clean up and release
  15682. api.on( 'destroy.dtSelect', function () {
  15683. api.rows({selected: true}).deselect();
  15684. disableMouseSelection( api );
  15685. api.off( '.dtSelect' );
  15686. $('body').off('.dtSelect' + _safeId(api.table().node()));
  15687. } );
  15688. }
  15689. /**
  15690. * Add one or more items (rows or columns) to the selection when shift clicking
  15691. * in OS selection style
  15692. *
  15693. * @param {DataTable.Api} dt DataTable
  15694. * @param {string} type Row or column range selector
  15695. * @param {object} idx Item index to select to
  15696. * @param {object} last Item index to select from
  15697. * @private
  15698. */
  15699. function rowColumnRange( dt, type, idx, last )
  15700. {
  15701. // Add a range of rows from the last selected row to this one
  15702. var indexes = dt[type+'s']( { search: 'applied' } ).indexes();
  15703. var idx1 = $.inArray( last, indexes );
  15704. var idx2 = $.inArray( idx, indexes );
  15705. if ( ! dt[type+'s']( { selected: true } ).any() && idx1 === -1 ) {
  15706. // select from top to here - slightly odd, but both Windows and Mac OS
  15707. // do this
  15708. indexes.splice( $.inArray( idx, indexes )+1, indexes.length );
  15709. }
  15710. else {
  15711. // reverse so we can shift click 'up' as well as down
  15712. if ( idx1 > idx2 ) {
  15713. var tmp = idx2;
  15714. idx2 = idx1;
  15715. idx1 = tmp;
  15716. }
  15717. indexes.splice( idx2+1, indexes.length );
  15718. indexes.splice( 0, idx1 );
  15719. }
  15720. if ( ! dt[type]( idx, { selected: true } ).any() ) {
  15721. // Select range
  15722. dt[type+'s']( indexes ).select();
  15723. }
  15724. else {
  15725. // Deselect range - need to keep the clicked on row selected
  15726. indexes.splice( $.inArray( idx, indexes ), 1 );
  15727. dt[type+'s']( indexes ).deselect();
  15728. }
  15729. }
  15730. /**
  15731. * Clear all selected items
  15732. *
  15733. * @param {DataTable.settings} ctx Settings object of the host DataTable
  15734. * @param {boolean} [force=false] Force the de-selection to happen, regardless
  15735. * of selection style
  15736. * @private
  15737. */
  15738. function clear( ctx, force )
  15739. {
  15740. if ( force || ctx._select.style === 'single' ) {
  15741. var api = new DataTable.Api( ctx );
  15742. api.rows( { selected: true } ).deselect();
  15743. api.columns( { selected: true } ).deselect();
  15744. api.cells( { selected: true } ).deselect();
  15745. }
  15746. }
  15747. /**
  15748. * Select items based on the current configuration for style and items.
  15749. *
  15750. * @param {object} e Mouse event object
  15751. * @param {DataTables.Api} dt DataTable
  15752. * @param {DataTable.settings} ctx Settings object of the host DataTable
  15753. * @param {string} type Items to select
  15754. * @param {int|object} idx Index of the item to select
  15755. * @private
  15756. */
  15757. function typeSelect ( e, dt, ctx, type, idx )
  15758. {
  15759. var style = dt.select.style();
  15760. var toggleable = dt.select.toggleable();
  15761. var isSelected = dt[type]( idx, { selected: true } ).any();
  15762. if ( isSelected && ! toggleable ) {
  15763. return;
  15764. }
  15765. if ( style === 'os' ) {
  15766. if ( e.ctrlKey || e.metaKey ) {
  15767. // Add or remove from the selection
  15768. dt[type]( idx ).select( ! isSelected );
  15769. }
  15770. else if ( e.shiftKey ) {
  15771. if ( type === 'cell' ) {
  15772. cellRange( dt, idx, ctx._select_lastCell || null );
  15773. }
  15774. else {
  15775. rowColumnRange( dt, type, idx, ctx._select_lastCell ?
  15776. ctx._select_lastCell[type] :
  15777. null
  15778. );
  15779. }
  15780. }
  15781. else {
  15782. // No cmd or shift click - deselect if selected, or select
  15783. // this row only
  15784. var selected = dt[type+'s']( { selected: true } );
  15785. if ( isSelected && selected.flatten().length === 1 ) {
  15786. dt[type]( idx ).deselect();
  15787. }
  15788. else {
  15789. selected.deselect();
  15790. dt[type]( idx ).select();
  15791. }
  15792. }
  15793. } else if ( style == 'multi+shift' ) {
  15794. if ( e.shiftKey ) {
  15795. if ( type === 'cell' ) {
  15796. cellRange( dt, idx, ctx._select_lastCell || null );
  15797. }
  15798. else {
  15799. rowColumnRange( dt, type, idx, ctx._select_lastCell ?
  15800. ctx._select_lastCell[type] :
  15801. null
  15802. );
  15803. }
  15804. }
  15805. else {
  15806. dt[ type ]( idx ).select( ! isSelected );
  15807. }
  15808. }
  15809. else {
  15810. dt[ type ]( idx ).select( ! isSelected );
  15811. }
  15812. }
  15813. function _safeId( node ) {
  15814. return node.id.replace(/[^a-zA-Z0-9\-\_]/g, '-');
  15815. }
  15816. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  15817. * DataTables selectors
  15818. */
  15819. // row and column are basically identical just assigned to different properties
  15820. // and checking a different array, so we can dynamically create the functions to
  15821. // reduce the code size
  15822. $.each( [
  15823. { type: 'row', prop: 'aoData' },
  15824. { type: 'column', prop: 'aoColumns' }
  15825. ], function ( i, o ) {
  15826. DataTable.ext.selector[ o.type ].push( function ( settings, opts, indexes ) {
  15827. var selected = opts.selected;
  15828. var data;
  15829. var out = [];
  15830. if ( selected !== true && selected !== false ) {
  15831. return indexes;
  15832. }
  15833. for ( var i=0, ien=indexes.length ; i<ien ; i++ ) {
  15834. data = settings[ o.prop ][ indexes[i] ];
  15835. if ( (selected === true && data._select_selected === true) ||
  15836. (selected === false && ! data._select_selected )
  15837. ) {
  15838. out.push( indexes[i] );
  15839. }
  15840. }
  15841. return out;
  15842. } );
  15843. } );
  15844. DataTable.ext.selector.cell.push( function ( settings, opts, cells ) {
  15845. var selected = opts.selected;
  15846. var rowData;
  15847. var out = [];
  15848. if ( selected === undefined ) {
  15849. return cells;
  15850. }
  15851. for ( var i=0, ien=cells.length ; i<ien ; i++ ) {
  15852. rowData = settings.aoData[ cells[i].row ];
  15853. if ( (selected === true && rowData._selected_cells && rowData._selected_cells[ cells[i].column ] === true) ||
  15854. (selected === false && ( ! rowData._selected_cells || ! rowData._selected_cells[ cells[i].column ] ) )
  15855. ) {
  15856. out.push( cells[i] );
  15857. }
  15858. }
  15859. return out;
  15860. } );
  15861. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  15862. * DataTables API
  15863. *
  15864. * For complete documentation, please refer to the docs/api directory or the
  15865. * DataTables site
  15866. */
  15867. // Local variables to improve compression
  15868. var apiRegister = DataTable.Api.register;
  15869. var apiRegisterPlural = DataTable.Api.registerPlural;
  15870. apiRegister( 'select()', function () {
  15871. return this.iterator( 'table', function ( ctx ) {
  15872. DataTable.select.init( new DataTable.Api( ctx ) );
  15873. } );
  15874. } );
  15875. apiRegister( 'select.blurable()', function ( flag ) {
  15876. if ( flag === undefined ) {
  15877. return this.context[0]._select.blurable;
  15878. }
  15879. return this.iterator( 'table', function ( ctx ) {
  15880. ctx._select.blurable = flag;
  15881. } );
  15882. } );
  15883. apiRegister( 'select.toggleable()', function ( flag ) {
  15884. if ( flag === undefined ) {
  15885. return this.context[0]._select.toggleable;
  15886. }
  15887. return this.iterator( 'table', function ( ctx ) {
  15888. ctx._select.toggleable = flag;
  15889. } );
  15890. } );
  15891. apiRegister( 'select.info()', function ( flag ) {
  15892. if ( flag === undefined ) {
  15893. return this.context[0]._select.info;
  15894. }
  15895. return this.iterator( 'table', function ( ctx ) {
  15896. ctx._select.info = flag;
  15897. } );
  15898. } );
  15899. apiRegister( 'select.items()', function ( items ) {
  15900. if ( items === undefined ) {
  15901. return this.context[0]._select.items;
  15902. }
  15903. return this.iterator( 'table', function ( ctx ) {
  15904. ctx._select.items = items;
  15905. eventTrigger( new DataTable.Api( ctx ), 'selectItems', [ items ] );
  15906. } );
  15907. } );
  15908. // Takes effect from the _next_ selection. None disables future selection, but
  15909. // does not clear the current selection. Use the `deselect` methods for that
  15910. apiRegister( 'select.style()', function ( style ) {
  15911. if ( style === undefined ) {
  15912. return this.context[0]._select.style;
  15913. }
  15914. return this.iterator( 'table', function ( ctx ) {
  15915. if ( ! ctx._select ) {
  15916. DataTable.select.init( new DataTable.Api(ctx) );
  15917. }
  15918. if ( ! ctx._select_init ) {
  15919. init(ctx);
  15920. }
  15921. ctx._select.style = style;
  15922. // Add / remove mouse event handlers. They aren't required when only
  15923. // API selection is available
  15924. var dt = new DataTable.Api( ctx );
  15925. disableMouseSelection( dt );
  15926. if ( style !== 'api' ) {
  15927. enableMouseSelection( dt );
  15928. }
  15929. eventTrigger( new DataTable.Api( ctx ), 'selectStyle', [ style ] );
  15930. } );
  15931. } );
  15932. apiRegister( 'select.selector()', function ( selector ) {
  15933. if ( selector === undefined ) {
  15934. return this.context[0]._select.selector;
  15935. }
  15936. return this.iterator( 'table', function ( ctx ) {
  15937. disableMouseSelection( new DataTable.Api( ctx ) );
  15938. ctx._select.selector = selector;
  15939. if ( ctx._select.style !== 'api' ) {
  15940. enableMouseSelection( new DataTable.Api( ctx ) );
  15941. }
  15942. } );
  15943. } );
  15944. apiRegisterPlural( 'rows().select()', 'row().select()', function ( select ) {
  15945. var api = this;
  15946. if ( select === false ) {
  15947. return this.deselect();
  15948. }
  15949. this.iterator( 'row', function ( ctx, idx ) {
  15950. clear( ctx );
  15951. ctx.aoData[ idx ]._select_selected = true;
  15952. $( ctx.aoData[ idx ].nTr ).addClass( ctx._select.className );
  15953. } );
  15954. this.iterator( 'table', function ( ctx, i ) {
  15955. eventTrigger( api, 'select', [ 'row', api[i] ], true );
  15956. } );
  15957. return this;
  15958. } );
  15959. apiRegister( 'row().selected()', function () {
  15960. var ctx = this.context[0];
  15961. if (
  15962. ctx &&
  15963. this.length &&
  15964. ctx.aoData[this[0]] &&
  15965. ctx.aoData[this[0]]._select_selected
  15966. ) {
  15967. return true;
  15968. }
  15969. return false;
  15970. } );
  15971. apiRegisterPlural( 'columns().select()', 'column().select()', function ( select ) {
  15972. var api = this;
  15973. if ( select === false ) {
  15974. return this.deselect();
  15975. }
  15976. this.iterator( 'column', function ( ctx, idx ) {
  15977. clear( ctx );
  15978. ctx.aoColumns[ idx ]._select_selected = true;
  15979. var column = new DataTable.Api( ctx ).column( idx );
  15980. $( column.header() ).addClass( ctx._select.className );
  15981. $( column.footer() ).addClass( ctx._select.className );
  15982. column.nodes().to$().addClass( ctx._select.className );
  15983. } );
  15984. this.iterator( 'table', function ( ctx, i ) {
  15985. eventTrigger( api, 'select', [ 'column', api[i] ], true );
  15986. } );
  15987. return this;
  15988. } );
  15989. apiRegister( 'column().selected()', function () {
  15990. var ctx = this.context[0];
  15991. if (
  15992. ctx &&
  15993. this.length &&
  15994. ctx.aoColumns[this[0]] &&
  15995. ctx.aoColumns[this[0]]._select_selected
  15996. ) {
  15997. return true;
  15998. }
  15999. return false;
  16000. } );
  16001. apiRegisterPlural( 'cells().select()', 'cell().select()', function ( select ) {
  16002. var api = this;
  16003. if ( select === false ) {
  16004. return this.deselect();
  16005. }
  16006. this.iterator( 'cell', function ( ctx, rowIdx, colIdx ) {
  16007. clear( ctx );
  16008. var data = ctx.aoData[ rowIdx ];
  16009. if ( data._selected_cells === undefined ) {
  16010. data._selected_cells = [];
  16011. }
  16012. data._selected_cells[ colIdx ] = true;
  16013. if ( data.anCells ) {
  16014. $( data.anCells[ colIdx ] ).addClass( ctx._select.className );
  16015. }
  16016. } );
  16017. this.iterator( 'table', function ( ctx, i ) {
  16018. eventTrigger( api, 'select', [ 'cell', api.cells(api[i]).indexes().toArray() ], true );
  16019. } );
  16020. return this;
  16021. } );
  16022. apiRegister( 'cell().selected()', function () {
  16023. var ctx = this.context[0];
  16024. if (ctx && this.length) {
  16025. var row = ctx.aoData[this[0][0].row];
  16026. if (row && row._selected_cells && row._selected_cells[this[0][0].column]) {
  16027. return true;
  16028. }
  16029. }
  16030. return false;
  16031. } );
  16032. apiRegisterPlural( 'rows().deselect()', 'row().deselect()', function () {
  16033. var api = this;
  16034. this.iterator( 'row', function ( ctx, idx ) {
  16035. ctx.aoData[ idx ]._select_selected = false;
  16036. ctx._select_lastCell = null;
  16037. $( ctx.aoData[ idx ].nTr ).removeClass( ctx._select.className );
  16038. } );
  16039. this.iterator( 'table', function ( ctx, i ) {
  16040. eventTrigger( api, 'deselect', [ 'row', api[i] ], true );
  16041. } );
  16042. return this;
  16043. } );
  16044. apiRegisterPlural( 'columns().deselect()', 'column().deselect()', function () {
  16045. var api = this;
  16046. this.iterator( 'column', function ( ctx, idx ) {
  16047. ctx.aoColumns[ idx ]._select_selected = false;
  16048. var api = new DataTable.Api( ctx );
  16049. var column = api.column( idx );
  16050. $( column.header() ).removeClass( ctx._select.className );
  16051. $( column.footer() ).removeClass( ctx._select.className );
  16052. // Need to loop over each cell, rather than just using
  16053. // `column().nodes()` as cells which are individually selected should
  16054. // not have the `selected` class removed from them
  16055. api.cells( null, idx ).indexes().each( function (cellIdx) {
  16056. var data = ctx.aoData[ cellIdx.row ];
  16057. var cellSelected = data._selected_cells;
  16058. if ( data.anCells && (! cellSelected || ! cellSelected[ cellIdx.column ]) ) {
  16059. $( data.anCells[ cellIdx.column ] ).removeClass( ctx._select.className );
  16060. }
  16061. } );
  16062. } );
  16063. this.iterator( 'table', function ( ctx, i ) {
  16064. eventTrigger( api, 'deselect', [ 'column', api[i] ], true );
  16065. } );
  16066. return this;
  16067. } );
  16068. apiRegisterPlural( 'cells().deselect()', 'cell().deselect()', function () {
  16069. var api = this;
  16070. this.iterator( 'cell', function ( ctx, rowIdx, colIdx ) {
  16071. var data = ctx.aoData[ rowIdx ];
  16072. if(data._selected_cells !== undefined) {
  16073. data._selected_cells[ colIdx ] = false;
  16074. }
  16075. // Remove class only if the cells exist, and the cell is not column
  16076. // selected, in which case the class should remain (since it is selected
  16077. // in the column)
  16078. if ( data.anCells && ! ctx.aoColumns[ colIdx ]._select_selected ) {
  16079. $( data.anCells[ colIdx ] ).removeClass( ctx._select.className );
  16080. }
  16081. } );
  16082. this.iterator( 'table', function ( ctx, i ) {
  16083. eventTrigger( api, 'deselect', [ 'cell', api[i] ], true );
  16084. } );
  16085. return this;
  16086. } );
  16087. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  16088. * Buttons
  16089. */
  16090. function i18n( label, def ) {
  16091. return function (dt) {
  16092. return dt.i18n( 'buttons.'+label, def );
  16093. };
  16094. }
  16095. // Common events with suitable namespaces
  16096. function namespacedEvents ( config ) {
  16097. var unique = config._eventNamespace;
  16098. return 'draw.dt.DT'+unique+' select.dt.DT'+unique+' deselect.dt.DT'+unique;
  16099. }
  16100. function enabled ( dt, config ) {
  16101. if ( $.inArray( 'rows', config.limitTo ) !== -1 && dt.rows( { selected: true } ).any() ) {
  16102. return true;
  16103. }
  16104. if ( $.inArray( 'columns', config.limitTo ) !== -1 && dt.columns( { selected: true } ).any() ) {
  16105. return true;
  16106. }
  16107. if ( $.inArray( 'cells', config.limitTo ) !== -1 && dt.cells( { selected: true } ).any() ) {
  16108. return true;
  16109. }
  16110. return false;
  16111. }
  16112. var _buttonNamespace = 0;
  16113. $.extend( DataTable.ext.buttons, {
  16114. selected: {
  16115. text: i18n( 'selected', 'Selected' ),
  16116. className: 'buttons-selected',
  16117. limitTo: [ 'rows', 'columns', 'cells' ],
  16118. init: function ( dt, node, config ) {
  16119. var that = this;
  16120. config._eventNamespace = '.select'+(_buttonNamespace++);
  16121. // .DT namespace listeners are removed by DataTables automatically
  16122. // on table destroy
  16123. dt.on( namespacedEvents(config), function () {
  16124. that.enable( enabled(dt, config) );
  16125. } );
  16126. this.disable();
  16127. },
  16128. destroy: function ( dt, node, config ) {
  16129. dt.off( config._eventNamespace );
  16130. }
  16131. },
  16132. selectedSingle: {
  16133. text: i18n( 'selectedSingle', 'Selected single' ),
  16134. className: 'buttons-selected-single',
  16135. init: function ( dt, node, config ) {
  16136. var that = this;
  16137. config._eventNamespace = '.select'+(_buttonNamespace++);
  16138. dt.on( namespacedEvents(config), function () {
  16139. var count = dt.rows( { selected: true } ).flatten().length +
  16140. dt.columns( { selected: true } ).flatten().length +
  16141. dt.cells( { selected: true } ).flatten().length;
  16142. that.enable( count === 1 );
  16143. } );
  16144. this.disable();
  16145. },
  16146. destroy: function ( dt, node, config ) {
  16147. dt.off( config._eventNamespace );
  16148. }
  16149. },
  16150. selectAll: {
  16151. text: i18n( 'selectAll', 'Select all' ),
  16152. className: 'buttons-select-all',
  16153. action: function () {
  16154. var items = this.select.items();
  16155. this[ items+'s' ]().select();
  16156. }
  16157. },
  16158. selectNone: {
  16159. text: i18n( 'selectNone', 'Deselect all' ),
  16160. className: 'buttons-select-none',
  16161. action: function () {
  16162. clear( this.settings()[0], true );
  16163. },
  16164. init: function ( dt, node, config ) {
  16165. var that = this;
  16166. config._eventNamespace = '.select'+(_buttonNamespace++);
  16167. dt.on( namespacedEvents(config), function () {
  16168. var count = dt.rows( { selected: true } ).flatten().length +
  16169. dt.columns( { selected: true } ).flatten().length +
  16170. dt.cells( { selected: true } ).flatten().length;
  16171. that.enable( count > 0 );
  16172. } );
  16173. this.disable();
  16174. },
  16175. destroy: function ( dt, node, config ) {
  16176. dt.off( config._eventNamespace );
  16177. }
  16178. }
  16179. } );
  16180. $.each( [ 'Row', 'Column', 'Cell' ], function ( i, item ) {
  16181. var lc = item.toLowerCase();
  16182. DataTable.ext.buttons[ 'select'+item+'s' ] = {
  16183. text: i18n( 'select'+item+'s', 'Select '+lc+'s' ),
  16184. className: 'buttons-select-'+lc+'s',
  16185. action: function () {
  16186. this.select.items( lc );
  16187. },
  16188. init: function ( dt ) {
  16189. var that = this;
  16190. dt.on( 'selectItems.dt.DT', function ( e, ctx, items ) {
  16191. that.active( items === lc );
  16192. } );
  16193. }
  16194. };
  16195. } );
  16196. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  16197. * Initialisation
  16198. */
  16199. // DataTables creation - check if select has been defined in the options. Note
  16200. // this required that the table be in the document! If it isn't then something
  16201. // needs to trigger this method unfortunately. The next major release of
  16202. // DataTables will rework the events and address this.
  16203. $(document).on( 'preInit.dt.dtSelect', function (e, ctx) {
  16204. if ( e.namespace !== 'dt' ) {
  16205. return;
  16206. }
  16207. DataTable.select.init( new DataTable.Api( ctx ) );
  16208. } );
  16209. return DataTable;
  16210. }));