jquery.dataTables.js 369 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099
  1. /**
  2. * @summary DataTables
  3. * @description Paginate, search and sort HTML tables
  4. * @version 1.9.4
  5. * @file jquery.dataTables.js
  6. * @author Allan Jardine (www.sprymedia.co.uk)
  7. * @contact www.sprymedia.co.uk/contact
  8. *
  9. * @copyright Copyright 2008-2012 Allan Jardine, all rights reserved.
  10. *
  11. * This source file is free software, under either the GPL v2 license or a
  12. * BSD style license, available at:
  13. * http://datatables.net/license_gpl2
  14. * http://datatables.net/license_bsd
  15. *
  16. * This source file is distributed in the hope that it will be useful, but
  17. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  18. * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  19. *
  20. * For details please refer to: http://www.datatables.net
  21. */
  22. /*jslint evil: true, undef: true, browser: true */
  23. /*globals $, jQuery,define,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageCompat,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnApplyColumnDefs,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnJsonString,_fnRender,_fnNodeToColumnIndex,_fnInfoMacros,_fnBrowserDetect,_fnGetColumns*/
  24. (/** @lends <global> */function( window, document, undefined ) {
  25. (function( factory ) {
  26. "use strict";
  27. // Define as an AMD module if possible
  28. if ( typeof define === 'function' && define.amd )
  29. {
  30. define( ['jquery'], factory );
  31. }
  32. /* Define using browser globals otherwise
  33. * Prevent multiple instantiations if the script is loaded twice
  34. */
  35. else if ( jQuery && !jQuery.fn.dataTable )
  36. {
  37. factory( jQuery );
  38. }
  39. }
  40. (/** @lends <global> */function( $ ) {
  41. "use strict";
  42. /**
  43. * DataTables is a plug-in for the jQuery Javascript library. It is a
  44. * highly flexible tool, based upon the foundations of progressive
  45. * enhancement, which will add advanced interaction controls to any
  46. * HTML table. For a full list of features please refer to
  47. * <a href="http://datatables.net">DataTables.net</a>.
  48. *
  49. * Note that the <i>DataTable</i> object is not a global variable but is
  50. * aliased to <i>jQuery.fn.DataTable</i> and <i>jQuery.fn.dataTable</i> through which
  51. * it may be accessed.
  52. *
  53. * @class
  54. * @param {object} [oInit={}] Configuration object for DataTables. Options
  55. * are defined by {@link DataTable.defaults}
  56. * @requires jQuery 1.3+
  57. *
  58. * @example
  59. * // Basic initialisation
  60. * $(document).ready( function {
  61. * $('#example').dataTable();
  62. * } );
  63. *
  64. * @example
  65. * // Initialisation with configuration options - in this case, disable
  66. * // pagination and sorting.
  67. * $(document).ready( function {
  68. * $('#example').dataTable( {
  69. * "bPaginate": false,
  70. * "bSort": false
  71. * } );
  72. * } );
  73. */
  74. var DataTable = function( oInit )
  75. {
  76. /**
  77. * Add a column to the list used for the table with default values
  78. * @param {object} oSettings dataTables settings object
  79. * @param {node} nTh The th element for this column
  80. * @memberof DataTable#oApi
  81. */
  82. function _fnAddColumn( oSettings, nTh )
  83. {
  84. var oDefaults = DataTable.defaults.columns;
  85. var iCol = oSettings.aoColumns.length;
  86. var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
  87. "sSortingClass": oSettings.oClasses.sSortable,
  88. "sSortingClassJUI": oSettings.oClasses.sSortJUI,
  89. "nTh": nTh ? nTh : document.createElement('th'),
  90. "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',
  91. "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
  92. "mData": oDefaults.mData ? oDefaults.oDefaults : iCol
  93. } );
  94. oSettings.aoColumns.push( oCol );
  95. /* Add a column specific filter */
  96. if ( oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null )
  97. {
  98. oSettings.aoPreSearchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch );
  99. }
  100. else
  101. {
  102. var oPre = oSettings.aoPreSearchCols[ iCol ];
  103. /* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */
  104. if ( oPre.bRegex === undefined )
  105. {
  106. oPre.bRegex = true;
  107. }
  108. if ( oPre.bSmart === undefined )
  109. {
  110. oPre.bSmart = true;
  111. }
  112. if ( oPre.bCaseInsensitive === undefined )
  113. {
  114. oPre.bCaseInsensitive = true;
  115. }
  116. }
  117. /* Use the column options function to initialise classes etc */
  118. _fnColumnOptions( oSettings, iCol, null );
  119. }
  120. /**
  121. * Apply options for a column
  122. * @param {object} oSettings dataTables settings object
  123. * @param {int} iCol column index to consider
  124. * @param {object} oOptions object with sType, bVisible and bSearchable etc
  125. * @memberof DataTable#oApi
  126. */
  127. function _fnColumnOptions( oSettings, iCol, oOptions )
  128. {
  129. var oCol = oSettings.aoColumns[ iCol ];
  130. /* User specified column options */
  131. if ( oOptions !== undefined && oOptions !== null )
  132. {
  133. /* Backwards compatibility for mDataProp */
  134. if ( oOptions.mDataProp && !oOptions.mData )
  135. {
  136. oOptions.mData = oOptions.mDataProp;
  137. }
  138. if ( oOptions.sType !== undefined )
  139. {
  140. oCol.sType = oOptions.sType;
  141. oCol._bAutoType = false;
  142. }
  143. $.extend( oCol, oOptions );
  144. _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
  145. /* iDataSort to be applied (backwards compatibility), but aDataSort will take
  146. * priority if defined
  147. */
  148. if ( oOptions.iDataSort !== undefined )
  149. {
  150. oCol.aDataSort = [ oOptions.iDataSort ];
  151. }
  152. _fnMap( oCol, oOptions, "aDataSort" );
  153. }
  154. /* Cache the data get and set functions for speed */
  155. var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
  156. var mData = _fnGetObjectDataFn( oCol.mData );
  157. oCol.fnGetData = function (oData, sSpecific) {
  158. var innerData = mData( oData, sSpecific );
  159. if ( oCol.mRender && (sSpecific && sSpecific !== '') )
  160. {
  161. return mRender( innerData, sSpecific, oData );
  162. }
  163. return innerData;
  164. };
  165. oCol.fnSetData = _fnSetObjectDataFn( oCol.mData );
  166. /* Feature sorting overrides column specific when off */
  167. if ( !oSettings.oFeatures.bSort )
  168. {
  169. oCol.bSortable = false;
  170. }
  171. /* Check that the class assignment is correct for sorting */
  172. if ( !oCol.bSortable ||
  173. ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) )
  174. {
  175. oCol.sSortingClass = oSettings.oClasses.sSortableNone;
  176. oCol.sSortingClassJUI = "";
  177. }
  178. else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1 )
  179. {
  180. oCol.sSortingClass = oSettings.oClasses.sSortable;
  181. oCol.sSortingClassJUI = oSettings.oClasses.sSortJUI;
  182. }
  183. else if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 )
  184. {
  185. oCol.sSortingClass = oSettings.oClasses.sSortableAsc;
  186. oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed;
  187. }
  188. else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 )
  189. {
  190. oCol.sSortingClass = oSettings.oClasses.sSortableDesc;
  191. oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed;
  192. }
  193. }
  194. /**
  195. * Adjust the table column widths for new data. Note: you would probably want to
  196. * do a redraw after calling this function!
  197. * @param {object} oSettings dataTables settings object
  198. * @memberof DataTable#oApi
  199. */
  200. function _fnAdjustColumnSizing ( oSettings )
  201. {
  202. /* Not interested in doing column width calculation if auto-width is disabled */
  203. if ( oSettings.oFeatures.bAutoWidth === false )
  204. {
  205. return false;
  206. }
  207. _fnCalculateColumnWidths( oSettings );
  208. for ( var i=0 , iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  209. {
  210. oSettings.aoColumns[i].nTh.style.width = oSettings.aoColumns[i].sWidth;
  211. }
  212. }
  213. /**
  214. * Covert the index of a visible column to the index in the data array (take account
  215. * of hidden columns)
  216. * @param {object} oSettings dataTables settings object
  217. * @param {int} iMatch Visible column index to lookup
  218. * @returns {int} i the data index
  219. * @memberof DataTable#oApi
  220. */
  221. function _fnVisibleToColumnIndex( oSettings, iMatch )
  222. {
  223. var aiVis = _fnGetColumns( oSettings, 'bVisible' );
  224. return typeof aiVis[iMatch] === 'number' ?
  225. aiVis[iMatch] :
  226. null;
  227. }
  228. /**
  229. * Covert the index of an index in the data array and convert it to the visible
  230. * column index (take account of hidden columns)
  231. * @param {int} iMatch Column index to lookup
  232. * @param {object} oSettings dataTables settings object
  233. * @returns {int} i the data index
  234. * @memberof DataTable#oApi
  235. */
  236. function _fnColumnIndexToVisible( oSettings, iMatch )
  237. {
  238. var aiVis = _fnGetColumns( oSettings, 'bVisible' );
  239. var iPos = $.inArray( iMatch, aiVis );
  240. return iPos !== -1 ? iPos : null;
  241. }
  242. /**
  243. * Get the number of visible columns
  244. * @param {object} oSettings dataTables settings object
  245. * @returns {int} i the number of visible columns
  246. * @memberof DataTable#oApi
  247. */
  248. function _fnVisbleColumns( oSettings )
  249. {
  250. return _fnGetColumns( oSettings, 'bVisible' ).length;
  251. }
  252. /**
  253. * Get an array of column indexes that match a given property
  254. * @param {object} oSettings dataTables settings object
  255. * @param {string} sParam Parameter in aoColumns to look for - typically
  256. * bVisible or bSearchable
  257. * @returns {array} Array of indexes with matched properties
  258. * @memberof DataTable#oApi
  259. */
  260. function _fnGetColumns( oSettings, sParam )
  261. {
  262. var a = [];
  263. $.map( oSettings.aoColumns, function(val, i) {
  264. if ( val[sParam] ) {
  265. a.push( i );
  266. }
  267. } );
  268. return a;
  269. }
  270. /**
  271. * Get the sort type based on an input string
  272. * @param {string} sData data we wish to know the type of
  273. * @returns {string} type (defaults to 'string' if no type can be detected)
  274. * @memberof DataTable#oApi
  275. */
  276. function _fnDetectType( sData )
  277. {
  278. var aTypes = DataTable.ext.aTypes;
  279. var iLen = aTypes.length;
  280. for ( var i=0 ; i<iLen ; i++ )
  281. {
  282. var sType = aTypes[i]( sData );
  283. if ( sType !== null )
  284. {
  285. return sType;
  286. }
  287. }
  288. return 'string';
  289. }
  290. /**
  291. * Figure out how to reorder a display list
  292. * @param {object} oSettings dataTables settings object
  293. * @returns array {int} aiReturn index list for reordering
  294. * @memberof DataTable#oApi
  295. */
  296. function _fnReOrderIndex ( oSettings, sColumns )
  297. {
  298. var aColumns = sColumns.split(',');
  299. var aiReturn = [];
  300. for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  301. {
  302. for ( var j=0 ; j<iLen ; j++ )
  303. {
  304. if ( oSettings.aoColumns[i].sName == aColumns[j] )
  305. {
  306. aiReturn.push( j );
  307. break;
  308. }
  309. }
  310. }
  311. return aiReturn;
  312. }
  313. /**
  314. * Get the column ordering that DataTables expects
  315. * @param {object} oSettings dataTables settings object
  316. * @returns {string} comma separated list of names
  317. * @memberof DataTable#oApi
  318. */
  319. function _fnColumnOrdering ( oSettings )
  320. {
  321. var sNames = '';
  322. for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  323. {
  324. sNames += oSettings.aoColumns[i].sName+',';
  325. }
  326. if ( sNames.length == iLen )
  327. {
  328. return "";
  329. }
  330. return sNames.slice(0, -1);
  331. }
  332. /**
  333. * Take the column definitions and static columns arrays and calculate how
  334. * they relate to column indexes. The callback function will then apply the
  335. * definition found for a column to a suitable configuration object.
  336. * @param {object} oSettings dataTables settings object
  337. * @param {array} aoColDefs The aoColumnDefs array that is to be applied
  338. * @param {array} aoCols The aoColumns array that defines columns individually
  339. * @param {function} fn Callback function - takes two parameters, the calculated
  340. * column index and the definition for that column.
  341. * @memberof DataTable#oApi
  342. */
  343. function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
  344. {
  345. var i, iLen, j, jLen, k, kLen;
  346. // Column definitions with aTargets
  347. if ( aoColDefs )
  348. {
  349. /* Loop over the definitions array - loop in reverse so first instance has priority */
  350. for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
  351. {
  352. /* Each definition can target multiple columns, as it is an array */
  353. var aTargets = aoColDefs[i].aTargets;
  354. if ( !$.isArray( aTargets ) )
  355. {
  356. _fnLog( oSettings, 1, 'aTargets must be an array of targets, not a '+(typeof aTargets) );
  357. }
  358. for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
  359. {
  360. if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
  361. {
  362. /* Add columns that we don't yet know about */
  363. while( oSettings.aoColumns.length <= aTargets[j] )
  364. {
  365. _fnAddColumn( oSettings );
  366. }
  367. /* Integer, basic index */
  368. fn( aTargets[j], aoColDefs[i] );
  369. }
  370. else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
  371. {
  372. /* Negative integer, right to left column counting */
  373. fn( oSettings.aoColumns.length+aTargets[j], aoColDefs[i] );
  374. }
  375. else if ( typeof aTargets[j] === 'string' )
  376. {
  377. /* Class name matching on TH element */
  378. for ( k=0, kLen=oSettings.aoColumns.length ; k<kLen ; k++ )
  379. {
  380. if ( aTargets[j] == "_all" ||
  381. $(oSettings.aoColumns[k].nTh).hasClass( aTargets[j] ) )
  382. {
  383. fn( k, aoColDefs[i] );
  384. }
  385. }
  386. }
  387. }
  388. }
  389. }
  390. // Statically defined columns array
  391. if ( aoCols )
  392. {
  393. for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
  394. {
  395. fn( i, aoCols[i] );
  396. }
  397. }
  398. }
  399. /**
  400. * Add a data array to the table, creating DOM node etc. This is the parallel to
  401. * _fnGatherData, but for adding rows from a Javascript source, rather than a
  402. * DOM source.
  403. * @param {object} oSettings dataTables settings object
  404. * @param {array} aData data array to be added
  405. * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
  406. * @memberof DataTable#oApi
  407. */
  408. function _fnAddData ( oSettings, aDataSupplied )
  409. {
  410. var oCol;
  411. /* Take an independent copy of the data source so we can bash it about as we wish */
  412. var aDataIn = ($.isArray(aDataSupplied)) ?
  413. aDataSupplied.slice() :
  414. $.extend( true, {}, aDataSupplied );
  415. /* Create the object for storing information about this new row */
  416. var iRow = oSettings.aoData.length;
  417. var oData = $.extend( true, {}, DataTable.models.oRow );
  418. oData._aData = aDataIn;
  419. oSettings.aoData.push( oData );
  420. /* Create the cells */
  421. var nTd, sThisType;
  422. for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  423. {
  424. oCol = oSettings.aoColumns[i];
  425. /* Use rendered data for filtering / sorting */
  426. if ( typeof oCol.fnRender === 'function' && oCol.bUseRendered && oCol.mData !== null )
  427. {
  428. _fnSetCellData( oSettings, iRow, i, _fnRender(oSettings, iRow, i) );
  429. }
  430. else
  431. {
  432. _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
  433. }
  434. /* See if we should auto-detect the column type */
  435. if ( oCol._bAutoType && oCol.sType != 'string' )
  436. {
  437. /* Attempt to auto detect the type - same as _fnGatherData() */
  438. var sVarType = _fnGetCellData( oSettings, iRow, i, 'type' );
  439. if ( sVarType !== null && sVarType !== '' )
  440. {
  441. sThisType = _fnDetectType( sVarType );
  442. if ( oCol.sType === null )
  443. {
  444. oCol.sType = sThisType;
  445. }
  446. else if ( oCol.sType != sThisType && oCol.sType != "html" )
  447. {
  448. /* String is always the 'fallback' option */
  449. oCol.sType = 'string';
  450. }
  451. }
  452. }
  453. }
  454. /* Add to the display array */
  455. oSettings.aiDisplayMaster.push( iRow );
  456. /* Create the DOM information */
  457. if ( !oSettings.oFeatures.bDeferRender )
  458. {
  459. _fnCreateTr( oSettings, iRow );
  460. }
  461. return iRow;
  462. }
  463. /**
  464. * Read in the data from the target table from the DOM
  465. * @param {object} oSettings dataTables settings object
  466. * @memberof DataTable#oApi
  467. */
  468. function _fnGatherData( oSettings )
  469. {
  470. var iLoop, i, iLen, j, jLen, jInner,
  471. nTds, nTrs, nTd, nTr, aLocalData, iThisIndex,
  472. iRow, iRows, iColumn, iColumns, sNodeName,
  473. oCol, oData;
  474. /*
  475. * Process by row first
  476. * Add the data object for the whole table - storing the tr node. Note - no point in getting
  477. * DOM based data if we are going to go and replace it with Ajax source data.
  478. */
  479. if ( oSettings.bDeferLoading || oSettings.sAjaxSource === null )
  480. {
  481. nTr = oSettings.nTBody.firstChild;
  482. while ( nTr )
  483. {
  484. if ( nTr.nodeName.toUpperCase() == "TR" )
  485. {
  486. iThisIndex = oSettings.aoData.length;
  487. nTr._DT_RowIndex = iThisIndex;
  488. oSettings.aoData.push( $.extend( true, {}, DataTable.models.oRow, {
  489. "nTr": nTr
  490. } ) );
  491. oSettings.aiDisplayMaster.push( iThisIndex );
  492. nTd = nTr.firstChild;
  493. jInner = 0;
  494. while ( nTd )
  495. {
  496. sNodeName = nTd.nodeName.toUpperCase();
  497. if ( sNodeName == "TD" || sNodeName == "TH" )
  498. {
  499. _fnSetCellData( oSettings, iThisIndex, jInner, $.trim(nTd.innerHTML) );
  500. jInner++;
  501. }
  502. nTd = nTd.nextSibling;
  503. }
  504. }
  505. nTr = nTr.nextSibling;
  506. }
  507. }
  508. /* Gather in the TD elements of the Table - note that this is basically the same as
  509. * fnGetTdNodes, but that function takes account of hidden columns, which we haven't yet
  510. * setup!
  511. */
  512. nTrs = _fnGetTrNodes( oSettings );
  513. nTds = [];
  514. for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  515. {
  516. nTd = nTrs[i].firstChild;
  517. while ( nTd )
  518. {
  519. sNodeName = nTd.nodeName.toUpperCase();
  520. if ( sNodeName == "TD" || sNodeName == "TH" )
  521. {
  522. nTds.push( nTd );
  523. }
  524. nTd = nTd.nextSibling;
  525. }
  526. }
  527. /* Now process by column */
  528. for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ )
  529. {
  530. oCol = oSettings.aoColumns[iColumn];
  531. /* Get the title of the column - unless there is a user set one */
  532. if ( oCol.sTitle === null )
  533. {
  534. oCol.sTitle = oCol.nTh.innerHTML;
  535. }
  536. var
  537. bAutoType = oCol._bAutoType,
  538. bRender = typeof oCol.fnRender === 'function',
  539. bClass = oCol.sClass !== null,
  540. bVisible = oCol.bVisible,
  541. nCell, sThisType, sRendered, sValType;
  542. /* A single loop to rule them all (and be more efficient) */
  543. if ( bAutoType || bRender || bClass || !bVisible )
  544. {
  545. for ( iRow=0, iRows=oSettings.aoData.length ; iRow<iRows ; iRow++ )
  546. {
  547. oData = oSettings.aoData[iRow];
  548. nCell = nTds[ (iRow*iColumns) + iColumn ];
  549. /* Type detection */
  550. if ( bAutoType && oCol.sType != 'string' )
  551. {
  552. sValType = _fnGetCellData( oSettings, iRow, iColumn, 'type' );
  553. if ( sValType !== '' )
  554. {
  555. sThisType = _fnDetectType( sValType );
  556. if ( oCol.sType === null )
  557. {
  558. oCol.sType = sThisType;
  559. }
  560. else if ( oCol.sType != sThisType &&
  561. oCol.sType != "html" )
  562. {
  563. /* String is always the 'fallback' option */
  564. oCol.sType = 'string';
  565. }
  566. }
  567. }
  568. if ( oCol.mRender )
  569. {
  570. // mRender has been defined, so we need to get the value and set it
  571. nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' );
  572. }
  573. else if ( oCol.mData !== iColumn )
  574. {
  575. // If mData is not the same as the column number, then we need to
  576. // get the dev set value. If it is the column, no point in wasting
  577. // time setting the value that is already there!
  578. nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' );
  579. }
  580. /* Rendering */
  581. if ( bRender )
  582. {
  583. sRendered = _fnRender( oSettings, iRow, iColumn );
  584. nCell.innerHTML = sRendered;
  585. if ( oCol.bUseRendered )
  586. {
  587. /* Use the rendered data for filtering / sorting */
  588. _fnSetCellData( oSettings, iRow, iColumn, sRendered );
  589. }
  590. }
  591. /* Classes */
  592. if ( bClass )
  593. {
  594. nCell.className += ' '+oCol.sClass;
  595. }
  596. /* Column visibility */
  597. if ( !bVisible )
  598. {
  599. oData._anHidden[iColumn] = nCell;
  600. nCell.parentNode.removeChild( nCell );
  601. }
  602. else
  603. {
  604. oData._anHidden[iColumn] = null;
  605. }
  606. if ( oCol.fnCreatedCell )
  607. {
  608. oCol.fnCreatedCell.call( oSettings.oInstance,
  609. nCell, _fnGetCellData( oSettings, iRow, iColumn, 'display' ), oData._aData, iRow, iColumn
  610. );
  611. }
  612. }
  613. }
  614. }
  615. /* Row created callbacks */
  616. if ( oSettings.aoRowCreatedCallback.length !== 0 )
  617. {
  618. for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
  619. {
  620. oData = oSettings.aoData[i];
  621. _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, i] );
  622. }
  623. }
  624. }
  625. /**
  626. * Take a TR element and convert it to an index in aoData
  627. * @param {object} oSettings dataTables settings object
  628. * @param {node} n the TR element to find
  629. * @returns {int} index if the node is found, null if not
  630. * @memberof DataTable#oApi
  631. */
  632. function _fnNodeToDataIndex( oSettings, n )
  633. {
  634. return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
  635. }
  636. /**
  637. * Take a TD element and convert it into a column data index (not the visible index)
  638. * @param {object} oSettings dataTables settings object
  639. * @param {int} iRow The row number the TD/TH can be found in
  640. * @param {node} n The TD/TH element to find
  641. * @returns {int} index if the node is found, -1 if not
  642. * @memberof DataTable#oApi
  643. */
  644. function _fnNodeToColumnIndex( oSettings, iRow, n )
  645. {
  646. var anCells = _fnGetTdNodes( oSettings, iRow );
  647. for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  648. {
  649. if ( anCells[i] === n )
  650. {
  651. return i;
  652. }
  653. }
  654. return -1;
  655. }
  656. /**
  657. * Get an array of data for a given row from the internal data cache
  658. * @param {object} oSettings dataTables settings object
  659. * @param {int} iRow aoData row id
  660. * @param {string} sSpecific data get type ('type' 'filter' 'sort')
  661. * @param {array} aiColumns Array of column indexes to get data from
  662. * @returns {array} Data array
  663. * @memberof DataTable#oApi
  664. */
  665. function _fnGetRowData( oSettings, iRow, sSpecific, aiColumns )
  666. {
  667. var out = [];
  668. for ( var i=0, iLen=aiColumns.length ; i<iLen ; i++ )
  669. {
  670. out.push( _fnGetCellData( oSettings, iRow, aiColumns[i], sSpecific ) );
  671. }
  672. return out;
  673. }
  674. /**
  675. * Get the data for a given cell from the internal cache, taking into account data mapping
  676. * @param {object} oSettings dataTables settings object
  677. * @param {int} iRow aoData row id
  678. * @param {int} iCol Column index
  679. * @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort')
  680. * @returns {*} Cell data
  681. * @memberof DataTable#oApi
  682. */
  683. function _fnGetCellData( oSettings, iRow, iCol, sSpecific )
  684. {
  685. var sData;
  686. var oCol = oSettings.aoColumns[iCol];
  687. var oData = oSettings.aoData[iRow]._aData;
  688. if ( (sData=oCol.fnGetData( oData, sSpecific )) === undefined )
  689. {
  690. if ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null )
  691. {
  692. _fnLog( oSettings, 0, "Requested unknown parameter "+
  693. (typeof oCol.mData=='function' ? '{mData function}' : "'"+oCol.mData+"'")+
  694. " from the data source for row "+iRow );
  695. oSettings.iDrawError = oSettings.iDraw;
  696. }
  697. return oCol.sDefaultContent;
  698. }
  699. /* When the data source is null, we can use default column data */
  700. if ( sData === null && oCol.sDefaultContent !== null )
  701. {
  702. sData = oCol.sDefaultContent;
  703. }
  704. else if ( typeof sData === 'function' )
  705. {
  706. /* If the data source is a function, then we run it and use the return */
  707. return sData();
  708. }
  709. if ( sSpecific == 'display' && sData === null )
  710. {
  711. return '';
  712. }
  713. return sData;
  714. }
  715. /**
  716. * Set the value for a specific cell, into the internal data cache
  717. * @param {object} oSettings dataTables settings object
  718. * @param {int} iRow aoData row id
  719. * @param {int} iCol Column index
  720. * @param {*} val Value to set
  721. * @memberof DataTable#oApi
  722. */
  723. function _fnSetCellData( oSettings, iRow, iCol, val )
  724. {
  725. var oCol = oSettings.aoColumns[iCol];
  726. var oData = oSettings.aoData[iRow]._aData;
  727. oCol.fnSetData( oData, val );
  728. }
  729. // Private variable that is used to match array syntax in the data property object
  730. var __reArray = /\[.*?\]$/;
  731. /**
  732. * Return a function that can be used to get data from a source object, taking
  733. * into account the ability to use nested objects as a source
  734. * @param {string|int|function} mSource The data source for the object
  735. * @returns {function} Data get function
  736. * @memberof DataTable#oApi
  737. */
  738. function _fnGetObjectDataFn( mSource )
  739. {
  740. if ( mSource === null )
  741. {
  742. /* Give an empty string for rendering / sorting etc */
  743. return function (data, type) {
  744. return null;
  745. };
  746. }
  747. else if ( typeof mSource === 'function' )
  748. {
  749. return function (data, type, extra) {
  750. return mSource( data, type, extra );
  751. };
  752. }
  753. else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) )
  754. {
  755. /* If there is a . in the source string then the data source is in a
  756. * nested object so we loop over the data for each level to get the next
  757. * level down. On each loop we test for undefined, and if found immediately
  758. * return. This allows entire objects to be missing and sDefaultContent to
  759. * be used if defined, rather than throwing an error
  760. */
  761. var fetchData = function (data, type, src) {
  762. var a = src.split('.');
  763. var arrayNotation, out, innerSrc;
  764. if ( src !== "" )
  765. {
  766. for ( var i=0, iLen=a.length ; i<iLen ; i++ )
  767. {
  768. // Check if we are dealing with an array notation request
  769. arrayNotation = a[i].match(__reArray);
  770. if ( arrayNotation ) {
  771. a[i] = a[i].replace(__reArray, '');
  772. // Condition allows simply [] to be passed in
  773. if ( a[i] !== "" ) {
  774. data = data[ a[i] ];
  775. }
  776. out = [];
  777. // Get the remainder of the nested object to get
  778. a.splice( 0, i+1 );
  779. innerSrc = a.join('.');
  780. // Traverse each entry in the array getting the properties requested
  781. for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
  782. out.push( fetchData( data[j], type, innerSrc ) );
  783. }
  784. // If a string is given in between the array notation indicators, that
  785. // is used to join the strings together, otherwise an array is returned
  786. var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
  787. data = (join==="") ? out : out.join(join);
  788. // The inner call to fetchData has already traversed through the remainder
  789. // of the source requested, so we exit from the loop
  790. break;
  791. }
  792. if ( data === null || data[ a[i] ] === undefined )
  793. {
  794. return undefined;
  795. }
  796. data = data[ a[i] ];
  797. }
  798. }
  799. return data;
  800. };
  801. return function (data, type) {
  802. return fetchData( data, type, mSource );
  803. };
  804. }
  805. else
  806. {
  807. /* Array or flat object mapping */
  808. return function (data, type) {
  809. return data[mSource];
  810. };
  811. }
  812. }
  813. /**
  814. * Return a function that can be used to set data from a source object, taking
  815. * into account the ability to use nested objects as a source
  816. * @param {string|int|function} mSource The data source for the object
  817. * @returns {function} Data set function
  818. * @memberof DataTable#oApi
  819. */
  820. function _fnSetObjectDataFn( mSource )
  821. {
  822. if ( mSource === null )
  823. {
  824. /* Nothing to do when the data source is null */
  825. return function (data, val) {};
  826. }
  827. else if ( typeof mSource === 'function' )
  828. {
  829. return function (data, val) {
  830. mSource( data, 'set', val );
  831. };
  832. }
  833. else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) )
  834. {
  835. /* Like the get, we need to get data from a nested object */
  836. var setData = function (data, val, src) {
  837. var a = src.split('.'), b;
  838. var arrayNotation, o, innerSrc;
  839. for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
  840. {
  841. // Check if we are dealing with an array notation request
  842. arrayNotation = a[i].match(__reArray);
  843. if ( arrayNotation )
  844. {
  845. a[i] = a[i].replace(__reArray, '');
  846. data[ a[i] ] = [];
  847. // Get the remainder of the nested object to set so we can recurse
  848. b = a.slice();
  849. b.splice( 0, i+1 );
  850. innerSrc = b.join('.');
  851. // Traverse each entry in the array setting the properties requested
  852. for ( var j=0, jLen=val.length ; j<jLen ; j++ )
  853. {
  854. o = {};
  855. setData( o, val[j], innerSrc );
  856. data[ a[i] ].push( o );
  857. }
  858. // The inner call to setData has already traversed through the remainder
  859. // of the source and has set the data, thus we can exit here
  860. return;
  861. }
  862. // If the nested object doesn't currently exist - since we are
  863. // trying to set the value - create it
  864. if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
  865. {
  866. data[ a[i] ] = {};
  867. }
  868. data = data[ a[i] ];
  869. }
  870. // If array notation is used, we just want to strip it and use the property name
  871. // and assign the value. If it isn't used, then we get the result we want anyway
  872. data[ a[a.length-1].replace(__reArray, '') ] = val;
  873. };
  874. return function (data, val) {
  875. return setData( data, val, mSource );
  876. };
  877. }
  878. else
  879. {
  880. /* Array or flat object mapping */
  881. return function (data, val) {
  882. data[mSource] = val;
  883. };
  884. }
  885. }
  886. /**
  887. * Return an array with the full table data
  888. * @param {object} oSettings dataTables settings object
  889. * @returns array {array} aData Master data array
  890. * @memberof DataTable#oApi
  891. */
  892. function _fnGetDataMaster ( oSettings )
  893. {
  894. var aData = [];
  895. var iLen = oSettings.aoData.length;
  896. for ( var i=0 ; i<iLen; i++ )
  897. {
  898. aData.push( oSettings.aoData[i]._aData );
  899. }
  900. return aData;
  901. }
  902. /**
  903. * Nuke the table
  904. * @param {object} oSettings dataTables settings object
  905. * @memberof DataTable#oApi
  906. */
  907. function _fnClearTable( oSettings )
  908. {
  909. oSettings.aoData.splice( 0, oSettings.aoData.length );
  910. oSettings.aiDisplayMaster.splice( 0, oSettings.aiDisplayMaster.length );
  911. oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length );
  912. _fnCalculateEnd( oSettings );
  913. }
  914. /**
  915. * Take an array of integers (index array) and remove a target integer (value - not
  916. * the key!)
  917. * @param {array} a Index array to target
  918. * @param {int} iTarget value to find
  919. * @memberof DataTable#oApi
  920. */
  921. function _fnDeleteIndex( a, iTarget )
  922. {
  923. var iTargetIndex = -1;
  924. for ( var i=0, iLen=a.length ; i<iLen ; i++ )
  925. {
  926. if ( a[i] == iTarget )
  927. {
  928. iTargetIndex = i;
  929. }
  930. else if ( a[i] > iTarget )
  931. {
  932. a[i]--;
  933. }
  934. }
  935. if ( iTargetIndex != -1 )
  936. {
  937. a.splice( iTargetIndex, 1 );
  938. }
  939. }
  940. /**
  941. * Call the developer defined fnRender function for a given cell (row/column) with
  942. * the required parameters and return the result.
  943. * @param {object} oSettings dataTables settings object
  944. * @param {int} iRow aoData index for the row
  945. * @param {int} iCol aoColumns index for the column
  946. * @returns {*} Return of the developer's fnRender function
  947. * @memberof DataTable#oApi
  948. */
  949. function _fnRender( oSettings, iRow, iCol )
  950. {
  951. var oCol = oSettings.aoColumns[iCol];
  952. return oCol.fnRender( {
  953. "iDataRow": iRow,
  954. "iDataColumn": iCol,
  955. "oSettings": oSettings,
  956. "aData": oSettings.aoData[iRow]._aData,
  957. "mDataProp": oCol.mData
  958. }, _fnGetCellData(oSettings, iRow, iCol, 'display') );
  959. }
  960. /**
  961. * Create a new TR element (and it's TD children) for a row
  962. * @param {object} oSettings dataTables settings object
  963. * @param {int} iRow Row to consider
  964. * @memberof DataTable#oApi
  965. */
  966. function _fnCreateTr ( oSettings, iRow )
  967. {
  968. var oData = oSettings.aoData[iRow];
  969. var nTd;
  970. if ( oData.nTr === null )
  971. {
  972. oData.nTr = document.createElement('tr');
  973. /* Use a private property on the node to allow reserve mapping from the node
  974. * to the aoData array for fast look up
  975. */
  976. oData.nTr._DT_RowIndex = iRow;
  977. /* Special parameters can be given by the data source to be used on the row */
  978. if ( oData._aData.DT_RowId )
  979. {
  980. oData.nTr.id = oData._aData.DT_RowId;
  981. }
  982. if ( oData._aData.DT_RowClass )
  983. {
  984. oData.nTr.className = oData._aData.DT_RowClass;
  985. }
  986. /* Process each column */
  987. for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  988. {
  989. var oCol = oSettings.aoColumns[i];
  990. nTd = document.createElement( oCol.sCellType );
  991. /* Render if needed - if bUseRendered is true then we already have the rendered
  992. * value in the data source - so can just use that
  993. */
  994. nTd.innerHTML = (typeof oCol.fnRender === 'function' && (!oCol.bUseRendered || oCol.mData === null)) ?
  995. _fnRender( oSettings, iRow, i ) :
  996. _fnGetCellData( oSettings, iRow, i, 'display' );
  997. /* Add user defined class */
  998. if ( oCol.sClass !== null )
  999. {
  1000. nTd.className = oCol.sClass;
  1001. }
  1002. if ( oCol.bVisible )
  1003. {
  1004. oData.nTr.appendChild( nTd );
  1005. oData._anHidden[i] = null;
  1006. }
  1007. else
  1008. {
  1009. oData._anHidden[i] = nTd;
  1010. }
  1011. if ( oCol.fnCreatedCell )
  1012. {
  1013. oCol.fnCreatedCell.call( oSettings.oInstance,
  1014. nTd, _fnGetCellData( oSettings, iRow, i, 'display' ), oData._aData, iRow, i
  1015. );
  1016. }
  1017. }
  1018. _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, iRow] );
  1019. }
  1020. }
  1021. /**
  1022. * Create the HTML header for the table
  1023. * @param {object} oSettings dataTables settings object
  1024. * @memberof DataTable#oApi
  1025. */
  1026. function _fnBuildHead( oSettings )
  1027. {
  1028. var i, nTh, iLen, j, jLen;
  1029. var iThs = $('th, td', oSettings.nTHead).length;
  1030. var iCorrector = 0;
  1031. var jqChildren;
  1032. /* If there is a header in place - then use it - otherwise it's going to get nuked... */
  1033. if ( iThs !== 0 )
  1034. {
  1035. /* We've got a thead from the DOM, so remove hidden columns and apply width to vis cols */
  1036. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  1037. {
  1038. nTh = oSettings.aoColumns[i].nTh;
  1039. nTh.setAttribute('role', 'columnheader');
  1040. if ( oSettings.aoColumns[i].bSortable )
  1041. {
  1042. nTh.setAttribute('tabindex', oSettings.iTabIndex);
  1043. nTh.setAttribute('aria-controls', oSettings.sTableId);
  1044. }
  1045. if ( oSettings.aoColumns[i].sClass !== null )
  1046. {
  1047. $(nTh).addClass( oSettings.aoColumns[i].sClass );
  1048. }
  1049. /* Set the title of the column if it is user defined (not what was auto detected) */
  1050. if ( oSettings.aoColumns[i].sTitle != nTh.innerHTML )
  1051. {
  1052. nTh.innerHTML = oSettings.aoColumns[i].sTitle;
  1053. }
  1054. }
  1055. }
  1056. else
  1057. {
  1058. /* We don't have a header in the DOM - so we are going to have to create one */
  1059. var nTr = document.createElement( "tr" );
  1060. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  1061. {
  1062. nTh = oSettings.aoColumns[i].nTh;
  1063. nTh.innerHTML = oSettings.aoColumns[i].sTitle;
  1064. nTh.setAttribute('tabindex', '0');
  1065. if ( oSettings.aoColumns[i].sClass !== null )
  1066. {
  1067. $(nTh).addClass( oSettings.aoColumns[i].sClass );
  1068. }
  1069. nTr.appendChild( nTh );
  1070. }
  1071. $(oSettings.nTHead).html( '' )[0].appendChild( nTr );
  1072. _fnDetectHeader( oSettings.aoHeader, oSettings.nTHead );
  1073. }
  1074. /* ARIA role for the rows */
  1075. $(oSettings.nTHead).children('tr').attr('role', 'row');
  1076. /* Add the extra markup needed by jQuery UI's themes */
  1077. if ( oSettings.bJUI )
  1078. {
  1079. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  1080. {
  1081. nTh = oSettings.aoColumns[i].nTh;
  1082. var nDiv = document.createElement('div');
  1083. nDiv.className = oSettings.oClasses.sSortJUIWrapper;
  1084. $(nTh).contents().appendTo(nDiv);
  1085. var nSpan = document.createElement('span');
  1086. nSpan.className = oSettings.oClasses.sSortIcon;
  1087. nDiv.appendChild( nSpan );
  1088. nTh.appendChild( nDiv );
  1089. }
  1090. }
  1091. if ( oSettings.oFeatures.bSort )
  1092. {
  1093. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  1094. {
  1095. if ( oSettings.aoColumns[i].bSortable !== false )
  1096. {
  1097. _fnSortAttachListener( oSettings, oSettings.aoColumns[i].nTh, i );
  1098. }
  1099. else
  1100. {
  1101. $(oSettings.aoColumns[i].nTh).addClass( oSettings.oClasses.sSortableNone );
  1102. }
  1103. }
  1104. }
  1105. /* Deal with the footer - add classes if required */
  1106. if ( oSettings.oClasses.sFooterTH !== "" )
  1107. {
  1108. $(oSettings.nTFoot).children('tr').children('th').addClass( oSettings.oClasses.sFooterTH );
  1109. }
  1110. /* Cache the footer elements */
  1111. if ( oSettings.nTFoot !== null )
  1112. {
  1113. var anCells = _fnGetUniqueThs( oSettings, null, oSettings.aoFooter );
  1114. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  1115. {
  1116. if ( anCells[i] )
  1117. {
  1118. oSettings.aoColumns[i].nTf = anCells[i];
  1119. if ( oSettings.aoColumns[i].sClass )
  1120. {
  1121. $(anCells[i]).addClass( oSettings.aoColumns[i].sClass );
  1122. }
  1123. }
  1124. }
  1125. }
  1126. }
  1127. /**
  1128. * Draw the header (or footer) element based on the column visibility states. The
  1129. * methodology here is to use the layout array from _fnDetectHeader, modified for
  1130. * the instantaneous column visibility, to construct the new layout. The grid is
  1131. * traversed over cell at a time in a rows x columns grid fashion, although each
  1132. * cell insert can cover multiple elements in the grid - which is tracks using the
  1133. * aApplied array. Cell inserts in the grid will only occur where there isn't
  1134. * already a cell in that position.
  1135. * @param {object} oSettings dataTables settings object
  1136. * @param array {objects} aoSource Layout array from _fnDetectHeader
  1137. * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
  1138. * @memberof DataTable#oApi
  1139. */
  1140. function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
  1141. {
  1142. var i, iLen, j, jLen, k, kLen, n, nLocalTr;
  1143. var aoLocal = [];
  1144. var aApplied = [];
  1145. var iColumns = oSettings.aoColumns.length;
  1146. var iRowspan, iColspan;
  1147. if ( bIncludeHidden === undefined )
  1148. {
  1149. bIncludeHidden = false;
  1150. }
  1151. /* Make a copy of the master layout array, but without the visible columns in it */
  1152. for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
  1153. {
  1154. aoLocal[i] = aoSource[i].slice();
  1155. aoLocal[i].nTr = aoSource[i].nTr;
  1156. /* Remove any columns which are currently hidden */
  1157. for ( j=iColumns-1 ; j>=0 ; j-- )
  1158. {
  1159. if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
  1160. {
  1161. aoLocal[i].splice( j, 1 );
  1162. }
  1163. }
  1164. /* Prep the applied array - it needs an element for each row */
  1165. aApplied.push( [] );
  1166. }
  1167. for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
  1168. {
  1169. nLocalTr = aoLocal[i].nTr;
  1170. /* All cells are going to be replaced, so empty out the row */
  1171. if ( nLocalTr )
  1172. {
  1173. while( (n = nLocalTr.firstChild) )
  1174. {
  1175. nLocalTr.removeChild( n );
  1176. }
  1177. }
  1178. for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
  1179. {
  1180. iRowspan = 1;
  1181. iColspan = 1;
  1182. /* Check to see if there is already a cell (row/colspan) covering our target
  1183. * insert point. If there is, then there is nothing to do.
  1184. */
  1185. if ( aApplied[i][j] === undefined )
  1186. {
  1187. nLocalTr.appendChild( aoLocal[i][j].cell );
  1188. aApplied[i][j] = 1;
  1189. /* Expand the cell to cover as many rows as needed */
  1190. while ( aoLocal[i+iRowspan] !== undefined &&
  1191. aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
  1192. {
  1193. aApplied[i+iRowspan][j] = 1;
  1194. iRowspan++;
  1195. }
  1196. /* Expand the cell to cover as many columns as needed */
  1197. while ( aoLocal[i][j+iColspan] !== undefined &&
  1198. aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
  1199. {
  1200. /* Must update the applied array over the rows for the columns */
  1201. for ( k=0 ; k<iRowspan ; k++ )
  1202. {
  1203. aApplied[i+k][j+iColspan] = 1;
  1204. }
  1205. iColspan++;
  1206. }
  1207. /* Do the actual expansion in the DOM */
  1208. aoLocal[i][j].cell.rowSpan = iRowspan;
  1209. aoLocal[i][j].cell.colSpan = iColspan;
  1210. }
  1211. }
  1212. }
  1213. }
  1214. /**
  1215. * Insert the required TR nodes into the table for display
  1216. * @param {object} oSettings dataTables settings object
  1217. * @memberof DataTable#oApi
  1218. */
  1219. function _fnDraw( oSettings )
  1220. {
  1221. /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
  1222. var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
  1223. if ( $.inArray( false, aPreDraw ) !== -1 )
  1224. {
  1225. _fnProcessingDisplay( oSettings, false );
  1226. return;
  1227. }
  1228. var i, iLen, n;
  1229. var anRows = [];
  1230. var iRowCount = 0;
  1231. var iStripes = oSettings.asStripeClasses.length;
  1232. var iOpenRows = oSettings.aoOpenRows.length;
  1233. oSettings.bDrawing = true;
  1234. /* Check and see if we have an initial draw position from state saving */
  1235. if ( oSettings.iInitDisplayStart !== undefined && oSettings.iInitDisplayStart != -1 )
  1236. {
  1237. if ( oSettings.oFeatures.bServerSide )
  1238. {
  1239. oSettings._iDisplayStart = oSettings.iInitDisplayStart;
  1240. }
  1241. else
  1242. {
  1243. oSettings._iDisplayStart = (oSettings.iInitDisplayStart >= oSettings.fnRecordsDisplay()) ?
  1244. 0 : oSettings.iInitDisplayStart;
  1245. }
  1246. oSettings.iInitDisplayStart = -1;
  1247. _fnCalculateEnd( oSettings );
  1248. }
  1249. /* Server-side processing draw intercept */
  1250. if ( oSettings.bDeferLoading )
  1251. {
  1252. oSettings.bDeferLoading = false;
  1253. oSettings.iDraw++;
  1254. }
  1255. else if ( !oSettings.oFeatures.bServerSide )
  1256. {
  1257. oSettings.iDraw++;
  1258. }
  1259. else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
  1260. {
  1261. return;
  1262. }
  1263. if ( oSettings.aiDisplay.length !== 0 )
  1264. {
  1265. var iStart = oSettings._iDisplayStart;
  1266. var iEnd = oSettings._iDisplayEnd;
  1267. if ( oSettings.oFeatures.bServerSide )
  1268. {
  1269. iStart = 0;
  1270. iEnd = oSettings.aoData.length;
  1271. }
  1272. for ( var j=iStart ; j<iEnd ; j++ )
  1273. {
  1274. var aoData = oSettings.aoData[ oSettings.aiDisplay[j] ];
  1275. if ( aoData.nTr === null )
  1276. {
  1277. _fnCreateTr( oSettings, oSettings.aiDisplay[j] );
  1278. }
  1279. var nRow = aoData.nTr;
  1280. /* Remove the old striping classes and then add the new one */
  1281. if ( iStripes !== 0 )
  1282. {
  1283. var sStripe = oSettings.asStripeClasses[ iRowCount % iStripes ];
  1284. if ( aoData._sRowStripe != sStripe )
  1285. {
  1286. $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
  1287. aoData._sRowStripe = sStripe;
  1288. }
  1289. }
  1290. /* Row callback functions - might want to manipulate the row */
  1291. _fnCallbackFire( oSettings, 'aoRowCallback', null,
  1292. [nRow, oSettings.aoData[ oSettings.aiDisplay[j] ]._aData, iRowCount, j] );
  1293. anRows.push( nRow );
  1294. iRowCount++;
  1295. /* If there is an open row - and it is attached to this parent - attach it on redraw */
  1296. if ( iOpenRows !== 0 )
  1297. {
  1298. for ( var k=0 ; k<iOpenRows ; k++ )
  1299. {
  1300. if ( nRow == oSettings.aoOpenRows[k].nParent )
  1301. {
  1302. anRows.push( oSettings.aoOpenRows[k].nTr );
  1303. break;
  1304. }
  1305. }
  1306. }
  1307. }
  1308. }
  1309. else
  1310. {
  1311. /* Table is empty - create a row with an empty message in it */
  1312. anRows[ 0 ] = document.createElement( 'tr' );
  1313. if ( oSettings.asStripeClasses[0] )
  1314. {
  1315. anRows[ 0 ].className = oSettings.asStripeClasses[0];
  1316. }
  1317. var oLang = oSettings.oLanguage;
  1318. var sZero = oLang.sZeroRecords;
  1319. if ( oSettings.iDraw == 1 && oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )
  1320. {
  1321. sZero = oLang.sLoadingRecords;
  1322. }
  1323. else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
  1324. {
  1325. sZero = oLang.sEmptyTable;
  1326. }
  1327. var nTd = document.createElement( 'td' );
  1328. nTd.setAttribute( 'valign', "top" );
  1329. nTd.colSpan = _fnVisbleColumns( oSettings );
  1330. nTd.className = oSettings.oClasses.sRowEmpty;
  1331. nTd.innerHTML = _fnInfoMacros( oSettings, sZero );
  1332. anRows[ iRowCount ].appendChild( nTd );
  1333. }
  1334. /* Header and footer callbacks */
  1335. _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
  1336. _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] );
  1337. _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
  1338. _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] );
  1339. /*
  1340. * Need to remove any old row from the display - note we can't just empty the tbody using
  1341. * $().html('') since this will unbind the jQuery event handlers (even although the node
  1342. * still exists!) - equally we can't use innerHTML, since IE throws an exception.
  1343. */
  1344. var
  1345. nAddFrag = document.createDocumentFragment(),
  1346. nRemoveFrag = document.createDocumentFragment(),
  1347. nBodyPar, nTrs;
  1348. if ( oSettings.nTBody )
  1349. {
  1350. nBodyPar = oSettings.nTBody.parentNode;
  1351. nRemoveFrag.appendChild( oSettings.nTBody );
  1352. /* When doing infinite scrolling, only remove child rows when sorting, filtering or start
  1353. * up. When not infinite scroll, always do it.
  1354. */
  1355. if ( !oSettings.oScroll.bInfinite || !oSettings._bInitComplete ||
  1356. oSettings.bSorted || oSettings.bFiltered )
  1357. {
  1358. while( (n = oSettings.nTBody.firstChild) )
  1359. {
  1360. oSettings.nTBody.removeChild( n );
  1361. }
  1362. }
  1363. /* Put the draw table into the dom */
  1364. for ( i=0, iLen=anRows.length ; i<iLen ; i++ )
  1365. {
  1366. nAddFrag.appendChild( anRows[i] );
  1367. }
  1368. oSettings.nTBody.appendChild( nAddFrag );
  1369. if ( nBodyPar !== null )
  1370. {
  1371. nBodyPar.appendChild( oSettings.nTBody );
  1372. }
  1373. }
  1374. /* Call all required callback functions for the end of a draw */
  1375. _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
  1376. /* Draw is complete, sorting and filtering must be as well */
  1377. oSettings.bSorted = false;
  1378. oSettings.bFiltered = false;
  1379. oSettings.bDrawing = false;
  1380. if ( oSettings.oFeatures.bServerSide )
  1381. {
  1382. _fnProcessingDisplay( oSettings, false );
  1383. if ( !oSettings._bInitComplete )
  1384. {
  1385. _fnInitComplete( oSettings );
  1386. }
  1387. }
  1388. }
  1389. /**
  1390. * Redraw the table - taking account of the various features which are enabled
  1391. * @param {object} oSettings dataTables settings object
  1392. * @memberof DataTable#oApi
  1393. */
  1394. function _fnReDraw( oSettings )
  1395. {
  1396. if ( oSettings.oFeatures.bSort )
  1397. {
  1398. /* Sorting will refilter and draw for us */
  1399. _fnSort( oSettings, oSettings.oPreviousSearch );
  1400. }
  1401. else if ( oSettings.oFeatures.bFilter )
  1402. {
  1403. /* Filtering will redraw for us */
  1404. _fnFilterComplete( oSettings, oSettings.oPreviousSearch );
  1405. }
  1406. else
  1407. {
  1408. _fnCalculateEnd( oSettings );
  1409. _fnDraw( oSettings );
  1410. }
  1411. }
  1412. /**
  1413. * Add the options to the page HTML for the table
  1414. * @param {object} oSettings dataTables settings object
  1415. * @memberof DataTable#oApi
  1416. */
  1417. function _fnAddOptionsHtml ( oSettings )
  1418. {
  1419. /*
  1420. * Create a temporary, empty, div which we can later on replace with what we have generated
  1421. * we do it this way to rendering the 'options' html offline - speed :-)
  1422. */
  1423. var nHolding = $('<div></div>')[0];
  1424. oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable );
  1425. /*
  1426. * All DataTables are wrapped in a div
  1427. */
  1428. oSettings.nTableWrapper = $('<div id="'+oSettings.sTableId+'_wrapper" class="'+oSettings.oClasses.sWrapper+'" role="grid"></div>')[0];
  1429. oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
  1430. /* Track where we want to insert the option */
  1431. var nInsertNode = oSettings.nTableWrapper;
  1432. /* Loop over the user set positioning and place the elements as needed */
  1433. var aDom = oSettings.sDom.split('');
  1434. var nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j;
  1435. for ( var i=0 ; i<aDom.length ; i++ )
  1436. {
  1437. iPushFeature = 0;
  1438. cOption = aDom[i];
  1439. if ( cOption == '<' )
  1440. {
  1441. /* New container div */
  1442. nNewNode = $('<div></div>')[0];
  1443. /* Check to see if we should append an id and/or a class name to the container */
  1444. cNext = aDom[i+1];
  1445. if ( cNext == "'" || cNext == '"' )
  1446. {
  1447. sAttr = "";
  1448. j = 2;
  1449. while ( aDom[i+j] != cNext )
  1450. {
  1451. sAttr += aDom[i+j];
  1452. j++;
  1453. }
  1454. /* Replace jQuery UI constants */
  1455. if ( sAttr == "H" )
  1456. {
  1457. sAttr = oSettings.oClasses.sJUIHeader;
  1458. }
  1459. else if ( sAttr == "F" )
  1460. {
  1461. sAttr = oSettings.oClasses.sJUIFooter;
  1462. }
  1463. /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
  1464. * breaks the string into parts and applies them as needed
  1465. */
  1466. if ( sAttr.indexOf('.') != -1 )
  1467. {
  1468. var aSplit = sAttr.split('.');
  1469. nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
  1470. nNewNode.className = aSplit[1];
  1471. }
  1472. else if ( sAttr.charAt(0) == "#" )
  1473. {
  1474. nNewNode.id = sAttr.substr(1, sAttr.length-1);
  1475. }
  1476. else
  1477. {
  1478. nNewNode.className = sAttr;
  1479. }
  1480. i += j; /* Move along the position array */
  1481. }
  1482. nInsertNode.appendChild( nNewNode );
  1483. nInsertNode = nNewNode;
  1484. }
  1485. else if ( cOption == '>' )
  1486. {
  1487. /* End container div */
  1488. nInsertNode = nInsertNode.parentNode;
  1489. }
  1490. else if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange )
  1491. {
  1492. /* Length */
  1493. nTmp = _fnFeatureHtmlLength( oSettings );
  1494. iPushFeature = 1;
  1495. }
  1496. else if ( cOption == 'f' && oSettings.oFeatures.bFilter )
  1497. {
  1498. /* Filter */
  1499. nTmp = _fnFeatureHtmlFilter( oSettings );
  1500. iPushFeature = 1;
  1501. }
  1502. else if ( cOption == 'r' && oSettings.oFeatures.bProcessing )
  1503. {
  1504. /* pRocessing */
  1505. nTmp = _fnFeatureHtmlProcessing( oSettings );
  1506. iPushFeature = 1;
  1507. }
  1508. else if ( cOption == 't' )
  1509. {
  1510. /* Table */
  1511. nTmp = _fnFeatureHtmlTable( oSettings );
  1512. iPushFeature = 1;
  1513. }
  1514. else if ( cOption == 'i' && oSettings.oFeatures.bInfo )
  1515. {
  1516. /* Info */
  1517. nTmp = _fnFeatureHtmlInfo( oSettings );
  1518. iPushFeature = 1;
  1519. }
  1520. else if ( cOption == 'p' && oSettings.oFeatures.bPaginate )
  1521. {
  1522. /* Pagination */
  1523. nTmp = _fnFeatureHtmlPaginate( oSettings );
  1524. iPushFeature = 1;
  1525. }
  1526. else if ( DataTable.ext.aoFeatures.length !== 0 )
  1527. {
  1528. /* Plug-in features */
  1529. var aoFeatures = DataTable.ext.aoFeatures;
  1530. for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
  1531. {
  1532. if ( cOption == aoFeatures[k].cFeature )
  1533. {
  1534. nTmp = aoFeatures[k].fnInit( oSettings );
  1535. if ( nTmp )
  1536. {
  1537. iPushFeature = 1;
  1538. }
  1539. break;
  1540. }
  1541. }
  1542. }
  1543. /* Add to the 2D features array */
  1544. if ( iPushFeature == 1 && nTmp !== null )
  1545. {
  1546. if ( typeof oSettings.aanFeatures[cOption] !== 'object' )
  1547. {
  1548. oSettings.aanFeatures[cOption] = [];
  1549. }
  1550. oSettings.aanFeatures[cOption].push( nTmp );
  1551. nInsertNode.appendChild( nTmp );
  1552. }
  1553. }
  1554. /* Built our DOM structure - replace the holding div with what we want */
  1555. nHolding.parentNode.replaceChild( oSettings.nTableWrapper, nHolding );
  1556. }
  1557. /**
  1558. * Use the DOM source to create up an array of header cells. The idea here is to
  1559. * create a layout grid (array) of rows x columns, which contains a reference
  1560. * to the cell that that point in the grid (regardless of col/rowspan), such that
  1561. * any column / row could be removed and the new grid constructed
  1562. * @param array {object} aLayout Array to store the calculated layout in
  1563. * @param {node} nThead The header/footer element for the table
  1564. * @memberof DataTable#oApi
  1565. */
  1566. function _fnDetectHeader ( aLayout, nThead )
  1567. {
  1568. var nTrs = $(nThead).children('tr');
  1569. var nTr, nCell;
  1570. var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
  1571. var bUnique;
  1572. var fnShiftCol = function ( a, i, j ) {
  1573. var k = a[i];
  1574. while ( k[j] ) {
  1575. j++;
  1576. }
  1577. return j;
  1578. };
  1579. aLayout.splice( 0, aLayout.length );
  1580. /* We know how many rows there are in the layout - so prep it */
  1581. for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  1582. {
  1583. aLayout.push( [] );
  1584. }
  1585. /* Calculate a layout array */
  1586. for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  1587. {
  1588. nTr = nTrs[i];
  1589. iColumn = 0;
  1590. /* For every cell in the row... */
  1591. nCell = nTr.firstChild;
  1592. while ( nCell ) {
  1593. if ( nCell.nodeName.toUpperCase() == "TD" ||
  1594. nCell.nodeName.toUpperCase() == "TH" )
  1595. {
  1596. /* Get the col and rowspan attributes from the DOM and sanitise them */
  1597. iColspan = nCell.getAttribute('colspan') * 1;
  1598. iRowspan = nCell.getAttribute('rowspan') * 1;
  1599. iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
  1600. iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
  1601. /* There might be colspan cells already in this row, so shift our target
  1602. * accordingly
  1603. */
  1604. iColShifted = fnShiftCol( aLayout, i, iColumn );
  1605. /* Cache calculation for unique columns */
  1606. bUnique = iColspan === 1 ? true : false;
  1607. /* If there is col / rowspan, copy the information into the layout grid */
  1608. for ( l=0 ; l<iColspan ; l++ )
  1609. {
  1610. for ( k=0 ; k<iRowspan ; k++ )
  1611. {
  1612. aLayout[i+k][iColShifted+l] = {
  1613. "cell": nCell,
  1614. "unique": bUnique
  1615. };
  1616. aLayout[i+k].nTr = nTr;
  1617. }
  1618. }
  1619. }
  1620. nCell = nCell.nextSibling;
  1621. }
  1622. }
  1623. }
  1624. /**
  1625. * Get an array of unique th elements, one for each column
  1626. * @param {object} oSettings dataTables settings object
  1627. * @param {node} nHeader automatically detect the layout from this node - optional
  1628. * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
  1629. * @returns array {node} aReturn list of unique th's
  1630. * @memberof DataTable#oApi
  1631. */
  1632. function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
  1633. {
  1634. var aReturn = [];
  1635. if ( !aLayout )
  1636. {
  1637. aLayout = oSettings.aoHeader;
  1638. if ( nHeader )
  1639. {
  1640. aLayout = [];
  1641. _fnDetectHeader( aLayout, nHeader );
  1642. }
  1643. }
  1644. for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
  1645. {
  1646. for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
  1647. {
  1648. if ( aLayout[i][j].unique &&
  1649. (!aReturn[j] || !oSettings.bSortCellsTop) )
  1650. {
  1651. aReturn[j] = aLayout[i][j].cell;
  1652. }
  1653. }
  1654. }
  1655. return aReturn;
  1656. }
  1657. /**
  1658. * Update the table using an Ajax call
  1659. * @param {object} oSettings dataTables settings object
  1660. * @returns {boolean} Block the table drawing or not
  1661. * @memberof DataTable#oApi
  1662. */
  1663. function _fnAjaxUpdate( oSettings )
  1664. {
  1665. if ( oSettings.bAjaxDataGet )
  1666. {
  1667. oSettings.iDraw++;
  1668. _fnProcessingDisplay( oSettings, true );
  1669. var iColumns = oSettings.aoColumns.length;
  1670. var aoData = _fnAjaxParameters( oSettings );
  1671. _fnServerParams( oSettings, aoData );
  1672. oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData,
  1673. function(json) {
  1674. _fnAjaxUpdateDraw( oSettings, json );
  1675. }, oSettings );
  1676. return false;
  1677. }
  1678. else
  1679. {
  1680. return true;
  1681. }
  1682. }
  1683. /**
  1684. * Build up the parameters in an object needed for a server-side processing request
  1685. * @param {object} oSettings dataTables settings object
  1686. * @returns {bool} block the table drawing or not
  1687. * @memberof DataTable#oApi
  1688. */
  1689. function _fnAjaxParameters( oSettings )
  1690. {
  1691. var iColumns = oSettings.aoColumns.length;
  1692. var aoData = [], mDataProp, aaSort, aDataSort;
  1693. var i, j;
  1694. aoData.push( { "name": "sEcho", "value": oSettings.iDraw } );
  1695. aoData.push( { "name": "iColumns", "value": iColumns } );
  1696. aoData.push( { "name": "sColumns", "value": _fnColumnOrdering(oSettings) } );
  1697. aoData.push( { "name": "iDisplayStart", "value": oSettings._iDisplayStart } );
  1698. aoData.push( { "name": "iDisplayLength", "value": oSettings.oFeatures.bPaginate !== false ?
  1699. oSettings._iDisplayLength : -1 } );
  1700. for ( i=0 ; i<iColumns ; i++ )
  1701. {
  1702. mDataProp = oSettings.aoColumns[i].mData;
  1703. aoData.push( { "name": "mDataProp_"+i, "value": typeof(mDataProp)==="function" ? 'function' : mDataProp } );
  1704. }
  1705. /* Filtering */
  1706. if ( oSettings.oFeatures.bFilter !== false )
  1707. {
  1708. aoData.push( { "name": "sSearch", "value": oSettings.oPreviousSearch.sSearch } );
  1709. aoData.push( { "name": "bRegex", "value": oSettings.oPreviousSearch.bRegex } );
  1710. for ( i=0 ; i<iColumns ; i++ )
  1711. {
  1712. aoData.push( { "name": "sSearch_"+i, "value": oSettings.aoPreSearchCols[i].sSearch } );
  1713. aoData.push( { "name": "bRegex_"+i, "value": oSettings.aoPreSearchCols[i].bRegex } );
  1714. aoData.push( { "name": "bSearchable_"+i, "value": oSettings.aoColumns[i].bSearchable } );
  1715. }
  1716. }
  1717. /* Sorting */
  1718. if ( oSettings.oFeatures.bSort !== false )
  1719. {
  1720. var iCounter = 0;
  1721. aaSort = ( oSettings.aaSortingFixed !== null ) ?
  1722. oSettings.aaSortingFixed.concat( oSettings.aaSorting ) :
  1723. oSettings.aaSorting.slice();
  1724. for ( i=0 ; i<aaSort.length ; i++ )
  1725. {
  1726. aDataSort = oSettings.aoColumns[ aaSort[i][0] ].aDataSort;
  1727. for ( j=0 ; j<aDataSort.length ; j++ )
  1728. {
  1729. aoData.push( { "name": "iSortCol_"+iCounter, "value": aDataSort[j] } );
  1730. aoData.push( { "name": "sSortDir_"+iCounter, "value": aaSort[i][1] } );
  1731. iCounter++;
  1732. }
  1733. }
  1734. aoData.push( { "name": "iSortingCols", "value": iCounter } );
  1735. for ( i=0 ; i<iColumns ; i++ )
  1736. {
  1737. aoData.push( { "name": "bSortable_"+i, "value": oSettings.aoColumns[i].bSortable } );
  1738. }
  1739. }
  1740. return aoData;
  1741. }
  1742. /**
  1743. * Add Ajax parameters from plug-ins
  1744. * @param {object} oSettings dataTables settings object
  1745. * @param array {objects} aoData name/value pairs to send to the server
  1746. * @memberof DataTable#oApi
  1747. */
  1748. function _fnServerParams( oSettings, aoData )
  1749. {
  1750. _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [aoData] );
  1751. }
  1752. /**
  1753. * Data the data from the server (nuking the old) and redraw the table
  1754. * @param {object} oSettings dataTables settings object
  1755. * @param {object} json json data return from the server.
  1756. * @param {string} json.sEcho Tracking flag for DataTables to match requests
  1757. * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
  1758. * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
  1759. * @param {array} json.aaData The data to display on this page
  1760. * @param {string} [json.sColumns] Column ordering (sName, comma separated)
  1761. * @memberof DataTable#oApi
  1762. */
  1763. function _fnAjaxUpdateDraw ( oSettings, json )
  1764. {
  1765. if ( json.sEcho !== undefined )
  1766. {
  1767. /* Protect against old returns over-writing a new one. Possible when you get
  1768. * very fast interaction, and later queries are completed much faster
  1769. */
  1770. if ( json.sEcho*1 < oSettings.iDraw )
  1771. {
  1772. return;
  1773. }
  1774. else
  1775. {
  1776. oSettings.iDraw = json.sEcho * 1;
  1777. }
  1778. }
  1779. if ( !oSettings.oScroll.bInfinite ||
  1780. (oSettings.oScroll.bInfinite && (oSettings.bSorted || oSettings.bFiltered)) )
  1781. {
  1782. _fnClearTable( oSettings );
  1783. }
  1784. oSettings._iRecordsTotal = parseInt(json.iTotalRecords, 10);
  1785. oSettings._iRecordsDisplay = parseInt(json.iTotalDisplayRecords, 10);
  1786. /* Determine if reordering is required */
  1787. var sOrdering = _fnColumnOrdering(oSettings);
  1788. var bReOrder = (json.sColumns !== undefined && sOrdering !== "" && json.sColumns != sOrdering );
  1789. var aiIndex;
  1790. if ( bReOrder )
  1791. {
  1792. aiIndex = _fnReOrderIndex( oSettings, json.sColumns );
  1793. }
  1794. var aData = _fnGetObjectDataFn( oSettings.sAjaxDataProp )( json );
  1795. for ( var i=0, iLen=aData.length ; i<iLen ; i++ )
  1796. {
  1797. if ( bReOrder )
  1798. {
  1799. /* If we need to re-order, then create a new array with the correct order and add it */
  1800. var aDataSorted = [];
  1801. for ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ )
  1802. {
  1803. aDataSorted.push( aData[i][ aiIndex[j] ] );
  1804. }
  1805. _fnAddData( oSettings, aDataSorted );
  1806. }
  1807. else
  1808. {
  1809. /* No re-order required, sever got it "right" - just straight add */
  1810. _fnAddData( oSettings, aData[i] );
  1811. }
  1812. }
  1813. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  1814. oSettings.bAjaxDataGet = false;
  1815. _fnDraw( oSettings );
  1816. oSettings.bAjaxDataGet = true;
  1817. _fnProcessingDisplay( oSettings, false );
  1818. }
  1819. /**
  1820. * Generate the node required for filtering text
  1821. * @returns {node} Filter control element
  1822. * @param {object} oSettings dataTables settings object
  1823. * @memberof DataTable#oApi
  1824. */
  1825. function _fnFeatureHtmlFilter ( oSettings )
  1826. {
  1827. var oPreviousSearch = oSettings.oPreviousSearch;
  1828. var sSearchStr = oSettings.oLanguage.sSearch;
  1829. sSearchStr = (sSearchStr.indexOf('_INPUT_') !== -1) ?
  1830. sSearchStr.replace('_INPUT_', '<input type="text" />') :
  1831. sSearchStr==="" ? '<input type="text" />' : sSearchStr+' <input type="text" />';
  1832. var nFilter = document.createElement( 'div' );
  1833. nFilter.className = oSettings.oClasses.sFilter;
  1834. nFilter.innerHTML = '<label>'+sSearchStr+'</label>';
  1835. if ( !oSettings.aanFeatures.f )
  1836. {
  1837. nFilter.id = oSettings.sTableId+'_filter';
  1838. }
  1839. var jqFilter = $('input[type="text"]', nFilter);
  1840. // Store a reference to the input element, so other input elements could be
  1841. // added to the filter wrapper if needed (submit button for example)
  1842. nFilter._DT_Input = jqFilter[0];
  1843. jqFilter.val( oPreviousSearch.sSearch.replace('"','&quot;') );
  1844. jqFilter.bind( 'keyup.DT', function(e) {
  1845. /* Update all other filter input elements for the new display */
  1846. var n = oSettings.aanFeatures.f;
  1847. var val = this.value==="" ? "" : this.value; // mental IE8 fix :-(
  1848. for ( var i=0, iLen=n.length ; i<iLen ; i++ )
  1849. {
  1850. if ( n[i] != $(this).parents('div.dataTables_filter')[0] )
  1851. {
  1852. $(n[i]._DT_Input).val( val );
  1853. }
  1854. }
  1855. /* Now do the filter */
  1856. if ( val != oPreviousSearch.sSearch )
  1857. {
  1858. _fnFilterComplete( oSettings, {
  1859. "sSearch": val,
  1860. "bRegex": oPreviousSearch.bRegex,
  1861. "bSmart": oPreviousSearch.bSmart ,
  1862. "bCaseInsensitive": oPreviousSearch.bCaseInsensitive
  1863. } );
  1864. }
  1865. } );
  1866. jqFilter
  1867. .attr('aria-controls', oSettings.sTableId)
  1868. .bind( 'keypress.DT', function(e) {
  1869. /* Prevent form submission */
  1870. if ( e.keyCode == 13 )
  1871. {
  1872. return false;
  1873. }
  1874. }
  1875. );
  1876. return nFilter;
  1877. }
  1878. /**
  1879. * Filter the table using both the global filter and column based filtering
  1880. * @param {object} oSettings dataTables settings object
  1881. * @param {object} oSearch search information
  1882. * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
  1883. * @memberof DataTable#oApi
  1884. */
  1885. function _fnFilterComplete ( oSettings, oInput, iForce )
  1886. {
  1887. var oPrevSearch = oSettings.oPreviousSearch;
  1888. var aoPrevSearch = oSettings.aoPreSearchCols;
  1889. var fnSaveFilter = function ( oFilter ) {
  1890. /* Save the filtering values */
  1891. oPrevSearch.sSearch = oFilter.sSearch;
  1892. oPrevSearch.bRegex = oFilter.bRegex;
  1893. oPrevSearch.bSmart = oFilter.bSmart;
  1894. oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
  1895. };
  1896. /* In server-side processing all filtering is done by the server, so no point hanging around here */
  1897. if ( !oSettings.oFeatures.bServerSide )
  1898. {
  1899. /* Global filter */
  1900. _fnFilter( oSettings, oInput.sSearch, iForce, oInput.bRegex, oInput.bSmart, oInput.bCaseInsensitive );
  1901. fnSaveFilter( oInput );
  1902. /* Now do the individual column filter */
  1903. for ( var i=0 ; i<oSettings.aoPreSearchCols.length ; i++ )
  1904. {
  1905. _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, aoPrevSearch[i].bRegex,
  1906. aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
  1907. }
  1908. /* Custom filtering */
  1909. _fnFilterCustom( oSettings );
  1910. }
  1911. else
  1912. {
  1913. fnSaveFilter( oInput );
  1914. }
  1915. /* Tell the draw function we have been filtering */
  1916. oSettings.bFiltered = true;
  1917. $(oSettings.oInstance).trigger('filter', oSettings);
  1918. /* Redraw the table */
  1919. oSettings._iDisplayStart = 0;
  1920. _fnCalculateEnd( oSettings );
  1921. _fnDraw( oSettings );
  1922. /* Rebuild search array 'offline' */
  1923. _fnBuildSearchArray( oSettings, 0 );
  1924. }
  1925. /**
  1926. * Apply custom filtering functions
  1927. * @param {object} oSettings dataTables settings object
  1928. * @memberof DataTable#oApi
  1929. */
  1930. function _fnFilterCustom( oSettings )
  1931. {
  1932. var afnFilters = DataTable.ext.afnFiltering;
  1933. var aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' );
  1934. for ( var i=0, iLen=afnFilters.length ; i<iLen ; i++ )
  1935. {
  1936. var iCorrector = 0;
  1937. for ( var j=0, jLen=oSettings.aiDisplay.length ; j<jLen ; j++ )
  1938. {
  1939. var iDisIndex = oSettings.aiDisplay[j-iCorrector];
  1940. var bTest = afnFilters[i](
  1941. oSettings,
  1942. _fnGetRowData( oSettings, iDisIndex, 'filter', aiFilterColumns ),
  1943. iDisIndex
  1944. );
  1945. /* Check if we should use this row based on the filtering function */
  1946. if ( !bTest )
  1947. {
  1948. oSettings.aiDisplay.splice( j-iCorrector, 1 );
  1949. iCorrector++;
  1950. }
  1951. }
  1952. }
  1953. }
  1954. /**
  1955. * Filter the table on a per-column basis
  1956. * @param {object} oSettings dataTables settings object
  1957. * @param {string} sInput string to filter on
  1958. * @param {int} iColumn column to filter
  1959. * @param {bool} bRegex treat search string as a regular expression or not
  1960. * @param {bool} bSmart use smart filtering or not
  1961. * @param {bool} bCaseInsensitive Do case insenstive matching or not
  1962. * @memberof DataTable#oApi
  1963. */
  1964. function _fnFilterColumn ( oSettings, sInput, iColumn, bRegex, bSmart, bCaseInsensitive )
  1965. {
  1966. if ( sInput === "" )
  1967. {
  1968. return;
  1969. }
  1970. var iIndexCorrector = 0;
  1971. var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );
  1972. for ( var i=oSettings.aiDisplay.length-1 ; i>=0 ; i-- )
  1973. {
  1974. var sData = _fnDataToSearch( _fnGetCellData( oSettings, oSettings.aiDisplay[i], iColumn, 'filter' ),
  1975. oSettings.aoColumns[iColumn].sType );
  1976. if ( ! rpSearch.test( sData ) )
  1977. {
  1978. oSettings.aiDisplay.splice( i, 1 );
  1979. iIndexCorrector++;
  1980. }
  1981. }
  1982. }
  1983. /**
  1984. * Filter the data table based on user input and draw the table
  1985. * @param {object} oSettings dataTables settings object
  1986. * @param {string} sInput string to filter on
  1987. * @param {int} iForce optional - force a research of the master array (1) or not (undefined or 0)
  1988. * @param {bool} bRegex treat as a regular expression or not
  1989. * @param {bool} bSmart perform smart filtering or not
  1990. * @param {bool} bCaseInsensitive Do case insenstive matching or not
  1991. * @memberof DataTable#oApi
  1992. */
  1993. function _fnFilter( oSettings, sInput, iForce, bRegex, bSmart, bCaseInsensitive )
  1994. {
  1995. var i;
  1996. var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );
  1997. var oPrevSearch = oSettings.oPreviousSearch;
  1998. /* Check if we are forcing or not - optional parameter */
  1999. if ( !iForce )
  2000. {
  2001. iForce = 0;
  2002. }
  2003. /* Need to take account of custom filtering functions - always filter */
  2004. if ( DataTable.ext.afnFiltering.length !== 0 )
  2005. {
  2006. iForce = 1;
  2007. }
  2008. /*
  2009. * If the input is blank - we want the full data set
  2010. */
  2011. if ( sInput.length <= 0 )
  2012. {
  2013. oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
  2014. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  2015. }
  2016. else
  2017. {
  2018. /*
  2019. * We are starting a new search or the new search string is smaller
  2020. * then the old one (i.e. delete). Search from the master array
  2021. */
  2022. if ( oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length ||
  2023. oPrevSearch.sSearch.length > sInput.length || iForce == 1 ||
  2024. sInput.indexOf(oPrevSearch.sSearch) !== 0 )
  2025. {
  2026. /* Nuke the old display array - we are going to rebuild it */
  2027. oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
  2028. /* Force a rebuild of the search array */
  2029. _fnBuildSearchArray( oSettings, 1 );
  2030. /* Search through all records to populate the search array
  2031. * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1
  2032. * mapping
  2033. */
  2034. for ( i=0 ; i<oSettings.aiDisplayMaster.length ; i++ )
  2035. {
  2036. if ( rpSearch.test(oSettings.asDataSearch[i]) )
  2037. {
  2038. oSettings.aiDisplay.push( oSettings.aiDisplayMaster[i] );
  2039. }
  2040. }
  2041. }
  2042. else
  2043. {
  2044. /* Using old search array - refine it - do it this way for speed
  2045. * Don't have to search the whole master array again
  2046. */
  2047. var iIndexCorrector = 0;
  2048. /* Search the current results */
  2049. for ( i=0 ; i<oSettings.asDataSearch.length ; i++ )
  2050. {
  2051. if ( ! rpSearch.test(oSettings.asDataSearch[i]) )
  2052. {
  2053. oSettings.aiDisplay.splice( i-iIndexCorrector, 1 );
  2054. iIndexCorrector++;
  2055. }
  2056. }
  2057. }
  2058. }
  2059. }
  2060. /**
  2061. * Create an array which can be quickly search through
  2062. * @param {object} oSettings dataTables settings object
  2063. * @param {int} iMaster use the master data array - optional
  2064. * @memberof DataTable#oApi
  2065. */
  2066. function _fnBuildSearchArray ( oSettings, iMaster )
  2067. {
  2068. if ( !oSettings.oFeatures.bServerSide )
  2069. {
  2070. /* Clear out the old data */
  2071. oSettings.asDataSearch = [];
  2072. var aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' );
  2073. var aiIndex = (iMaster===1) ?
  2074. oSettings.aiDisplayMaster :
  2075. oSettings.aiDisplay;
  2076. for ( var i=0, iLen=aiIndex.length ; i<iLen ; i++ )
  2077. {
  2078. oSettings.asDataSearch[i] = _fnBuildSearchRow(
  2079. oSettings,
  2080. _fnGetRowData( oSettings, aiIndex[i], 'filter', aiFilterColumns )
  2081. );
  2082. }
  2083. }
  2084. }
  2085. /**
  2086. * Create a searchable string from a single data row
  2087. * @param {object} oSettings dataTables settings object
  2088. * @param {array} aData Row data array to use for the data to search
  2089. * @memberof DataTable#oApi
  2090. */
  2091. function _fnBuildSearchRow( oSettings, aData )
  2092. {
  2093. var sSearch = aData.join(' ');
  2094. /* If it looks like there is an HTML entity in the string, attempt to decode it */
  2095. if ( sSearch.indexOf('&') !== -1 )
  2096. {
  2097. sSearch = $('<div>').html(sSearch).text();
  2098. }
  2099. // Strip newline characters
  2100. return sSearch.replace( /[\n\r]/g, " " );
  2101. }
  2102. /**
  2103. * Build a regular expression object suitable for searching a table
  2104. * @param {string} sSearch string to search for
  2105. * @param {bool} bRegex treat as a regular expression or not
  2106. * @param {bool} bSmart perform smart filtering or not
  2107. * @param {bool} bCaseInsensitive Do case insensitive matching or not
  2108. * @returns {RegExp} constructed object
  2109. * @memberof DataTable#oApi
  2110. */
  2111. function _fnFilterCreateSearch( sSearch, bRegex, bSmart, bCaseInsensitive )
  2112. {
  2113. var asSearch, sRegExpString;
  2114. if ( bSmart )
  2115. {
  2116. /* Generate the regular expression to use. Something along the lines of:
  2117. * ^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$
  2118. */
  2119. asSearch = bRegex ? sSearch.split( ' ' ) : _fnEscapeRegex( sSearch ).split( ' ' );
  2120. sRegExpString = '^(?=.*?'+asSearch.join( ')(?=.*?' )+').*$';
  2121. return new RegExp( sRegExpString, bCaseInsensitive ? "i" : "" );
  2122. }
  2123. else
  2124. {
  2125. sSearch = bRegex ? sSearch : _fnEscapeRegex( sSearch );
  2126. return new RegExp( sSearch, bCaseInsensitive ? "i" : "" );
  2127. }
  2128. }
  2129. /**
  2130. * Convert raw data into something that the user can search on
  2131. * @param {string} sData data to be modified
  2132. * @param {string} sType data type
  2133. * @returns {string} search string
  2134. * @memberof DataTable#oApi
  2135. */
  2136. function _fnDataToSearch ( sData, sType )
  2137. {
  2138. if ( typeof DataTable.ext.ofnSearch[sType] === "function" )
  2139. {
  2140. return DataTable.ext.ofnSearch[sType]( sData );
  2141. }
  2142. else if ( sData === null )
  2143. {
  2144. return '';
  2145. }
  2146. else if ( sType == "html" )
  2147. {
  2148. return sData.replace(/[\r\n]/g," ").replace( /<.*?>/g, "" );
  2149. }
  2150. else if ( typeof sData === "string" )
  2151. {
  2152. return sData.replace(/[\r\n]/g," ");
  2153. }
  2154. return sData;
  2155. }
  2156. /**
  2157. * scape a string such that it can be used in a regular expression
  2158. * @param {string} sVal string to escape
  2159. * @returns {string} escaped string
  2160. * @memberof DataTable#oApi
  2161. */
  2162. function _fnEscapeRegex ( sVal )
  2163. {
  2164. var acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ];
  2165. var reReplace = new RegExp( '(\\' + acEscape.join('|\\') + ')', 'g' );
  2166. return sVal.replace(reReplace, '\\$1');
  2167. }
  2168. /**
  2169. * Generate the node required for the info display
  2170. * @param {object} oSettings dataTables settings object
  2171. * @returns {node} Information element
  2172. * @memberof DataTable#oApi
  2173. */
  2174. function _fnFeatureHtmlInfo ( oSettings )
  2175. {
  2176. var nInfo = document.createElement( 'div' );
  2177. nInfo.className = oSettings.oClasses.sInfo;
  2178. /* Actions that are to be taken once only for this feature */
  2179. if ( !oSettings.aanFeatures.i )
  2180. {
  2181. /* Add draw callback */
  2182. oSettings.aoDrawCallback.push( {
  2183. "fn": _fnUpdateInfo,
  2184. "sName": "information"
  2185. } );
  2186. /* Add id */
  2187. nInfo.id = oSettings.sTableId+'_info';
  2188. }
  2189. oSettings.nTable.setAttribute( 'aria-describedby', oSettings.sTableId+'_info' );
  2190. return nInfo;
  2191. }
  2192. /**
  2193. * Update the information elements in the display
  2194. * @param {object} oSettings dataTables settings object
  2195. * @memberof DataTable#oApi
  2196. */
  2197. function _fnUpdateInfo ( oSettings )
  2198. {
  2199. /* Show information about the table */
  2200. if ( !oSettings.oFeatures.bInfo || oSettings.aanFeatures.i.length === 0 )
  2201. {
  2202. return;
  2203. }
  2204. var
  2205. oLang = oSettings.oLanguage,
  2206. iStart = oSettings._iDisplayStart+1,
  2207. iEnd = oSettings.fnDisplayEnd(),
  2208. iMax = oSettings.fnRecordsTotal(),
  2209. iTotal = oSettings.fnRecordsDisplay(),
  2210. sOut;
  2211. if ( iTotal === 0 )
  2212. {
  2213. /* Empty record set */
  2214. sOut = oLang.sInfoEmpty;
  2215. }
  2216. else {
  2217. /* Normal record set */
  2218. sOut = oLang.sInfo;
  2219. }
  2220. if ( iTotal != iMax )
  2221. {
  2222. /* Record set after filtering */
  2223. sOut += ' ' + oLang.sInfoFiltered;
  2224. }
  2225. // Convert the macros
  2226. sOut += oLang.sInfoPostFix;
  2227. sOut = _fnInfoMacros( oSettings, sOut );
  2228. if ( oLang.fnInfoCallback !== null )
  2229. {
  2230. sOut = oLang.fnInfoCallback.call( oSettings.oInstance,
  2231. oSettings, iStart, iEnd, iMax, iTotal, sOut );
  2232. }
  2233. var n = oSettings.aanFeatures.i;
  2234. for ( var i=0, iLen=n.length ; i<iLen ; i++ )
  2235. {
  2236. $(n[i]).html( sOut );
  2237. }
  2238. }
  2239. function _fnInfoMacros ( oSettings, str )
  2240. {
  2241. var
  2242. iStart = oSettings._iDisplayStart+1,
  2243. sStart = oSettings.fnFormatNumber( iStart ),
  2244. iEnd = oSettings.fnDisplayEnd(),
  2245. sEnd = oSettings.fnFormatNumber( iEnd ),
  2246. iTotal = oSettings.fnRecordsDisplay(),
  2247. sTotal = oSettings.fnFormatNumber( iTotal ),
  2248. iMax = oSettings.fnRecordsTotal(),
  2249. sMax = oSettings.fnFormatNumber( iMax );
  2250. // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
  2251. // internally
  2252. if ( oSettings.oScroll.bInfinite )
  2253. {
  2254. sStart = oSettings.fnFormatNumber( 1 );
  2255. }
  2256. return str.
  2257. replace(/_START_/g, sStart).
  2258. replace(/_END_/g, sEnd).
  2259. replace(/_TOTAL_/g, sTotal).
  2260. replace(/_MAX_/g, sMax);
  2261. }
  2262. /**
  2263. * Draw the table for the first time, adding all required features
  2264. * @param {object} oSettings dataTables settings object
  2265. * @memberof DataTable#oApi
  2266. */
  2267. function _fnInitialise ( oSettings )
  2268. {
  2269. var i, iLen, iAjaxStart=oSettings.iInitDisplayStart;
  2270. /* Ensure that the table data is fully initialised */
  2271. if ( oSettings.bInitialised === false )
  2272. {
  2273. setTimeout( function(){ _fnInitialise( oSettings ); }, 200 );
  2274. return;
  2275. }
  2276. /* Show the display HTML options */
  2277. _fnAddOptionsHtml( oSettings );
  2278. /* Build and draw the header / footer for the table */
  2279. _fnBuildHead( oSettings );
  2280. _fnDrawHead( oSettings, oSettings.aoHeader );
  2281. if ( oSettings.nTFoot )
  2282. {
  2283. _fnDrawHead( oSettings, oSettings.aoFooter );
  2284. }
  2285. /* Okay to show that something is going on now */
  2286. _fnProcessingDisplay( oSettings, true );
  2287. /* Calculate sizes for columns */
  2288. if ( oSettings.oFeatures.bAutoWidth )
  2289. {
  2290. _fnCalculateColumnWidths( oSettings );
  2291. }
  2292. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  2293. {
  2294. if ( oSettings.aoColumns[i].sWidth !== null )
  2295. {
  2296. oSettings.aoColumns[i].nTh.style.width = _fnStringToCss( oSettings.aoColumns[i].sWidth );
  2297. }
  2298. }
  2299. /* If there is default sorting required - let's do it. The sort function will do the
  2300. * drawing for us. Otherwise we draw the table regardless of the Ajax source - this allows
  2301. * the table to look initialised for Ajax sourcing data (show 'loading' message possibly)
  2302. */
  2303. if ( oSettings.oFeatures.bSort )
  2304. {
  2305. _fnSort( oSettings );
  2306. }
  2307. else if ( oSettings.oFeatures.bFilter )
  2308. {
  2309. _fnFilterComplete( oSettings, oSettings.oPreviousSearch );
  2310. }
  2311. else
  2312. {
  2313. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  2314. _fnCalculateEnd( oSettings );
  2315. _fnDraw( oSettings );
  2316. }
  2317. /* if there is an ajax source load the data */
  2318. if ( oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )
  2319. {
  2320. var aoData = [];
  2321. _fnServerParams( oSettings, aoData );
  2322. oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData, function(json) {
  2323. var aData = (oSettings.sAjaxDataProp !== "") ?
  2324. _fnGetObjectDataFn( oSettings.sAjaxDataProp )(json) : json;
  2325. /* Got the data - add it to the table */
  2326. for ( i=0 ; i<aData.length ; i++ )
  2327. {
  2328. _fnAddData( oSettings, aData[i] );
  2329. }
  2330. /* Reset the init display for cookie saving. We've already done a filter, and
  2331. * therefore cleared it before. So we need to make it appear 'fresh'
  2332. */
  2333. oSettings.iInitDisplayStart = iAjaxStart;
  2334. if ( oSettings.oFeatures.bSort )
  2335. {
  2336. _fnSort( oSettings );
  2337. }
  2338. else
  2339. {
  2340. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  2341. _fnCalculateEnd( oSettings );
  2342. _fnDraw( oSettings );
  2343. }
  2344. _fnProcessingDisplay( oSettings, false );
  2345. _fnInitComplete( oSettings, json );
  2346. }, oSettings );
  2347. return;
  2348. }
  2349. /* Server-side processing initialisation complete is done at the end of _fnDraw */
  2350. if ( !oSettings.oFeatures.bServerSide )
  2351. {
  2352. _fnProcessingDisplay( oSettings, false );
  2353. _fnInitComplete( oSettings );
  2354. }
  2355. }
  2356. /**
  2357. * Draw the table for the first time, adding all required features
  2358. * @param {object} oSettings dataTables settings object
  2359. * @param {object} [json] JSON from the server that completed the table, if using Ajax source
  2360. * with client-side processing (optional)
  2361. * @memberof DataTable#oApi
  2362. */
  2363. function _fnInitComplete ( oSettings, json )
  2364. {
  2365. oSettings._bInitComplete = true;
  2366. _fnCallbackFire( oSettings, 'aoInitComplete', 'init', [oSettings, json] );
  2367. }
  2368. /**
  2369. * Language compatibility - when certain options are given, and others aren't, we
  2370. * need to duplicate the values over, in order to provide backwards compatibility
  2371. * with older language files.
  2372. * @param {object} oSettings dataTables settings object
  2373. * @memberof DataTable#oApi
  2374. */
  2375. function _fnLanguageCompat( oLanguage )
  2376. {
  2377. var oDefaults = DataTable.defaults.oLanguage;
  2378. /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
  2379. * sZeroRecords - assuming that is given.
  2380. */
  2381. if ( !oLanguage.sEmptyTable && oLanguage.sZeroRecords &&
  2382. oDefaults.sEmptyTable === "No data available in table" )
  2383. {
  2384. _fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sEmptyTable' );
  2385. }
  2386. /* Likewise with loading records */
  2387. if ( !oLanguage.sLoadingRecords && oLanguage.sZeroRecords &&
  2388. oDefaults.sLoadingRecords === "Loading..." )
  2389. {
  2390. _fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sLoadingRecords' );
  2391. }
  2392. }
  2393. /**
  2394. * Generate the node required for user display length changing
  2395. * @param {object} oSettings dataTables settings object
  2396. * @returns {node} Display length feature node
  2397. * @memberof DataTable#oApi
  2398. */
  2399. function _fnFeatureHtmlLength ( oSettings )
  2400. {
  2401. if ( oSettings.oScroll.bInfinite )
  2402. {
  2403. return null;
  2404. }
  2405. /* This can be overruled by not using the _MENU_ var/macro in the language variable */
  2406. var sName = 'name="'+oSettings.sTableId+'_length"';
  2407. var sStdMenu = '<select size="1" '+sName+'>';
  2408. var i, iLen;
  2409. var aLengthMenu = oSettings.aLengthMenu;
  2410. if ( aLengthMenu.length == 2 && typeof aLengthMenu[0] === 'object' &&
  2411. typeof aLengthMenu[1] === 'object' )
  2412. {
  2413. for ( i=0, iLen=aLengthMenu[0].length ; i<iLen ; i++ )
  2414. {
  2415. sStdMenu += '<option value="'+aLengthMenu[0][i]+'">'+aLengthMenu[1][i]+'</option>';
  2416. }
  2417. }
  2418. else
  2419. {
  2420. for ( i=0, iLen=aLengthMenu.length ; i<iLen ; i++ )
  2421. {
  2422. sStdMenu += '<option value="'+aLengthMenu[i]+'">'+aLengthMenu[i]+'</option>';
  2423. }
  2424. }
  2425. sStdMenu += '</select>';
  2426. var nLength = document.createElement( 'div' );
  2427. if ( !oSettings.aanFeatures.l )
  2428. {
  2429. nLength.id = oSettings.sTableId+'_length';
  2430. }
  2431. nLength.className = oSettings.oClasses.sLength;
  2432. nLength.innerHTML = '<label>'+oSettings.oLanguage.sLengthMenu.replace( '_MENU_', sStdMenu )+'</label>';
  2433. /*
  2434. * Set the length to the current display length - thanks to Andrea Pavlovic for this fix,
  2435. * and Stefan Skopnik for fixing the fix!
  2436. */
  2437. $('select option[value="'+oSettings._iDisplayLength+'"]', nLength).attr("selected", true);
  2438. $('select', nLength).bind( 'change.DT', function(e) {
  2439. var iVal = $(this).val();
  2440. /* Update all other length options for the new display */
  2441. var n = oSettings.aanFeatures.l;
  2442. for ( i=0, iLen=n.length ; i<iLen ; i++ )
  2443. {
  2444. if ( n[i] != this.parentNode )
  2445. {
  2446. $('select', n[i]).val( iVal );
  2447. }
  2448. }
  2449. /* Redraw the table */
  2450. oSettings._iDisplayLength = parseInt(iVal, 10);
  2451. _fnCalculateEnd( oSettings );
  2452. /* If we have space to show extra rows (backing up from the end point - then do so */
  2453. if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() )
  2454. {
  2455. oSettings._iDisplayStart = oSettings.fnDisplayEnd() - oSettings._iDisplayLength;
  2456. if ( oSettings._iDisplayStart < 0 )
  2457. {
  2458. oSettings._iDisplayStart = 0;
  2459. }
  2460. }
  2461. if ( oSettings._iDisplayLength == -1 )
  2462. {
  2463. oSettings._iDisplayStart = 0;
  2464. }
  2465. _fnDraw( oSettings );
  2466. } );
  2467. $('select', nLength).attr('aria-controls', oSettings.sTableId);
  2468. return nLength;
  2469. }
  2470. /**
  2471. * Recalculate the end point based on the start point
  2472. * @param {object} oSettings dataTables settings object
  2473. * @memberof DataTable#oApi
  2474. */
  2475. function _fnCalculateEnd( oSettings )
  2476. {
  2477. if ( oSettings.oFeatures.bPaginate === false )
  2478. {
  2479. oSettings._iDisplayEnd = oSettings.aiDisplay.length;
  2480. }
  2481. else
  2482. {
  2483. /* Set the end point of the display - based on how many elements there are
  2484. * still to display
  2485. */
  2486. if ( oSettings._iDisplayStart + oSettings._iDisplayLength > oSettings.aiDisplay.length ||
  2487. oSettings._iDisplayLength == -1 )
  2488. {
  2489. oSettings._iDisplayEnd = oSettings.aiDisplay.length;
  2490. }
  2491. else
  2492. {
  2493. oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength;
  2494. }
  2495. }
  2496. }
  2497. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2498. * Note that most of the paging logic is done in
  2499. * DataTable.ext.oPagination
  2500. */
  2501. /**
  2502. * Generate the node required for default pagination
  2503. * @param {object} oSettings dataTables settings object
  2504. * @returns {node} Pagination feature node
  2505. * @memberof DataTable#oApi
  2506. */
  2507. function _fnFeatureHtmlPaginate ( oSettings )
  2508. {
  2509. if ( oSettings.oScroll.bInfinite )
  2510. {
  2511. return null;
  2512. }
  2513. var nPaginate = document.createElement( 'div' );
  2514. nPaginate.className = oSettings.oClasses.sPaging+oSettings.sPaginationType;
  2515. DataTable.ext.oPagination[ oSettings.sPaginationType ].fnInit( oSettings, nPaginate,
  2516. function( oSettings ) {
  2517. _fnCalculateEnd( oSettings );
  2518. _fnDraw( oSettings );
  2519. }
  2520. );
  2521. /* Add a draw callback for the pagination on first instance, to update the paging display */
  2522. if ( !oSettings.aanFeatures.p )
  2523. {
  2524. oSettings.aoDrawCallback.push( {
  2525. "fn": function( oSettings ) {
  2526. DataTable.ext.oPagination[ oSettings.sPaginationType ].fnUpdate( oSettings, function( oSettings ) {
  2527. _fnCalculateEnd( oSettings );
  2528. _fnDraw( oSettings );
  2529. } );
  2530. },
  2531. "sName": "pagination"
  2532. } );
  2533. }
  2534. return nPaginate;
  2535. }
  2536. /**
  2537. * Alter the display settings to change the page
  2538. * @param {object} oSettings dataTables settings object
  2539. * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
  2540. * or page number to jump to (integer)
  2541. * @returns {bool} true page has changed, false - no change (no effect) eg 'first' on page 1
  2542. * @memberof DataTable#oApi
  2543. */
  2544. function _fnPageChange ( oSettings, mAction )
  2545. {
  2546. var iOldStart = oSettings._iDisplayStart;
  2547. if ( typeof mAction === "number" )
  2548. {
  2549. oSettings._iDisplayStart = mAction * oSettings._iDisplayLength;
  2550. if ( oSettings._iDisplayStart > oSettings.fnRecordsDisplay() )
  2551. {
  2552. oSettings._iDisplayStart = 0;
  2553. }
  2554. }
  2555. else if ( mAction == "first" )
  2556. {
  2557. oSettings._iDisplayStart = 0;
  2558. }
  2559. else if ( mAction == "previous" )
  2560. {
  2561. oSettings._iDisplayStart = oSettings._iDisplayLength>=0 ?
  2562. oSettings._iDisplayStart - oSettings._iDisplayLength :
  2563. 0;
  2564. /* Correct for under-run */
  2565. if ( oSettings._iDisplayStart < 0 )
  2566. {
  2567. oSettings._iDisplayStart = 0;
  2568. }
  2569. }
  2570. else if ( mAction == "next" )
  2571. {
  2572. if ( oSettings._iDisplayLength >= 0 )
  2573. {
  2574. /* Make sure we are not over running the display array */
  2575. if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() )
  2576. {
  2577. oSettings._iDisplayStart += oSettings._iDisplayLength;
  2578. }
  2579. }
  2580. else
  2581. {
  2582. oSettings._iDisplayStart = 0;
  2583. }
  2584. }
  2585. else if ( mAction == "last" )
  2586. {
  2587. if ( oSettings._iDisplayLength >= 0 )
  2588. {
  2589. var iPages = parseInt( (oSettings.fnRecordsDisplay()-1) / oSettings._iDisplayLength, 10 ) + 1;
  2590. oSettings._iDisplayStart = (iPages-1) * oSettings._iDisplayLength;
  2591. }
  2592. else
  2593. {
  2594. oSettings._iDisplayStart = 0;
  2595. }
  2596. }
  2597. else
  2598. {
  2599. _fnLog( oSettings, 0, "Unknown paging action: "+mAction );
  2600. }
  2601. $(oSettings.oInstance).trigger('page', oSettings);
  2602. return iOldStart != oSettings._iDisplayStart;
  2603. }
  2604. /**
  2605. * Generate the node required for the processing node
  2606. * @param {object} oSettings dataTables settings object
  2607. * @returns {node} Processing element
  2608. * @memberof DataTable#oApi
  2609. */
  2610. function _fnFeatureHtmlProcessing ( oSettings )
  2611. {
  2612. var nProcessing = document.createElement( 'div' );
  2613. if ( !oSettings.aanFeatures.r )
  2614. {
  2615. nProcessing.id = oSettings.sTableId+'_processing';
  2616. }
  2617. nProcessing.innerHTML = oSettings.oLanguage.sProcessing;
  2618. nProcessing.className = oSettings.oClasses.sProcessing;
  2619. oSettings.nTable.parentNode.insertBefore( nProcessing, oSettings.nTable );
  2620. return nProcessing;
  2621. }
  2622. /**
  2623. * Display or hide the processing indicator
  2624. * @param {object} oSettings dataTables settings object
  2625. * @param {bool} bShow Show the processing indicator (true) or not (false)
  2626. * @memberof DataTable#oApi
  2627. */
  2628. function _fnProcessingDisplay ( oSettings, bShow )
  2629. {
  2630. if ( oSettings.oFeatures.bProcessing )
  2631. {
  2632. var an = oSettings.aanFeatures.r;
  2633. for ( var i=0, iLen=an.length ; i<iLen ; i++ )
  2634. {
  2635. an[i].style.visibility = bShow ? "visible" : "hidden";
  2636. }
  2637. }
  2638. $(oSettings.oInstance).trigger('processing', [oSettings, bShow]);
  2639. }
  2640. /**
  2641. * Add any control elements for the table - specifically scrolling
  2642. * @param {object} oSettings dataTables settings object
  2643. * @returns {node} Node to add to the DOM
  2644. * @memberof DataTable#oApi
  2645. */
  2646. function _fnFeatureHtmlTable ( oSettings )
  2647. {
  2648. /* Check if scrolling is enabled or not - if not then leave the DOM unaltered */
  2649. if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" )
  2650. {
  2651. return oSettings.nTable;
  2652. }
  2653. /*
  2654. * The HTML structure that we want to generate in this function is:
  2655. * div - nScroller
  2656. * div - nScrollHead
  2657. * div - nScrollHeadInner
  2658. * table - nScrollHeadTable
  2659. * thead - nThead
  2660. * div - nScrollBody
  2661. * table - oSettings.nTable
  2662. * thead - nTheadSize
  2663. * tbody - nTbody
  2664. * div - nScrollFoot
  2665. * div - nScrollFootInner
  2666. * table - nScrollFootTable
  2667. * tfoot - nTfoot
  2668. */
  2669. var
  2670. nScroller = document.createElement('div'),
  2671. nScrollHead = document.createElement('div'),
  2672. nScrollHeadInner = document.createElement('div'),
  2673. nScrollBody = document.createElement('div'),
  2674. nScrollFoot = document.createElement('div'),
  2675. nScrollFootInner = document.createElement('div'),
  2676. nScrollHeadTable = oSettings.nTable.cloneNode(false),
  2677. nScrollFootTable = oSettings.nTable.cloneNode(false),
  2678. nThead = oSettings.nTable.getElementsByTagName('thead')[0],
  2679. nTfoot = oSettings.nTable.getElementsByTagName('tfoot').length === 0 ? null :
  2680. oSettings.nTable.getElementsByTagName('tfoot')[0],
  2681. oClasses = oSettings.oClasses;
  2682. nScrollHead.appendChild( nScrollHeadInner );
  2683. nScrollFoot.appendChild( nScrollFootInner );
  2684. nScrollBody.appendChild( oSettings.nTable );
  2685. nScroller.appendChild( nScrollHead );
  2686. nScroller.appendChild( nScrollBody );
  2687. nScrollHeadInner.appendChild( nScrollHeadTable );
  2688. nScrollHeadTable.appendChild( nThead );
  2689. if ( nTfoot !== null )
  2690. {
  2691. nScroller.appendChild( nScrollFoot );
  2692. nScrollFootInner.appendChild( nScrollFootTable );
  2693. nScrollFootTable.appendChild( nTfoot );
  2694. }
  2695. nScroller.className = oClasses.sScrollWrapper;
  2696. nScrollHead.className = oClasses.sScrollHead;
  2697. nScrollHeadInner.className = oClasses.sScrollHeadInner;
  2698. nScrollBody.className = oClasses.sScrollBody;
  2699. nScrollFoot.className = oClasses.sScrollFoot;
  2700. nScrollFootInner.className = oClasses.sScrollFootInner;
  2701. if ( oSettings.oScroll.bAutoCss )
  2702. {
  2703. nScrollHead.style.overflow = "hidden";
  2704. nScrollHead.style.position = "relative";
  2705. nScrollFoot.style.overflow = "hidden";
  2706. nScrollBody.style.overflow = "auto";
  2707. }
  2708. nScrollHead.style.border = "0";
  2709. nScrollHead.style.width = "100%";
  2710. nScrollFoot.style.border = "0";
  2711. nScrollHeadInner.style.width = oSettings.oScroll.sXInner !== "" ?
  2712. oSettings.oScroll.sXInner : "100%"; /* will be overwritten */
  2713. /* Modify attributes to respect the clones */
  2714. nScrollHeadTable.removeAttribute('id');
  2715. nScrollHeadTable.style.marginLeft = "0";
  2716. oSettings.nTable.style.marginLeft = "0";
  2717. if ( nTfoot !== null )
  2718. {
  2719. nScrollFootTable.removeAttribute('id');
  2720. nScrollFootTable.style.marginLeft = "0";
  2721. }
  2722. /* Move caption elements from the body to the header, footer or leave where it is
  2723. * depending on the configuration. Note that the DTD says there can be only one caption */
  2724. var nCaption = $(oSettings.nTable).children('caption');
  2725. if ( nCaption.length > 0 )
  2726. {
  2727. nCaption = nCaption[0];
  2728. if ( nCaption._captionSide === "top" )
  2729. {
  2730. nScrollHeadTable.appendChild( nCaption );
  2731. }
  2732. else if ( nCaption._captionSide === "bottom" && nTfoot )
  2733. {
  2734. nScrollFootTable.appendChild( nCaption );
  2735. }
  2736. }
  2737. /*
  2738. * Sizing
  2739. */
  2740. /* When x-scrolling add the width and a scroller to move the header with the body */
  2741. if ( oSettings.oScroll.sX !== "" )
  2742. {
  2743. nScrollHead.style.width = _fnStringToCss( oSettings.oScroll.sX );
  2744. nScrollBody.style.width = _fnStringToCss( oSettings.oScroll.sX );
  2745. if ( nTfoot !== null )
  2746. {
  2747. nScrollFoot.style.width = _fnStringToCss( oSettings.oScroll.sX );
  2748. }
  2749. /* When the body is scrolled, then we also want to scroll the headers */
  2750. $(nScrollBody).scroll( function (e) {
  2751. nScrollHead.scrollLeft = this.scrollLeft;
  2752. if ( nTfoot !== null )
  2753. {
  2754. nScrollFoot.scrollLeft = this.scrollLeft;
  2755. }
  2756. } );
  2757. }
  2758. /* When yscrolling, add the height */
  2759. if ( oSettings.oScroll.sY !== "" )
  2760. {
  2761. nScrollBody.style.height = _fnStringToCss( oSettings.oScroll.sY );
  2762. }
  2763. /* Redraw - align columns across the tables */
  2764. oSettings.aoDrawCallback.push( {
  2765. "fn": _fnScrollDraw,
  2766. "sName": "scrolling"
  2767. } );
  2768. /* Infinite scrolling event handlers */
  2769. if ( oSettings.oScroll.bInfinite )
  2770. {
  2771. $(nScrollBody).scroll( function() {
  2772. /* Use a blocker to stop scrolling from loading more data while other data is still loading */
  2773. if ( !oSettings.bDrawing && $(this).scrollTop() !== 0 )
  2774. {
  2775. /* Check if we should load the next data set */
  2776. if ( $(this).scrollTop() + $(this).height() >
  2777. $(oSettings.nTable).height() - oSettings.oScroll.iLoadGap )
  2778. {
  2779. /* Only do the redraw if we have to - we might be at the end of the data */
  2780. if ( oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay() )
  2781. {
  2782. _fnPageChange( oSettings, 'next' );
  2783. _fnCalculateEnd( oSettings );
  2784. _fnDraw( oSettings );
  2785. }
  2786. }
  2787. }
  2788. } );
  2789. }
  2790. oSettings.nScrollHead = nScrollHead;
  2791. oSettings.nScrollFoot = nScrollFoot;
  2792. return nScroller;
  2793. }
  2794. /**
  2795. * Update the various tables for resizing. It's a bit of a pig this function, but
  2796. * basically the idea to:
  2797. * 1. Re-create the table inside the scrolling div
  2798. * 2. Take live measurements from the DOM
  2799. * 3. Apply the measurements
  2800. * 4. Clean up
  2801. * @param {object} o dataTables settings object
  2802. * @returns {node} Node to add to the DOM
  2803. * @memberof DataTable#oApi
  2804. */
  2805. function _fnScrollDraw ( o )
  2806. {
  2807. var
  2808. nScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0],
  2809. nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],
  2810. nScrollBody = o.nTable.parentNode,
  2811. i, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis,
  2812. nTheadSize, nTfootSize,
  2813. iWidth, aApplied=[], aAppliedFooter=[], iSanityWidth,
  2814. nScrollFootInner = (o.nTFoot !== null) ? o.nScrollFoot.getElementsByTagName('div')[0] : null,
  2815. nScrollFootTable = (o.nTFoot !== null) ? nScrollFootInner.getElementsByTagName('table')[0] : null,
  2816. ie67 = o.oBrowser.bScrollOversize,
  2817. zeroOut = function(nSizer) {
  2818. oStyle = nSizer.style;
  2819. oStyle.paddingTop = "0";
  2820. oStyle.paddingBottom = "0";
  2821. oStyle.borderTopWidth = "0";
  2822. oStyle.borderBottomWidth = "0";
  2823. oStyle.height = 0;
  2824. };
  2825. /*
  2826. * 1. Re-create the table inside the scrolling div
  2827. */
  2828. /* Remove the old minimised thead and tfoot elements in the inner table */
  2829. $(o.nTable).children('thead, tfoot').remove();
  2830. /* Clone the current header and footer elements and then place it into the inner table */
  2831. nTheadSize = $(o.nTHead).clone()[0];
  2832. o.nTable.insertBefore( nTheadSize, o.nTable.childNodes[0] );
  2833. anHeadToSize = o.nTHead.getElementsByTagName('tr');
  2834. anHeadSizers = nTheadSize.getElementsByTagName('tr');
  2835. if ( o.nTFoot !== null )
  2836. {
  2837. nTfootSize = $(o.nTFoot).clone()[0];
  2838. o.nTable.insertBefore( nTfootSize, o.nTable.childNodes[1] );
  2839. anFootToSize = o.nTFoot.getElementsByTagName('tr');
  2840. anFootSizers = nTfootSize.getElementsByTagName('tr');
  2841. }
  2842. /*
  2843. * 2. Take live measurements from the DOM - do not alter the DOM itself!
  2844. */
  2845. /* Remove old sizing and apply the calculated column widths
  2846. * Get the unique column headers in the newly created (cloned) header. We want to apply the
  2847. * calculated sizes to this header
  2848. */
  2849. if ( o.oScroll.sX === "" )
  2850. {
  2851. nScrollBody.style.width = '100%';
  2852. nScrollHeadInner.parentNode.style.width = '100%';
  2853. }
  2854. var nThs = _fnGetUniqueThs( o, nTheadSize );
  2855. for ( i=0, iLen=nThs.length ; i<iLen ; i++ )
  2856. {
  2857. iVis = _fnVisibleToColumnIndex( o, i );
  2858. nThs[i].style.width = o.aoColumns[iVis].sWidth;
  2859. }
  2860. if ( o.nTFoot !== null )
  2861. {
  2862. _fnApplyToChildren( function(n) {
  2863. n.style.width = "";
  2864. }, anFootSizers );
  2865. }
  2866. // If scroll collapse is enabled, when we put the headers back into the body for sizing, we
  2867. // will end up forcing the scrollbar to appear, making our measurements wrong for when we
  2868. // then hide it (end of this function), so add the header height to the body scroller.
  2869. if ( o.oScroll.bCollapse && o.oScroll.sY !== "" )
  2870. {
  2871. nScrollBody.style.height = (nScrollBody.offsetHeight + o.nTHead.offsetHeight)+"px";
  2872. }
  2873. /* Size the table as a whole */
  2874. iSanityWidth = $(o.nTable).outerWidth();
  2875. if ( o.oScroll.sX === "" )
  2876. {
  2877. /* No x scrolling */
  2878. o.nTable.style.width = "100%";
  2879. /* I know this is rubbish - but IE7 will make the width of the table when 100% include
  2880. * the scrollbar - which is shouldn't. When there is a scrollbar we need to take this
  2881. * into account.
  2882. */
  2883. if ( ie67 && ($('tbody', nScrollBody).height() > nScrollBody.offsetHeight ||
  2884. $(nScrollBody).css('overflow-y') == "scroll") )
  2885. {
  2886. o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth() - o.oScroll.iBarWidth);
  2887. }
  2888. }
  2889. else
  2890. {
  2891. if ( o.oScroll.sXInner !== "" )
  2892. {
  2893. /* x scroll inner has been given - use it */
  2894. o.nTable.style.width = _fnStringToCss(o.oScroll.sXInner);
  2895. }
  2896. else if ( iSanityWidth == $(nScrollBody).width() &&
  2897. $(nScrollBody).height() < $(o.nTable).height() )
  2898. {
  2899. /* There is y-scrolling - try to take account of the y scroll bar */
  2900. o.nTable.style.width = _fnStringToCss( iSanityWidth-o.oScroll.iBarWidth );
  2901. if ( $(o.nTable).outerWidth() > iSanityWidth-o.oScroll.iBarWidth )
  2902. {
  2903. /* Not possible to take account of it */
  2904. o.nTable.style.width = _fnStringToCss( iSanityWidth );
  2905. }
  2906. }
  2907. else
  2908. {
  2909. /* All else fails */
  2910. o.nTable.style.width = _fnStringToCss( iSanityWidth );
  2911. }
  2912. }
  2913. /* Recalculate the sanity width - now that we've applied the required width, before it was
  2914. * a temporary variable. This is required because the column width calculation is done
  2915. * before this table DOM is created.
  2916. */
  2917. iSanityWidth = $(o.nTable).outerWidth();
  2918. /* We want the hidden header to have zero height, so remove padding and borders. Then
  2919. * set the width based on the real headers
  2920. */
  2921. // Apply all styles in one pass. Invalidates layout only once because we don't read any
  2922. // DOM properties.
  2923. _fnApplyToChildren( zeroOut, anHeadSizers );
  2924. // Read all widths in next pass. Forces layout only once because we do not change
  2925. // any DOM properties.
  2926. _fnApplyToChildren( function(nSizer) {
  2927. aApplied.push( _fnStringToCss( $(nSizer).width() ) );
  2928. }, anHeadSizers );
  2929. // Apply all widths in final pass. Invalidates layout only once because we do not
  2930. // read any DOM properties.
  2931. _fnApplyToChildren( function(nToSize, i) {
  2932. nToSize.style.width = aApplied[i];
  2933. }, anHeadToSize );
  2934. $(anHeadSizers).height(0);
  2935. /* Same again with the footer if we have one */
  2936. if ( o.nTFoot !== null )
  2937. {
  2938. _fnApplyToChildren( zeroOut, anFootSizers );
  2939. _fnApplyToChildren( function(nSizer) {
  2940. aAppliedFooter.push( _fnStringToCss( $(nSizer).width() ) );
  2941. }, anFootSizers );
  2942. _fnApplyToChildren( function(nToSize, i) {
  2943. nToSize.style.width = aAppliedFooter[i];
  2944. }, anFootToSize );
  2945. $(anFootSizers).height(0);
  2946. }
  2947. /*
  2948. * 3. Apply the measurements
  2949. */
  2950. /* "Hide" the header and footer that we used for the sizing. We want to also fix their width
  2951. * to what they currently are
  2952. */
  2953. _fnApplyToChildren( function(nSizer, i) {
  2954. nSizer.innerHTML = "";
  2955. nSizer.style.width = aApplied[i];
  2956. }, anHeadSizers );
  2957. if ( o.nTFoot !== null )
  2958. {
  2959. _fnApplyToChildren( function(nSizer, i) {
  2960. nSizer.innerHTML = "";
  2961. nSizer.style.width = aAppliedFooter[i];
  2962. }, anFootSizers );
  2963. }
  2964. /* Sanity check that the table is of a sensible width. If not then we are going to get
  2965. * misalignment - try to prevent this by not allowing the table to shrink below its min width
  2966. */
  2967. if ( $(o.nTable).outerWidth() < iSanityWidth )
  2968. {
  2969. /* The min width depends upon if we have a vertical scrollbar visible or not */
  2970. var iCorrection = ((nScrollBody.scrollHeight > nScrollBody.offsetHeight ||
  2971. $(nScrollBody).css('overflow-y') == "scroll")) ?
  2972. iSanityWidth+o.oScroll.iBarWidth : iSanityWidth;
  2973. /* IE6/7 are a law unto themselves... */
  2974. if ( ie67 && (nScrollBody.scrollHeight >
  2975. nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll") )
  2976. {
  2977. o.nTable.style.width = _fnStringToCss( iCorrection-o.oScroll.iBarWidth );
  2978. }
  2979. /* Apply the calculated minimum width to the table wrappers */
  2980. nScrollBody.style.width = _fnStringToCss( iCorrection );
  2981. o.nScrollHead.style.width = _fnStringToCss( iCorrection );
  2982. if ( o.nTFoot !== null )
  2983. {
  2984. o.nScrollFoot.style.width = _fnStringToCss( iCorrection );
  2985. }
  2986. /* And give the user a warning that we've stopped the table getting too small */
  2987. if ( o.oScroll.sX === "" )
  2988. {
  2989. _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
  2990. " misalignment. The table has been drawn at its minimum possible width." );
  2991. }
  2992. else if ( o.oScroll.sXInner !== "" )
  2993. {
  2994. _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
  2995. " misalignment. Increase the sScrollXInner value or remove it to allow automatic"+
  2996. " calculation" );
  2997. }
  2998. }
  2999. else
  3000. {
  3001. nScrollBody.style.width = _fnStringToCss( '100%' );
  3002. o.nScrollHead.style.width = _fnStringToCss( '100%' );
  3003. if ( o.nTFoot !== null )
  3004. {
  3005. o.nScrollFoot.style.width = _fnStringToCss( '100%' );
  3006. }
  3007. }
  3008. /*
  3009. * 4. Clean up
  3010. */
  3011. if ( o.oScroll.sY === "" )
  3012. {
  3013. /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
  3014. * the scrollbar height from the visible display, rather than adding it on. We need to
  3015. * set the height in order to sort this. Don't want to do it in any other browsers.
  3016. */
  3017. if ( ie67 )
  3018. {
  3019. nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+o.oScroll.iBarWidth );
  3020. }
  3021. }
  3022. if ( o.oScroll.sY !== "" && o.oScroll.bCollapse )
  3023. {
  3024. nScrollBody.style.height = _fnStringToCss( o.oScroll.sY );
  3025. var iExtra = (o.oScroll.sX !== "" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ?
  3026. o.oScroll.iBarWidth : 0;
  3027. if ( o.nTable.offsetHeight < nScrollBody.offsetHeight )
  3028. {
  3029. nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+iExtra );
  3030. }
  3031. }
  3032. /* Finally set the width's of the header and footer tables */
  3033. var iOuterWidth = $(o.nTable).outerWidth();
  3034. nScrollHeadTable.style.width = _fnStringToCss( iOuterWidth );
  3035. nScrollHeadInner.style.width = _fnStringToCss( iOuterWidth );
  3036. // Figure out if there are scrollbar present - if so then we need a the header and footer to
  3037. // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
  3038. var bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll";
  3039. nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
  3040. if ( o.nTFoot !== null )
  3041. {
  3042. nScrollFootTable.style.width = _fnStringToCss( iOuterWidth );
  3043. nScrollFootInner.style.width = _fnStringToCss( iOuterWidth );
  3044. nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
  3045. }
  3046. /* Adjust the position of the header in case we loose the y-scrollbar */
  3047. $(nScrollBody).scroll();
  3048. /* If sorting or filtering has occurred, jump the scrolling back to the top */
  3049. if ( o.bSorted || o.bFiltered )
  3050. {
  3051. nScrollBody.scrollTop = 0;
  3052. }
  3053. }
  3054. /**
  3055. * Apply a given function to the display child nodes of an element array (typically
  3056. * TD children of TR rows
  3057. * @param {function} fn Method to apply to the objects
  3058. * @param array {nodes} an1 List of elements to look through for display children
  3059. * @param array {nodes} an2 Another list (identical structure to the first) - optional
  3060. * @memberof DataTable#oApi
  3061. */
  3062. function _fnApplyToChildren( fn, an1, an2 )
  3063. {
  3064. var index=0, i=0, iLen=an1.length;
  3065. var nNode1, nNode2;
  3066. while ( i < iLen )
  3067. {
  3068. nNode1 = an1[i].firstChild;
  3069. nNode2 = an2 ? an2[i].firstChild : null;
  3070. while ( nNode1 )
  3071. {
  3072. if ( nNode1.nodeType === 1 )
  3073. {
  3074. if ( an2 )
  3075. {
  3076. fn( nNode1, nNode2, index );
  3077. }
  3078. else
  3079. {
  3080. fn( nNode1, index );
  3081. }
  3082. index++;
  3083. }
  3084. nNode1 = nNode1.nextSibling;
  3085. nNode2 = an2 ? nNode2.nextSibling : null;
  3086. }
  3087. i++;
  3088. }
  3089. }
  3090. /**
  3091. * Convert a CSS unit width to pixels (e.g. 2em)
  3092. * @param {string} sWidth width to be converted
  3093. * @param {node} nParent parent to get the with for (required for relative widths) - optional
  3094. * @returns {int} iWidth width in pixels
  3095. * @memberof DataTable#oApi
  3096. */
  3097. function _fnConvertToWidth ( sWidth, nParent )
  3098. {
  3099. if ( !sWidth || sWidth === null || sWidth === '' )
  3100. {
  3101. return 0;
  3102. }
  3103. if ( !nParent )
  3104. {
  3105. nParent = document.body;
  3106. }
  3107. var iWidth;
  3108. var nTmp = document.createElement( "div" );
  3109. nTmp.style.width = _fnStringToCss( sWidth );
  3110. nParent.appendChild( nTmp );
  3111. iWidth = nTmp.offsetWidth;
  3112. nParent.removeChild( nTmp );
  3113. return ( iWidth );
  3114. }
  3115. /**
  3116. * Calculate the width of columns for the table
  3117. * @param {object} oSettings dataTables settings object
  3118. * @memberof DataTable#oApi
  3119. */
  3120. function _fnCalculateColumnWidths ( oSettings )
  3121. {
  3122. var iTableWidth = oSettings.nTable.offsetWidth;
  3123. var iUserInputs = 0;
  3124. var iTmpWidth;
  3125. var iVisibleColumns = 0;
  3126. var iColums = oSettings.aoColumns.length;
  3127. var i, iIndex, iCorrector, iWidth;
  3128. var oHeaders = $('th', oSettings.nTHead);
  3129. var widthAttr = oSettings.nTable.getAttribute('width');
  3130. var nWrapper = oSettings.nTable.parentNode;
  3131. /* Convert any user input sizes into pixel sizes */
  3132. for ( i=0 ; i<iColums ; i++ )
  3133. {
  3134. if ( oSettings.aoColumns[i].bVisible )
  3135. {
  3136. iVisibleColumns++;
  3137. if ( oSettings.aoColumns[i].sWidth !== null )
  3138. {
  3139. iTmpWidth = _fnConvertToWidth( oSettings.aoColumns[i].sWidthOrig,
  3140. nWrapper );
  3141. if ( iTmpWidth !== null )
  3142. {
  3143. oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth );
  3144. }
  3145. iUserInputs++;
  3146. }
  3147. }
  3148. }
  3149. /* If the number of columns in the DOM equals the number that we have to process in
  3150. * DataTables, then we can use the offsets that are created by the web-browser. No custom
  3151. * sizes can be set in order for this to happen, nor scrolling used
  3152. */
  3153. if ( iColums == oHeaders.length && iUserInputs === 0 && iVisibleColumns == iColums &&
  3154. oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" )
  3155. {
  3156. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  3157. {
  3158. iTmpWidth = $(oHeaders[i]).width();
  3159. if ( iTmpWidth !== null )
  3160. {
  3161. oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth );
  3162. }
  3163. }
  3164. }
  3165. else
  3166. {
  3167. /* Otherwise we are going to have to do some calculations to get the width of each column.
  3168. * Construct a 1 row table with the widest node in the data, and any user defined widths,
  3169. * then insert it into the DOM and allow the browser to do all the hard work of
  3170. * calculating table widths.
  3171. */
  3172. var
  3173. nCalcTmp = oSettings.nTable.cloneNode( false ),
  3174. nTheadClone = oSettings.nTHead.cloneNode(true),
  3175. nBody = document.createElement( 'tbody' ),
  3176. nTr = document.createElement( 'tr' ),
  3177. nDivSizing;
  3178. nCalcTmp.removeAttribute( "id" );
  3179. nCalcTmp.appendChild( nTheadClone );
  3180. if ( oSettings.nTFoot !== null )
  3181. {
  3182. nCalcTmp.appendChild( oSettings.nTFoot.cloneNode(true) );
  3183. _fnApplyToChildren( function(n) {
  3184. n.style.width = "";
  3185. }, nCalcTmp.getElementsByTagName('tr') );
  3186. }
  3187. nCalcTmp.appendChild( nBody );
  3188. nBody.appendChild( nTr );
  3189. /* Remove any sizing that was previously applied by the styles */
  3190. var jqColSizing = $('thead th', nCalcTmp);
  3191. if ( jqColSizing.length === 0 )
  3192. {
  3193. jqColSizing = $('tbody tr:eq(0)>td', nCalcTmp);
  3194. }
  3195. /* Apply custom sizing to the cloned header */
  3196. var nThs = _fnGetUniqueThs( oSettings, nTheadClone );
  3197. iCorrector = 0;
  3198. for ( i=0 ; i<iColums ; i++ )
  3199. {
  3200. var oColumn = oSettings.aoColumns[i];
  3201. if ( oColumn.bVisible && oColumn.sWidthOrig !== null && oColumn.sWidthOrig !== "" )
  3202. {
  3203. nThs[i-iCorrector].style.width = _fnStringToCss( oColumn.sWidthOrig );
  3204. }
  3205. else if ( oColumn.bVisible )
  3206. {
  3207. nThs[i-iCorrector].style.width = "";
  3208. }
  3209. else
  3210. {
  3211. iCorrector++;
  3212. }
  3213. }
  3214. /* Find the biggest td for each column and put it into the table */
  3215. for ( i=0 ; i<iColums ; i++ )
  3216. {
  3217. if ( oSettings.aoColumns[i].bVisible )
  3218. {
  3219. var nTd = _fnGetWidestNode( oSettings, i );
  3220. if ( nTd !== null )
  3221. {
  3222. nTd = nTd.cloneNode(true);
  3223. if ( oSettings.aoColumns[i].sContentPadding !== "" )
  3224. {
  3225. nTd.innerHTML += oSettings.aoColumns[i].sContentPadding;
  3226. }
  3227. nTr.appendChild( nTd );
  3228. }
  3229. }
  3230. }
  3231. /* Build the table and 'display' it */
  3232. nWrapper.appendChild( nCalcTmp );
  3233. /* When scrolling (X or Y) we want to set the width of the table as appropriate. However,
  3234. * when not scrolling leave the table width as it is. This results in slightly different,
  3235. * but I think correct behaviour
  3236. */
  3237. if ( oSettings.oScroll.sX !== "" && oSettings.oScroll.sXInner !== "" )
  3238. {
  3239. nCalcTmp.style.width = _fnStringToCss(oSettings.oScroll.sXInner);
  3240. }
  3241. else if ( oSettings.oScroll.sX !== "" )
  3242. {
  3243. nCalcTmp.style.width = "";
  3244. if ( $(nCalcTmp).width() < nWrapper.offsetWidth )
  3245. {
  3246. nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth );
  3247. }
  3248. }
  3249. else if ( oSettings.oScroll.sY !== "" )
  3250. {
  3251. nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth );
  3252. }
  3253. else if ( widthAttr )
  3254. {
  3255. nCalcTmp.style.width = _fnStringToCss( widthAttr );
  3256. }
  3257. nCalcTmp.style.visibility = "hidden";
  3258. /* Scrolling considerations */
  3259. _fnScrollingWidthAdjust( oSettings, nCalcTmp );
  3260. /* Read the width's calculated by the browser and store them for use by the caller. We
  3261. * first of all try to use the elements in the body, but it is possible that there are
  3262. * no elements there, under which circumstances we use the header elements
  3263. */
  3264. var oNodes = $("tbody tr:eq(0)", nCalcTmp).children();
  3265. if ( oNodes.length === 0 )
  3266. {
  3267. oNodes = _fnGetUniqueThs( oSettings, $('thead', nCalcTmp)[0] );
  3268. }
  3269. /* Browsers need a bit of a hand when a width is assigned to any columns when
  3270. * x-scrolling as they tend to collapse the table to the min-width, even if
  3271. * we sent the column widths. So we need to keep track of what the table width
  3272. * should be by summing the user given values, and the automatic values
  3273. */
  3274. if ( oSettings.oScroll.sX !== "" )
  3275. {
  3276. var iTotal = 0;
  3277. iCorrector = 0;
  3278. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  3279. {
  3280. if ( oSettings.aoColumns[i].bVisible )
  3281. {
  3282. if ( oSettings.aoColumns[i].sWidthOrig === null )
  3283. {
  3284. iTotal += $(oNodes[iCorrector]).outerWidth();
  3285. }
  3286. else
  3287. {
  3288. iTotal += parseInt(oSettings.aoColumns[i].sWidth.replace('px',''), 10) +
  3289. ($(oNodes[iCorrector]).outerWidth() - $(oNodes[iCorrector]).width());
  3290. }
  3291. iCorrector++;
  3292. }
  3293. }
  3294. nCalcTmp.style.width = _fnStringToCss( iTotal );
  3295. oSettings.nTable.style.width = _fnStringToCss( iTotal );
  3296. }
  3297. iCorrector = 0;
  3298. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  3299. {
  3300. if ( oSettings.aoColumns[i].bVisible )
  3301. {
  3302. iWidth = $(oNodes[iCorrector]).width();
  3303. if ( iWidth !== null && iWidth > 0 )
  3304. {
  3305. oSettings.aoColumns[i].sWidth = _fnStringToCss( iWidth );
  3306. }
  3307. iCorrector++;
  3308. }
  3309. }
  3310. var cssWidth = $(nCalcTmp).css('width');
  3311. oSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ?
  3312. cssWidth : _fnStringToCss( $(nCalcTmp).outerWidth() );
  3313. nCalcTmp.parentNode.removeChild( nCalcTmp );
  3314. }
  3315. if ( widthAttr )
  3316. {
  3317. oSettings.nTable.style.width = _fnStringToCss( widthAttr );
  3318. }
  3319. }
  3320. /**
  3321. * Adjust a table's width to take account of scrolling
  3322. * @param {object} oSettings dataTables settings object
  3323. * @param {node} n table node
  3324. * @memberof DataTable#oApi
  3325. */
  3326. function _fnScrollingWidthAdjust ( oSettings, n )
  3327. {
  3328. if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "" )
  3329. {
  3330. /* When y-scrolling only, we want to remove the width of the scroll bar so the table
  3331. * + scroll bar will fit into the area avaialble.
  3332. */
  3333. var iOrigWidth = $(n).width();
  3334. n.style.width = _fnStringToCss( $(n).outerWidth()-oSettings.oScroll.iBarWidth );
  3335. }
  3336. else if ( oSettings.oScroll.sX !== "" )
  3337. {
  3338. /* When x-scrolling both ways, fix the table at it's current size, without adjusting */
  3339. n.style.width = _fnStringToCss( $(n).outerWidth() );
  3340. }
  3341. }
  3342. /**
  3343. * Get the widest node
  3344. * @param {object} oSettings dataTables settings object
  3345. * @param {int} iCol column of interest
  3346. * @returns {node} widest table node
  3347. * @memberof DataTable#oApi
  3348. */
  3349. function _fnGetWidestNode( oSettings, iCol )
  3350. {
  3351. var iMaxIndex = _fnGetMaxLenString( oSettings, iCol );
  3352. if ( iMaxIndex < 0 )
  3353. {
  3354. return null;
  3355. }
  3356. if ( oSettings.aoData[iMaxIndex].nTr === null )
  3357. {
  3358. var n = document.createElement('td');
  3359. n.innerHTML = _fnGetCellData( oSettings, iMaxIndex, iCol, '' );
  3360. return n;
  3361. }
  3362. return _fnGetTdNodes(oSettings, iMaxIndex)[iCol];
  3363. }
  3364. /**
  3365. * Get the maximum strlen for each data column
  3366. * @param {object} oSettings dataTables settings object
  3367. * @param {int} iCol column of interest
  3368. * @returns {string} max string length for each column
  3369. * @memberof DataTable#oApi
  3370. */
  3371. function _fnGetMaxLenString( oSettings, iCol )
  3372. {
  3373. var iMax = -1;
  3374. var iMaxIndex = -1;
  3375. for ( var i=0 ; i<oSettings.aoData.length ; i++ )
  3376. {
  3377. var s = _fnGetCellData( oSettings, i, iCol, 'display' )+"";
  3378. s = s.replace( /<.*?>/g, "" );
  3379. if ( s.length > iMax )
  3380. {
  3381. iMax = s.length;
  3382. iMaxIndex = i;
  3383. }
  3384. }
  3385. return iMaxIndex;
  3386. }
  3387. /**
  3388. * Append a CSS unit (only if required) to a string
  3389. * @param {array} aArray1 first array
  3390. * @param {array} aArray2 second array
  3391. * @returns {int} 0 if match, 1 if length is different, 2 if no match
  3392. * @memberof DataTable#oApi
  3393. */
  3394. function _fnStringToCss( s )
  3395. {
  3396. if ( s === null )
  3397. {
  3398. return "0px";
  3399. }
  3400. if ( typeof s == 'number' )
  3401. {
  3402. if ( s < 0 )
  3403. {
  3404. return "0px";
  3405. }
  3406. return s+"px";
  3407. }
  3408. /* Check if the last character is not 0-9 */
  3409. var c = s.charCodeAt( s.length-1 );
  3410. if (c < 0x30 || c > 0x39)
  3411. {
  3412. return s;
  3413. }
  3414. return s+"px";
  3415. }
  3416. /**
  3417. * Get the width of a scroll bar in this browser being used
  3418. * @returns {int} width in pixels
  3419. * @memberof DataTable#oApi
  3420. */
  3421. function _fnScrollBarWidth ()
  3422. {
  3423. var inner = document.createElement('p');
  3424. var style = inner.style;
  3425. style.width = "100%";
  3426. style.height = "200px";
  3427. style.padding = "0px";
  3428. var outer = document.createElement('div');
  3429. style = outer.style;
  3430. style.position = "absolute";
  3431. style.top = "0px";
  3432. style.left = "0px";
  3433. style.visibility = "hidden";
  3434. style.width = "200px";
  3435. style.height = "150px";
  3436. style.padding = "0px";
  3437. style.overflow = "hidden";
  3438. outer.appendChild(inner);
  3439. document.body.appendChild(outer);
  3440. var w1 = inner.offsetWidth;
  3441. outer.style.overflow = 'scroll';
  3442. var w2 = inner.offsetWidth;
  3443. if ( w1 == w2 )
  3444. {
  3445. w2 = outer.clientWidth;
  3446. }
  3447. document.body.removeChild(outer);
  3448. return (w1 - w2);
  3449. }
  3450. /**
  3451. * Change the order of the table
  3452. * @param {object} oSettings dataTables settings object
  3453. * @param {bool} bApplyClasses optional - should we apply classes or not
  3454. * @memberof DataTable#oApi
  3455. */
  3456. function _fnSort ( oSettings, bApplyClasses )
  3457. {
  3458. var
  3459. i, iLen, j, jLen, k, kLen,
  3460. sDataType, nTh,
  3461. aaSort = [],
  3462. aiOrig = [],
  3463. oSort = DataTable.ext.oSort,
  3464. aoData = oSettings.aoData,
  3465. aoColumns = oSettings.aoColumns,
  3466. oAria = oSettings.oLanguage.oAria;
  3467. /* No sorting required if server-side or no sorting array */
  3468. if ( !oSettings.oFeatures.bServerSide &&
  3469. (oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null) )
  3470. {
  3471. aaSort = ( oSettings.aaSortingFixed !== null ) ?
  3472. oSettings.aaSortingFixed.concat( oSettings.aaSorting ) :
  3473. oSettings.aaSorting.slice();
  3474. /* If there is a sorting data type, and a function belonging to it, then we need to
  3475. * get the data from the developer's function and apply it for this column
  3476. */
  3477. for ( i=0 ; i<aaSort.length ; i++ )
  3478. {
  3479. var iColumn = aaSort[i][0];
  3480. var iVisColumn = _fnColumnIndexToVisible( oSettings, iColumn );
  3481. sDataType = oSettings.aoColumns[ iColumn ].sSortDataType;
  3482. if ( DataTable.ext.afnSortData[sDataType] )
  3483. {
  3484. var aData = DataTable.ext.afnSortData[sDataType].call(
  3485. oSettings.oInstance, oSettings, iColumn, iVisColumn
  3486. );
  3487. if ( aData.length === aoData.length )
  3488. {
  3489. for ( j=0, jLen=aoData.length ; j<jLen ; j++ )
  3490. {
  3491. _fnSetCellData( oSettings, j, iColumn, aData[j] );
  3492. }
  3493. }
  3494. else
  3495. {
  3496. _fnLog( oSettings, 0, "Returned data sort array (col "+iColumn+") is the wrong length" );
  3497. }
  3498. }
  3499. }
  3500. /* Create a value - key array of the current row positions such that we can use their
  3501. * current position during the sort, if values match, in order to perform stable sorting
  3502. */
  3503. for ( i=0, iLen=oSettings.aiDisplayMaster.length ; i<iLen ; i++ )
  3504. {
  3505. aiOrig[ oSettings.aiDisplayMaster[i] ] = i;
  3506. }
  3507. /* Build an internal data array which is specific to the sort, so we can get and prep
  3508. * the data to be sorted only once, rather than needing to do it every time the sorting
  3509. * function runs. This make the sorting function a very simple comparison
  3510. */
  3511. var iSortLen = aaSort.length;
  3512. var fnSortFormat, aDataSort;
  3513. for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
  3514. {
  3515. for ( j=0 ; j<iSortLen ; j++ )
  3516. {
  3517. aDataSort = aoColumns[ aaSort[j][0] ].aDataSort;
  3518. for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
  3519. {
  3520. sDataType = aoColumns[ aDataSort[k] ].sType;
  3521. fnSortFormat = oSort[ (sDataType ? sDataType : 'string')+"-pre" ];
  3522. aoData[i]._aSortData[ aDataSort[k] ] = fnSortFormat ?
  3523. fnSortFormat( _fnGetCellData( oSettings, i, aDataSort[k], 'sort' ) ) :
  3524. _fnGetCellData( oSettings, i, aDataSort[k], 'sort' );
  3525. }
  3526. }
  3527. }
  3528. /* Do the sort - here we want multi-column sorting based on a given data source (column)
  3529. * and sorting function (from oSort) in a certain direction. It's reasonably complex to
  3530. * follow on it's own, but this is what we want (example two column sorting):
  3531. * fnLocalSorting = function(a,b){
  3532. * var iTest;
  3533. * iTest = oSort['string-asc']('data11', 'data12');
  3534. * if (iTest !== 0)
  3535. * return iTest;
  3536. * iTest = oSort['numeric-desc']('data21', 'data22');
  3537. * if (iTest !== 0)
  3538. * return iTest;
  3539. * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
  3540. * }
  3541. * Basically we have a test for each sorting column, if the data in that column is equal,
  3542. * test the next column. If all columns match, then we use a numeric sort on the row
  3543. * positions in the original data array to provide a stable sort.
  3544. */
  3545. oSettings.aiDisplayMaster.sort( function ( a, b ) {
  3546. var k, l, lLen, iTest, aDataSort, sDataType;
  3547. for ( k=0 ; k<iSortLen ; k++ )
  3548. {
  3549. aDataSort = aoColumns[ aaSort[k][0] ].aDataSort;
  3550. for ( l=0, lLen=aDataSort.length ; l<lLen ; l++ )
  3551. {
  3552. sDataType = aoColumns[ aDataSort[l] ].sType;
  3553. iTest = oSort[ (sDataType ? sDataType : 'string')+"-"+aaSort[k][1] ](
  3554. aoData[a]._aSortData[ aDataSort[l] ],
  3555. aoData[b]._aSortData[ aDataSort[l] ]
  3556. );
  3557. if ( iTest !== 0 )
  3558. {
  3559. return iTest;
  3560. }
  3561. }
  3562. }
  3563. return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
  3564. } );
  3565. }
  3566. /* Alter the sorting classes to take account of the changes */
  3567. if ( (bApplyClasses === undefined || bApplyClasses) && !oSettings.oFeatures.bDeferRender )
  3568. {
  3569. _fnSortingClasses( oSettings );
  3570. }
  3571. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  3572. {
  3573. var sTitle = aoColumns[i].sTitle.replace( /<.*?>/g, "" );
  3574. nTh = aoColumns[i].nTh;
  3575. nTh.removeAttribute('aria-sort');
  3576. nTh.removeAttribute('aria-label');
  3577. /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
  3578. if ( aoColumns[i].bSortable )
  3579. {
  3580. if ( aaSort.length > 0 && aaSort[0][0] == i )
  3581. {
  3582. nTh.setAttribute('aria-sort', aaSort[0][1]=="asc" ? "ascending" : "descending" );
  3583. var nextSort = (aoColumns[i].asSorting[ aaSort[0][2]+1 ]) ?
  3584. aoColumns[i].asSorting[ aaSort[0][2]+1 ] : aoColumns[i].asSorting[0];
  3585. nTh.setAttribute('aria-label', sTitle+
  3586. (nextSort=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
  3587. }
  3588. else
  3589. {
  3590. nTh.setAttribute('aria-label', sTitle+
  3591. (aoColumns[i].asSorting[0]=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
  3592. }
  3593. }
  3594. else
  3595. {
  3596. nTh.setAttribute('aria-label', sTitle);
  3597. }
  3598. }
  3599. /* Tell the draw function that we have sorted the data */
  3600. oSettings.bSorted = true;
  3601. $(oSettings.oInstance).trigger('sort', oSettings);
  3602. /* Copy the master data into the draw array and re-draw */
  3603. if ( oSettings.oFeatures.bFilter )
  3604. {
  3605. /* _fnFilter() will redraw the table for us */
  3606. _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
  3607. }
  3608. else
  3609. {
  3610. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  3611. oSettings._iDisplayStart = 0; /* reset display back to page 0 */
  3612. _fnCalculateEnd( oSettings );
  3613. _fnDraw( oSettings );
  3614. }
  3615. }
  3616. /**
  3617. * Attach a sort handler (click) to a node
  3618. * @param {object} oSettings dataTables settings object
  3619. * @param {node} nNode node to attach the handler to
  3620. * @param {int} iDataIndex column sorting index
  3621. * @param {function} [fnCallback] callback function
  3622. * @memberof DataTable#oApi
  3623. */
  3624. function _fnSortAttachListener ( oSettings, nNode, iDataIndex, fnCallback )
  3625. {
  3626. _fnBindAction( nNode, {}, function (e) {
  3627. /* If the column is not sortable - don't to anything */
  3628. if ( oSettings.aoColumns[iDataIndex].bSortable === false )
  3629. {
  3630. return;
  3631. }
  3632. /*
  3633. * This is a little bit odd I admit... I declare a temporary function inside the scope of
  3634. * _fnBuildHead and the click handler in order that the code presented here can be used
  3635. * twice - once for when bProcessing is enabled, and another time for when it is
  3636. * disabled, as we need to perform slightly different actions.
  3637. * Basically the issue here is that the Javascript engine in modern browsers don't
  3638. * appear to allow the rendering engine to update the display while it is still executing
  3639. * it's thread (well - it does but only after long intervals). This means that the
  3640. * 'processing' display doesn't appear for a table sort. To break the js thread up a bit
  3641. * I force an execution break by using setTimeout - but this breaks the expected
  3642. * thread continuation for the end-developer's point of view (their code would execute
  3643. * too early), so we only do it when we absolutely have to.
  3644. */
  3645. var fnInnerSorting = function () {
  3646. var iColumn, iNextSort;
  3647. /* If the shift key is pressed then we are multiple column sorting */
  3648. if ( e.shiftKey )
  3649. {
  3650. /* Are we already doing some kind of sort on this column? */
  3651. var bFound = false;
  3652. for ( var i=0 ; i<oSettings.aaSorting.length ; i++ )
  3653. {
  3654. if ( oSettings.aaSorting[i][0] == iDataIndex )
  3655. {
  3656. bFound = true;
  3657. iColumn = oSettings.aaSorting[i][0];
  3658. iNextSort = oSettings.aaSorting[i][2]+1;
  3659. if ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] )
  3660. {
  3661. /* Reached the end of the sorting options, remove from multi-col sort */
  3662. oSettings.aaSorting.splice( i, 1 );
  3663. }
  3664. else
  3665. {
  3666. /* Move onto next sorting direction */
  3667. oSettings.aaSorting[i][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];
  3668. oSettings.aaSorting[i][2] = iNextSort;
  3669. }
  3670. break;
  3671. }
  3672. }
  3673. /* No sort yet - add it in */
  3674. if ( bFound === false )
  3675. {
  3676. oSettings.aaSorting.push( [ iDataIndex,
  3677. oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] );
  3678. }
  3679. }
  3680. else
  3681. {
  3682. /* If no shift key then single column sort */
  3683. if ( oSettings.aaSorting.length == 1 && oSettings.aaSorting[0][0] == iDataIndex )
  3684. {
  3685. iColumn = oSettings.aaSorting[0][0];
  3686. iNextSort = oSettings.aaSorting[0][2]+1;
  3687. if ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] )
  3688. {
  3689. iNextSort = 0;
  3690. }
  3691. oSettings.aaSorting[0][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];
  3692. oSettings.aaSorting[0][2] = iNextSort;
  3693. }
  3694. else
  3695. {
  3696. oSettings.aaSorting.splice( 0, oSettings.aaSorting.length );
  3697. oSettings.aaSorting.push( [ iDataIndex,
  3698. oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] );
  3699. }
  3700. }
  3701. /* Run the sort */
  3702. _fnSort( oSettings );
  3703. }; /* /fnInnerSorting */
  3704. if ( !oSettings.oFeatures.bProcessing )
  3705. {
  3706. fnInnerSorting();
  3707. }
  3708. else
  3709. {
  3710. _fnProcessingDisplay( oSettings, true );
  3711. setTimeout( function() {
  3712. fnInnerSorting();
  3713. if ( !oSettings.oFeatures.bServerSide )
  3714. {
  3715. _fnProcessingDisplay( oSettings, false );
  3716. }
  3717. }, 0 );
  3718. }
  3719. /* Call the user specified callback function - used for async user interaction */
  3720. if ( typeof fnCallback == 'function' )
  3721. {
  3722. fnCallback( oSettings );
  3723. }
  3724. } );
  3725. }
  3726. /**
  3727. * Set the sorting classes on the header, Note: it is safe to call this function
  3728. * when bSort and bSortClasses are false
  3729. * @param {object} oSettings dataTables settings object
  3730. * @memberof DataTable#oApi
  3731. */
  3732. function _fnSortingClasses( oSettings )
  3733. {
  3734. var i, iLen, j, jLen, iFound;
  3735. var aaSort, sClass;
  3736. var iColumns = oSettings.aoColumns.length;
  3737. var oClasses = oSettings.oClasses;
  3738. for ( i=0 ; i<iColumns ; i++ )
  3739. {
  3740. if ( oSettings.aoColumns[i].bSortable )
  3741. {
  3742. $(oSettings.aoColumns[i].nTh).removeClass( oClasses.sSortAsc +" "+ oClasses.sSortDesc +
  3743. " "+ oSettings.aoColumns[i].sSortingClass );
  3744. }
  3745. }
  3746. if ( oSettings.aaSortingFixed !== null )
  3747. {
  3748. aaSort = oSettings.aaSortingFixed.concat( oSettings.aaSorting );
  3749. }
  3750. else
  3751. {
  3752. aaSort = oSettings.aaSorting.slice();
  3753. }
  3754. /* Apply the required classes to the header */
  3755. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  3756. {
  3757. if ( oSettings.aoColumns[i].bSortable )
  3758. {
  3759. sClass = oSettings.aoColumns[i].sSortingClass;
  3760. iFound = -1;
  3761. for ( j=0 ; j<aaSort.length ; j++ )
  3762. {
  3763. if ( aaSort[j][0] == i )
  3764. {
  3765. sClass = ( aaSort[j][1] == "asc" ) ?
  3766. oClasses.sSortAsc : oClasses.sSortDesc;
  3767. iFound = j;
  3768. break;
  3769. }
  3770. }
  3771. $(oSettings.aoColumns[i].nTh).addClass( sClass );
  3772. if ( oSettings.bJUI )
  3773. {
  3774. /* jQuery UI uses extra markup */
  3775. var jqSpan = $("span."+oClasses.sSortIcon, oSettings.aoColumns[i].nTh);
  3776. jqSpan.removeClass(oClasses.sSortJUIAsc +" "+ oClasses.sSortJUIDesc +" "+
  3777. oClasses.sSortJUI +" "+ oClasses.sSortJUIAscAllowed +" "+ oClasses.sSortJUIDescAllowed );
  3778. var sSpanClass;
  3779. if ( iFound == -1 )
  3780. {
  3781. sSpanClass = oSettings.aoColumns[i].sSortingClassJUI;
  3782. }
  3783. else if ( aaSort[iFound][1] == "asc" )
  3784. {
  3785. sSpanClass = oClasses.sSortJUIAsc;
  3786. }
  3787. else
  3788. {
  3789. sSpanClass = oClasses.sSortJUIDesc;
  3790. }
  3791. jqSpan.addClass( sSpanClass );
  3792. }
  3793. }
  3794. else
  3795. {
  3796. /* No sorting on this column, so add the base class. This will have been assigned by
  3797. * _fnAddColumn
  3798. */
  3799. $(oSettings.aoColumns[i].nTh).addClass( oSettings.aoColumns[i].sSortingClass );
  3800. }
  3801. }
  3802. /*
  3803. * Apply the required classes to the table body
  3804. * Note that this is given as a feature switch since it can significantly slow down a sort
  3805. * on large data sets (adding and removing of classes is always slow at the best of times..)
  3806. * Further to this, note that this code is admittedly fairly ugly. It could be made a lot
  3807. * simpler using jQuery selectors and add/removeClass, but that is significantly slower
  3808. * (on the order of 5 times slower) - hence the direct DOM manipulation here.
  3809. * Note that for deferred drawing we do use jQuery - the reason being that taking the first
  3810. * row found to see if the whole column needs processed can miss classes since the first
  3811. * column might be new.
  3812. */
  3813. sClass = oClasses.sSortColumn;
  3814. if ( oSettings.oFeatures.bSort && oSettings.oFeatures.bSortClasses )
  3815. {
  3816. var nTds = _fnGetTdNodes( oSettings );
  3817. /* Determine what the sorting class for each column should be */
  3818. var iClass, iTargetCol;
  3819. var asClasses = [];
  3820. for (i = 0; i < iColumns; i++)
  3821. {
  3822. asClasses.push("");
  3823. }
  3824. for (i = 0, iClass = 1; i < aaSort.length; i++)
  3825. {
  3826. iTargetCol = parseInt( aaSort[i][0], 10 );
  3827. asClasses[iTargetCol] = sClass + iClass;
  3828. if ( iClass < 3 )
  3829. {
  3830. iClass++;
  3831. }
  3832. }
  3833. /* Make changes to the classes for each cell as needed */
  3834. var reClass = new RegExp(sClass + "[123]");
  3835. var sTmpClass, sCurrentClass, sNewClass;
  3836. for ( i=0, iLen=nTds.length; i<iLen; i++ )
  3837. {
  3838. /* Determine which column we're looking at */
  3839. iTargetCol = i % iColumns;
  3840. /* What is the full list of classes now */
  3841. sCurrentClass = nTds[i].className;
  3842. /* What sorting class should be applied? */
  3843. sNewClass = asClasses[iTargetCol];
  3844. /* What would the new full list be if we did a replacement? */
  3845. sTmpClass = sCurrentClass.replace(reClass, sNewClass);
  3846. if ( sTmpClass != sCurrentClass )
  3847. {
  3848. /* We changed something */
  3849. nTds[i].className = $.trim( sTmpClass );
  3850. }
  3851. else if ( sNewClass.length > 0 && sCurrentClass.indexOf(sNewClass) == -1 )
  3852. {
  3853. /* We need to add a class */
  3854. nTds[i].className = sCurrentClass + " " + sNewClass;
  3855. }
  3856. }
  3857. }
  3858. }
  3859. /**
  3860. * Save the state of a table in a cookie such that the page can be reloaded
  3861. * @param {object} oSettings dataTables settings object
  3862. * @memberof DataTable#oApi
  3863. */
  3864. function _fnSaveState ( oSettings )
  3865. {
  3866. if ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying )
  3867. {
  3868. return;
  3869. }
  3870. /* Store the interesting variables */
  3871. var i, iLen, bInfinite=oSettings.oScroll.bInfinite;
  3872. var oState = {
  3873. "iCreate": new Date().getTime(),
  3874. "iStart": (bInfinite ? 0 : oSettings._iDisplayStart),
  3875. "iEnd": (bInfinite ? oSettings._iDisplayLength : oSettings._iDisplayEnd),
  3876. "iLength": oSettings._iDisplayLength,
  3877. "aaSorting": $.extend( true, [], oSettings.aaSorting ),
  3878. "oSearch": $.extend( true, {}, oSettings.oPreviousSearch ),
  3879. "aoSearchCols": $.extend( true, [], oSettings.aoPreSearchCols ),
  3880. "abVisCols": []
  3881. };
  3882. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  3883. {
  3884. oState.abVisCols.push( oSettings.aoColumns[i].bVisible );
  3885. }
  3886. _fnCallbackFire( oSettings, "aoStateSaveParams", 'stateSaveParams', [oSettings, oState] );
  3887. oSettings.fnStateSave.call( oSettings.oInstance, oSettings, oState );
  3888. }
  3889. /**
  3890. * Attempt to load a saved table state from a cookie
  3891. * @param {object} oSettings dataTables settings object
  3892. * @param {object} oInit DataTables init object so we can override settings
  3893. * @memberof DataTable#oApi
  3894. */
  3895. function _fnLoadState ( oSettings, oInit )
  3896. {
  3897. if ( !oSettings.oFeatures.bStateSave )
  3898. {
  3899. return;
  3900. }
  3901. var oData = oSettings.fnStateLoad.call( oSettings.oInstance, oSettings );
  3902. if ( !oData )
  3903. {
  3904. return;
  3905. }
  3906. /* Allow custom and plug-in manipulation functions to alter the saved data set and
  3907. * cancelling of loading by returning false
  3908. */
  3909. var abStateLoad = _fnCallbackFire( oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData] );
  3910. if ( $.inArray( false, abStateLoad ) !== -1 )
  3911. {
  3912. return;
  3913. }
  3914. /* Store the saved state so it might be accessed at any time */
  3915. oSettings.oLoadedState = $.extend( true, {}, oData );
  3916. /* Restore key features */
  3917. oSettings._iDisplayStart = oData.iStart;
  3918. oSettings.iInitDisplayStart = oData.iStart;
  3919. oSettings._iDisplayEnd = oData.iEnd;
  3920. oSettings._iDisplayLength = oData.iLength;
  3921. oSettings.aaSorting = oData.aaSorting.slice();
  3922. oSettings.saved_aaSorting = oData.aaSorting.slice();
  3923. /* Search filtering */
  3924. $.extend( oSettings.oPreviousSearch, oData.oSearch );
  3925. $.extend( true, oSettings.aoPreSearchCols, oData.aoSearchCols );
  3926. /* Column visibility state
  3927. * Pass back visibility settings to the init handler, but to do not here override
  3928. * the init object that the user might have passed in
  3929. */
  3930. oInit.saved_aoColumns = [];
  3931. for ( var i=0 ; i<oData.abVisCols.length ; i++ )
  3932. {
  3933. oInit.saved_aoColumns[i] = {};
  3934. oInit.saved_aoColumns[i].bVisible = oData.abVisCols[i];
  3935. }
  3936. _fnCallbackFire( oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData] );
  3937. }
  3938. /**
  3939. * Create a new cookie with a value to store the state of a table
  3940. * @param {string} sName name of the cookie to create
  3941. * @param {string} sValue the value the cookie should take
  3942. * @param {int} iSecs duration of the cookie
  3943. * @param {string} sBaseName sName is made up of the base + file name - this is the base
  3944. * @param {function} fnCallback User definable function to modify the cookie
  3945. * @memberof DataTable#oApi
  3946. */
  3947. function _fnCreateCookie ( sName, sValue, iSecs, sBaseName, fnCallback )
  3948. {
  3949. var date = new Date();
  3950. date.setTime( date.getTime()+(iSecs*1000) );
  3951. /*
  3952. * Shocking but true - it would appear IE has major issues with having the path not having
  3953. * a trailing slash on it. We need the cookie to be available based on the path, so we
  3954. * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the
  3955. * patch to use at least some of the path
  3956. */
  3957. var aParts = window.location.pathname.split('/');
  3958. var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g,"").toLowerCase();
  3959. var sFullCookie, oData;
  3960. if ( fnCallback !== null )
  3961. {
  3962. oData = (typeof $.parseJSON === 'function') ?
  3963. $.parseJSON( sValue ) : eval( '('+sValue+')' );
  3964. sFullCookie = fnCallback( sNameFile, oData, date.toGMTString(),
  3965. aParts.join('/')+"/" );
  3966. }
  3967. else
  3968. {
  3969. sFullCookie = sNameFile + "=" + encodeURIComponent(sValue) +
  3970. "; expires=" + date.toGMTString() +"; path=" + aParts.join('/')+"/";
  3971. }
  3972. /* Are we going to go over the cookie limit of 4KiB? If so, try to delete a cookies
  3973. * belonging to DataTables.
  3974. */
  3975. var
  3976. aCookies =document.cookie.split(';'),
  3977. iNewCookieLen = sFullCookie.split(';')[0].length,
  3978. aOldCookies = [];
  3979. if ( iNewCookieLen+document.cookie.length+10 > 4096 ) /* Magic 10 for padding */
  3980. {
  3981. for ( var i=0, iLen=aCookies.length ; i<iLen ; i++ )
  3982. {
  3983. if ( aCookies[i].indexOf( sBaseName ) != -1 )
  3984. {
  3985. /* It's a DataTables cookie, so eval it and check the time stamp */
  3986. var aSplitCookie = aCookies[i].split('=');
  3987. try {
  3988. oData = eval( '('+decodeURIComponent(aSplitCookie[1])+')' );
  3989. if ( oData && oData.iCreate )
  3990. {
  3991. aOldCookies.push( {
  3992. "name": aSplitCookie[0],
  3993. "time": oData.iCreate
  3994. } );
  3995. }
  3996. }
  3997. catch( e ) {}
  3998. }
  3999. }
  4000. // Make sure we delete the oldest ones first
  4001. aOldCookies.sort( function (a, b) {
  4002. return b.time - a.time;
  4003. } );
  4004. // Eliminate as many old DataTables cookies as we need to
  4005. while ( iNewCookieLen + document.cookie.length + 10 > 4096 ) {
  4006. if ( aOldCookies.length === 0 ) {
  4007. // Deleted all DT cookies and still not enough space. Can't state save
  4008. return;
  4009. }
  4010. var old = aOldCookies.pop();
  4011. document.cookie = old.name+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+
  4012. aParts.join('/') + "/";
  4013. }
  4014. }
  4015. document.cookie = sFullCookie;
  4016. }
  4017. /**
  4018. * Read an old cookie to get a cookie with an old table state
  4019. * @param {string} sName name of the cookie to read
  4020. * @returns {string} contents of the cookie - or null if no cookie with that name found
  4021. * @memberof DataTable#oApi
  4022. */
  4023. function _fnReadCookie ( sName )
  4024. {
  4025. var
  4026. aParts = window.location.pathname.split('/'),
  4027. sNameEQ = sName + '_' + aParts[aParts.length-1].replace(/[\/:]/g,"").toLowerCase() + '=',
  4028. sCookieContents = document.cookie.split(';');
  4029. for( var i=0 ; i<sCookieContents.length ; i++ )
  4030. {
  4031. var c = sCookieContents[i];
  4032. while (c.charAt(0)==' ')
  4033. {
  4034. c = c.substring(1,c.length);
  4035. }
  4036. if (c.indexOf(sNameEQ) === 0)
  4037. {
  4038. return decodeURIComponent( c.substring(sNameEQ.length,c.length) );
  4039. }
  4040. }
  4041. return null;
  4042. }
  4043. /**
  4044. * Return the settings object for a particular table
  4045. * @param {node} nTable table we are using as a dataTable
  4046. * @returns {object} Settings object - or null if not found
  4047. * @memberof DataTable#oApi
  4048. */
  4049. function _fnSettingsFromNode ( nTable )
  4050. {
  4051. for ( var i=0 ; i<DataTable.settings.length ; i++ )
  4052. {
  4053. if ( DataTable.settings[i].nTable === nTable )
  4054. {
  4055. return DataTable.settings[i];
  4056. }
  4057. }
  4058. return null;
  4059. }
  4060. /**
  4061. * Return an array with the TR nodes for the table
  4062. * @param {object} oSettings dataTables settings object
  4063. * @returns {array} TR array
  4064. * @memberof DataTable#oApi
  4065. */
  4066. function _fnGetTrNodes ( oSettings )
  4067. {
  4068. var aNodes = [];
  4069. var aoData = oSettings.aoData;
  4070. for ( var i=0, iLen=aoData.length ; i<iLen ; i++ )
  4071. {
  4072. if ( aoData[i].nTr !== null )
  4073. {
  4074. aNodes.push( aoData[i].nTr );
  4075. }
  4076. }
  4077. return aNodes;
  4078. }
  4079. /**
  4080. * Return an flat array with all TD nodes for the table, or row
  4081. * @param {object} oSettings dataTables settings object
  4082. * @param {int} [iIndividualRow] aoData index to get the nodes for - optional
  4083. * if not given then the return array will contain all nodes for the table
  4084. * @returns {array} TD array
  4085. * @memberof DataTable#oApi
  4086. */
  4087. function _fnGetTdNodes ( oSettings, iIndividualRow )
  4088. {
  4089. var anReturn = [];
  4090. var iCorrector;
  4091. var anTds, nTd;
  4092. var iRow, iRows=oSettings.aoData.length,
  4093. iColumn, iColumns, oData, sNodeName, iStart=0, iEnd=iRows;
  4094. /* Allow the collection to be limited to just one row */
  4095. if ( iIndividualRow !== undefined )
  4096. {
  4097. iStart = iIndividualRow;
  4098. iEnd = iIndividualRow+1;
  4099. }
  4100. for ( iRow=iStart ; iRow<iEnd ; iRow++ )
  4101. {
  4102. oData = oSettings.aoData[iRow];
  4103. if ( oData.nTr !== null )
  4104. {
  4105. /* get the TD child nodes - taking into account text etc nodes */
  4106. anTds = [];
  4107. nTd = oData.nTr.firstChild;
  4108. while ( nTd )
  4109. {
  4110. sNodeName = nTd.nodeName.toLowerCase();
  4111. if ( sNodeName == 'td' || sNodeName == 'th' )
  4112. {
  4113. anTds.push( nTd );
  4114. }
  4115. nTd = nTd.nextSibling;
  4116. }
  4117. iCorrector = 0;
  4118. for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ )
  4119. {
  4120. if ( oSettings.aoColumns[iColumn].bVisible )
  4121. {
  4122. anReturn.push( anTds[iColumn-iCorrector] );
  4123. }
  4124. else
  4125. {
  4126. anReturn.push( oData._anHidden[iColumn] );
  4127. iCorrector++;
  4128. }
  4129. }
  4130. }
  4131. }
  4132. return anReturn;
  4133. }
  4134. /**
  4135. * Log an error message
  4136. * @param {object} oSettings dataTables settings object
  4137. * @param {int} iLevel log error messages, or display them to the user
  4138. * @param {string} sMesg error message
  4139. * @memberof DataTable#oApi
  4140. */
  4141. function _fnLog( oSettings, iLevel, sMesg )
  4142. {
  4143. var sAlert = (oSettings===null) ?
  4144. "DataTables warning: "+sMesg :
  4145. "DataTables warning (table id = '"+oSettings.sTableId+"'): "+sMesg;
  4146. if ( iLevel === 0 )
  4147. {
  4148. if ( DataTable.ext.sErrMode == 'alert' )
  4149. {
  4150. alert( sAlert );
  4151. }
  4152. else
  4153. {
  4154. throw new Error(sAlert);
  4155. }
  4156. return;
  4157. }
  4158. else if ( window.console && console.log )
  4159. {
  4160. console.log( sAlert );
  4161. }
  4162. }
  4163. /**
  4164. * See if a property is defined on one object, if so assign it to the other object
  4165. * @param {object} oRet target object
  4166. * @param {object} oSrc source object
  4167. * @param {string} sName property
  4168. * @param {string} [sMappedName] name to map too - optional, sName used if not given
  4169. * @memberof DataTable#oApi
  4170. */
  4171. function _fnMap( oRet, oSrc, sName, sMappedName )
  4172. {
  4173. if ( sMappedName === undefined )
  4174. {
  4175. sMappedName = sName;
  4176. }
  4177. if ( oSrc[sName] !== undefined )
  4178. {
  4179. oRet[sMappedName] = oSrc[sName];
  4180. }
  4181. }
  4182. /**
  4183. * Extend objects - very similar to jQuery.extend, but deep copy objects, and shallow
  4184. * copy arrays. The reason we need to do this, is that we don't want to deep copy array
  4185. * init values (such as aaSorting) since the dev wouldn't be able to override them, but
  4186. * we do want to deep copy arrays.
  4187. * @param {object} oOut Object to extend
  4188. * @param {object} oExtender Object from which the properties will be applied to oOut
  4189. * @returns {object} oOut Reference, just for convenience - oOut === the return.
  4190. * @memberof DataTable#oApi
  4191. * @todo This doesn't take account of arrays inside the deep copied objects.
  4192. */
  4193. function _fnExtend( oOut, oExtender )
  4194. {
  4195. var val;
  4196. for ( var prop in oExtender )
  4197. {
  4198. if ( oExtender.hasOwnProperty(prop) )
  4199. {
  4200. val = oExtender[prop];
  4201. if ( typeof oInit[prop] === 'object' && val !== null && $.isArray(val) === false )
  4202. {
  4203. $.extend( true, oOut[prop], val );
  4204. }
  4205. else
  4206. {
  4207. oOut[prop] = val;
  4208. }
  4209. }
  4210. }
  4211. return oOut;
  4212. }
  4213. /**
  4214. * Bind an event handers to allow a click or return key to activate the callback.
  4215. * This is good for accessibility since a return on the keyboard will have the
  4216. * same effect as a click, if the element has focus.
  4217. * @param {element} n Element to bind the action to
  4218. * @param {object} oData Data object to pass to the triggered function
  4219. * @param {function} fn Callback function for when the event is triggered
  4220. * @memberof DataTable#oApi
  4221. */
  4222. function _fnBindAction( n, oData, fn )
  4223. {
  4224. $(n)
  4225. .bind( 'click.DT', oData, function (e) {
  4226. n.blur(); // Remove focus outline for mouse users
  4227. fn(e);
  4228. } )
  4229. .bind( 'keypress.DT', oData, function (e){
  4230. if ( e.which === 13 ) {
  4231. fn(e);
  4232. } } )
  4233. .bind( 'selectstart.DT', function () {
  4234. /* Take the brutal approach to cancelling text selection */
  4235. return false;
  4236. } );
  4237. }
  4238. /**
  4239. * Register a callback function. Easily allows a callback function to be added to
  4240. * an array store of callback functions that can then all be called together.
  4241. * @param {object} oSettings dataTables settings object
  4242. * @param {string} sStore Name of the array storage for the callbacks in oSettings
  4243. * @param {function} fn Function to be called back
  4244. * @param {string} sName Identifying name for the callback (i.e. a label)
  4245. * @memberof DataTable#oApi
  4246. */
  4247. function _fnCallbackReg( oSettings, sStore, fn, sName )
  4248. {
  4249. if ( fn )
  4250. {
  4251. oSettings[sStore].push( {
  4252. "fn": fn,
  4253. "sName": sName
  4254. } );
  4255. }
  4256. }
  4257. /**
  4258. * Fire callback functions and trigger events. Note that the loop over the callback
  4259. * array store is done backwards! Further note that you do not want to fire off triggers
  4260. * in time sensitive applications (for example cell creation) as its slow.
  4261. * @param {object} oSettings dataTables settings object
  4262. * @param {string} sStore Name of the array storage for the callbacks in oSettings
  4263. * @param {string} sTrigger Name of the jQuery custom event to trigger. If null no trigger
  4264. * is fired
  4265. * @param {array} aArgs Array of arguments to pass to the callback function / trigger
  4266. * @memberof DataTable#oApi
  4267. */
  4268. function _fnCallbackFire( oSettings, sStore, sTrigger, aArgs )
  4269. {
  4270. var aoStore = oSettings[sStore];
  4271. var aRet =[];
  4272. for ( var i=aoStore.length-1 ; i>=0 ; i-- )
  4273. {
  4274. aRet.push( aoStore[i].fn.apply( oSettings.oInstance, aArgs ) );
  4275. }
  4276. if ( sTrigger !== null )
  4277. {
  4278. $(oSettings.oInstance).trigger(sTrigger, aArgs);
  4279. }
  4280. return aRet;
  4281. }
  4282. /**
  4283. * JSON stringify. If JSON.stringify it provided by the browser, json2.js or any other
  4284. * library, then we use that as it is fast, safe and accurate. If the function isn't
  4285. * available then we need to built it ourselves - the inspiration for this function comes
  4286. * from Craig Buckler ( http://www.sitepoint.com/javascript-json-serialization/ ). It is
  4287. * not perfect and absolutely should not be used as a replacement to json2.js - but it does
  4288. * do what we need, without requiring a dependency for DataTables.
  4289. * @param {object} o JSON object to be converted
  4290. * @returns {string} JSON string
  4291. * @memberof DataTable#oApi
  4292. */
  4293. var _fnJsonString = (window.JSON) ? JSON.stringify : function( o )
  4294. {
  4295. /* Not an object or array */
  4296. var sType = typeof o;
  4297. if (sType !== "object" || o === null)
  4298. {
  4299. // simple data type
  4300. if (sType === "string")
  4301. {
  4302. o = '"'+o+'"';
  4303. }
  4304. return o+"";
  4305. }
  4306. /* If object or array, need to recurse over it */
  4307. var
  4308. sProp, mValue,
  4309. json = [],
  4310. bArr = $.isArray(o);
  4311. for (sProp in o)
  4312. {
  4313. mValue = o[sProp];
  4314. sType = typeof mValue;
  4315. if (sType === "string")
  4316. {
  4317. mValue = '"'+mValue+'"';
  4318. }
  4319. else if (sType === "object" && mValue !== null)
  4320. {
  4321. mValue = _fnJsonString(mValue);
  4322. }
  4323. json.push((bArr ? "" : '"'+sProp+'":') + mValue);
  4324. }
  4325. return (bArr ? "[" : "{") + json + (bArr ? "]" : "}");
  4326. };
  4327. /**
  4328. * From some browsers (specifically IE6/7) we need special handling to work around browser
  4329. * bugs - this function is used to detect when these workarounds are needed.
  4330. * @param {object} oSettings dataTables settings object
  4331. * @memberof DataTable#oApi
  4332. */
  4333. function _fnBrowserDetect( oSettings )
  4334. {
  4335. /* IE6/7 will oversize a width 100% element inside a scrolling element, to include the
  4336. * width of the scrollbar, while other browsers ensure the inner element is contained
  4337. * without forcing scrolling
  4338. */
  4339. var n = $(
  4340. '<div style="position:absolute; top:0; left:0; height:1px; width:1px; overflow:hidden">'+
  4341. '<div style="position:absolute; top:1px; left:1px; width:100px; overflow:scroll;">'+
  4342. '<div id="DT_BrowserTest" style="width:100%; height:10px;"></div>'+
  4343. '</div>'+
  4344. '</div>')[0];
  4345. document.body.appendChild( n );
  4346. oSettings.oBrowser.bScrollOversize = $('#DT_BrowserTest', n)[0].offsetWidth === 100 ? true : false;
  4347. document.body.removeChild( n );
  4348. }
  4349. /**
  4350. * Perform a jQuery selector action on the table's TR elements (from the tbody) and
  4351. * return the resulting jQuery object.
  4352. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  4353. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  4354. * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
  4355. * criterion ("applied") or all TR elements (i.e. no filter).
  4356. * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
  4357. * Can be either 'current', whereby the current sorting of the table is used, or
  4358. * 'original' whereby the original order the data was read into the table is used.
  4359. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  4360. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  4361. * 'current' and filter is 'applied', regardless of what they might be given as.
  4362. * @returns {object} jQuery object, filtered by the given selector.
  4363. * @dtopt API
  4364. *
  4365. * @example
  4366. * $(document).ready(function() {
  4367. * var oTable = $('#example').dataTable();
  4368. *
  4369. * // Highlight every second row
  4370. * oTable.$('tr:odd').css('backgroundColor', 'blue');
  4371. * } );
  4372. *
  4373. * @example
  4374. * $(document).ready(function() {
  4375. * var oTable = $('#example').dataTable();
  4376. *
  4377. * // Filter to rows with 'Webkit' in them, add a background colour and then
  4378. * // remove the filter, thus highlighting the 'Webkit' rows only.
  4379. * oTable.fnFilter('Webkit');
  4380. * oTable.$('tr', {"filter": "applied"}).css('backgroundColor', 'blue');
  4381. * oTable.fnFilter('');
  4382. * } );
  4383. */
  4384. this.$ = function ( sSelector, oOpts )
  4385. {
  4386. var i, iLen, a = [], tr;
  4387. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4388. var aoData = oSettings.aoData;
  4389. var aiDisplay = oSettings.aiDisplay;
  4390. var aiDisplayMaster = oSettings.aiDisplayMaster;
  4391. if ( !oOpts )
  4392. {
  4393. oOpts = {};
  4394. }
  4395. oOpts = $.extend( {}, {
  4396. "filter": "none", // applied
  4397. "order": "current", // "original"
  4398. "page": "all" // current
  4399. }, oOpts );
  4400. // Current page implies that order=current and fitler=applied, since it is fairly
  4401. // senseless otherwise
  4402. if ( oOpts.page == 'current' )
  4403. {
  4404. for ( i=oSettings._iDisplayStart, iLen=oSettings.fnDisplayEnd() ; i<iLen ; i++ )
  4405. {
  4406. tr = aoData[ aiDisplay[i] ].nTr;
  4407. if ( tr )
  4408. {
  4409. a.push( tr );
  4410. }
  4411. }
  4412. }
  4413. else if ( oOpts.order == "current" && oOpts.filter == "none" )
  4414. {
  4415. for ( i=0, iLen=aiDisplayMaster.length ; i<iLen ; i++ )
  4416. {
  4417. tr = aoData[ aiDisplayMaster[i] ].nTr;
  4418. if ( tr )
  4419. {
  4420. a.push( tr );
  4421. }
  4422. }
  4423. }
  4424. else if ( oOpts.order == "current" && oOpts.filter == "applied" )
  4425. {
  4426. for ( i=0, iLen=aiDisplay.length ; i<iLen ; i++ )
  4427. {
  4428. tr = aoData[ aiDisplay[i] ].nTr;
  4429. if ( tr )
  4430. {
  4431. a.push( tr );
  4432. }
  4433. }
  4434. }
  4435. else if ( oOpts.order == "original" && oOpts.filter == "none" )
  4436. {
  4437. for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
  4438. {
  4439. tr = aoData[ i ].nTr ;
  4440. if ( tr )
  4441. {
  4442. a.push( tr );
  4443. }
  4444. }
  4445. }
  4446. else if ( oOpts.order == "original" && oOpts.filter == "applied" )
  4447. {
  4448. for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
  4449. {
  4450. tr = aoData[ i ].nTr;
  4451. if ( $.inArray( i, aiDisplay ) !== -1 && tr )
  4452. {
  4453. a.push( tr );
  4454. }
  4455. }
  4456. }
  4457. else
  4458. {
  4459. _fnLog( oSettings, 1, "Unknown selection options" );
  4460. }
  4461. /* We need to filter on the TR elements and also 'find' in their descendants
  4462. * to make the selector act like it would in a full table - so we need
  4463. * to build both results and then combine them together
  4464. */
  4465. var jqA = $(a);
  4466. var jqTRs = jqA.filter( sSelector );
  4467. var jqDescendants = jqA.find( sSelector );
  4468. return $( [].concat($.makeArray(jqTRs), $.makeArray(jqDescendants)) );
  4469. };
  4470. /**
  4471. * Almost identical to $ in operation, but in this case returns the data for the matched
  4472. * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
  4473. * rather than any descendants, so the data can be obtained for the row/cell. If matching
  4474. * rows are found, the data returned is the original data array/object that was used to
  4475. * create the row (or a generated array if from a DOM source).
  4476. *
  4477. * This method is often useful in-combination with $ where both functions are given the
  4478. * same parameters and the array indexes will match identically.
  4479. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  4480. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  4481. * @param {string} [oOpts.filter=none] Select elements that meet the current filter
  4482. * criterion ("applied") or all elements (i.e. no filter).
  4483. * @param {string} [oOpts.order=current] Order of the data in the processed array.
  4484. * Can be either 'current', whereby the current sorting of the table is used, or
  4485. * 'original' whereby the original order the data was read into the table is used.
  4486. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  4487. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  4488. * 'current' and filter is 'applied', regardless of what they might be given as.
  4489. * @returns {array} Data for the matched elements. If any elements, as a result of the
  4490. * selector, were not TR, TD or TH elements in the DataTable, they will have a null
  4491. * entry in the array.
  4492. * @dtopt API
  4493. *
  4494. * @example
  4495. * $(document).ready(function() {
  4496. * var oTable = $('#example').dataTable();
  4497. *
  4498. * // Get the data from the first row in the table
  4499. * var data = oTable._('tr:first');
  4500. *
  4501. * // Do something useful with the data
  4502. * alert( "First cell is: "+data[0] );
  4503. * } );
  4504. *
  4505. * @example
  4506. * $(document).ready(function() {
  4507. * var oTable = $('#example').dataTable();
  4508. *
  4509. * // Filter to 'Webkit' and get all data for
  4510. * oTable.fnFilter('Webkit');
  4511. * var data = oTable._('tr', {"filter": "applied"});
  4512. *
  4513. * // Do something with the data
  4514. * alert( data.length+" rows matched the filter" );
  4515. * } );
  4516. */
  4517. this._ = function ( sSelector, oOpts )
  4518. {
  4519. var aOut = [];
  4520. var i, iLen, iIndex;
  4521. var aTrs = this.$( sSelector, oOpts );
  4522. for ( i=0, iLen=aTrs.length ; i<iLen ; i++ )
  4523. {
  4524. aOut.push( this.fnGetData(aTrs[i]) );
  4525. }
  4526. return aOut;
  4527. };
  4528. /**
  4529. * Add a single new row or multiple rows of data to the table. Please note
  4530. * that this is suitable for client-side processing only - if you are using
  4531. * server-side processing (i.e. "bServerSide": true), then to add data, you
  4532. * must add it to the data source, i.e. the server-side, through an Ajax call.
  4533. * @param {array|object} mData The data to be added to the table. This can be:
  4534. * <ul>
  4535. * <li>1D array of data - add a single row with the data provided</li>
  4536. * <li>2D array of arrays - add multiple rows in a single call</li>
  4537. * <li>object - data object when using <i>mData</i></li>
  4538. * <li>array of objects - multiple data objects when using <i>mData</i></li>
  4539. * </ul>
  4540. * @param {bool} [bRedraw=true] redraw the table or not
  4541. * @returns {array} An array of integers, representing the list of indexes in
  4542. * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
  4543. * the table.
  4544. * @dtopt API
  4545. *
  4546. * @example
  4547. * // Global var for counter
  4548. * var giCount = 2;
  4549. *
  4550. * $(document).ready(function() {
  4551. * $('#example').dataTable();
  4552. * } );
  4553. *
  4554. * function fnClickAddRow() {
  4555. * $('#example').dataTable().fnAddData( [
  4556. * giCount+".1",
  4557. * giCount+".2",
  4558. * giCount+".3",
  4559. * giCount+".4" ]
  4560. * );
  4561. *
  4562. * giCount++;
  4563. * }
  4564. */
  4565. this.fnAddData = function( mData, bRedraw )
  4566. {
  4567. if ( mData.length === 0 )
  4568. {
  4569. return [];
  4570. }
  4571. var aiReturn = [];
  4572. var iTest;
  4573. /* Find settings from table node */
  4574. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4575. /* Check if we want to add multiple rows or not */
  4576. if ( typeof mData[0] === "object" && mData[0] !== null )
  4577. {
  4578. for ( var i=0 ; i<mData.length ; i++ )
  4579. {
  4580. iTest = _fnAddData( oSettings, mData[i] );
  4581. if ( iTest == -1 )
  4582. {
  4583. return aiReturn;
  4584. }
  4585. aiReturn.push( iTest );
  4586. }
  4587. }
  4588. else
  4589. {
  4590. iTest = _fnAddData( oSettings, mData );
  4591. if ( iTest == -1 )
  4592. {
  4593. return aiReturn;
  4594. }
  4595. aiReturn.push( iTest );
  4596. }
  4597. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  4598. if ( bRedraw === undefined || bRedraw )
  4599. {
  4600. _fnReDraw( oSettings );
  4601. }
  4602. return aiReturn;
  4603. };
  4604. /**
  4605. * This function will make DataTables recalculate the column sizes, based on the data
  4606. * contained in the table and the sizes applied to the columns (in the DOM, CSS or
  4607. * through the sWidth parameter). This can be useful when the width of the table's
  4608. * parent element changes (for example a window resize).
  4609. * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
  4610. * @dtopt API
  4611. *
  4612. * @example
  4613. * $(document).ready(function() {
  4614. * var oTable = $('#example').dataTable( {
  4615. * "sScrollY": "200px",
  4616. * "bPaginate": false
  4617. * } );
  4618. *
  4619. * $(window).bind('resize', function () {
  4620. * oTable.fnAdjustColumnSizing();
  4621. * } );
  4622. * } );
  4623. */
  4624. this.fnAdjustColumnSizing = function ( bRedraw )
  4625. {
  4626. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4627. _fnAdjustColumnSizing( oSettings );
  4628. if ( bRedraw === undefined || bRedraw )
  4629. {
  4630. this.fnDraw( false );
  4631. }
  4632. else if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
  4633. {
  4634. /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
  4635. this.oApi._fnScrollDraw(oSettings);
  4636. }
  4637. };
  4638. /**
  4639. * Quickly and simply clear a table
  4640. * @param {bool} [bRedraw=true] redraw the table or not
  4641. * @dtopt API
  4642. *
  4643. * @example
  4644. * $(document).ready(function() {
  4645. * var oTable = $('#example').dataTable();
  4646. *
  4647. * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
  4648. * oTable.fnClearTable();
  4649. * } );
  4650. */
  4651. this.fnClearTable = function( bRedraw )
  4652. {
  4653. /* Find settings from table node */
  4654. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4655. _fnClearTable( oSettings );
  4656. if ( bRedraw === undefined || bRedraw )
  4657. {
  4658. _fnDraw( oSettings );
  4659. }
  4660. };
  4661. /**
  4662. * The exact opposite of 'opening' a row, this function will close any rows which
  4663. * are currently 'open'.
  4664. * @param {node} nTr the table row to 'close'
  4665. * @returns {int} 0 on success, or 1 if failed (can't find the row)
  4666. * @dtopt API
  4667. *
  4668. * @example
  4669. * $(document).ready(function() {
  4670. * var oTable;
  4671. *
  4672. * // 'open' an information row when a row is clicked on
  4673. * $('#example tbody tr').click( function () {
  4674. * if ( oTable.fnIsOpen(this) ) {
  4675. * oTable.fnClose( this );
  4676. * } else {
  4677. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  4678. * }
  4679. * } );
  4680. *
  4681. * oTable = $('#example').dataTable();
  4682. * } );
  4683. */
  4684. this.fnClose = function( nTr )
  4685. {
  4686. /* Find settings from table node */
  4687. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4688. for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ )
  4689. {
  4690. if ( oSettings.aoOpenRows[i].nParent == nTr )
  4691. {
  4692. var nTrParent = oSettings.aoOpenRows[i].nTr.parentNode;
  4693. if ( nTrParent )
  4694. {
  4695. /* Remove it if it is currently on display */
  4696. nTrParent.removeChild( oSettings.aoOpenRows[i].nTr );
  4697. }
  4698. oSettings.aoOpenRows.splice( i, 1 );
  4699. return 0;
  4700. }
  4701. }
  4702. return 1;
  4703. };
  4704. /**
  4705. * Remove a row for the table
  4706. * @param {mixed} mTarget The index of the row from aoData to be deleted, or
  4707. * the TR element you want to delete
  4708. * @param {function|null} [fnCallBack] Callback function
  4709. * @param {bool} [bRedraw=true] Redraw the table or not
  4710. * @returns {array} The row that was deleted
  4711. * @dtopt API
  4712. *
  4713. * @example
  4714. * $(document).ready(function() {
  4715. * var oTable = $('#example').dataTable();
  4716. *
  4717. * // Immediately remove the first row
  4718. * oTable.fnDeleteRow( 0 );
  4719. * } );
  4720. */
  4721. this.fnDeleteRow = function( mTarget, fnCallBack, bRedraw )
  4722. {
  4723. /* Find settings from table node */
  4724. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4725. var i, iLen, iAODataIndex;
  4726. iAODataIndex = (typeof mTarget === 'object') ?
  4727. _fnNodeToDataIndex(oSettings, mTarget) : mTarget;
  4728. /* Return the data array from this row */
  4729. var oData = oSettings.aoData.splice( iAODataIndex, 1 );
  4730. /* Update the _DT_RowIndex parameter */
  4731. for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
  4732. {
  4733. if ( oSettings.aoData[i].nTr !== null )
  4734. {
  4735. oSettings.aoData[i].nTr._DT_RowIndex = i;
  4736. }
  4737. }
  4738. /* Remove the target row from the search array */
  4739. var iDisplayIndex = $.inArray( iAODataIndex, oSettings.aiDisplay );
  4740. oSettings.asDataSearch.splice( iDisplayIndex, 1 );
  4741. /* Delete from the display arrays */
  4742. _fnDeleteIndex( oSettings.aiDisplayMaster, iAODataIndex );
  4743. _fnDeleteIndex( oSettings.aiDisplay, iAODataIndex );
  4744. /* If there is a user callback function - call it */
  4745. if ( typeof fnCallBack === "function" )
  4746. {
  4747. fnCallBack.call( this, oSettings, oData );
  4748. }
  4749. /* Check for an 'overflow' they case for displaying the table */
  4750. if ( oSettings._iDisplayStart >= oSettings.fnRecordsDisplay() )
  4751. {
  4752. oSettings._iDisplayStart -= oSettings._iDisplayLength;
  4753. if ( oSettings._iDisplayStart < 0 )
  4754. {
  4755. oSettings._iDisplayStart = 0;
  4756. }
  4757. }
  4758. if ( bRedraw === undefined || bRedraw )
  4759. {
  4760. _fnCalculateEnd( oSettings );
  4761. _fnDraw( oSettings );
  4762. }
  4763. return oData;
  4764. };
  4765. /**
  4766. * Restore the table to it's original state in the DOM by removing all of DataTables
  4767. * enhancements, alterations to the DOM structure of the table and event listeners.
  4768. * @param {boolean} [bRemove=false] Completely remove the table from the DOM
  4769. * @dtopt API
  4770. *
  4771. * @example
  4772. * $(document).ready(function() {
  4773. * // This example is fairly pointless in reality, but shows how fnDestroy can be used
  4774. * var oTable = $('#example').dataTable();
  4775. * oTable.fnDestroy();
  4776. * } );
  4777. */
  4778. this.fnDestroy = function ( bRemove )
  4779. {
  4780. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4781. var nOrig = oSettings.nTableWrapper.parentNode;
  4782. var nBody = oSettings.nTBody;
  4783. var i, iLen;
  4784. bRemove = (bRemove===undefined) ? false : bRemove;
  4785. /* Flag to note that the table is currently being destroyed - no action should be taken */
  4786. oSettings.bDestroying = true;
  4787. /* Fire off the destroy callbacks for plug-ins etc */
  4788. _fnCallbackFire( oSettings, "aoDestroyCallback", "destroy", [oSettings] );
  4789. /* If the table is not being removed, restore the hidden columns */
  4790. if ( !bRemove )
  4791. {
  4792. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  4793. {
  4794. if ( oSettings.aoColumns[i].bVisible === false )
  4795. {
  4796. this.fnSetColumnVis( i, true );
  4797. }
  4798. }
  4799. }
  4800. /* Blitz all DT events */
  4801. $(oSettings.nTableWrapper).find('*').andSelf().unbind('.DT');
  4802. /* If there is an 'empty' indicator row, remove it */
  4803. $('tbody>tr>td.'+oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove();
  4804. /* When scrolling we had to break the table up - restore it */
  4805. if ( oSettings.nTable != oSettings.nTHead.parentNode )
  4806. {
  4807. $(oSettings.nTable).children('thead').remove();
  4808. oSettings.nTable.appendChild( oSettings.nTHead );
  4809. }
  4810. if ( oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode )
  4811. {
  4812. $(oSettings.nTable).children('tfoot').remove();
  4813. oSettings.nTable.appendChild( oSettings.nTFoot );
  4814. }
  4815. /* Remove the DataTables generated nodes, events and classes */
  4816. oSettings.nTable.parentNode.removeChild( oSettings.nTable );
  4817. $(oSettings.nTableWrapper).remove();
  4818. oSettings.aaSorting = [];
  4819. oSettings.aaSortingFixed = [];
  4820. _fnSortingClasses( oSettings );
  4821. $(_fnGetTrNodes( oSettings )).removeClass( oSettings.asStripeClasses.join(' ') );
  4822. $('th, td', oSettings.nTHead).removeClass( [
  4823. oSettings.oClasses.sSortable,
  4824. oSettings.oClasses.sSortableAsc,
  4825. oSettings.oClasses.sSortableDesc,
  4826. oSettings.oClasses.sSortableNone ].join(' ')
  4827. );
  4828. if ( oSettings.bJUI )
  4829. {
  4830. $('th span.'+oSettings.oClasses.sSortIcon
  4831. + ', td span.'+oSettings.oClasses.sSortIcon, oSettings.nTHead).remove();
  4832. $('th, td', oSettings.nTHead).each( function () {
  4833. var jqWrapper = $('div.'+oSettings.oClasses.sSortJUIWrapper, this);
  4834. var kids = jqWrapper.contents();
  4835. $(this).append( kids );
  4836. jqWrapper.remove();
  4837. } );
  4838. }
  4839. /* Add the TR elements back into the table in their original order */
  4840. if ( !bRemove && oSettings.nTableReinsertBefore )
  4841. {
  4842. nOrig.insertBefore( oSettings.nTable, oSettings.nTableReinsertBefore );
  4843. }
  4844. else if ( !bRemove )
  4845. {
  4846. nOrig.appendChild( oSettings.nTable );
  4847. }
  4848. for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
  4849. {
  4850. if ( oSettings.aoData[i].nTr !== null )
  4851. {
  4852. nBody.appendChild( oSettings.aoData[i].nTr );
  4853. }
  4854. }
  4855. /* Restore the width of the original table */
  4856. if ( oSettings.oFeatures.bAutoWidth === true )
  4857. {
  4858. oSettings.nTable.style.width = _fnStringToCss(oSettings.sDestroyWidth);
  4859. }
  4860. /* If the were originally stripe classes - then we add them back here. Note
  4861. * this is not fool proof (for example if not all rows had stripe classes - but
  4862. * it's a good effort without getting carried away
  4863. */
  4864. iLen = oSettings.asDestroyStripes.length;
  4865. if (iLen)
  4866. {
  4867. var anRows = $(nBody).children('tr');
  4868. for ( i=0 ; i<iLen ; i++ )
  4869. {
  4870. anRows.filter(':nth-child(' + iLen + 'n + ' + i + ')').addClass( oSettings.asDestroyStripes[i] );
  4871. }
  4872. }
  4873. /* Remove the settings object from the settings array */
  4874. for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ )
  4875. {
  4876. if ( DataTable.settings[i] == oSettings )
  4877. {
  4878. DataTable.settings.splice( i, 1 );
  4879. }
  4880. }
  4881. /* End it all */
  4882. oSettings = null;
  4883. oInit = null;
  4884. };
  4885. /**
  4886. * Redraw the table
  4887. * @param {bool} [bComplete=true] Re-filter and resort (if enabled) the table before the draw.
  4888. * @dtopt API
  4889. *
  4890. * @example
  4891. * $(document).ready(function() {
  4892. * var oTable = $('#example').dataTable();
  4893. *
  4894. * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
  4895. * oTable.fnDraw();
  4896. * } );
  4897. */
  4898. this.fnDraw = function( bComplete )
  4899. {
  4900. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4901. if ( bComplete === false )
  4902. {
  4903. _fnCalculateEnd( oSettings );
  4904. _fnDraw( oSettings );
  4905. }
  4906. else
  4907. {
  4908. _fnReDraw( oSettings );
  4909. }
  4910. };
  4911. /**
  4912. * Filter the input based on data
  4913. * @param {string} sInput String to filter the table on
  4914. * @param {int|null} [iColumn] Column to limit filtering to
  4915. * @param {bool} [bRegex=false] Treat as regular expression or not
  4916. * @param {bool} [bSmart=true] Perform smart filtering or not
  4917. * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
  4918. * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
  4919. * @dtopt API
  4920. *
  4921. * @example
  4922. * $(document).ready(function() {
  4923. * var oTable = $('#example').dataTable();
  4924. *
  4925. * // Sometime later - filter...
  4926. * oTable.fnFilter( 'test string' );
  4927. * } );
  4928. */
  4929. this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
  4930. {
  4931. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4932. if ( !oSettings.oFeatures.bFilter )
  4933. {
  4934. return;
  4935. }
  4936. if ( bRegex === undefined || bRegex === null )
  4937. {
  4938. bRegex = false;
  4939. }
  4940. if ( bSmart === undefined || bSmart === null )
  4941. {
  4942. bSmart = true;
  4943. }
  4944. if ( bShowGlobal === undefined || bShowGlobal === null )
  4945. {
  4946. bShowGlobal = true;
  4947. }
  4948. if ( bCaseInsensitive === undefined || bCaseInsensitive === null )
  4949. {
  4950. bCaseInsensitive = true;
  4951. }
  4952. if ( iColumn === undefined || iColumn === null )
  4953. {
  4954. /* Global filter */
  4955. _fnFilterComplete( oSettings, {
  4956. "sSearch":sInput+"",
  4957. "bRegex": bRegex,
  4958. "bSmart": bSmart,
  4959. "bCaseInsensitive": bCaseInsensitive
  4960. }, 1 );
  4961. if ( bShowGlobal && oSettings.aanFeatures.f )
  4962. {
  4963. var n = oSettings.aanFeatures.f;
  4964. for ( var i=0, iLen=n.length ; i<iLen ; i++ )
  4965. {
  4966. // IE9 throws an 'unknown error' if document.activeElement is used
  4967. // inside an iframe or frame...
  4968. try {
  4969. if ( n[i]._DT_Input != document.activeElement )
  4970. {
  4971. $(n[i]._DT_Input).val( sInput );
  4972. }
  4973. }
  4974. catch ( e ) {
  4975. $(n[i]._DT_Input).val( sInput );
  4976. }
  4977. }
  4978. }
  4979. }
  4980. else
  4981. {
  4982. /* Single column filter */
  4983. $.extend( oSettings.aoPreSearchCols[ iColumn ], {
  4984. "sSearch": sInput+"",
  4985. "bRegex": bRegex,
  4986. "bSmart": bSmart,
  4987. "bCaseInsensitive": bCaseInsensitive
  4988. } );
  4989. _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
  4990. }
  4991. };
  4992. /**
  4993. * Get the data for the whole table, an individual row or an individual cell based on the
  4994. * provided parameters.
  4995. * @param {int|node} [mRow] A TR row node, TD/TH cell node or an integer. If given as
  4996. * a TR node then the data source for the whole row will be returned. If given as a
  4997. * TD/TH cell node then iCol will be automatically calculated and the data for the
  4998. * cell returned. If given as an integer, then this is treated as the aoData internal
  4999. * data index for the row (see fnGetPosition) and the data for that row used.
  5000. * @param {int} [iCol] Optional column index that you want the data of.
  5001. * @returns {array|object|string} If mRow is undefined, then the data for all rows is
  5002. * returned. If mRow is defined, just data for that row, and is iCol is
  5003. * defined, only data for the designated cell is returned.
  5004. * @dtopt API
  5005. *
  5006. * @example
  5007. * // Row data
  5008. * $(document).ready(function() {
  5009. * oTable = $('#example').dataTable();
  5010. *
  5011. * oTable.$('tr').click( function () {
  5012. * var data = oTable.fnGetData( this );
  5013. * // ... do something with the array / object of data for the row
  5014. * } );
  5015. * } );
  5016. *
  5017. * @example
  5018. * // Individual cell data
  5019. * $(document).ready(function() {
  5020. * oTable = $('#example').dataTable();
  5021. *
  5022. * oTable.$('td').click( function () {
  5023. * var sData = oTable.fnGetData( this );
  5024. * alert( 'The cell clicked on had the value of '+sData );
  5025. * } );
  5026. * } );
  5027. */
  5028. this.fnGetData = function( mRow, iCol )
  5029. {
  5030. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5031. if ( mRow !== undefined )
  5032. {
  5033. var iRow = mRow;
  5034. if ( typeof mRow === 'object' )
  5035. {
  5036. var sNode = mRow.nodeName.toLowerCase();
  5037. if (sNode === "tr" )
  5038. {
  5039. iRow = _fnNodeToDataIndex(oSettings, mRow);
  5040. }
  5041. else if ( sNode === "td" )
  5042. {
  5043. iRow = _fnNodeToDataIndex(oSettings, mRow.parentNode);
  5044. iCol = _fnNodeToColumnIndex( oSettings, iRow, mRow );
  5045. }
  5046. }
  5047. if ( iCol !== undefined )
  5048. {
  5049. return _fnGetCellData( oSettings, iRow, iCol, '' );
  5050. }
  5051. return (oSettings.aoData[iRow]!==undefined) ?
  5052. oSettings.aoData[iRow]._aData : null;
  5053. }
  5054. return _fnGetDataMaster( oSettings );
  5055. };
  5056. /**
  5057. * Get an array of the TR nodes that are used in the table's body. Note that you will
  5058. * typically want to use the '$' API method in preference to this as it is more
  5059. * flexible.
  5060. * @param {int} [iRow] Optional row index for the TR element you want
  5061. * @returns {array|node} If iRow is undefined, returns an array of all TR elements
  5062. * in the table's body, or iRow is defined, just the TR element requested.
  5063. * @dtopt API
  5064. *
  5065. * @example
  5066. * $(document).ready(function() {
  5067. * var oTable = $('#example').dataTable();
  5068. *
  5069. * // Get the nodes from the table
  5070. * var nNodes = oTable.fnGetNodes( );
  5071. * } );
  5072. */
  5073. this.fnGetNodes = function( iRow )
  5074. {
  5075. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5076. if ( iRow !== undefined ) {
  5077. return (oSettings.aoData[iRow]!==undefined) ?
  5078. oSettings.aoData[iRow].nTr : null;
  5079. }
  5080. return _fnGetTrNodes( oSettings );
  5081. };
  5082. /**
  5083. * Get the array indexes of a particular cell from it's DOM element
  5084. * and column index including hidden columns
  5085. * @param {node} nNode this can either be a TR, TD or TH in the table's body
  5086. * @returns {int} If nNode is given as a TR, then a single index is returned, or
  5087. * if given as a cell, an array of [row index, column index (visible),
  5088. * column index (all)] is given.
  5089. * @dtopt API
  5090. *
  5091. * @example
  5092. * $(document).ready(function() {
  5093. * $('#example tbody td').click( function () {
  5094. * // Get the position of the current data from the node
  5095. * var aPos = oTable.fnGetPosition( this );
  5096. *
  5097. * // Get the data array for this row
  5098. * var aData = oTable.fnGetData( aPos[0] );
  5099. *
  5100. * // Update the data array and return the value
  5101. * aData[ aPos[1] ] = 'clicked';
  5102. * this.innerHTML = 'clicked';
  5103. * } );
  5104. *
  5105. * // Init DataTables
  5106. * oTable = $('#example').dataTable();
  5107. * } );
  5108. */
  5109. this.fnGetPosition = function( nNode )
  5110. {
  5111. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5112. var sNodeName = nNode.nodeName.toUpperCase();
  5113. if ( sNodeName == "TR" )
  5114. {
  5115. return _fnNodeToDataIndex(oSettings, nNode);
  5116. }
  5117. else if ( sNodeName == "TD" || sNodeName == "TH" )
  5118. {
  5119. var iDataIndex = _fnNodeToDataIndex( oSettings, nNode.parentNode );
  5120. var iColumnIndex = _fnNodeToColumnIndex( oSettings, iDataIndex, nNode );
  5121. return [ iDataIndex, _fnColumnIndexToVisible(oSettings, iColumnIndex ), iColumnIndex ];
  5122. }
  5123. return null;
  5124. };
  5125. /**
  5126. * Check to see if a row is 'open' or not.
  5127. * @param {node} nTr the table row to check
  5128. * @returns {boolean} true if the row is currently open, false otherwise
  5129. * @dtopt API
  5130. *
  5131. * @example
  5132. * $(document).ready(function() {
  5133. * var oTable;
  5134. *
  5135. * // 'open' an information row when a row is clicked on
  5136. * $('#example tbody tr').click( function () {
  5137. * if ( oTable.fnIsOpen(this) ) {
  5138. * oTable.fnClose( this );
  5139. * } else {
  5140. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  5141. * }
  5142. * } );
  5143. *
  5144. * oTable = $('#example').dataTable();
  5145. * } );
  5146. */
  5147. this.fnIsOpen = function( nTr )
  5148. {
  5149. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5150. var aoOpenRows = oSettings.aoOpenRows;
  5151. for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ )
  5152. {
  5153. if ( oSettings.aoOpenRows[i].nParent == nTr )
  5154. {
  5155. return true;
  5156. }
  5157. }
  5158. return false;
  5159. };
  5160. /**
  5161. * This function will place a new row directly after a row which is currently
  5162. * on display on the page, with the HTML contents that is passed into the
  5163. * function. This can be used, for example, to ask for confirmation that a
  5164. * particular record should be deleted.
  5165. * @param {node} nTr The table row to 'open'
  5166. * @param {string|node|jQuery} mHtml The HTML to put into the row
  5167. * @param {string} sClass Class to give the new TD cell
  5168. * @returns {node} The row opened. Note that if the table row passed in as the
  5169. * first parameter, is not found in the table, this method will silently
  5170. * return.
  5171. * @dtopt API
  5172. *
  5173. * @example
  5174. * $(document).ready(function() {
  5175. * var oTable;
  5176. *
  5177. * // 'open' an information row when a row is clicked on
  5178. * $('#example tbody tr').click( function () {
  5179. * if ( oTable.fnIsOpen(this) ) {
  5180. * oTable.fnClose( this );
  5181. * } else {
  5182. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  5183. * }
  5184. * } );
  5185. *
  5186. * oTable = $('#example').dataTable();
  5187. * } );
  5188. */
  5189. this.fnOpen = function( nTr, mHtml, sClass )
  5190. {
  5191. /* Find settings from table node */
  5192. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5193. /* Check that the row given is in the table */
  5194. var nTableRows = _fnGetTrNodes( oSettings );
  5195. if ( $.inArray(nTr, nTableRows) === -1 )
  5196. {
  5197. return;
  5198. }
  5199. /* the old open one if there is one */
  5200. this.fnClose( nTr );
  5201. var nNewRow = document.createElement("tr");
  5202. var nNewCell = document.createElement("td");
  5203. nNewRow.appendChild( nNewCell );
  5204. nNewCell.className = sClass;
  5205. nNewCell.colSpan = _fnVisbleColumns( oSettings );
  5206. if (typeof mHtml === "string")
  5207. {
  5208. nNewCell.innerHTML = mHtml;
  5209. }
  5210. else
  5211. {
  5212. $(nNewCell).html( mHtml );
  5213. }
  5214. /* If the nTr isn't on the page at the moment - then we don't insert at the moment */
  5215. var nTrs = $('tr', oSettings.nTBody);
  5216. if ( $.inArray(nTr, nTrs) != -1 )
  5217. {
  5218. $(nNewRow).insertAfter(nTr);
  5219. }
  5220. oSettings.aoOpenRows.push( {
  5221. "nTr": nNewRow,
  5222. "nParent": nTr
  5223. } );
  5224. return nNewRow;
  5225. };
  5226. /**
  5227. * Change the pagination - provides the internal logic for pagination in a simple API
  5228. * function. With this function you can have a DataTables table go to the next,
  5229. * previous, first or last pages.
  5230. * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
  5231. * or page number to jump to (integer), note that page 0 is the first page.
  5232. * @param {bool} [bRedraw=true] Redraw the table or not
  5233. * @dtopt API
  5234. *
  5235. * @example
  5236. * $(document).ready(function() {
  5237. * var oTable = $('#example').dataTable();
  5238. * oTable.fnPageChange( 'next' );
  5239. * } );
  5240. */
  5241. this.fnPageChange = function ( mAction, bRedraw )
  5242. {
  5243. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5244. _fnPageChange( oSettings, mAction );
  5245. _fnCalculateEnd( oSettings );
  5246. if ( bRedraw === undefined || bRedraw )
  5247. {
  5248. _fnDraw( oSettings );
  5249. }
  5250. };
  5251. /**
  5252. * Show a particular column
  5253. * @param {int} iCol The column whose display should be changed
  5254. * @param {bool} bShow Show (true) or hide (false) the column
  5255. * @param {bool} [bRedraw=true] Redraw the table or not
  5256. * @dtopt API
  5257. *
  5258. * @example
  5259. * $(document).ready(function() {
  5260. * var oTable = $('#example').dataTable();
  5261. *
  5262. * // Hide the second column after initialisation
  5263. * oTable.fnSetColumnVis( 1, false );
  5264. * } );
  5265. */
  5266. this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
  5267. {
  5268. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5269. var i, iLen;
  5270. var aoColumns = oSettings.aoColumns;
  5271. var aoData = oSettings.aoData;
  5272. var nTd, bAppend, iBefore;
  5273. /* No point in doing anything if we are requesting what is already true */
  5274. if ( aoColumns[iCol].bVisible == bShow )
  5275. {
  5276. return;
  5277. }
  5278. /* Show the column */
  5279. if ( bShow )
  5280. {
  5281. var iInsert = 0;
  5282. for ( i=0 ; i<iCol ; i++ )
  5283. {
  5284. if ( aoColumns[i].bVisible )
  5285. {
  5286. iInsert++;
  5287. }
  5288. }
  5289. /* Need to decide if we should use appendChild or insertBefore */
  5290. bAppend = (iInsert >= _fnVisbleColumns( oSettings ));
  5291. /* Which coloumn should we be inserting before? */
  5292. if ( !bAppend )
  5293. {
  5294. for ( i=iCol ; i<aoColumns.length ; i++ )
  5295. {
  5296. if ( aoColumns[i].bVisible )
  5297. {
  5298. iBefore = i;
  5299. break;
  5300. }
  5301. }
  5302. }
  5303. for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
  5304. {
  5305. if ( aoData[i].nTr !== null )
  5306. {
  5307. if ( bAppend )
  5308. {
  5309. aoData[i].nTr.appendChild(
  5310. aoData[i]._anHidden[iCol]
  5311. );
  5312. }
  5313. else
  5314. {
  5315. aoData[i].nTr.insertBefore(
  5316. aoData[i]._anHidden[iCol],
  5317. _fnGetTdNodes( oSettings, i )[iBefore] );
  5318. }
  5319. }
  5320. }
  5321. }
  5322. else
  5323. {
  5324. /* Remove a column from display */
  5325. for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
  5326. {
  5327. if ( aoData[i].nTr !== null )
  5328. {
  5329. nTd = _fnGetTdNodes( oSettings, i )[iCol];
  5330. aoData[i]._anHidden[iCol] = nTd;
  5331. nTd.parentNode.removeChild( nTd );
  5332. }
  5333. }
  5334. }
  5335. /* Clear to set the visible flag */
  5336. aoColumns[iCol].bVisible = bShow;
  5337. /* Redraw the header and footer based on the new column visibility */
  5338. _fnDrawHead( oSettings, oSettings.aoHeader );
  5339. if ( oSettings.nTFoot )
  5340. {
  5341. _fnDrawHead( oSettings, oSettings.aoFooter );
  5342. }
  5343. /* If there are any 'open' rows, then we need to alter the colspan for this col change */
  5344. for ( i=0, iLen=oSettings.aoOpenRows.length ; i<iLen ; i++ )
  5345. {
  5346. oSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns( oSettings );
  5347. }
  5348. /* Do a redraw incase anything depending on the table columns needs it
  5349. * (built-in: scrolling)
  5350. */
  5351. if ( bRedraw === undefined || bRedraw )
  5352. {
  5353. _fnAdjustColumnSizing( oSettings );
  5354. _fnDraw( oSettings );
  5355. }
  5356. _fnSaveState( oSettings );
  5357. };
  5358. /**
  5359. * Get the settings for a particular table for external manipulation
  5360. * @returns {object} DataTables settings object. See
  5361. * {@link DataTable.models.oSettings}
  5362. * @dtopt API
  5363. *
  5364. * @example
  5365. * $(document).ready(function() {
  5366. * var oTable = $('#example').dataTable();
  5367. * var oSettings = oTable.fnSettings();
  5368. *
  5369. * // Show an example parameter from the settings
  5370. * alert( oSettings._iDisplayStart );
  5371. * } );
  5372. */
  5373. this.fnSettings = function()
  5374. {
  5375. return _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5376. };
  5377. /**
  5378. * Sort the table by a particular column
  5379. * @param {int} iCol the data index to sort on. Note that this will not match the
  5380. * 'display index' if you have hidden data entries
  5381. * @dtopt API
  5382. *
  5383. * @example
  5384. * $(document).ready(function() {
  5385. * var oTable = $('#example').dataTable();
  5386. *
  5387. * // Sort immediately with columns 0 and 1
  5388. * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
  5389. * } );
  5390. */
  5391. this.fnSort = function( aaSort )
  5392. {
  5393. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5394. oSettings.aaSorting = aaSort;
  5395. _fnSort( oSettings );
  5396. };
  5397. /**
  5398. * Attach a sort listener to an element for a given column
  5399. * @param {node} nNode the element to attach the sort listener to
  5400. * @param {int} iColumn the column that a click on this node will sort on
  5401. * @param {function} [fnCallback] callback function when sort is run
  5402. * @dtopt API
  5403. *
  5404. * @example
  5405. * $(document).ready(function() {
  5406. * var oTable = $('#example').dataTable();
  5407. *
  5408. * // Sort on column 1, when 'sorter' is clicked on
  5409. * oTable.fnSortListener( document.getElementById('sorter'), 1 );
  5410. * } );
  5411. */
  5412. this.fnSortListener = function( nNode, iColumn, fnCallback )
  5413. {
  5414. _fnSortAttachListener( _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ), nNode, iColumn,
  5415. fnCallback );
  5416. };
  5417. /**
  5418. * Update a table cell or row - this method will accept either a single value to
  5419. * update the cell with, an array of values with one element for each column or
  5420. * an object in the same format as the original data source. The function is
  5421. * self-referencing in order to make the multi column updates easier.
  5422. * @param {object|array|string} mData Data to update the cell/row with
  5423. * @param {node|int} mRow TR element you want to update or the aoData index
  5424. * @param {int} [iColumn] The column to update (not used of mData is an array or object)
  5425. * @param {bool} [bRedraw=true] Redraw the table or not
  5426. * @param {bool} [bAction=true] Perform pre-draw actions or not
  5427. * @returns {int} 0 on success, 1 on error
  5428. * @dtopt API
  5429. *
  5430. * @example
  5431. * $(document).ready(function() {
  5432. * var oTable = $('#example').dataTable();
  5433. * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
  5434. * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], 1, 0 ); // Row
  5435. * } );
  5436. */
  5437. this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
  5438. {
  5439. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5440. var i, iLen, sDisplay;
  5441. var iRow = (typeof mRow === 'object') ?
  5442. _fnNodeToDataIndex(oSettings, mRow) : mRow;
  5443. if ( $.isArray(mData) && iColumn === undefined )
  5444. {
  5445. /* Array update - update the whole row */
  5446. oSettings.aoData[iRow]._aData = mData.slice();
  5447. /* Flag to the function that we are recursing */
  5448. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  5449. {
  5450. this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false );
  5451. }
  5452. }
  5453. else if ( $.isPlainObject(mData) && iColumn === undefined )
  5454. {
  5455. /* Object update - update the whole row - assume the developer gets the object right */
  5456. oSettings.aoData[iRow]._aData = $.extend( true, {}, mData );
  5457. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  5458. {
  5459. this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false );
  5460. }
  5461. }
  5462. else
  5463. {
  5464. /* Individual cell update */
  5465. _fnSetCellData( oSettings, iRow, iColumn, mData );
  5466. sDisplay = _fnGetCellData( oSettings, iRow, iColumn, 'display' );
  5467. var oCol = oSettings.aoColumns[iColumn];
  5468. if ( oCol.fnRender !== null )
  5469. {
  5470. sDisplay = _fnRender( oSettings, iRow, iColumn );
  5471. if ( oCol.bUseRendered )
  5472. {
  5473. _fnSetCellData( oSettings, iRow, iColumn, sDisplay );
  5474. }
  5475. }
  5476. if ( oSettings.aoData[iRow].nTr !== null )
  5477. {
  5478. /* Do the actual HTML update */
  5479. _fnGetTdNodes( oSettings, iRow )[iColumn].innerHTML = sDisplay;
  5480. }
  5481. }
  5482. /* Modify the search index for this row (strictly this is likely not needed, since fnReDraw
  5483. * will rebuild the search array - however, the redraw might be disabled by the user)
  5484. */
  5485. var iDisplayIndex = $.inArray( iRow, oSettings.aiDisplay );
  5486. oSettings.asDataSearch[iDisplayIndex] = _fnBuildSearchRow(
  5487. oSettings,
  5488. _fnGetRowData( oSettings, iRow, 'filter', _fnGetColumns( oSettings, 'bSearchable' ) )
  5489. );
  5490. /* Perform pre-draw actions */
  5491. if ( bAction === undefined || bAction )
  5492. {
  5493. _fnAdjustColumnSizing( oSettings );
  5494. }
  5495. /* Redraw the table */
  5496. if ( bRedraw === undefined || bRedraw )
  5497. {
  5498. _fnReDraw( oSettings );
  5499. }
  5500. return 0;
  5501. };
  5502. /**
  5503. * Provide a common method for plug-ins to check the version of DataTables being used, in order
  5504. * to ensure compatibility.
  5505. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
  5506. * formats "X" and "X.Y" are also acceptable.
  5507. * @returns {boolean} true if this version of DataTables is greater or equal to the required
  5508. * version, or false if this version of DataTales is not suitable
  5509. * @method
  5510. * @dtopt API
  5511. *
  5512. * @example
  5513. * $(document).ready(function() {
  5514. * var oTable = $('#example').dataTable();
  5515. * alert( oTable.fnVersionCheck( '1.9.0' ) );
  5516. * } );
  5517. */
  5518. this.fnVersionCheck = DataTable.ext.fnVersionCheck;
  5519. /*
  5520. * This is really a good bit rubbish this method of exposing the internal methods
  5521. * publicly... - To be fixed in 2.0 using methods on the prototype
  5522. */
  5523. /**
  5524. * Create a wrapper function for exporting an internal functions to an external API.
  5525. * @param {string} sFunc API function name
  5526. * @returns {function} wrapped function
  5527. * @memberof DataTable#oApi
  5528. */
  5529. function _fnExternApiFunc (sFunc)
  5530. {
  5531. return function() {
  5532. var aArgs = [_fnSettingsFromNode(this[DataTable.ext.iApiIndex])].concat(
  5533. Array.prototype.slice.call(arguments) );
  5534. return DataTable.ext.oApi[sFunc].apply( this, aArgs );
  5535. };
  5536. }
  5537. /**
  5538. * Reference to internal functions for use by plug-in developers. Note that these
  5539. * methods are references to internal functions and are considered to be private.
  5540. * If you use these methods, be aware that they are liable to change between versions
  5541. * (check the upgrade notes).
  5542. * @namespace
  5543. */
  5544. this.oApi = {
  5545. "_fnExternApiFunc": _fnExternApiFunc,
  5546. "_fnInitialise": _fnInitialise,
  5547. "_fnInitComplete": _fnInitComplete,
  5548. "_fnLanguageCompat": _fnLanguageCompat,
  5549. "_fnAddColumn": _fnAddColumn,
  5550. "_fnColumnOptions": _fnColumnOptions,
  5551. "_fnAddData": _fnAddData,
  5552. "_fnCreateTr": _fnCreateTr,
  5553. "_fnGatherData": _fnGatherData,
  5554. "_fnBuildHead": _fnBuildHead,
  5555. "_fnDrawHead": _fnDrawHead,
  5556. "_fnDraw": _fnDraw,
  5557. "_fnReDraw": _fnReDraw,
  5558. "_fnAjaxUpdate": _fnAjaxUpdate,
  5559. "_fnAjaxParameters": _fnAjaxParameters,
  5560. "_fnAjaxUpdateDraw": _fnAjaxUpdateDraw,
  5561. "_fnServerParams": _fnServerParams,
  5562. "_fnAddOptionsHtml": _fnAddOptionsHtml,
  5563. "_fnFeatureHtmlTable": _fnFeatureHtmlTable,
  5564. "_fnScrollDraw": _fnScrollDraw,
  5565. "_fnAdjustColumnSizing": _fnAdjustColumnSizing,
  5566. "_fnFeatureHtmlFilter": _fnFeatureHtmlFilter,
  5567. "_fnFilterComplete": _fnFilterComplete,
  5568. "_fnFilterCustom": _fnFilterCustom,
  5569. "_fnFilterColumn": _fnFilterColumn,
  5570. "_fnFilter": _fnFilter,
  5571. "_fnBuildSearchArray": _fnBuildSearchArray,
  5572. "_fnBuildSearchRow": _fnBuildSearchRow,
  5573. "_fnFilterCreateSearch": _fnFilterCreateSearch,
  5574. "_fnDataToSearch": _fnDataToSearch,
  5575. "_fnSort": _fnSort,
  5576. "_fnSortAttachListener": _fnSortAttachListener,
  5577. "_fnSortingClasses": _fnSortingClasses,
  5578. "_fnFeatureHtmlPaginate": _fnFeatureHtmlPaginate,
  5579. "_fnPageChange": _fnPageChange,
  5580. "_fnFeatureHtmlInfo": _fnFeatureHtmlInfo,
  5581. "_fnUpdateInfo": _fnUpdateInfo,
  5582. "_fnFeatureHtmlLength": _fnFeatureHtmlLength,
  5583. "_fnFeatureHtmlProcessing": _fnFeatureHtmlProcessing,
  5584. "_fnProcessingDisplay": _fnProcessingDisplay,
  5585. "_fnVisibleToColumnIndex": _fnVisibleToColumnIndex,
  5586. "_fnColumnIndexToVisible": _fnColumnIndexToVisible,
  5587. "_fnNodeToDataIndex": _fnNodeToDataIndex,
  5588. "_fnVisbleColumns": _fnVisbleColumns,
  5589. "_fnCalculateEnd": _fnCalculateEnd,
  5590. "_fnConvertToWidth": _fnConvertToWidth,
  5591. "_fnCalculateColumnWidths": _fnCalculateColumnWidths,
  5592. "_fnScrollingWidthAdjust": _fnScrollingWidthAdjust,
  5593. "_fnGetWidestNode": _fnGetWidestNode,
  5594. "_fnGetMaxLenString": _fnGetMaxLenString,
  5595. "_fnStringToCss": _fnStringToCss,
  5596. "_fnDetectType": _fnDetectType,
  5597. "_fnSettingsFromNode": _fnSettingsFromNode,
  5598. "_fnGetDataMaster": _fnGetDataMaster,
  5599. "_fnGetTrNodes": _fnGetTrNodes,
  5600. "_fnGetTdNodes": _fnGetTdNodes,
  5601. "_fnEscapeRegex": _fnEscapeRegex,
  5602. "_fnDeleteIndex": _fnDeleteIndex,
  5603. "_fnReOrderIndex": _fnReOrderIndex,
  5604. "_fnColumnOrdering": _fnColumnOrdering,
  5605. "_fnLog": _fnLog,
  5606. "_fnClearTable": _fnClearTable,
  5607. "_fnSaveState": _fnSaveState,
  5608. "_fnLoadState": _fnLoadState,
  5609. "_fnCreateCookie": _fnCreateCookie,
  5610. "_fnReadCookie": _fnReadCookie,
  5611. "_fnDetectHeader": _fnDetectHeader,
  5612. "_fnGetUniqueThs": _fnGetUniqueThs,
  5613. "_fnScrollBarWidth": _fnScrollBarWidth,
  5614. "_fnApplyToChildren": _fnApplyToChildren,
  5615. "_fnMap": _fnMap,
  5616. "_fnGetRowData": _fnGetRowData,
  5617. "_fnGetCellData": _fnGetCellData,
  5618. "_fnSetCellData": _fnSetCellData,
  5619. "_fnGetObjectDataFn": _fnGetObjectDataFn,
  5620. "_fnSetObjectDataFn": _fnSetObjectDataFn,
  5621. "_fnApplyColumnDefs": _fnApplyColumnDefs,
  5622. "_fnBindAction": _fnBindAction,
  5623. "_fnExtend": _fnExtend,
  5624. "_fnCallbackReg": _fnCallbackReg,
  5625. "_fnCallbackFire": _fnCallbackFire,
  5626. "_fnJsonString": _fnJsonString,
  5627. "_fnRender": _fnRender,
  5628. "_fnNodeToColumnIndex": _fnNodeToColumnIndex,
  5629. "_fnInfoMacros": _fnInfoMacros,
  5630. "_fnBrowserDetect": _fnBrowserDetect,
  5631. "_fnGetColumns": _fnGetColumns
  5632. };
  5633. $.extend( DataTable.ext.oApi, this.oApi );
  5634. for ( var sFunc in DataTable.ext.oApi )
  5635. {
  5636. if ( sFunc )
  5637. {
  5638. this[sFunc] = _fnExternApiFunc(sFunc);
  5639. }
  5640. }
  5641. var _that = this;
  5642. this.each(function() {
  5643. var i=0, iLen, j, jLen, k, kLen;
  5644. var sId = this.getAttribute( 'id' );
  5645. var bInitHandedOff = false;
  5646. var bUsePassedData = false;
  5647. /* Sanity check */
  5648. if ( this.nodeName.toLowerCase() != 'table' )
  5649. {
  5650. _fnLog( null, 0, "Attempted to initialise DataTables on a node which is not a "+
  5651. "table: "+this.nodeName );
  5652. return;
  5653. }
  5654. /* Check to see if we are re-initialising a table */
  5655. for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ )
  5656. {
  5657. /* Base check on table node */
  5658. if ( DataTable.settings[i].nTable == this )
  5659. {
  5660. if ( oInit === undefined || oInit.bRetrieve )
  5661. {
  5662. return DataTable.settings[i].oInstance;
  5663. }
  5664. else if ( oInit.bDestroy )
  5665. {
  5666. DataTable.settings[i].oInstance.fnDestroy();
  5667. break;
  5668. }
  5669. else
  5670. {
  5671. _fnLog( DataTable.settings[i], 0, "Cannot reinitialise DataTable.\n\n"+
  5672. "To retrieve the DataTables object for this table, pass no arguments or see "+
  5673. "the docs for bRetrieve and bDestroy" );
  5674. return;
  5675. }
  5676. }
  5677. /* If the element we are initialising has the same ID as a table which was previously
  5678. * initialised, but the table nodes don't match (from before) then we destroy the old
  5679. * instance by simply deleting it. This is under the assumption that the table has been
  5680. * destroyed by other methods. Anyone using non-id selectors will need to do this manually
  5681. */
  5682. if ( DataTable.settings[i].sTableId == this.id )
  5683. {
  5684. DataTable.settings.splice( i, 1 );
  5685. break;
  5686. }
  5687. }
  5688. /* Ensure the table has an ID - required for accessibility */
  5689. if ( sId === null || sId === "" )
  5690. {
  5691. sId = "DataTables_Table_"+(DataTable.ext._oExternConfig.iNextUnique++);
  5692. this.id = sId;
  5693. }
  5694. /* Create the settings object for this table and set some of the default parameters */
  5695. var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
  5696. "nTable": this,
  5697. "oApi": _that.oApi,
  5698. "oInit": oInit,
  5699. "sDestroyWidth": $(this).width(),
  5700. "sInstance": sId,
  5701. "sTableId": sId
  5702. } );
  5703. DataTable.settings.push( oSettings );
  5704. // Need to add the instance after the instance after the settings object has been added
  5705. // to the settings array, so we can self reference the table instance if more than one
  5706. oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable();
  5707. /* Setting up the initialisation object */
  5708. if ( !oInit )
  5709. {
  5710. oInit = {};
  5711. }
  5712. // Backwards compatibility, before we apply all the defaults
  5713. if ( oInit.oLanguage )
  5714. {
  5715. _fnLanguageCompat( oInit.oLanguage );
  5716. }
  5717. oInit = _fnExtend( $.extend(true, {}, DataTable.defaults), oInit );
  5718. // Map the initialisation options onto the settings object
  5719. _fnMap( oSettings.oFeatures, oInit, "bPaginate" );
  5720. _fnMap( oSettings.oFeatures, oInit, "bLengthChange" );
  5721. _fnMap( oSettings.oFeatures, oInit, "bFilter" );
  5722. _fnMap( oSettings.oFeatures, oInit, "bSort" );
  5723. _fnMap( oSettings.oFeatures, oInit, "bInfo" );
  5724. _fnMap( oSettings.oFeatures, oInit, "bProcessing" );
  5725. _fnMap( oSettings.oFeatures, oInit, "bAutoWidth" );
  5726. _fnMap( oSettings.oFeatures, oInit, "bSortClasses" );
  5727. _fnMap( oSettings.oFeatures, oInit, "bServerSide" );
  5728. _fnMap( oSettings.oFeatures, oInit, "bDeferRender" );
  5729. _fnMap( oSettings.oScroll, oInit, "sScrollX", "sX" );
  5730. _fnMap( oSettings.oScroll, oInit, "sScrollXInner", "sXInner" );
  5731. _fnMap( oSettings.oScroll, oInit, "sScrollY", "sY" );
  5732. _fnMap( oSettings.oScroll, oInit, "bScrollCollapse", "bCollapse" );
  5733. _fnMap( oSettings.oScroll, oInit, "bScrollInfinite", "bInfinite" );
  5734. _fnMap( oSettings.oScroll, oInit, "iScrollLoadGap", "iLoadGap" );
  5735. _fnMap( oSettings.oScroll, oInit, "bScrollAutoCss", "bAutoCss" );
  5736. _fnMap( oSettings, oInit, "asStripeClasses" );
  5737. _fnMap( oSettings, oInit, "asStripClasses", "asStripeClasses" ); // legacy
  5738. _fnMap( oSettings, oInit, "fnServerData" );
  5739. _fnMap( oSettings, oInit, "fnFormatNumber" );
  5740. _fnMap( oSettings, oInit, "sServerMethod" );
  5741. _fnMap( oSettings, oInit, "aaSorting" );
  5742. _fnMap( oSettings, oInit, "aaSortingFixed" );
  5743. _fnMap( oSettings, oInit, "aLengthMenu" );
  5744. _fnMap( oSettings, oInit, "sPaginationType" );
  5745. _fnMap( oSettings, oInit, "sAjaxSource" );
  5746. _fnMap( oSettings, oInit, "sAjaxDataProp" );
  5747. _fnMap( oSettings, oInit, "iCookieDuration" );
  5748. _fnMap( oSettings, oInit, "sCookiePrefix" );
  5749. _fnMap( oSettings, oInit, "sDom" );
  5750. _fnMap( oSettings, oInit, "bSortCellsTop" );
  5751. _fnMap( oSettings, oInit, "iTabIndex" );
  5752. _fnMap( oSettings, oInit, "oSearch", "oPreviousSearch" );
  5753. _fnMap( oSettings, oInit, "aoSearchCols", "aoPreSearchCols" );
  5754. _fnMap( oSettings, oInit, "iDisplayLength", "_iDisplayLength" );
  5755. _fnMap( oSettings, oInit, "bJQueryUI", "bJUI" );
  5756. _fnMap( oSettings, oInit, "fnCookieCallback" );
  5757. _fnMap( oSettings, oInit, "fnStateLoad" );
  5758. _fnMap( oSettings, oInit, "fnStateSave" );
  5759. _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
  5760. /* Callback functions which are array driven */
  5761. _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' );
  5762. _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' );
  5763. _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' );
  5764. _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' );
  5765. _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' );
  5766. _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' );
  5767. _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' );
  5768. _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' );
  5769. _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' );
  5770. _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' );
  5771. _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' );
  5772. if ( oSettings.oFeatures.bServerSide && oSettings.oFeatures.bSort &&
  5773. oSettings.oFeatures.bSortClasses )
  5774. {
  5775. /* Enable sort classes for server-side processing. Safe to do it here, since server-side
  5776. * processing must be enabled by the developer
  5777. */
  5778. _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'server_side_sort_classes' );
  5779. }
  5780. else if ( oSettings.oFeatures.bDeferRender )
  5781. {
  5782. _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'defer_sort_classes' );
  5783. }
  5784. if ( oInit.bJQueryUI )
  5785. {
  5786. /* Use the JUI classes object for display. You could clone the oStdClasses object if
  5787. * you want to have multiple tables with multiple independent classes
  5788. */
  5789. $.extend( oSettings.oClasses, DataTable.ext.oJUIClasses );
  5790. if ( oInit.sDom === DataTable.defaults.sDom && DataTable.defaults.sDom === "lfrtip" )
  5791. {
  5792. /* Set the DOM to use a layout suitable for jQuery UI's theming */
  5793. oSettings.sDom = '<"H"lfr>t<"F"ip>';
  5794. }
  5795. }
  5796. else
  5797. {
  5798. $.extend( oSettings.oClasses, DataTable.ext.oStdClasses );
  5799. }
  5800. $(this).addClass( oSettings.oClasses.sTable );
  5801. /* Calculate the scroll bar width and cache it for use later on */
  5802. if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
  5803. {
  5804. oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
  5805. }
  5806. if ( oSettings.iInitDisplayStart === undefined )
  5807. {
  5808. /* Display start point, taking into account the save saving */
  5809. oSettings.iInitDisplayStart = oInit.iDisplayStart;
  5810. oSettings._iDisplayStart = oInit.iDisplayStart;
  5811. }
  5812. /* Must be done after everything which can be overridden by a cookie! */
  5813. if ( oInit.bStateSave )
  5814. {
  5815. oSettings.oFeatures.bStateSave = true;
  5816. _fnLoadState( oSettings, oInit );
  5817. _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
  5818. }
  5819. if ( oInit.iDeferLoading !== null )
  5820. {
  5821. oSettings.bDeferLoading = true;
  5822. var tmp = $.isArray( oInit.iDeferLoading );
  5823. oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
  5824. oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
  5825. }
  5826. if ( oInit.aaData !== null )
  5827. {
  5828. bUsePassedData = true;
  5829. }
  5830. /* Language definitions */
  5831. if ( oInit.oLanguage.sUrl !== "" )
  5832. {
  5833. /* Get the language definitions from a file - because this Ajax call makes the language
  5834. * get async to the remainder of this function we use bInitHandedOff to indicate that
  5835. * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
  5836. */
  5837. oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;
  5838. $.getJSON( oSettings.oLanguage.sUrl, null, function( json ) {
  5839. _fnLanguageCompat( json );
  5840. $.extend( true, oSettings.oLanguage, oInit.oLanguage, json );
  5841. _fnInitialise( oSettings );
  5842. } );
  5843. bInitHandedOff = true;
  5844. }
  5845. else
  5846. {
  5847. $.extend( true, oSettings.oLanguage, oInit.oLanguage );
  5848. }
  5849. /*
  5850. * Stripes
  5851. */
  5852. if ( oInit.asStripeClasses === null )
  5853. {
  5854. oSettings.asStripeClasses =[
  5855. oSettings.oClasses.sStripeOdd,
  5856. oSettings.oClasses.sStripeEven
  5857. ];
  5858. }
  5859. /* Remove row stripe classes if they are already on the table row */
  5860. iLen=oSettings.asStripeClasses.length;
  5861. oSettings.asDestroyStripes = [];
  5862. if (iLen)
  5863. {
  5864. var bStripeRemove = false;
  5865. var anRows = $(this).children('tbody').children('tr:lt(' + iLen + ')');
  5866. for ( i=0 ; i<iLen ; i++ )
  5867. {
  5868. if ( anRows.hasClass( oSettings.asStripeClasses[i] ) )
  5869. {
  5870. bStripeRemove = true;
  5871. /* Store the classes which we are about to remove so they can be re-added on destroy */
  5872. oSettings.asDestroyStripes.push( oSettings.asStripeClasses[i] );
  5873. }
  5874. }
  5875. if ( bStripeRemove )
  5876. {
  5877. anRows.removeClass( oSettings.asStripeClasses.join(' ') );
  5878. }
  5879. }
  5880. /*
  5881. * Columns
  5882. * See if we should load columns automatically or use defined ones
  5883. */
  5884. var anThs = [];
  5885. var aoColumnsInit;
  5886. var nThead = this.getElementsByTagName('thead');
  5887. if ( nThead.length !== 0 )
  5888. {
  5889. _fnDetectHeader( oSettings.aoHeader, nThead[0] );
  5890. anThs = _fnGetUniqueThs( oSettings );
  5891. }
  5892. /* If not given a column array, generate one with nulls */
  5893. if ( oInit.aoColumns === null )
  5894. {
  5895. aoColumnsInit = [];
  5896. for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
  5897. {
  5898. aoColumnsInit.push( null );
  5899. }
  5900. }
  5901. else
  5902. {
  5903. aoColumnsInit = oInit.aoColumns;
  5904. }
  5905. /* Add the columns */
  5906. for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
  5907. {
  5908. /* Short cut - use the loop to check if we have column visibility state to restore */
  5909. if ( oInit.saved_aoColumns !== undefined && oInit.saved_aoColumns.length == iLen )
  5910. {
  5911. if ( aoColumnsInit[i] === null )
  5912. {
  5913. aoColumnsInit[i] = {};
  5914. }
  5915. aoColumnsInit[i].bVisible = oInit.saved_aoColumns[i].bVisible;
  5916. }
  5917. _fnAddColumn( oSettings, anThs ? anThs[i] : null );
  5918. }
  5919. /* Apply the column definitions */
  5920. _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
  5921. _fnColumnOptions( oSettings, iCol, oDef );
  5922. } );
  5923. /*
  5924. * Sorting
  5925. * Check the aaSorting array
  5926. */
  5927. for ( i=0, iLen=oSettings.aaSorting.length ; i<iLen ; i++ )
  5928. {
  5929. if ( oSettings.aaSorting[i][0] >= oSettings.aoColumns.length )
  5930. {
  5931. oSettings.aaSorting[i][0] = 0;
  5932. }
  5933. var oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ];
  5934. /* Add a default sorting index */
  5935. if ( oSettings.aaSorting[i][2] === undefined )
  5936. {
  5937. oSettings.aaSorting[i][2] = 0;
  5938. }
  5939. /* If aaSorting is not defined, then we use the first indicator in asSorting */
  5940. if ( oInit.aaSorting === undefined && oSettings.saved_aaSorting === undefined )
  5941. {
  5942. oSettings.aaSorting[i][1] = oColumn.asSorting[0];
  5943. }
  5944. /* Set the current sorting index based on aoColumns.asSorting */
  5945. for ( j=0, jLen=oColumn.asSorting.length ; j<jLen ; j++ )
  5946. {
  5947. if ( oSettings.aaSorting[i][1] == oColumn.asSorting[j] )
  5948. {
  5949. oSettings.aaSorting[i][2] = j;
  5950. break;
  5951. }
  5952. }
  5953. }
  5954. /* Do a first pass on the sorting classes (allows any size changes to be taken into
  5955. * account, and also will apply sorting disabled classes if disabled
  5956. */
  5957. _fnSortingClasses( oSettings );
  5958. /*
  5959. * Final init
  5960. * Cache the header, body and footer as required, creating them if needed
  5961. */
  5962. /* Browser support detection */
  5963. _fnBrowserDetect( oSettings );
  5964. // Work around for Webkit bug 83867 - store the caption-side before removing from doc
  5965. var captions = $(this).children('caption').each( function () {
  5966. this._captionSide = $(this).css('caption-side');
  5967. } );
  5968. var thead = $(this).children('thead');
  5969. if ( thead.length === 0 )
  5970. {
  5971. thead = [ document.createElement( 'thead' ) ];
  5972. this.appendChild( thead[0] );
  5973. }
  5974. oSettings.nTHead = thead[0];
  5975. var tbody = $(this).children('tbody');
  5976. if ( tbody.length === 0 )
  5977. {
  5978. tbody = [ document.createElement( 'tbody' ) ];
  5979. this.appendChild( tbody[0] );
  5980. }
  5981. oSettings.nTBody = tbody[0];
  5982. oSettings.nTBody.setAttribute( "role", "alert" );
  5983. oSettings.nTBody.setAttribute( "aria-live", "polite" );
  5984. oSettings.nTBody.setAttribute( "aria-relevant", "all" );
  5985. var tfoot = $(this).children('tfoot');
  5986. if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
  5987. {
  5988. // If we are a scrolling table, and no footer has been given, then we need to create
  5989. // a tfoot element for the caption element to be appended to
  5990. tfoot = [ document.createElement( 'tfoot' ) ];
  5991. this.appendChild( tfoot[0] );
  5992. }
  5993. if ( tfoot.length > 0 )
  5994. {
  5995. oSettings.nTFoot = tfoot[0];
  5996. _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
  5997. }
  5998. /* Check if there is data passing into the constructor */
  5999. if ( bUsePassedData )
  6000. {
  6001. for ( i=0 ; i<oInit.aaData.length ; i++ )
  6002. {
  6003. _fnAddData( oSettings, oInit.aaData[ i ] );
  6004. }
  6005. }
  6006. else
  6007. {
  6008. /* Grab the data from the page */
  6009. _fnGatherData( oSettings );
  6010. }
  6011. /* Copy the data index array */
  6012. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  6013. /* Initialisation complete - table can be drawn */
  6014. oSettings.bInitialised = true;
  6015. /* Check if we need to initialise the table (it might not have been handed off to the
  6016. * language processor)
  6017. */
  6018. if ( bInitHandedOff === false )
  6019. {
  6020. _fnInitialise( oSettings );
  6021. }
  6022. } );
  6023. _that = null;
  6024. return this;
  6025. };
  6026. /**
  6027. * Provide a common method for plug-ins to check the version of DataTables being used, in order
  6028. * to ensure compatibility.
  6029. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
  6030. * formats "X" and "X.Y" are also acceptable.
  6031. * @returns {boolean} true if this version of DataTables is greater or equal to the required
  6032. * version, or false if this version of DataTales is not suitable
  6033. * @static
  6034. * @dtopt API-Static
  6035. *
  6036. * @example
  6037. * alert( $.fn.dataTable.fnVersionCheck( '1.9.0' ) );
  6038. */
  6039. DataTable.fnVersionCheck = function( sVersion )
  6040. {
  6041. /* This is cheap, but effective */
  6042. var fnZPad = function (Zpad, count)
  6043. {
  6044. while(Zpad.length < count) {
  6045. Zpad += '0';
  6046. }
  6047. return Zpad;
  6048. };
  6049. var aThis = DataTable.ext.sVersion.split('.');
  6050. var aThat = sVersion.split('.');
  6051. var sThis = '', sThat = '';
  6052. for ( var i=0, iLen=aThat.length ; i<iLen ; i++ )
  6053. {
  6054. sThis += fnZPad( aThis[i], 3 );
  6055. sThat += fnZPad( aThat[i], 3 );
  6056. }
  6057. return parseInt(sThis, 10) >= parseInt(sThat, 10);
  6058. };
  6059. /**
  6060. * Check if a TABLE node is a DataTable table already or not.
  6061. * @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other
  6062. * node types can be passed in, but will always return false).
  6063. * @returns {boolean} true the table given is a DataTable, or false otherwise
  6064. * @static
  6065. * @dtopt API-Static
  6066. *
  6067. * @example
  6068. * var ex = document.getElementById('example');
  6069. * if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) {
  6070. * $(ex).dataTable();
  6071. * }
  6072. */
  6073. DataTable.fnIsDataTable = function ( nTable )
  6074. {
  6075. var o = DataTable.settings;
  6076. for ( var i=0 ; i<o.length ; i++ )
  6077. {
  6078. if ( o[i].nTable === nTable || o[i].nScrollHead === nTable || o[i].nScrollFoot === nTable )
  6079. {
  6080. return true;
  6081. }
  6082. }
  6083. return false;
  6084. };
  6085. /**
  6086. * Get all DataTable tables that have been initialised - optionally you can select to
  6087. * get only currently visible tables.
  6088. * @param {boolean} [bVisible=false] Flag to indicate if you want all (default) or
  6089. * visible tables only.
  6090. * @returns {array} Array of TABLE nodes (not DataTable instances) which are DataTables
  6091. * @static
  6092. * @dtopt API-Static
  6093. *
  6094. * @example
  6095. * var table = $.fn.dataTable.fnTables(true);
  6096. * if ( table.length > 0 ) {
  6097. * $(table).dataTable().fnAdjustColumnSizing();
  6098. * }
  6099. */
  6100. DataTable.fnTables = function ( bVisible )
  6101. {
  6102. var out = [];
  6103. jQuery.each( DataTable.settings, function (i, o) {
  6104. if ( !bVisible || (bVisible === true && $(o.nTable).is(':visible')) )
  6105. {
  6106. out.push( o.nTable );
  6107. }
  6108. } );
  6109. return out;
  6110. };
  6111. /**
  6112. * Version string for plug-ins to check compatibility. Allowed format is
  6113. * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
  6114. * e are optional
  6115. * @member
  6116. * @type string
  6117. * @default Version number
  6118. */
  6119. DataTable.version = "1.9.4";
  6120. /**
  6121. * Private data store, containing all of the settings objects that are created for the
  6122. * tables on a given page.
  6123. *
  6124. * Note that the <i>DataTable.settings</i> object is aliased to <i>jQuery.fn.dataTableExt</i>
  6125. * through which it may be accessed and manipulated, or <i>jQuery.fn.dataTable.settings</i>.
  6126. * @member
  6127. * @type array
  6128. * @default []
  6129. * @private
  6130. */
  6131. DataTable.settings = [];
  6132. /**
  6133. * Object models container, for the various models that DataTables has available
  6134. * to it. These models define the objects that are used to hold the active state
  6135. * and configuration of the table.
  6136. * @namespace
  6137. */
  6138. DataTable.models = {};
  6139. /**
  6140. * DataTables extension options and plug-ins. This namespace acts as a collection "area"
  6141. * for plug-ins that can be used to extend the default DataTables behaviour - indeed many
  6142. * of the build in methods use this method to provide their own capabilities (sorting methods
  6143. * for example).
  6144. *
  6145. * Note that this namespace is aliased to jQuery.fn.dataTableExt so it can be readily accessed
  6146. * and modified by plug-ins.
  6147. * @namespace
  6148. */
  6149. DataTable.models.ext = {
  6150. /**
  6151. * Plug-in filtering functions - this method of filtering is complimentary to the default
  6152. * type based filtering, and a lot more comprehensive as it allows you complete control
  6153. * over the filtering logic. Each element in this array is a function (parameters
  6154. * described below) that is called for every row in the table, and your logic decides if
  6155. * it should be included in the filtered data set or not.
  6156. * <ul>
  6157. * <li>
  6158. * Function input parameters:
  6159. * <ul>
  6160. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  6161. * <li>{array|object} Data for the row to be processed (same as the original format
  6162. * that was passed in as the data source, or an array from a DOM data source</li>
  6163. * <li>{int} Row index in aoData ({@link DataTable.models.oSettings.aoData}), which can
  6164. * be useful to retrieve the TR element if you need DOM interaction.</li>
  6165. * </ul>
  6166. * </li>
  6167. * <li>
  6168. * Function return:
  6169. * <ul>
  6170. * <li>{boolean} Include the row in the filtered result set (true) or not (false)</li>
  6171. * </ul>
  6172. * </il>
  6173. * </ul>
  6174. * @type array
  6175. * @default []
  6176. *
  6177. * @example
  6178. * // The following example shows custom filtering being applied to the fourth column (i.e.
  6179. * // the aData[3] index) based on two input values from the end-user, matching the data in
  6180. * // a certain range.
  6181. * $.fn.dataTableExt.afnFiltering.push(
  6182. * function( oSettings, aData, iDataIndex ) {
  6183. * var iMin = document.getElementById('min').value * 1;
  6184. * var iMax = document.getElementById('max').value * 1;
  6185. * var iVersion = aData[3] == "-" ? 0 : aData[3]*1;
  6186. * if ( iMin == "" && iMax == "" ) {
  6187. * return true;
  6188. * }
  6189. * else if ( iMin == "" && iVersion < iMax ) {
  6190. * return true;
  6191. * }
  6192. * else if ( iMin < iVersion && "" == iMax ) {
  6193. * return true;
  6194. * }
  6195. * else if ( iMin < iVersion && iVersion < iMax ) {
  6196. * return true;
  6197. * }
  6198. * return false;
  6199. * }
  6200. * );
  6201. */
  6202. "afnFiltering": [],
  6203. /**
  6204. * Plug-in sorting functions - this method of sorting is complimentary to the default type
  6205. * based sorting that DataTables does automatically, allowing much greater control over the
  6206. * the data that is being used to sort a column. This is useful if you want to do sorting
  6207. * based on live data (for example the contents of an 'input' element) rather than just the
  6208. * static string that DataTables knows of. The way these plug-ins work is that you create
  6209. * an array of the values you wish to be sorted for the column in question and then return
  6210. * that array. Which pre-sorting function is run here depends on the sSortDataType parameter
  6211. * that is used for the column (if any). This is the corollary of <i>ofnSearch</i> for sort
  6212. * data.
  6213. * <ul>
  6214. * <li>
  6215. * Function input parameters:
  6216. * <ul>
  6217. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  6218. * <li>{int} Target column index</li>
  6219. * </ul>
  6220. * </li>
  6221. * <li>
  6222. * Function return:
  6223. * <ul>
  6224. * <li>{array} Data for the column to be sorted upon</li>
  6225. * </ul>
  6226. * </il>
  6227. * </ul>
  6228. *
  6229. * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for
  6230. * the different uses that DataTables can put the data to. Specifically <i>mData</i> when
  6231. * used as a function will give you a 'type' (sorting, filtering etc) that you can use to
  6232. * prepare the data as required for the different types. As such, this method is deprecated.
  6233. * @type array
  6234. * @default []
  6235. * @deprecated
  6236. *
  6237. * @example
  6238. * // Updating the cached sorting information with user entered values in HTML input elements
  6239. * jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn )
  6240. * {
  6241. * var aData = [];
  6242. * $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
  6243. * aData.push( this.value );
  6244. * } );
  6245. * return aData;
  6246. * }
  6247. */
  6248. "afnSortData": [],
  6249. /**
  6250. * Feature plug-ins - This is an array of objects which describe the feature plug-ins that are
  6251. * available to DataTables. These feature plug-ins are accessible through the sDom initialisation
  6252. * option. As such, each feature plug-in must describe a function that is used to initialise
  6253. * itself (fnInit), a character so the feature can be enabled by sDom (cFeature) and the name
  6254. * of the feature (sFeature). Thus the objects attached to this method must provide:
  6255. * <ul>
  6256. * <li>{function} fnInit Initialisation of the plug-in
  6257. * <ul>
  6258. * <li>
  6259. * Function input parameters:
  6260. * <ul>
  6261. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  6262. * </ul>
  6263. * </li>
  6264. * <li>
  6265. * Function return:
  6266. * <ul>
  6267. * <li>{node|null} The element which contains your feature. Note that the return
  6268. * may also be void if your plug-in does not require to inject any DOM elements
  6269. * into DataTables control (sDom) - for example this might be useful when
  6270. * developing a plug-in which allows table control via keyboard entry.</li>
  6271. * </ul>
  6272. * </il>
  6273. * </ul>
  6274. * </li>
  6275. * <li>{character} cFeature Character that will be matched in sDom - case sensitive</li>
  6276. * <li>{string} sFeature Feature name</li>
  6277. * </ul>
  6278. * @type array
  6279. * @default []
  6280. *
  6281. * @example
  6282. * // How TableTools initialises itself.
  6283. * $.fn.dataTableExt.aoFeatures.push( {
  6284. * "fnInit": function( oSettings ) {
  6285. * return new TableTools( { "oDTSettings": oSettings } );
  6286. * },
  6287. * "cFeature": "T",
  6288. * "sFeature": "TableTools"
  6289. * } );
  6290. */
  6291. "aoFeatures": [],
  6292. /**
  6293. * Type detection plug-in functions - DataTables utilises types to define how sorting and
  6294. * filtering behave, and types can be either be defined by the developer (sType for the
  6295. * column) or they can be automatically detected by the methods in this array. The functions
  6296. * defined in the array are quite simple, taking a single parameter (the data to analyse)
  6297. * and returning the type if it is a known type, or null otherwise.
  6298. * <ul>
  6299. * <li>
  6300. * Function input parameters:
  6301. * <ul>
  6302. * <li>{*} Data from the column cell to be analysed</li>
  6303. * </ul>
  6304. * </li>
  6305. * <li>
  6306. * Function return:
  6307. * <ul>
  6308. * <li>{string|null} Data type detected, or null if unknown (and thus pass it
  6309. * on to the other type detection functions.</li>
  6310. * </ul>
  6311. * </il>
  6312. * </ul>
  6313. * @type array
  6314. * @default []
  6315. *
  6316. * @example
  6317. * // Currency type detection plug-in:
  6318. * jQuery.fn.dataTableExt.aTypes.push(
  6319. * function ( sData ) {
  6320. * var sValidChars = "0123456789.-";
  6321. * var Char;
  6322. *
  6323. * // Check the numeric part
  6324. * for ( i=1 ; i<sData.length ; i++ ) {
  6325. * Char = sData.charAt(i);
  6326. * if (sValidChars.indexOf(Char) == -1) {
  6327. * return null;
  6328. * }
  6329. * }
  6330. *
  6331. * // Check prefixed by currency
  6332. * if ( sData.charAt(0) == '$' || sData.charAt(0) == '&pound;' ) {
  6333. * return 'currency';
  6334. * }
  6335. * return null;
  6336. * }
  6337. * );
  6338. */
  6339. "aTypes": [],
  6340. /**
  6341. * Provide a common method for plug-ins to check the version of DataTables being used,
  6342. * in order to ensure compatibility.
  6343. * @type function
  6344. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note
  6345. * that the formats "X" and "X.Y" are also acceptable.
  6346. * @returns {boolean} true if this version of DataTables is greater or equal to the
  6347. * required version, or false if this version of DataTales is not suitable
  6348. *
  6349. * @example
  6350. * $(document).ready(function() {
  6351. * var oTable = $('#example').dataTable();
  6352. * alert( oTable.fnVersionCheck( '1.9.0' ) );
  6353. * } );
  6354. */
  6355. "fnVersionCheck": DataTable.fnVersionCheck,
  6356. /**
  6357. * Index for what 'this' index API functions should use
  6358. * @type int
  6359. * @default 0
  6360. */
  6361. "iApiIndex": 0,
  6362. /**
  6363. * Pre-processing of filtering data plug-ins - When you assign the sType for a column
  6364. * (or have it automatically detected for you by DataTables or a type detection plug-in),
  6365. * you will typically be using this for custom sorting, but it can also be used to provide
  6366. * custom filtering by allowing you to pre-processing the data and returning the data in
  6367. * the format that should be filtered upon. This is done by adding functions this object
  6368. * with a parameter name which matches the sType for that target column. This is the
  6369. * corollary of <i>afnSortData</i> for filtering data.
  6370. * <ul>
  6371. * <li>
  6372. * Function input parameters:
  6373. * <ul>
  6374. * <li>{*} Data from the column cell to be prepared for filtering</li>
  6375. * </ul>
  6376. * </li>
  6377. * <li>
  6378. * Function return:
  6379. * <ul>
  6380. * <li>{string|null} Formatted string that will be used for the filtering.</li>
  6381. * </ul>
  6382. * </il>
  6383. * </ul>
  6384. *
  6385. * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for
  6386. * the different uses that DataTables can put the data to. Specifically <i>mData</i> when
  6387. * used as a function will give you a 'type' (sorting, filtering etc) that you can use to
  6388. * prepare the data as required for the different types. As such, this method is deprecated.
  6389. * @type object
  6390. * @default {}
  6391. * @deprecated
  6392. *
  6393. * @example
  6394. * $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) {
  6395. * return sData.replace(/\n/g," ").replace( /<.*?>/g, "" );
  6396. * }
  6397. */
  6398. "ofnSearch": {},
  6399. /**
  6400. * Container for all private functions in DataTables so they can be exposed externally
  6401. * @type object
  6402. * @default {}
  6403. */
  6404. "oApi": {},
  6405. /**
  6406. * Storage for the various classes that DataTables uses
  6407. * @type object
  6408. * @default {}
  6409. */
  6410. "oStdClasses": {},
  6411. /**
  6412. * Storage for the various classes that DataTables uses - jQuery UI suitable
  6413. * @type object
  6414. * @default {}
  6415. */
  6416. "oJUIClasses": {},
  6417. /**
  6418. * Pagination plug-in methods - The style and controls of the pagination can significantly
  6419. * impact on how the end user interacts with the data in your table, and DataTables allows
  6420. * the addition of pagination controls by extending this object, which can then be enabled
  6421. * through the <i>sPaginationType</i> initialisation parameter. Each pagination type that
  6422. * is added is an object (the property name of which is what <i>sPaginationType</i> refers
  6423. * to) that has two properties, both methods that are used by DataTables to update the
  6424. * control's state.
  6425. * <ul>
  6426. * <li>
  6427. * fnInit - Initialisation of the paging controls. Called only during initialisation
  6428. * of the table. It is expected that this function will add the required DOM elements
  6429. * to the page for the paging controls to work. The element pointer
  6430. * 'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging
  6431. * controls (note that this is a 2D array to allow for multiple instances of each
  6432. * DataTables DOM element). It is suggested that you add the controls to this element
  6433. * as children
  6434. * <ul>
  6435. * <li>
  6436. * Function input parameters:
  6437. * <ul>
  6438. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  6439. * <li>{node} Container into which the pagination controls must be inserted</li>
  6440. * <li>{function} Draw callback function - whenever the controls cause a page
  6441. * change, this method must be called to redraw the table.</li>
  6442. * </ul>
  6443. * </li>
  6444. * <li>
  6445. * Function return:
  6446. * <ul>
  6447. * <li>No return required</li>
  6448. * </ul>
  6449. * </il>
  6450. * </ul>
  6451. * </il>
  6452. * <li>
  6453. * fnInit - This function is called whenever the paging status of the table changes and is
  6454. * typically used to update classes and/or text of the paging controls to reflex the new
  6455. * status.
  6456. * <ul>
  6457. * <li>
  6458. * Function input parameters:
  6459. * <ul>
  6460. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  6461. * <li>{function} Draw callback function - in case you need to redraw the table again
  6462. * or attach new event listeners</li>
  6463. * </ul>
  6464. * </li>
  6465. * <li>
  6466. * Function return:
  6467. * <ul>
  6468. * <li>No return required</li>
  6469. * </ul>
  6470. * </il>
  6471. * </ul>
  6472. * </il>
  6473. * </ul>
  6474. * @type object
  6475. * @default {}
  6476. *
  6477. * @example
  6478. * $.fn.dataTableExt.oPagination.four_button = {
  6479. * "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) {
  6480. * nFirst = document.createElement( 'span' );
  6481. * nPrevious = document.createElement( 'span' );
  6482. * nNext = document.createElement( 'span' );
  6483. * nLast = document.createElement( 'span' );
  6484. *
  6485. * nFirst.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sFirst ) );
  6486. * nPrevious.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sPrevious ) );
  6487. * nNext.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sNext ) );
  6488. * nLast.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sLast ) );
  6489. *
  6490. * nFirst.className = "paginate_button first";
  6491. * nPrevious.className = "paginate_button previous";
  6492. * nNext.className="paginate_button next";
  6493. * nLast.className = "paginate_button last";
  6494. *
  6495. * nPaging.appendChild( nFirst );
  6496. * nPaging.appendChild( nPrevious );
  6497. * nPaging.appendChild( nNext );
  6498. * nPaging.appendChild( nLast );
  6499. *
  6500. * $(nFirst).click( function () {
  6501. * oSettings.oApi._fnPageChange( oSettings, "first" );
  6502. * fnCallbackDraw( oSettings );
  6503. * } );
  6504. *
  6505. * $(nPrevious).click( function() {
  6506. * oSettings.oApi._fnPageChange( oSettings, "previous" );
  6507. * fnCallbackDraw( oSettings );
  6508. * } );
  6509. *
  6510. * $(nNext).click( function() {
  6511. * oSettings.oApi._fnPageChange( oSettings, "next" );
  6512. * fnCallbackDraw( oSettings );
  6513. * } );
  6514. *
  6515. * $(nLast).click( function() {
  6516. * oSettings.oApi._fnPageChange( oSettings, "last" );
  6517. * fnCallbackDraw( oSettings );
  6518. * } );
  6519. *
  6520. * $(nFirst).bind( 'selectstart', function () { return false; } );
  6521. * $(nPrevious).bind( 'selectstart', function () { return false; } );
  6522. * $(nNext).bind( 'selectstart', function () { return false; } );
  6523. * $(nLast).bind( 'selectstart', function () { return false; } );
  6524. * },
  6525. *
  6526. * "fnUpdate": function ( oSettings, fnCallbackDraw ) {
  6527. * if ( !oSettings.aanFeatures.p ) {
  6528. * return;
  6529. * }
  6530. *
  6531. * // Loop over each instance of the pager
  6532. * var an = oSettings.aanFeatures.p;
  6533. * for ( var i=0, iLen=an.length ; i<iLen ; i++ ) {
  6534. * var buttons = an[i].getElementsByTagName('span');
  6535. * if ( oSettings._iDisplayStart === 0 ) {
  6536. * buttons[0].className = "paginate_disabled_previous";
  6537. * buttons[1].className = "paginate_disabled_previous";
  6538. * }
  6539. * else {
  6540. * buttons[0].className = "paginate_enabled_previous";
  6541. * buttons[1].className = "paginate_enabled_previous";
  6542. * }
  6543. *
  6544. * if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) {
  6545. * buttons[2].className = "paginate_disabled_next";
  6546. * buttons[3].className = "paginate_disabled_next";
  6547. * }
  6548. * else {
  6549. * buttons[2].className = "paginate_enabled_next";
  6550. * buttons[3].className = "paginate_enabled_next";
  6551. * }
  6552. * }
  6553. * }
  6554. * };
  6555. */
  6556. "oPagination": {},
  6557. /**
  6558. * Sorting plug-in methods - Sorting in DataTables is based on the detected type of the
  6559. * data column (you can add your own type detection functions, or override automatic
  6560. * detection using sType). With this specific type given to the column, DataTables will
  6561. * apply the required sort from the functions in the object. Each sort type must provide
  6562. * two mandatory methods, one each for ascending and descending sorting, and can optionally
  6563. * provide a pre-formatting method that will help speed up sorting by allowing DataTables
  6564. * to pre-format the sort data only once (rather than every time the actual sort functions
  6565. * are run). The two sorting functions are typical Javascript sort methods:
  6566. * <ul>
  6567. * <li>
  6568. * Function input parameters:
  6569. * <ul>
  6570. * <li>{*} Data to compare to the second parameter</li>
  6571. * <li>{*} Data to compare to the first parameter</li>
  6572. * </ul>
  6573. * </li>
  6574. * <li>
  6575. * Function return:
  6576. * <ul>
  6577. * <li>{int} Sorting match: <0 if first parameter should be sorted lower than
  6578. * the second parameter, ===0 if the two parameters are equal and >0 if
  6579. * the first parameter should be sorted height than the second parameter.</li>
  6580. * </ul>
  6581. * </il>
  6582. * </ul>
  6583. * @type object
  6584. * @default {}
  6585. *
  6586. * @example
  6587. * // Case-sensitive string sorting, with no pre-formatting method
  6588. * $.extend( $.fn.dataTableExt.oSort, {
  6589. * "string-case-asc": function(x,y) {
  6590. * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  6591. * },
  6592. * "string-case-desc": function(x,y) {
  6593. * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  6594. * }
  6595. * } );
  6596. *
  6597. * @example
  6598. * // Case-insensitive string sorting, with pre-formatting
  6599. * $.extend( $.fn.dataTableExt.oSort, {
  6600. * "string-pre": function(x) {
  6601. * return x.toLowerCase();
  6602. * },
  6603. * "string-asc": function(x,y) {
  6604. * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  6605. * },
  6606. * "string-desc": function(x,y) {
  6607. * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  6608. * }
  6609. * } );
  6610. */
  6611. "oSort": {},
  6612. /**
  6613. * Version string for plug-ins to check compatibility. Allowed format is
  6614. * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
  6615. * e are optional
  6616. * @type string
  6617. * @default Version number
  6618. */
  6619. "sVersion": DataTable.version,
  6620. /**
  6621. * How should DataTables report an error. Can take the value 'alert' or 'throw'
  6622. * @type string
  6623. * @default alert
  6624. */
  6625. "sErrMode": "alert",
  6626. /**
  6627. * Store information for DataTables to access globally about other instances
  6628. * @namespace
  6629. * @private
  6630. */
  6631. "_oExternConfig": {
  6632. /* int:iNextUnique - next unique number for an instance */
  6633. "iNextUnique": 0
  6634. }
  6635. };
  6636. /**
  6637. * Template object for the way in which DataTables holds information about
  6638. * search information for the global filter and individual column filters.
  6639. * @namespace
  6640. */
  6641. DataTable.models.oSearch = {
  6642. /**
  6643. * Flag to indicate if the filtering should be case insensitive or not
  6644. * @type boolean
  6645. * @default true
  6646. */
  6647. "bCaseInsensitive": true,
  6648. /**
  6649. * Applied search term
  6650. * @type string
  6651. * @default <i>Empty string</i>
  6652. */
  6653. "sSearch": "",
  6654. /**
  6655. * Flag to indicate if the search term should be interpreted as a
  6656. * regular expression (true) or not (false) and therefore and special
  6657. * regex characters escaped.
  6658. * @type boolean
  6659. * @default false
  6660. */
  6661. "bRegex": false,
  6662. /**
  6663. * Flag to indicate if DataTables is to use its smart filtering or not.
  6664. * @type boolean
  6665. * @default true
  6666. */
  6667. "bSmart": true
  6668. };
  6669. /**
  6670. * Template object for the way in which DataTables holds information about
  6671. * each individual row. This is the object format used for the settings
  6672. * aoData array.
  6673. * @namespace
  6674. */
  6675. DataTable.models.oRow = {
  6676. /**
  6677. * TR element for the row
  6678. * @type node
  6679. * @default null
  6680. */
  6681. "nTr": null,
  6682. /**
  6683. * Data object from the original data source for the row. This is either
  6684. * an array if using the traditional form of DataTables, or an object if
  6685. * using mData options. The exact type will depend on the passed in
  6686. * data from the data source, or will be an array if using DOM a data
  6687. * source.
  6688. * @type array|object
  6689. * @default []
  6690. */
  6691. "_aData": [],
  6692. /**
  6693. * Sorting data cache - this array is ostensibly the same length as the
  6694. * number of columns (although each index is generated only as it is
  6695. * needed), and holds the data that is used for sorting each column in the
  6696. * row. We do this cache generation at the start of the sort in order that
  6697. * the formatting of the sort data need be done only once for each cell
  6698. * per sort. This array should not be read from or written to by anything
  6699. * other than the master sorting methods.
  6700. * @type array
  6701. * @default []
  6702. * @private
  6703. */
  6704. "_aSortData": [],
  6705. /**
  6706. * Array of TD elements that are cached for hidden rows, so they can be
  6707. * reinserted into the table if a column is made visible again (or to act
  6708. * as a store if a column is made hidden). Only hidden columns have a
  6709. * reference in the array. For non-hidden columns the value is either
  6710. * undefined or null.
  6711. * @type array nodes
  6712. * @default []
  6713. * @private
  6714. */
  6715. "_anHidden": [],
  6716. /**
  6717. * Cache of the class name that DataTables has applied to the row, so we
  6718. * can quickly look at this variable rather than needing to do a DOM check
  6719. * on className for the nTr property.
  6720. * @type string
  6721. * @default <i>Empty string</i>
  6722. * @private
  6723. */
  6724. "_sRowStripe": ""
  6725. };
  6726. /**
  6727. * Template object for the column information object in DataTables. This object
  6728. * is held in the settings aoColumns array and contains all the information that
  6729. * DataTables needs about each individual column.
  6730. *
  6731. * Note that this object is related to {@link DataTable.defaults.columns}
  6732. * but this one is the internal data store for DataTables's cache of columns.
  6733. * It should NOT be manipulated outside of DataTables. Any configuration should
  6734. * be done through the initialisation options.
  6735. * @namespace
  6736. */
  6737. DataTable.models.oColumn = {
  6738. /**
  6739. * A list of the columns that sorting should occur on when this column
  6740. * is sorted. That this property is an array allows multi-column sorting
  6741. * to be defined for a column (for example first name / last name columns
  6742. * would benefit from this). The values are integers pointing to the
  6743. * columns to be sorted on (typically it will be a single integer pointing
  6744. * at itself, but that doesn't need to be the case).
  6745. * @type array
  6746. */
  6747. "aDataSort": null,
  6748. /**
  6749. * Define the sorting directions that are applied to the column, in sequence
  6750. * as the column is repeatedly sorted upon - i.e. the first value is used
  6751. * as the sorting direction when the column if first sorted (clicked on).
  6752. * Sort it again (click again) and it will move on to the next index.
  6753. * Repeat until loop.
  6754. * @type array
  6755. */
  6756. "asSorting": null,
  6757. /**
  6758. * Flag to indicate if the column is searchable, and thus should be included
  6759. * in the filtering or not.
  6760. * @type boolean
  6761. */
  6762. "bSearchable": null,
  6763. /**
  6764. * Flag to indicate if the column is sortable or not.
  6765. * @type boolean
  6766. */
  6767. "bSortable": null,
  6768. /**
  6769. * <code>Deprecated</code> When using fnRender, you have two options for what
  6770. * to do with the data, and this property serves as the switch. Firstly, you
  6771. * can have the sorting and filtering use the rendered value (true - default),
  6772. * or you can have the sorting and filtering us the original value (false).
  6773. *
  6774. * Please note that this option has now been deprecated and will be removed
  6775. * in the next version of DataTables. Please use mRender / mData rather than
  6776. * fnRender.
  6777. * @type boolean
  6778. * @deprecated
  6779. */
  6780. "bUseRendered": null,
  6781. /**
  6782. * Flag to indicate if the column is currently visible in the table or not
  6783. * @type boolean
  6784. */
  6785. "bVisible": null,
  6786. /**
  6787. * Flag to indicate to the type detection method if the automatic type
  6788. * detection should be used, or if a column type (sType) has been specified
  6789. * @type boolean
  6790. * @default true
  6791. * @private
  6792. */
  6793. "_bAutoType": true,
  6794. /**
  6795. * Developer definable function that is called whenever a cell is created (Ajax source,
  6796. * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  6797. * allowing you to modify the DOM element (add background colour for example) when the
  6798. * element is available.
  6799. * @type function
  6800. * @param {element} nTd The TD node that has been created
  6801. * @param {*} sData The Data for the cell
  6802. * @param {array|object} oData The data for the whole row
  6803. * @param {int} iRow The row index for the aoData data store
  6804. * @default null
  6805. */
  6806. "fnCreatedCell": null,
  6807. /**
  6808. * Function to get data from a cell in a column. You should <b>never</b>
  6809. * access data directly through _aData internally in DataTables - always use
  6810. * the method attached to this property. It allows mData to function as
  6811. * required. This function is automatically assigned by the column
  6812. * initialisation method
  6813. * @type function
  6814. * @param {array|object} oData The data array/object for the array
  6815. * (i.e. aoData[]._aData)
  6816. * @param {string} sSpecific The specific data type you want to get -
  6817. * 'display', 'type' 'filter' 'sort'
  6818. * @returns {*} The data for the cell from the given row's data
  6819. * @default null
  6820. */
  6821. "fnGetData": null,
  6822. /**
  6823. * <code>Deprecated</code> Custom display function that will be called for the
  6824. * display of each cell in this column.
  6825. *
  6826. * Please note that this option has now been deprecated and will be removed
  6827. * in the next version of DataTables. Please use mRender / mData rather than
  6828. * fnRender.
  6829. * @type function
  6830. * @param {object} o Object with the following parameters:
  6831. * @param {int} o.iDataRow The row in aoData
  6832. * @param {int} o.iDataColumn The column in question
  6833. * @param {array} o.aData The data for the row in question
  6834. * @param {object} o.oSettings The settings object for this DataTables instance
  6835. * @returns {string} The string you which to use in the display
  6836. * @default null
  6837. * @deprecated
  6838. */
  6839. "fnRender": null,
  6840. /**
  6841. * Function to set data for a cell in the column. You should <b>never</b>
  6842. * set the data directly to _aData internally in DataTables - always use
  6843. * this method. It allows mData to function as required. This function
  6844. * is automatically assigned by the column initialisation method
  6845. * @type function
  6846. * @param {array|object} oData The data array/object for the array
  6847. * (i.e. aoData[]._aData)
  6848. * @param {*} sValue Value to set
  6849. * @default null
  6850. */
  6851. "fnSetData": null,
  6852. /**
  6853. * Property to read the value for the cells in the column from the data
  6854. * source array / object. If null, then the default content is used, if a
  6855. * function is given then the return from the function is used.
  6856. * @type function|int|string|null
  6857. * @default null
  6858. */
  6859. "mData": null,
  6860. /**
  6861. * Partner property to mData which is used (only when defined) to get
  6862. * the data - i.e. it is basically the same as mData, but without the
  6863. * 'set' option, and also the data fed to it is the result from mData.
  6864. * This is the rendering method to match the data method of mData.
  6865. * @type function|int|string|null
  6866. * @default null
  6867. */
  6868. "mRender": null,
  6869. /**
  6870. * Unique header TH/TD element for this column - this is what the sorting
  6871. * listener is attached to (if sorting is enabled.)
  6872. * @type node
  6873. * @default null
  6874. */
  6875. "nTh": null,
  6876. /**
  6877. * Unique footer TH/TD element for this column (if there is one). Not used
  6878. * in DataTables as such, but can be used for plug-ins to reference the
  6879. * footer for each column.
  6880. * @type node
  6881. * @default null
  6882. */
  6883. "nTf": null,
  6884. /**
  6885. * The class to apply to all TD elements in the table's TBODY for the column
  6886. * @type string
  6887. * @default null
  6888. */
  6889. "sClass": null,
  6890. /**
  6891. * When DataTables calculates the column widths to assign to each column,
  6892. * it finds the longest string in each column and then constructs a
  6893. * temporary table and reads the widths from that. The problem with this
  6894. * is that "mmm" is much wider then "iiii", but the latter is a longer
  6895. * string - thus the calculation can go wrong (doing it properly and putting
  6896. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  6897. * a "work around" we provide this option. It will append its value to the
  6898. * text that is found to be the longest string for the column - i.e. padding.
  6899. * @type string
  6900. */
  6901. "sContentPadding": null,
  6902. /**
  6903. * Allows a default value to be given for a column's data, and will be used
  6904. * whenever a null data source is encountered (this can be because mData
  6905. * is set to null, or because the data source itself is null).
  6906. * @type string
  6907. * @default null
  6908. */
  6909. "sDefaultContent": null,
  6910. /**
  6911. * Name for the column, allowing reference to the column by name as well as
  6912. * by index (needs a lookup to work by name).
  6913. * @type string
  6914. */
  6915. "sName": null,
  6916. /**
  6917. * Custom sorting data type - defines which of the available plug-ins in
  6918. * afnSortData the custom sorting will use - if any is defined.
  6919. * @type string
  6920. * @default std
  6921. */
  6922. "sSortDataType": 'std',
  6923. /**
  6924. * Class to be applied to the header element when sorting on this column
  6925. * @type string
  6926. * @default null
  6927. */
  6928. "sSortingClass": null,
  6929. /**
  6930. * Class to be applied to the header element when sorting on this column -
  6931. * when jQuery UI theming is used.
  6932. * @type string
  6933. * @default null
  6934. */
  6935. "sSortingClassJUI": null,
  6936. /**
  6937. * Title of the column - what is seen in the TH element (nTh).
  6938. * @type string
  6939. */
  6940. "sTitle": null,
  6941. /**
  6942. * Column sorting and filtering type
  6943. * @type string
  6944. * @default null
  6945. */
  6946. "sType": null,
  6947. /**
  6948. * Width of the column
  6949. * @type string
  6950. * @default null
  6951. */
  6952. "sWidth": null,
  6953. /**
  6954. * Width of the column when it was first "encountered"
  6955. * @type string
  6956. * @default null
  6957. */
  6958. "sWidthOrig": null
  6959. };
  6960. /**
  6961. * Initialisation options that can be given to DataTables at initialisation
  6962. * time.
  6963. * @namespace
  6964. */
  6965. DataTable.defaults = {
  6966. /**
  6967. * An array of data to use for the table, passed in at initialisation which
  6968. * will be used in preference to any data which is already in the DOM. This is
  6969. * particularly useful for constructing tables purely in Javascript, for
  6970. * example with a custom Ajax call.
  6971. * @type array
  6972. * @default null
  6973. * @dtopt Option
  6974. *
  6975. * @example
  6976. * // Using a 2D array data source
  6977. * $(document).ready( function () {
  6978. * $('#example').dataTable( {
  6979. * "aaData": [
  6980. * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
  6981. * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
  6982. * ],
  6983. * "aoColumns": [
  6984. * { "sTitle": "Engine" },
  6985. * { "sTitle": "Browser" },
  6986. * { "sTitle": "Platform" },
  6987. * { "sTitle": "Version" },
  6988. * { "sTitle": "Grade" }
  6989. * ]
  6990. * } );
  6991. * } );
  6992. *
  6993. * @example
  6994. * // Using an array of objects as a data source (mData)
  6995. * $(document).ready( function () {
  6996. * $('#example').dataTable( {
  6997. * "aaData": [
  6998. * {
  6999. * "engine": "Trident",
  7000. * "browser": "Internet Explorer 4.0",
  7001. * "platform": "Win 95+",
  7002. * "version": 4,
  7003. * "grade": "X"
  7004. * },
  7005. * {
  7006. * "engine": "Trident",
  7007. * "browser": "Internet Explorer 5.0",
  7008. * "platform": "Win 95+",
  7009. * "version": 5,
  7010. * "grade": "C"
  7011. * }
  7012. * ],
  7013. * "aoColumns": [
  7014. * { "sTitle": "Engine", "mData": "engine" },
  7015. * { "sTitle": "Browser", "mData": "browser" },
  7016. * { "sTitle": "Platform", "mData": "platform" },
  7017. * { "sTitle": "Version", "mData": "version" },
  7018. * { "sTitle": "Grade", "mData": "grade" }
  7019. * ]
  7020. * } );
  7021. * } );
  7022. */
  7023. "aaData": null,
  7024. /**
  7025. * If sorting is enabled, then DataTables will perform a first pass sort on
  7026. * initialisation. You can define which column(s) the sort is performed upon,
  7027. * and the sorting direction, with this variable. The aaSorting array should
  7028. * contain an array for each column to be sorted initially containing the
  7029. * column's index and a direction string ('asc' or 'desc').
  7030. * @type array
  7031. * @default [[0,'asc']]
  7032. * @dtopt Option
  7033. *
  7034. * @example
  7035. * // Sort by 3rd column first, and then 4th column
  7036. * $(document).ready( function() {
  7037. * $('#example').dataTable( {
  7038. * "aaSorting": [[2,'asc'], [3,'desc']]
  7039. * } );
  7040. * } );
  7041. *
  7042. * // No initial sorting
  7043. * $(document).ready( function() {
  7044. * $('#example').dataTable( {
  7045. * "aaSorting": []
  7046. * } );
  7047. * } );
  7048. */
  7049. "aaSorting": [[0,'asc']],
  7050. /**
  7051. * This parameter is basically identical to the aaSorting parameter, but
  7052. * cannot be overridden by user interaction with the table. What this means
  7053. * is that you could have a column (visible or hidden) which the sorting will
  7054. * always be forced on first - any sorting after that (from the user) will
  7055. * then be performed as required. This can be useful for grouping rows
  7056. * together.
  7057. * @type array
  7058. * @default null
  7059. * @dtopt Option
  7060. *
  7061. * @example
  7062. * $(document).ready( function() {
  7063. * $('#example').dataTable( {
  7064. * "aaSortingFixed": [[0,'asc']]
  7065. * } );
  7066. * } )
  7067. */
  7068. "aaSortingFixed": null,
  7069. /**
  7070. * This parameter allows you to readily specify the entries in the length drop
  7071. * down menu that DataTables shows when pagination is enabled. It can be
  7072. * either a 1D array of options which will be used for both the displayed
  7073. * option and the value, or a 2D array which will use the array in the first
  7074. * position as the value, and the array in the second position as the
  7075. * displayed options (useful for language strings such as 'All').
  7076. * @type array
  7077. * @default [ 10, 25, 50, 100 ]
  7078. * @dtopt Option
  7079. *
  7080. * @example
  7081. * $(document).ready( function() {
  7082. * $('#example').dataTable( {
  7083. * "aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
  7084. * } );
  7085. * } );
  7086. *
  7087. * @example
  7088. * // Setting the default display length as well as length menu
  7089. * // This is likely to be wanted if you remove the '10' option which
  7090. * // is the iDisplayLength default.
  7091. * $(document).ready( function() {
  7092. * $('#example').dataTable( {
  7093. * "iDisplayLength": 25,
  7094. * "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]]
  7095. * } );
  7096. * } );
  7097. */
  7098. "aLengthMenu": [ 10, 25, 50, 100 ],
  7099. /**
  7100. * The aoColumns option in the initialisation parameter allows you to define
  7101. * details about the way individual columns behave. For a full list of
  7102. * column options that can be set, please see
  7103. * {@link DataTable.defaults.columns}. Note that if you use aoColumns to
  7104. * define your columns, you must have an entry in the array for every single
  7105. * column that you have in your table (these can be null if you don't which
  7106. * to specify any options).
  7107. * @member
  7108. */
  7109. "aoColumns": null,
  7110. /**
  7111. * Very similar to aoColumns, aoColumnDefs allows you to target a specific
  7112. * column, multiple columns, or all columns, using the aTargets property of
  7113. * each object in the array. This allows great flexibility when creating
  7114. * tables, as the aoColumnDefs arrays can be of any length, targeting the
  7115. * columns you specifically want. aoColumnDefs may use any of the column
  7116. * options available: {@link DataTable.defaults.columns}, but it _must_
  7117. * have aTargets defined in each object in the array. Values in the aTargets
  7118. * array may be:
  7119. * <ul>
  7120. * <li>a string - class name will be matched on the TH for the column</li>
  7121. * <li>0 or a positive integer - column index counting from the left</li>
  7122. * <li>a negative integer - column index counting from the right</li>
  7123. * <li>the string "_all" - all columns (i.e. assign a default)</li>
  7124. * </ul>
  7125. * @member
  7126. */
  7127. "aoColumnDefs": null,
  7128. /**
  7129. * Basically the same as oSearch, this parameter defines the individual column
  7130. * filtering state at initialisation time. The array must be of the same size
  7131. * as the number of columns, and each element be an object with the parameters
  7132. * "sSearch" and "bEscapeRegex" (the latter is optional). 'null' is also
  7133. * accepted and the default will be used.
  7134. * @type array
  7135. * @default []
  7136. * @dtopt Option
  7137. *
  7138. * @example
  7139. * $(document).ready( function() {
  7140. * $('#example').dataTable( {
  7141. * "aoSearchCols": [
  7142. * null,
  7143. * { "sSearch": "My filter" },
  7144. * null,
  7145. * { "sSearch": "^[0-9]", "bEscapeRegex": false }
  7146. * ]
  7147. * } );
  7148. * } )
  7149. */
  7150. "aoSearchCols": [],
  7151. /**
  7152. * An array of CSS classes that should be applied to displayed rows. This
  7153. * array may be of any length, and DataTables will apply each class
  7154. * sequentially, looping when required.
  7155. * @type array
  7156. * @default null <i>Will take the values determined by the oClasses.sStripe*
  7157. * options</i>
  7158. * @dtopt Option
  7159. *
  7160. * @example
  7161. * $(document).ready( function() {
  7162. * $('#example').dataTable( {
  7163. * "asStripeClasses": [ 'strip1', 'strip2', 'strip3' ]
  7164. * } );
  7165. * } )
  7166. */
  7167. "asStripeClasses": null,
  7168. /**
  7169. * Enable or disable automatic column width calculation. This can be disabled
  7170. * as an optimisation (it takes some time to calculate the widths) if the
  7171. * tables widths are passed in using aoColumns.
  7172. * @type boolean
  7173. * @default true
  7174. * @dtopt Features
  7175. *
  7176. * @example
  7177. * $(document).ready( function () {
  7178. * $('#example').dataTable( {
  7179. * "bAutoWidth": false
  7180. * } );
  7181. * } );
  7182. */
  7183. "bAutoWidth": true,
  7184. /**
  7185. * Deferred rendering can provide DataTables with a huge speed boost when you
  7186. * are using an Ajax or JS data source for the table. This option, when set to
  7187. * true, will cause DataTables to defer the creation of the table elements for
  7188. * each row until they are needed for a draw - saving a significant amount of
  7189. * time.
  7190. * @type boolean
  7191. * @default false
  7192. * @dtopt Features
  7193. *
  7194. * @example
  7195. * $(document).ready( function() {
  7196. * var oTable = $('#example').dataTable( {
  7197. * "sAjaxSource": "sources/arrays.txt",
  7198. * "bDeferRender": true
  7199. * } );
  7200. * } );
  7201. */
  7202. "bDeferRender": false,
  7203. /**
  7204. * Replace a DataTable which matches the given selector and replace it with
  7205. * one which has the properties of the new initialisation object passed. If no
  7206. * table matches the selector, then the new DataTable will be constructed as
  7207. * per normal.
  7208. * @type boolean
  7209. * @default false
  7210. * @dtopt Options
  7211. *
  7212. * @example
  7213. * $(document).ready( function() {
  7214. * $('#example').dataTable( {
  7215. * "sScrollY": "200px",
  7216. * "bPaginate": false
  7217. * } );
  7218. *
  7219. * // Some time later....
  7220. * $('#example').dataTable( {
  7221. * "bFilter": false,
  7222. * "bDestroy": true
  7223. * } );
  7224. * } );
  7225. */
  7226. "bDestroy": false,
  7227. /**
  7228. * Enable or disable filtering of data. Filtering in DataTables is "smart" in
  7229. * that it allows the end user to input multiple words (space separated) and
  7230. * will match a row containing those words, even if not in the order that was
  7231. * specified (this allow matching across multiple columns). Note that if you
  7232. * wish to use filtering in DataTables this must remain 'true' - to remove the
  7233. * default filtering input box and retain filtering abilities, please use
  7234. * {@link DataTable.defaults.sDom}.
  7235. * @type boolean
  7236. * @default true
  7237. * @dtopt Features
  7238. *
  7239. * @example
  7240. * $(document).ready( function () {
  7241. * $('#example').dataTable( {
  7242. * "bFilter": false
  7243. * } );
  7244. * } );
  7245. */
  7246. "bFilter": true,
  7247. /**
  7248. * Enable or disable the table information display. This shows information
  7249. * about the data that is currently visible on the page, including information
  7250. * about filtered data if that action is being performed.
  7251. * @type boolean
  7252. * @default true
  7253. * @dtopt Features
  7254. *
  7255. * @example
  7256. * $(document).ready( function () {
  7257. * $('#example').dataTable( {
  7258. * "bInfo": false
  7259. * } );
  7260. * } );
  7261. */
  7262. "bInfo": true,
  7263. /**
  7264. * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
  7265. * slightly different and additional mark-up from what DataTables has
  7266. * traditionally used).
  7267. * @type boolean
  7268. * @default false
  7269. * @dtopt Features
  7270. *
  7271. * @example
  7272. * $(document).ready( function() {
  7273. * $('#example').dataTable( {
  7274. * "bJQueryUI": true
  7275. * } );
  7276. * } );
  7277. */
  7278. "bJQueryUI": false,
  7279. /**
  7280. * Allows the end user to select the size of a formatted page from a select
  7281. * menu (sizes are 10, 25, 50 and 100). Requires pagination (bPaginate).
  7282. * @type boolean
  7283. * @default true
  7284. * @dtopt Features
  7285. *
  7286. * @example
  7287. * $(document).ready( function () {
  7288. * $('#example').dataTable( {
  7289. * "bLengthChange": false
  7290. * } );
  7291. * } );
  7292. */
  7293. "bLengthChange": true,
  7294. /**
  7295. * Enable or disable pagination.
  7296. * @type boolean
  7297. * @default true
  7298. * @dtopt Features
  7299. *
  7300. * @example
  7301. * $(document).ready( function () {
  7302. * $('#example').dataTable( {
  7303. * "bPaginate": false
  7304. * } );
  7305. * } );
  7306. */
  7307. "bPaginate": true,
  7308. /**
  7309. * Enable or disable the display of a 'processing' indicator when the table is
  7310. * being processed (e.g. a sort). This is particularly useful for tables with
  7311. * large amounts of data where it can take a noticeable amount of time to sort
  7312. * the entries.
  7313. * @type boolean
  7314. * @default false
  7315. * @dtopt Features
  7316. *
  7317. * @example
  7318. * $(document).ready( function () {
  7319. * $('#example').dataTable( {
  7320. * "bProcessing": true
  7321. * } );
  7322. * } );
  7323. */
  7324. "bProcessing": false,
  7325. /**
  7326. * Retrieve the DataTables object for the given selector. Note that if the
  7327. * table has already been initialised, this parameter will cause DataTables
  7328. * to simply return the object that has already been set up - it will not take
  7329. * account of any changes you might have made to the initialisation object
  7330. * passed to DataTables (setting this parameter to true is an acknowledgement
  7331. * that you understand this). bDestroy can be used to reinitialise a table if
  7332. * you need.
  7333. * @type boolean
  7334. * @default false
  7335. * @dtopt Options
  7336. *
  7337. * @example
  7338. * $(document).ready( function() {
  7339. * initTable();
  7340. * tableActions();
  7341. * } );
  7342. *
  7343. * function initTable ()
  7344. * {
  7345. * return $('#example').dataTable( {
  7346. * "sScrollY": "200px",
  7347. * "bPaginate": false,
  7348. * "bRetrieve": true
  7349. * } );
  7350. * }
  7351. *
  7352. * function tableActions ()
  7353. * {
  7354. * var oTable = initTable();
  7355. * // perform API operations with oTable
  7356. * }
  7357. */
  7358. "bRetrieve": false,
  7359. /**
  7360. * Indicate if DataTables should be allowed to set the padding / margin
  7361. * etc for the scrolling header elements or not. Typically you will want
  7362. * this.
  7363. * @type boolean
  7364. * @default true
  7365. * @dtopt Options
  7366. *
  7367. * @example
  7368. * $(document).ready( function() {
  7369. * $('#example').dataTable( {
  7370. * "bScrollAutoCss": false,
  7371. * "sScrollY": "200px"
  7372. * } );
  7373. * } );
  7374. */
  7375. "bScrollAutoCss": true,
  7376. /**
  7377. * When vertical (y) scrolling is enabled, DataTables will force the height of
  7378. * the table's viewport to the given height at all times (useful for layout).
  7379. * However, this can look odd when filtering data down to a small data set,
  7380. * and the footer is left "floating" further down. This parameter (when
  7381. * enabled) will cause DataTables to collapse the table's viewport down when
  7382. * the result set will fit within the given Y height.
  7383. * @type boolean
  7384. * @default false
  7385. * @dtopt Options
  7386. *
  7387. * @example
  7388. * $(document).ready( function() {
  7389. * $('#example').dataTable( {
  7390. * "sScrollY": "200",
  7391. * "bScrollCollapse": true
  7392. * } );
  7393. * } );
  7394. */
  7395. "bScrollCollapse": false,
  7396. /**
  7397. * Enable infinite scrolling for DataTables (to be used in combination with
  7398. * sScrollY). Infinite scrolling means that DataTables will continually load
  7399. * data as a user scrolls through a table, which is very useful for large
  7400. * dataset. This cannot be used with pagination, which is automatically
  7401. * disabled. Note - the Scroller extra for DataTables is recommended in
  7402. * in preference to this option.
  7403. * @type boolean
  7404. * @default false
  7405. * @dtopt Features
  7406. *
  7407. * @example
  7408. * $(document).ready( function() {
  7409. * $('#example').dataTable( {
  7410. * "bScrollInfinite": true,
  7411. * "bScrollCollapse": true,
  7412. * "sScrollY": "200px"
  7413. * } );
  7414. * } );
  7415. */
  7416. "bScrollInfinite": false,
  7417. /**
  7418. * Configure DataTables to use server-side processing. Note that the
  7419. * sAjaxSource parameter must also be given in order to give DataTables a
  7420. * source to obtain the required data for each draw.
  7421. * @type boolean
  7422. * @default false
  7423. * @dtopt Features
  7424. * @dtopt Server-side
  7425. *
  7426. * @example
  7427. * $(document).ready( function () {
  7428. * $('#example').dataTable( {
  7429. * "bServerSide": true,
  7430. * "sAjaxSource": "xhr.php"
  7431. * } );
  7432. * } );
  7433. */
  7434. "bServerSide": false,
  7435. /**
  7436. * Enable or disable sorting of columns. Sorting of individual columns can be
  7437. * disabled by the "bSortable" option for each column.
  7438. * @type boolean
  7439. * @default true
  7440. * @dtopt Features
  7441. *
  7442. * @example
  7443. * $(document).ready( function () {
  7444. * $('#example').dataTable( {
  7445. * "bSort": false
  7446. * } );
  7447. * } );
  7448. */
  7449. "bSort": true,
  7450. /**
  7451. * Allows control over whether DataTables should use the top (true) unique
  7452. * cell that is found for a single column, or the bottom (false - default).
  7453. * This is useful when using complex headers.
  7454. * @type boolean
  7455. * @default false
  7456. * @dtopt Options
  7457. *
  7458. * @example
  7459. * $(document).ready( function() {
  7460. * $('#example').dataTable( {
  7461. * "bSortCellsTop": true
  7462. * } );
  7463. * } );
  7464. */
  7465. "bSortCellsTop": false,
  7466. /**
  7467. * Enable or disable the addition of the classes 'sorting_1', 'sorting_2' and
  7468. * 'sorting_3' to the columns which are currently being sorted on. This is
  7469. * presented as a feature switch as it can increase processing time (while
  7470. * classes are removed and added) so for large data sets you might want to
  7471. * turn this off.
  7472. * @type boolean
  7473. * @default true
  7474. * @dtopt Features
  7475. *
  7476. * @example
  7477. * $(document).ready( function () {
  7478. * $('#example').dataTable( {
  7479. * "bSortClasses": false
  7480. * } );
  7481. * } );
  7482. */
  7483. "bSortClasses": true,
  7484. /**
  7485. * Enable or disable state saving. When enabled a cookie will be used to save
  7486. * table display information such as pagination information, display length,
  7487. * filtering and sorting. As such when the end user reloads the page the
  7488. * display display will match what thy had previously set up.
  7489. * @type boolean
  7490. * @default false
  7491. * @dtopt Features
  7492. *
  7493. * @example
  7494. * $(document).ready( function () {
  7495. * $('#example').dataTable( {
  7496. * "bStateSave": true
  7497. * } );
  7498. * } );
  7499. */
  7500. "bStateSave": false,
  7501. /**
  7502. * Customise the cookie and / or the parameters being stored when using
  7503. * DataTables with state saving enabled. This function is called whenever
  7504. * the cookie is modified, and it expects a fully formed cookie string to be
  7505. * returned. Note that the data object passed in is a Javascript object which
  7506. * must be converted to a string (JSON.stringify for example).
  7507. * @type function
  7508. * @param {string} sName Name of the cookie defined by DataTables
  7509. * @param {object} oData Data to be stored in the cookie
  7510. * @param {string} sExpires Cookie expires string
  7511. * @param {string} sPath Path of the cookie to set
  7512. * @returns {string} Cookie formatted string (which should be encoded by
  7513. * using encodeURIComponent())
  7514. * @dtopt Callbacks
  7515. *
  7516. * @example
  7517. * $(document).ready( function () {
  7518. * $('#example').dataTable( {
  7519. * "fnCookieCallback": function (sName, oData, sExpires, sPath) {
  7520. * // Customise oData or sName or whatever else here
  7521. * return sName + "="+JSON.stringify(oData)+"; expires=" + sExpires +"; path=" + sPath;
  7522. * }
  7523. * } );
  7524. * } );
  7525. */
  7526. "fnCookieCallback": null,
  7527. /**
  7528. * This function is called when a TR element is created (and all TD child
  7529. * elements have been inserted), or registered if using a DOM source, allowing
  7530. * manipulation of the TR element (adding classes etc).
  7531. * @type function
  7532. * @param {node} nRow "TR" element for the current row
  7533. * @param {array} aData Raw data array for this row
  7534. * @param {int} iDataIndex The index of this row in aoData
  7535. * @dtopt Callbacks
  7536. *
  7537. * @example
  7538. * $(document).ready( function() {
  7539. * $('#example').dataTable( {
  7540. * "fnCreatedRow": function( nRow, aData, iDataIndex ) {
  7541. * // Bold the grade for all 'A' grade browsers
  7542. * if ( aData[4] == "A" )
  7543. * {
  7544. * $('td:eq(4)', nRow).html( '<b>A</b>' );
  7545. * }
  7546. * }
  7547. * } );
  7548. * } );
  7549. */
  7550. "fnCreatedRow": null,
  7551. /**
  7552. * This function is called on every 'draw' event, and allows you to
  7553. * dynamically modify any aspect you want about the created DOM.
  7554. * @type function
  7555. * @param {object} oSettings DataTables settings object
  7556. * @dtopt Callbacks
  7557. *
  7558. * @example
  7559. * $(document).ready( function() {
  7560. * $('#example').dataTable( {
  7561. * "fnDrawCallback": function( oSettings ) {
  7562. * alert( 'DataTables has redrawn the table' );
  7563. * }
  7564. * } );
  7565. * } );
  7566. */
  7567. "fnDrawCallback": null,
  7568. /**
  7569. * Identical to fnHeaderCallback() but for the table footer this function
  7570. * allows you to modify the table footer on every 'draw' even.
  7571. * @type function
  7572. * @param {node} nFoot "TR" element for the footer
  7573. * @param {array} aData Full table data (as derived from the original HTML)
  7574. * @param {int} iStart Index for the current display starting point in the
  7575. * display array
  7576. * @param {int} iEnd Index for the current display ending point in the
  7577. * display array
  7578. * @param {array int} aiDisplay Index array to translate the visual position
  7579. * to the full data array
  7580. * @dtopt Callbacks
  7581. *
  7582. * @example
  7583. * $(document).ready( function() {
  7584. * $('#example').dataTable( {
  7585. * "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) {
  7586. * nFoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+iStart;
  7587. * }
  7588. * } );
  7589. * } )
  7590. */
  7591. "fnFooterCallback": null,
  7592. /**
  7593. * When rendering large numbers in the information element for the table
  7594. * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
  7595. * to have a comma separator for the 'thousands' units (e.g. 1 million is
  7596. * rendered as "1,000,000") to help readability for the end user. This
  7597. * function will override the default method DataTables uses.
  7598. * @type function
  7599. * @member
  7600. * @param {int} iIn number to be formatted
  7601. * @returns {string} formatted string for DataTables to show the number
  7602. * @dtopt Callbacks
  7603. *
  7604. * @example
  7605. * $(document).ready( function() {
  7606. * $('#example').dataTable( {
  7607. * "fnFormatNumber": function ( iIn ) {
  7608. * if ( iIn &lt; 1000 ) {
  7609. * return iIn;
  7610. * } else {
  7611. * var
  7612. * s=(iIn+""),
  7613. * a=s.split(""), out="",
  7614. * iLen=s.length;
  7615. *
  7616. * for ( var i=0 ; i&lt;iLen ; i++ ) {
  7617. * if ( i%3 === 0 &amp;&amp; i !== 0 ) {
  7618. * out = "'"+out;
  7619. * }
  7620. * out = a[iLen-i-1]+out;
  7621. * }
  7622. * }
  7623. * return out;
  7624. * };
  7625. * } );
  7626. * } );
  7627. */
  7628. "fnFormatNumber": function ( iIn ) {
  7629. if ( iIn < 1000 )
  7630. {
  7631. // A small optimisation for what is likely to be the majority of use cases
  7632. return iIn;
  7633. }
  7634. var s=(iIn+""), a=s.split(""), out="", iLen=s.length;
  7635. for ( var i=0 ; i<iLen ; i++ )
  7636. {
  7637. if ( i%3 === 0 && i !== 0 )
  7638. {
  7639. out = this.oLanguage.sInfoThousands+out;
  7640. }
  7641. out = a[iLen-i-1]+out;
  7642. }
  7643. return out;
  7644. },
  7645. /**
  7646. * This function is called on every 'draw' event, and allows you to
  7647. * dynamically modify the header row. This can be used to calculate and
  7648. * display useful information about the table.
  7649. * @type function
  7650. * @param {node} nHead "TR" element for the header
  7651. * @param {array} aData Full table data (as derived from the original HTML)
  7652. * @param {int} iStart Index for the current display starting point in the
  7653. * display array
  7654. * @param {int} iEnd Index for the current display ending point in the
  7655. * display array
  7656. * @param {array int} aiDisplay Index array to translate the visual position
  7657. * to the full data array
  7658. * @dtopt Callbacks
  7659. *
  7660. * @example
  7661. * $(document).ready( function() {
  7662. * $('#example').dataTable( {
  7663. * "fnHeaderCallback": function( nHead, aData, iStart, iEnd, aiDisplay ) {
  7664. * nHead.getElementsByTagName('th')[0].innerHTML = "Displaying "+(iEnd-iStart)+" records";
  7665. * }
  7666. * } );
  7667. * } )
  7668. */
  7669. "fnHeaderCallback": null,
  7670. /**
  7671. * The information element can be used to convey information about the current
  7672. * state of the table. Although the internationalisation options presented by
  7673. * DataTables are quite capable of dealing with most customisations, there may
  7674. * be times where you wish to customise the string further. This callback
  7675. * allows you to do exactly that.
  7676. * @type function
  7677. * @param {object} oSettings DataTables settings object
  7678. * @param {int} iStart Starting position in data for the draw
  7679. * @param {int} iEnd End position in data for the draw
  7680. * @param {int} iMax Total number of rows in the table (regardless of
  7681. * filtering)
  7682. * @param {int} iTotal Total number of rows in the data set, after filtering
  7683. * @param {string} sPre The string that DataTables has formatted using it's
  7684. * own rules
  7685. * @returns {string} The string to be displayed in the information element.
  7686. * @dtopt Callbacks
  7687. *
  7688. * @example
  7689. * $('#example').dataTable( {
  7690. * "fnInfoCallback": function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) {
  7691. * return iStart +" to "+ iEnd;
  7692. * }
  7693. * } );
  7694. */
  7695. "fnInfoCallback": null,
  7696. /**
  7697. * Called when the table has been initialised. Normally DataTables will
  7698. * initialise sequentially and there will be no need for this function,
  7699. * however, this does not hold true when using external language information
  7700. * since that is obtained using an async XHR call.
  7701. * @type function
  7702. * @param {object} oSettings DataTables settings object
  7703. * @param {object} json The JSON object request from the server - only
  7704. * present if client-side Ajax sourced data is used
  7705. * @dtopt Callbacks
  7706. *
  7707. * @example
  7708. * $(document).ready( function() {
  7709. * $('#example').dataTable( {
  7710. * "fnInitComplete": function(oSettings, json) {
  7711. * alert( 'DataTables has finished its initialisation.' );
  7712. * }
  7713. * } );
  7714. * } )
  7715. */
  7716. "fnInitComplete": null,
  7717. /**
  7718. * Called at the very start of each table draw and can be used to cancel the
  7719. * draw by returning false, any other return (including undefined) results in
  7720. * the full draw occurring).
  7721. * @type function
  7722. * @param {object} oSettings DataTables settings object
  7723. * @returns {boolean} False will cancel the draw, anything else (including no
  7724. * return) will allow it to complete.
  7725. * @dtopt Callbacks
  7726. *
  7727. * @example
  7728. * $(document).ready( function() {
  7729. * $('#example').dataTable( {
  7730. * "fnPreDrawCallback": function( oSettings ) {
  7731. * if ( $('#test').val() == 1 ) {
  7732. * return false;
  7733. * }
  7734. * }
  7735. * } );
  7736. * } );
  7737. */
  7738. "fnPreDrawCallback": null,
  7739. /**
  7740. * This function allows you to 'post process' each row after it have been
  7741. * generated for each table draw, but before it is rendered on screen. This
  7742. * function might be used for setting the row class name etc.
  7743. * @type function
  7744. * @param {node} nRow "TR" element for the current row
  7745. * @param {array} aData Raw data array for this row
  7746. * @param {int} iDisplayIndex The display index for the current table draw
  7747. * @param {int} iDisplayIndexFull The index of the data in the full list of
  7748. * rows (after filtering)
  7749. * @dtopt Callbacks
  7750. *
  7751. * @example
  7752. * $(document).ready( function() {
  7753. * $('#example').dataTable( {
  7754. * "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
  7755. * // Bold the grade for all 'A' grade browsers
  7756. * if ( aData[4] == "A" )
  7757. * {
  7758. * $('td:eq(4)', nRow).html( '<b>A</b>' );
  7759. * }
  7760. * }
  7761. * } );
  7762. * } );
  7763. */
  7764. "fnRowCallback": null,
  7765. /**
  7766. * This parameter allows you to override the default function which obtains
  7767. * the data from the server ($.getJSON) so something more suitable for your
  7768. * application. For example you could use POST data, or pull information from
  7769. * a Gears or AIR database.
  7770. * @type function
  7771. * @member
  7772. * @param {string} sSource HTTP source to obtain the data from (sAjaxSource)
  7773. * @param {array} aoData A key/value pair object containing the data to send
  7774. * to the server
  7775. * @param {function} fnCallback to be called on completion of the data get
  7776. * process that will draw the data on the page.
  7777. * @param {object} oSettings DataTables settings object
  7778. * @dtopt Callbacks
  7779. * @dtopt Server-side
  7780. *
  7781. * @example
  7782. * // POST data to server
  7783. * $(document).ready( function() {
  7784. * $('#example').dataTable( {
  7785. * "bProcessing": true,
  7786. * "bServerSide": true,
  7787. * "sAjaxSource": "xhr.php",
  7788. * "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) {
  7789. * oSettings.jqXHR = $.ajax( {
  7790. * "dataType": 'json',
  7791. * "type": "POST",
  7792. * "url": sSource,
  7793. * "data": aoData,
  7794. * "success": fnCallback
  7795. * } );
  7796. * }
  7797. * } );
  7798. * } );
  7799. */
  7800. "fnServerData": function ( sUrl, aoData, fnCallback, oSettings ) {
  7801. oSettings.jqXHR = $.ajax( {
  7802. "url": sUrl,
  7803. "data": aoData,
  7804. "success": function (json) {
  7805. if ( json.sError ) {
  7806. oSettings.oApi._fnLog( oSettings, 0, json.sError );
  7807. }
  7808. $(oSettings.oInstance).trigger('xhr', [oSettings, json]);
  7809. fnCallback( json );
  7810. },
  7811. "dataType": "json",
  7812. "cache": false,
  7813. "type": oSettings.sServerMethod,
  7814. "error": function (xhr, error, thrown) {
  7815. if ( error == "parsererror" ) {
  7816. oSettings.oApi._fnLog( oSettings, 0, "DataTables warning: JSON data from "+
  7817. "server could not be parsed. This is caused by a JSON formatting error." );
  7818. }
  7819. }
  7820. } );
  7821. },
  7822. /**
  7823. * It is often useful to send extra data to the server when making an Ajax
  7824. * request - for example custom filtering information, and this callback
  7825. * function makes it trivial to send extra information to the server. The
  7826. * passed in parameter is the data set that has been constructed by
  7827. * DataTables, and you can add to this or modify it as you require.
  7828. * @type function
  7829. * @param {array} aoData Data array (array of objects which are name/value
  7830. * pairs) that has been constructed by DataTables and will be sent to the
  7831. * server. In the case of Ajax sourced data with server-side processing
  7832. * this will be an empty array, for server-side processing there will be a
  7833. * significant number of parameters!
  7834. * @returns {undefined} Ensure that you modify the aoData array passed in,
  7835. * as this is passed by reference.
  7836. * @dtopt Callbacks
  7837. * @dtopt Server-side
  7838. *
  7839. * @example
  7840. * $(document).ready( function() {
  7841. * $('#example').dataTable( {
  7842. * "bProcessing": true,
  7843. * "bServerSide": true,
  7844. * "sAjaxSource": "scripts/server_processing.php",
  7845. * "fnServerParams": function ( aoData ) {
  7846. * aoData.push( { "name": "more_data", "value": "my_value" } );
  7847. * }
  7848. * } );
  7849. * } );
  7850. */
  7851. "fnServerParams": null,
  7852. /**
  7853. * Load the table state. With this function you can define from where, and how, the
  7854. * state of a table is loaded. By default DataTables will load from its state saving
  7855. * cookie, but you might wish to use local storage (HTML5) or a server-side database.
  7856. * @type function
  7857. * @member
  7858. * @param {object} oSettings DataTables settings object
  7859. * @return {object} The DataTables state object to be loaded
  7860. * @dtopt Callbacks
  7861. *
  7862. * @example
  7863. * $(document).ready( function() {
  7864. * $('#example').dataTable( {
  7865. * "bStateSave": true,
  7866. * "fnStateLoad": function (oSettings) {
  7867. * var o;
  7868. *
  7869. * // Send an Ajax request to the server to get the data. Note that
  7870. * // this is a synchronous request.
  7871. * $.ajax( {
  7872. * "url": "/state_load",
  7873. * "async": false,
  7874. * "dataType": "json",
  7875. * "success": function (json) {
  7876. * o = json;
  7877. * }
  7878. * } );
  7879. *
  7880. * return o;
  7881. * }
  7882. * } );
  7883. * } );
  7884. */
  7885. "fnStateLoad": function ( oSettings ) {
  7886. var sData = this.oApi._fnReadCookie( oSettings.sCookiePrefix+oSettings.sInstance );
  7887. var oData;
  7888. try {
  7889. oData = (typeof $.parseJSON === 'function') ?
  7890. $.parseJSON(sData) : eval( '('+sData+')' );
  7891. } catch (e) {
  7892. oData = null;
  7893. }
  7894. return oData;
  7895. },
  7896. /**
  7897. * Callback which allows modification of the saved state prior to loading that state.
  7898. * This callback is called when the table is loading state from the stored data, but
  7899. * prior to the settings object being modified by the saved state. Note that for
  7900. * plug-in authors, you should use the 'stateLoadParams' event to load parameters for
  7901. * a plug-in.
  7902. * @type function
  7903. * @param {object} oSettings DataTables settings object
  7904. * @param {object} oData The state object that is to be loaded
  7905. * @dtopt Callbacks
  7906. *
  7907. * @example
  7908. * // Remove a saved filter, so filtering is never loaded
  7909. * $(document).ready( function() {
  7910. * $('#example').dataTable( {
  7911. * "bStateSave": true,
  7912. * "fnStateLoadParams": function (oSettings, oData) {
  7913. * oData.oSearch.sSearch = "";
  7914. * }
  7915. * } );
  7916. * } );
  7917. *
  7918. * @example
  7919. * // Disallow state loading by returning false
  7920. * $(document).ready( function() {
  7921. * $('#example').dataTable( {
  7922. * "bStateSave": true,
  7923. * "fnStateLoadParams": function (oSettings, oData) {
  7924. * return false;
  7925. * }
  7926. * } );
  7927. * } );
  7928. */
  7929. "fnStateLoadParams": null,
  7930. /**
  7931. * Callback that is called when the state has been loaded from the state saving method
  7932. * and the DataTables settings object has been modified as a result of the loaded state.
  7933. * @type function
  7934. * @param {object} oSettings DataTables settings object
  7935. * @param {object} oData The state object that was loaded
  7936. * @dtopt Callbacks
  7937. *
  7938. * @example
  7939. * // Show an alert with the filtering value that was saved
  7940. * $(document).ready( function() {
  7941. * $('#example').dataTable( {
  7942. * "bStateSave": true,
  7943. * "fnStateLoaded": function (oSettings, oData) {
  7944. * alert( 'Saved filter was: '+oData.oSearch.sSearch );
  7945. * }
  7946. * } );
  7947. * } );
  7948. */
  7949. "fnStateLoaded": null,
  7950. /**
  7951. * Save the table state. This function allows you to define where and how the state
  7952. * information for the table is stored - by default it will use a cookie, but you
  7953. * might want to use local storage (HTML5) or a server-side database.
  7954. * @type function
  7955. * @member
  7956. * @param {object} oSettings DataTables settings object
  7957. * @param {object} oData The state object to be saved
  7958. * @dtopt Callbacks
  7959. *
  7960. * @example
  7961. * $(document).ready( function() {
  7962. * $('#example').dataTable( {
  7963. * "bStateSave": true,
  7964. * "fnStateSave": function (oSettings, oData) {
  7965. * // Send an Ajax request to the server with the state object
  7966. * $.ajax( {
  7967. * "url": "/state_save",
  7968. * "data": oData,
  7969. * "dataType": "json",
  7970. * "method": "POST"
  7971. * "success": function () {}
  7972. * } );
  7973. * }
  7974. * } );
  7975. * } );
  7976. */
  7977. "fnStateSave": function ( oSettings, oData ) {
  7978. this.oApi._fnCreateCookie(
  7979. oSettings.sCookiePrefix+oSettings.sInstance,
  7980. this.oApi._fnJsonString(oData),
  7981. oSettings.iCookieDuration,
  7982. oSettings.sCookiePrefix,
  7983. oSettings.fnCookieCallback
  7984. );
  7985. },
  7986. /**
  7987. * Callback which allows modification of the state to be saved. Called when the table
  7988. * has changed state a new state save is required. This method allows modification of
  7989. * the state saving object prior to actually doing the save, including addition or
  7990. * other state properties or modification. Note that for plug-in authors, you should
  7991. * use the 'stateSaveParams' event to save parameters for a plug-in.
  7992. * @type function
  7993. * @param {object} oSettings DataTables settings object
  7994. * @param {object} oData The state object to be saved
  7995. * @dtopt Callbacks
  7996. *
  7997. * @example
  7998. * // Remove a saved filter, so filtering is never saved
  7999. * $(document).ready( function() {
  8000. * $('#example').dataTable( {
  8001. * "bStateSave": true,
  8002. * "fnStateSaveParams": function (oSettings, oData) {
  8003. * oData.oSearch.sSearch = "";
  8004. * }
  8005. * } );
  8006. * } );
  8007. */
  8008. "fnStateSaveParams": null,
  8009. /**
  8010. * Duration of the cookie which is used for storing session information. This
  8011. * value is given in seconds.
  8012. * @type int
  8013. * @default 7200 <i>(2 hours)</i>
  8014. * @dtopt Options
  8015. *
  8016. * @example
  8017. * $(document).ready( function() {
  8018. * $('#example').dataTable( {
  8019. * "iCookieDuration": 60*60*24; // 1 day
  8020. * } );
  8021. * } )
  8022. */
  8023. "iCookieDuration": 7200,
  8024. /**
  8025. * When enabled DataTables will not make a request to the server for the first
  8026. * page draw - rather it will use the data already on the page (no sorting etc
  8027. * will be applied to it), thus saving on an XHR at load time. iDeferLoading
  8028. * is used to indicate that deferred loading is required, but it is also used
  8029. * to tell DataTables how many records there are in the full table (allowing
  8030. * the information element and pagination to be displayed correctly). In the case
  8031. * where a filtering is applied to the table on initial load, this can be
  8032. * indicated by giving the parameter as an array, where the first element is
  8033. * the number of records available after filtering and the second element is the
  8034. * number of records without filtering (allowing the table information element
  8035. * to be shown correctly).
  8036. * @type int | array
  8037. * @default null
  8038. * @dtopt Options
  8039. *
  8040. * @example
  8041. * // 57 records available in the table, no filtering applied
  8042. * $(document).ready( function() {
  8043. * $('#example').dataTable( {
  8044. * "bServerSide": true,
  8045. * "sAjaxSource": "scripts/server_processing.php",
  8046. * "iDeferLoading": 57
  8047. * } );
  8048. * } );
  8049. *
  8050. * @example
  8051. * // 57 records after filtering, 100 without filtering (an initial filter applied)
  8052. * $(document).ready( function() {
  8053. * $('#example').dataTable( {
  8054. * "bServerSide": true,
  8055. * "sAjaxSource": "scripts/server_processing.php",
  8056. * "iDeferLoading": [ 57, 100 ],
  8057. * "oSearch": {
  8058. * "sSearch": "my_filter"
  8059. * }
  8060. * } );
  8061. * } );
  8062. */
  8063. "iDeferLoading": null,
  8064. /**
  8065. * Number of rows to display on a single page when using pagination. If
  8066. * feature enabled (bLengthChange) then the end user will be able to override
  8067. * this to a custom setting using a pop-up menu.
  8068. * @type int
  8069. * @default 10
  8070. * @dtopt Options
  8071. *
  8072. * @example
  8073. * $(document).ready( function() {
  8074. * $('#example').dataTable( {
  8075. * "iDisplayLength": 50
  8076. * } );
  8077. * } )
  8078. */
  8079. "iDisplayLength": 10,
  8080. /**
  8081. * Define the starting point for data display when using DataTables with
  8082. * pagination. Note that this parameter is the number of records, rather than
  8083. * the page number, so if you have 10 records per page and want to start on
  8084. * the third page, it should be "20".
  8085. * @type int
  8086. * @default 0
  8087. * @dtopt Options
  8088. *
  8089. * @example
  8090. * $(document).ready( function() {
  8091. * $('#example').dataTable( {
  8092. * "iDisplayStart": 20
  8093. * } );
  8094. * } )
  8095. */
  8096. "iDisplayStart": 0,
  8097. /**
  8098. * The scroll gap is the amount of scrolling that is left to go before
  8099. * DataTables will load the next 'page' of data automatically. You typically
  8100. * want a gap which is big enough that the scrolling will be smooth for the
  8101. * user, while not so large that it will load more data than need.
  8102. * @type int
  8103. * @default 100
  8104. * @dtopt Options
  8105. *
  8106. * @example
  8107. * $(document).ready( function() {
  8108. * $('#example').dataTable( {
  8109. * "bScrollInfinite": true,
  8110. * "bScrollCollapse": true,
  8111. * "sScrollY": "200px",
  8112. * "iScrollLoadGap": 50
  8113. * } );
  8114. * } );
  8115. */
  8116. "iScrollLoadGap": 100,
  8117. /**
  8118. * By default DataTables allows keyboard navigation of the table (sorting, paging,
  8119. * and filtering) by adding a tabindex attribute to the required elements. This
  8120. * allows you to tab through the controls and press the enter key to activate them.
  8121. * The tabindex is default 0, meaning that the tab follows the flow of the document.
  8122. * You can overrule this using this parameter if you wish. Use a value of -1 to
  8123. * disable built-in keyboard navigation.
  8124. * @type int
  8125. * @default 0
  8126. * @dtopt Options
  8127. *
  8128. * @example
  8129. * $(document).ready( function() {
  8130. * $('#example').dataTable( {
  8131. * "iTabIndex": 1
  8132. * } );
  8133. * } );
  8134. */
  8135. "iTabIndex": 0,
  8136. /**
  8137. * All strings that DataTables uses in the user interface that it creates
  8138. * are defined in this object, allowing you to modified them individually or
  8139. * completely replace them all as required.
  8140. * @namespace
  8141. */
  8142. "oLanguage": {
  8143. /**
  8144. * Strings that are used for WAI-ARIA labels and controls only (these are not
  8145. * actually visible on the page, but will be read by screenreaders, and thus
  8146. * must be internationalised as well).
  8147. * @namespace
  8148. */
  8149. "oAria": {
  8150. /**
  8151. * ARIA label that is added to the table headers when the column may be
  8152. * sorted ascending by activing the column (click or return when focused).
  8153. * Note that the column header is prefixed to this string.
  8154. * @type string
  8155. * @default : activate to sort column ascending
  8156. * @dtopt Language
  8157. *
  8158. * @example
  8159. * $(document).ready( function() {
  8160. * $('#example').dataTable( {
  8161. * "oLanguage": {
  8162. * "oAria": {
  8163. * "sSortAscending": " - click/return to sort ascending"
  8164. * }
  8165. * }
  8166. * } );
  8167. * } );
  8168. */
  8169. "sSortAscending": ": activate to sort column ascending",
  8170. /**
  8171. * ARIA label that is added to the table headers when the column may be
  8172. * sorted descending by activing the column (click or return when focused).
  8173. * Note that the column header is prefixed to this string.
  8174. * @type string
  8175. * @default : activate to sort column ascending
  8176. * @dtopt Language
  8177. *
  8178. * @example
  8179. * $(document).ready( function() {
  8180. * $('#example').dataTable( {
  8181. * "oLanguage": {
  8182. * "oAria": {
  8183. * "sSortDescending": " - click/return to sort descending"
  8184. * }
  8185. * }
  8186. * } );
  8187. * } );
  8188. */
  8189. "sSortDescending": ": activate to sort column descending"
  8190. },
  8191. /**
  8192. * Pagination string used by DataTables for the two built-in pagination
  8193. * control types ("two_button" and "full_numbers")
  8194. * @namespace
  8195. */
  8196. "oPaginate": {
  8197. /**
  8198. * Text to use when using the 'full_numbers' type of pagination for the
  8199. * button to take the user to the first page.
  8200. * @type string
  8201. * @default First
  8202. * @dtopt Language
  8203. *
  8204. * @example
  8205. * $(document).ready( function() {
  8206. * $('#example').dataTable( {
  8207. * "oLanguage": {
  8208. * "oPaginate": {
  8209. * "sFirst": "First page"
  8210. * }
  8211. * }
  8212. * } );
  8213. * } );
  8214. */
  8215. "sFirst": "First",
  8216. /**
  8217. * Text to use when using the 'full_numbers' type of pagination for the
  8218. * button to take the user to the last page.
  8219. * @type string
  8220. * @default Last
  8221. * @dtopt Language
  8222. *
  8223. * @example
  8224. * $(document).ready( function() {
  8225. * $('#example').dataTable( {
  8226. * "oLanguage": {
  8227. * "oPaginate": {
  8228. * "sLast": "Last page"
  8229. * }
  8230. * }
  8231. * } );
  8232. * } );
  8233. */
  8234. "sLast": "Last",
  8235. /**
  8236. * Text to use for the 'next' pagination button (to take the user to the
  8237. * next page).
  8238. * @type string
  8239. * @default Next
  8240. * @dtopt Language
  8241. *
  8242. * @example
  8243. * $(document).ready( function() {
  8244. * $('#example').dataTable( {
  8245. * "oLanguage": {
  8246. * "oPaginate": {
  8247. * "sNext": "Next page"
  8248. * }
  8249. * }
  8250. * } );
  8251. * } );
  8252. */
  8253. "sNext": "Next",
  8254. /**
  8255. * Text to use for the 'previous' pagination button (to take the user to
  8256. * the previous page).
  8257. * @type string
  8258. * @default Previous
  8259. * @dtopt Language
  8260. *
  8261. * @example
  8262. * $(document).ready( function() {
  8263. * $('#example').dataTable( {
  8264. * "oLanguage": {
  8265. * "oPaginate": {
  8266. * "sPrevious": "Previous page"
  8267. * }
  8268. * }
  8269. * } );
  8270. * } );
  8271. */
  8272. "sPrevious": "Previous"
  8273. },
  8274. /**
  8275. * This string is shown in preference to sZeroRecords when the table is
  8276. * empty of data (regardless of filtering). Note that this is an optional
  8277. * parameter - if it is not given, the value of sZeroRecords will be used
  8278. * instead (either the default or given value).
  8279. * @type string
  8280. * @default No data available in table
  8281. * @dtopt Language
  8282. *
  8283. * @example
  8284. * $(document).ready( function() {
  8285. * $('#example').dataTable( {
  8286. * "oLanguage": {
  8287. * "sEmptyTable": "No data available in table"
  8288. * }
  8289. * } );
  8290. * } );
  8291. */
  8292. "sEmptyTable": "No data available in table",
  8293. /**
  8294. * This string gives information to the end user about the information that
  8295. * is current on display on the page. The _START_, _END_ and _TOTAL_
  8296. * variables are all dynamically replaced as the table display updates, and
  8297. * can be freely moved or removed as the language requirements change.
  8298. * @type string
  8299. * @default Showing _START_ to _END_ of _TOTAL_ entries
  8300. * @dtopt Language
  8301. *
  8302. * @example
  8303. * $(document).ready( function() {
  8304. * $('#example').dataTable( {
  8305. * "oLanguage": {
  8306. * "sInfo": "Got a total of _TOTAL_ entries to show (_START_ to _END_)"
  8307. * }
  8308. * } );
  8309. * } );
  8310. */
  8311. "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
  8312. /**
  8313. * Display information string for when the table is empty. Typically the
  8314. * format of this string should match sInfo.
  8315. * @type string
  8316. * @default Showing 0 to 0 of 0 entries
  8317. * @dtopt Language
  8318. *
  8319. * @example
  8320. * $(document).ready( function() {
  8321. * $('#example').dataTable( {
  8322. * "oLanguage": {
  8323. * "sInfoEmpty": "No entries to show"
  8324. * }
  8325. * } );
  8326. * } );
  8327. */
  8328. "sInfoEmpty": "Showing 0 to 0 of 0 entries",
  8329. /**
  8330. * When a user filters the information in a table, this string is appended
  8331. * to the information (sInfo) to give an idea of how strong the filtering
  8332. * is. The variable _MAX_ is dynamically updated.
  8333. * @type string
  8334. * @default (filtered from _MAX_ total entries)
  8335. * @dtopt Language
  8336. *
  8337. * @example
  8338. * $(document).ready( function() {
  8339. * $('#example').dataTable( {
  8340. * "oLanguage": {
  8341. * "sInfoFiltered": " - filtering from _MAX_ records"
  8342. * }
  8343. * } );
  8344. * } );
  8345. */
  8346. "sInfoFiltered": "(filtered from _MAX_ total entries)",
  8347. /**
  8348. * If can be useful to append extra information to the info string at times,
  8349. * and this variable does exactly that. This information will be appended to
  8350. * the sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are
  8351. * being used) at all times.
  8352. * @type string
  8353. * @default <i>Empty string</i>
  8354. * @dtopt Language
  8355. *
  8356. * @example
  8357. * $(document).ready( function() {
  8358. * $('#example').dataTable( {
  8359. * "oLanguage": {
  8360. * "sInfoPostFix": "All records shown are derived from real information."
  8361. * }
  8362. * } );
  8363. * } );
  8364. */
  8365. "sInfoPostFix": "",
  8366. /**
  8367. * DataTables has a build in number formatter (fnFormatNumber) which is used
  8368. * to format large numbers that are used in the table information. By
  8369. * default a comma is used, but this can be trivially changed to any
  8370. * character you wish with this parameter.
  8371. * @type string
  8372. * @default ,
  8373. * @dtopt Language
  8374. *
  8375. * @example
  8376. * $(document).ready( function() {
  8377. * $('#example').dataTable( {
  8378. * "oLanguage": {
  8379. * "sInfoThousands": "'"
  8380. * }
  8381. * } );
  8382. * } );
  8383. */
  8384. "sInfoThousands": ",",
  8385. /**
  8386. * Detail the action that will be taken when the drop down menu for the
  8387. * pagination length option is changed. The '_MENU_' variable is replaced
  8388. * with a default select list of 10, 25, 50 and 100, and can be replaced
  8389. * with a custom select box if required.
  8390. * @type string
  8391. * @default Show _MENU_ entries
  8392. * @dtopt Language
  8393. *
  8394. * @example
  8395. * // Language change only
  8396. * $(document).ready( function() {
  8397. * $('#example').dataTable( {
  8398. * "oLanguage": {
  8399. * "sLengthMenu": "Display _MENU_ records"
  8400. * }
  8401. * } );
  8402. * } );
  8403. *
  8404. * @example
  8405. * // Language and options change
  8406. * $(document).ready( function() {
  8407. * $('#example').dataTable( {
  8408. * "oLanguage": {
  8409. * "sLengthMenu": 'Display <select>'+
  8410. * '<option value="10">10</option>'+
  8411. * '<option value="20">20</option>'+
  8412. * '<option value="30">30</option>'+
  8413. * '<option value="40">40</option>'+
  8414. * '<option value="50">50</option>'+
  8415. * '<option value="-1">All</option>'+
  8416. * '</select> records'
  8417. * }
  8418. * } );
  8419. * } );
  8420. */
  8421. "sLengthMenu": "Show _MENU_ entries",
  8422. /**
  8423. * When using Ajax sourced data and during the first draw when DataTables is
  8424. * gathering the data, this message is shown in an empty row in the table to
  8425. * indicate to the end user the the data is being loaded. Note that this
  8426. * parameter is not used when loading data by server-side processing, just
  8427. * Ajax sourced data with client-side processing.
  8428. * @type string
  8429. * @default Loading...
  8430. * @dtopt Language
  8431. *
  8432. * @example
  8433. * $(document).ready( function() {
  8434. * $('#example').dataTable( {
  8435. * "oLanguage": {
  8436. * "sLoadingRecords": "Please wait - loading..."
  8437. * }
  8438. * } );
  8439. * } );
  8440. */
  8441. "sLoadingRecords": "Loading...",
  8442. /**
  8443. * Text which is displayed when the table is processing a user action
  8444. * (usually a sort command or similar).
  8445. * @type string
  8446. * @default Processing...
  8447. * @dtopt Language
  8448. *
  8449. * @example
  8450. * $(document).ready( function() {
  8451. * $('#example').dataTable( {
  8452. * "oLanguage": {
  8453. * "sProcessing": "DataTables is currently busy"
  8454. * }
  8455. * } );
  8456. * } );
  8457. */
  8458. "sProcessing": "Processing...",
  8459. /**
  8460. * Details the actions that will be taken when the user types into the
  8461. * filtering input text box. The variable "_INPUT_", if used in the string,
  8462. * is replaced with the HTML text box for the filtering input allowing
  8463. * control over where it appears in the string. If "_INPUT_" is not given
  8464. * then the input box is appended to the string automatically.
  8465. * @type string
  8466. * @default Search:
  8467. * @dtopt Language
  8468. *
  8469. * @example
  8470. * // Input text box will be appended at the end automatically
  8471. * $(document).ready( function() {
  8472. * $('#example').dataTable( {
  8473. * "oLanguage": {
  8474. * "sSearch": "Filter records:"
  8475. * }
  8476. * } );
  8477. * } );
  8478. *
  8479. * @example
  8480. * // Specify where the filter should appear
  8481. * $(document).ready( function() {
  8482. * $('#example').dataTable( {
  8483. * "oLanguage": {
  8484. * "sSearch": "Apply filter _INPUT_ to table"
  8485. * }
  8486. * } );
  8487. * } );
  8488. */
  8489. "sSearch": "Search:",
  8490. /**
  8491. * All of the language information can be stored in a file on the
  8492. * server-side, which DataTables will look up if this parameter is passed.
  8493. * It must store the URL of the language file, which is in a JSON format,
  8494. * and the object has the same properties as the oLanguage object in the
  8495. * initialiser object (i.e. the above parameters). Please refer to one of
  8496. * the example language files to see how this works in action.
  8497. * @type string
  8498. * @default <i>Empty string - i.e. disabled</i>
  8499. * @dtopt Language
  8500. *
  8501. * @example
  8502. * $(document).ready( function() {
  8503. * $('#example').dataTable( {
  8504. * "oLanguage": {
  8505. * "sUrl": "http://www.sprymedia.co.uk/dataTables/lang.txt"
  8506. * }
  8507. * } );
  8508. * } );
  8509. */
  8510. "sUrl": "",
  8511. /**
  8512. * Text shown inside the table records when the is no information to be
  8513. * displayed after filtering. sEmptyTable is shown when there is simply no
  8514. * information in the table at all (regardless of filtering).
  8515. * @type string
  8516. * @default No matching records found
  8517. * @dtopt Language
  8518. *
  8519. * @example
  8520. * $(document).ready( function() {
  8521. * $('#example').dataTable( {
  8522. * "oLanguage": {
  8523. * "sZeroRecords": "No records to display"
  8524. * }
  8525. * } );
  8526. * } );
  8527. */
  8528. "sZeroRecords": "No matching records found"
  8529. },
  8530. /**
  8531. * This parameter allows you to have define the global filtering state at
  8532. * initialisation time. As an object the "sSearch" parameter must be
  8533. * defined, but all other parameters are optional. When "bRegex" is true,
  8534. * the search string will be treated as a regular expression, when false
  8535. * (default) it will be treated as a straight string. When "bSmart"
  8536. * DataTables will use it's smart filtering methods (to word match at
  8537. * any point in the data), when false this will not be done.
  8538. * @namespace
  8539. * @extends DataTable.models.oSearch
  8540. * @dtopt Options
  8541. *
  8542. * @example
  8543. * $(document).ready( function() {
  8544. * $('#example').dataTable( {
  8545. * "oSearch": {"sSearch": "Initial search"}
  8546. * } );
  8547. * } )
  8548. */
  8549. "oSearch": $.extend( {}, DataTable.models.oSearch ),
  8550. /**
  8551. * By default DataTables will look for the property 'aaData' when obtaining
  8552. * data from an Ajax source or for server-side processing - this parameter
  8553. * allows that property to be changed. You can use Javascript dotted object
  8554. * notation to get a data source for multiple levels of nesting.
  8555. * @type string
  8556. * @default aaData
  8557. * @dtopt Options
  8558. * @dtopt Server-side
  8559. *
  8560. * @example
  8561. * // Get data from { "data": [...] }
  8562. * $(document).ready( function() {
  8563. * var oTable = $('#example').dataTable( {
  8564. * "sAjaxSource": "sources/data.txt",
  8565. * "sAjaxDataProp": "data"
  8566. * } );
  8567. * } );
  8568. *
  8569. * @example
  8570. * // Get data from { "data": { "inner": [...] } }
  8571. * $(document).ready( function() {
  8572. * var oTable = $('#example').dataTable( {
  8573. * "sAjaxSource": "sources/data.txt",
  8574. * "sAjaxDataProp": "data.inner"
  8575. * } );
  8576. * } );
  8577. */
  8578. "sAjaxDataProp": "aaData",
  8579. /**
  8580. * You can instruct DataTables to load data from an external source using this
  8581. * parameter (use aData if you want to pass data in you already have). Simply
  8582. * provide a url a JSON object can be obtained from. This object must include
  8583. * the parameter 'aaData' which is the data source for the table.
  8584. * @type string
  8585. * @default null
  8586. * @dtopt Options
  8587. * @dtopt Server-side
  8588. *
  8589. * @example
  8590. * $(document).ready( function() {
  8591. * $('#example').dataTable( {
  8592. * "sAjaxSource": "http://www.sprymedia.co.uk/dataTables/json.php"
  8593. * } );
  8594. * } )
  8595. */
  8596. "sAjaxSource": null,
  8597. /**
  8598. * This parameter can be used to override the default prefix that DataTables
  8599. * assigns to a cookie when state saving is enabled.
  8600. * @type string
  8601. * @default SpryMedia_DataTables_
  8602. * @dtopt Options
  8603. *
  8604. * @example
  8605. * $(document).ready( function() {
  8606. * $('#example').dataTable( {
  8607. * "sCookiePrefix": "my_datatable_",
  8608. * } );
  8609. * } );
  8610. */
  8611. "sCookiePrefix": "SpryMedia_DataTables_",
  8612. /**
  8613. * This initialisation variable allows you to specify exactly where in the
  8614. * DOM you want DataTables to inject the various controls it adds to the page
  8615. * (for example you might want the pagination controls at the top of the
  8616. * table). DIV elements (with or without a custom class) can also be added to
  8617. * aid styling. The follow syntax is used:
  8618. * <ul>
  8619. * <li>The following options are allowed:
  8620. * <ul>
  8621. * <li>'l' - Length changing</li
  8622. * <li>'f' - Filtering input</li>
  8623. * <li>'t' - The table!</li>
  8624. * <li>'i' - Information</li>
  8625. * <li>'p' - Pagination</li>
  8626. * <li>'r' - pRocessing</li>
  8627. * </ul>
  8628. * </li>
  8629. * <li>The following constants are allowed:
  8630. * <ul>
  8631. * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
  8632. * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
  8633. * </ul>
  8634. * </li>
  8635. * <li>The following syntax is expected:
  8636. * <ul>
  8637. * <li>'&lt;' and '&gt;' - div elements</li>
  8638. * <li>'&lt;"class" and '&gt;' - div with a class</li>
  8639. * <li>'&lt;"#id" and '&gt;' - div with an ID</li>
  8640. * </ul>
  8641. * </li>
  8642. * <li>Examples:
  8643. * <ul>
  8644. * <li>'&lt;"wrapper"flipt&gt;'</li>
  8645. * <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
  8646. * </ul>
  8647. * </li>
  8648. * </ul>
  8649. * @type string
  8650. * @default lfrtip <i>(when bJQueryUI is false)</i> <b>or</b>
  8651. * <"H"lfr>t<"F"ip> <i>(when bJQueryUI is true)</i>
  8652. * @dtopt Options
  8653. *
  8654. * @example
  8655. * $(document).ready( function() {
  8656. * $('#example').dataTable( {
  8657. * "sDom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
  8658. * } );
  8659. * } );
  8660. */
  8661. "sDom": "lfrtip",
  8662. /**
  8663. * DataTables features two different built-in pagination interaction methods
  8664. * ('two_button' or 'full_numbers') which present different page controls to
  8665. * the end user. Further methods can be added using the API (see below).
  8666. * @type string
  8667. * @default two_button
  8668. * @dtopt Options
  8669. *
  8670. * @example
  8671. * $(document).ready( function() {
  8672. * $('#example').dataTable( {
  8673. * "sPaginationType": "full_numbers"
  8674. * } );
  8675. * } )
  8676. */
  8677. "sPaginationType": "two_button",
  8678. /**
  8679. * Enable horizontal scrolling. When a table is too wide to fit into a certain
  8680. * layout, or you have a large number of columns in the table, you can enable
  8681. * x-scrolling to show the table in a viewport, which can be scrolled. This
  8682. * property can be any CSS unit, or a number (in which case it will be treated
  8683. * as a pixel measurement).
  8684. * @type string
  8685. * @default <i>blank string - i.e. disabled</i>
  8686. * @dtopt Features
  8687. *
  8688. * @example
  8689. * $(document).ready( function() {
  8690. * $('#example').dataTable( {
  8691. * "sScrollX": "100%",
  8692. * "bScrollCollapse": true
  8693. * } );
  8694. * } );
  8695. */
  8696. "sScrollX": "",
  8697. /**
  8698. * This property can be used to force a DataTable to use more width than it
  8699. * might otherwise do when x-scrolling is enabled. For example if you have a
  8700. * table which requires to be well spaced, this parameter is useful for
  8701. * "over-sizing" the table, and thus forcing scrolling. This property can by
  8702. * any CSS unit, or a number (in which case it will be treated as a pixel
  8703. * measurement).
  8704. * @type string
  8705. * @default <i>blank string - i.e. disabled</i>
  8706. * @dtopt Options
  8707. *
  8708. * @example
  8709. * $(document).ready( function() {
  8710. * $('#example').dataTable( {
  8711. * "sScrollX": "100%",
  8712. * "sScrollXInner": "110%"
  8713. * } );
  8714. * } );
  8715. */
  8716. "sScrollXInner": "",
  8717. /**
  8718. * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
  8719. * to the given height, and enable scrolling for any data which overflows the
  8720. * current viewport. This can be used as an alternative to paging to display
  8721. * a lot of data in a small area (although paging and scrolling can both be
  8722. * enabled at the same time). This property can be any CSS unit, or a number
  8723. * (in which case it will be treated as a pixel measurement).
  8724. * @type string
  8725. * @default <i>blank string - i.e. disabled</i>
  8726. * @dtopt Features
  8727. *
  8728. * @example
  8729. * $(document).ready( function() {
  8730. * $('#example').dataTable( {
  8731. * "sScrollY": "200px",
  8732. * "bPaginate": false
  8733. * } );
  8734. * } );
  8735. */
  8736. "sScrollY": "",
  8737. /**
  8738. * Set the HTTP method that is used to make the Ajax call for server-side
  8739. * processing or Ajax sourced data.
  8740. * @type string
  8741. * @default GET
  8742. * @dtopt Options
  8743. * @dtopt Server-side
  8744. *
  8745. * @example
  8746. * $(document).ready( function() {
  8747. * $('#example').dataTable( {
  8748. * "bServerSide": true,
  8749. * "sAjaxSource": "scripts/post.php",
  8750. * "sServerMethod": "POST"
  8751. * } );
  8752. * } );
  8753. */
  8754. "sServerMethod": "GET"
  8755. };
  8756. /**
  8757. * Column options that can be given to DataTables at initialisation time.
  8758. * @namespace
  8759. */
  8760. DataTable.defaults.columns = {
  8761. /**
  8762. * Allows a column's sorting to take multiple columns into account when
  8763. * doing a sort. For example first name / last name columns make sense to
  8764. * do a multi-column sort over the two columns.
  8765. * @type array
  8766. * @default null <i>Takes the value of the column index automatically</i>
  8767. * @dtopt Columns
  8768. *
  8769. * @example
  8770. * // Using aoColumnDefs
  8771. * $(document).ready( function() {
  8772. * $('#example').dataTable( {
  8773. * "aoColumnDefs": [
  8774. * { "aDataSort": [ 0, 1 ], "aTargets": [ 0 ] },
  8775. * { "aDataSort": [ 1, 0 ], "aTargets": [ 1 ] },
  8776. * { "aDataSort": [ 2, 3, 4 ], "aTargets": [ 2 ] }
  8777. * ]
  8778. * } );
  8779. * } );
  8780. *
  8781. * @example
  8782. * // Using aoColumns
  8783. * $(document).ready( function() {
  8784. * $('#example').dataTable( {
  8785. * "aoColumns": [
  8786. * { "aDataSort": [ 0, 1 ] },
  8787. * { "aDataSort": [ 1, 0 ] },
  8788. * { "aDataSort": [ 2, 3, 4 ] },
  8789. * null,
  8790. * null
  8791. * ]
  8792. * } );
  8793. * } );
  8794. */
  8795. "aDataSort": null,
  8796. /**
  8797. * You can control the default sorting direction, and even alter the behaviour
  8798. * of the sort handler (i.e. only allow ascending sorting etc) using this
  8799. * parameter.
  8800. * @type array
  8801. * @default [ 'asc', 'desc' ]
  8802. * @dtopt Columns
  8803. *
  8804. * @example
  8805. * // Using aoColumnDefs
  8806. * $(document).ready( function() {
  8807. * $('#example').dataTable( {
  8808. * "aoColumnDefs": [
  8809. * { "asSorting": [ "asc" ], "aTargets": [ 1 ] },
  8810. * { "asSorting": [ "desc", "asc", "asc" ], "aTargets": [ 2 ] },
  8811. * { "asSorting": [ "desc" ], "aTargets": [ 3 ] }
  8812. * ]
  8813. * } );
  8814. * } );
  8815. *
  8816. * @example
  8817. * // Using aoColumns
  8818. * $(document).ready( function() {
  8819. * $('#example').dataTable( {
  8820. * "aoColumns": [
  8821. * null,
  8822. * { "asSorting": [ "asc" ] },
  8823. * { "asSorting": [ "desc", "asc", "asc" ] },
  8824. * { "asSorting": [ "desc" ] },
  8825. * null
  8826. * ]
  8827. * } );
  8828. * } );
  8829. */
  8830. "asSorting": [ 'asc', 'desc' ],
  8831. /**
  8832. * Enable or disable filtering on the data in this column.
  8833. * @type boolean
  8834. * @default true
  8835. * @dtopt Columns
  8836. *
  8837. * @example
  8838. * // Using aoColumnDefs
  8839. * $(document).ready( function() {
  8840. * $('#example').dataTable( {
  8841. * "aoColumnDefs": [
  8842. * { "bSearchable": false, "aTargets": [ 0 ] }
  8843. * ] } );
  8844. * } );
  8845. *
  8846. * @example
  8847. * // Using aoColumns
  8848. * $(document).ready( function() {
  8849. * $('#example').dataTable( {
  8850. * "aoColumns": [
  8851. * { "bSearchable": false },
  8852. * null,
  8853. * null,
  8854. * null,
  8855. * null
  8856. * ] } );
  8857. * } );
  8858. */
  8859. "bSearchable": true,
  8860. /**
  8861. * Enable or disable sorting on this column.
  8862. * @type boolean
  8863. * @default true
  8864. * @dtopt Columns
  8865. *
  8866. * @example
  8867. * // Using aoColumnDefs
  8868. * $(document).ready( function() {
  8869. * $('#example').dataTable( {
  8870. * "aoColumnDefs": [
  8871. * { "bSortable": false, "aTargets": [ 0 ] }
  8872. * ] } );
  8873. * } );
  8874. *
  8875. * @example
  8876. * // Using aoColumns
  8877. * $(document).ready( function() {
  8878. * $('#example').dataTable( {
  8879. * "aoColumns": [
  8880. * { "bSortable": false },
  8881. * null,
  8882. * null,
  8883. * null,
  8884. * null
  8885. * ] } );
  8886. * } );
  8887. */
  8888. "bSortable": true,
  8889. /**
  8890. * <code>Deprecated</code> When using fnRender() for a column, you may wish
  8891. * to use the original data (before rendering) for sorting and filtering
  8892. * (the default is to used the rendered data that the user can see). This
  8893. * may be useful for dates etc.
  8894. *
  8895. * Please note that this option has now been deprecated and will be removed
  8896. * in the next version of DataTables. Please use mRender / mData rather than
  8897. * fnRender.
  8898. * @type boolean
  8899. * @default true
  8900. * @dtopt Columns
  8901. * @deprecated
  8902. */
  8903. "bUseRendered": true,
  8904. /**
  8905. * Enable or disable the display of this column.
  8906. * @type boolean
  8907. * @default true
  8908. * @dtopt Columns
  8909. *
  8910. * @example
  8911. * // Using aoColumnDefs
  8912. * $(document).ready( function() {
  8913. * $('#example').dataTable( {
  8914. * "aoColumnDefs": [
  8915. * { "bVisible": false, "aTargets": [ 0 ] }
  8916. * ] } );
  8917. * } );
  8918. *
  8919. * @example
  8920. * // Using aoColumns
  8921. * $(document).ready( function() {
  8922. * $('#example').dataTable( {
  8923. * "aoColumns": [
  8924. * { "bVisible": false },
  8925. * null,
  8926. * null,
  8927. * null,
  8928. * null
  8929. * ] } );
  8930. * } );
  8931. */
  8932. "bVisible": true,
  8933. /**
  8934. * Developer definable function that is called whenever a cell is created (Ajax source,
  8935. * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  8936. * allowing you to modify the DOM element (add background colour for example) when the
  8937. * element is available.
  8938. * @type function
  8939. * @param {element} nTd The TD node that has been created
  8940. * @param {*} sData The Data for the cell
  8941. * @param {array|object} oData The data for the whole row
  8942. * @param {int} iRow The row index for the aoData data store
  8943. * @param {int} iCol The column index for aoColumns
  8944. * @dtopt Columns
  8945. *
  8946. * @example
  8947. * $(document).ready( function() {
  8948. * $('#example').dataTable( {
  8949. * "aoColumnDefs": [ {
  8950. * "aTargets": [3],
  8951. * "fnCreatedCell": function (nTd, sData, oData, iRow, iCol) {
  8952. * if ( sData == "1.7" ) {
  8953. * $(nTd).css('color', 'blue')
  8954. * }
  8955. * }
  8956. * } ]
  8957. * });
  8958. * } );
  8959. */
  8960. "fnCreatedCell": null,
  8961. /**
  8962. * <code>Deprecated</code> Custom display function that will be called for the
  8963. * display of each cell in this column.
  8964. *
  8965. * Please note that this option has now been deprecated and will be removed
  8966. * in the next version of DataTables. Please use mRender / mData rather than
  8967. * fnRender.
  8968. * @type function
  8969. * @param {object} o Object with the following parameters:
  8970. * @param {int} o.iDataRow The row in aoData
  8971. * @param {int} o.iDataColumn The column in question
  8972. * @param {array} o.aData The data for the row in question
  8973. * @param {object} o.oSettings The settings object for this DataTables instance
  8974. * @param {object} o.mDataProp The data property used for this column
  8975. * @param {*} val The current cell value
  8976. * @returns {string} The string you which to use in the display
  8977. * @dtopt Columns
  8978. * @deprecated
  8979. */
  8980. "fnRender": null,
  8981. /**
  8982. * The column index (starting from 0!) that you wish a sort to be performed
  8983. * upon when this column is selected for sorting. This can be used for sorting
  8984. * on hidden columns for example.
  8985. * @type int
  8986. * @default -1 <i>Use automatically calculated column index</i>
  8987. * @dtopt Columns
  8988. *
  8989. * @example
  8990. * // Using aoColumnDefs
  8991. * $(document).ready( function() {
  8992. * $('#example').dataTable( {
  8993. * "aoColumnDefs": [
  8994. * { "iDataSort": 1, "aTargets": [ 0 ] }
  8995. * ]
  8996. * } );
  8997. * } );
  8998. *
  8999. * @example
  9000. * // Using aoColumns
  9001. * $(document).ready( function() {
  9002. * $('#example').dataTable( {
  9003. * "aoColumns": [
  9004. * { "iDataSort": 1 },
  9005. * null,
  9006. * null,
  9007. * null,
  9008. * null
  9009. * ]
  9010. * } );
  9011. * } );
  9012. */
  9013. "iDataSort": -1,
  9014. /**
  9015. * This parameter has been replaced by mData in DataTables to ensure naming
  9016. * consistency. mDataProp can still be used, as there is backwards compatibility
  9017. * in DataTables for this option, but it is strongly recommended that you use
  9018. * mData in preference to mDataProp.
  9019. * @name DataTable.defaults.columns.mDataProp
  9020. */
  9021. /**
  9022. * This property can be used to read data from any JSON data source property,
  9023. * including deeply nested objects / properties. mData can be given in a
  9024. * number of different ways which effect its behaviour:
  9025. * <ul>
  9026. * <li>integer - treated as an array index for the data source. This is the
  9027. * default that DataTables uses (incrementally increased for each column).</li>
  9028. * <li>string - read an object property from the data source. Note that you can
  9029. * use Javascript dotted notation to read deep properties / arrays from the
  9030. * data source.</li>
  9031. * <li>null - the sDefaultContent option will be used for the cell (null
  9032. * by default, so you will need to specify the default content you want -
  9033. * typically an empty string). This can be useful on generated columns such
  9034. * as edit / delete action columns.</li>
  9035. * <li>function - the function given will be executed whenever DataTables
  9036. * needs to set or get the data for a cell in the column. The function
  9037. * takes three parameters:
  9038. * <ul>
  9039. * <li>{array|object} The data source for the row</li>
  9040. * <li>{string} The type call data requested - this will be 'set' when
  9041. * setting data or 'filter', 'display', 'type', 'sort' or undefined when
  9042. * gathering data. Note that when <i>undefined</i> is given for the type
  9043. * DataTables expects to get the raw data for the object back</li>
  9044. * <li>{*} Data to set when the second parameter is 'set'.</li>
  9045. * </ul>
  9046. * The return value from the function is not required when 'set' is the type
  9047. * of call, but otherwise the return is what will be used for the data
  9048. * requested.</li>
  9049. * </ul>
  9050. *
  9051. * Note that prior to DataTables 1.9.2 mData was called mDataProp. The name change
  9052. * reflects the flexibility of this property and is consistent with the naming of
  9053. * mRender. If 'mDataProp' is given, then it will still be used by DataTables, as
  9054. * it automatically maps the old name to the new if required.
  9055. * @type string|int|function|null
  9056. * @default null <i>Use automatically calculated column index</i>
  9057. * @dtopt Columns
  9058. *
  9059. * @example
  9060. * // Read table data from objects
  9061. * $(document).ready( function() {
  9062. * var oTable = $('#example').dataTable( {
  9063. * "sAjaxSource": "sources/deep.txt",
  9064. * "aoColumns": [
  9065. * { "mData": "engine" },
  9066. * { "mData": "browser" },
  9067. * { "mData": "platform.inner" },
  9068. * { "mData": "platform.details.0" },
  9069. * { "mData": "platform.details.1" }
  9070. * ]
  9071. * } );
  9072. * } );
  9073. *
  9074. * @example
  9075. * // Using mData as a function to provide different information for
  9076. * // sorting, filtering and display. In this case, currency (price)
  9077. * $(document).ready( function() {
  9078. * var oTable = $('#example').dataTable( {
  9079. * "aoColumnDefs": [ {
  9080. * "aTargets": [ 0 ],
  9081. * "mData": function ( source, type, val ) {
  9082. * if (type === 'set') {
  9083. * source.price = val;
  9084. * // Store the computed dislay and filter values for efficiency
  9085. * source.price_display = val=="" ? "" : "$"+numberFormat(val);
  9086. * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
  9087. * return;
  9088. * }
  9089. * else if (type === 'display') {
  9090. * return source.price_display;
  9091. * }
  9092. * else if (type === 'filter') {
  9093. * return source.price_filter;
  9094. * }
  9095. * // 'sort', 'type' and undefined all just use the integer
  9096. * return source.price;
  9097. * }
  9098. * } ]
  9099. * } );
  9100. * } );
  9101. */
  9102. "mData": null,
  9103. /**
  9104. * This property is the rendering partner to mData and it is suggested that
  9105. * when you want to manipulate data for display (including filtering, sorting etc)
  9106. * but not altering the underlying data for the table, use this property. mData
  9107. * can actually do everything this property can and more, but this parameter is
  9108. * easier to use since there is no 'set' option. Like mData is can be given
  9109. * in a number of different ways to effect its behaviour, with the addition of
  9110. * supporting array syntax for easy outputting of arrays (including arrays of
  9111. * objects):
  9112. * <ul>
  9113. * <li>integer - treated as an array index for the data source. This is the
  9114. * default that DataTables uses (incrementally increased for each column).</li>
  9115. * <li>string - read an object property from the data source. Note that you can
  9116. * use Javascript dotted notation to read deep properties / arrays from the
  9117. * data source and also array brackets to indicate that the data reader should
  9118. * loop over the data source array. When characters are given between the array
  9119. * brackets, these characters are used to join the data source array together.
  9120. * For example: "accounts[, ].name" would result in a comma separated list with
  9121. * the 'name' value from the 'accounts' array of objects.</li>
  9122. * <li>function - the function given will be executed whenever DataTables
  9123. * needs to set or get the data for a cell in the column. The function
  9124. * takes three parameters:
  9125. * <ul>
  9126. * <li>{array|object} The data source for the row (based on mData)</li>
  9127. * <li>{string} The type call data requested - this will be 'filter', 'display',
  9128. * 'type' or 'sort'.</li>
  9129. * <li>{array|object} The full data source for the row (not based on mData)</li>
  9130. * </ul>
  9131. * The return value from the function is what will be used for the data
  9132. * requested.</li>
  9133. * </ul>
  9134. * @type string|int|function|null
  9135. * @default null <i>Use mData</i>
  9136. * @dtopt Columns
  9137. *
  9138. * @example
  9139. * // Create a comma separated list from an array of objects
  9140. * $(document).ready( function() {
  9141. * var oTable = $('#example').dataTable( {
  9142. * "sAjaxSource": "sources/deep.txt",
  9143. * "aoColumns": [
  9144. * { "mData": "engine" },
  9145. * { "mData": "browser" },
  9146. * {
  9147. * "mData": "platform",
  9148. * "mRender": "[, ].name"
  9149. * }
  9150. * ]
  9151. * } );
  9152. * } );
  9153. *
  9154. * @example
  9155. * // Use as a function to create a link from the data source
  9156. * $(document).ready( function() {
  9157. * var oTable = $('#example').dataTable( {
  9158. * "aoColumnDefs": [
  9159. * {
  9160. * "aTargets": [ 0 ],
  9161. * "mData": "download_link",
  9162. * "mRender": function ( data, type, full ) {
  9163. * return '<a href="'+data+'">Download</a>';
  9164. * }
  9165. * ]
  9166. * } );
  9167. * } );
  9168. */
  9169. "mRender": null,
  9170. /**
  9171. * Change the cell type created for the column - either TD cells or TH cells. This
  9172. * can be useful as TH cells have semantic meaning in the table body, allowing them
  9173. * to act as a header for a row (you may wish to add scope='row' to the TH elements).
  9174. * @type string
  9175. * @default td
  9176. * @dtopt Columns
  9177. *
  9178. * @example
  9179. * // Make the first column use TH cells
  9180. * $(document).ready( function() {
  9181. * var oTable = $('#example').dataTable( {
  9182. * "aoColumnDefs": [ {
  9183. * "aTargets": [ 0 ],
  9184. * "sCellType": "th"
  9185. * } ]
  9186. * } );
  9187. * } );
  9188. */
  9189. "sCellType": "td",
  9190. /**
  9191. * Class to give to each cell in this column.
  9192. * @type string
  9193. * @default <i>Empty string</i>
  9194. * @dtopt Columns
  9195. *
  9196. * @example
  9197. * // Using aoColumnDefs
  9198. * $(document).ready( function() {
  9199. * $('#example').dataTable( {
  9200. * "aoColumnDefs": [
  9201. * { "sClass": "my_class", "aTargets": [ 0 ] }
  9202. * ]
  9203. * } );
  9204. * } );
  9205. *
  9206. * @example
  9207. * // Using aoColumns
  9208. * $(document).ready( function() {
  9209. * $('#example').dataTable( {
  9210. * "aoColumns": [
  9211. * { "sClass": "my_class" },
  9212. * null,
  9213. * null,
  9214. * null,
  9215. * null
  9216. * ]
  9217. * } );
  9218. * } );
  9219. */
  9220. "sClass": "",
  9221. /**
  9222. * When DataTables calculates the column widths to assign to each column,
  9223. * it finds the longest string in each column and then constructs a
  9224. * temporary table and reads the widths from that. The problem with this
  9225. * is that "mmm" is much wider then "iiii", but the latter is a longer
  9226. * string - thus the calculation can go wrong (doing it properly and putting
  9227. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  9228. * a "work around" we provide this option. It will append its value to the
  9229. * text that is found to be the longest string for the column - i.e. padding.
  9230. * Generally you shouldn't need this, and it is not documented on the
  9231. * general DataTables.net documentation
  9232. * @type string
  9233. * @default <i>Empty string<i>
  9234. * @dtopt Columns
  9235. *
  9236. * @example
  9237. * // Using aoColumns
  9238. * $(document).ready( function() {
  9239. * $('#example').dataTable( {
  9240. * "aoColumns": [
  9241. * null,
  9242. * null,
  9243. * null,
  9244. * {
  9245. * "sContentPadding": "mmm"
  9246. * }
  9247. * ]
  9248. * } );
  9249. * } );
  9250. */
  9251. "sContentPadding": "",
  9252. /**
  9253. * Allows a default value to be given for a column's data, and will be used
  9254. * whenever a null data source is encountered (this can be because mData
  9255. * is set to null, or because the data source itself is null).
  9256. * @type string
  9257. * @default null
  9258. * @dtopt Columns
  9259. *
  9260. * @example
  9261. * // Using aoColumnDefs
  9262. * $(document).ready( function() {
  9263. * $('#example').dataTable( {
  9264. * "aoColumnDefs": [
  9265. * {
  9266. * "mData": null,
  9267. * "sDefaultContent": "Edit",
  9268. * "aTargets": [ -1 ]
  9269. * }
  9270. * ]
  9271. * } );
  9272. * } );
  9273. *
  9274. * @example
  9275. * // Using aoColumns
  9276. * $(document).ready( function() {
  9277. * $('#example').dataTable( {
  9278. * "aoColumns": [
  9279. * null,
  9280. * null,
  9281. * null,
  9282. * {
  9283. * "mData": null,
  9284. * "sDefaultContent": "Edit"
  9285. * }
  9286. * ]
  9287. * } );
  9288. * } );
  9289. */
  9290. "sDefaultContent": null,
  9291. /**
  9292. * This parameter is only used in DataTables' server-side processing. It can
  9293. * be exceptionally useful to know what columns are being displayed on the
  9294. * client side, and to map these to database fields. When defined, the names
  9295. * also allow DataTables to reorder information from the server if it comes
  9296. * back in an unexpected order (i.e. if you switch your columns around on the
  9297. * client-side, your server-side code does not also need updating).
  9298. * @type string
  9299. * @default <i>Empty string</i>
  9300. * @dtopt Columns
  9301. *
  9302. * @example
  9303. * // Using aoColumnDefs
  9304. * $(document).ready( function() {
  9305. * $('#example').dataTable( {
  9306. * "aoColumnDefs": [
  9307. * { "sName": "engine", "aTargets": [ 0 ] },
  9308. * { "sName": "browser", "aTargets": [ 1 ] },
  9309. * { "sName": "platform", "aTargets": [ 2 ] },
  9310. * { "sName": "version", "aTargets": [ 3 ] },
  9311. * { "sName": "grade", "aTargets": [ 4 ] }
  9312. * ]
  9313. * } );
  9314. * } );
  9315. *
  9316. * @example
  9317. * // Using aoColumns
  9318. * $(document).ready( function() {
  9319. * $('#example').dataTable( {
  9320. * "aoColumns": [
  9321. * { "sName": "engine" },
  9322. * { "sName": "browser" },
  9323. * { "sName": "platform" },
  9324. * { "sName": "version" },
  9325. * { "sName": "grade" }
  9326. * ]
  9327. * } );
  9328. * } );
  9329. */
  9330. "sName": "",
  9331. /**
  9332. * Defines a data source type for the sorting which can be used to read
  9333. * real-time information from the table (updating the internally cached
  9334. * version) prior to sorting. This allows sorting to occur on user editable
  9335. * elements such as form inputs.
  9336. * @type string
  9337. * @default std
  9338. * @dtopt Columns
  9339. *
  9340. * @example
  9341. * // Using aoColumnDefs
  9342. * $(document).ready( function() {
  9343. * $('#example').dataTable( {
  9344. * "aoColumnDefs": [
  9345. * { "sSortDataType": "dom-text", "aTargets": [ 2, 3 ] },
  9346. * { "sType": "numeric", "aTargets": [ 3 ] },
  9347. * { "sSortDataType": "dom-select", "aTargets": [ 4 ] },
  9348. * { "sSortDataType": "dom-checkbox", "aTargets": [ 5 ] }
  9349. * ]
  9350. * } );
  9351. * } );
  9352. *
  9353. * @example
  9354. * // Using aoColumns
  9355. * $(document).ready( function() {
  9356. * $('#example').dataTable( {
  9357. * "aoColumns": [
  9358. * null,
  9359. * null,
  9360. * { "sSortDataType": "dom-text" },
  9361. * { "sSortDataType": "dom-text", "sType": "numeric" },
  9362. * { "sSortDataType": "dom-select" },
  9363. * { "sSortDataType": "dom-checkbox" }
  9364. * ]
  9365. * } );
  9366. * } );
  9367. */
  9368. "sSortDataType": "std",
  9369. /**
  9370. * The title of this column.
  9371. * @type string
  9372. * @default null <i>Derived from the 'TH' value for this column in the
  9373. * original HTML table.</i>
  9374. * @dtopt Columns
  9375. *
  9376. * @example
  9377. * // Using aoColumnDefs
  9378. * $(document).ready( function() {
  9379. * $('#example').dataTable( {
  9380. * "aoColumnDefs": [
  9381. * { "sTitle": "My column title", "aTargets": [ 0 ] }
  9382. * ]
  9383. * } );
  9384. * } );
  9385. *
  9386. * @example
  9387. * // Using aoColumns
  9388. * $(document).ready( function() {
  9389. * $('#example').dataTable( {
  9390. * "aoColumns": [
  9391. * { "sTitle": "My column title" },
  9392. * null,
  9393. * null,
  9394. * null,
  9395. * null
  9396. * ]
  9397. * } );
  9398. * } );
  9399. */
  9400. "sTitle": null,
  9401. /**
  9402. * The type allows you to specify how the data for this column will be sorted.
  9403. * Four types (string, numeric, date and html (which will strip HTML tags
  9404. * before sorting)) are currently available. Note that only date formats
  9405. * understood by Javascript's Date() object will be accepted as type date. For
  9406. * example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 'numeric',
  9407. * 'date' or 'html' (by default). Further types can be adding through
  9408. * plug-ins.
  9409. * @type string
  9410. * @default null <i>Auto-detected from raw data</i>
  9411. * @dtopt Columns
  9412. *
  9413. * @example
  9414. * // Using aoColumnDefs
  9415. * $(document).ready( function() {
  9416. * $('#example').dataTable( {
  9417. * "aoColumnDefs": [
  9418. * { "sType": "html", "aTargets": [ 0 ] }
  9419. * ]
  9420. * } );
  9421. * } );
  9422. *
  9423. * @example
  9424. * // Using aoColumns
  9425. * $(document).ready( function() {
  9426. * $('#example').dataTable( {
  9427. * "aoColumns": [
  9428. * { "sType": "html" },
  9429. * null,
  9430. * null,
  9431. * null,
  9432. * null
  9433. * ]
  9434. * } );
  9435. * } );
  9436. */
  9437. "sType": null,
  9438. /**
  9439. * Defining the width of the column, this parameter may take any CSS value
  9440. * (3em, 20px etc). DataTables apples 'smart' widths to columns which have not
  9441. * been given a specific width through this interface ensuring that the table
  9442. * remains readable.
  9443. * @type string
  9444. * @default null <i>Automatic</i>
  9445. * @dtopt Columns
  9446. *
  9447. * @example
  9448. * // Using aoColumnDefs
  9449. * $(document).ready( function() {
  9450. * $('#example').dataTable( {
  9451. * "aoColumnDefs": [
  9452. * { "sWidth": "20%", "aTargets": [ 0 ] }
  9453. * ]
  9454. * } );
  9455. * } );
  9456. *
  9457. * @example
  9458. * // Using aoColumns
  9459. * $(document).ready( function() {
  9460. * $('#example').dataTable( {
  9461. * "aoColumns": [
  9462. * { "sWidth": "20%" },
  9463. * null,
  9464. * null,
  9465. * null,
  9466. * null
  9467. * ]
  9468. * } );
  9469. * } );
  9470. */
  9471. "sWidth": null
  9472. };
  9473. /**
  9474. * DataTables settings object - this holds all the information needed for a
  9475. * given table, including configuration, data and current application of the
  9476. * table options. DataTables does not have a single instance for each DataTable
  9477. * with the settings attached to that instance, but rather instances of the
  9478. * DataTable "class" are created on-the-fly as needed (typically by a
  9479. * $().dataTable() call) and the settings object is then applied to that
  9480. * instance.
  9481. *
  9482. * Note that this object is related to {@link DataTable.defaults} but this
  9483. * one is the internal data store for DataTables's cache of columns. It should
  9484. * NOT be manipulated outside of DataTables. Any configuration should be done
  9485. * through the initialisation options.
  9486. * @namespace
  9487. * @todo Really should attach the settings object to individual instances so we
  9488. * don't need to create new instances on each $().dataTable() call (if the
  9489. * table already exists). It would also save passing oSettings around and
  9490. * into every single function. However, this is a very significant
  9491. * architecture change for DataTables and will almost certainly break
  9492. * backwards compatibility with older installations. This is something that
  9493. * will be done in 2.0.
  9494. */
  9495. DataTable.models.oSettings = {
  9496. /**
  9497. * Primary features of DataTables and their enablement state.
  9498. * @namespace
  9499. */
  9500. "oFeatures": {
  9501. /**
  9502. * Flag to say if DataTables should automatically try to calculate the
  9503. * optimum table and columns widths (true) or not (false).
  9504. * Note that this parameter will be set by the initialisation routine. To
  9505. * set a default use {@link DataTable.defaults}.
  9506. * @type boolean
  9507. */
  9508. "bAutoWidth": null,
  9509. /**
  9510. * Delay the creation of TR and TD elements until they are actually
  9511. * needed by a driven page draw. This can give a significant speed
  9512. * increase for Ajax source and Javascript source data, but makes no
  9513. * difference at all fro DOM and server-side processing tables.
  9514. * Note that this parameter will be set by the initialisation routine. To
  9515. * set a default use {@link DataTable.defaults}.
  9516. * @type boolean
  9517. */
  9518. "bDeferRender": null,
  9519. /**
  9520. * Enable filtering on the table or not. Note that if this is disabled
  9521. * then there is no filtering at all on the table, including fnFilter.
  9522. * To just remove the filtering input use sDom and remove the 'f' option.
  9523. * Note that this parameter will be set by the initialisation routine. To
  9524. * set a default use {@link DataTable.defaults}.
  9525. * @type boolean
  9526. */
  9527. "bFilter": null,
  9528. /**
  9529. * Table information element (the 'Showing x of y records' div) enable
  9530. * flag.
  9531. * Note that this parameter will be set by the initialisation routine. To
  9532. * set a default use {@link DataTable.defaults}.
  9533. * @type boolean
  9534. */
  9535. "bInfo": null,
  9536. /**
  9537. * Present a user control allowing the end user to change the page size
  9538. * when pagination is enabled.
  9539. * Note that this parameter will be set by the initialisation routine. To
  9540. * set a default use {@link DataTable.defaults}.
  9541. * @type boolean
  9542. */
  9543. "bLengthChange": null,
  9544. /**
  9545. * Pagination enabled or not. Note that if this is disabled then length
  9546. * changing must also be disabled.
  9547. * Note that this parameter will be set by the initialisation routine. To
  9548. * set a default use {@link DataTable.defaults}.
  9549. * @type boolean
  9550. */
  9551. "bPaginate": null,
  9552. /**
  9553. * Processing indicator enable flag whenever DataTables is enacting a
  9554. * user request - typically an Ajax request for server-side processing.
  9555. * Note that this parameter will be set by the initialisation routine. To
  9556. * set a default use {@link DataTable.defaults}.
  9557. * @type boolean
  9558. */
  9559. "bProcessing": null,
  9560. /**
  9561. * Server-side processing enabled flag - when enabled DataTables will
  9562. * get all data from the server for every draw - there is no filtering,
  9563. * sorting or paging done on the client-side.
  9564. * Note that this parameter will be set by the initialisation routine. To
  9565. * set a default use {@link DataTable.defaults}.
  9566. * @type boolean
  9567. */
  9568. "bServerSide": null,
  9569. /**
  9570. * Sorting enablement flag.
  9571. * Note that this parameter will be set by the initialisation routine. To
  9572. * set a default use {@link DataTable.defaults}.
  9573. * @type boolean
  9574. */
  9575. "bSort": null,
  9576. /**
  9577. * Apply a class to the columns which are being sorted to provide a
  9578. * visual highlight or not. This can slow things down when enabled since
  9579. * there is a lot of DOM interaction.
  9580. * Note that this parameter will be set by the initialisation routine. To
  9581. * set a default use {@link DataTable.defaults}.
  9582. * @type boolean
  9583. */
  9584. "bSortClasses": null,
  9585. /**
  9586. * State saving enablement flag.
  9587. * Note that this parameter will be set by the initialisation routine. To
  9588. * set a default use {@link DataTable.defaults}.
  9589. * @type boolean
  9590. */
  9591. "bStateSave": null
  9592. },
  9593. /**
  9594. * Scrolling settings for a table.
  9595. * @namespace
  9596. */
  9597. "oScroll": {
  9598. /**
  9599. * Indicate if DataTables should be allowed to set the padding / margin
  9600. * etc for the scrolling header elements or not. Typically you will want
  9601. * this.
  9602. * Note that this parameter will be set by the initialisation routine. To
  9603. * set a default use {@link DataTable.defaults}.
  9604. * @type boolean
  9605. */
  9606. "bAutoCss": null,
  9607. /**
  9608. * When the table is shorter in height than sScrollY, collapse the
  9609. * table container down to the height of the table (when true).
  9610. * Note that this parameter will be set by the initialisation routine. To
  9611. * set a default use {@link DataTable.defaults}.
  9612. * @type boolean
  9613. */
  9614. "bCollapse": null,
  9615. /**
  9616. * Infinite scrolling enablement flag. Now deprecated in favour of
  9617. * using the Scroller plug-in.
  9618. * Note that this parameter will be set by the initialisation routine. To
  9619. * set a default use {@link DataTable.defaults}.
  9620. * @type boolean
  9621. */
  9622. "bInfinite": null,
  9623. /**
  9624. * Width of the scrollbar for the web-browser's platform. Calculated
  9625. * during table initialisation.
  9626. * @type int
  9627. * @default 0
  9628. */
  9629. "iBarWidth": 0,
  9630. /**
  9631. * Space (in pixels) between the bottom of the scrolling container and
  9632. * the bottom of the scrolling viewport before the next page is loaded
  9633. * when using infinite scrolling.
  9634. * Note that this parameter will be set by the initialisation routine. To
  9635. * set a default use {@link DataTable.defaults}.
  9636. * @type int
  9637. */
  9638. "iLoadGap": null,
  9639. /**
  9640. * Viewport width for horizontal scrolling. Horizontal scrolling is
  9641. * disabled if an empty string.
  9642. * Note that this parameter will be set by the initialisation routine. To
  9643. * set a default use {@link DataTable.defaults}.
  9644. * @type string
  9645. */
  9646. "sX": null,
  9647. /**
  9648. * Width to expand the table to when using x-scrolling. Typically you
  9649. * should not need to use this.
  9650. * Note that this parameter will be set by the initialisation routine. To
  9651. * set a default use {@link DataTable.defaults}.
  9652. * @type string
  9653. * @deprecated
  9654. */
  9655. "sXInner": null,
  9656. /**
  9657. * Viewport height for vertical scrolling. Vertical scrolling is disabled
  9658. * if an empty string.
  9659. * Note that this parameter will be set by the initialisation routine. To
  9660. * set a default use {@link DataTable.defaults}.
  9661. * @type string
  9662. */
  9663. "sY": null
  9664. },
  9665. /**
  9666. * Language information for the table.
  9667. * @namespace
  9668. * @extends DataTable.defaults.oLanguage
  9669. */
  9670. "oLanguage": {
  9671. /**
  9672. * Information callback function. See
  9673. * {@link DataTable.defaults.fnInfoCallback}
  9674. * @type function
  9675. * @default null
  9676. */
  9677. "fnInfoCallback": null
  9678. },
  9679. /**
  9680. * Browser support parameters
  9681. * @namespace
  9682. */
  9683. "oBrowser": {
  9684. /**
  9685. * Indicate if the browser incorrectly calculates width:100% inside a
  9686. * scrolling element (IE6/7)
  9687. * @type boolean
  9688. * @default false
  9689. */
  9690. "bScrollOversize": false
  9691. },
  9692. /**
  9693. * Array referencing the nodes which are used for the features. The
  9694. * parameters of this object match what is allowed by sDom - i.e.
  9695. * <ul>
  9696. * <li>'l' - Length changing</li>
  9697. * <li>'f' - Filtering input</li>
  9698. * <li>'t' - The table!</li>
  9699. * <li>'i' - Information</li>
  9700. * <li>'p' - Pagination</li>
  9701. * <li>'r' - pRocessing</li>
  9702. * </ul>
  9703. * @type array
  9704. * @default []
  9705. */
  9706. "aanFeatures": [],
  9707. /**
  9708. * Store data information - see {@link DataTable.models.oRow} for detailed
  9709. * information.
  9710. * @type array
  9711. * @default []
  9712. */
  9713. "aoData": [],
  9714. /**
  9715. * Array of indexes which are in the current display (after filtering etc)
  9716. * @type array
  9717. * @default []
  9718. */
  9719. "aiDisplay": [],
  9720. /**
  9721. * Array of indexes for display - no filtering
  9722. * @type array
  9723. * @default []
  9724. */
  9725. "aiDisplayMaster": [],
  9726. /**
  9727. * Store information about each column that is in use
  9728. * @type array
  9729. * @default []
  9730. */
  9731. "aoColumns": [],
  9732. /**
  9733. * Store information about the table's header
  9734. * @type array
  9735. * @default []
  9736. */
  9737. "aoHeader": [],
  9738. /**
  9739. * Store information about the table's footer
  9740. * @type array
  9741. * @default []
  9742. */
  9743. "aoFooter": [],
  9744. /**
  9745. * Search data array for regular expression searching
  9746. * @type array
  9747. * @default []
  9748. */
  9749. "asDataSearch": [],
  9750. /**
  9751. * Store the applied global search information in case we want to force a
  9752. * research or compare the old search to a new one.
  9753. * Note that this parameter will be set by the initialisation routine. To
  9754. * set a default use {@link DataTable.defaults}.
  9755. * @namespace
  9756. * @extends DataTable.models.oSearch
  9757. */
  9758. "oPreviousSearch": {},
  9759. /**
  9760. * Store the applied search for each column - see
  9761. * {@link DataTable.models.oSearch} for the format that is used for the
  9762. * filtering information for each column.
  9763. * @type array
  9764. * @default []
  9765. */
  9766. "aoPreSearchCols": [],
  9767. /**
  9768. * Sorting that is applied to the table. Note that the inner arrays are
  9769. * used in the following manner:
  9770. * <ul>
  9771. * <li>Index 0 - column number</li>
  9772. * <li>Index 1 - current sorting direction</li>
  9773. * <li>Index 2 - index of asSorting for this column</li>
  9774. * </ul>
  9775. * Note that this parameter will be set by the initialisation routine. To
  9776. * set a default use {@link DataTable.defaults}.
  9777. * @type array
  9778. * @todo These inner arrays should really be objects
  9779. */
  9780. "aaSorting": null,
  9781. /**
  9782. * Sorting that is always applied to the table (i.e. prefixed in front of
  9783. * aaSorting).
  9784. * Note that this parameter will be set by the initialisation routine. To
  9785. * set a default use {@link DataTable.defaults}.
  9786. * @type array|null
  9787. * @default null
  9788. */
  9789. "aaSortingFixed": null,
  9790. /**
  9791. * Classes to use for the striping of a table.
  9792. * Note that this parameter will be set by the initialisation routine. To
  9793. * set a default use {@link DataTable.defaults}.
  9794. * @type array
  9795. * @default []
  9796. */
  9797. "asStripeClasses": null,
  9798. /**
  9799. * If restoring a table - we should restore its striping classes as well
  9800. * @type array
  9801. * @default []
  9802. */
  9803. "asDestroyStripes": [],
  9804. /**
  9805. * If restoring a table - we should restore its width
  9806. * @type int
  9807. * @default 0
  9808. */
  9809. "sDestroyWidth": 0,
  9810. /**
  9811. * Callback functions array for every time a row is inserted (i.e. on a draw).
  9812. * @type array
  9813. * @default []
  9814. */
  9815. "aoRowCallback": [],
  9816. /**
  9817. * Callback functions for the header on each draw.
  9818. * @type array
  9819. * @default []
  9820. */
  9821. "aoHeaderCallback": [],
  9822. /**
  9823. * Callback function for the footer on each draw.
  9824. * @type array
  9825. * @default []
  9826. */
  9827. "aoFooterCallback": [],
  9828. /**
  9829. * Array of callback functions for draw callback functions
  9830. * @type array
  9831. * @default []
  9832. */
  9833. "aoDrawCallback": [],
  9834. /**
  9835. * Array of callback functions for row created function
  9836. * @type array
  9837. * @default []
  9838. */
  9839. "aoRowCreatedCallback": [],
  9840. /**
  9841. * Callback functions for just before the table is redrawn. A return of
  9842. * false will be used to cancel the draw.
  9843. * @type array
  9844. * @default []
  9845. */
  9846. "aoPreDrawCallback": [],
  9847. /**
  9848. * Callback functions for when the table has been initialised.
  9849. * @type array
  9850. * @default []
  9851. */
  9852. "aoInitComplete": [],
  9853. /**
  9854. * Callbacks for modifying the settings to be stored for state saving, prior to
  9855. * saving state.
  9856. * @type array
  9857. * @default []
  9858. */
  9859. "aoStateSaveParams": [],
  9860. /**
  9861. * Callbacks for modifying the settings that have been stored for state saving
  9862. * prior to using the stored values to restore the state.
  9863. * @type array
  9864. * @default []
  9865. */
  9866. "aoStateLoadParams": [],
  9867. /**
  9868. * Callbacks for operating on the settings object once the saved state has been
  9869. * loaded
  9870. * @type array
  9871. * @default []
  9872. */
  9873. "aoStateLoaded": [],
  9874. /**
  9875. * Cache the table ID for quick access
  9876. * @type string
  9877. * @default <i>Empty string</i>
  9878. */
  9879. "sTableId": "",
  9880. /**
  9881. * The TABLE node for the main table
  9882. * @type node
  9883. * @default null
  9884. */
  9885. "nTable": null,
  9886. /**
  9887. * Permanent ref to the thead element
  9888. * @type node
  9889. * @default null
  9890. */
  9891. "nTHead": null,
  9892. /**
  9893. * Permanent ref to the tfoot element - if it exists
  9894. * @type node
  9895. * @default null
  9896. */
  9897. "nTFoot": null,
  9898. /**
  9899. * Permanent ref to the tbody element
  9900. * @type node
  9901. * @default null
  9902. */
  9903. "nTBody": null,
  9904. /**
  9905. * Cache the wrapper node (contains all DataTables controlled elements)
  9906. * @type node
  9907. * @default null
  9908. */
  9909. "nTableWrapper": null,
  9910. /**
  9911. * Indicate if when using server-side processing the loading of data
  9912. * should be deferred until the second draw.
  9913. * Note that this parameter will be set by the initialisation routine. To
  9914. * set a default use {@link DataTable.defaults}.
  9915. * @type boolean
  9916. * @default false
  9917. */
  9918. "bDeferLoading": false,
  9919. /**
  9920. * Indicate if all required information has been read in
  9921. * @type boolean
  9922. * @default false
  9923. */
  9924. "bInitialised": false,
  9925. /**
  9926. * Information about open rows. Each object in the array has the parameters
  9927. * 'nTr' and 'nParent'
  9928. * @type array
  9929. * @default []
  9930. */
  9931. "aoOpenRows": [],
  9932. /**
  9933. * Dictate the positioning of DataTables' control elements - see
  9934. * {@link DataTable.model.oInit.sDom}.
  9935. * Note that this parameter will be set by the initialisation routine. To
  9936. * set a default use {@link DataTable.defaults}.
  9937. * @type string
  9938. * @default null
  9939. */
  9940. "sDom": null,
  9941. /**
  9942. * Which type of pagination should be used.
  9943. * Note that this parameter will be set by the initialisation routine. To
  9944. * set a default use {@link DataTable.defaults}.
  9945. * @type string
  9946. * @default two_button
  9947. */
  9948. "sPaginationType": "two_button",
  9949. /**
  9950. * The cookie duration (for bStateSave) in seconds.
  9951. * Note that this parameter will be set by the initialisation routine. To
  9952. * set a default use {@link DataTable.defaults}.
  9953. * @type int
  9954. * @default 0
  9955. */
  9956. "iCookieDuration": 0,
  9957. /**
  9958. * The cookie name prefix.
  9959. * Note that this parameter will be set by the initialisation routine. To
  9960. * set a default use {@link DataTable.defaults}.
  9961. * @type string
  9962. * @default <i>Empty string</i>
  9963. */
  9964. "sCookiePrefix": "",
  9965. /**
  9966. * Callback function for cookie creation.
  9967. * Note that this parameter will be set by the initialisation routine. To
  9968. * set a default use {@link DataTable.defaults}.
  9969. * @type function
  9970. * @default null
  9971. */
  9972. "fnCookieCallback": null,
  9973. /**
  9974. * Array of callback functions for state saving. Each array element is an
  9975. * object with the following parameters:
  9976. * <ul>
  9977. * <li>function:fn - function to call. Takes two parameters, oSettings
  9978. * and the JSON string to save that has been thus far created. Returns
  9979. * a JSON string to be inserted into a json object
  9980. * (i.e. '"param": [ 0, 1, 2]')</li>
  9981. * <li>string:sName - name of callback</li>
  9982. * </ul>
  9983. * @type array
  9984. * @default []
  9985. */
  9986. "aoStateSave": [],
  9987. /**
  9988. * Array of callback functions for state loading. Each array element is an
  9989. * object with the following parameters:
  9990. * <ul>
  9991. * <li>function:fn - function to call. Takes two parameters, oSettings
  9992. * and the object stored. May return false to cancel state loading</li>
  9993. * <li>string:sName - name of callback</li>
  9994. * </ul>
  9995. * @type array
  9996. * @default []
  9997. */
  9998. "aoStateLoad": [],
  9999. /**
  10000. * State that was loaded from the cookie. Useful for back reference
  10001. * @type object
  10002. * @default null
  10003. */
  10004. "oLoadedState": null,
  10005. /**
  10006. * Source url for AJAX data for the table.
  10007. * Note that this parameter will be set by the initialisation routine. To
  10008. * set a default use {@link DataTable.defaults}.
  10009. * @type string
  10010. * @default null
  10011. */
  10012. "sAjaxSource": null,
  10013. /**
  10014. * Property from a given object from which to read the table data from. This
  10015. * can be an empty string (when not server-side processing), in which case
  10016. * it is assumed an an array is given directly.
  10017. * Note that this parameter will be set by the initialisation routine. To
  10018. * set a default use {@link DataTable.defaults}.
  10019. * @type string
  10020. */
  10021. "sAjaxDataProp": null,
  10022. /**
  10023. * Note if draw should be blocked while getting data
  10024. * @type boolean
  10025. * @default true
  10026. */
  10027. "bAjaxDataGet": true,
  10028. /**
  10029. * The last jQuery XHR object that was used for server-side data gathering.
  10030. * This can be used for working with the XHR information in one of the
  10031. * callbacks
  10032. * @type object
  10033. * @default null
  10034. */
  10035. "jqXHR": null,
  10036. /**
  10037. * Function to get the server-side data.
  10038. * Note that this parameter will be set by the initialisation routine. To
  10039. * set a default use {@link DataTable.defaults}.
  10040. * @type function
  10041. */
  10042. "fnServerData": null,
  10043. /**
  10044. * Functions which are called prior to sending an Ajax request so extra
  10045. * parameters can easily be sent to the server
  10046. * @type array
  10047. * @default []
  10048. */
  10049. "aoServerParams": [],
  10050. /**
  10051. * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
  10052. * required).
  10053. * Note that this parameter will be set by the initialisation routine. To
  10054. * set a default use {@link DataTable.defaults}.
  10055. * @type string
  10056. */
  10057. "sServerMethod": null,
  10058. /**
  10059. * Format numbers for display.
  10060. * Note that this parameter will be set by the initialisation routine. To
  10061. * set a default use {@link DataTable.defaults}.
  10062. * @type function
  10063. */
  10064. "fnFormatNumber": null,
  10065. /**
  10066. * List of options that can be used for the user selectable length menu.
  10067. * Note that this parameter will be set by the initialisation routine. To
  10068. * set a default use {@link DataTable.defaults}.
  10069. * @type array
  10070. * @default []
  10071. */
  10072. "aLengthMenu": null,
  10073. /**
  10074. * Counter for the draws that the table does. Also used as a tracker for
  10075. * server-side processing
  10076. * @type int
  10077. * @default 0
  10078. */
  10079. "iDraw": 0,
  10080. /**
  10081. * Indicate if a redraw is being done - useful for Ajax
  10082. * @type boolean
  10083. * @default false
  10084. */
  10085. "bDrawing": false,
  10086. /**
  10087. * Draw index (iDraw) of the last error when parsing the returned data
  10088. * @type int
  10089. * @default -1
  10090. */
  10091. "iDrawError": -1,
  10092. /**
  10093. * Paging display length
  10094. * @type int
  10095. * @default 10
  10096. */
  10097. "_iDisplayLength": 10,
  10098. /**
  10099. * Paging start point - aiDisplay index
  10100. * @type int
  10101. * @default 0
  10102. */
  10103. "_iDisplayStart": 0,
  10104. /**
  10105. * Paging end point - aiDisplay index. Use fnDisplayEnd rather than
  10106. * this property to get the end point
  10107. * @type int
  10108. * @default 10
  10109. * @private
  10110. */
  10111. "_iDisplayEnd": 10,
  10112. /**
  10113. * Server-side processing - number of records in the result set
  10114. * (i.e. before filtering), Use fnRecordsTotal rather than
  10115. * this property to get the value of the number of records, regardless of
  10116. * the server-side processing setting.
  10117. * @type int
  10118. * @default 0
  10119. * @private
  10120. */
  10121. "_iRecordsTotal": 0,
  10122. /**
  10123. * Server-side processing - number of records in the current display set
  10124. * (i.e. after filtering). Use fnRecordsDisplay rather than
  10125. * this property to get the value of the number of records, regardless of
  10126. * the server-side processing setting.
  10127. * @type boolean
  10128. * @default 0
  10129. * @private
  10130. */
  10131. "_iRecordsDisplay": 0,
  10132. /**
  10133. * Flag to indicate if jQuery UI marking and classes should be used.
  10134. * Note that this parameter will be set by the initialisation routine. To
  10135. * set a default use {@link DataTable.defaults}.
  10136. * @type boolean
  10137. */
  10138. "bJUI": null,
  10139. /**
  10140. * The classes to use for the table
  10141. * @type object
  10142. * @default {}
  10143. */
  10144. "oClasses": {},
  10145. /**
  10146. * Flag attached to the settings object so you can check in the draw
  10147. * callback if filtering has been done in the draw. Deprecated in favour of
  10148. * events.
  10149. * @type boolean
  10150. * @default false
  10151. * @deprecated
  10152. */
  10153. "bFiltered": false,
  10154. /**
  10155. * Flag attached to the settings object so you can check in the draw
  10156. * callback if sorting has been done in the draw. Deprecated in favour of
  10157. * events.
  10158. * @type boolean
  10159. * @default false
  10160. * @deprecated
  10161. */
  10162. "bSorted": false,
  10163. /**
  10164. * Indicate that if multiple rows are in the header and there is more than
  10165. * one unique cell per column, if the top one (true) or bottom one (false)
  10166. * should be used for sorting / title by DataTables.
  10167. * Note that this parameter will be set by the initialisation routine. To
  10168. * set a default use {@link DataTable.defaults}.
  10169. * @type boolean
  10170. */
  10171. "bSortCellsTop": null,
  10172. /**
  10173. * Initialisation object that is used for the table
  10174. * @type object
  10175. * @default null
  10176. */
  10177. "oInit": null,
  10178. /**
  10179. * Destroy callback functions - for plug-ins to attach themselves to the
  10180. * destroy so they can clean up markup and events.
  10181. * @type array
  10182. * @default []
  10183. */
  10184. "aoDestroyCallback": [],
  10185. /**
  10186. * Get the number of records in the current record set, before filtering
  10187. * @type function
  10188. */
  10189. "fnRecordsTotal": function ()
  10190. {
  10191. if ( this.oFeatures.bServerSide ) {
  10192. return parseInt(this._iRecordsTotal, 10);
  10193. } else {
  10194. return this.aiDisplayMaster.length;
  10195. }
  10196. },
  10197. /**
  10198. * Get the number of records in the current record set, after filtering
  10199. * @type function
  10200. */
  10201. "fnRecordsDisplay": function ()
  10202. {
  10203. if ( this.oFeatures.bServerSide ) {
  10204. return parseInt(this._iRecordsDisplay, 10);
  10205. } else {
  10206. return this.aiDisplay.length;
  10207. }
  10208. },
  10209. /**
  10210. * Set the display end point - aiDisplay index
  10211. * @type function
  10212. * @todo Should do away with _iDisplayEnd and calculate it on-the-fly here
  10213. */
  10214. "fnDisplayEnd": function ()
  10215. {
  10216. if ( this.oFeatures.bServerSide ) {
  10217. if ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) {
  10218. return this._iDisplayStart+this.aiDisplay.length;
  10219. } else {
  10220. return Math.min( this._iDisplayStart+this._iDisplayLength,
  10221. this._iRecordsDisplay );
  10222. }
  10223. } else {
  10224. return this._iDisplayEnd;
  10225. }
  10226. },
  10227. /**
  10228. * The DataTables object for this table
  10229. * @type object
  10230. * @default null
  10231. */
  10232. "oInstance": null,
  10233. /**
  10234. * Unique identifier for each instance of the DataTables object. If there
  10235. * is an ID on the table node, then it takes that value, otherwise an
  10236. * incrementing internal counter is used.
  10237. * @type string
  10238. * @default null
  10239. */
  10240. "sInstance": null,
  10241. /**
  10242. * tabindex attribute value that is added to DataTables control elements, allowing
  10243. * keyboard navigation of the table and its controls.
  10244. */
  10245. "iTabIndex": 0,
  10246. /**
  10247. * DIV container for the footer scrolling table if scrolling
  10248. */
  10249. "nScrollHead": null,
  10250. /**
  10251. * DIV container for the footer scrolling table if scrolling
  10252. */
  10253. "nScrollFoot": null
  10254. };
  10255. /**
  10256. * Extension object for DataTables that is used to provide all extension options.
  10257. *
  10258. * Note that the <i>DataTable.ext</i> object is available through
  10259. * <i>jQuery.fn.dataTable.ext</i> where it may be accessed and manipulated. It is
  10260. * also aliased to <i>jQuery.fn.dataTableExt</i> for historic reasons.
  10261. * @namespace
  10262. * @extends DataTable.models.ext
  10263. */
  10264. DataTable.ext = $.extend( true, {}, DataTable.models.ext );
  10265. $.extend( DataTable.ext.oStdClasses, {
  10266. "sTable": "dataTable",
  10267. /* Two buttons buttons */
  10268. "sPagePrevEnabled": "paginate_enabled_previous",
  10269. "sPagePrevDisabled": "paginate_disabled_previous",
  10270. "sPageNextEnabled": "paginate_enabled_next",
  10271. "sPageNextDisabled": "paginate_disabled_next",
  10272. "sPageJUINext": "",
  10273. "sPageJUIPrev": "",
  10274. /* Full numbers paging buttons */
  10275. "sPageButton": "paginate_button",
  10276. "sPageButtonActive": "paginate_active",
  10277. "sPageButtonStaticDisabled": "paginate_button paginate_button_disabled",
  10278. "sPageFirst": "first",
  10279. "sPagePrevious": "previous",
  10280. "sPageNext": "next",
  10281. "sPageLast": "last",
  10282. /* Striping classes */
  10283. "sStripeOdd": "odd",
  10284. "sStripeEven": "even",
  10285. /* Empty row */
  10286. "sRowEmpty": "dataTables_empty",
  10287. /* Features */
  10288. "sWrapper": "dataTables_wrapper",
  10289. "sFilter": "dataTables_filter",
  10290. "sInfo": "dataTables_info",
  10291. "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
  10292. "sLength": "dataTables_length",
  10293. "sProcessing": "dataTables_processing",
  10294. /* Sorting */
  10295. "sSortAsc": "sorting_asc",
  10296. "sSortDesc": "sorting_desc",
  10297. "sSortable": "sorting", /* Sortable in both directions */
  10298. "sSortableAsc": "sorting_asc_disabled",
  10299. "sSortableDesc": "sorting_desc_disabled",
  10300. "sSortableNone": "sorting_disabled",
  10301. "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
  10302. "sSortJUIAsc": "",
  10303. "sSortJUIDesc": "",
  10304. "sSortJUI": "",
  10305. "sSortJUIAscAllowed": "",
  10306. "sSortJUIDescAllowed": "",
  10307. "sSortJUIWrapper": "",
  10308. "sSortIcon": "",
  10309. /* Scrolling */
  10310. "sScrollWrapper": "dataTables_scroll",
  10311. "sScrollHead": "dataTables_scrollHead",
  10312. "sScrollHeadInner": "dataTables_scrollHeadInner",
  10313. "sScrollBody": "dataTables_scrollBody",
  10314. "sScrollFoot": "dataTables_scrollFoot",
  10315. "sScrollFootInner": "dataTables_scrollFootInner",
  10316. /* Misc */
  10317. "sFooterTH": "",
  10318. "sJUIHeader": "",
  10319. "sJUIFooter": ""
  10320. } );
  10321. $.extend( DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, {
  10322. /* Two buttons buttons */
  10323. "sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left",
  10324. "sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",
  10325. "sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right",
  10326. "sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",
  10327. "sPageJUINext": "ui-icon ui-icon-circle-arrow-e",
  10328. "sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w",
  10329. /* Full numbers paging buttons */
  10330. "sPageButton": "fg-button ui-button ui-state-default",
  10331. "sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled",
  10332. "sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled",
  10333. "sPageFirst": "first ui-corner-tl ui-corner-bl",
  10334. "sPageLast": "last ui-corner-tr ui-corner-br",
  10335. /* Features */
  10336. "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
  10337. "ui-buttonset-multi paging_", /* Note that the type is postfixed */
  10338. /* Sorting */
  10339. "sSortAsc": "ui-state-default",
  10340. "sSortDesc": "ui-state-default",
  10341. "sSortable": "ui-state-default",
  10342. "sSortableAsc": "ui-state-default",
  10343. "sSortableDesc": "ui-state-default",
  10344. "sSortableNone": "ui-state-default",
  10345. "sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n",
  10346. "sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s",
  10347. "sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s",
  10348. "sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n",
  10349. "sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s",
  10350. "sSortJUIWrapper": "DataTables_sort_wrapper",
  10351. "sSortIcon": "DataTables_sort_icon",
  10352. /* Scrolling */
  10353. "sScrollHead": "dataTables_scrollHead ui-state-default",
  10354. "sScrollFoot": "dataTables_scrollFoot ui-state-default",
  10355. /* Misc */
  10356. "sFooterTH": "ui-state-default",
  10357. "sJUIHeader": "fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix",
  10358. "sJUIFooter": "fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"
  10359. } );
  10360. /*
  10361. * Variable: oPagination
  10362. * Purpose:
  10363. * Scope: jQuery.fn.dataTableExt
  10364. */
  10365. $.extend( DataTable.ext.oPagination, {
  10366. /*
  10367. * Variable: two_button
  10368. * Purpose: Standard two button (forward/back) pagination
  10369. * Scope: jQuery.fn.dataTableExt.oPagination
  10370. */
  10371. "two_button": {
  10372. /*
  10373. * Function: oPagination.two_button.fnInit
  10374. * Purpose: Initialise dom elements required for pagination with forward/back buttons only
  10375. * Returns: -
  10376. * Inputs: object:oSettings - dataTables settings object
  10377. * node:nPaging - the DIV which contains this pagination control
  10378. * function:fnCallbackDraw - draw function which must be called on update
  10379. */
  10380. "fnInit": function ( oSettings, nPaging, fnCallbackDraw )
  10381. {
  10382. var oLang = oSettings.oLanguage.oPaginate;
  10383. var oClasses = oSettings.oClasses;
  10384. var fnClickHandler = function ( e ) {
  10385. if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) )
  10386. {
  10387. fnCallbackDraw( oSettings );
  10388. }
  10389. };
  10390. var sAppend = (!oSettings.bJUI) ?
  10391. '<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sPrevious+'</a>'+
  10392. '<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sNext+'</a>'
  10393. :
  10394. '<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUIPrev+'"></span></a>'+
  10395. '<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUINext+'"></span></a>';
  10396. $(nPaging).append( sAppend );
  10397. var els = $('a', nPaging);
  10398. var nPrevious = els[0],
  10399. nNext = els[1];
  10400. oSettings.oApi._fnBindAction( nPrevious, {action: "previous"}, fnClickHandler );
  10401. oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler );
  10402. /* ID the first elements only */
  10403. if ( !oSettings.aanFeatures.p )
  10404. {
  10405. nPaging.id = oSettings.sTableId+'_paginate';
  10406. nPrevious.id = oSettings.sTableId+'_previous';
  10407. nNext.id = oSettings.sTableId+'_next';
  10408. nPrevious.setAttribute('aria-controls', oSettings.sTableId);
  10409. nNext.setAttribute('aria-controls', oSettings.sTableId);
  10410. }
  10411. },
  10412. /*
  10413. * Function: oPagination.two_button.fnUpdate
  10414. * Purpose: Update the two button pagination at the end of the draw
  10415. * Returns: -
  10416. * Inputs: object:oSettings - dataTables settings object
  10417. * function:fnCallbackDraw - draw function to call on page change
  10418. */
  10419. "fnUpdate": function ( oSettings, fnCallbackDraw )
  10420. {
  10421. if ( !oSettings.aanFeatures.p )
  10422. {
  10423. return;
  10424. }
  10425. var oClasses = oSettings.oClasses;
  10426. var an = oSettings.aanFeatures.p;
  10427. var nNode;
  10428. /* Loop over each instance of the pager */
  10429. for ( var i=0, iLen=an.length ; i<iLen ; i++ )
  10430. {
  10431. nNode = an[i].firstChild;
  10432. if ( nNode )
  10433. {
  10434. /* Previous page */
  10435. nNode.className = ( oSettings._iDisplayStart === 0 ) ?
  10436. oClasses.sPagePrevDisabled : oClasses.sPagePrevEnabled;
  10437. /* Next page */
  10438. nNode = nNode.nextSibling;
  10439. nNode.className = ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) ?
  10440. oClasses.sPageNextDisabled : oClasses.sPageNextEnabled;
  10441. }
  10442. }
  10443. }
  10444. },
  10445. /*
  10446. * Variable: iFullNumbersShowPages
  10447. * Purpose: Change the number of pages which can be seen
  10448. * Scope: jQuery.fn.dataTableExt.oPagination
  10449. */
  10450. "iFullNumbersShowPages": 5,
  10451. /*
  10452. * Variable: full_numbers
  10453. * Purpose: Full numbers pagination
  10454. * Scope: jQuery.fn.dataTableExt.oPagination
  10455. */
  10456. "full_numbers": {
  10457. /*
  10458. * Function: oPagination.full_numbers.fnInit
  10459. * Purpose: Initialise dom elements required for pagination with a list of the pages
  10460. * Returns: -
  10461. * Inputs: object:oSettings - dataTables settings object
  10462. * node:nPaging - the DIV which contains this pagination control
  10463. * function:fnCallbackDraw - draw function which must be called on update
  10464. */
  10465. "fnInit": function ( oSettings, nPaging, fnCallbackDraw )
  10466. {
  10467. var oLang = oSettings.oLanguage.oPaginate;
  10468. var oClasses = oSettings.oClasses;
  10469. var fnClickHandler = function ( e ) {
  10470. if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) )
  10471. {
  10472. fnCallbackDraw( oSettings );
  10473. }
  10474. };
  10475. $(nPaging).append(
  10476. '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageFirst+'">'+oLang.sFirst+'</a>'+
  10477. '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPagePrevious+'">'+oLang.sPrevious+'</a>'+
  10478. '<span></span>'+
  10479. '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageNext+'">'+oLang.sNext+'</a>'+
  10480. '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageLast+'">'+oLang.sLast+'</a>'
  10481. );
  10482. var els = $('a', nPaging);
  10483. var nFirst = els[0],
  10484. nPrev = els[1],
  10485. nNext = els[2],
  10486. nLast = els[3];
  10487. oSettings.oApi._fnBindAction( nFirst, {action: "first"}, fnClickHandler );
  10488. oSettings.oApi._fnBindAction( nPrev, {action: "previous"}, fnClickHandler );
  10489. oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler );
  10490. oSettings.oApi._fnBindAction( nLast, {action: "last"}, fnClickHandler );
  10491. /* ID the first elements only */
  10492. if ( !oSettings.aanFeatures.p )
  10493. {
  10494. nPaging.id = oSettings.sTableId+'_paginate';
  10495. nFirst.id =oSettings.sTableId+'_first';
  10496. nPrev.id =oSettings.sTableId+'_previous';
  10497. nNext.id =oSettings.sTableId+'_next';
  10498. nLast.id =oSettings.sTableId+'_last';
  10499. }
  10500. },
  10501. /*
  10502. * Function: oPagination.full_numbers.fnUpdate
  10503. * Purpose: Update the list of page buttons shows
  10504. * Returns: -
  10505. * Inputs: object:oSettings - dataTables settings object
  10506. * function:fnCallbackDraw - draw function to call on page change
  10507. */
  10508. "fnUpdate": function ( oSettings, fnCallbackDraw )
  10509. {
  10510. if ( !oSettings.aanFeatures.p )
  10511. {
  10512. return;
  10513. }
  10514. var iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages;
  10515. var iPageCountHalf = Math.floor(iPageCount / 2);
  10516. var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
  10517. var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
  10518. var sList = "";
  10519. var iStartButton, iEndButton, i, iLen;
  10520. var oClasses = oSettings.oClasses;
  10521. var anButtons, anStatic, nPaginateList, nNode;
  10522. var an = oSettings.aanFeatures.p;
  10523. var fnBind = function (j) {
  10524. oSettings.oApi._fnBindAction( this, {"page": j+iStartButton-1}, function(e) {
  10525. /* Use the information in the element to jump to the required page */
  10526. oSettings.oApi._fnPageChange( oSettings, e.data.page );
  10527. fnCallbackDraw( oSettings );
  10528. e.preventDefault();
  10529. } );
  10530. };
  10531. /* Pages calculation */
  10532. if ( oSettings._iDisplayLength === -1 )
  10533. {
  10534. iStartButton = 1;
  10535. iEndButton = 1;
  10536. iCurrentPage = 1;
  10537. }
  10538. else if (iPages < iPageCount)
  10539. {
  10540. iStartButton = 1;
  10541. iEndButton = iPages;
  10542. }
  10543. else if (iCurrentPage <= iPageCountHalf)
  10544. {
  10545. iStartButton = 1;
  10546. iEndButton = iPageCount;
  10547. }
  10548. else if (iCurrentPage >= (iPages - iPageCountHalf))
  10549. {
  10550. iStartButton = iPages - iPageCount + 1;
  10551. iEndButton = iPages;
  10552. }
  10553. else
  10554. {
  10555. iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
  10556. iEndButton = iStartButton + iPageCount - 1;
  10557. }
  10558. /* Build the dynamic list */
  10559. for ( i=iStartButton ; i<=iEndButton ; i++ )
  10560. {
  10561. sList += (iCurrentPage !== i) ?
  10562. '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+'">'+oSettings.fnFormatNumber(i)+'</a>' :
  10563. '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButtonActive+'">'+oSettings.fnFormatNumber(i)+'</a>';
  10564. }
  10565. /* Loop over each instance of the pager */
  10566. for ( i=0, iLen=an.length ; i<iLen ; i++ )
  10567. {
  10568. nNode = an[i];
  10569. if ( !nNode.hasChildNodes() )
  10570. {
  10571. continue;
  10572. }
  10573. /* Build up the dynamic list first - html and listeners */
  10574. $('span:eq(0)', nNode)
  10575. .html( sList )
  10576. .children('a').each( fnBind );
  10577. /* Update the permanent button's classes */
  10578. anButtons = nNode.getElementsByTagName('a');
  10579. anStatic = [
  10580. anButtons[0], anButtons[1],
  10581. anButtons[anButtons.length-2], anButtons[anButtons.length-1]
  10582. ];
  10583. $(anStatic).removeClass( oClasses.sPageButton+" "+oClasses.sPageButtonActive+" "+oClasses.sPageButtonStaticDisabled );
  10584. $([anStatic[0], anStatic[1]]).addClass(
  10585. (iCurrentPage==1) ?
  10586. oClasses.sPageButtonStaticDisabled :
  10587. oClasses.sPageButton
  10588. );
  10589. $([anStatic[2], anStatic[3]]).addClass(
  10590. (iPages===0 || iCurrentPage===iPages || oSettings._iDisplayLength===-1) ?
  10591. oClasses.sPageButtonStaticDisabled :
  10592. oClasses.sPageButton
  10593. );
  10594. }
  10595. }
  10596. }
  10597. } );
  10598. $.extend( DataTable.ext.oSort, {
  10599. /*
  10600. * text sorting
  10601. */
  10602. "string-pre": function ( a )
  10603. {
  10604. if ( typeof a != 'string' ) {
  10605. a = (a !== null && a.toString) ? a.toString() : '';
  10606. }
  10607. return a.toLowerCase();
  10608. },
  10609. "string-asc": function ( x, y )
  10610. {
  10611. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  10612. },
  10613. "string-desc": function ( x, y )
  10614. {
  10615. return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  10616. },
  10617. /*
  10618. * html sorting (ignore html tags)
  10619. */
  10620. "html-pre": function ( a )
  10621. {
  10622. return a.replace( /<.*?>/g, "" ).toLowerCase();
  10623. },
  10624. "html-asc": function ( x, y )
  10625. {
  10626. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  10627. },
  10628. "html-desc": function ( x, y )
  10629. {
  10630. return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  10631. },
  10632. /*
  10633. * date sorting
  10634. */
  10635. "date-pre": function ( a )
  10636. {
  10637. var x = Date.parse( a );
  10638. if ( isNaN(x) || x==="" )
  10639. {
  10640. x = Date.parse( "01/01/1970 00:00:00" );
  10641. }
  10642. return x;
  10643. },
  10644. "date-asc": function ( x, y )
  10645. {
  10646. return x - y;
  10647. },
  10648. "date-desc": function ( x, y )
  10649. {
  10650. return y - x;
  10651. },
  10652. /*
  10653. * numerical sorting
  10654. */
  10655. "numeric-pre": function ( a )
  10656. {
  10657. return (a=="-" || a==="") ? 0 : a*1;
  10658. },
  10659. "numeric-asc": function ( x, y )
  10660. {
  10661. return x - y;
  10662. },
  10663. "numeric-desc": function ( x, y )
  10664. {
  10665. return y - x;
  10666. }
  10667. } );
  10668. $.extend( DataTable.ext.aTypes, [
  10669. /*
  10670. * Function: -
  10671. * Purpose: Check to see if a string is numeric
  10672. * Returns: string:'numeric' or null
  10673. * Inputs: mixed:sText - string to check
  10674. */
  10675. function ( sData )
  10676. {
  10677. /* Allow zero length strings as a number */
  10678. if ( typeof sData === 'number' )
  10679. {
  10680. return 'numeric';
  10681. }
  10682. else if ( typeof sData !== 'string' )
  10683. {
  10684. return null;
  10685. }
  10686. var sValidFirstChars = "0123456789-";
  10687. var sValidChars = "0123456789.";
  10688. var Char;
  10689. var bDecimal = false;
  10690. /* Check for a valid first char (no period and allow negatives) */
  10691. Char = sData.charAt(0);
  10692. if (sValidFirstChars.indexOf(Char) == -1)
  10693. {
  10694. return null;
  10695. }
  10696. /* Check all the other characters are valid */
  10697. for ( var i=1 ; i<sData.length ; i++ )
  10698. {
  10699. Char = sData.charAt(i);
  10700. if (sValidChars.indexOf(Char) == -1)
  10701. {
  10702. return null;
  10703. }
  10704. /* Only allowed one decimal place... */
  10705. if ( Char == "." )
  10706. {
  10707. if ( bDecimal )
  10708. {
  10709. return null;
  10710. }
  10711. bDecimal = true;
  10712. }
  10713. }
  10714. return 'numeric';
  10715. },
  10716. /*
  10717. * Function: -
  10718. * Purpose: Check to see if a string is actually a formatted date
  10719. * Returns: string:'date' or null
  10720. * Inputs: string:sText - string to check
  10721. */
  10722. function ( sData )
  10723. {
  10724. var iParse = Date.parse(sData);
  10725. if ( (iParse !== null && !isNaN(iParse)) || (typeof sData === 'string' && sData.length === 0) )
  10726. {
  10727. return 'date';
  10728. }
  10729. return null;
  10730. },
  10731. /*
  10732. * Function: -
  10733. * Purpose: Check to see if a string should be treated as an HTML string
  10734. * Returns: string:'html' or null
  10735. * Inputs: string:sText - string to check
  10736. */
  10737. function ( sData )
  10738. {
  10739. if ( typeof sData === 'string' && sData.indexOf('<') != -1 && sData.indexOf('>') != -1 )
  10740. {
  10741. return 'html';
  10742. }
  10743. return null;
  10744. }
  10745. ] );
  10746. // jQuery aliases
  10747. $.fn.DataTable = DataTable;
  10748. $.fn.dataTable = DataTable;
  10749. $.fn.dataTableSettings = DataTable.settings;
  10750. $.fn.dataTableExt = DataTable.ext;
  10751. // Information about events fired by DataTables - for documentation.
  10752. /**
  10753. * Draw event, fired whenever the table is redrawn on the page, at the same point as
  10754. * fnDrawCallback. This may be useful for binding events or performing calculations when
  10755. * the table is altered at all.
  10756. * @name DataTable#draw
  10757. * @event
  10758. * @param {event} e jQuery event object
  10759. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10760. */
  10761. /**
  10762. * Filter event, fired when the filtering applied to the table (using the build in global
  10763. * global filter, or column filters) is altered.
  10764. * @name DataTable#filter
  10765. * @event
  10766. * @param {event} e jQuery event object
  10767. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10768. */
  10769. /**
  10770. * Page change event, fired when the paging of the table is altered.
  10771. * @name DataTable#page
  10772. * @event
  10773. * @param {event} e jQuery event object
  10774. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10775. */
  10776. /**
  10777. * Sort event, fired when the sorting applied to the table is altered.
  10778. * @name DataTable#sort
  10779. * @event
  10780. * @param {event} e jQuery event object
  10781. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10782. */
  10783. /**
  10784. * DataTables initialisation complete event, fired when the table is fully drawn,
  10785. * including Ajax data loaded, if Ajax data is required.
  10786. * @name DataTable#init
  10787. * @event
  10788. * @param {event} e jQuery event object
  10789. * @param {object} oSettings DataTables settings object
  10790. * @param {object} json The JSON object request from the server - only
  10791. * present if client-side Ajax sourced data is used</li></ol>
  10792. */
  10793. /**
  10794. * State save event, fired when the table has changed state a new state save is required.
  10795. * This method allows modification of the state saving object prior to actually doing the
  10796. * save, including addition or other state properties (for plug-ins) or modification
  10797. * of a DataTables core property.
  10798. * @name DataTable#stateSaveParams
  10799. * @event
  10800. * @param {event} e jQuery event object
  10801. * @param {object} oSettings DataTables settings object
  10802. * @param {object} json The state information to be saved
  10803. */
  10804. /**
  10805. * State load event, fired when the table is loading state from the stored data, but
  10806. * prior to the settings object being modified by the saved state - allowing modification
  10807. * of the saved state is required or loading of state for a plug-in.
  10808. * @name DataTable#stateLoadParams
  10809. * @event
  10810. * @param {event} e jQuery event object
  10811. * @param {object} oSettings DataTables settings object
  10812. * @param {object} json The saved state information
  10813. */
  10814. /**
  10815. * State loaded event, fired when state has been loaded from stored data and the settings
  10816. * object has been modified by the loaded data.
  10817. * @name DataTable#stateLoaded
  10818. * @event
  10819. * @param {event} e jQuery event object
  10820. * @param {object} oSettings DataTables settings object
  10821. * @param {object} json The saved state information
  10822. */
  10823. /**
  10824. * Processing event, fired when DataTables is doing some kind of processing (be it,
  10825. * sort, filter or anything else). Can be used to indicate to the end user that
  10826. * there is something happening, or that something has finished.
  10827. * @name DataTable#processing
  10828. * @event
  10829. * @param {event} e jQuery event object
  10830. * @param {object} oSettings DataTables settings object
  10831. * @param {boolean} bShow Flag for if DataTables is doing processing or not
  10832. */
  10833. /**
  10834. * Ajax (XHR) event, fired whenever an Ajax request is completed from a request to
  10835. * made to the server for new data (note that this trigger is called in fnServerData,
  10836. * if you override fnServerData and which to use this event, you need to trigger it in
  10837. * you success function).
  10838. * @name DataTable#xhr
  10839. * @event
  10840. * @param {event} e jQuery event object
  10841. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10842. * @param {object} json JSON returned from the server
  10843. */
  10844. /**
  10845. * Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing
  10846. * the bDestroy:true parameter in the initialisation object. This can be used to remove
  10847. * bound events, added DOM nodes, etc.
  10848. * @name DataTable#destroy
  10849. * @event
  10850. * @param {event} e jQuery event object
  10851. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10852. */
  10853. }));
  10854. }(window, document));