jquery.dataTables.js 420 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272
  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. define(['jquery'], factory);
  30. }
  31. /* Define using browser globals otherwise
  32. * Prevent multiple instantiations if the script is loaded twice
  33. */
  34. else if (jQuery && !jQuery.fn.dataTable) {
  35. factory(jQuery);
  36. }
  37. }
  38. (/** @lends <global> */function ($) {
  39. "use strict";
  40. /**
  41. * DataTables is a plug-in for the jQuery Javascript library. It is a
  42. * highly flexible tool, based upon the foundations of progressive
  43. * enhancement, which will add advanced interaction controls to any
  44. * HTML table. For a full list of features please refer to
  45. * <a href="http://datatables.net">DataTables.net</a>.
  46. *
  47. * Note that the <i>DataTable</i> object is not a global variable but is
  48. * aliased to <i>jQuery.fn.DataTable</i> and <i>jQuery.fn.dataTable</i> through which
  49. * it may be accessed.
  50. *
  51. * @class
  52. * @param {object} [oInit={}] Configuration object for DataTables. Options
  53. * are defined by {@link DataTable.defaults}
  54. * @requires jQuery 1.3+
  55. *
  56. * @example
  57. * // Basic initialisation
  58. * $(document).ready( function {
  59. * $('#example').dataTable();
  60. * } );
  61. *
  62. * @example
  63. * // Initialisation with configuration options - in this case, disable
  64. * // pagination and sorting.
  65. * $(document).ready( function {
  66. * $('#example').dataTable( {
  67. * "bPaginate": false,
  68. * "bSort": false
  69. * } );
  70. * } );
  71. */
  72. var DataTable = function (oInit) {
  73. /**
  74. * Add a column to the list used for the table with default values
  75. * @param {object} oSettings dataTables settings object
  76. * @param {node} nTh The th element for this column
  77. * @memberof DataTable#oApi
  78. */
  79. function _fnAddColumn(oSettings, nTh) {
  80. var oDefaults = DataTable.defaults.columns;
  81. var iCol = oSettings.aoColumns.length;
  82. var oCol = $.extend({}, DataTable.models.oColumn, oDefaults, {
  83. "sSortingClass":oSettings.oClasses.sSortable,
  84. "sSortingClassJUI":oSettings.oClasses.sSortJUI,
  85. "nTh":nTh ? nTh : document.createElement('th'),
  86. "sTitle":oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',
  87. "aDataSort":oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
  88. "mData":oDefaults.mData ? oDefaults.oDefaults : iCol
  89. });
  90. oSettings.aoColumns.push(oCol);
  91. /* Add a column specific filter */
  92. if (oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null) {
  93. oSettings.aoPreSearchCols[ iCol ] = $.extend({}, DataTable.models.oSearch);
  94. }
  95. else {
  96. var oPre = oSettings.aoPreSearchCols[ iCol ];
  97. /* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */
  98. if (oPre.bRegex === undefined) {
  99. oPre.bRegex = true;
  100. }
  101. if (oPre.bSmart === undefined) {
  102. oPre.bSmart = true;
  103. }
  104. if (oPre.bCaseInsensitive === undefined) {
  105. oPre.bCaseInsensitive = true;
  106. }
  107. }
  108. /* Use the column options function to initialise classes etc */
  109. _fnColumnOptions(oSettings, iCol, null);
  110. }
  111. /**
  112. * Apply options for a column
  113. * @param {object} oSettings dataTables settings object
  114. * @param {int} iCol column index to consider
  115. * @param {object} oOptions object with sType, bVisible and bSearchable etc
  116. * @memberof DataTable#oApi
  117. */
  118. function _fnColumnOptions(oSettings, iCol, oOptions) {
  119. var oCol = oSettings.aoColumns[ iCol ];
  120. /* User specified column options */
  121. if (oOptions !== undefined && oOptions !== null) {
  122. /* Backwards compatibility for mDataProp */
  123. if (oOptions.mDataProp && !oOptions.mData) {
  124. oOptions.mData = oOptions.mDataProp;
  125. }
  126. if (oOptions.sType !== undefined) {
  127. oCol.sType = oOptions.sType;
  128. oCol._bAutoType = false;
  129. }
  130. $.extend(oCol, oOptions);
  131. _fnMap(oCol, oOptions, "sWidth", "sWidthOrig");
  132. /* iDataSort to be applied (backwards compatibility), but aDataSort will take
  133. * priority if defined
  134. */
  135. if (oOptions.iDataSort !== undefined) {
  136. oCol.aDataSort = [ oOptions.iDataSort ];
  137. }
  138. _fnMap(oCol, oOptions, "aDataSort");
  139. }
  140. /* Cache the data get and set functions for speed */
  141. var mRender = oCol.mRender ? _fnGetObjectDataFn(oCol.mRender) : null;
  142. var mData = _fnGetObjectDataFn(oCol.mData);
  143. oCol.fnGetData = function (oData, sSpecific) {
  144. var innerData = mData(oData, sSpecific);
  145. if (oCol.mRender && (sSpecific && sSpecific !== '')) {
  146. return mRender(innerData, sSpecific, oData);
  147. }
  148. return innerData;
  149. };
  150. oCol.fnSetData = _fnSetObjectDataFn(oCol.mData);
  151. /* Feature sorting overrides column specific when off */
  152. if (!oSettings.oFeatures.bSort) {
  153. oCol.bSortable = false;
  154. }
  155. /* Check that the class assignment is correct for sorting */
  156. if (!oCol.bSortable ||
  157. ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1)) {
  158. oCol.sSortingClass = oSettings.oClasses.sSortableNone;
  159. oCol.sSortingClassJUI = "";
  160. }
  161. else if ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) {
  162. oCol.sSortingClass = oSettings.oClasses.sSortable;
  163. oCol.sSortingClassJUI = oSettings.oClasses.sSortJUI;
  164. }
  165. else if ($.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1) {
  166. oCol.sSortingClass = oSettings.oClasses.sSortableAsc;
  167. oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed;
  168. }
  169. else if ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1) {
  170. oCol.sSortingClass = oSettings.oClasses.sSortableDesc;
  171. oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed;
  172. }
  173. }
  174. /**
  175. * Adjust the table column widths for new data. Note: you would probably want to
  176. * do a redraw after calling this function!
  177. * @param {object} oSettings dataTables settings object
  178. * @memberof DataTable#oApi
  179. */
  180. function _fnAdjustColumnSizing(oSettings) {
  181. /* Not interested in doing column width calculation if auto-width is disabled */
  182. if (oSettings.oFeatures.bAutoWidth === false) {
  183. return false;
  184. }
  185. _fnCalculateColumnWidths(oSettings);
  186. for (var i = 0 , iLen = oSettings.aoColumns.length; i < iLen; i++) {
  187. oSettings.aoColumns[i].nTh.style.width = oSettings.aoColumns[i].sWidth;
  188. }
  189. }
  190. /**
  191. * Covert the index of a visible column to the index in the data array (take account
  192. * of hidden columns)
  193. * @param {object} oSettings dataTables settings object
  194. * @param {int} iMatch Visible column index to lookup
  195. * @returns {int} i the data index
  196. * @memberof DataTable#oApi
  197. */
  198. function _fnVisibleToColumnIndex(oSettings, iMatch) {
  199. var aiVis = _fnGetColumns(oSettings, 'bVisible');
  200. return typeof aiVis[iMatch] === 'number' ?
  201. aiVis[iMatch] :
  202. null;
  203. }
  204. /**
  205. * Covert the index of an index in the data array and convert it to the visible
  206. * column index (take account of hidden columns)
  207. * @param {int} iMatch Column index to lookup
  208. * @param {object} oSettings dataTables settings object
  209. * @returns {int} i the data index
  210. * @memberof DataTable#oApi
  211. */
  212. function _fnColumnIndexToVisible(oSettings, iMatch) {
  213. var aiVis = _fnGetColumns(oSettings, 'bVisible');
  214. var iPos = $.inArray(iMatch, aiVis);
  215. return iPos !== -1 ? iPos : null;
  216. }
  217. /**
  218. * Get the number of visible columns
  219. * @param {object} oSettings dataTables settings object
  220. * @returns {int} i the number of visible columns
  221. * @memberof DataTable#oApi
  222. */
  223. function _fnVisbleColumns(oSettings) {
  224. return _fnGetColumns(oSettings, 'bVisible').length;
  225. }
  226. /**
  227. * Get an array of column indexes that match a given property
  228. * @param {object} oSettings dataTables settings object
  229. * @param {string} sParam Parameter in aoColumns to look for - typically
  230. * bVisible or bSearchable
  231. * @returns {array} Array of indexes with matched properties
  232. * @memberof DataTable#oApi
  233. */
  234. function _fnGetColumns(oSettings, sParam) {
  235. var a = [];
  236. $.map(oSettings.aoColumns, function (val, i) {
  237. if (val[sParam]) {
  238. a.push(i);
  239. }
  240. });
  241. return a;
  242. }
  243. /**
  244. * Get the sort type based on an input string
  245. * @param {string} sData data we wish to know the type of
  246. * @returns {string} type (defaults to 'string' if no type can be detected)
  247. * @memberof DataTable#oApi
  248. */
  249. function _fnDetectType(sData) {
  250. var aTypes = DataTable.ext.aTypes;
  251. var iLen = aTypes.length;
  252. for (var i = 0; i < iLen; i++) {
  253. var sType = aTypes[i](sData);
  254. if (sType !== null) {
  255. return sType;
  256. }
  257. }
  258. return 'string';
  259. }
  260. /**
  261. * Figure out how to reorder a display list
  262. * @param {object} oSettings dataTables settings object
  263. * @returns array {int} aiReturn index list for reordering
  264. * @memberof DataTable#oApi
  265. */
  266. function _fnReOrderIndex(oSettings, sColumns) {
  267. var aColumns = sColumns.split(',');
  268. var aiReturn = [];
  269. for (var i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  270. for (var j = 0; j < iLen; j++) {
  271. if (oSettings.aoColumns[i].sName == aColumns[j]) {
  272. aiReturn.push(j);
  273. break;
  274. }
  275. }
  276. }
  277. return aiReturn;
  278. }
  279. /**
  280. * Get the column ordering that DataTables expects
  281. * @param {object} oSettings dataTables settings object
  282. * @returns {string} comma separated list of names
  283. * @memberof DataTable#oApi
  284. */
  285. function _fnColumnOrdering(oSettings) {
  286. var sNames = '';
  287. for (var i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  288. sNames += oSettings.aoColumns[i].sName + ',';
  289. }
  290. if (sNames.length == iLen) {
  291. return "";
  292. }
  293. return sNames.slice(0, -1);
  294. }
  295. /**
  296. * Take the column definitions and static columns arrays and calculate how
  297. * they relate to column indexes. The callback function will then apply the
  298. * definition found for a column to a suitable configuration object.
  299. * @param {object} oSettings dataTables settings object
  300. * @param {array} aoColDefs The aoColumnDefs array that is to be applied
  301. * @param {array} aoCols The aoColumns array that defines columns individually
  302. * @param {function} fn Callback function - takes two parameters, the calculated
  303. * column index and the definition for that column.
  304. * @memberof DataTable#oApi
  305. */
  306. function _fnApplyColumnDefs(oSettings, aoColDefs, aoCols, fn) {
  307. var i, iLen, j, jLen, k, kLen;
  308. // Column definitions with aTargets
  309. if (aoColDefs) {
  310. /* Loop over the definitions array - loop in reverse so first instance has priority */
  311. for (i = aoColDefs.length - 1; i >= 0; i--) {
  312. /* Each definition can target multiple columns, as it is an array */
  313. var aTargets = aoColDefs[i].aTargets;
  314. if (!$.isArray(aTargets)) {
  315. _fnLog(oSettings, 1, 'aTargets must be an array of targets, not a ' + (typeof aTargets));
  316. }
  317. for (j = 0, jLen = aTargets.length; j < jLen; j++) {
  318. if (typeof aTargets[j] === 'number' && aTargets[j] >= 0) {
  319. /* Add columns that we don't yet know about */
  320. while (oSettings.aoColumns.length <= aTargets[j]) {
  321. _fnAddColumn(oSettings);
  322. }
  323. /* Integer, basic index */
  324. fn(aTargets[j], aoColDefs[i]);
  325. }
  326. else if (typeof aTargets[j] === 'number' && aTargets[j] < 0) {
  327. /* Negative integer, right to left column counting */
  328. fn(oSettings.aoColumns.length + aTargets[j], aoColDefs[i]);
  329. }
  330. else if (typeof aTargets[j] === 'string') {
  331. /* Class name matching on TH element */
  332. for (k = 0, kLen = oSettings.aoColumns.length; k < kLen; k++) {
  333. if (aTargets[j] == "_all" ||
  334. $(oSettings.aoColumns[k].nTh).hasClass(aTargets[j])) {
  335. fn(k, aoColDefs[i]);
  336. }
  337. }
  338. }
  339. }
  340. }
  341. }
  342. // Statically defined columns array
  343. if (aoCols) {
  344. for (i = 0, iLen = aoCols.length; i < iLen; i++) {
  345. fn(i, aoCols[i]);
  346. }
  347. }
  348. }
  349. /**
  350. * Add a data array to the table, creating DOM node etc. This is the parallel to
  351. * _fnGatherData, but for adding rows from a Javascript source, rather than a
  352. * DOM source.
  353. * @param {object} oSettings dataTables settings object
  354. * @param {array} aData data array to be added
  355. * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
  356. * @memberof DataTable#oApi
  357. */
  358. function _fnAddData(oSettings, aDataSupplied) {
  359. var oCol;
  360. /* Take an independent copy of the data source so we can bash it about as we wish */
  361. var aDataIn = ($.isArray(aDataSupplied)) ?
  362. aDataSupplied.slice() :
  363. $.extend(true, {}, aDataSupplied);
  364. /* Create the object for storing information about this new row */
  365. var iRow = oSettings.aoData.length;
  366. var oData = $.extend(true, {}, DataTable.models.oRow);
  367. oData._aData = aDataIn;
  368. oSettings.aoData.push(oData);
  369. /* Create the cells */
  370. var nTd, sThisType;
  371. for (var i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  372. oCol = oSettings.aoColumns[i];
  373. /* Use rendered data for filtering / sorting */
  374. if (typeof oCol.fnRender === 'function' && oCol.bUseRendered && oCol.mData !== null) {
  375. _fnSetCellData(oSettings, iRow, i, _fnRender(oSettings, iRow, i));
  376. }
  377. else {
  378. _fnSetCellData(oSettings, iRow, i, _fnGetCellData(oSettings, iRow, i));
  379. }
  380. /* See if we should auto-detect the column type */
  381. if (oCol._bAutoType && oCol.sType != 'string') {
  382. /* Attempt to auto detect the type - same as _fnGatherData() */
  383. var sVarType = _fnGetCellData(oSettings, iRow, i, 'type');
  384. if (sVarType !== null && sVarType !== '') {
  385. sThisType = _fnDetectType(sVarType);
  386. if (oCol.sType === null) {
  387. oCol.sType = sThisType;
  388. }
  389. else if (oCol.sType != sThisType && oCol.sType != "html") {
  390. /* String is always the 'fallback' option */
  391. oCol.sType = 'string';
  392. }
  393. }
  394. }
  395. }
  396. /* Add to the display array */
  397. oSettings.aiDisplayMaster.push(iRow);
  398. /* Create the DOM information */
  399. if (!oSettings.oFeatures.bDeferRender) {
  400. _fnCreateTr(oSettings, iRow);
  401. }
  402. return iRow;
  403. }
  404. /**
  405. * Read in the data from the target table from the DOM
  406. * @param {object} oSettings dataTables settings object
  407. * @memberof DataTable#oApi
  408. */
  409. function _fnGatherData(oSettings) {
  410. var iLoop, i, iLen, j, jLen, jInner,
  411. nTds, nTrs, nTd, nTr, aLocalData, iThisIndex,
  412. iRow, iRows, iColumn, iColumns, sNodeName,
  413. oCol, oData;
  414. /*
  415. * Process by row first
  416. * Add the data object for the whole table - storing the tr node. Note - no point in getting
  417. * DOM based data if we are going to go and replace it with Ajax source data.
  418. */
  419. if (oSettings.bDeferLoading || oSettings.sAjaxSource === null) {
  420. nTr = oSettings.nTBody.firstChild;
  421. while (nTr) {
  422. if (nTr.nodeName.toUpperCase() == "TR") {
  423. iThisIndex = oSettings.aoData.length;
  424. nTr._DT_RowIndex = iThisIndex;
  425. oSettings.aoData.push($.extend(true, {}, DataTable.models.oRow, {
  426. "nTr":nTr
  427. }));
  428. oSettings.aiDisplayMaster.push(iThisIndex);
  429. nTd = nTr.firstChild;
  430. jInner = 0;
  431. while (nTd) {
  432. sNodeName = nTd.nodeName.toUpperCase();
  433. if (sNodeName == "TD" || sNodeName == "TH") {
  434. _fnSetCellData(oSettings, iThisIndex, jInner, $.trim(nTd.innerHTML));
  435. jInner++;
  436. }
  437. nTd = nTd.nextSibling;
  438. }
  439. }
  440. nTr = nTr.nextSibling;
  441. }
  442. }
  443. /* Gather in the TD elements of the Table - note that this is basically the same as
  444. * fnGetTdNodes, but that function takes account of hidden columns, which we haven't yet
  445. * setup!
  446. */
  447. nTrs = _fnGetTrNodes(oSettings);
  448. nTds = [];
  449. for (i = 0, iLen = nTrs.length; i < iLen; i++) {
  450. nTd = nTrs[i].firstChild;
  451. while (nTd) {
  452. sNodeName = nTd.nodeName.toUpperCase();
  453. if (sNodeName == "TD" || sNodeName == "TH") {
  454. nTds.push(nTd);
  455. }
  456. nTd = nTd.nextSibling;
  457. }
  458. }
  459. /* Now process by column */
  460. for (iColumn = 0, iColumns = oSettings.aoColumns.length; iColumn < iColumns; iColumn++) {
  461. oCol = oSettings.aoColumns[iColumn];
  462. /* Get the title of the column - unless there is a user set one */
  463. if (oCol.sTitle === null) {
  464. oCol.sTitle = oCol.nTh.innerHTML;
  465. }
  466. var
  467. bAutoType = oCol._bAutoType,
  468. bRender = typeof oCol.fnRender === 'function',
  469. bClass = oCol.sClass !== null,
  470. bVisible = oCol.bVisible,
  471. nCell, sThisType, sRendered, sValType;
  472. /* A single loop to rule them all (and be more efficient) */
  473. if (bAutoType || bRender || bClass || !bVisible) {
  474. for (iRow = 0, iRows = oSettings.aoData.length; iRow < iRows; iRow++) {
  475. oData = oSettings.aoData[iRow];
  476. nCell = nTds[ (iRow * iColumns) + iColumn ];
  477. /* Type detection */
  478. if (bAutoType && oCol.sType != 'string') {
  479. sValType = _fnGetCellData(oSettings, iRow, iColumn, 'type');
  480. if (sValType !== '') {
  481. sThisType = _fnDetectType(sValType);
  482. if (oCol.sType === null) {
  483. oCol.sType = sThisType;
  484. }
  485. else if (oCol.sType != sThisType &&
  486. oCol.sType != "html") {
  487. /* String is always the 'fallback' option */
  488. oCol.sType = 'string';
  489. }
  490. }
  491. }
  492. if (oCol.mRender) {
  493. // mRender has been defined, so we need to get the value and set it
  494. nCell.innerHTML = _fnGetCellData(oSettings, iRow, iColumn, 'display');
  495. }
  496. else if (oCol.mData !== iColumn) {
  497. // If mData is not the same as the column number, then we need to
  498. // get the dev set value. If it is the column, no point in wasting
  499. // time setting the value that is already there!
  500. nCell.innerHTML = _fnGetCellData(oSettings, iRow, iColumn, 'display');
  501. }
  502. /* Rendering */
  503. if (bRender) {
  504. sRendered = _fnRender(oSettings, iRow, iColumn);
  505. nCell.innerHTML = sRendered;
  506. if (oCol.bUseRendered) {
  507. /* Use the rendered data for filtering / sorting */
  508. _fnSetCellData(oSettings, iRow, iColumn, sRendered);
  509. }
  510. }
  511. /* Classes */
  512. if (bClass) {
  513. nCell.className += ' ' + oCol.sClass;
  514. }
  515. /* Column visibility */
  516. if (!bVisible) {
  517. oData._anHidden[iColumn] = nCell;
  518. nCell.parentNode.removeChild(nCell);
  519. }
  520. else {
  521. oData._anHidden[iColumn] = null;
  522. }
  523. if (oCol.fnCreatedCell) {
  524. oCol.fnCreatedCell.call(oSettings.oInstance,
  525. nCell, _fnGetCellData(oSettings, iRow, iColumn, 'display'), oData._aData, iRow, iColumn
  526. );
  527. }
  528. }
  529. }
  530. }
  531. /* Row created callbacks */
  532. if (oSettings.aoRowCreatedCallback.length !== 0) {
  533. for (i = 0, iLen = oSettings.aoData.length; i < iLen; i++) {
  534. oData = oSettings.aoData[i];
  535. _fnCallbackFire(oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, i]);
  536. }
  537. }
  538. }
  539. /**
  540. * Take a TR element and convert it to an index in aoData
  541. * @param {object} oSettings dataTables settings object
  542. * @param {node} n the TR element to find
  543. * @returns {int} index if the node is found, null if not
  544. * @memberof DataTable#oApi
  545. */
  546. function _fnNodeToDataIndex(oSettings, n) {
  547. return (n._DT_RowIndex !== undefined) ? n._DT_RowIndex : null;
  548. }
  549. /**
  550. * Take a TD element and convert it into a column data index (not the visible index)
  551. * @param {object} oSettings dataTables settings object
  552. * @param {int} iRow The row number the TD/TH can be found in
  553. * @param {node} n The TD/TH element to find
  554. * @returns {int} index if the node is found, -1 if not
  555. * @memberof DataTable#oApi
  556. */
  557. function _fnNodeToColumnIndex(oSettings, iRow, n) {
  558. var anCells = _fnGetTdNodes(oSettings, iRow);
  559. for (var i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  560. if (anCells[i] === n) {
  561. return i;
  562. }
  563. }
  564. return -1;
  565. }
  566. /**
  567. * Get an array of data for a given row from the internal data cache
  568. * @param {object} oSettings dataTables settings object
  569. * @param {int} iRow aoData row id
  570. * @param {string} sSpecific data get type ('type' 'filter' 'sort')
  571. * @param {array} aiColumns Array of column indexes to get data from
  572. * @returns {array} Data array
  573. * @memberof DataTable#oApi
  574. */
  575. function _fnGetRowData(oSettings, iRow, sSpecific, aiColumns) {
  576. var out = [];
  577. for (var i = 0, iLen = aiColumns.length; i < iLen; i++) {
  578. out.push(_fnGetCellData(oSettings, iRow, aiColumns[i], sSpecific));
  579. }
  580. return out;
  581. }
  582. /**
  583. * Get the data for a given cell from the internal cache, taking into account data mapping
  584. * @param {object} oSettings dataTables settings object
  585. * @param {int} iRow aoData row id
  586. * @param {int} iCol Column index
  587. * @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort')
  588. * @returns {*} Cell data
  589. * @memberof DataTable#oApi
  590. */
  591. function _fnGetCellData(oSettings, iRow, iCol, sSpecific) {
  592. var sData;
  593. var oCol = oSettings.aoColumns[iCol];
  594. var oData = oSettings.aoData[iRow]._aData;
  595. if ((sData = oCol.fnGetData(oData, sSpecific)) === undefined) {
  596. if (oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null) {
  597. _fnLog(oSettings, 0, "Requested unknown parameter " +
  598. (typeof oCol.mData == 'function' ? '{mData function}' : "'" + oCol.mData + "'") +
  599. " from the data source for row " + iRow);
  600. oSettings.iDrawError = oSettings.iDraw;
  601. }
  602. return oCol.sDefaultContent;
  603. }
  604. /* When the data source is null, we can use default column data */
  605. if (sData === null && oCol.sDefaultContent !== null) {
  606. sData = oCol.sDefaultContent;
  607. }
  608. else if (typeof sData === 'function') {
  609. /* If the data source is a function, then we run it and use the return */
  610. return sData();
  611. }
  612. if (sSpecific == 'display' && sData === null) {
  613. return '';
  614. }
  615. return sData;
  616. }
  617. /**
  618. * Set the value for a specific cell, into the internal data cache
  619. * @param {object} oSettings dataTables settings object
  620. * @param {int} iRow aoData row id
  621. * @param {int} iCol Column index
  622. * @param {*} val Value to set
  623. * @memberof DataTable#oApi
  624. */
  625. function _fnSetCellData(oSettings, iRow, iCol, val) {
  626. var oCol = oSettings.aoColumns[iCol];
  627. var oData = oSettings.aoData[iRow]._aData;
  628. oCol.fnSetData(oData, val);
  629. }
  630. // Private variable that is used to match array syntax in the data property object
  631. var __reArray = /\[.*?\]$/;
  632. /**
  633. * Return a function that can be used to get data from a source object, taking
  634. * into account the ability to use nested objects as a source
  635. * @param {string|int|function} mSource The data source for the object
  636. * @returns {function} Data get function
  637. * @memberof DataTable#oApi
  638. */
  639. function _fnGetObjectDataFn(mSource) {
  640. if (mSource === null) {
  641. /* Give an empty string for rendering / sorting etc */
  642. return function (data, type) {
  643. return null;
  644. };
  645. }
  646. else if (typeof mSource === 'function') {
  647. return function (data, type, extra) {
  648. return mSource(data, type, extra);
  649. };
  650. }
  651. else if (typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1)) {
  652. /* If there is a . in the source string then the data source is in a
  653. * nested object so we loop over the data for each level to get the next
  654. * level down. On each loop we test for undefined, and if found immediately
  655. * return. This allows entire objects to be missing and sDefaultContent to
  656. * be used if defined, rather than throwing an error
  657. */
  658. var fetchData = function (data, type, src) {
  659. var a = src.split('.');
  660. var arrayNotation, out, innerSrc;
  661. if (src !== "") {
  662. for (var i = 0, iLen = a.length; i < iLen; i++) {
  663. // Check if we are dealing with an array notation request
  664. arrayNotation = a[i].match(__reArray);
  665. if (arrayNotation) {
  666. a[i] = a[i].replace(__reArray, '');
  667. // Condition allows simply [] to be passed in
  668. if (a[i] !== "") {
  669. data = data[ a[i] ];
  670. }
  671. out = [];
  672. // Get the remainder of the nested object to get
  673. a.splice(0, i + 1);
  674. innerSrc = a.join('.');
  675. // Traverse each entry in the array getting the properties requested
  676. for (var j = 0, jLen = data.length; j < jLen; j++) {
  677. out.push(fetchData(data[j], type, innerSrc));
  678. }
  679. // If a string is given in between the array notation indicators, that
  680. // is used to join the strings together, otherwise an array is returned
  681. var join = arrayNotation[0].substring(1, arrayNotation[0].length - 1);
  682. data = (join === "") ? out : out.join(join);
  683. // The inner call to fetchData has already traversed through the remainder
  684. // of the source requested, so we exit from the loop
  685. break;
  686. }
  687. if (data === null || data[ a[i] ] === undefined) {
  688. return undefined;
  689. }
  690. data = data[ a[i] ];
  691. }
  692. }
  693. return data;
  694. };
  695. return function (data, type) {
  696. return fetchData(data, type, mSource);
  697. };
  698. }
  699. else {
  700. /* Array or flat object mapping */
  701. return function (data, type) {
  702. return data[mSource];
  703. };
  704. }
  705. }
  706. /**
  707. * Return a function that can be used to set data from a source object, taking
  708. * into account the ability to use nested objects as a source
  709. * @param {string|int|function} mSource The data source for the object
  710. * @returns {function} Data set function
  711. * @memberof DataTable#oApi
  712. */
  713. function _fnSetObjectDataFn(mSource) {
  714. if (mSource === null) {
  715. /* Nothing to do when the data source is null */
  716. return function (data, val) {
  717. };
  718. }
  719. else if (typeof mSource === 'function') {
  720. return function (data, val) {
  721. mSource(data, 'set', val);
  722. };
  723. }
  724. else if (typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1)) {
  725. /* Like the get, we need to get data from a nested object */
  726. var setData = function (data, val, src) {
  727. var a = src.split('.'), b;
  728. var arrayNotation, o, innerSrc;
  729. for (var i = 0, iLen = a.length - 1; i < iLen; i++) {
  730. // Check if we are dealing with an array notation request
  731. arrayNotation = a[i].match(__reArray);
  732. if (arrayNotation) {
  733. a[i] = a[i].replace(__reArray, '');
  734. data[ a[i] ] = [];
  735. // Get the remainder of the nested object to set so we can recurse
  736. b = a.slice();
  737. b.splice(0, i + 1);
  738. innerSrc = b.join('.');
  739. // Traverse each entry in the array setting the properties requested
  740. for (var j = 0, jLen = val.length; j < jLen; j++) {
  741. o = {};
  742. setData(o, val[j], innerSrc);
  743. data[ a[i] ].push(o);
  744. }
  745. // The inner call to setData has already traversed through the remainder
  746. // of the source and has set the data, thus we can exit here
  747. return;
  748. }
  749. // If the nested object doesn't currently exist - since we are
  750. // trying to set the value - create it
  751. if (data[ a[i] ] === null || data[ a[i] ] === undefined) {
  752. data[ a[i] ] = {};
  753. }
  754. data = data[ a[i] ];
  755. }
  756. // If array notation is used, we just want to strip it and use the property name
  757. // and assign the value. If it isn't used, then we get the result we want anyway
  758. data[ a[a.length - 1].replace(__reArray, '') ] = val;
  759. };
  760. return function (data, val) {
  761. return setData(data, val, mSource);
  762. };
  763. }
  764. else {
  765. /* Array or flat object mapping */
  766. return function (data, val) {
  767. data[mSource] = val;
  768. };
  769. }
  770. }
  771. /**
  772. * Return an array with the full table data
  773. * @param {object} oSettings dataTables settings object
  774. * @returns array {array} aData Master data array
  775. * @memberof DataTable#oApi
  776. */
  777. function _fnGetDataMaster(oSettings) {
  778. var aData = [];
  779. var iLen = oSettings.aoData.length;
  780. for (var i = 0; i < iLen; i++) {
  781. aData.push(oSettings.aoData[i]._aData);
  782. }
  783. return aData;
  784. }
  785. /**
  786. * Nuke the table
  787. * @param {object} oSettings dataTables settings object
  788. * @memberof DataTable#oApi
  789. */
  790. function _fnClearTable(oSettings) {
  791. oSettings.aoData.splice(0, oSettings.aoData.length);
  792. oSettings.aiDisplayMaster.splice(0, oSettings.aiDisplayMaster.length);
  793. oSettings.aiDisplay.splice(0, oSettings.aiDisplay.length);
  794. _fnCalculateEnd(oSettings);
  795. }
  796. /**
  797. * Take an array of integers (index array) and remove a target integer (value - not
  798. * the key!)
  799. * @param {array} a Index array to target
  800. * @param {int} iTarget value to find
  801. * @memberof DataTable#oApi
  802. */
  803. function _fnDeleteIndex(a, iTarget) {
  804. var iTargetIndex = -1;
  805. for (var i = 0, iLen = a.length; i < iLen; i++) {
  806. if (a[i] == iTarget) {
  807. iTargetIndex = i;
  808. }
  809. else if (a[i] > iTarget) {
  810. a[i]--;
  811. }
  812. }
  813. if (iTargetIndex != -1) {
  814. a.splice(iTargetIndex, 1);
  815. }
  816. }
  817. /**
  818. * Call the developer defined fnRender function for a given cell (row/column) with
  819. * the required parameters and return the result.
  820. * @param {object} oSettings dataTables settings object
  821. * @param {int} iRow aoData index for the row
  822. * @param {int} iCol aoColumns index for the column
  823. * @returns {*} Return of the developer's fnRender function
  824. * @memberof DataTable#oApi
  825. */
  826. function _fnRender(oSettings, iRow, iCol) {
  827. var oCol = oSettings.aoColumns[iCol];
  828. return oCol.fnRender({
  829. "iDataRow":iRow,
  830. "iDataColumn":iCol,
  831. "oSettings":oSettings,
  832. "aData":oSettings.aoData[iRow]._aData,
  833. "mDataProp":oCol.mData
  834. }, _fnGetCellData(oSettings, iRow, iCol, 'display'));
  835. }
  836. /**
  837. * Create a new TR element (and it's TD children) for a row
  838. * @param {object} oSettings dataTables settings object
  839. * @param {int} iRow Row to consider
  840. * @memberof DataTable#oApi
  841. */
  842. function _fnCreateTr(oSettings, iRow) {
  843. var oData = oSettings.aoData[iRow];
  844. var nTd;
  845. if (oData.nTr === null) {
  846. oData.nTr = document.createElement('tr');
  847. /* Use a private property on the node to allow reserve mapping from the node
  848. * to the aoData array for fast look up
  849. */
  850. oData.nTr._DT_RowIndex = iRow;
  851. /* Special parameters can be given by the data source to be used on the row */
  852. if (oData._aData.DT_RowId) {
  853. oData.nTr.id = oData._aData.DT_RowId;
  854. }
  855. if (oData._aData.DT_RowClass) {
  856. oData.nTr.className = oData._aData.DT_RowClass;
  857. }
  858. /* Process each column */
  859. for (var i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  860. var oCol = oSettings.aoColumns[i];
  861. nTd = document.createElement(oCol.sCellType);
  862. /* Render if needed - if bUseRendered is true then we already have the rendered
  863. * value in the data source - so can just use that
  864. */
  865. nTd.innerHTML = (typeof oCol.fnRender === 'function' && (!oCol.bUseRendered || oCol.mData === null)) ?
  866. _fnRender(oSettings, iRow, i) :
  867. _fnGetCellData(oSettings, iRow, i, 'display');
  868. /* Add user defined class */
  869. if (oCol.sClass !== null) {
  870. nTd.className = oCol.sClass;
  871. }
  872. if (oCol.bVisible) {
  873. oData.nTr.appendChild(nTd);
  874. oData._anHidden[i] = null;
  875. }
  876. else {
  877. oData._anHidden[i] = nTd;
  878. }
  879. if (oCol.fnCreatedCell) {
  880. oCol.fnCreatedCell.call(oSettings.oInstance,
  881. nTd, _fnGetCellData(oSettings, iRow, i, 'display'), oData._aData, iRow, i
  882. );
  883. }
  884. }
  885. _fnCallbackFire(oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, iRow]);
  886. }
  887. }
  888. /**
  889. * Create the HTML header for the table
  890. * @param {object} oSettings dataTables settings object
  891. * @memberof DataTable#oApi
  892. */
  893. function _fnBuildHead(oSettings) {
  894. var i, nTh, iLen, j, jLen;
  895. var iThs = $('th, td', oSettings.nTHead).length;
  896. var iCorrector = 0;
  897. var jqChildren;
  898. /* If there is a header in place - then use it - otherwise it's going to get nuked... */
  899. if (iThs !== 0) {
  900. /* We've got a thead from the DOM, so remove hidden columns and apply width to vis cols */
  901. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  902. nTh = oSettings.aoColumns[i].nTh;
  903. nTh.setAttribute('role', 'columnheader');
  904. if (oSettings.aoColumns[i].bSortable) {
  905. nTh.setAttribute('tabindex', oSettings.iTabIndex);
  906. nTh.setAttribute('aria-controls', oSettings.sTableId);
  907. }
  908. if (oSettings.aoColumns[i].sClass !== null) {
  909. $(nTh).addClass(oSettings.aoColumns[i].sClass);
  910. }
  911. /* Set the title of the column if it is user defined (not what was auto detected) */
  912. if (oSettings.aoColumns[i].sTitle != nTh.innerHTML) {
  913. nTh.innerHTML = oSettings.aoColumns[i].sTitle;
  914. }
  915. }
  916. }
  917. else {
  918. /* We don't have a header in the DOM - so we are going to have to create one */
  919. var nTr = document.createElement("tr");
  920. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  921. nTh = oSettings.aoColumns[i].nTh;
  922. nTh.innerHTML = oSettings.aoColumns[i].sTitle;
  923. nTh.setAttribute('tabindex', '0');
  924. if (oSettings.aoColumns[i].sClass !== null) {
  925. $(nTh).addClass(oSettings.aoColumns[i].sClass);
  926. }
  927. nTr.appendChild(nTh);
  928. }
  929. $(oSettings.nTHead).html('')[0].appendChild(nTr);
  930. _fnDetectHeader(oSettings.aoHeader, oSettings.nTHead);
  931. }
  932. /* ARIA role for the rows */
  933. $(oSettings.nTHead).children('tr').attr('role', 'row');
  934. /* Add the extra markup needed by jQuery UI's themes */
  935. if (oSettings.bJUI) {
  936. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  937. nTh = oSettings.aoColumns[i].nTh;
  938. var nDiv = document.createElement('div');
  939. nDiv.className = oSettings.oClasses.sSortJUIWrapper;
  940. $(nTh).contents().appendTo(nDiv);
  941. var nSpan = document.createElement('span');
  942. nSpan.className = oSettings.oClasses.sSortIcon;
  943. nDiv.appendChild(nSpan);
  944. nTh.appendChild(nDiv);
  945. }
  946. }
  947. if (oSettings.oFeatures.bSort) {
  948. for (i = 0; i < oSettings.aoColumns.length; i++) {
  949. if (oSettings.aoColumns[i].bSortable !== false) {
  950. _fnSortAttachListener(oSettings, oSettings.aoColumns[i].nTh, i);
  951. }
  952. else {
  953. $(oSettings.aoColumns[i].nTh).addClass(oSettings.oClasses.sSortableNone);
  954. }
  955. }
  956. }
  957. /* Deal with the footer - add classes if required */
  958. if (oSettings.oClasses.sFooterTH !== "") {
  959. $(oSettings.nTFoot).children('tr').children('th').addClass(oSettings.oClasses.sFooterTH);
  960. }
  961. /* Cache the footer elements */
  962. if (oSettings.nTFoot !== null) {
  963. var anCells = _fnGetUniqueThs(oSettings, null, oSettings.aoFooter);
  964. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  965. if (anCells[i]) {
  966. oSettings.aoColumns[i].nTf = anCells[i];
  967. if (oSettings.aoColumns[i].sClass) {
  968. $(anCells[i]).addClass(oSettings.aoColumns[i].sClass);
  969. }
  970. }
  971. }
  972. }
  973. }
  974. /**
  975. * Draw the header (or footer) element based on the column visibility states. The
  976. * methodology here is to use the layout array from _fnDetectHeader, modified for
  977. * the instantaneous column visibility, to construct the new layout. The grid is
  978. * traversed over cell at a time in a rows x columns grid fashion, although each
  979. * cell insert can cover multiple elements in the grid - which is tracks using the
  980. * aApplied array. Cell inserts in the grid will only occur where there isn't
  981. * already a cell in that position.
  982. * @param {object} oSettings dataTables settings object
  983. * @param array {objects} aoSource Layout array from _fnDetectHeader
  984. * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
  985. * @memberof DataTable#oApi
  986. */
  987. function _fnDrawHead(oSettings, aoSource, bIncludeHidden) {
  988. var i, iLen, j, jLen, k, kLen, n, nLocalTr;
  989. var aoLocal = [];
  990. var aApplied = [];
  991. var iColumns = oSettings.aoColumns.length;
  992. var iRowspan, iColspan;
  993. if (bIncludeHidden === undefined) {
  994. bIncludeHidden = false;
  995. }
  996. /* Make a copy of the master layout array, but without the visible columns in it */
  997. for (i = 0, iLen = aoSource.length; i < iLen; i++) {
  998. aoLocal[i] = aoSource[i].slice();
  999. aoLocal[i].nTr = aoSource[i].nTr;
  1000. /* Remove any columns which are currently hidden */
  1001. for (j = iColumns - 1; j >= 0; j--) {
  1002. if (!oSettings.aoColumns[j].bVisible && !bIncludeHidden) {
  1003. aoLocal[i].splice(j, 1);
  1004. }
  1005. }
  1006. /* Prep the applied array - it needs an element for each row */
  1007. aApplied.push([]);
  1008. }
  1009. for (i = 0, iLen = aoLocal.length; i < iLen; i++) {
  1010. nLocalTr = aoLocal[i].nTr;
  1011. /* All cells are going to be replaced, so empty out the row */
  1012. if (nLocalTr) {
  1013. while ((n = nLocalTr.firstChild)) {
  1014. nLocalTr.removeChild(n);
  1015. }
  1016. }
  1017. for (j = 0, jLen = aoLocal[i].length; j < jLen; j++) {
  1018. iRowspan = 1;
  1019. iColspan = 1;
  1020. /* Check to see if there is already a cell (row/colspan) covering our target
  1021. * insert point. If there is, then there is nothing to do.
  1022. */
  1023. if (aApplied[i][j] === undefined) {
  1024. nLocalTr.appendChild(aoLocal[i][j].cell);
  1025. aApplied[i][j] = 1;
  1026. /* Expand the cell to cover as many rows as needed */
  1027. while (aoLocal[i + iRowspan] !== undefined &&
  1028. aoLocal[i][j].cell == aoLocal[i + iRowspan][j].cell) {
  1029. aApplied[i + iRowspan][j] = 1;
  1030. iRowspan++;
  1031. }
  1032. /* Expand the cell to cover as many columns as needed */
  1033. while (aoLocal[i][j + iColspan] !== undefined &&
  1034. aoLocal[i][j].cell == aoLocal[i][j + iColspan].cell) {
  1035. /* Must update the applied array over the rows for the columns */
  1036. for (k = 0; k < iRowspan; k++) {
  1037. aApplied[i + k][j + iColspan] = 1;
  1038. }
  1039. iColspan++;
  1040. }
  1041. /* Do the actual expansion in the DOM */
  1042. aoLocal[i][j].cell.rowSpan = iRowspan;
  1043. aoLocal[i][j].cell.colSpan = iColspan;
  1044. }
  1045. }
  1046. }
  1047. }
  1048. /**
  1049. * Insert the required TR nodes into the table for display
  1050. * @param {object} oSettings dataTables settings object
  1051. * @memberof DataTable#oApi
  1052. */
  1053. function _fnDraw(oSettings) {
  1054. /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
  1055. var aPreDraw = _fnCallbackFire(oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings]);
  1056. if ($.inArray(false, aPreDraw) !== -1) {
  1057. _fnProcessingDisplay(oSettings, false);
  1058. return;
  1059. }
  1060. var i, iLen, n;
  1061. var anRows = [];
  1062. var iRowCount = 0;
  1063. var iStripes = oSettings.asStripeClasses.length;
  1064. var iOpenRows = oSettings.aoOpenRows.length;
  1065. oSettings.bDrawing = true;
  1066. /* Check and see if we have an initial draw position from state saving */
  1067. if (oSettings.iInitDisplayStart !== undefined && oSettings.iInitDisplayStart != -1) {
  1068. if (oSettings.oFeatures.bServerSide) {
  1069. oSettings._iDisplayStart = oSettings.iInitDisplayStart;
  1070. }
  1071. else {
  1072. oSettings._iDisplayStart = (oSettings.iInitDisplayStart >= oSettings.fnRecordsDisplay()) ?
  1073. 0 : oSettings.iInitDisplayStart;
  1074. }
  1075. oSettings.iInitDisplayStart = -1;
  1076. _fnCalculateEnd(oSettings);
  1077. }
  1078. /* Server-side processing draw intercept */
  1079. if (oSettings.bDeferLoading) {
  1080. oSettings.bDeferLoading = false;
  1081. oSettings.iDraw++;
  1082. }
  1083. else if (!oSettings.oFeatures.bServerSide) {
  1084. oSettings.iDraw++;
  1085. }
  1086. else if (!oSettings.bDestroying && !_fnAjaxUpdate(oSettings)) {
  1087. return;
  1088. }
  1089. if (oSettings.aiDisplay.length !== 0) {
  1090. var iStart = oSettings._iDisplayStart;
  1091. var iEnd = oSettings._iDisplayEnd;
  1092. if (oSettings.oFeatures.bServerSide) {
  1093. iStart = 0;
  1094. iEnd = oSettings.aoData.length;
  1095. }
  1096. for (var j = iStart; j < iEnd; j++) {
  1097. var aoData = oSettings.aoData[ oSettings.aiDisplay[j] ];
  1098. if (aoData.nTr === null) {
  1099. _fnCreateTr(oSettings, oSettings.aiDisplay[j]);
  1100. }
  1101. var nRow = aoData.nTr;
  1102. /* Remove the old striping classes and then add the new one */
  1103. if (iStripes !== 0) {
  1104. var sStripe = oSettings.asStripeClasses[ iRowCount % iStripes ];
  1105. if (aoData._sRowStripe != sStripe) {
  1106. $(nRow).removeClass(aoData._sRowStripe).addClass(sStripe);
  1107. aoData._sRowStripe = sStripe;
  1108. }
  1109. }
  1110. /* Row callback functions - might want to manipulate the row */
  1111. _fnCallbackFire(oSettings, 'aoRowCallback', null,
  1112. [nRow, oSettings.aoData[ oSettings.aiDisplay[j] ]._aData, iRowCount, j]);
  1113. anRows.push(nRow);
  1114. iRowCount++;
  1115. /* If there is an open row - and it is attached to this parent - attach it on redraw */
  1116. if (iOpenRows !== 0) {
  1117. for (var k = 0; k < iOpenRows; k++) {
  1118. if (nRow == oSettings.aoOpenRows[k].nParent) {
  1119. anRows.push(oSettings.aoOpenRows[k].nTr);
  1120. break;
  1121. }
  1122. }
  1123. }
  1124. }
  1125. }
  1126. else {
  1127. /* Table is empty - create a row with an empty message in it */
  1128. anRows[ 0 ] = document.createElement('tr');
  1129. if (oSettings.asStripeClasses[0]) {
  1130. anRows[ 0 ].className = oSettings.asStripeClasses[0];
  1131. }
  1132. var oLang = oSettings.oLanguage;
  1133. var sZero = oLang.sZeroRecords;
  1134. if (oSettings.iDraw == 1 && oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide) {
  1135. sZero = oLang.sLoadingRecords;
  1136. }
  1137. else if (oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0) {
  1138. sZero = oLang.sEmptyTable;
  1139. }
  1140. var nTd = document.createElement('td');
  1141. nTd.setAttribute('valign', "top");
  1142. nTd.colSpan = _fnVisbleColumns(oSettings);
  1143. nTd.className = oSettings.oClasses.sRowEmpty;
  1144. nTd.innerHTML = _fnInfoMacros(oSettings, sZero);
  1145. anRows[ iRowCount ].appendChild(nTd);
  1146. }
  1147. /* Header and footer callbacks */
  1148. _fnCallbackFire(oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
  1149. _fnGetDataMaster(oSettings), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ]);
  1150. _fnCallbackFire(oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
  1151. _fnGetDataMaster(oSettings), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ]);
  1152. /*
  1153. * Need to remove any old row from the display - note we can't just empty the tbody using
  1154. * $().html('') since this will unbind the jQuery event handlers (even although the node
  1155. * still exists!) - equally we can't use innerHTML, since IE throws an exception.
  1156. */
  1157. var
  1158. nAddFrag = document.createDocumentFragment(),
  1159. nRemoveFrag = document.createDocumentFragment(),
  1160. nBodyPar, nTrs;
  1161. if (oSettings.nTBody) {
  1162. nBodyPar = oSettings.nTBody.parentNode;
  1163. nRemoveFrag.appendChild(oSettings.nTBody);
  1164. /* When doing infinite scrolling, only remove child rows when sorting, filtering or start
  1165. * up. When not infinite scroll, always do it.
  1166. */
  1167. if (!oSettings.oScroll.bInfinite || !oSettings._bInitComplete ||
  1168. oSettings.bSorted || oSettings.bFiltered) {
  1169. while ((n = oSettings.nTBody.firstChild)) {
  1170. oSettings.nTBody.removeChild(n);
  1171. }
  1172. }
  1173. /* Put the draw table into the dom */
  1174. for (i = 0, iLen = anRows.length; i < iLen; i++) {
  1175. nAddFrag.appendChild(anRows[i]);
  1176. }
  1177. oSettings.nTBody.appendChild(nAddFrag);
  1178. if (nBodyPar !== null) {
  1179. nBodyPar.appendChild(oSettings.nTBody);
  1180. }
  1181. }
  1182. /* Call all required callback functions for the end of a draw */
  1183. _fnCallbackFire(oSettings, 'aoDrawCallback', 'draw', [oSettings]);
  1184. /* Draw is complete, sorting and filtering must be as well */
  1185. oSettings.bSorted = false;
  1186. oSettings.bFiltered = false;
  1187. oSettings.bDrawing = false;
  1188. if (oSettings.oFeatures.bServerSide) {
  1189. _fnProcessingDisplay(oSettings, false);
  1190. if (!oSettings._bInitComplete) {
  1191. _fnInitComplete(oSettings);
  1192. }
  1193. }
  1194. }
  1195. /**
  1196. * Redraw the table - taking account of the various features which are enabled
  1197. * @param {object} oSettings dataTables settings object
  1198. * @memberof DataTable#oApi
  1199. */
  1200. function _fnReDraw(oSettings) {
  1201. if (oSettings.oFeatures.bSort) {
  1202. /* Sorting will refilter and draw for us */
  1203. _fnSort(oSettings, oSettings.oPreviousSearch);
  1204. }
  1205. else if (oSettings.oFeatures.bFilter) {
  1206. /* Filtering will redraw for us */
  1207. _fnFilterComplete(oSettings, oSettings.oPreviousSearch);
  1208. }
  1209. else {
  1210. _fnCalculateEnd(oSettings);
  1211. _fnDraw(oSettings);
  1212. }
  1213. }
  1214. /**
  1215. * Add the options to the page HTML for the table
  1216. * @param {object} oSettings dataTables settings object
  1217. * @memberof DataTable#oApi
  1218. */
  1219. function _fnAddOptionsHtml(oSettings) {
  1220. /*
  1221. * Create a temporary, empty, div which we can later on replace with what we have generated
  1222. * we do it this way to rendering the 'options' html offline - speed :-)
  1223. */
  1224. var nHolding = $('<div></div>')[0];
  1225. oSettings.nTable.parentNode.insertBefore(nHolding, oSettings.nTable);
  1226. /*
  1227. * All DataTables are wrapped in a div
  1228. */
  1229. oSettings.nTableWrapper = $('<div id="' + oSettings.sTableId + '_wrapper" class="' + oSettings.oClasses.sWrapper + '" role="grid"></div>')[0];
  1230. oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
  1231. /* Track where we want to insert the option */
  1232. var nInsertNode = oSettings.nTableWrapper;
  1233. /* Loop over the user set positioning and place the elements as needed */
  1234. var aDom = oSettings.sDom.split('');
  1235. var nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j;
  1236. for (var i = 0; i < aDom.length; i++) {
  1237. iPushFeature = 0;
  1238. cOption = aDom[i];
  1239. if (cOption == '<') {
  1240. /* New container div */
  1241. nNewNode = $('<div></div>')[0];
  1242. /* Check to see if we should append an id and/or a class name to the container */
  1243. cNext = aDom[i + 1];
  1244. if (cNext == "'" || cNext == '"') {
  1245. sAttr = "";
  1246. j = 2;
  1247. while (aDom[i + j] != cNext) {
  1248. sAttr += aDom[i + j];
  1249. j++;
  1250. }
  1251. /* Replace jQuery UI constants */
  1252. if (sAttr == "H") {
  1253. sAttr = oSettings.oClasses.sJUIHeader;
  1254. }
  1255. else if (sAttr == "F") {
  1256. sAttr = oSettings.oClasses.sJUIFooter;
  1257. }
  1258. /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
  1259. * breaks the string into parts and applies them as needed
  1260. */
  1261. if (sAttr.indexOf('.') != -1) {
  1262. var aSplit = sAttr.split('.');
  1263. nNewNode.id = aSplit[0].substr(1, aSplit[0].length - 1);
  1264. nNewNode.className = aSplit[1];
  1265. }
  1266. else if (sAttr.charAt(0) == "#") {
  1267. nNewNode.id = sAttr.substr(1, sAttr.length - 1);
  1268. }
  1269. else {
  1270. nNewNode.className = sAttr;
  1271. }
  1272. i += j;
  1273. /* Move along the position array */
  1274. }
  1275. nInsertNode.appendChild(nNewNode);
  1276. nInsertNode = nNewNode;
  1277. }
  1278. else if (cOption == '>') {
  1279. /* End container div */
  1280. nInsertNode = nInsertNode.parentNode;
  1281. }
  1282. else if (cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange) {
  1283. /* Length */
  1284. nTmp = _fnFeatureHtmlLength(oSettings);
  1285. iPushFeature = 1;
  1286. }
  1287. else if (cOption == 'f' && oSettings.oFeatures.bFilter) {
  1288. /* Filter */
  1289. nTmp = _fnFeatureHtmlFilter(oSettings);
  1290. iPushFeature = 1;
  1291. }
  1292. else if (cOption == 'r' && oSettings.oFeatures.bProcessing) {
  1293. /* pRocessing */
  1294. nTmp = _fnFeatureHtmlProcessing(oSettings);
  1295. iPushFeature = 1;
  1296. }
  1297. else if (cOption == 't') {
  1298. /* Table */
  1299. nTmp = _fnFeatureHtmlTable(oSettings);
  1300. iPushFeature = 1;
  1301. }
  1302. else if (cOption == 'i' && oSettings.oFeatures.bInfo) {
  1303. /* Info */
  1304. nTmp = _fnFeatureHtmlInfo(oSettings);
  1305. iPushFeature = 1;
  1306. }
  1307. else if (cOption == 'p' && oSettings.oFeatures.bPaginate) {
  1308. /* Pagination */
  1309. nTmp = _fnFeatureHtmlPaginate(oSettings);
  1310. iPushFeature = 1;
  1311. }
  1312. else if (DataTable.ext.aoFeatures.length !== 0) {
  1313. /* Plug-in features */
  1314. var aoFeatures = DataTable.ext.aoFeatures;
  1315. for (var k = 0, kLen = aoFeatures.length; k < kLen; k++) {
  1316. if (cOption == aoFeatures[k].cFeature) {
  1317. nTmp = aoFeatures[k].fnInit(oSettings);
  1318. if (nTmp) {
  1319. iPushFeature = 1;
  1320. }
  1321. break;
  1322. }
  1323. }
  1324. }
  1325. /* Add to the 2D features array */
  1326. if (iPushFeature == 1 && nTmp !== null) {
  1327. if (typeof oSettings.aanFeatures[cOption] !== 'object') {
  1328. oSettings.aanFeatures[cOption] = [];
  1329. }
  1330. oSettings.aanFeatures[cOption].push(nTmp);
  1331. nInsertNode.appendChild(nTmp);
  1332. }
  1333. }
  1334. /* Built our DOM structure - replace the holding div with what we want */
  1335. nHolding.parentNode.replaceChild(oSettings.nTableWrapper, nHolding);
  1336. }
  1337. /**
  1338. * Use the DOM source to create up an array of header cells. The idea here is to
  1339. * create a layout grid (array) of rows x columns, which contains a reference
  1340. * to the cell that that point in the grid (regardless of col/rowspan), such that
  1341. * any column / row could be removed and the new grid constructed
  1342. * @param array {object} aLayout Array to store the calculated layout in
  1343. * @param {node} nThead The header/footer element for the table
  1344. * @memberof DataTable#oApi
  1345. */
  1346. function _fnDetectHeader(aLayout, nThead) {
  1347. var nTrs = $(nThead).children('tr');
  1348. var nTr, nCell;
  1349. var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
  1350. var bUnique;
  1351. var fnShiftCol = function (a, i, j) {
  1352. var k = a[i];
  1353. while (k[j]) {
  1354. j++;
  1355. }
  1356. return j;
  1357. };
  1358. aLayout.splice(0, aLayout.length);
  1359. /* We know how many rows there are in the layout - so prep it */
  1360. for (i = 0, iLen = nTrs.length; i < iLen; i++) {
  1361. aLayout.push([]);
  1362. }
  1363. /* Calculate a layout array */
  1364. for (i = 0, iLen = nTrs.length; i < iLen; i++) {
  1365. nTr = nTrs[i];
  1366. iColumn = 0;
  1367. /* For every cell in the row... */
  1368. nCell = nTr.firstChild;
  1369. while (nCell) {
  1370. if (nCell.nodeName.toUpperCase() == "TD" ||
  1371. nCell.nodeName.toUpperCase() == "TH") {
  1372. /* Get the col and rowspan attributes from the DOM and sanitise them */
  1373. iColspan = nCell.getAttribute('colspan') * 1;
  1374. iRowspan = nCell.getAttribute('rowspan') * 1;
  1375. iColspan = (!iColspan || iColspan === 0 || iColspan === 1) ? 1 : iColspan;
  1376. iRowspan = (!iRowspan || iRowspan === 0 || iRowspan === 1) ? 1 : iRowspan;
  1377. /* There might be colspan cells already in this row, so shift our target
  1378. * accordingly
  1379. */
  1380. iColShifted = fnShiftCol(aLayout, i, iColumn);
  1381. /* Cache calculation for unique columns */
  1382. bUnique = iColspan === 1 ? true : false;
  1383. /* If there is col / rowspan, copy the information into the layout grid */
  1384. for (l = 0; l < iColspan; l++) {
  1385. for (k = 0; k < iRowspan; k++) {
  1386. aLayout[i + k][iColShifted + l] = {
  1387. "cell":nCell,
  1388. "unique":bUnique
  1389. };
  1390. aLayout[i + k].nTr = nTr;
  1391. }
  1392. }
  1393. }
  1394. nCell = nCell.nextSibling;
  1395. }
  1396. }
  1397. }
  1398. /**
  1399. * Get an array of unique th elements, one for each column
  1400. * @param {object} oSettings dataTables settings object
  1401. * @param {node} nHeader automatically detect the layout from this node - optional
  1402. * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
  1403. * @returns array {node} aReturn list of unique th's
  1404. * @memberof DataTable#oApi
  1405. */
  1406. function _fnGetUniqueThs(oSettings, nHeader, aLayout) {
  1407. var aReturn = [];
  1408. if (!aLayout) {
  1409. aLayout = oSettings.aoHeader;
  1410. if (nHeader) {
  1411. aLayout = [];
  1412. _fnDetectHeader(aLayout, nHeader);
  1413. }
  1414. }
  1415. for (var i = 0, iLen = aLayout.length; i < iLen; i++) {
  1416. for (var j = 0, jLen = aLayout[i].length; j < jLen; j++) {
  1417. if (aLayout[i][j].unique &&
  1418. (!aReturn[j] || !oSettings.bSortCellsTop)) {
  1419. aReturn[j] = aLayout[i][j].cell;
  1420. }
  1421. }
  1422. }
  1423. return aReturn;
  1424. }
  1425. /**
  1426. * Update the table using an Ajax call
  1427. * @param {object} oSettings dataTables settings object
  1428. * @returns {boolean} Block the table drawing or not
  1429. * @memberof DataTable#oApi
  1430. */
  1431. function _fnAjaxUpdate(oSettings) {
  1432. if (oSettings.bAjaxDataGet) {
  1433. oSettings.iDraw++;
  1434. _fnProcessingDisplay(oSettings, true);
  1435. var iColumns = oSettings.aoColumns.length;
  1436. var aoData = _fnAjaxParameters(oSettings);
  1437. _fnServerParams(oSettings, aoData);
  1438. oSettings.fnServerData.call(oSettings.oInstance, oSettings.sAjaxSource, aoData,
  1439. function (json) {
  1440. _fnAjaxUpdateDraw(oSettings, json);
  1441. }, oSettings);
  1442. return false;
  1443. }
  1444. else {
  1445. return true;
  1446. }
  1447. }
  1448. /**
  1449. * Build up the parameters in an object needed for a server-side processing request
  1450. * @param {object} oSettings dataTables settings object
  1451. * @returns {bool} block the table drawing or not
  1452. * @memberof DataTable#oApi
  1453. */
  1454. function _fnAjaxParameters(oSettings) {
  1455. var iColumns = oSettings.aoColumns.length;
  1456. var aoData = [], mDataProp, aaSort, aDataSort;
  1457. var i, j;
  1458. aoData.push({ "name":"sEcho", "value":oSettings.iDraw });
  1459. aoData.push({ "name":"iColumns", "value":iColumns });
  1460. aoData.push({ "name":"sColumns", "value":_fnColumnOrdering(oSettings) });
  1461. aoData.push({ "name":"iDisplayStart", "value":oSettings._iDisplayStart });
  1462. aoData.push({ "name":"iDisplayLength", "value":oSettings.oFeatures.bPaginate !== false ?
  1463. oSettings._iDisplayLength : -1 });
  1464. for (i = 0; i < iColumns; i++) {
  1465. mDataProp = oSettings.aoColumns[i].mData;
  1466. aoData.push({ "name":"mDataProp_" + i, "value":typeof(mDataProp) === "function" ? 'function' : mDataProp });
  1467. }
  1468. /* Filtering */
  1469. if (oSettings.oFeatures.bFilter !== false) {
  1470. aoData.push({ "name":"sSearch", "value":oSettings.oPreviousSearch.sSearch });
  1471. aoData.push({ "name":"bRegex", "value":oSettings.oPreviousSearch.bRegex });
  1472. for (i = 0; i < iColumns; i++) {
  1473. aoData.push({ "name":"sSearch_" + i, "value":oSettings.aoPreSearchCols[i].sSearch });
  1474. aoData.push({ "name":"bRegex_" + i, "value":oSettings.aoPreSearchCols[i].bRegex });
  1475. aoData.push({ "name":"bSearchable_" + i, "value":oSettings.aoColumns[i].bSearchable });
  1476. }
  1477. }
  1478. /* Sorting */
  1479. if (oSettings.oFeatures.bSort !== false) {
  1480. var iCounter = 0;
  1481. aaSort = ( oSettings.aaSortingFixed !== null ) ?
  1482. oSettings.aaSortingFixed.concat(oSettings.aaSorting) :
  1483. oSettings.aaSorting.slice();
  1484. for (i = 0; i < aaSort.length; i++) {
  1485. aDataSort = oSettings.aoColumns[ aaSort[i][0] ].aDataSort;
  1486. for (j = 0; j < aDataSort.length; j++) {
  1487. aoData.push({ "name":"iSortCol_" + iCounter, "value":aDataSort[j] });
  1488. aoData.push({ "name":"sSortDir_" + iCounter, "value":aaSort[i][1] });
  1489. iCounter++;
  1490. }
  1491. }
  1492. aoData.push({ "name":"iSortingCols", "value":iCounter });
  1493. for (i = 0; i < iColumns; i++) {
  1494. aoData.push({ "name":"bSortable_" + i, "value":oSettings.aoColumns[i].bSortable });
  1495. }
  1496. }
  1497. return aoData;
  1498. }
  1499. /**
  1500. * Add Ajax parameters from plug-ins
  1501. * @param {object} oSettings dataTables settings object
  1502. * @param array {objects} aoData name/value pairs to send to the server
  1503. * @memberof DataTable#oApi
  1504. */
  1505. function _fnServerParams(oSettings, aoData) {
  1506. _fnCallbackFire(oSettings, 'aoServerParams', 'serverParams', [aoData]);
  1507. }
  1508. /**
  1509. * Data the data from the server (nuking the old) and redraw the table
  1510. * @param {object} oSettings dataTables settings object
  1511. * @param {object} json json data return from the server.
  1512. * @param {string} json.sEcho Tracking flag for DataTables to match requests
  1513. * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
  1514. * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
  1515. * @param {array} json.aaData The data to display on this page
  1516. * @param {string} [json.sColumns] Column ordering (sName, comma separated)
  1517. * @memberof DataTable#oApi
  1518. */
  1519. function _fnAjaxUpdateDraw(oSettings, json) {
  1520. if (json.sEcho !== undefined) {
  1521. /* Protect against old returns over-writing a new one. Possible when you get
  1522. * very fast interaction, and later queries are completed much faster
  1523. */
  1524. if (json.sEcho * 1 < oSettings.iDraw) {
  1525. return;
  1526. }
  1527. else {
  1528. oSettings.iDraw = json.sEcho * 1;
  1529. }
  1530. }
  1531. if (!oSettings.oScroll.bInfinite ||
  1532. (oSettings.oScroll.bInfinite && (oSettings.bSorted || oSettings.bFiltered))) {
  1533. _fnClearTable(oSettings);
  1534. }
  1535. oSettings._iRecordsTotal = parseInt(json.iTotalRecords, 10);
  1536. oSettings._iRecordsDisplay = parseInt(json.iTotalDisplayRecords, 10);
  1537. /* Determine if reordering is required */
  1538. var sOrdering = _fnColumnOrdering(oSettings);
  1539. var bReOrder = (json.sColumns !== undefined && sOrdering !== "" && json.sColumns != sOrdering );
  1540. var aiIndex;
  1541. if (bReOrder) {
  1542. aiIndex = _fnReOrderIndex(oSettings, json.sColumns);
  1543. }
  1544. var aData = _fnGetObjectDataFn(oSettings.sAjaxDataProp)(json);
  1545. for (var i = 0, iLen = aData.length; i < iLen; i++) {
  1546. if (bReOrder) {
  1547. /* If we need to re-order, then create a new array with the correct order and add it */
  1548. var aDataSorted = [];
  1549. for (var j = 0, jLen = oSettings.aoColumns.length; j < jLen; j++) {
  1550. aDataSorted.push(aData[i][ aiIndex[j] ]);
  1551. }
  1552. _fnAddData(oSettings, aDataSorted);
  1553. }
  1554. else {
  1555. /* No re-order required, sever got it "right" - just straight add */
  1556. _fnAddData(oSettings, aData[i]);
  1557. }
  1558. }
  1559. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  1560. oSettings.bAjaxDataGet = false;
  1561. _fnDraw(oSettings);
  1562. oSettings.bAjaxDataGet = true;
  1563. _fnProcessingDisplay(oSettings, false);
  1564. }
  1565. /**
  1566. * Generate the node required for filtering text
  1567. * @returns {node} Filter control element
  1568. * @param {object} oSettings dataTables settings object
  1569. * @memberof DataTable#oApi
  1570. */
  1571. function _fnFeatureHtmlFilter(oSettings) {
  1572. var oPreviousSearch = oSettings.oPreviousSearch;
  1573. var sSearchStr = oSettings.oLanguage.sSearch;
  1574. sSearchStr = (sSearchStr.indexOf('_INPUT_') !== -1) ?
  1575. sSearchStr.replace('_INPUT_', '<input type="text" />') :
  1576. sSearchStr === "" ? '<input type="text" />' : sSearchStr + ' <input type="text" />';
  1577. var nFilter = document.createElement('div');
  1578. nFilter.className = oSettings.oClasses.sFilter;
  1579. nFilter.innerHTML = '<label>' + sSearchStr + '</label>';
  1580. if (!oSettings.aanFeatures.f) {
  1581. nFilter.id = oSettings.sTableId + '_filter';
  1582. }
  1583. var jqFilter = $('input[type="text"]', nFilter);
  1584. // Store a reference to the input element, so other input elements could be
  1585. // added to the filter wrapper if needed (submit button for example)
  1586. nFilter._DT_Input = jqFilter[0];
  1587. jqFilter.val(oPreviousSearch.sSearch.replace('"', '&quot;'));
  1588. jqFilter.bind('keyup.DT', function (e) {
  1589. /* Update all other filter input elements for the new display */
  1590. var n = oSettings.aanFeatures.f;
  1591. var val = this.value === "" ? "" : this.value; // mental IE8 fix :-(
  1592. for (var i = 0, iLen = n.length; i < iLen; i++) {
  1593. if (n[i] != $(this).parents('div.dataTables_filter')[0]) {
  1594. $(n[i]._DT_Input).val(val);
  1595. }
  1596. }
  1597. /* Now do the filter */
  1598. if (val != oPreviousSearch.sSearch) {
  1599. _fnFilterComplete(oSettings, {
  1600. "sSearch":val,
  1601. "bRegex":oPreviousSearch.bRegex,
  1602. "bSmart":oPreviousSearch.bSmart,
  1603. "bCaseInsensitive":oPreviousSearch.bCaseInsensitive
  1604. });
  1605. }
  1606. });
  1607. jqFilter
  1608. .attr('aria-controls', oSettings.sTableId)
  1609. .bind('keypress.DT', function (e) {
  1610. /* Prevent form submission */
  1611. if (e.keyCode == 13) {
  1612. return false;
  1613. }
  1614. }
  1615. );
  1616. return nFilter;
  1617. }
  1618. /**
  1619. * Filter the table using both the global filter and column based filtering
  1620. * @param {object} oSettings dataTables settings object
  1621. * @param {object} oSearch search information
  1622. * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
  1623. * @memberof DataTable#oApi
  1624. */
  1625. function _fnFilterComplete(oSettings, oInput, iForce) {
  1626. var oPrevSearch = oSettings.oPreviousSearch;
  1627. var aoPrevSearch = oSettings.aoPreSearchCols;
  1628. var fnSaveFilter = function (oFilter) {
  1629. /* Save the filtering values */
  1630. oPrevSearch.sSearch = oFilter.sSearch;
  1631. oPrevSearch.bRegex = oFilter.bRegex;
  1632. oPrevSearch.bSmart = oFilter.bSmart;
  1633. oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
  1634. };
  1635. /* In server-side processing all filtering is done by the server, so no point hanging around here */
  1636. if (!oSettings.oFeatures.bServerSide) {
  1637. /* Global filter */
  1638. _fnFilter(oSettings, oInput.sSearch, iForce, oInput.bRegex, oInput.bSmart, oInput.bCaseInsensitive);
  1639. fnSaveFilter(oInput);
  1640. /* Now do the individual column filter */
  1641. for (var i = 0; i < oSettings.aoPreSearchCols.length; i++) {
  1642. _fnFilterColumn(oSettings, aoPrevSearch[i].sSearch, i, aoPrevSearch[i].bRegex,
  1643. aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive);
  1644. }
  1645. /* Custom filtering */
  1646. _fnFilterCustom(oSettings);
  1647. }
  1648. else {
  1649. fnSaveFilter(oInput);
  1650. }
  1651. /* Tell the draw function we have been filtering */
  1652. oSettings.bFiltered = true;
  1653. $(oSettings.oInstance).trigger('filter', oSettings);
  1654. /* Redraw the table */
  1655. oSettings._iDisplayStart = 0;
  1656. _fnCalculateEnd(oSettings);
  1657. _fnDraw(oSettings);
  1658. /* Rebuild search array 'offline' */
  1659. _fnBuildSearchArray(oSettings, 0);
  1660. }
  1661. /**
  1662. * Apply custom filtering functions
  1663. * @param {object} oSettings dataTables settings object
  1664. * @memberof DataTable#oApi
  1665. */
  1666. function _fnFilterCustom(oSettings) {
  1667. var afnFilters = DataTable.ext.afnFiltering;
  1668. var aiFilterColumns = _fnGetColumns(oSettings, 'bSearchable');
  1669. for (var i = 0, iLen = afnFilters.length; i < iLen; i++) {
  1670. var iCorrector = 0;
  1671. for (var j = 0, jLen = oSettings.aiDisplay.length; j < jLen; j++) {
  1672. var iDisIndex = oSettings.aiDisplay[j - iCorrector];
  1673. var bTest = afnFilters[i](
  1674. oSettings,
  1675. _fnGetRowData(oSettings, iDisIndex, 'filter', aiFilterColumns),
  1676. iDisIndex
  1677. );
  1678. /* Check if we should use this row based on the filtering function */
  1679. if (!bTest) {
  1680. oSettings.aiDisplay.splice(j - iCorrector, 1);
  1681. iCorrector++;
  1682. }
  1683. }
  1684. }
  1685. }
  1686. /**
  1687. * Filter the table on a per-column basis
  1688. * @param {object} oSettings dataTables settings object
  1689. * @param {string} sInput string to filter on
  1690. * @param {int} iColumn column to filter
  1691. * @param {bool} bRegex treat search string as a regular expression or not
  1692. * @param {bool} bSmart use smart filtering or not
  1693. * @param {bool} bCaseInsensitive Do case insenstive matching or not
  1694. * @memberof DataTable#oApi
  1695. */
  1696. function _fnFilterColumn(oSettings, sInput, iColumn, bRegex, bSmart, bCaseInsensitive) {
  1697. if (sInput === "") {
  1698. return;
  1699. }
  1700. var iIndexCorrector = 0;
  1701. var rpSearch = _fnFilterCreateSearch(sInput, bRegex, bSmart, bCaseInsensitive);
  1702. for (var i = oSettings.aiDisplay.length - 1; i >= 0; i--) {
  1703. var sData = _fnDataToSearch(_fnGetCellData(oSettings, oSettings.aiDisplay[i], iColumn, 'filter'),
  1704. oSettings.aoColumns[iColumn].sType);
  1705. if (!rpSearch.test(sData)) {
  1706. oSettings.aiDisplay.splice(i, 1);
  1707. iIndexCorrector++;
  1708. }
  1709. }
  1710. }
  1711. /**
  1712. * Filter the data table based on user input and draw the table
  1713. * @param {object} oSettings dataTables settings object
  1714. * @param {string} sInput string to filter on
  1715. * @param {int} iForce optional - force a research of the master array (1) or not (undefined or 0)
  1716. * @param {bool} bRegex treat as a regular expression or not
  1717. * @param {bool} bSmart perform smart filtering or not
  1718. * @param {bool} bCaseInsensitive Do case insenstive matching or not
  1719. * @memberof DataTable#oApi
  1720. */
  1721. function _fnFilter(oSettings, sInput, iForce, bRegex, bSmart, bCaseInsensitive) {
  1722. var i;
  1723. var rpSearch = _fnFilterCreateSearch(sInput, bRegex, bSmart, bCaseInsensitive);
  1724. var oPrevSearch = oSettings.oPreviousSearch;
  1725. /* Check if we are forcing or not - optional parameter */
  1726. if (!iForce) {
  1727. iForce = 0;
  1728. }
  1729. /* Need to take account of custom filtering functions - always filter */
  1730. if (DataTable.ext.afnFiltering.length !== 0) {
  1731. iForce = 1;
  1732. }
  1733. /*
  1734. * If the input is blank - we want the full data set
  1735. */
  1736. if (sInput.length <= 0) {
  1737. oSettings.aiDisplay.splice(0, oSettings.aiDisplay.length);
  1738. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  1739. }
  1740. else {
  1741. /*
  1742. * We are starting a new search or the new search string is smaller
  1743. * then the old one (i.e. delete). Search from the master array
  1744. */
  1745. if (oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length ||
  1746. oPrevSearch.sSearch.length > sInput.length || iForce == 1 ||
  1747. sInput.indexOf(oPrevSearch.sSearch) !== 0) {
  1748. /* Nuke the old display array - we are going to rebuild it */
  1749. oSettings.aiDisplay.splice(0, oSettings.aiDisplay.length);
  1750. /* Force a rebuild of the search array */
  1751. _fnBuildSearchArray(oSettings, 1);
  1752. /* Search through all records to populate the search array
  1753. * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1
  1754. * mapping
  1755. */
  1756. for (i = 0; i < oSettings.aiDisplayMaster.length; i++) {
  1757. if (rpSearch.test(oSettings.asDataSearch[i])) {
  1758. oSettings.aiDisplay.push(oSettings.aiDisplayMaster[i]);
  1759. }
  1760. }
  1761. }
  1762. else {
  1763. /* Using old search array - refine it - do it this way for speed
  1764. * Don't have to search the whole master array again
  1765. */
  1766. var iIndexCorrector = 0;
  1767. /* Search the current results */
  1768. for (i = 0; i < oSettings.asDataSearch.length; i++) {
  1769. if (!rpSearch.test(oSettings.asDataSearch[i])) {
  1770. oSettings.aiDisplay.splice(i - iIndexCorrector, 1);
  1771. iIndexCorrector++;
  1772. }
  1773. }
  1774. }
  1775. }
  1776. }
  1777. /**
  1778. * Create an array which can be quickly search through
  1779. * @param {object} oSettings dataTables settings object
  1780. * @param {int} iMaster use the master data array - optional
  1781. * @memberof DataTable#oApi
  1782. */
  1783. function _fnBuildSearchArray(oSettings, iMaster) {
  1784. if (!oSettings.oFeatures.bServerSide) {
  1785. /* Clear out the old data */
  1786. oSettings.asDataSearch = [];
  1787. var aiFilterColumns = _fnGetColumns(oSettings, 'bSearchable');
  1788. var aiIndex = (iMaster === 1) ?
  1789. oSettings.aiDisplayMaster :
  1790. oSettings.aiDisplay;
  1791. for (var i = 0, iLen = aiIndex.length; i < iLen; i++) {
  1792. oSettings.asDataSearch[i] = _fnBuildSearchRow(
  1793. oSettings,
  1794. _fnGetRowData(oSettings, aiIndex[i], 'filter', aiFilterColumns)
  1795. );
  1796. }
  1797. }
  1798. }
  1799. /**
  1800. * Create a searchable string from a single data row
  1801. * @param {object} oSettings dataTables settings object
  1802. * @param {array} aData Row data array to use for the data to search
  1803. * @memberof DataTable#oApi
  1804. */
  1805. function _fnBuildSearchRow(oSettings, aData) {
  1806. var sSearch = aData.join(' ');
  1807. /* If it looks like there is an HTML entity in the string, attempt to decode it */
  1808. if (sSearch.indexOf('&') !== -1) {
  1809. sSearch = $('<div>').html(sSearch).text();
  1810. }
  1811. // Strip newline characters
  1812. return sSearch.replace(/[\n\r]/g, " ");
  1813. }
  1814. /**
  1815. * Build a regular expression object suitable for searching a table
  1816. * @param {string} sSearch string to search for
  1817. * @param {bool} bRegex treat as a regular expression or not
  1818. * @param {bool} bSmart perform smart filtering or not
  1819. * @param {bool} bCaseInsensitive Do case insensitive matching or not
  1820. * @returns {RegExp} constructed object
  1821. * @memberof DataTable#oApi
  1822. */
  1823. function _fnFilterCreateSearch(sSearch, bRegex, bSmart, bCaseInsensitive) {
  1824. var asSearch, sRegExpString;
  1825. if (bSmart) {
  1826. /* Generate the regular expression to use. Something along the lines of:
  1827. * ^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$
  1828. */
  1829. asSearch = bRegex ? sSearch.split(' ') : _fnEscapeRegex(sSearch).split(' ');
  1830. sRegExpString = '^(?=.*?' + asSearch.join(')(?=.*?') + ').*$';
  1831. return new RegExp(sRegExpString, bCaseInsensitive ? "i" : "");
  1832. }
  1833. else {
  1834. sSearch = bRegex ? sSearch : _fnEscapeRegex(sSearch);
  1835. return new RegExp(sSearch, bCaseInsensitive ? "i" : "");
  1836. }
  1837. }
  1838. /**
  1839. * Convert raw data into something that the user can search on
  1840. * @param {string} sData data to be modified
  1841. * @param {string} sType data type
  1842. * @returns {string} search string
  1843. * @memberof DataTable#oApi
  1844. */
  1845. function _fnDataToSearch(sData, sType) {
  1846. if (typeof DataTable.ext.ofnSearch[sType] === "function") {
  1847. return DataTable.ext.ofnSearch[sType](sData);
  1848. }
  1849. else if (sData === null) {
  1850. return '';
  1851. }
  1852. else if (sType == "html") {
  1853. return sData.replace(/[\r\n]/g, " ").replace(/<.*?>/g, "");
  1854. }
  1855. else if (typeof sData === "string") {
  1856. return sData.replace(/[\r\n]/g, " ");
  1857. }
  1858. return sData;
  1859. }
  1860. /**
  1861. * scape a string such that it can be used in a regular expression
  1862. * @param {string} sVal string to escape
  1863. * @returns {string} escaped string
  1864. * @memberof DataTable#oApi
  1865. */
  1866. function _fnEscapeRegex(sVal) {
  1867. var acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ];
  1868. var reReplace = new RegExp('(\\' + acEscape.join('|\\') + ')', 'g');
  1869. return sVal.replace(reReplace, '\\$1');
  1870. }
  1871. /**
  1872. * Generate the node required for the info display
  1873. * @param {object} oSettings dataTables settings object
  1874. * @returns {node} Information element
  1875. * @memberof DataTable#oApi
  1876. */
  1877. function _fnFeatureHtmlInfo(oSettings) {
  1878. var nInfo = document.createElement('div');
  1879. nInfo.className = oSettings.oClasses.sInfo;
  1880. /* Actions that are to be taken once only for this feature */
  1881. if (!oSettings.aanFeatures.i) {
  1882. /* Add draw callback */
  1883. oSettings.aoDrawCallback.push({
  1884. "fn":_fnUpdateInfo,
  1885. "sName":"information"
  1886. });
  1887. /* Add id */
  1888. nInfo.id = oSettings.sTableId + '_info';
  1889. }
  1890. oSettings.nTable.setAttribute('aria-describedby', oSettings.sTableId + '_info');
  1891. return nInfo;
  1892. }
  1893. /**
  1894. * Update the information elements in the display
  1895. * @param {object} oSettings dataTables settings object
  1896. * @memberof DataTable#oApi
  1897. */
  1898. function _fnUpdateInfo(oSettings) {
  1899. /* Show information about the table */
  1900. if (!oSettings.oFeatures.bInfo || oSettings.aanFeatures.i.length === 0) {
  1901. return;
  1902. }
  1903. var
  1904. oLang = oSettings.oLanguage,
  1905. iStart = oSettings._iDisplayStart + 1,
  1906. iEnd = oSettings.fnDisplayEnd(),
  1907. iMax = oSettings.fnRecordsTotal(),
  1908. iTotal = oSettings.fnRecordsDisplay(),
  1909. sOut;
  1910. if (iTotal === 0) {
  1911. /* Empty record set */
  1912. sOut = oLang.sInfoEmpty;
  1913. }
  1914. else {
  1915. /* Normal record set */
  1916. sOut = oLang.sInfo;
  1917. }
  1918. if (iTotal != iMax) {
  1919. /* Record set after filtering */
  1920. sOut += ' ' + oLang.sInfoFiltered;
  1921. }
  1922. // Convert the macros
  1923. sOut += oLang.sInfoPostFix;
  1924. sOut = _fnInfoMacros(oSettings, sOut);
  1925. if (oLang.fnInfoCallback !== null) {
  1926. sOut = oLang.fnInfoCallback.call(oSettings.oInstance,
  1927. oSettings, iStart, iEnd, iMax, iTotal, sOut);
  1928. }
  1929. var n = oSettings.aanFeatures.i;
  1930. for (var i = 0, iLen = n.length; i < iLen; i++) {
  1931. $(n[i]).html(sOut);
  1932. }
  1933. }
  1934. function _fnInfoMacros(oSettings, str) {
  1935. var
  1936. iStart = oSettings._iDisplayStart + 1,
  1937. sStart = oSettings.fnFormatNumber(iStart),
  1938. iEnd = oSettings.fnDisplayEnd(),
  1939. sEnd = oSettings.fnFormatNumber(iEnd),
  1940. iTotal = oSettings.fnRecordsDisplay(),
  1941. sTotal = oSettings.fnFormatNumber(iTotal),
  1942. iMax = oSettings.fnRecordsTotal(),
  1943. sMax = oSettings.fnFormatNumber(iMax);
  1944. // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
  1945. // internally
  1946. if (oSettings.oScroll.bInfinite) {
  1947. sStart = oSettings.fnFormatNumber(1);
  1948. }
  1949. return str.
  1950. replace(/_START_/g, sStart).
  1951. replace(/_END_/g, sEnd).
  1952. replace(/_TOTAL_/g, sTotal).
  1953. replace(/_MAX_/g, sMax);
  1954. }
  1955. /**
  1956. * Draw the table for the first time, adding all required features
  1957. * @param {object} oSettings dataTables settings object
  1958. * @memberof DataTable#oApi
  1959. */
  1960. function _fnInitialise(oSettings) {
  1961. var i, iLen, iAjaxStart = oSettings.iInitDisplayStart;
  1962. /* Ensure that the table data is fully initialised */
  1963. if (oSettings.bInitialised === false) {
  1964. setTimeout(function () {
  1965. _fnInitialise(oSettings);
  1966. }, 200);
  1967. return;
  1968. }
  1969. /* Show the display HTML options */
  1970. _fnAddOptionsHtml(oSettings);
  1971. /* Build and draw the header / footer for the table */
  1972. _fnBuildHead(oSettings);
  1973. _fnDrawHead(oSettings, oSettings.aoHeader);
  1974. if (oSettings.nTFoot) {
  1975. _fnDrawHead(oSettings, oSettings.aoFooter);
  1976. }
  1977. /* Okay to show that something is going on now */
  1978. _fnProcessingDisplay(oSettings, true);
  1979. /* Calculate sizes for columns */
  1980. if (oSettings.oFeatures.bAutoWidth) {
  1981. _fnCalculateColumnWidths(oSettings);
  1982. }
  1983. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  1984. if (oSettings.aoColumns[i].sWidth !== null) {
  1985. oSettings.aoColumns[i].nTh.style.width = _fnStringToCss(oSettings.aoColumns[i].sWidth);
  1986. }
  1987. }
  1988. /* If there is default sorting required - let's do it. The sort function will do the
  1989. * drawing for us. Otherwise we draw the table regardless of the Ajax source - this allows
  1990. * the table to look initialised for Ajax sourcing data (show 'loading' message possibly)
  1991. */
  1992. if (oSettings.oFeatures.bSort) {
  1993. _fnSort(oSettings);
  1994. }
  1995. else if (oSettings.oFeatures.bFilter) {
  1996. _fnFilterComplete(oSettings, oSettings.oPreviousSearch);
  1997. }
  1998. else {
  1999. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  2000. _fnCalculateEnd(oSettings);
  2001. _fnDraw(oSettings);
  2002. }
  2003. /* if there is an ajax source load the data */
  2004. if (oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide) {
  2005. var aoData = [];
  2006. _fnServerParams(oSettings, aoData);
  2007. oSettings.fnServerData.call(oSettings.oInstance, oSettings.sAjaxSource, aoData, function (json) {
  2008. var aData = (oSettings.sAjaxDataProp !== "") ?
  2009. _fnGetObjectDataFn(oSettings.sAjaxDataProp)(json) : json;
  2010. /* Got the data - add it to the table */
  2011. for (i = 0; i < aData.length; i++) {
  2012. _fnAddData(oSettings, aData[i]);
  2013. }
  2014. /* Reset the init display for cookie saving. We've already done a filter, and
  2015. * therefore cleared it before. So we need to make it appear 'fresh'
  2016. */
  2017. oSettings.iInitDisplayStart = iAjaxStart;
  2018. if (oSettings.oFeatures.bSort) {
  2019. _fnSort(oSettings);
  2020. }
  2021. else {
  2022. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  2023. _fnCalculateEnd(oSettings);
  2024. _fnDraw(oSettings);
  2025. }
  2026. _fnProcessingDisplay(oSettings, false);
  2027. _fnInitComplete(oSettings, json);
  2028. }, oSettings);
  2029. return;
  2030. }
  2031. /* Server-side processing initialisation complete is done at the end of _fnDraw */
  2032. if (!oSettings.oFeatures.bServerSide) {
  2033. _fnProcessingDisplay(oSettings, false);
  2034. _fnInitComplete(oSettings);
  2035. }
  2036. }
  2037. /**
  2038. * Draw the table for the first time, adding all required features
  2039. * @param {object} oSettings dataTables settings object
  2040. * @param {object} [json] JSON from the server that completed the table, if using Ajax source
  2041. * with client-side processing (optional)
  2042. * @memberof DataTable#oApi
  2043. */
  2044. function _fnInitComplete(oSettings, json) {
  2045. oSettings._bInitComplete = true;
  2046. _fnCallbackFire(oSettings, 'aoInitComplete', 'init', [oSettings, json]);
  2047. }
  2048. /**
  2049. * Language compatibility - when certain options are given, and others aren't, we
  2050. * need to duplicate the values over, in order to provide backwards compatibility
  2051. * with older language files.
  2052. * @param {object} oSettings dataTables settings object
  2053. * @memberof DataTable#oApi
  2054. */
  2055. function _fnLanguageCompat(oLanguage) {
  2056. var oDefaults = DataTable.defaults.oLanguage;
  2057. /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
  2058. * sZeroRecords - assuming that is given.
  2059. */
  2060. if (!oLanguage.sEmptyTable && oLanguage.sZeroRecords &&
  2061. oDefaults.sEmptyTable === "No data available in table") {
  2062. _fnMap(oLanguage, oLanguage, 'sZeroRecords', 'sEmptyTable');
  2063. }
  2064. /* Likewise with loading records */
  2065. if (!oLanguage.sLoadingRecords && oLanguage.sZeroRecords &&
  2066. oDefaults.sLoadingRecords === "Loading...") {
  2067. _fnMap(oLanguage, oLanguage, 'sZeroRecords', 'sLoadingRecords');
  2068. }
  2069. }
  2070. /**
  2071. * Generate the node required for user display length changing
  2072. * @param {object} oSettings dataTables settings object
  2073. * @returns {node} Display length feature node
  2074. * @memberof DataTable#oApi
  2075. */
  2076. function _fnFeatureHtmlLength(oSettings) {
  2077. if (oSettings.oScroll.bInfinite) {
  2078. return null;
  2079. }
  2080. /* This can be overruled by not using the _MENU_ var/macro in the language variable */
  2081. var sName = 'name="' + oSettings.sTableId + '_length"';
  2082. var sStdMenu = '<select size="1" ' + sName + '>';
  2083. var i, iLen;
  2084. var aLengthMenu = oSettings.aLengthMenu;
  2085. if (aLengthMenu.length == 2 && typeof aLengthMenu[0] === 'object' &&
  2086. typeof aLengthMenu[1] === 'object') {
  2087. for (i = 0, iLen = aLengthMenu[0].length; i < iLen; i++) {
  2088. sStdMenu += '<option value="' + aLengthMenu[0][i] + '">' + aLengthMenu[1][i] + '</option>';
  2089. }
  2090. }
  2091. else {
  2092. for (i = 0, iLen = aLengthMenu.length; i < iLen; i++) {
  2093. sStdMenu += '<option value="' + aLengthMenu[i] + '">' + aLengthMenu[i] + '</option>';
  2094. }
  2095. }
  2096. sStdMenu += '</select>';
  2097. var nLength = document.createElement('div');
  2098. if (!oSettings.aanFeatures.l) {
  2099. nLength.id = oSettings.sTableId + '_length';
  2100. }
  2101. nLength.className = oSettings.oClasses.sLength;
  2102. nLength.innerHTML = '<label>' + oSettings.oLanguage.sLengthMenu.replace('_MENU_', sStdMenu) + '</label>';
  2103. /*
  2104. * Set the length to the current display length - thanks to Andrea Pavlovic for this fix,
  2105. * and Stefan Skopnik for fixing the fix!
  2106. */
  2107. $('select option[value="' + oSettings._iDisplayLength + '"]', nLength).attr("selected", true);
  2108. $('select', nLength).bind('change.DT', function (e) {
  2109. var iVal = $(this).val();
  2110. /* Update all other length options for the new display */
  2111. var n = oSettings.aanFeatures.l;
  2112. for (i = 0, iLen = n.length; i < iLen; i++) {
  2113. if (n[i] != this.parentNode) {
  2114. $('select', n[i]).val(iVal);
  2115. }
  2116. }
  2117. /* Redraw the table */
  2118. oSettings._iDisplayLength = parseInt(iVal, 10);
  2119. _fnCalculateEnd(oSettings);
  2120. /* If we have space to show extra rows (backing up from the end point - then do so */
  2121. if (oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay()) {
  2122. oSettings._iDisplayStart = oSettings.fnDisplayEnd() - oSettings._iDisplayLength;
  2123. if (oSettings._iDisplayStart < 0) {
  2124. oSettings._iDisplayStart = 0;
  2125. }
  2126. }
  2127. if (oSettings._iDisplayLength == -1) {
  2128. oSettings._iDisplayStart = 0;
  2129. }
  2130. _fnDraw(oSettings);
  2131. });
  2132. $('select', nLength).attr('aria-controls', oSettings.sTableId);
  2133. return nLength;
  2134. }
  2135. /**
  2136. * Recalculate the end point based on the start point
  2137. * @param {object} oSettings dataTables settings object
  2138. * @memberof DataTable#oApi
  2139. */
  2140. function _fnCalculateEnd(oSettings) {
  2141. if (oSettings.oFeatures.bPaginate === false) {
  2142. oSettings._iDisplayEnd = oSettings.aiDisplay.length;
  2143. }
  2144. else {
  2145. /* Set the end point of the display - based on how many elements there are
  2146. * still to display
  2147. */
  2148. if (oSettings._iDisplayStart + oSettings._iDisplayLength > oSettings.aiDisplay.length ||
  2149. oSettings._iDisplayLength == -1) {
  2150. oSettings._iDisplayEnd = oSettings.aiDisplay.length;
  2151. }
  2152. else {
  2153. oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength;
  2154. }
  2155. }
  2156. }
  2157. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2158. * Note that most of the paging logic is done in
  2159. * DataTable.ext.oPagination
  2160. */
  2161. /**
  2162. * Generate the node required for default pagination
  2163. * @param {object} oSettings dataTables settings object
  2164. * @returns {node} Pagination feature node
  2165. * @memberof DataTable#oApi
  2166. */
  2167. function _fnFeatureHtmlPaginate(oSettings) {
  2168. if (oSettings.oScroll.bInfinite) {
  2169. return null;
  2170. }
  2171. var nPaginate = document.createElement('div');
  2172. nPaginate.className = oSettings.oClasses.sPaging + oSettings.sPaginationType;
  2173. DataTable.ext.oPagination[ oSettings.sPaginationType ].fnInit(oSettings, nPaginate,
  2174. function (oSettings) {
  2175. _fnCalculateEnd(oSettings);
  2176. _fnDraw(oSettings);
  2177. }
  2178. );
  2179. /* Add a draw callback for the pagination on first instance, to update the paging display */
  2180. if (!oSettings.aanFeatures.p) {
  2181. oSettings.aoDrawCallback.push({
  2182. "fn":function (oSettings) {
  2183. DataTable.ext.oPagination[ oSettings.sPaginationType ].fnUpdate(oSettings, function (oSettings) {
  2184. _fnCalculateEnd(oSettings);
  2185. _fnDraw(oSettings);
  2186. });
  2187. },
  2188. "sName":"pagination"
  2189. });
  2190. }
  2191. return nPaginate;
  2192. }
  2193. /**
  2194. * Alter the display settings to change the page
  2195. * @param {object} oSettings dataTables settings object
  2196. * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
  2197. * or page number to jump to (integer)
  2198. * @returns {bool} true page has changed, false - no change (no effect) eg 'first' on page 1
  2199. * @memberof DataTable#oApi
  2200. */
  2201. function _fnPageChange(oSettings, mAction) {
  2202. var iOldStart = oSettings._iDisplayStart;
  2203. if (typeof mAction === "number") {
  2204. oSettings._iDisplayStart = mAction * oSettings._iDisplayLength;
  2205. if (oSettings._iDisplayStart > oSettings.fnRecordsDisplay()) {
  2206. oSettings._iDisplayStart = 0;
  2207. }
  2208. }
  2209. else if (mAction == "first") {
  2210. oSettings._iDisplayStart = 0;
  2211. }
  2212. else if (mAction == "previous") {
  2213. oSettings._iDisplayStart = oSettings._iDisplayLength >= 0 ?
  2214. oSettings._iDisplayStart - oSettings._iDisplayLength :
  2215. 0;
  2216. /* Correct for under-run */
  2217. if (oSettings._iDisplayStart < 0) {
  2218. oSettings._iDisplayStart = 0;
  2219. }
  2220. }
  2221. else if (mAction == "next") {
  2222. if (oSettings._iDisplayLength >= 0) {
  2223. /* Make sure we are not over running the display array */
  2224. if (oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay()) {
  2225. oSettings._iDisplayStart += oSettings._iDisplayLength;
  2226. }
  2227. }
  2228. else {
  2229. oSettings._iDisplayStart = 0;
  2230. }
  2231. }
  2232. else if (mAction == "last") {
  2233. if (oSettings._iDisplayLength >= 0) {
  2234. var iPages = parseInt((oSettings.fnRecordsDisplay() - 1) / oSettings._iDisplayLength, 10) + 1;
  2235. oSettings._iDisplayStart = (iPages - 1) * oSettings._iDisplayLength;
  2236. }
  2237. else {
  2238. oSettings._iDisplayStart = 0;
  2239. }
  2240. }
  2241. else {
  2242. _fnLog(oSettings, 0, "Unknown paging action: " + mAction);
  2243. }
  2244. $(oSettings.oInstance).trigger('page', oSettings);
  2245. return iOldStart != oSettings._iDisplayStart;
  2246. }
  2247. /**
  2248. * Generate the node required for the processing node
  2249. * @param {object} oSettings dataTables settings object
  2250. * @returns {node} Processing element
  2251. * @memberof DataTable#oApi
  2252. */
  2253. function _fnFeatureHtmlProcessing(oSettings) {
  2254. var nProcessing = document.createElement('div');
  2255. if (!oSettings.aanFeatures.r) {
  2256. nProcessing.id = oSettings.sTableId + '_processing';
  2257. }
  2258. nProcessing.innerHTML = oSettings.oLanguage.sProcessing;
  2259. nProcessing.className = oSettings.oClasses.sProcessing;
  2260. oSettings.nTable.parentNode.insertBefore(nProcessing, oSettings.nTable);
  2261. return nProcessing;
  2262. }
  2263. /**
  2264. * Display or hide the processing indicator
  2265. * @param {object} oSettings dataTables settings object
  2266. * @param {bool} bShow Show the processing indicator (true) or not (false)
  2267. * @memberof DataTable#oApi
  2268. */
  2269. function _fnProcessingDisplay(oSettings, bShow) {
  2270. if (oSettings.oFeatures.bProcessing) {
  2271. var an = oSettings.aanFeatures.r;
  2272. for (var i = 0, iLen = an.length; i < iLen; i++) {
  2273. an[i].style.visibility = bShow ? "visible" : "hidden";
  2274. }
  2275. }
  2276. $(oSettings.oInstance).trigger('processing', [oSettings, bShow]);
  2277. }
  2278. /**
  2279. * Add any control elements for the table - specifically scrolling
  2280. * @param {object} oSettings dataTables settings object
  2281. * @returns {node} Node to add to the DOM
  2282. * @memberof DataTable#oApi
  2283. */
  2284. function _fnFeatureHtmlTable(oSettings) {
  2285. /* Check if scrolling is enabled or not - if not then leave the DOM unaltered */
  2286. if (oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "") {
  2287. return oSettings.nTable;
  2288. }
  2289. /*
  2290. * The HTML structure that we want to generate in this function is:
  2291. * div - nScroller
  2292. * div - nScrollHead
  2293. * div - nScrollHeadInner
  2294. * table - nScrollHeadTable
  2295. * thead - nThead
  2296. * div - nScrollBody
  2297. * table - oSettings.nTable
  2298. * thead - nTheadSize
  2299. * tbody - nTbody
  2300. * div - nScrollFoot
  2301. * div - nScrollFootInner
  2302. * table - nScrollFootTable
  2303. * tfoot - nTfoot
  2304. */
  2305. var
  2306. nScroller = document.createElement('div'),
  2307. nScrollHead = document.createElement('div'),
  2308. nScrollHeadInner = document.createElement('div'),
  2309. nScrollBody = document.createElement('div'),
  2310. nScrollFoot = document.createElement('div'),
  2311. nScrollFootInner = document.createElement('div'),
  2312. nScrollHeadTable = oSettings.nTable.cloneNode(false),
  2313. nScrollFootTable = oSettings.nTable.cloneNode(false),
  2314. nThead = oSettings.nTable.getElementsByTagName('thead')[0],
  2315. nTfoot = oSettings.nTable.getElementsByTagName('tfoot').length === 0 ? null :
  2316. oSettings.nTable.getElementsByTagName('tfoot')[0],
  2317. oClasses = oSettings.oClasses;
  2318. nScrollHead.appendChild(nScrollHeadInner);
  2319. nScrollFoot.appendChild(nScrollFootInner);
  2320. nScrollBody.appendChild(oSettings.nTable);
  2321. nScroller.appendChild(nScrollHead);
  2322. nScroller.appendChild(nScrollBody);
  2323. nScrollHeadInner.appendChild(nScrollHeadTable);
  2324. nScrollHeadTable.appendChild(nThead);
  2325. if (nTfoot !== null) {
  2326. nScroller.appendChild(nScrollFoot);
  2327. nScrollFootInner.appendChild(nScrollFootTable);
  2328. nScrollFootTable.appendChild(nTfoot);
  2329. }
  2330. nScroller.className = oClasses.sScrollWrapper;
  2331. nScrollHead.className = oClasses.sScrollHead;
  2332. nScrollHeadInner.className = oClasses.sScrollHeadInner;
  2333. nScrollBody.className = oClasses.sScrollBody;
  2334. nScrollFoot.className = oClasses.sScrollFoot;
  2335. nScrollFootInner.className = oClasses.sScrollFootInner;
  2336. if (oSettings.oScroll.bAutoCss) {
  2337. nScrollHead.style.overflow = "hidden";
  2338. nScrollHead.style.position = "relative";
  2339. nScrollFoot.style.overflow = "hidden";
  2340. nScrollBody.style.overflow = "auto";
  2341. }
  2342. nScrollHead.style.border = "0";
  2343. nScrollHead.style.width = "100%";
  2344. nScrollFoot.style.border = "0";
  2345. nScrollHeadInner.style.width = oSettings.oScroll.sXInner !== "" ?
  2346. oSettings.oScroll.sXInner : "100%";
  2347. /* will be overwritten */
  2348. /* Modify attributes to respect the clones */
  2349. nScrollHeadTable.removeAttribute('id');
  2350. nScrollHeadTable.style.marginLeft = "0";
  2351. oSettings.nTable.style.marginLeft = "0";
  2352. if (nTfoot !== null) {
  2353. nScrollFootTable.removeAttribute('id');
  2354. nScrollFootTable.style.marginLeft = "0";
  2355. }
  2356. /* Move caption elements from the body to the header, footer or leave where it is
  2357. * depending on the configuration. Note that the DTD says there can be only one caption */
  2358. var nCaption = $(oSettings.nTable).children('caption');
  2359. if (nCaption.length > 0) {
  2360. nCaption = nCaption[0];
  2361. if (nCaption._captionSide === "top") {
  2362. nScrollHeadTable.appendChild(nCaption);
  2363. }
  2364. else if (nCaption._captionSide === "bottom" && nTfoot) {
  2365. nScrollFootTable.appendChild(nCaption);
  2366. }
  2367. }
  2368. /*
  2369. * Sizing
  2370. */
  2371. /* When x-scrolling add the width and a scroller to move the header with the body */
  2372. if (oSettings.oScroll.sX !== "") {
  2373. nScrollHead.style.width = _fnStringToCss(oSettings.oScroll.sX);
  2374. nScrollBody.style.width = _fnStringToCss(oSettings.oScroll.sX);
  2375. if (nTfoot !== null) {
  2376. nScrollFoot.style.width = _fnStringToCss(oSettings.oScroll.sX);
  2377. }
  2378. /* When the body is scrolled, then we also want to scroll the headers */
  2379. $(nScrollBody).scroll(function (e) {
  2380. nScrollHead.scrollLeft = this.scrollLeft;
  2381. if (nTfoot !== null) {
  2382. nScrollFoot.scrollLeft = this.scrollLeft;
  2383. }
  2384. });
  2385. }
  2386. /* When yscrolling, add the height */
  2387. if (oSettings.oScroll.sY !== "") {
  2388. nScrollBody.style.height = _fnStringToCss(oSettings.oScroll.sY);
  2389. }
  2390. /* Redraw - align columns across the tables */
  2391. oSettings.aoDrawCallback.push({
  2392. "fn":_fnScrollDraw,
  2393. "sName":"scrolling"
  2394. });
  2395. /* Infinite scrolling event handlers */
  2396. if (oSettings.oScroll.bInfinite) {
  2397. $(nScrollBody).scroll(function () {
  2398. /* Use a blocker to stop scrolling from loading more data while other data is still loading */
  2399. if (!oSettings.bDrawing && $(this).scrollTop() !== 0) {
  2400. /* Check if we should load the next data set */
  2401. if ($(this).scrollTop() + $(this).height() >
  2402. $(oSettings.nTable).height() - oSettings.oScroll.iLoadGap) {
  2403. /* Only do the redraw if we have to - we might be at the end of the data */
  2404. if (oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay()) {
  2405. _fnPageChange(oSettings, 'next');
  2406. _fnCalculateEnd(oSettings);
  2407. _fnDraw(oSettings);
  2408. }
  2409. }
  2410. }
  2411. });
  2412. }
  2413. oSettings.nScrollHead = nScrollHead;
  2414. oSettings.nScrollFoot = nScrollFoot;
  2415. return nScroller;
  2416. }
  2417. /**
  2418. * Update the various tables for resizing. It's a bit of a pig this function, but
  2419. * basically the idea to:
  2420. * 1. Re-create the table inside the scrolling div
  2421. * 2. Take live measurements from the DOM
  2422. * 3. Apply the measurements
  2423. * 4. Clean up
  2424. * @param {object} o dataTables settings object
  2425. * @returns {node} Node to add to the DOM
  2426. * @memberof DataTable#oApi
  2427. */
  2428. function _fnScrollDraw(o) {
  2429. var
  2430. nScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0],
  2431. nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],
  2432. nScrollBody = o.nTable.parentNode,
  2433. i, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis,
  2434. nTheadSize, nTfootSize,
  2435. iWidth, aApplied = [], aAppliedFooter = [], iSanityWidth,
  2436. nScrollFootInner = (o.nTFoot !== null) ? o.nScrollFoot.getElementsByTagName('div')[0] : null,
  2437. nScrollFootTable = (o.nTFoot !== null) ? nScrollFootInner.getElementsByTagName('table')[0] : null,
  2438. ie67 = o.oBrowser.bScrollOversize,
  2439. zeroOut = function (nSizer) {
  2440. oStyle = nSizer.style;
  2441. oStyle.paddingTop = "0";
  2442. oStyle.paddingBottom = "0";
  2443. oStyle.borderTopWidth = "0";
  2444. oStyle.borderBottomWidth = "0";
  2445. oStyle.height = 0;
  2446. };
  2447. /*
  2448. * 1. Re-create the table inside the scrolling div
  2449. */
  2450. /* Remove the old minimised thead and tfoot elements in the inner table */
  2451. $(o.nTable).children('thead, tfoot').remove();
  2452. /* Clone the current header and footer elements and then place it into the inner table */
  2453. nTheadSize = $(o.nTHead).clone()[0];
  2454. o.nTable.insertBefore(nTheadSize, o.nTable.childNodes[0]);
  2455. anHeadToSize = o.nTHead.getElementsByTagName('tr');
  2456. anHeadSizers = nTheadSize.getElementsByTagName('tr');
  2457. if (o.nTFoot !== null) {
  2458. nTfootSize = $(o.nTFoot).clone()[0];
  2459. o.nTable.insertBefore(nTfootSize, o.nTable.childNodes[1]);
  2460. anFootToSize = o.nTFoot.getElementsByTagName('tr');
  2461. anFootSizers = nTfootSize.getElementsByTagName('tr');
  2462. }
  2463. /*
  2464. * 2. Take live measurements from the DOM - do not alter the DOM itself!
  2465. */
  2466. /* Remove old sizing and apply the calculated column widths
  2467. * Get the unique column headers in the newly created (cloned) header. We want to apply the
  2468. * calculated sizes to this header
  2469. */
  2470. if (o.oScroll.sX === "") {
  2471. nScrollBody.style.width = '100%';
  2472. nScrollHeadInner.parentNode.style.width = '100%';
  2473. }
  2474. var nThs = _fnGetUniqueThs(o, nTheadSize);
  2475. for (i = 0, iLen = nThs.length; i < iLen; i++) {
  2476. iVis = _fnVisibleToColumnIndex(o, i);
  2477. nThs[i].style.width = o.aoColumns[iVis].sWidth;
  2478. }
  2479. if (o.nTFoot !== null) {
  2480. _fnApplyToChildren(function (n) {
  2481. n.style.width = "";
  2482. }, anFootSizers);
  2483. }
  2484. // If scroll collapse is enabled, when we put the headers back into the body for sizing, we
  2485. // will end up forcing the scrollbar to appear, making our measurements wrong for when we
  2486. // then hide it (end of this function), so add the header height to the body scroller.
  2487. if (o.oScroll.bCollapse && o.oScroll.sY !== "") {
  2488. nScrollBody.style.height = (nScrollBody.offsetHeight + o.nTHead.offsetHeight) + "px";
  2489. }
  2490. /* Size the table as a whole */
  2491. iSanityWidth = $(o.nTable).outerWidth();
  2492. if (o.oScroll.sX === "") {
  2493. /* No x scrolling */
  2494. o.nTable.style.width = "100%";
  2495. /* I know this is rubbish - but IE7 will make the width of the table when 100% include
  2496. * the scrollbar - which is shouldn't. When there is a scrollbar we need to take this
  2497. * into account.
  2498. */
  2499. if (ie67 && ($('tbody', nScrollBody).height() > nScrollBody.offsetHeight ||
  2500. $(nScrollBody).css('overflow-y') == "scroll")) {
  2501. o.nTable.style.width = _fnStringToCss($(o.nTable).outerWidth() - o.oScroll.iBarWidth);
  2502. }
  2503. }
  2504. else {
  2505. if (o.oScroll.sXInner !== "") {
  2506. /* x scroll inner has been given - use it */
  2507. o.nTable.style.width = _fnStringToCss(o.oScroll.sXInner);
  2508. }
  2509. else if (iSanityWidth == $(nScrollBody).width() &&
  2510. $(nScrollBody).height() < $(o.nTable).height()) {
  2511. /* There is y-scrolling - try to take account of the y scroll bar */
  2512. o.nTable.style.width = _fnStringToCss(iSanityWidth - o.oScroll.iBarWidth);
  2513. if ($(o.nTable).outerWidth() > iSanityWidth - o.oScroll.iBarWidth) {
  2514. /* Not possible to take account of it */
  2515. o.nTable.style.width = _fnStringToCss(iSanityWidth);
  2516. }
  2517. }
  2518. else {
  2519. /* All else fails */
  2520. o.nTable.style.width = _fnStringToCss(iSanityWidth);
  2521. }
  2522. }
  2523. /* Recalculate the sanity width - now that we've applied the required width, before it was
  2524. * a temporary variable. This is required because the column width calculation is done
  2525. * before this table DOM is created.
  2526. */
  2527. iSanityWidth = $(o.nTable).outerWidth();
  2528. /* We want the hidden header to have zero height, so remove padding and borders. Then
  2529. * set the width based on the real headers
  2530. */
  2531. // Apply all styles in one pass. Invalidates layout only once because we don't read any
  2532. // DOM properties.
  2533. _fnApplyToChildren(zeroOut, anHeadSizers);
  2534. // Read all widths in next pass. Forces layout only once because we do not change
  2535. // any DOM properties.
  2536. _fnApplyToChildren(function (nSizer) {
  2537. aApplied.push(_fnStringToCss($(nSizer).width()));
  2538. }, anHeadSizers);
  2539. // Apply all widths in final pass. Invalidates layout only once because we do not
  2540. // read any DOM properties.
  2541. _fnApplyToChildren(function (nToSize, i) {
  2542. nToSize.style.width = aApplied[i];
  2543. }, anHeadToSize);
  2544. $(anHeadSizers).height(0);
  2545. /* Same again with the footer if we have one */
  2546. if (o.nTFoot !== null) {
  2547. _fnApplyToChildren(zeroOut, anFootSizers);
  2548. _fnApplyToChildren(function (nSizer) {
  2549. aAppliedFooter.push(_fnStringToCss($(nSizer).width()));
  2550. }, anFootSizers);
  2551. _fnApplyToChildren(function (nToSize, i) {
  2552. nToSize.style.width = aAppliedFooter[i];
  2553. }, anFootToSize);
  2554. $(anFootSizers).height(0);
  2555. }
  2556. /*
  2557. * 3. Apply the measurements
  2558. */
  2559. /* "Hide" the header and footer that we used for the sizing. We want to also fix their width
  2560. * to what they currently are
  2561. */
  2562. _fnApplyToChildren(function (nSizer, i) {
  2563. nSizer.innerHTML = "";
  2564. nSizer.style.width = aApplied[i];
  2565. }, anHeadSizers);
  2566. if (o.nTFoot !== null) {
  2567. _fnApplyToChildren(function (nSizer, i) {
  2568. nSizer.innerHTML = "";
  2569. nSizer.style.width = aAppliedFooter[i];
  2570. }, anFootSizers);
  2571. }
  2572. /* Sanity check that the table is of a sensible width. If not then we are going to get
  2573. * misalignment - try to prevent this by not allowing the table to shrink below its min width
  2574. */
  2575. if ($(o.nTable).outerWidth() < iSanityWidth) {
  2576. /* The min width depends upon if we have a vertical scrollbar visible or not */
  2577. var iCorrection = ((nScrollBody.scrollHeight > nScrollBody.offsetHeight ||
  2578. $(nScrollBody).css('overflow-y') == "scroll")) ?
  2579. iSanityWidth + o.oScroll.iBarWidth : iSanityWidth;
  2580. /* IE6/7 are a law unto themselves... */
  2581. if (ie67 && (nScrollBody.scrollHeight >
  2582. nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll")) {
  2583. o.nTable.style.width = _fnStringToCss(iCorrection - o.oScroll.iBarWidth);
  2584. }
  2585. /* Apply the calculated minimum width to the table wrappers */
  2586. nScrollBody.style.width = _fnStringToCss(iCorrection);
  2587. o.nScrollHead.style.width = _fnStringToCss(iCorrection);
  2588. if (o.nTFoot !== null) {
  2589. o.nScrollFoot.style.width = _fnStringToCss(iCorrection);
  2590. }
  2591. /* And give the user a warning that we've stopped the table getting too small */
  2592. if (o.oScroll.sX === "") {
  2593. _fnLog(o, 1, "The table cannot fit into the current element which will cause column" +
  2594. " misalignment. The table has been drawn at its minimum possible width.");
  2595. }
  2596. else if (o.oScroll.sXInner !== "") {
  2597. _fnLog(o, 1, "The table cannot fit into the current element which will cause column" +
  2598. " misalignment. Increase the sScrollXInner value or remove it to allow automatic" +
  2599. " calculation");
  2600. }
  2601. }
  2602. else {
  2603. nScrollBody.style.width = _fnStringToCss('100%');
  2604. o.nScrollHead.style.width = _fnStringToCss('100%');
  2605. if (o.nTFoot !== null) {
  2606. o.nScrollFoot.style.width = _fnStringToCss('100%');
  2607. }
  2608. }
  2609. /*
  2610. * 4. Clean up
  2611. */
  2612. if (o.oScroll.sY === "") {
  2613. /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
  2614. * the scrollbar height from the visible display, rather than adding it on. We need to
  2615. * set the height in order to sort this. Don't want to do it in any other browsers.
  2616. */
  2617. if (ie67) {
  2618. nScrollBody.style.height = _fnStringToCss(o.nTable.offsetHeight + o.oScroll.iBarWidth);
  2619. }
  2620. }
  2621. if (o.oScroll.sY !== "" && o.oScroll.bCollapse) {
  2622. nScrollBody.style.height = _fnStringToCss(o.oScroll.sY);
  2623. var iExtra = (o.oScroll.sX !== "" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ?
  2624. o.oScroll.iBarWidth : 0;
  2625. if (o.nTable.offsetHeight < nScrollBody.offsetHeight) {
  2626. nScrollBody.style.height = _fnStringToCss(o.nTable.offsetHeight + iExtra);
  2627. }
  2628. }
  2629. /* Finally set the width's of the header and footer tables */
  2630. var iOuterWidth = $(o.nTable).outerWidth();
  2631. nScrollHeadTable.style.width = _fnStringToCss(iOuterWidth);
  2632. nScrollHeadInner.style.width = _fnStringToCss(iOuterWidth);
  2633. // Figure out if there are scrollbar present - if so then we need a the header and footer to
  2634. // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
  2635. var bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll";
  2636. nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth + "px" : "0px";
  2637. if (o.nTFoot !== null) {
  2638. nScrollFootTable.style.width = _fnStringToCss(iOuterWidth);
  2639. nScrollFootInner.style.width = _fnStringToCss(iOuterWidth);
  2640. nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth + "px" : "0px";
  2641. }
  2642. /* Adjust the position of the header in case we loose the y-scrollbar */
  2643. $(nScrollBody).scroll();
  2644. /* If sorting or filtering has occurred, jump the scrolling back to the top */
  2645. if (o.bSorted || o.bFiltered) {
  2646. nScrollBody.scrollTop = 0;
  2647. }
  2648. }
  2649. /**
  2650. * Apply a given function to the display child nodes of an element array (typically
  2651. * TD children of TR rows
  2652. * @param {function} fn Method to apply to the objects
  2653. * @param array {nodes} an1 List of elements to look through for display children
  2654. * @param array {nodes} an2 Another list (identical structure to the first) - optional
  2655. * @memberof DataTable#oApi
  2656. */
  2657. function _fnApplyToChildren(fn, an1, an2) {
  2658. var index = 0, i = 0, iLen = an1.length;
  2659. var nNode1, nNode2;
  2660. while (i < iLen) {
  2661. nNode1 = an1[i].firstChild;
  2662. nNode2 = an2 ? an2[i].firstChild : null;
  2663. while (nNode1) {
  2664. if (nNode1.nodeType === 1) {
  2665. if (an2) {
  2666. fn(nNode1, nNode2, index);
  2667. }
  2668. else {
  2669. fn(nNode1, index);
  2670. }
  2671. index++;
  2672. }
  2673. nNode1 = nNode1.nextSibling;
  2674. nNode2 = an2 ? nNode2.nextSibling : null;
  2675. }
  2676. i++;
  2677. }
  2678. }
  2679. /**
  2680. * Convert a CSS unit width to pixels (e.g. 2em)
  2681. * @param {string} sWidth width to be converted
  2682. * @param {node} nParent parent to get the with for (required for relative widths) - optional
  2683. * @returns {int} iWidth width in pixels
  2684. * @memberof DataTable#oApi
  2685. */
  2686. function _fnConvertToWidth(sWidth, nParent) {
  2687. if (!sWidth || sWidth === null || sWidth === '') {
  2688. return 0;
  2689. }
  2690. if (!nParent) {
  2691. nParent = document.body;
  2692. }
  2693. var iWidth;
  2694. var nTmp = document.createElement("div");
  2695. nTmp.style.width = _fnStringToCss(sWidth);
  2696. nParent.appendChild(nTmp);
  2697. iWidth = nTmp.offsetWidth;
  2698. nParent.removeChild(nTmp);
  2699. return ( iWidth );
  2700. }
  2701. /**
  2702. * Calculate the width of columns for the table
  2703. * @param {object} oSettings dataTables settings object
  2704. * @memberof DataTable#oApi
  2705. */
  2706. function _fnCalculateColumnWidths(oSettings) {
  2707. var iTableWidth = oSettings.nTable.offsetWidth;
  2708. var iUserInputs = 0;
  2709. var iTmpWidth;
  2710. var iVisibleColumns = 0;
  2711. var iColums = oSettings.aoColumns.length;
  2712. var i, iIndex, iCorrector, iWidth;
  2713. var oHeaders = $('th', oSettings.nTHead);
  2714. var widthAttr = oSettings.nTable.getAttribute('width');
  2715. var nWrapper = oSettings.nTable.parentNode;
  2716. /* Convert any user input sizes into pixel sizes */
  2717. for (i = 0; i < iColums; i++) {
  2718. if (oSettings.aoColumns[i].bVisible) {
  2719. iVisibleColumns++;
  2720. if (oSettings.aoColumns[i].sWidth !== null) {
  2721. iTmpWidth = _fnConvertToWidth(oSettings.aoColumns[i].sWidthOrig,
  2722. nWrapper);
  2723. if (iTmpWidth !== null) {
  2724. oSettings.aoColumns[i].sWidth = _fnStringToCss(iTmpWidth);
  2725. }
  2726. iUserInputs++;
  2727. }
  2728. }
  2729. }
  2730. /* If the number of columns in the DOM equals the number that we have to process in
  2731. * DataTables, then we can use the offsets that are created by the web-browser. No custom
  2732. * sizes can be set in order for this to happen, nor scrolling used
  2733. */
  2734. if (iColums == oHeaders.length && iUserInputs === 0 && iVisibleColumns == iColums &&
  2735. oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "") {
  2736. for (i = 0; i < oSettings.aoColumns.length; i++) {
  2737. iTmpWidth = $(oHeaders[i]).width();
  2738. if (iTmpWidth !== null) {
  2739. oSettings.aoColumns[i].sWidth = _fnStringToCss(iTmpWidth);
  2740. }
  2741. }
  2742. }
  2743. else {
  2744. /* Otherwise we are going to have to do some calculations to get the width of each column.
  2745. * Construct a 1 row table with the widest node in the data, and any user defined widths,
  2746. * then insert it into the DOM and allow the browser to do all the hard work of
  2747. * calculating table widths.
  2748. */
  2749. var
  2750. nCalcTmp = oSettings.nTable.cloneNode(false),
  2751. nTheadClone = oSettings.nTHead.cloneNode(true),
  2752. nBody = document.createElement('tbody'),
  2753. nTr = document.createElement('tr'),
  2754. nDivSizing;
  2755. nCalcTmp.removeAttribute("id");
  2756. nCalcTmp.appendChild(nTheadClone);
  2757. if (oSettings.nTFoot !== null) {
  2758. nCalcTmp.appendChild(oSettings.nTFoot.cloneNode(true));
  2759. _fnApplyToChildren(function (n) {
  2760. n.style.width = "";
  2761. }, nCalcTmp.getElementsByTagName('tr'));
  2762. }
  2763. nCalcTmp.appendChild(nBody);
  2764. nBody.appendChild(nTr);
  2765. /* Remove any sizing that was previously applied by the styles */
  2766. var jqColSizing = $('thead th', nCalcTmp);
  2767. if (jqColSizing.length === 0) {
  2768. jqColSizing = $('tbody tr:eq(0)>td', nCalcTmp);
  2769. }
  2770. /* Apply custom sizing to the cloned header */
  2771. var nThs = _fnGetUniqueThs(oSettings, nTheadClone);
  2772. iCorrector = 0;
  2773. for (i = 0; i < iColums; i++) {
  2774. var oColumn = oSettings.aoColumns[i];
  2775. if (oColumn.bVisible && oColumn.sWidthOrig !== null && oColumn.sWidthOrig !== "") {
  2776. nThs[i - iCorrector].style.width = _fnStringToCss(oColumn.sWidthOrig);
  2777. }
  2778. else if (oColumn.bVisible) {
  2779. nThs[i - iCorrector].style.width = "";
  2780. }
  2781. else {
  2782. iCorrector++;
  2783. }
  2784. }
  2785. /* Find the biggest td for each column and put it into the table */
  2786. for (i = 0; i < iColums; i++) {
  2787. if (oSettings.aoColumns[i].bVisible) {
  2788. var nTd = _fnGetWidestNode(oSettings, i);
  2789. if (nTd !== null) {
  2790. nTd = nTd.cloneNode(true);
  2791. if (oSettings.aoColumns[i].sContentPadding !== "") {
  2792. nTd.innerHTML += oSettings.aoColumns[i].sContentPadding;
  2793. }
  2794. nTr.appendChild(nTd);
  2795. }
  2796. }
  2797. }
  2798. /* Build the table and 'display' it */
  2799. nWrapper.appendChild(nCalcTmp);
  2800. /* When scrolling (X or Y) we want to set the width of the table as appropriate. However,
  2801. * when not scrolling leave the table width as it is. This results in slightly different,
  2802. * but I think correct behaviour
  2803. */
  2804. if (oSettings.oScroll.sX !== "" && oSettings.oScroll.sXInner !== "") {
  2805. nCalcTmp.style.width = _fnStringToCss(oSettings.oScroll.sXInner);
  2806. }
  2807. else if (oSettings.oScroll.sX !== "") {
  2808. nCalcTmp.style.width = "";
  2809. if ($(nCalcTmp).width() < nWrapper.offsetWidth) {
  2810. nCalcTmp.style.width = _fnStringToCss(nWrapper.offsetWidth);
  2811. }
  2812. }
  2813. else if (oSettings.oScroll.sY !== "") {
  2814. nCalcTmp.style.width = _fnStringToCss(nWrapper.offsetWidth);
  2815. }
  2816. else if (widthAttr) {
  2817. nCalcTmp.style.width = _fnStringToCss(widthAttr);
  2818. }
  2819. nCalcTmp.style.visibility = "hidden";
  2820. /* Scrolling considerations */
  2821. _fnScrollingWidthAdjust(oSettings, nCalcTmp);
  2822. /* Read the width's calculated by the browser and store them for use by the caller. We
  2823. * first of all try to use the elements in the body, but it is possible that there are
  2824. * no elements there, under which circumstances we use the header elements
  2825. */
  2826. var oNodes = $("tbody tr:eq(0)", nCalcTmp).children();
  2827. if (oNodes.length === 0) {
  2828. oNodes = _fnGetUniqueThs(oSettings, $('thead', nCalcTmp)[0]);
  2829. }
  2830. /* Browsers need a bit of a hand when a width is assigned to any columns when
  2831. * x-scrolling as they tend to collapse the table to the min-width, even if
  2832. * we sent the column widths. So we need to keep track of what the table width
  2833. * should be by summing the user given values, and the automatic values
  2834. */
  2835. if (oSettings.oScroll.sX !== "") {
  2836. var iTotal = 0;
  2837. iCorrector = 0;
  2838. for (i = 0; i < oSettings.aoColumns.length; i++) {
  2839. if (oSettings.aoColumns[i].bVisible) {
  2840. if (oSettings.aoColumns[i].sWidthOrig === null) {
  2841. iTotal += $(oNodes[iCorrector]).outerWidth();
  2842. }
  2843. else {
  2844. iTotal += parseInt(oSettings.aoColumns[i].sWidth.replace('px', ''), 10) +
  2845. ($(oNodes[iCorrector]).outerWidth() - $(oNodes[iCorrector]).width());
  2846. }
  2847. iCorrector++;
  2848. }
  2849. }
  2850. nCalcTmp.style.width = _fnStringToCss(iTotal);
  2851. oSettings.nTable.style.width = _fnStringToCss(iTotal);
  2852. }
  2853. iCorrector = 0;
  2854. for (i = 0; i < oSettings.aoColumns.length; i++) {
  2855. if (oSettings.aoColumns[i].bVisible) {
  2856. iWidth = $(oNodes[iCorrector]).width();
  2857. if (iWidth !== null && iWidth > 0) {
  2858. oSettings.aoColumns[i].sWidth = _fnStringToCss(iWidth);
  2859. }
  2860. iCorrector++;
  2861. }
  2862. }
  2863. var cssWidth = $(nCalcTmp).css('width');
  2864. oSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ?
  2865. cssWidth : _fnStringToCss($(nCalcTmp).outerWidth());
  2866. nCalcTmp.parentNode.removeChild(nCalcTmp);
  2867. }
  2868. if (widthAttr) {
  2869. oSettings.nTable.style.width = _fnStringToCss(widthAttr);
  2870. }
  2871. }
  2872. /**
  2873. * Adjust a table's width to take account of scrolling
  2874. * @param {object} oSettings dataTables settings object
  2875. * @param {node} n table node
  2876. * @memberof DataTable#oApi
  2877. */
  2878. function _fnScrollingWidthAdjust(oSettings, n) {
  2879. if (oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "") {
  2880. /* When y-scrolling only, we want to remove the width of the scroll bar so the table
  2881. * + scroll bar will fit into the area avaialble.
  2882. */
  2883. var iOrigWidth = $(n).width();
  2884. n.style.width = _fnStringToCss($(n).outerWidth() - oSettings.oScroll.iBarWidth);
  2885. }
  2886. else if (oSettings.oScroll.sX !== "") {
  2887. /* When x-scrolling both ways, fix the table at it's current size, without adjusting */
  2888. n.style.width = _fnStringToCss($(n).outerWidth());
  2889. }
  2890. }
  2891. /**
  2892. * Get the widest node
  2893. * @param {object} oSettings dataTables settings object
  2894. * @param {int} iCol column of interest
  2895. * @returns {node} widest table node
  2896. * @memberof DataTable#oApi
  2897. */
  2898. function _fnGetWidestNode(oSettings, iCol) {
  2899. var iMaxIndex = _fnGetMaxLenString(oSettings, iCol);
  2900. if (iMaxIndex < 0) {
  2901. return null;
  2902. }
  2903. if (oSettings.aoData[iMaxIndex].nTr === null) {
  2904. var n = document.createElement('td');
  2905. n.innerHTML = _fnGetCellData(oSettings, iMaxIndex, iCol, '');
  2906. return n;
  2907. }
  2908. return _fnGetTdNodes(oSettings, iMaxIndex)[iCol];
  2909. }
  2910. /**
  2911. * Get the maximum strlen for each data column
  2912. * @param {object} oSettings dataTables settings object
  2913. * @param {int} iCol column of interest
  2914. * @returns {string} max string length for each column
  2915. * @memberof DataTable#oApi
  2916. */
  2917. function _fnGetMaxLenString(oSettings, iCol) {
  2918. var iMax = -1;
  2919. var iMaxIndex = -1;
  2920. for (var i = 0; i < oSettings.aoData.length; i++) {
  2921. var s = _fnGetCellData(oSettings, i, iCol, 'display') + "";
  2922. s = s.replace(/<.*?>/g, "");
  2923. if (s.length > iMax) {
  2924. iMax = s.length;
  2925. iMaxIndex = i;
  2926. }
  2927. }
  2928. return iMaxIndex;
  2929. }
  2930. /**
  2931. * Append a CSS unit (only if required) to a string
  2932. * @param {array} aArray1 first array
  2933. * @param {array} aArray2 second array
  2934. * @returns {int} 0 if match, 1 if length is different, 2 if no match
  2935. * @memberof DataTable#oApi
  2936. */
  2937. function _fnStringToCss(s) {
  2938. if (s === null) {
  2939. return "0px";
  2940. }
  2941. if (typeof s == 'number') {
  2942. if (s < 0) {
  2943. return "0px";
  2944. }
  2945. return s + "px";
  2946. }
  2947. /* Check if the last character is not 0-9 */
  2948. var c = s.charCodeAt(s.length - 1);
  2949. if (c < 0x30 || c > 0x39) {
  2950. return s;
  2951. }
  2952. return s + "px";
  2953. }
  2954. /**
  2955. * Get the width of a scroll bar in this browser being used
  2956. * @returns {int} width in pixels
  2957. * @memberof DataTable#oApi
  2958. */
  2959. function _fnScrollBarWidth() {
  2960. var inner = document.createElement('p');
  2961. var style = inner.style;
  2962. style.width = "100%";
  2963. style.height = "200px";
  2964. style.padding = "0px";
  2965. var outer = document.createElement('div');
  2966. style = outer.style;
  2967. style.position = "absolute";
  2968. style.top = "0px";
  2969. style.left = "0px";
  2970. style.visibility = "hidden";
  2971. style.width = "200px";
  2972. style.height = "150px";
  2973. style.padding = "0px";
  2974. style.overflow = "hidden";
  2975. outer.appendChild(inner);
  2976. document.body.appendChild(outer);
  2977. var w1 = inner.offsetWidth;
  2978. outer.style.overflow = 'scroll';
  2979. var w2 = inner.offsetWidth;
  2980. if (w1 == w2) {
  2981. w2 = outer.clientWidth;
  2982. }
  2983. document.body.removeChild(outer);
  2984. return (w1 - w2);
  2985. }
  2986. /**
  2987. * Change the order of the table
  2988. * @param {object} oSettings dataTables settings object
  2989. * @param {bool} bApplyClasses optional - should we apply classes or not
  2990. * @memberof DataTable#oApi
  2991. */
  2992. function _fnSort(oSettings, bApplyClasses) {
  2993. var
  2994. i, iLen, j, jLen, k, kLen,
  2995. sDataType, nTh,
  2996. aaSort = [],
  2997. aiOrig = [],
  2998. oSort = DataTable.ext.oSort,
  2999. aoData = oSettings.aoData,
  3000. aoColumns = oSettings.aoColumns,
  3001. oAria = oSettings.oLanguage.oAria;
  3002. /* No sorting required if server-side or no sorting array */
  3003. if (!oSettings.oFeatures.bServerSide &&
  3004. (oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null)) {
  3005. aaSort = ( oSettings.aaSortingFixed !== null ) ?
  3006. oSettings.aaSortingFixed.concat(oSettings.aaSorting) :
  3007. oSettings.aaSorting.slice();
  3008. /* If there is a sorting data type, and a function belonging to it, then we need to
  3009. * get the data from the developer's function and apply it for this column
  3010. */
  3011. for (i = 0; i < aaSort.length; i++) {
  3012. var iColumn = aaSort[i][0];
  3013. var iVisColumn = _fnColumnIndexToVisible(oSettings, iColumn);
  3014. sDataType = oSettings.aoColumns[ iColumn ].sSortDataType;
  3015. if (DataTable.ext.afnSortData[sDataType]) {
  3016. var aData = DataTable.ext.afnSortData[sDataType].call(
  3017. oSettings.oInstance, oSettings, iColumn, iVisColumn
  3018. );
  3019. if (aData.length === aoData.length) {
  3020. for (j = 0, jLen = aoData.length; j < jLen; j++) {
  3021. _fnSetCellData(oSettings, j, iColumn, aData[j]);
  3022. }
  3023. }
  3024. else {
  3025. _fnLog(oSettings, 0, "Returned data sort array (col " + iColumn + ") is the wrong length");
  3026. }
  3027. }
  3028. }
  3029. /* Create a value - key array of the current row positions such that we can use their
  3030. * current position during the sort, if values match, in order to perform stable sorting
  3031. */
  3032. for (i = 0, iLen = oSettings.aiDisplayMaster.length; i < iLen; i++) {
  3033. aiOrig[ oSettings.aiDisplayMaster[i] ] = i;
  3034. }
  3035. /* Build an internal data array which is specific to the sort, so we can get and prep
  3036. * the data to be sorted only once, rather than needing to do it every time the sorting
  3037. * function runs. This make the sorting function a very simple comparison
  3038. */
  3039. var iSortLen = aaSort.length;
  3040. var fnSortFormat, aDataSort;
  3041. for (i = 0, iLen = aoData.length; i < iLen; i++) {
  3042. for (j = 0; j < iSortLen; j++) {
  3043. aDataSort = aoColumns[ aaSort[j][0] ].aDataSort;
  3044. for (k = 0, kLen = aDataSort.length; k < kLen; k++) {
  3045. sDataType = aoColumns[ aDataSort[k] ].sType;
  3046. fnSortFormat = oSort[ (sDataType ? sDataType : 'string') + "-pre" ];
  3047. aoData[i]._aSortData[ aDataSort[k] ] = fnSortFormat ?
  3048. fnSortFormat(_fnGetCellData(oSettings, i, aDataSort[k], 'sort')) :
  3049. _fnGetCellData(oSettings, i, aDataSort[k], 'sort');
  3050. }
  3051. }
  3052. }
  3053. /* Do the sort - here we want multi-column sorting based on a given data source (column)
  3054. * and sorting function (from oSort) in a certain direction. It's reasonably complex to
  3055. * follow on it's own, but this is what we want (example two column sorting):
  3056. * fnLocalSorting = function(a,b){
  3057. * var iTest;
  3058. * iTest = oSort['string-asc']('data11', 'data12');
  3059. * if (iTest !== 0)
  3060. * return iTest;
  3061. * iTest = oSort['numeric-desc']('data21', 'data22');
  3062. * if (iTest !== 0)
  3063. * return iTest;
  3064. * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
  3065. * }
  3066. * Basically we have a test for each sorting column, if the data in that column is equal,
  3067. * test the next column. If all columns match, then we use a numeric sort on the row
  3068. * positions in the original data array to provide a stable sort.
  3069. */
  3070. oSettings.aiDisplayMaster.sort(function (a, b) {
  3071. var k, l, lLen, iTest, aDataSort, sDataType;
  3072. for (k = 0; k < iSortLen; k++) {
  3073. aDataSort = aoColumns[ aaSort[k][0] ].aDataSort;
  3074. for (l = 0, lLen = aDataSort.length; l < lLen; l++) {
  3075. sDataType = aoColumns[ aDataSort[l] ].sType;
  3076. iTest = oSort[ (sDataType ? sDataType : 'string') + "-" + aaSort[k][1] ](
  3077. aoData[a]._aSortData[ aDataSort[l] ],
  3078. aoData[b]._aSortData[ aDataSort[l] ]
  3079. );
  3080. if (iTest !== 0) {
  3081. return iTest;
  3082. }
  3083. }
  3084. }
  3085. return oSort['numeric-asc'](aiOrig[a], aiOrig[b]);
  3086. });
  3087. }
  3088. /* Alter the sorting classes to take account of the changes */
  3089. if ((bApplyClasses === undefined || bApplyClasses) && !oSettings.oFeatures.bDeferRender) {
  3090. _fnSortingClasses(oSettings);
  3091. }
  3092. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  3093. var sTitle = aoColumns[i].sTitle.replace(/<.*?>/g, "");
  3094. nTh = aoColumns[i].nTh;
  3095. nTh.removeAttribute('aria-sort');
  3096. nTh.removeAttribute('aria-label');
  3097. /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
  3098. if (aoColumns[i].bSortable) {
  3099. if (aaSort.length > 0 && aaSort[0][0] == i) {
  3100. nTh.setAttribute('aria-sort', aaSort[0][1] == "asc" ? "ascending" : "descending");
  3101. var nextSort = (aoColumns[i].asSorting[ aaSort[0][2] + 1 ]) ?
  3102. aoColumns[i].asSorting[ aaSort[0][2] + 1 ] : aoColumns[i].asSorting[0];
  3103. nTh.setAttribute('aria-label', sTitle +
  3104. (nextSort == "asc" ? oAria.sSortAscending : oAria.sSortDescending));
  3105. }
  3106. else {
  3107. nTh.setAttribute('aria-label', sTitle +
  3108. (aoColumns[i].asSorting[0] == "asc" ? oAria.sSortAscending : oAria.sSortDescending));
  3109. }
  3110. }
  3111. else {
  3112. nTh.setAttribute('aria-label', sTitle);
  3113. }
  3114. }
  3115. /* Tell the draw function that we have sorted the data */
  3116. oSettings.bSorted = true;
  3117. $(oSettings.oInstance).trigger('sort', oSettings);
  3118. /* Copy the master data into the draw array and re-draw */
  3119. if (oSettings.oFeatures.bFilter) {
  3120. /* _fnFilter() will redraw the table for us */
  3121. _fnFilterComplete(oSettings, oSettings.oPreviousSearch, 1);
  3122. }
  3123. else {
  3124. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  3125. oSettings._iDisplayStart = 0;
  3126. /* reset display back to page 0 */
  3127. _fnCalculateEnd(oSettings);
  3128. _fnDraw(oSettings);
  3129. }
  3130. }
  3131. /**
  3132. * Attach a sort handler (click) to a node
  3133. * @param {object} oSettings dataTables settings object
  3134. * @param {node} nNode node to attach the handler to
  3135. * @param {int} iDataIndex column sorting index
  3136. * @param {function} [fnCallback] callback function
  3137. * @memberof DataTable#oApi
  3138. */
  3139. function _fnSortAttachListener(oSettings, nNode, iDataIndex, fnCallback) {
  3140. _fnBindAction(nNode, {}, function (e) {
  3141. /* If the column is not sortable - don't to anything */
  3142. if (oSettings.aoColumns[iDataIndex].bSortable === false) {
  3143. return;
  3144. }
  3145. /*
  3146. * This is a little bit odd I admit... I declare a temporary function inside the scope of
  3147. * _fnBuildHead and the click handler in order that the code presented here can be used
  3148. * twice - once for when bProcessing is enabled, and another time for when it is
  3149. * disabled, as we need to perform slightly different actions.
  3150. * Basically the issue here is that the Javascript engine in modern browsers don't
  3151. * appear to allow the rendering engine to update the display while it is still executing
  3152. * it's thread (well - it does but only after long intervals). This means that the
  3153. * 'processing' display doesn't appear for a table sort. To break the js thread up a bit
  3154. * I force an execution break by using setTimeout - but this breaks the expected
  3155. * thread continuation for the end-developer's point of view (their code would execute
  3156. * too early), so we only do it when we absolutely have to.
  3157. */
  3158. var fnInnerSorting = function () {
  3159. var iColumn, iNextSort;
  3160. /* If the shift key is pressed then we are multiple column sorting */
  3161. if (e.shiftKey) {
  3162. /* Are we already doing some kind of sort on this column? */
  3163. var bFound = false;
  3164. for (var i = 0; i < oSettings.aaSorting.length; i++) {
  3165. if (oSettings.aaSorting[i][0] == iDataIndex) {
  3166. bFound = true;
  3167. iColumn = oSettings.aaSorting[i][0];
  3168. iNextSort = oSettings.aaSorting[i][2] + 1;
  3169. if (!oSettings.aoColumns[iColumn].asSorting[iNextSort]) {
  3170. /* Reached the end of the sorting options, remove from multi-col sort */
  3171. oSettings.aaSorting.splice(i, 1);
  3172. }
  3173. else {
  3174. /* Move onto next sorting direction */
  3175. oSettings.aaSorting[i][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];
  3176. oSettings.aaSorting[i][2] = iNextSort;
  3177. }
  3178. break;
  3179. }
  3180. }
  3181. /* No sort yet - add it in */
  3182. if (bFound === false) {
  3183. oSettings.aaSorting.push([ iDataIndex,
  3184. oSettings.aoColumns[iDataIndex].asSorting[0], 0 ]);
  3185. }
  3186. }
  3187. else {
  3188. /* If no shift key then single column sort */
  3189. if (oSettings.aaSorting.length == 1 && oSettings.aaSorting[0][0] == iDataIndex) {
  3190. iColumn = oSettings.aaSorting[0][0];
  3191. iNextSort = oSettings.aaSorting[0][2] + 1;
  3192. if (!oSettings.aoColumns[iColumn].asSorting[iNextSort]) {
  3193. iNextSort = 0;
  3194. }
  3195. oSettings.aaSorting[0][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];
  3196. oSettings.aaSorting[0][2] = iNextSort;
  3197. }
  3198. else {
  3199. oSettings.aaSorting.splice(0, oSettings.aaSorting.length);
  3200. oSettings.aaSorting.push([ iDataIndex,
  3201. oSettings.aoColumns[iDataIndex].asSorting[0], 0 ]);
  3202. }
  3203. }
  3204. /* Run the sort */
  3205. _fnSort(oSettings);
  3206. };
  3207. /* /fnInnerSorting */
  3208. if (!oSettings.oFeatures.bProcessing) {
  3209. fnInnerSorting();
  3210. }
  3211. else {
  3212. _fnProcessingDisplay(oSettings, true);
  3213. setTimeout(function () {
  3214. fnInnerSorting();
  3215. if (!oSettings.oFeatures.bServerSide) {
  3216. _fnProcessingDisplay(oSettings, false);
  3217. }
  3218. }, 0);
  3219. }
  3220. /* Call the user specified callback function - used for async user interaction */
  3221. if (typeof fnCallback == 'function') {
  3222. fnCallback(oSettings);
  3223. }
  3224. });
  3225. }
  3226. /**
  3227. * Set the sorting classes on the header, Note: it is safe to call this function
  3228. * when bSort and bSortClasses are false
  3229. * @param {object} oSettings dataTables settings object
  3230. * @memberof DataTable#oApi
  3231. */
  3232. function _fnSortingClasses(oSettings) {
  3233. var i, iLen, j, jLen, iFound;
  3234. var aaSort, sClass;
  3235. var iColumns = oSettings.aoColumns.length;
  3236. var oClasses = oSettings.oClasses;
  3237. for (i = 0; i < iColumns; i++) {
  3238. if (oSettings.aoColumns[i].bSortable) {
  3239. $(oSettings.aoColumns[i].nTh).removeClass(oClasses.sSortAsc + " " + oClasses.sSortDesc +
  3240. " " + oSettings.aoColumns[i].sSortingClass);
  3241. }
  3242. }
  3243. if (oSettings.aaSortingFixed !== null) {
  3244. aaSort = oSettings.aaSortingFixed.concat(oSettings.aaSorting);
  3245. }
  3246. else {
  3247. aaSort = oSettings.aaSorting.slice();
  3248. }
  3249. /* Apply the required classes to the header */
  3250. for (i = 0; i < oSettings.aoColumns.length; i++) {
  3251. if (oSettings.aoColumns[i].bSortable) {
  3252. sClass = oSettings.aoColumns[i].sSortingClass;
  3253. iFound = -1;
  3254. for (j = 0; j < aaSort.length; j++) {
  3255. if (aaSort[j][0] == i) {
  3256. sClass = ( aaSort[j][1] == "asc" ) ?
  3257. oClasses.sSortAsc : oClasses.sSortDesc;
  3258. iFound = j;
  3259. break;
  3260. }
  3261. }
  3262. $(oSettings.aoColumns[i].nTh).addClass(sClass);
  3263. if (oSettings.bJUI) {
  3264. /* jQuery UI uses extra markup */
  3265. var jqSpan = $("span." + oClasses.sSortIcon, oSettings.aoColumns[i].nTh);
  3266. jqSpan.removeClass(oClasses.sSortJUIAsc + " " + oClasses.sSortJUIDesc + " " +
  3267. oClasses.sSortJUI + " " + oClasses.sSortJUIAscAllowed + " " + oClasses.sSortJUIDescAllowed);
  3268. var sSpanClass;
  3269. if (iFound == -1) {
  3270. sSpanClass = oSettings.aoColumns[i].sSortingClassJUI;
  3271. }
  3272. else if (aaSort[iFound][1] == "asc") {
  3273. sSpanClass = oClasses.sSortJUIAsc;
  3274. }
  3275. else {
  3276. sSpanClass = oClasses.sSortJUIDesc;
  3277. }
  3278. jqSpan.addClass(sSpanClass);
  3279. }
  3280. }
  3281. else {
  3282. /* No sorting on this column, so add the base class. This will have been assigned by
  3283. * _fnAddColumn
  3284. */
  3285. $(oSettings.aoColumns[i].nTh).addClass(oSettings.aoColumns[i].sSortingClass);
  3286. }
  3287. }
  3288. /*
  3289. * Apply the required classes to the table body
  3290. * Note that this is given as a feature switch since it can significantly slow down a sort
  3291. * on large data sets (adding and removing of classes is always slow at the best of times..)
  3292. * Further to this, note that this code is admittedly fairly ugly. It could be made a lot
  3293. * simpler using jQuery selectors and add/removeClass, but that is significantly slower
  3294. * (on the order of 5 times slower) - hence the direct DOM manipulation here.
  3295. * Note that for deferred drawing we do use jQuery - the reason being that taking the first
  3296. * row found to see if the whole column needs processed can miss classes since the first
  3297. * column might be new.
  3298. */
  3299. sClass = oClasses.sSortColumn;
  3300. if (oSettings.oFeatures.bSort && oSettings.oFeatures.bSortClasses) {
  3301. var nTds = _fnGetTdNodes(oSettings);
  3302. /* Determine what the sorting class for each column should be */
  3303. var iClass, iTargetCol;
  3304. var asClasses = [];
  3305. for (i = 0; i < iColumns; i++) {
  3306. asClasses.push("");
  3307. }
  3308. for (i = 0, iClass = 1; i < aaSort.length; i++) {
  3309. iTargetCol = parseInt(aaSort[i][0], 10);
  3310. asClasses[iTargetCol] = sClass + iClass;
  3311. if (iClass < 3) {
  3312. iClass++;
  3313. }
  3314. }
  3315. /* Make changes to the classes for each cell as needed */
  3316. var reClass = new RegExp(sClass + "[123]");
  3317. var sTmpClass, sCurrentClass, sNewClass;
  3318. for (i = 0, iLen = nTds.length; i < iLen; i++) {
  3319. /* Determine which column we're looking at */
  3320. iTargetCol = i % iColumns;
  3321. /* What is the full list of classes now */
  3322. sCurrentClass = nTds[i].className;
  3323. /* What sorting class should be applied? */
  3324. sNewClass = asClasses[iTargetCol];
  3325. /* What would the new full list be if we did a replacement? */
  3326. sTmpClass = sCurrentClass.replace(reClass, sNewClass);
  3327. if (sTmpClass != sCurrentClass) {
  3328. /* We changed something */
  3329. nTds[i].className = $.trim(sTmpClass);
  3330. }
  3331. else if (sNewClass.length > 0 && sCurrentClass.indexOf(sNewClass) == -1) {
  3332. /* We need to add a class */
  3333. nTds[i].className = sCurrentClass + " " + sNewClass;
  3334. }
  3335. }
  3336. }
  3337. }
  3338. /**
  3339. * Save the state of a table in a cookie such that the page can be reloaded
  3340. * @param {object} oSettings dataTables settings object
  3341. * @memberof DataTable#oApi
  3342. */
  3343. function _fnSaveState(oSettings) {
  3344. if (!oSettings.oFeatures.bStateSave || oSettings.bDestroying) {
  3345. return;
  3346. }
  3347. /* Store the interesting variables */
  3348. var i, iLen, bInfinite = oSettings.oScroll.bInfinite;
  3349. var oState = {
  3350. "iCreate":new Date().getTime(),
  3351. "iStart":(bInfinite ? 0 : oSettings._iDisplayStart),
  3352. "iEnd":(bInfinite ? oSettings._iDisplayLength : oSettings._iDisplayEnd),
  3353. "iLength":oSettings._iDisplayLength,
  3354. "aaSorting":$.extend(true, [], oSettings.aaSorting),
  3355. "oSearch":$.extend(true, {}, oSettings.oPreviousSearch),
  3356. "aoSearchCols":$.extend(true, [], oSettings.aoPreSearchCols),
  3357. "abVisCols":[]
  3358. };
  3359. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  3360. oState.abVisCols.push(oSettings.aoColumns[i].bVisible);
  3361. }
  3362. _fnCallbackFire(oSettings, "aoStateSaveParams", 'stateSaveParams', [oSettings, oState]);
  3363. oSettings.fnStateSave.call(oSettings.oInstance, oSettings, oState);
  3364. }
  3365. /**
  3366. * Attempt to load a saved table state from a cookie
  3367. * @param {object} oSettings dataTables settings object
  3368. * @param {object} oInit DataTables init object so we can override settings
  3369. * @memberof DataTable#oApi
  3370. */
  3371. function _fnLoadState(oSettings, oInit) {
  3372. if (!oSettings.oFeatures.bStateSave) {
  3373. return;
  3374. }
  3375. var oData = oSettings.fnStateLoad.call(oSettings.oInstance, oSettings);
  3376. if (!oData) {
  3377. return;
  3378. }
  3379. /* Allow custom and plug-in manipulation functions to alter the saved data set and
  3380. * cancelling of loading by returning false
  3381. */
  3382. var abStateLoad = _fnCallbackFire(oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData]);
  3383. if ($.inArray(false, abStateLoad) !== -1) {
  3384. return;
  3385. }
  3386. /* Store the saved state so it might be accessed at any time */
  3387. oSettings.oLoadedState = $.extend(true, {}, oData);
  3388. /* Restore key features */
  3389. oSettings._iDisplayStart = oData.iStart;
  3390. oSettings.iInitDisplayStart = oData.iStart;
  3391. oSettings._iDisplayEnd = oData.iEnd;
  3392. oSettings._iDisplayLength = oData.iLength;
  3393. oSettings.aaSorting = oData.aaSorting.slice();
  3394. oSettings.saved_aaSorting = oData.aaSorting.slice();
  3395. /* Search filtering */
  3396. $.extend(oSettings.oPreviousSearch, oData.oSearch);
  3397. $.extend(true, oSettings.aoPreSearchCols, oData.aoSearchCols);
  3398. /* Column visibility state
  3399. * Pass back visibility settings to the init handler, but to do not here override
  3400. * the init object that the user might have passed in
  3401. */
  3402. oInit.saved_aoColumns = [];
  3403. for (var i = 0; i < oData.abVisCols.length; i++) {
  3404. oInit.saved_aoColumns[i] = {};
  3405. oInit.saved_aoColumns[i].bVisible = oData.abVisCols[i];
  3406. }
  3407. _fnCallbackFire(oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData]);
  3408. }
  3409. /**
  3410. * Create a new cookie with a value to store the state of a table
  3411. * @param {string} sName name of the cookie to create
  3412. * @param {string} sValue the value the cookie should take
  3413. * @param {int} iSecs duration of the cookie
  3414. * @param {string} sBaseName sName is made up of the base + file name - this is the base
  3415. * @param {function} fnCallback User definable function to modify the cookie
  3416. * @memberof DataTable#oApi
  3417. */
  3418. function _fnCreateCookie(sName, sValue, iSecs, sBaseName, fnCallback) {
  3419. var date = new Date();
  3420. date.setTime(date.getTime() + (iSecs * 1000));
  3421. /*
  3422. * Shocking but true - it would appear IE has major issues with having the path not having
  3423. * a trailing slash on it. We need the cookie to be available based on the path, so we
  3424. * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the
  3425. * patch to use at least some of the path
  3426. */
  3427. var aParts = window.location.pathname.split('/');
  3428. var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g, "").toLowerCase();
  3429. var sFullCookie, oData;
  3430. if (fnCallback !== null) {
  3431. oData = (typeof $.parseJSON === 'function') ?
  3432. $.parseJSON(sValue) : eval('(' + sValue + ')');
  3433. sFullCookie = fnCallback(sNameFile, oData, date.toGMTString(),
  3434. aParts.join('/') + "/");
  3435. }
  3436. else {
  3437. sFullCookie = sNameFile + "=" + encodeURIComponent(sValue) +
  3438. "; expires=" + date.toGMTString() + "; path=" + aParts.join('/') + "/";
  3439. }
  3440. /* Are we going to go over the cookie limit of 4KiB? If so, try to delete a cookies
  3441. * belonging to DataTables.
  3442. */
  3443. var
  3444. aCookies = document.cookie.split(';'),
  3445. iNewCookieLen = sFullCookie.split(';')[0].length,
  3446. aOldCookies = [];
  3447. if (iNewCookieLen + document.cookie.length + 10 > 4096) /* Magic 10 for padding */
  3448. {
  3449. for (var i = 0, iLen = aCookies.length; i < iLen; i++) {
  3450. if (aCookies[i].indexOf(sBaseName) != -1) {
  3451. /* It's a DataTables cookie, so eval it and check the time stamp */
  3452. var aSplitCookie = aCookies[i].split('=');
  3453. try {
  3454. oData = eval('(' + decodeURIComponent(aSplitCookie[1]) + ')');
  3455. if (oData && oData.iCreate) {
  3456. aOldCookies.push({
  3457. "name":aSplitCookie[0],
  3458. "time":oData.iCreate
  3459. });
  3460. }
  3461. }
  3462. catch (e) {
  3463. }
  3464. }
  3465. }
  3466. // Make sure we delete the oldest ones first
  3467. aOldCookies.sort(function (a, b) {
  3468. return b.time - a.time;
  3469. });
  3470. // Eliminate as many old DataTables cookies as we need to
  3471. while (iNewCookieLen + document.cookie.length + 10 > 4096) {
  3472. if (aOldCookies.length === 0) {
  3473. // Deleted all DT cookies and still not enough space. Can't state save
  3474. return;
  3475. }
  3476. var old = aOldCookies.pop();
  3477. document.cookie = old.name + "=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=" +
  3478. aParts.join('/') + "/";
  3479. }
  3480. }
  3481. document.cookie = sFullCookie;
  3482. }
  3483. /**
  3484. * Read an old cookie to get a cookie with an old table state
  3485. * @param {string} sName name of the cookie to read
  3486. * @returns {string} contents of the cookie - or null if no cookie with that name found
  3487. * @memberof DataTable#oApi
  3488. */
  3489. function _fnReadCookie(sName) {
  3490. var
  3491. aParts = window.location.pathname.split('/'),
  3492. sNameEQ = sName + '_' + aParts[aParts.length - 1].replace(/[\/:]/g, "").toLowerCase() + '=',
  3493. sCookieContents = document.cookie.split(';');
  3494. for (var i = 0; i < sCookieContents.length; i++) {
  3495. var c = sCookieContents[i];
  3496. while (c.charAt(0) == ' ') {
  3497. c = c.substring(1, c.length);
  3498. }
  3499. if (c.indexOf(sNameEQ) === 0) {
  3500. return decodeURIComponent(c.substring(sNameEQ.length, c.length));
  3501. }
  3502. }
  3503. return null;
  3504. }
  3505. /**
  3506. * Return the settings object for a particular table
  3507. * @param {node} nTable table we are using as a dataTable
  3508. * @returns {object} Settings object - or null if not found
  3509. * @memberof DataTable#oApi
  3510. */
  3511. function _fnSettingsFromNode(nTable) {
  3512. for (var i = 0; i < DataTable.settings.length; i++) {
  3513. if (DataTable.settings[i].nTable === nTable) {
  3514. return DataTable.settings[i];
  3515. }
  3516. }
  3517. return null;
  3518. }
  3519. /**
  3520. * Return an array with the TR nodes for the table
  3521. * @param {object} oSettings dataTables settings object
  3522. * @returns {array} TR array
  3523. * @memberof DataTable#oApi
  3524. */
  3525. function _fnGetTrNodes(oSettings) {
  3526. var aNodes = [];
  3527. var aoData = oSettings.aoData;
  3528. for (var i = 0, iLen = aoData.length; i < iLen; i++) {
  3529. if (aoData[i].nTr !== null) {
  3530. aNodes.push(aoData[i].nTr);
  3531. }
  3532. }
  3533. return aNodes;
  3534. }
  3535. /**
  3536. * Return an flat array with all TD nodes for the table, or row
  3537. * @param {object} oSettings dataTables settings object
  3538. * @param {int} [iIndividualRow] aoData index to get the nodes for - optional
  3539. * if not given then the return array will contain all nodes for the table
  3540. * @returns {array} TD array
  3541. * @memberof DataTable#oApi
  3542. */
  3543. function _fnGetTdNodes(oSettings, iIndividualRow) {
  3544. var anReturn = [];
  3545. var iCorrector;
  3546. var anTds, nTd;
  3547. var iRow, iRows = oSettings.aoData.length,
  3548. iColumn, iColumns, oData, sNodeName, iStart = 0, iEnd = iRows;
  3549. /* Allow the collection to be limited to just one row */
  3550. if (iIndividualRow !== undefined) {
  3551. iStart = iIndividualRow;
  3552. iEnd = iIndividualRow + 1;
  3553. }
  3554. for (iRow = iStart; iRow < iEnd; iRow++) {
  3555. oData = oSettings.aoData[iRow];
  3556. if (oData.nTr !== null) {
  3557. /* get the TD child nodes - taking into account text etc nodes */
  3558. anTds = [];
  3559. nTd = oData.nTr.firstChild;
  3560. while (nTd) {
  3561. sNodeName = nTd.nodeName.toLowerCase();
  3562. if (sNodeName == 'td' || sNodeName == 'th') {
  3563. anTds.push(nTd);
  3564. }
  3565. nTd = nTd.nextSibling;
  3566. }
  3567. iCorrector = 0;
  3568. for (iColumn = 0, iColumns = oSettings.aoColumns.length; iColumn < iColumns; iColumn++) {
  3569. if (oSettings.aoColumns[iColumn].bVisible) {
  3570. anReturn.push(anTds[iColumn - iCorrector]);
  3571. }
  3572. else {
  3573. anReturn.push(oData._anHidden[iColumn]);
  3574. iCorrector++;
  3575. }
  3576. }
  3577. }
  3578. }
  3579. return anReturn;
  3580. }
  3581. /**
  3582. * Log an error message
  3583. * @param {object} oSettings dataTables settings object
  3584. * @param {int} iLevel log error messages, or display them to the user
  3585. * @param {string} sMesg error message
  3586. * @memberof DataTable#oApi
  3587. */
  3588. function _fnLog(oSettings, iLevel, sMesg) {
  3589. var sAlert = (oSettings === null) ?
  3590. "DataTables warning: " + sMesg :
  3591. "DataTables warning (table id = '" + oSettings.sTableId + "'): " + sMesg;
  3592. if (iLevel === 0) {
  3593. if (DataTable.ext.sErrMode == 'alert') {
  3594. alert(sAlert);
  3595. }
  3596. else {
  3597. throw new Error(sAlert);
  3598. }
  3599. return;
  3600. }
  3601. else if (window.console && console.log) {
  3602. console.log(sAlert);
  3603. }
  3604. }
  3605. /**
  3606. * See if a property is defined on one object, if so assign it to the other object
  3607. * @param {object} oRet target object
  3608. * @param {object} oSrc source object
  3609. * @param {string} sName property
  3610. * @param {string} [sMappedName] name to map too - optional, sName used if not given
  3611. * @memberof DataTable#oApi
  3612. */
  3613. function _fnMap(oRet, oSrc, sName, sMappedName) {
  3614. if (sMappedName === undefined) {
  3615. sMappedName = sName;
  3616. }
  3617. if (oSrc[sName] !== undefined) {
  3618. oRet[sMappedName] = oSrc[sName];
  3619. }
  3620. }
  3621. /**
  3622. * Extend objects - very similar to jQuery.extend, but deep copy objects, and shallow
  3623. * copy arrays. The reason we need to do this, is that we don't want to deep copy array
  3624. * init values (such as aaSorting) since the dev wouldn't be able to override them, but
  3625. * we do want to deep copy arrays.
  3626. * @param {object} oOut Object to extend
  3627. * @param {object} oExtender Object from which the properties will be applied to oOut
  3628. * @returns {object} oOut Reference, just for convenience - oOut === the return.
  3629. * @memberof DataTable#oApi
  3630. * @todo This doesn't take account of arrays inside the deep copied objects.
  3631. */
  3632. function _fnExtend(oOut, oExtender) {
  3633. var val;
  3634. for (var prop in oExtender) {
  3635. if (oExtender.hasOwnProperty(prop)) {
  3636. val = oExtender[prop];
  3637. if (typeof oInit[prop] === 'object' && val !== null && $.isArray(val) === false) {
  3638. $.extend(true, oOut[prop], val);
  3639. }
  3640. else {
  3641. oOut[prop] = val;
  3642. }
  3643. }
  3644. }
  3645. return oOut;
  3646. }
  3647. /**
  3648. * Bind an event handers to allow a click or return key to activate the callback.
  3649. * This is good for accessibility since a return on the keyboard will have the
  3650. * same effect as a click, if the element has focus.
  3651. * @param {element} n Element to bind the action to
  3652. * @param {object} oData Data object to pass to the triggered function
  3653. * @param {function} fn Callback function for when the event is triggered
  3654. * @memberof DataTable#oApi
  3655. */
  3656. function _fnBindAction(n, oData, fn) {
  3657. $(n)
  3658. .bind('click.DT', oData, function (e) {
  3659. n.blur(); // Remove focus outline for mouse users
  3660. fn(e);
  3661. })
  3662. .bind('keypress.DT', oData, function (e) {
  3663. if (e.which === 13) {
  3664. fn(e);
  3665. }
  3666. })
  3667. .bind('selectstart.DT', function () {
  3668. /* Take the brutal approach to cancelling text selection */
  3669. return false;
  3670. });
  3671. }
  3672. /**
  3673. * Register a callback function. Easily allows a callback function to be added to
  3674. * an array store of callback functions that can then all be called together.
  3675. * @param {object} oSettings dataTables settings object
  3676. * @param {string} sStore Name of the array storage for the callbacks in oSettings
  3677. * @param {function} fn Function to be called back
  3678. * @param {string} sName Identifying name for the callback (i.e. a label)
  3679. * @memberof DataTable#oApi
  3680. */
  3681. function _fnCallbackReg(oSettings, sStore, fn, sName) {
  3682. if (fn) {
  3683. oSettings[sStore].push({
  3684. "fn":fn,
  3685. "sName":sName
  3686. });
  3687. }
  3688. }
  3689. /**
  3690. * Fire callback functions and trigger events. Note that the loop over the callback
  3691. * array store is done backwards! Further note that you do not want to fire off triggers
  3692. * in time sensitive applications (for example cell creation) as its slow.
  3693. * @param {object} oSettings dataTables settings object
  3694. * @param {string} sStore Name of the array storage for the callbacks in oSettings
  3695. * @param {string} sTrigger Name of the jQuery custom event to trigger. If null no trigger
  3696. * is fired
  3697. * @param {array} aArgs Array of arguments to pass to the callback function / trigger
  3698. * @memberof DataTable#oApi
  3699. */
  3700. function _fnCallbackFire(oSettings, sStore, sTrigger, aArgs) {
  3701. var aoStore = oSettings[sStore];
  3702. var aRet = [];
  3703. for (var i = aoStore.length - 1; i >= 0; i--) {
  3704. aRet.push(aoStore[i].fn.apply(oSettings.oInstance, aArgs));
  3705. }
  3706. if (sTrigger !== null) {
  3707. $(oSettings.oInstance).trigger(sTrigger, aArgs);
  3708. }
  3709. return aRet;
  3710. }
  3711. /**
  3712. * JSON stringify. If JSON.stringify it provided by the browser, json2.js or any other
  3713. * library, then we use that as it is fast, safe and accurate. If the function isn't
  3714. * available then we need to built it ourselves - the inspiration for this function comes
  3715. * from Craig Buckler ( http://www.sitepoint.com/javascript-json-serialization/ ). It is
  3716. * not perfect and absolutely should not be used as a replacement to json2.js - but it does
  3717. * do what we need, without requiring a dependency for DataTables.
  3718. * @param {object} o JSON object to be converted
  3719. * @returns {string} JSON string
  3720. * @memberof DataTable#oApi
  3721. */
  3722. var _fnJsonString = (window.JSON) ? JSON.stringify : function (o) {
  3723. /* Not an object or array */
  3724. var sType = typeof o;
  3725. if (sType !== "object" || o === null) {
  3726. // simple data type
  3727. if (sType === "string") {
  3728. o = '"' + o + '"';
  3729. }
  3730. return o + "";
  3731. }
  3732. /* If object or array, need to recurse over it */
  3733. var
  3734. sProp, mValue,
  3735. json = [],
  3736. bArr = $.isArray(o);
  3737. for (sProp in o) {
  3738. mValue = o[sProp];
  3739. sType = typeof mValue;
  3740. if (sType === "string") {
  3741. mValue = '"' + mValue + '"';
  3742. }
  3743. else if (sType === "object" && mValue !== null) {
  3744. mValue = _fnJsonString(mValue);
  3745. }
  3746. json.push((bArr ? "" : '"' + sProp + '":') + mValue);
  3747. }
  3748. return (bArr ? "[" : "{") + json + (bArr ? "]" : "}");
  3749. };
  3750. /**
  3751. * From some browsers (specifically IE6/7) we need special handling to work around browser
  3752. * bugs - this function is used to detect when these workarounds are needed.
  3753. * @param {object} oSettings dataTables settings object
  3754. * @memberof DataTable#oApi
  3755. */
  3756. function _fnBrowserDetect(oSettings) {
  3757. /* IE6/7 will oversize a width 100% element inside a scrolling element, to include the
  3758. * width of the scrollbar, while other browsers ensure the inner element is contained
  3759. * without forcing scrolling
  3760. */
  3761. var n = $(
  3762. '<div style="position:absolute; top:0; left:0; height:1px; width:1px; overflow:hidden">' +
  3763. '<div style="position:absolute; top:1px; left:1px; width:100px; overflow:scroll;">' +
  3764. '<div id="DT_BrowserTest" style="width:100%; height:10px;"></div>' +
  3765. '</div>' +
  3766. '</div>')[0];
  3767. document.body.appendChild(n);
  3768. oSettings.oBrowser.bScrollOversize = $('#DT_BrowserTest', n)[0].offsetWidth === 100 ? true : false;
  3769. document.body.removeChild(n);
  3770. }
  3771. /**
  3772. * Perform a jQuery selector action on the table's TR elements (from the tbody) and
  3773. * return the resulting jQuery object.
  3774. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  3775. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  3776. * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
  3777. * criterion ("applied") or all TR elements (i.e. no filter).
  3778. * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
  3779. * Can be either 'current', whereby the current sorting of the table is used, or
  3780. * 'original' whereby the original order the data was read into the table is used.
  3781. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  3782. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  3783. * 'current' and filter is 'applied', regardless of what they might be given as.
  3784. * @returns {object} jQuery object, filtered by the given selector.
  3785. * @dtopt API
  3786. *
  3787. * @example
  3788. * $(document).ready(function() {
  3789. * var oTable = $('#example').dataTable();
  3790. *
  3791. * // Highlight every second row
  3792. * oTable.$('tr:odd').css('backgroundColor', 'blue');
  3793. * } );
  3794. *
  3795. * @example
  3796. * $(document).ready(function() {
  3797. * var oTable = $('#example').dataTable();
  3798. *
  3799. * // Filter to rows with 'Webkit' in them, add a background colour and then
  3800. * // remove the filter, thus highlighting the 'Webkit' rows only.
  3801. * oTable.fnFilter('Webkit');
  3802. * oTable.$('tr', {"filter": "applied"}).css('backgroundColor', 'blue');
  3803. * oTable.fnFilter('');
  3804. * } );
  3805. */
  3806. this.$ = function (sSelector, oOpts) {
  3807. var i, iLen, a = [], tr;
  3808. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  3809. var aoData = oSettings.aoData;
  3810. var aiDisplay = oSettings.aiDisplay;
  3811. var aiDisplayMaster = oSettings.aiDisplayMaster;
  3812. if (!oOpts) {
  3813. oOpts = {};
  3814. }
  3815. oOpts = $.extend({}, {
  3816. "filter":"none", // applied
  3817. "order":"current", // "original"
  3818. "page":"all" // current
  3819. }, oOpts);
  3820. // Current page implies that order=current and fitler=applied, since it is fairly
  3821. // senseless otherwise
  3822. if (oOpts.page == 'current') {
  3823. for (i = oSettings._iDisplayStart, iLen = oSettings.fnDisplayEnd(); i < iLen; i++) {
  3824. tr = aoData[ aiDisplay[i] ].nTr;
  3825. if (tr) {
  3826. a.push(tr);
  3827. }
  3828. }
  3829. }
  3830. else if (oOpts.order == "current" && oOpts.filter == "none") {
  3831. for (i = 0, iLen = aiDisplayMaster.length; i < iLen; i++) {
  3832. tr = aoData[ aiDisplayMaster[i] ].nTr;
  3833. if (tr) {
  3834. a.push(tr);
  3835. }
  3836. }
  3837. }
  3838. else if (oOpts.order == "current" && oOpts.filter == "applied") {
  3839. for (i = 0, iLen = aiDisplay.length; i < iLen; i++) {
  3840. tr = aoData[ aiDisplay[i] ].nTr;
  3841. if (tr) {
  3842. a.push(tr);
  3843. }
  3844. }
  3845. }
  3846. else if (oOpts.order == "original" && oOpts.filter == "none") {
  3847. for (i = 0, iLen = aoData.length; i < iLen; i++) {
  3848. tr = aoData[ i ].nTr;
  3849. if (tr) {
  3850. a.push(tr);
  3851. }
  3852. }
  3853. }
  3854. else if (oOpts.order == "original" && oOpts.filter == "applied") {
  3855. for (i = 0, iLen = aoData.length; i < iLen; i++) {
  3856. tr = aoData[ i ].nTr;
  3857. if ($.inArray(i, aiDisplay) !== -1 && tr) {
  3858. a.push(tr);
  3859. }
  3860. }
  3861. }
  3862. else {
  3863. _fnLog(oSettings, 1, "Unknown selection options");
  3864. }
  3865. /* We need to filter on the TR elements and also 'find' in their descendants
  3866. * to make the selector act like it would in a full table - so we need
  3867. * to build both results and then combine them together
  3868. */
  3869. var jqA = $(a);
  3870. var jqTRs = jqA.filter(sSelector);
  3871. var jqDescendants = jqA.find(sSelector);
  3872. return $([].concat($.makeArray(jqTRs), $.makeArray(jqDescendants)));
  3873. };
  3874. /**
  3875. * Almost identical to $ in operation, but in this case returns the data for the matched
  3876. * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
  3877. * rather than any descendants, so the data can be obtained for the row/cell. If matching
  3878. * rows are found, the data returned is the original data array/object that was used to
  3879. * create the row (or a generated array if from a DOM source).
  3880. *
  3881. * This method is often useful in-combination with $ where both functions are given the
  3882. * same parameters and the array indexes will match identically.
  3883. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  3884. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  3885. * @param {string} [oOpts.filter=none] Select elements that meet the current filter
  3886. * criterion ("applied") or all elements (i.e. no filter).
  3887. * @param {string} [oOpts.order=current] Order of the data in the processed array.
  3888. * Can be either 'current', whereby the current sorting of the table is used, or
  3889. * 'original' whereby the original order the data was read into the table is used.
  3890. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  3891. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  3892. * 'current' and filter is 'applied', regardless of what they might be given as.
  3893. * @returns {array} Data for the matched elements. If any elements, as a result of the
  3894. * selector, were not TR, TD or TH elements in the DataTable, they will have a null
  3895. * entry in the array.
  3896. * @dtopt API
  3897. *
  3898. * @example
  3899. * $(document).ready(function() {
  3900. * var oTable = $('#example').dataTable();
  3901. *
  3902. * // Get the data from the first row in the table
  3903. * var data = oTable._('tr:first');
  3904. *
  3905. * // Do something useful with the data
  3906. * alert( "First cell is: "+data[0] );
  3907. * } );
  3908. *
  3909. * @example
  3910. * $(document).ready(function() {
  3911. * var oTable = $('#example').dataTable();
  3912. *
  3913. * // Filter to 'Webkit' and get all data for
  3914. * oTable.fnFilter('Webkit');
  3915. * var data = oTable._('tr', {"filter": "applied"});
  3916. *
  3917. * // Do something with the data
  3918. * alert( data.length+" rows matched the filter" );
  3919. * } );
  3920. */
  3921. this._ = function (sSelector, oOpts) {
  3922. var aOut = [];
  3923. var i, iLen, iIndex;
  3924. var aTrs = this.$(sSelector, oOpts);
  3925. for (i = 0, iLen = aTrs.length; i < iLen; i++) {
  3926. aOut.push(this.fnGetData(aTrs[i]));
  3927. }
  3928. return aOut;
  3929. };
  3930. /**
  3931. * Add a single new row or multiple rows of data to the table. Please note
  3932. * that this is suitable for client-side processing only - if you are using
  3933. * server-side processing (i.e. "bServerSide": true), then to add data, you
  3934. * must add it to the data source, i.e. the server-side, through an Ajax call.
  3935. * @param {array|object} mData The data to be added to the table. This can be:
  3936. * <ul>
  3937. * <li>1D array of data - add a single row with the data provided</li>
  3938. * <li>2D array of arrays - add multiple rows in a single call</li>
  3939. * <li>object - data object when using <i>mData</i></li>
  3940. * <li>array of objects - multiple data objects when using <i>mData</i></li>
  3941. * </ul>
  3942. * @param {bool} [bRedraw=true] redraw the table or not
  3943. * @returns {array} An array of integers, representing the list of indexes in
  3944. * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
  3945. * the table.
  3946. * @dtopt API
  3947. *
  3948. * @example
  3949. * // Global var for counter
  3950. * var giCount = 2;
  3951. *
  3952. * $(document).ready(function() {
  3953. * $('#example').dataTable();
  3954. * } );
  3955. *
  3956. * function fnClickAddRow() {
  3957. * $('#example').dataTable().fnAddData( [
  3958. * giCount+".1",
  3959. * giCount+".2",
  3960. * giCount+".3",
  3961. * giCount+".4" ]
  3962. * );
  3963. *
  3964. * giCount++;
  3965. * }
  3966. */
  3967. this.fnAddData = function (mData, bRedraw) {
  3968. if (mData.length === 0) {
  3969. return [];
  3970. }
  3971. var aiReturn = [];
  3972. var iTest;
  3973. /* Find settings from table node */
  3974. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  3975. /* Check if we want to add multiple rows or not */
  3976. if (typeof mData[0] === "object" && mData[0] !== null) {
  3977. for (var i = 0; i < mData.length; i++) {
  3978. iTest = _fnAddData(oSettings, mData[i]);
  3979. if (iTest == -1) {
  3980. return aiReturn;
  3981. }
  3982. aiReturn.push(iTest);
  3983. }
  3984. }
  3985. else {
  3986. iTest = _fnAddData(oSettings, mData);
  3987. if (iTest == -1) {
  3988. return aiReturn;
  3989. }
  3990. aiReturn.push(iTest);
  3991. }
  3992. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  3993. if (bRedraw === undefined || bRedraw) {
  3994. _fnReDraw(oSettings);
  3995. }
  3996. return aiReturn;
  3997. };
  3998. /**
  3999. * This function will make DataTables recalculate the column sizes, based on the data
  4000. * contained in the table and the sizes applied to the columns (in the DOM, CSS or
  4001. * through the sWidth parameter). This can be useful when the width of the table's
  4002. * parent element changes (for example a window resize).
  4003. * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
  4004. * @dtopt API
  4005. *
  4006. * @example
  4007. * $(document).ready(function() {
  4008. * var oTable = $('#example').dataTable( {
  4009. * "sScrollY": "200px",
  4010. * "bPaginate": false
  4011. * } );
  4012. *
  4013. * $(window).bind('resize', function () {
  4014. * oTable.fnAdjustColumnSizing();
  4015. * } );
  4016. * } );
  4017. */
  4018. this.fnAdjustColumnSizing = function (bRedraw) {
  4019. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4020. _fnAdjustColumnSizing(oSettings);
  4021. if (bRedraw === undefined || bRedraw) {
  4022. this.fnDraw(false);
  4023. }
  4024. else if (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") {
  4025. /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
  4026. this.oApi._fnScrollDraw(oSettings);
  4027. }
  4028. };
  4029. /**
  4030. * Quickly and simply clear a table
  4031. * @param {bool} [bRedraw=true] redraw the table or not
  4032. * @dtopt API
  4033. *
  4034. * @example
  4035. * $(document).ready(function() {
  4036. * var oTable = $('#example').dataTable();
  4037. *
  4038. * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
  4039. * oTable.fnClearTable();
  4040. * } );
  4041. */
  4042. this.fnClearTable = function (bRedraw) {
  4043. /* Find settings from table node */
  4044. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4045. _fnClearTable(oSettings);
  4046. if (bRedraw === undefined || bRedraw) {
  4047. _fnDraw(oSettings);
  4048. }
  4049. };
  4050. /**
  4051. * The exact opposite of 'opening' a row, this function will close any rows which
  4052. * are currently 'open'.
  4053. * @param {node} nTr the table row to 'close'
  4054. * @returns {int} 0 on success, or 1 if failed (can't find the row)
  4055. * @dtopt API
  4056. *
  4057. * @example
  4058. * $(document).ready(function() {
  4059. * var oTable;
  4060. *
  4061. * // 'open' an information row when a row is clicked on
  4062. * $('#example tbody tr').click( function () {
  4063. * if ( oTable.fnIsOpen(this) ) {
  4064. * oTable.fnClose( this );
  4065. * } else {
  4066. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  4067. * }
  4068. * } );
  4069. *
  4070. * oTable = $('#example').dataTable();
  4071. * } );
  4072. */
  4073. this.fnClose = function (nTr) {
  4074. /* Find settings from table node */
  4075. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4076. for (var i = 0; i < oSettings.aoOpenRows.length; i++) {
  4077. if (oSettings.aoOpenRows[i].nParent == nTr) {
  4078. var nTrParent = oSettings.aoOpenRows[i].nTr.parentNode;
  4079. if (nTrParent) {
  4080. /* Remove it if it is currently on display */
  4081. nTrParent.removeChild(oSettings.aoOpenRows[i].nTr);
  4082. }
  4083. oSettings.aoOpenRows.splice(i, 1);
  4084. return 0;
  4085. }
  4086. }
  4087. return 1;
  4088. };
  4089. /**
  4090. * Remove a row for the table
  4091. * @param {mixed} mTarget The index of the row from aoData to be deleted, or
  4092. * the TR element you want to delete
  4093. * @param {function|null} [fnCallBack] Callback function
  4094. * @param {bool} [bRedraw=true] Redraw the table or not
  4095. * @returns {array} The row that was deleted
  4096. * @dtopt API
  4097. *
  4098. * @example
  4099. * $(document).ready(function() {
  4100. * var oTable = $('#example').dataTable();
  4101. *
  4102. * // Immediately remove the first row
  4103. * oTable.fnDeleteRow( 0 );
  4104. * } );
  4105. */
  4106. this.fnDeleteRow = function (mTarget, fnCallBack, bRedraw) {
  4107. /* Find settings from table node */
  4108. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4109. var i, iLen, iAODataIndex;
  4110. iAODataIndex = (typeof mTarget === 'object') ?
  4111. _fnNodeToDataIndex(oSettings, mTarget) : mTarget;
  4112. /* Return the data array from this row */
  4113. var oData = oSettings.aoData.splice(iAODataIndex, 1);
  4114. /* Update the _DT_RowIndex parameter */
  4115. for (i = 0, iLen = oSettings.aoData.length; i < iLen; i++) {
  4116. if (oSettings.aoData[i].nTr !== null) {
  4117. oSettings.aoData[i].nTr._DT_RowIndex = i;
  4118. }
  4119. }
  4120. /* Remove the target row from the search array */
  4121. var iDisplayIndex = $.inArray(iAODataIndex, oSettings.aiDisplay);
  4122. oSettings.asDataSearch.splice(iDisplayIndex, 1);
  4123. /* Delete from the display arrays */
  4124. _fnDeleteIndex(oSettings.aiDisplayMaster, iAODataIndex);
  4125. _fnDeleteIndex(oSettings.aiDisplay, iAODataIndex);
  4126. /* If there is a user callback function - call it */
  4127. if (typeof fnCallBack === "function") {
  4128. fnCallBack.call(this, oSettings, oData);
  4129. }
  4130. /* Check for an 'overflow' they case for displaying the table */
  4131. if (oSettings._iDisplayStart >= oSettings.fnRecordsDisplay()) {
  4132. oSettings._iDisplayStart -= oSettings._iDisplayLength;
  4133. if (oSettings._iDisplayStart < 0) {
  4134. oSettings._iDisplayStart = 0;
  4135. }
  4136. }
  4137. if (bRedraw === undefined || bRedraw) {
  4138. _fnCalculateEnd(oSettings);
  4139. _fnDraw(oSettings);
  4140. }
  4141. return oData;
  4142. };
  4143. /**
  4144. * Restore the table to it's original state in the DOM by removing all of DataTables
  4145. * enhancements, alterations to the DOM structure of the table and event listeners.
  4146. * @param {boolean} [bRemove=false] Completely remove the table from the DOM
  4147. * @dtopt API
  4148. *
  4149. * @example
  4150. * $(document).ready(function() {
  4151. * // This example is fairly pointless in reality, but shows how fnDestroy can be used
  4152. * var oTable = $('#example').dataTable();
  4153. * oTable.fnDestroy();
  4154. * } );
  4155. */
  4156. this.fnDestroy = function (bRemove) {
  4157. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4158. var nOrig = oSettings.nTableWrapper.parentNode;
  4159. var nBody = oSettings.nTBody;
  4160. var i, iLen;
  4161. bRemove = (bRemove === undefined) ? false : bRemove;
  4162. /* Flag to note that the table is currently being destroyed - no action should be taken */
  4163. oSettings.bDestroying = true;
  4164. /* Fire off the destroy callbacks for plug-ins etc */
  4165. _fnCallbackFire(oSettings, "aoDestroyCallback", "destroy", [oSettings]);
  4166. /* If the table is not being removed, restore the hidden columns */
  4167. if (!bRemove) {
  4168. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  4169. if (oSettings.aoColumns[i].bVisible === false) {
  4170. this.fnSetColumnVis(i, true);
  4171. }
  4172. }
  4173. }
  4174. /* Blitz all DT events */
  4175. $(oSettings.nTableWrapper).find('*').andSelf().unbind('.DT');
  4176. /* If there is an 'empty' indicator row, remove it */
  4177. $('tbody>tr>td.' + oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove();
  4178. /* When scrolling we had to break the table up - restore it */
  4179. if (oSettings.nTable != oSettings.nTHead.parentNode) {
  4180. $(oSettings.nTable).children('thead').remove();
  4181. oSettings.nTable.appendChild(oSettings.nTHead);
  4182. }
  4183. if (oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode) {
  4184. $(oSettings.nTable).children('tfoot').remove();
  4185. oSettings.nTable.appendChild(oSettings.nTFoot);
  4186. }
  4187. /* Remove the DataTables generated nodes, events and classes */
  4188. oSettings.nTable.parentNode.removeChild(oSettings.nTable);
  4189. $(oSettings.nTableWrapper).remove();
  4190. oSettings.aaSorting = [];
  4191. oSettings.aaSortingFixed = [];
  4192. _fnSortingClasses(oSettings);
  4193. $(_fnGetTrNodes(oSettings)).removeClass(oSettings.asStripeClasses.join(' '));
  4194. $('th, td', oSettings.nTHead).removeClass([
  4195. oSettings.oClasses.sSortable,
  4196. oSettings.oClasses.sSortableAsc,
  4197. oSettings.oClasses.sSortableDesc,
  4198. oSettings.oClasses.sSortableNone ].join(' ')
  4199. );
  4200. if (oSettings.bJUI) {
  4201. $('th span.' + oSettings.oClasses.sSortIcon
  4202. + ', td span.' + oSettings.oClasses.sSortIcon, oSettings.nTHead).remove();
  4203. $('th, td', oSettings.nTHead).each(function () {
  4204. var jqWrapper = $('div.' + oSettings.oClasses.sSortJUIWrapper, this);
  4205. var kids = jqWrapper.contents();
  4206. $(this).append(kids);
  4207. jqWrapper.remove();
  4208. });
  4209. }
  4210. /* Add the TR elements back into the table in their original order */
  4211. if (!bRemove && oSettings.nTableReinsertBefore) {
  4212. nOrig.insertBefore(oSettings.nTable, oSettings.nTableReinsertBefore);
  4213. }
  4214. else if (!bRemove) {
  4215. nOrig.appendChild(oSettings.nTable);
  4216. }
  4217. for (i = 0, iLen = oSettings.aoData.length; i < iLen; i++) {
  4218. if (oSettings.aoData[i].nTr !== null) {
  4219. nBody.appendChild(oSettings.aoData[i].nTr);
  4220. }
  4221. }
  4222. /* Restore the width of the original table */
  4223. if (oSettings.oFeatures.bAutoWidth === true) {
  4224. oSettings.nTable.style.width = _fnStringToCss(oSettings.sDestroyWidth);
  4225. }
  4226. /* If the were originally stripe classes - then we add them back here. Note
  4227. * this is not fool proof (for example if not all rows had stripe classes - but
  4228. * it's a good effort without getting carried away
  4229. */
  4230. iLen = oSettings.asDestroyStripes.length;
  4231. if (iLen) {
  4232. var anRows = $(nBody).children('tr');
  4233. for (i = 0; i < iLen; i++) {
  4234. anRows.filter(':nth-child(' + iLen + 'n + ' + i + ')').addClass(oSettings.asDestroyStripes[i]);
  4235. }
  4236. }
  4237. /* Remove the settings object from the settings array */
  4238. for (i = 0, iLen = DataTable.settings.length; i < iLen; i++) {
  4239. if (DataTable.settings[i] == oSettings) {
  4240. DataTable.settings.splice(i, 1);
  4241. }
  4242. }
  4243. /* End it all */
  4244. oSettings = null;
  4245. oInit = null;
  4246. };
  4247. /**
  4248. * Redraw the table
  4249. * @param {bool} [bComplete=true] Re-filter and resort (if enabled) the table before the draw.
  4250. * @dtopt API
  4251. *
  4252. * @example
  4253. * $(document).ready(function() {
  4254. * var oTable = $('#example').dataTable();
  4255. *
  4256. * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
  4257. * oTable.fnDraw();
  4258. * } );
  4259. */
  4260. this.fnDraw = function (bComplete) {
  4261. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4262. if (bComplete === false) {
  4263. _fnCalculateEnd(oSettings);
  4264. _fnDraw(oSettings);
  4265. }
  4266. else {
  4267. _fnReDraw(oSettings);
  4268. }
  4269. };
  4270. /**
  4271. * Filter the input based on data
  4272. * @param {string} sInput String to filter the table on
  4273. * @param {int|null} [iColumn] Column to limit filtering to
  4274. * @param {bool} [bRegex=false] Treat as regular expression or not
  4275. * @param {bool} [bSmart=true] Perform smart filtering or not
  4276. * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
  4277. * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
  4278. * @dtopt API
  4279. *
  4280. * @example
  4281. * $(document).ready(function() {
  4282. * var oTable = $('#example').dataTable();
  4283. *
  4284. * // Sometime later - filter...
  4285. * oTable.fnFilter( 'test string' );
  4286. * } );
  4287. */
  4288. this.fnFilter = function (sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive) {
  4289. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4290. if (!oSettings.oFeatures.bFilter) {
  4291. return;
  4292. }
  4293. if (bRegex === undefined || bRegex === null) {
  4294. bRegex = false;
  4295. }
  4296. if (bSmart === undefined || bSmart === null) {
  4297. bSmart = true;
  4298. }
  4299. if (bShowGlobal === undefined || bShowGlobal === null) {
  4300. bShowGlobal = true;
  4301. }
  4302. if (bCaseInsensitive === undefined || bCaseInsensitive === null) {
  4303. bCaseInsensitive = true;
  4304. }
  4305. if (iColumn === undefined || iColumn === null) {
  4306. /* Global filter */
  4307. _fnFilterComplete(oSettings, {
  4308. "sSearch":sInput + "",
  4309. "bRegex":bRegex,
  4310. "bSmart":bSmart,
  4311. "bCaseInsensitive":bCaseInsensitive
  4312. }, 1);
  4313. if (bShowGlobal && oSettings.aanFeatures.f) {
  4314. var n = oSettings.aanFeatures.f;
  4315. for (var i = 0, iLen = n.length; i < iLen; i++) {
  4316. // IE9 throws an 'unknown error' if document.activeElement is used
  4317. // inside an iframe or frame...
  4318. try {
  4319. if (n[i]._DT_Input != document.activeElement) {
  4320. $(n[i]._DT_Input).val(sInput);
  4321. }
  4322. }
  4323. catch (e) {
  4324. $(n[i]._DT_Input).val(sInput);
  4325. }
  4326. }
  4327. }
  4328. }
  4329. else {
  4330. /* Single column filter */
  4331. $.extend(oSettings.aoPreSearchCols[ iColumn ], {
  4332. "sSearch":sInput + "",
  4333. "bRegex":bRegex,
  4334. "bSmart":bSmart,
  4335. "bCaseInsensitive":bCaseInsensitive
  4336. });
  4337. _fnFilterComplete(oSettings, oSettings.oPreviousSearch, 1);
  4338. }
  4339. };
  4340. /**
  4341. * Get the data for the whole table, an individual row or an individual cell based on the
  4342. * provided parameters.
  4343. * @param {int|node} [mRow] A TR row node, TD/TH cell node or an integer. If given as
  4344. * a TR node then the data source for the whole row will be returned. If given as a
  4345. * TD/TH cell node then iCol will be automatically calculated and the data for the
  4346. * cell returned. If given as an integer, then this is treated as the aoData internal
  4347. * data index for the row (see fnGetPosition) and the data for that row used.
  4348. * @param {int} [iCol] Optional column index that you want the data of.
  4349. * @returns {array|object|string} If mRow is undefined, then the data for all rows is
  4350. * returned. If mRow is defined, just data for that row, and is iCol is
  4351. * defined, only data for the designated cell is returned.
  4352. * @dtopt API
  4353. *
  4354. * @example
  4355. * // Row data
  4356. * $(document).ready(function() {
  4357. * oTable = $('#example').dataTable();
  4358. *
  4359. * oTable.$('tr').click( function () {
  4360. * var data = oTable.fnGetData( this );
  4361. * // ... do something with the array / object of data for the row
  4362. * } );
  4363. * } );
  4364. *
  4365. * @example
  4366. * // Individual cell data
  4367. * $(document).ready(function() {
  4368. * oTable = $('#example').dataTable();
  4369. *
  4370. * oTable.$('td').click( function () {
  4371. * var sData = oTable.fnGetData( this );
  4372. * alert( 'The cell clicked on had the value of '+sData );
  4373. * } );
  4374. * } );
  4375. */
  4376. this.fnGetData = function (mRow, iCol) {
  4377. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4378. if (mRow !== undefined) {
  4379. var iRow = mRow;
  4380. if (typeof mRow === 'object') {
  4381. var sNode = mRow.nodeName.toLowerCase();
  4382. if (sNode === "tr") {
  4383. iRow = _fnNodeToDataIndex(oSettings, mRow);
  4384. }
  4385. else if (sNode === "td") {
  4386. iRow = _fnNodeToDataIndex(oSettings, mRow.parentNode);
  4387. iCol = _fnNodeToColumnIndex(oSettings, iRow, mRow);
  4388. }
  4389. }
  4390. if (iCol !== undefined) {
  4391. return _fnGetCellData(oSettings, iRow, iCol, '');
  4392. }
  4393. return (oSettings.aoData[iRow] !== undefined) ?
  4394. oSettings.aoData[iRow]._aData : null;
  4395. }
  4396. return _fnGetDataMaster(oSettings);
  4397. };
  4398. /**
  4399. * Get an array of the TR nodes that are used in the table's body. Note that you will
  4400. * typically want to use the '$' API method in preference to this as it is more
  4401. * flexible.
  4402. * @param {int} [iRow] Optional row index for the TR element you want
  4403. * @returns {array|node} If iRow is undefined, returns an array of all TR elements
  4404. * in the table's body, or iRow is defined, just the TR element requested.
  4405. * @dtopt API
  4406. *
  4407. * @example
  4408. * $(document).ready(function() {
  4409. * var oTable = $('#example').dataTable();
  4410. *
  4411. * // Get the nodes from the table
  4412. * var nNodes = oTable.fnGetNodes( );
  4413. * } );
  4414. */
  4415. this.fnGetNodes = function (iRow) {
  4416. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4417. if (iRow !== undefined) {
  4418. return (oSettings.aoData[iRow] !== undefined) ?
  4419. oSettings.aoData[iRow].nTr : null;
  4420. }
  4421. return _fnGetTrNodes(oSettings);
  4422. };
  4423. /**
  4424. * Get the array indexes of a particular cell from it's DOM element
  4425. * and column index including hidden columns
  4426. * @param {node} nNode this can either be a TR, TD or TH in the table's body
  4427. * @returns {int} If nNode is given as a TR, then a single index is returned, or
  4428. * if given as a cell, an array of [row index, column index (visible),
  4429. * column index (all)] is given.
  4430. * @dtopt API
  4431. *
  4432. * @example
  4433. * $(document).ready(function() {
  4434. * $('#example tbody td').click( function () {
  4435. * // Get the position of the current data from the node
  4436. * var aPos = oTable.fnGetPosition( this );
  4437. *
  4438. * // Get the data array for this row
  4439. * var aData = oTable.fnGetData( aPos[0] );
  4440. *
  4441. * // Update the data array and return the value
  4442. * aData[ aPos[1] ] = 'clicked';
  4443. * this.innerHTML = 'clicked';
  4444. * } );
  4445. *
  4446. * // Init DataTables
  4447. * oTable = $('#example').dataTable();
  4448. * } );
  4449. */
  4450. this.fnGetPosition = function (nNode) {
  4451. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4452. var sNodeName = nNode.nodeName.toUpperCase();
  4453. if (sNodeName == "TR") {
  4454. return _fnNodeToDataIndex(oSettings, nNode);
  4455. }
  4456. else if (sNodeName == "TD" || sNodeName == "TH") {
  4457. var iDataIndex = _fnNodeToDataIndex(oSettings, nNode.parentNode);
  4458. var iColumnIndex = _fnNodeToColumnIndex(oSettings, iDataIndex, nNode);
  4459. return [ iDataIndex, _fnColumnIndexToVisible(oSettings, iColumnIndex), iColumnIndex ];
  4460. }
  4461. return null;
  4462. };
  4463. /**
  4464. * Check to see if a row is 'open' or not.
  4465. * @param {node} nTr the table row to check
  4466. * @returns {boolean} true if the row is currently open, false otherwise
  4467. * @dtopt API
  4468. *
  4469. * @example
  4470. * $(document).ready(function() {
  4471. * var oTable;
  4472. *
  4473. * // 'open' an information row when a row is clicked on
  4474. * $('#example tbody tr').click( function () {
  4475. * if ( oTable.fnIsOpen(this) ) {
  4476. * oTable.fnClose( this );
  4477. * } else {
  4478. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  4479. * }
  4480. * } );
  4481. *
  4482. * oTable = $('#example').dataTable();
  4483. * } );
  4484. */
  4485. this.fnIsOpen = function (nTr) {
  4486. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4487. var aoOpenRows = oSettings.aoOpenRows;
  4488. for (var i = 0; i < oSettings.aoOpenRows.length; i++) {
  4489. if (oSettings.aoOpenRows[i].nParent == nTr) {
  4490. return true;
  4491. }
  4492. }
  4493. return false;
  4494. };
  4495. /**
  4496. * This function will place a new row directly after a row which is currently
  4497. * on display on the page, with the HTML contents that is passed into the
  4498. * function. This can be used, for example, to ask for confirmation that a
  4499. * particular record should be deleted.
  4500. * @param {node} nTr The table row to 'open'
  4501. * @param {string|node|jQuery} mHtml The HTML to put into the row
  4502. * @param {string} sClass Class to give the new TD cell
  4503. * @returns {node} The row opened. Note that if the table row passed in as the
  4504. * first parameter, is not found in the table, this method will silently
  4505. * return.
  4506. * @dtopt API
  4507. *
  4508. * @example
  4509. * $(document).ready(function() {
  4510. * var oTable;
  4511. *
  4512. * // 'open' an information row when a row is clicked on
  4513. * $('#example tbody tr').click( function () {
  4514. * if ( oTable.fnIsOpen(this) ) {
  4515. * oTable.fnClose( this );
  4516. * } else {
  4517. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  4518. * }
  4519. * } );
  4520. *
  4521. * oTable = $('#example').dataTable();
  4522. * } );
  4523. */
  4524. this.fnOpen = function (nTr, mHtml, sClass) {
  4525. /* Find settings from table node */
  4526. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4527. /* Check that the row given is in the table */
  4528. var nTableRows = _fnGetTrNodes(oSettings);
  4529. if ($.inArray(nTr, nTableRows) === -1) {
  4530. return;
  4531. }
  4532. /* the old open one if there is one */
  4533. this.fnClose(nTr);
  4534. var nNewRow = document.createElement("tr");
  4535. var nNewCell = document.createElement("td");
  4536. nNewRow.appendChild(nNewCell);
  4537. nNewCell.className = sClass;
  4538. nNewCell.colSpan = _fnVisbleColumns(oSettings);
  4539. if (typeof mHtml === "string") {
  4540. nNewCell.innerHTML = mHtml;
  4541. }
  4542. else {
  4543. $(nNewCell).html(mHtml);
  4544. }
  4545. /* If the nTr isn't on the page at the moment - then we don't insert at the moment */
  4546. var nTrs = $('tr', oSettings.nTBody);
  4547. if ($.inArray(nTr, nTrs) != -1) {
  4548. $(nNewRow).insertAfter(nTr);
  4549. }
  4550. oSettings.aoOpenRows.push({
  4551. "nTr":nNewRow,
  4552. "nParent":nTr
  4553. });
  4554. return nNewRow;
  4555. };
  4556. /**
  4557. * Change the pagination - provides the internal logic for pagination in a simple API
  4558. * function. With this function you can have a DataTables table go to the next,
  4559. * previous, first or last pages.
  4560. * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
  4561. * or page number to jump to (integer), note that page 0 is the first page.
  4562. * @param {bool} [bRedraw=true] Redraw the table or not
  4563. * @dtopt API
  4564. *
  4565. * @example
  4566. * $(document).ready(function() {
  4567. * var oTable = $('#example').dataTable();
  4568. * oTable.fnPageChange( 'next' );
  4569. * } );
  4570. */
  4571. this.fnPageChange = function (mAction, bRedraw) {
  4572. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4573. _fnPageChange(oSettings, mAction);
  4574. _fnCalculateEnd(oSettings);
  4575. if (bRedraw === undefined || bRedraw) {
  4576. _fnDraw(oSettings);
  4577. }
  4578. };
  4579. /**
  4580. * Show a particular column
  4581. * @param {int} iCol The column whose display should be changed
  4582. * @param {bool} bShow Show (true) or hide (false) the column
  4583. * @param {bool} [bRedraw=true] Redraw the table or not
  4584. * @dtopt API
  4585. *
  4586. * @example
  4587. * $(document).ready(function() {
  4588. * var oTable = $('#example').dataTable();
  4589. *
  4590. * // Hide the second column after initialisation
  4591. * oTable.fnSetColumnVis( 1, false );
  4592. * } );
  4593. */
  4594. this.fnSetColumnVis = function (iCol, bShow, bRedraw) {
  4595. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4596. var i, iLen;
  4597. var aoColumns = oSettings.aoColumns;
  4598. var aoData = oSettings.aoData;
  4599. var nTd, bAppend, iBefore;
  4600. /* No point in doing anything if we are requesting what is already true */
  4601. if (aoColumns[iCol].bVisible == bShow) {
  4602. return;
  4603. }
  4604. /* Show the column */
  4605. if (bShow) {
  4606. var iInsert = 0;
  4607. for (i = 0; i < iCol; i++) {
  4608. if (aoColumns[i].bVisible) {
  4609. iInsert++;
  4610. }
  4611. }
  4612. /* Need to decide if we should use appendChild or insertBefore */
  4613. bAppend = (iInsert >= _fnVisbleColumns(oSettings));
  4614. /* Which coloumn should we be inserting before? */
  4615. if (!bAppend) {
  4616. for (i = iCol; i < aoColumns.length; i++) {
  4617. if (aoColumns[i].bVisible) {
  4618. iBefore = i;
  4619. break;
  4620. }
  4621. }
  4622. }
  4623. for (i = 0, iLen = aoData.length; i < iLen; i++) {
  4624. if (aoData[i].nTr !== null) {
  4625. if (bAppend) {
  4626. aoData[i].nTr.appendChild(
  4627. aoData[i]._anHidden[iCol]
  4628. );
  4629. }
  4630. else {
  4631. aoData[i].nTr.insertBefore(
  4632. aoData[i]._anHidden[iCol],
  4633. _fnGetTdNodes(oSettings, i)[iBefore]);
  4634. }
  4635. }
  4636. }
  4637. }
  4638. else {
  4639. /* Remove a column from display */
  4640. for (i = 0, iLen = aoData.length; i < iLen; i++) {
  4641. if (aoData[i].nTr !== null) {
  4642. nTd = _fnGetTdNodes(oSettings, i)[iCol];
  4643. aoData[i]._anHidden[iCol] = nTd;
  4644. nTd.parentNode.removeChild(nTd);
  4645. }
  4646. }
  4647. }
  4648. /* Clear to set the visible flag */
  4649. aoColumns[iCol].bVisible = bShow;
  4650. /* Redraw the header and footer based on the new column visibility */
  4651. _fnDrawHead(oSettings, oSettings.aoHeader);
  4652. if (oSettings.nTFoot) {
  4653. _fnDrawHead(oSettings, oSettings.aoFooter);
  4654. }
  4655. /* If there are any 'open' rows, then we need to alter the colspan for this col change */
  4656. for (i = 0, iLen = oSettings.aoOpenRows.length; i < iLen; i++) {
  4657. oSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns(oSettings);
  4658. }
  4659. /* Do a redraw incase anything depending on the table columns needs it
  4660. * (built-in: scrolling)
  4661. */
  4662. if (bRedraw === undefined || bRedraw) {
  4663. _fnAdjustColumnSizing(oSettings);
  4664. _fnDraw(oSettings);
  4665. }
  4666. _fnSaveState(oSettings);
  4667. };
  4668. /**
  4669. * Get the settings for a particular table for external manipulation
  4670. * @returns {object} DataTables settings object. See
  4671. * {@link DataTable.models.oSettings}
  4672. * @dtopt API
  4673. *
  4674. * @example
  4675. * $(document).ready(function() {
  4676. * var oTable = $('#example').dataTable();
  4677. * var oSettings = oTable.fnSettings();
  4678. *
  4679. * // Show an example parameter from the settings
  4680. * alert( oSettings._iDisplayStart );
  4681. * } );
  4682. */
  4683. this.fnSettings = function () {
  4684. return _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4685. };
  4686. /**
  4687. * Sort the table by a particular column
  4688. * @param {int} iCol the data index to sort on. Note that this will not match the
  4689. * 'display index' if you have hidden data entries
  4690. * @dtopt API
  4691. *
  4692. * @example
  4693. * $(document).ready(function() {
  4694. * var oTable = $('#example').dataTable();
  4695. *
  4696. * // Sort immediately with columns 0 and 1
  4697. * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
  4698. * } );
  4699. */
  4700. this.fnSort = function (aaSort) {
  4701. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4702. oSettings.aaSorting = aaSort;
  4703. _fnSort(oSettings);
  4704. };
  4705. /**
  4706. * Attach a sort listener to an element for a given column
  4707. * @param {node} nNode the element to attach the sort listener to
  4708. * @param {int} iColumn the column that a click on this node will sort on
  4709. * @param {function} [fnCallback] callback function when sort is run
  4710. * @dtopt API
  4711. *
  4712. * @example
  4713. * $(document).ready(function() {
  4714. * var oTable = $('#example').dataTable();
  4715. *
  4716. * // Sort on column 1, when 'sorter' is clicked on
  4717. * oTable.fnSortListener( document.getElementById('sorter'), 1 );
  4718. * } );
  4719. */
  4720. this.fnSortListener = function (nNode, iColumn, fnCallback) {
  4721. _fnSortAttachListener(_fnSettingsFromNode(this[DataTable.ext.iApiIndex]), nNode, iColumn,
  4722. fnCallback);
  4723. };
  4724. /**
  4725. * Update a table cell or row - this method will accept either a single value to
  4726. * update the cell with, an array of values with one element for each column or
  4727. * an object in the same format as the original data source. The function is
  4728. * self-referencing in order to make the multi column updates easier.
  4729. * @param {object|array|string} mData Data to update the cell/row with
  4730. * @param {node|int} mRow TR element you want to update or the aoData index
  4731. * @param {int} [iColumn] The column to update (not used of mData is an array or object)
  4732. * @param {bool} [bRedraw=true] Redraw the table or not
  4733. * @param {bool} [bAction=true] Perform pre-draw actions or not
  4734. * @returns {int} 0 on success, 1 on error
  4735. * @dtopt API
  4736. *
  4737. * @example
  4738. * $(document).ready(function() {
  4739. * var oTable = $('#example').dataTable();
  4740. * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
  4741. * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], 1, 0 ); // Row
  4742. * } );
  4743. */
  4744. this.fnUpdate = function (mData, mRow, iColumn, bRedraw, bAction) {
  4745. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4746. var i, iLen, sDisplay;
  4747. var iRow = (typeof mRow === 'object') ?
  4748. _fnNodeToDataIndex(oSettings, mRow) : mRow;
  4749. if ($.isArray(mData) && iColumn === undefined) {
  4750. /* Array update - update the whole row */
  4751. oSettings.aoData[iRow]._aData = mData.slice();
  4752. /* Flag to the function that we are recursing */
  4753. for (i = 0; i < oSettings.aoColumns.length; i++) {
  4754. this.fnUpdate(_fnGetCellData(oSettings, iRow, i), iRow, i, false, false);
  4755. }
  4756. }
  4757. else if ($.isPlainObject(mData) && iColumn === undefined) {
  4758. /* Object update - update the whole row - assume the developer gets the object right */
  4759. oSettings.aoData[iRow]._aData = $.extend(true, {}, mData);
  4760. for (i = 0; i < oSettings.aoColumns.length; i++) {
  4761. this.fnUpdate(_fnGetCellData(oSettings, iRow, i), iRow, i, false, false);
  4762. }
  4763. }
  4764. else {
  4765. /* Individual cell update */
  4766. _fnSetCellData(oSettings, iRow, iColumn, mData);
  4767. sDisplay = _fnGetCellData(oSettings, iRow, iColumn, 'display');
  4768. var oCol = oSettings.aoColumns[iColumn];
  4769. if (oCol.fnRender !== null) {
  4770. sDisplay = _fnRender(oSettings, iRow, iColumn);
  4771. if (oCol.bUseRendered) {
  4772. _fnSetCellData(oSettings, iRow, iColumn, sDisplay);
  4773. }
  4774. }
  4775. if (oSettings.aoData[iRow].nTr !== null) {
  4776. /* Do the actual HTML update */
  4777. _fnGetTdNodes(oSettings, iRow)[iColumn].innerHTML = sDisplay;
  4778. }
  4779. }
  4780. /* Modify the search index for this row (strictly this is likely not needed, since fnReDraw
  4781. * will rebuild the search array - however, the redraw might be disabled by the user)
  4782. */
  4783. var iDisplayIndex = $.inArray(iRow, oSettings.aiDisplay);
  4784. oSettings.asDataSearch[iDisplayIndex] = _fnBuildSearchRow(
  4785. oSettings,
  4786. _fnGetRowData(oSettings, iRow, 'filter', _fnGetColumns(oSettings, 'bSearchable'))
  4787. );
  4788. /* Perform pre-draw actions */
  4789. if (bAction === undefined || bAction) {
  4790. _fnAdjustColumnSizing(oSettings);
  4791. }
  4792. /* Redraw the table */
  4793. if (bRedraw === undefined || bRedraw) {
  4794. _fnReDraw(oSettings);
  4795. }
  4796. return 0;
  4797. };
  4798. /**
  4799. * Provide a common method for plug-ins to check the version of DataTables being used, in order
  4800. * to ensure compatibility.
  4801. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
  4802. * formats "X" and "X.Y" are also acceptable.
  4803. * @returns {boolean} true if this version of DataTables is greater or equal to the required
  4804. * version, or false if this version of DataTales is not suitable
  4805. * @method
  4806. * @dtopt API
  4807. *
  4808. * @example
  4809. * $(document).ready(function() {
  4810. * var oTable = $('#example').dataTable();
  4811. * alert( oTable.fnVersionCheck( '1.9.0' ) );
  4812. * } );
  4813. */
  4814. this.fnVersionCheck = DataTable.ext.fnVersionCheck;
  4815. /*
  4816. * This is really a good bit rubbish this method of exposing the internal methods
  4817. * publicly... - To be fixed in 2.0 using methods on the prototype
  4818. */
  4819. /**
  4820. * Create a wrapper function for exporting an internal functions to an external API.
  4821. * @param {string} sFunc API function name
  4822. * @returns {function} wrapped function
  4823. * @memberof DataTable#oApi
  4824. */
  4825. function _fnExternApiFunc(sFunc) {
  4826. return function () {
  4827. var aArgs = [_fnSettingsFromNode(this[DataTable.ext.iApiIndex])].concat(
  4828. Array.prototype.slice.call(arguments));
  4829. return DataTable.ext.oApi[sFunc].apply(this, aArgs);
  4830. };
  4831. }
  4832. /**
  4833. * Reference to internal functions for use by plug-in developers. Note that these
  4834. * methods are references to internal functions and are considered to be private.
  4835. * If you use these methods, be aware that they are liable to change between versions
  4836. * (check the upgrade notes).
  4837. * @namespace
  4838. */
  4839. this.oApi = {
  4840. "_fnExternApiFunc":_fnExternApiFunc,
  4841. "_fnInitialise":_fnInitialise,
  4842. "_fnInitComplete":_fnInitComplete,
  4843. "_fnLanguageCompat":_fnLanguageCompat,
  4844. "_fnAddColumn":_fnAddColumn,
  4845. "_fnColumnOptions":_fnColumnOptions,
  4846. "_fnAddData":_fnAddData,
  4847. "_fnCreateTr":_fnCreateTr,
  4848. "_fnGatherData":_fnGatherData,
  4849. "_fnBuildHead":_fnBuildHead,
  4850. "_fnDrawHead":_fnDrawHead,
  4851. "_fnDraw":_fnDraw,
  4852. "_fnReDraw":_fnReDraw,
  4853. "_fnAjaxUpdate":_fnAjaxUpdate,
  4854. "_fnAjaxParameters":_fnAjaxParameters,
  4855. "_fnAjaxUpdateDraw":_fnAjaxUpdateDraw,
  4856. "_fnServerParams":_fnServerParams,
  4857. "_fnAddOptionsHtml":_fnAddOptionsHtml,
  4858. "_fnFeatureHtmlTable":_fnFeatureHtmlTable,
  4859. "_fnScrollDraw":_fnScrollDraw,
  4860. "_fnAdjustColumnSizing":_fnAdjustColumnSizing,
  4861. "_fnFeatureHtmlFilter":_fnFeatureHtmlFilter,
  4862. "_fnFilterComplete":_fnFilterComplete,
  4863. "_fnFilterCustom":_fnFilterCustom,
  4864. "_fnFilterColumn":_fnFilterColumn,
  4865. "_fnFilter":_fnFilter,
  4866. "_fnBuildSearchArray":_fnBuildSearchArray,
  4867. "_fnBuildSearchRow":_fnBuildSearchRow,
  4868. "_fnFilterCreateSearch":_fnFilterCreateSearch,
  4869. "_fnDataToSearch":_fnDataToSearch,
  4870. "_fnSort":_fnSort,
  4871. "_fnSortAttachListener":_fnSortAttachListener,
  4872. "_fnSortingClasses":_fnSortingClasses,
  4873. "_fnFeatureHtmlPaginate":_fnFeatureHtmlPaginate,
  4874. "_fnPageChange":_fnPageChange,
  4875. "_fnFeatureHtmlInfo":_fnFeatureHtmlInfo,
  4876. "_fnUpdateInfo":_fnUpdateInfo,
  4877. "_fnFeatureHtmlLength":_fnFeatureHtmlLength,
  4878. "_fnFeatureHtmlProcessing":_fnFeatureHtmlProcessing,
  4879. "_fnProcessingDisplay":_fnProcessingDisplay,
  4880. "_fnVisibleToColumnIndex":_fnVisibleToColumnIndex,
  4881. "_fnColumnIndexToVisible":_fnColumnIndexToVisible,
  4882. "_fnNodeToDataIndex":_fnNodeToDataIndex,
  4883. "_fnVisbleColumns":_fnVisbleColumns,
  4884. "_fnCalculateEnd":_fnCalculateEnd,
  4885. "_fnConvertToWidth":_fnConvertToWidth,
  4886. "_fnCalculateColumnWidths":_fnCalculateColumnWidths,
  4887. "_fnScrollingWidthAdjust":_fnScrollingWidthAdjust,
  4888. "_fnGetWidestNode":_fnGetWidestNode,
  4889. "_fnGetMaxLenString":_fnGetMaxLenString,
  4890. "_fnStringToCss":_fnStringToCss,
  4891. "_fnDetectType":_fnDetectType,
  4892. "_fnSettingsFromNode":_fnSettingsFromNode,
  4893. "_fnGetDataMaster":_fnGetDataMaster,
  4894. "_fnGetTrNodes":_fnGetTrNodes,
  4895. "_fnGetTdNodes":_fnGetTdNodes,
  4896. "_fnEscapeRegex":_fnEscapeRegex,
  4897. "_fnDeleteIndex":_fnDeleteIndex,
  4898. "_fnReOrderIndex":_fnReOrderIndex,
  4899. "_fnColumnOrdering":_fnColumnOrdering,
  4900. "_fnLog":_fnLog,
  4901. "_fnClearTable":_fnClearTable,
  4902. "_fnSaveState":_fnSaveState,
  4903. "_fnLoadState":_fnLoadState,
  4904. "_fnCreateCookie":_fnCreateCookie,
  4905. "_fnReadCookie":_fnReadCookie,
  4906. "_fnDetectHeader":_fnDetectHeader,
  4907. "_fnGetUniqueThs":_fnGetUniqueThs,
  4908. "_fnScrollBarWidth":_fnScrollBarWidth,
  4909. "_fnApplyToChildren":_fnApplyToChildren,
  4910. "_fnMap":_fnMap,
  4911. "_fnGetRowData":_fnGetRowData,
  4912. "_fnGetCellData":_fnGetCellData,
  4913. "_fnSetCellData":_fnSetCellData,
  4914. "_fnGetObjectDataFn":_fnGetObjectDataFn,
  4915. "_fnSetObjectDataFn":_fnSetObjectDataFn,
  4916. "_fnApplyColumnDefs":_fnApplyColumnDefs,
  4917. "_fnBindAction":_fnBindAction,
  4918. "_fnExtend":_fnExtend,
  4919. "_fnCallbackReg":_fnCallbackReg,
  4920. "_fnCallbackFire":_fnCallbackFire,
  4921. "_fnJsonString":_fnJsonString,
  4922. "_fnRender":_fnRender,
  4923. "_fnNodeToColumnIndex":_fnNodeToColumnIndex,
  4924. "_fnInfoMacros":_fnInfoMacros,
  4925. "_fnBrowserDetect":_fnBrowserDetect,
  4926. "_fnGetColumns":_fnGetColumns
  4927. };
  4928. $.extend(DataTable.ext.oApi, this.oApi);
  4929. for (var sFunc in DataTable.ext.oApi) {
  4930. if (sFunc) {
  4931. this[sFunc] = _fnExternApiFunc(sFunc);
  4932. }
  4933. }
  4934. var _that = this;
  4935. this.each(function () {
  4936. var i = 0, iLen, j, jLen, k, kLen;
  4937. var sId = this.getAttribute('id');
  4938. var bInitHandedOff = false;
  4939. var bUsePassedData = false;
  4940. /* Sanity check */
  4941. if (this.nodeName.toLowerCase() != 'table') {
  4942. _fnLog(null, 0, "Attempted to initialise DataTables on a node which is not a " +
  4943. "table: " + this.nodeName);
  4944. return;
  4945. }
  4946. /* Check to see if we are re-initialising a table */
  4947. for (i = 0, iLen = DataTable.settings.length; i < iLen; i++) {
  4948. /* Base check on table node */
  4949. if (DataTable.settings[i].nTable == this) {
  4950. if (oInit === undefined || oInit.bRetrieve) {
  4951. return DataTable.settings[i].oInstance;
  4952. }
  4953. else if (oInit.bDestroy) {
  4954. DataTable.settings[i].oInstance.fnDestroy();
  4955. break;
  4956. }
  4957. else {
  4958. _fnLog(DataTable.settings[i], 0, "Cannot reinitialise DataTable.\n\n" +
  4959. "To retrieve the DataTables object for this table, pass no arguments or see " +
  4960. "the docs for bRetrieve and bDestroy");
  4961. return;
  4962. }
  4963. }
  4964. /* If the element we are initialising has the same ID as a table which was previously
  4965. * initialised, but the table nodes don't match (from before) then we destroy the old
  4966. * instance by simply deleting it. This is under the assumption that the table has been
  4967. * destroyed by other methods. Anyone using non-id selectors will need to do this manually
  4968. */
  4969. if (DataTable.settings[i].sTableId == this.id) {
  4970. DataTable.settings.splice(i, 1);
  4971. break;
  4972. }
  4973. }
  4974. /* Ensure the table has an ID - required for accessibility */
  4975. if (sId === null || sId === "") {
  4976. sId = "DataTables_Table_" + (DataTable.ext._oExternConfig.iNextUnique++);
  4977. this.id = sId;
  4978. }
  4979. /* Create the settings object for this table and set some of the default parameters */
  4980. var oSettings = $.extend(true, {}, DataTable.models.oSettings, {
  4981. "nTable":this,
  4982. "oApi":_that.oApi,
  4983. "oInit":oInit,
  4984. "sDestroyWidth":$(this).width(),
  4985. "sInstance":sId,
  4986. "sTableId":sId
  4987. });
  4988. DataTable.settings.push(oSettings);
  4989. // Need to add the instance after the instance after the settings object has been added
  4990. // to the settings array, so we can self reference the table instance if more than one
  4991. oSettings.oInstance = (_that.length === 1) ? _that : $(this).dataTable();
  4992. /* Setting up the initialisation object */
  4993. if (!oInit) {
  4994. oInit = {};
  4995. }
  4996. // Backwards compatibility, before we apply all the defaults
  4997. if (oInit.oLanguage) {
  4998. _fnLanguageCompat(oInit.oLanguage);
  4999. }
  5000. oInit = _fnExtend($.extend(true, {}, DataTable.defaults), oInit);
  5001. // Map the initialisation options onto the settings object
  5002. _fnMap(oSettings.oFeatures, oInit, "bPaginate");
  5003. _fnMap(oSettings.oFeatures, oInit, "bLengthChange");
  5004. _fnMap(oSettings.oFeatures, oInit, "bFilter");
  5005. _fnMap(oSettings.oFeatures, oInit, "bSort");
  5006. _fnMap(oSettings.oFeatures, oInit, "bInfo");
  5007. _fnMap(oSettings.oFeatures, oInit, "bProcessing");
  5008. _fnMap(oSettings.oFeatures, oInit, "bAutoWidth");
  5009. _fnMap(oSettings.oFeatures, oInit, "bSortClasses");
  5010. _fnMap(oSettings.oFeatures, oInit, "bServerSide");
  5011. _fnMap(oSettings.oFeatures, oInit, "bDeferRender");
  5012. _fnMap(oSettings.oScroll, oInit, "sScrollX", "sX");
  5013. _fnMap(oSettings.oScroll, oInit, "sScrollXInner", "sXInner");
  5014. _fnMap(oSettings.oScroll, oInit, "sScrollY", "sY");
  5015. _fnMap(oSettings.oScroll, oInit, "bScrollCollapse", "bCollapse");
  5016. _fnMap(oSettings.oScroll, oInit, "bScrollInfinite", "bInfinite");
  5017. _fnMap(oSettings.oScroll, oInit, "iScrollLoadGap", "iLoadGap");
  5018. _fnMap(oSettings.oScroll, oInit, "bScrollAutoCss", "bAutoCss");
  5019. _fnMap(oSettings, oInit, "asStripeClasses");
  5020. _fnMap(oSettings, oInit, "asStripClasses", "asStripeClasses"); // legacy
  5021. _fnMap(oSettings, oInit, "fnServerData");
  5022. _fnMap(oSettings, oInit, "fnFormatNumber");
  5023. _fnMap(oSettings, oInit, "sServerMethod");
  5024. _fnMap(oSettings, oInit, "aaSorting");
  5025. _fnMap(oSettings, oInit, "aaSortingFixed");
  5026. _fnMap(oSettings, oInit, "aLengthMenu");
  5027. _fnMap(oSettings, oInit, "sPaginationType");
  5028. _fnMap(oSettings, oInit, "sAjaxSource");
  5029. _fnMap(oSettings, oInit, "sAjaxDataProp");
  5030. _fnMap(oSettings, oInit, "iCookieDuration");
  5031. _fnMap(oSettings, oInit, "sCookiePrefix");
  5032. _fnMap(oSettings, oInit, "sDom");
  5033. _fnMap(oSettings, oInit, "bSortCellsTop");
  5034. _fnMap(oSettings, oInit, "iTabIndex");
  5035. _fnMap(oSettings, oInit, "oSearch", "oPreviousSearch");
  5036. _fnMap(oSettings, oInit, "aoSearchCols", "aoPreSearchCols");
  5037. _fnMap(oSettings, oInit, "iDisplayLength", "_iDisplayLength");
  5038. _fnMap(oSettings, oInit, "bJQueryUI", "bJUI");
  5039. _fnMap(oSettings, oInit, "fnCookieCallback");
  5040. _fnMap(oSettings, oInit, "fnStateLoad");
  5041. _fnMap(oSettings, oInit, "fnStateSave");
  5042. _fnMap(oSettings.oLanguage, oInit, "fnInfoCallback");
  5043. /* Callback functions which are array driven */
  5044. _fnCallbackReg(oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user');
  5045. _fnCallbackReg(oSettings, 'aoServerParams', oInit.fnServerParams, 'user');
  5046. _fnCallbackReg(oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user');
  5047. _fnCallbackReg(oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user');
  5048. _fnCallbackReg(oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user');
  5049. _fnCallbackReg(oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user');
  5050. _fnCallbackReg(oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user');
  5051. _fnCallbackReg(oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user');
  5052. _fnCallbackReg(oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user');
  5053. _fnCallbackReg(oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user');
  5054. _fnCallbackReg(oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user');
  5055. if (oSettings.oFeatures.bServerSide && oSettings.oFeatures.bSort &&
  5056. oSettings.oFeatures.bSortClasses) {
  5057. /* Enable sort classes for server-side processing. Safe to do it here, since server-side
  5058. * processing must be enabled by the developer
  5059. */
  5060. _fnCallbackReg(oSettings, 'aoDrawCallback', _fnSortingClasses, 'server_side_sort_classes');
  5061. }
  5062. else if (oSettings.oFeatures.bDeferRender) {
  5063. _fnCallbackReg(oSettings, 'aoDrawCallback', _fnSortingClasses, 'defer_sort_classes');
  5064. }
  5065. if (oInit.bJQueryUI) {
  5066. /* Use the JUI classes object for display. You could clone the oStdClasses object if
  5067. * you want to have multiple tables with multiple independent classes
  5068. */
  5069. $.extend(oSettings.oClasses, DataTable.ext.oJUIClasses);
  5070. if (oInit.sDom === DataTable.defaults.sDom && DataTable.defaults.sDom === "lfrtip") {
  5071. /* Set the DOM to use a layout suitable for jQuery UI's theming */
  5072. oSettings.sDom = '<"H"lfr>t<"F"ip>';
  5073. }
  5074. }
  5075. else {
  5076. $.extend(oSettings.oClasses, DataTable.ext.oStdClasses);
  5077. }
  5078. $(this).addClass(oSettings.oClasses.sTable);
  5079. /* Calculate the scroll bar width and cache it for use later on */
  5080. if (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") {
  5081. oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
  5082. }
  5083. if (oSettings.iInitDisplayStart === undefined) {
  5084. /* Display start point, taking into account the save saving */
  5085. oSettings.iInitDisplayStart = oInit.iDisplayStart;
  5086. oSettings._iDisplayStart = oInit.iDisplayStart;
  5087. }
  5088. /* Must be done after everything which can be overridden by a cookie! */
  5089. if (oInit.bStateSave) {
  5090. oSettings.oFeatures.bStateSave = true;
  5091. _fnLoadState(oSettings, oInit);
  5092. _fnCallbackReg(oSettings, 'aoDrawCallback', _fnSaveState, 'state_save');
  5093. }
  5094. if (oInit.iDeferLoading !== null) {
  5095. oSettings.bDeferLoading = true;
  5096. var tmp = $.isArray(oInit.iDeferLoading);
  5097. oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
  5098. oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
  5099. }
  5100. if (oInit.aaData !== null) {
  5101. bUsePassedData = true;
  5102. }
  5103. /* Language definitions */
  5104. if (oInit.oLanguage.sUrl !== "") {
  5105. /* Get the language definitions from a file - because this Ajax call makes the language
  5106. * get async to the remainder of this function we use bInitHandedOff to indicate that
  5107. * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
  5108. */
  5109. oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;
  5110. $.getJSON(oSettings.oLanguage.sUrl, null, function (json) {
  5111. _fnLanguageCompat(json);
  5112. $.extend(true, oSettings.oLanguage, oInit.oLanguage, json);
  5113. _fnInitialise(oSettings);
  5114. });
  5115. bInitHandedOff = true;
  5116. }
  5117. else {
  5118. $.extend(true, oSettings.oLanguage, oInit.oLanguage);
  5119. }
  5120. /*
  5121. * Stripes
  5122. */
  5123. if (oInit.asStripeClasses === null) {
  5124. oSettings.asStripeClasses = [
  5125. oSettings.oClasses.sStripeOdd,
  5126. oSettings.oClasses.sStripeEven
  5127. ];
  5128. }
  5129. /* Remove row stripe classes if they are already on the table row */
  5130. iLen = oSettings.asStripeClasses.length;
  5131. oSettings.asDestroyStripes = [];
  5132. if (iLen) {
  5133. var bStripeRemove = false;
  5134. var anRows = $(this).children('tbody').children('tr:lt(' + iLen + ')');
  5135. for (i = 0; i < iLen; i++) {
  5136. if (anRows.hasClass(oSettings.asStripeClasses[i])) {
  5137. bStripeRemove = true;
  5138. /* Store the classes which we are about to remove so they can be re-added on destroy */
  5139. oSettings.asDestroyStripes.push(oSettings.asStripeClasses[i]);
  5140. }
  5141. }
  5142. if (bStripeRemove) {
  5143. anRows.removeClass(oSettings.asStripeClasses.join(' '));
  5144. }
  5145. }
  5146. /*
  5147. * Columns
  5148. * See if we should load columns automatically or use defined ones
  5149. */
  5150. var anThs = [];
  5151. var aoColumnsInit;
  5152. var nThead = this.getElementsByTagName('thead');
  5153. if (nThead.length !== 0) {
  5154. _fnDetectHeader(oSettings.aoHeader, nThead[0]);
  5155. anThs = _fnGetUniqueThs(oSettings);
  5156. }
  5157. /* If not given a column array, generate one with nulls */
  5158. if (oInit.aoColumns === null) {
  5159. aoColumnsInit = [];
  5160. for (i = 0, iLen = anThs.length; i < iLen; i++) {
  5161. aoColumnsInit.push(null);
  5162. }
  5163. }
  5164. else {
  5165. aoColumnsInit = oInit.aoColumns;
  5166. }
  5167. /* Add the columns */
  5168. for (i = 0, iLen = aoColumnsInit.length; i < iLen; i++) {
  5169. /* Short cut - use the loop to check if we have column visibility state to restore */
  5170. if (oInit.saved_aoColumns !== undefined && oInit.saved_aoColumns.length == iLen) {
  5171. if (aoColumnsInit[i] === null) {
  5172. aoColumnsInit[i] = {};
  5173. }
  5174. aoColumnsInit[i].bVisible = oInit.saved_aoColumns[i].bVisible;
  5175. }
  5176. _fnAddColumn(oSettings, anThs ? anThs[i] : null);
  5177. }
  5178. /* Apply the column definitions */
  5179. _fnApplyColumnDefs(oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
  5180. _fnColumnOptions(oSettings, iCol, oDef);
  5181. });
  5182. /*
  5183. * Sorting
  5184. * Check the aaSorting array
  5185. */
  5186. for (i = 0, iLen = oSettings.aaSorting.length; i < iLen; i++) {
  5187. if (oSettings.aaSorting[i][0] >= oSettings.aoColumns.length) {
  5188. oSettings.aaSorting[i][0] = 0;
  5189. }
  5190. var oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ];
  5191. /* Add a default sorting index */
  5192. if (oSettings.aaSorting[i][2] === undefined) {
  5193. oSettings.aaSorting[i][2] = 0;
  5194. }
  5195. /* If aaSorting is not defined, then we use the first indicator in asSorting */
  5196. if (oInit.aaSorting === undefined && oSettings.saved_aaSorting === undefined) {
  5197. oSettings.aaSorting[i][1] = oColumn.asSorting[0];
  5198. }
  5199. /* Set the current sorting index based on aoColumns.asSorting */
  5200. for (j = 0, jLen = oColumn.asSorting.length; j < jLen; j++) {
  5201. if (oSettings.aaSorting[i][1] == oColumn.asSorting[j]) {
  5202. oSettings.aaSorting[i][2] = j;
  5203. break;
  5204. }
  5205. }
  5206. }
  5207. /* Do a first pass on the sorting classes (allows any size changes to be taken into
  5208. * account, and also will apply sorting disabled classes if disabled
  5209. */
  5210. _fnSortingClasses(oSettings);
  5211. /*
  5212. * Final init
  5213. * Cache the header, body and footer as required, creating them if needed
  5214. */
  5215. /* Browser support detection */
  5216. _fnBrowserDetect(oSettings);
  5217. // Work around for Webkit bug 83867 - store the caption-side before removing from doc
  5218. var captions = $(this).children('caption').each(function () {
  5219. this._captionSide = $(this).css('caption-side');
  5220. });
  5221. var thead = $(this).children('thead');
  5222. if (thead.length === 0) {
  5223. thead = [ document.createElement('thead') ];
  5224. this.appendChild(thead[0]);
  5225. }
  5226. oSettings.nTHead = thead[0];
  5227. var tbody = $(this).children('tbody');
  5228. if (tbody.length === 0) {
  5229. tbody = [ document.createElement('tbody') ];
  5230. this.appendChild(tbody[0]);
  5231. }
  5232. oSettings.nTBody = tbody[0];
  5233. oSettings.nTBody.setAttribute("role", "alert");
  5234. oSettings.nTBody.setAttribute("aria-live", "polite");
  5235. oSettings.nTBody.setAttribute("aria-relevant", "all");
  5236. var tfoot = $(this).children('tfoot');
  5237. if (tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "")) {
  5238. // If we are a scrolling table, and no footer has been given, then we need to create
  5239. // a tfoot element for the caption element to be appended to
  5240. tfoot = [ document.createElement('tfoot') ];
  5241. this.appendChild(tfoot[0]);
  5242. }
  5243. if (tfoot.length > 0) {
  5244. oSettings.nTFoot = tfoot[0];
  5245. _fnDetectHeader(oSettings.aoFooter, oSettings.nTFoot);
  5246. }
  5247. /* Check if there is data passing into the constructor */
  5248. if (bUsePassedData) {
  5249. for (i = 0; i < oInit.aaData.length; i++) {
  5250. _fnAddData(oSettings, oInit.aaData[ i ]);
  5251. }
  5252. }
  5253. else {
  5254. /* Grab the data from the page */
  5255. _fnGatherData(oSettings);
  5256. }
  5257. /* Copy the data index array */
  5258. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  5259. /* Initialisation complete - table can be drawn */
  5260. oSettings.bInitialised = true;
  5261. /* Check if we need to initialise the table (it might not have been handed off to the
  5262. * language processor)
  5263. */
  5264. if (bInitHandedOff === false) {
  5265. _fnInitialise(oSettings);
  5266. }
  5267. });
  5268. _that = null;
  5269. return this;
  5270. };
  5271. /**
  5272. * Provide a common method for plug-ins to check the version of DataTables being used, in order
  5273. * to ensure compatibility.
  5274. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
  5275. * formats "X" and "X.Y" are also acceptable.
  5276. * @returns {boolean} true if this version of DataTables is greater or equal to the required
  5277. * version, or false if this version of DataTales is not suitable
  5278. * @static
  5279. * @dtopt API-Static
  5280. *
  5281. * @example
  5282. * alert( $.fn.dataTable.fnVersionCheck( '1.9.0' ) );
  5283. */
  5284. DataTable.fnVersionCheck = function (sVersion) {
  5285. /* This is cheap, but effective */
  5286. var fnZPad = function (Zpad, count) {
  5287. while (Zpad.length < count) {
  5288. Zpad += '0';
  5289. }
  5290. return Zpad;
  5291. };
  5292. var aThis = DataTable.ext.sVersion.split('.');
  5293. var aThat = sVersion.split('.');
  5294. var sThis = '', sThat = '';
  5295. for (var i = 0, iLen = aThat.length; i < iLen; i++) {
  5296. sThis += fnZPad(aThis[i], 3);
  5297. sThat += fnZPad(aThat[i], 3);
  5298. }
  5299. return parseInt(sThis, 10) >= parseInt(sThat, 10);
  5300. };
  5301. /**
  5302. * Check if a TABLE node is a DataTable table already or not.
  5303. * @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other
  5304. * node types can be passed in, but will always return false).
  5305. * @returns {boolean} true the table given is a DataTable, or false otherwise
  5306. * @static
  5307. * @dtopt API-Static
  5308. *
  5309. * @example
  5310. * var ex = document.getElementById('example');
  5311. * if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) {
  5312. * $(ex).dataTable();
  5313. * }
  5314. */
  5315. DataTable.fnIsDataTable = function (nTable) {
  5316. var o = DataTable.settings;
  5317. for (var i = 0; i < o.length; i++) {
  5318. if (o[i].nTable === nTable || o[i].nScrollHead === nTable || o[i].nScrollFoot === nTable) {
  5319. return true;
  5320. }
  5321. }
  5322. return false;
  5323. };
  5324. /**
  5325. * Get all DataTable tables that have been initialised - optionally you can select to
  5326. * get only currently visible tables.
  5327. * @param {boolean} [bVisible=false] Flag to indicate if you want all (default) or
  5328. * visible tables only.
  5329. * @returns {array} Array of TABLE nodes (not DataTable instances) which are DataTables
  5330. * @static
  5331. * @dtopt API-Static
  5332. *
  5333. * @example
  5334. * var table = $.fn.dataTable.fnTables(true);
  5335. * if ( table.length > 0 ) {
  5336. * $(table).dataTable().fnAdjustColumnSizing();
  5337. * }
  5338. */
  5339. DataTable.fnTables = function (bVisible) {
  5340. var out = [];
  5341. jQuery.each(DataTable.settings, function (i, o) {
  5342. if (!bVisible || (bVisible === true && $(o.nTable).is(':visible'))) {
  5343. out.push(o.nTable);
  5344. }
  5345. });
  5346. return out;
  5347. };
  5348. /**
  5349. * Version string for plug-ins to check compatibility. Allowed format is
  5350. * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
  5351. * e are optional
  5352. * @member
  5353. * @type string
  5354. * @default Version number
  5355. */
  5356. DataTable.version = "1.9.4";
  5357. /**
  5358. * Private data store, containing all of the settings objects that are created for the
  5359. * tables on a given page.
  5360. *
  5361. * Note that the <i>DataTable.settings</i> object is aliased to <i>jQuery.fn.dataTableExt</i>
  5362. * through which it may be accessed and manipulated, or <i>jQuery.fn.dataTable.settings</i>.
  5363. * @member
  5364. * @type array
  5365. * @default []
  5366. * @private
  5367. */
  5368. DataTable.settings = [];
  5369. /**
  5370. * Object models container, for the various models that DataTables has available
  5371. * to it. These models define the objects that are used to hold the active state
  5372. * and configuration of the table.
  5373. * @namespace
  5374. */
  5375. DataTable.models = {};
  5376. /**
  5377. * DataTables extension options and plug-ins. This namespace acts as a collection "area"
  5378. * for plug-ins that can be used to extend the default DataTables behaviour - indeed many
  5379. * of the build in methods use this method to provide their own capabilities (sorting methods
  5380. * for example).
  5381. *
  5382. * Note that this namespace is aliased to jQuery.fn.dataTableExt so it can be readily accessed
  5383. * and modified by plug-ins.
  5384. * @namespace
  5385. */
  5386. DataTable.models.ext = {
  5387. /**
  5388. * Plug-in filtering functions - this method of filtering is complimentary to the default
  5389. * type based filtering, and a lot more comprehensive as it allows you complete control
  5390. * over the filtering logic. Each element in this array is a function (parameters
  5391. * described below) that is called for every row in the table, and your logic decides if
  5392. * it should be included in the filtered data set or not.
  5393. * <ul>
  5394. * <li>
  5395. * Function input parameters:
  5396. * <ul>
  5397. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  5398. * <li>{array|object} Data for the row to be processed (same as the original format
  5399. * that was passed in as the data source, or an array from a DOM data source</li>
  5400. * <li>{int} Row index in aoData ({@link DataTable.models.oSettings.aoData}), which can
  5401. * be useful to retrieve the TR element if you need DOM interaction.</li>
  5402. * </ul>
  5403. * </li>
  5404. * <li>
  5405. * Function return:
  5406. * <ul>
  5407. * <li>{boolean} Include the row in the filtered result set (true) or not (false)</li>
  5408. * </ul>
  5409. * </il>
  5410. * </ul>
  5411. * @type array
  5412. * @default []
  5413. *
  5414. * @example
  5415. * // The following example shows custom filtering being applied to the fourth column (i.e.
  5416. * // the aData[3] index) based on two input values from the end-user, matching the data in
  5417. * // a certain range.
  5418. * $.fn.dataTableExt.afnFiltering.push(
  5419. * function( oSettings, aData, iDataIndex ) {
  5420. * var iMin = document.getElementById('min').value * 1;
  5421. * var iMax = document.getElementById('max').value * 1;
  5422. * var iVersion = aData[3] == "-" ? 0 : aData[3]*1;
  5423. * if ( iMin == "" && iMax == "" ) {
  5424. * return true;
  5425. * }
  5426. * else if ( iMin == "" && iVersion < iMax ) {
  5427. * return true;
  5428. * }
  5429. * else if ( iMin < iVersion && "" == iMax ) {
  5430. * return true;
  5431. * }
  5432. * else if ( iMin < iVersion && iVersion < iMax ) {
  5433. * return true;
  5434. * }
  5435. * return false;
  5436. * }
  5437. * );
  5438. */
  5439. "afnFiltering":[],
  5440. /**
  5441. * Plug-in sorting functions - this method of sorting is complimentary to the default type
  5442. * based sorting that DataTables does automatically, allowing much greater control over the
  5443. * the data that is being used to sort a column. This is useful if you want to do sorting
  5444. * based on live data (for example the contents of an 'input' element) rather than just the
  5445. * static string that DataTables knows of. The way these plug-ins work is that you create
  5446. * an array of the values you wish to be sorted for the column in question and then return
  5447. * that array. Which pre-sorting function is run here depends on the sSortDataType parameter
  5448. * that is used for the column (if any). This is the corollary of <i>ofnSearch</i> for sort
  5449. * data.
  5450. * <ul>
  5451. * <li>
  5452. * Function input parameters:
  5453. * <ul>
  5454. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  5455. * <li>{int} Target column index</li>
  5456. * </ul>
  5457. * </li>
  5458. * <li>
  5459. * Function return:
  5460. * <ul>
  5461. * <li>{array} Data for the column to be sorted upon</li>
  5462. * </ul>
  5463. * </il>
  5464. * </ul>
  5465. *
  5466. * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for
  5467. * the different uses that DataTables can put the data to. Specifically <i>mData</i> when
  5468. * used as a function will give you a 'type' (sorting, filtering etc) that you can use to
  5469. * prepare the data as required for the different types. As such, this method is deprecated.
  5470. * @type array
  5471. * @default []
  5472. * @deprecated
  5473. *
  5474. * @example
  5475. * // Updating the cached sorting information with user entered values in HTML input elements
  5476. * jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn )
  5477. * {
  5478. * var aData = [];
  5479. * $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
  5480. * aData.push( this.value );
  5481. * } );
  5482. * return aData;
  5483. * }
  5484. */
  5485. "afnSortData":[],
  5486. /**
  5487. * Feature plug-ins - This is an array of objects which describe the feature plug-ins that are
  5488. * available to DataTables. These feature plug-ins are accessible through the sDom initialisation
  5489. * option. As such, each feature plug-in must describe a function that is used to initialise
  5490. * itself (fnInit), a character so the feature can be enabled by sDom (cFeature) and the name
  5491. * of the feature (sFeature). Thus the objects attached to this method must provide:
  5492. * <ul>
  5493. * <li>{function} fnInit Initialisation of the plug-in
  5494. * <ul>
  5495. * <li>
  5496. * Function input parameters:
  5497. * <ul>
  5498. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  5499. * </ul>
  5500. * </li>
  5501. * <li>
  5502. * Function return:
  5503. * <ul>
  5504. * <li>{node|null} The element which contains your feature. Note that the return
  5505. * may also be void if your plug-in does not require to inject any DOM elements
  5506. * into DataTables control (sDom) - for example this might be useful when
  5507. * developing a plug-in which allows table control via keyboard entry.</li>
  5508. * </ul>
  5509. * </il>
  5510. * </ul>
  5511. * </li>
  5512. * <li>{character} cFeature Character that will be matched in sDom - case sensitive</li>
  5513. * <li>{string} sFeature Feature name</li>
  5514. * </ul>
  5515. * @type array
  5516. * @default []
  5517. *
  5518. * @example
  5519. * // How TableTools initialises itself.
  5520. * $.fn.dataTableExt.aoFeatures.push( {
  5521. * "fnInit": function( oSettings ) {
  5522. * return new TableTools( { "oDTSettings": oSettings } );
  5523. * },
  5524. * "cFeature": "T",
  5525. * "sFeature": "TableTools"
  5526. * } );
  5527. */
  5528. "aoFeatures":[],
  5529. /**
  5530. * Type detection plug-in functions - DataTables utilises types to define how sorting and
  5531. * filtering behave, and types can be either be defined by the developer (sType for the
  5532. * column) or they can be automatically detected by the methods in this array. The functions
  5533. * defined in the array are quite simple, taking a single parameter (the data to analyse)
  5534. * and returning the type if it is a known type, or null otherwise.
  5535. * <ul>
  5536. * <li>
  5537. * Function input parameters:
  5538. * <ul>
  5539. * <li>{*} Data from the column cell to be analysed</li>
  5540. * </ul>
  5541. * </li>
  5542. * <li>
  5543. * Function return:
  5544. * <ul>
  5545. * <li>{string|null} Data type detected, or null if unknown (and thus pass it
  5546. * on to the other type detection functions.</li>
  5547. * </ul>
  5548. * </il>
  5549. * </ul>
  5550. * @type array
  5551. * @default []
  5552. *
  5553. * @example
  5554. * // Currency type detection plug-in:
  5555. * jQuery.fn.dataTableExt.aTypes.push(
  5556. * function ( sData ) {
  5557. * var sValidChars = "0123456789.-";
  5558. * var Char;
  5559. *
  5560. * // Check the numeric part
  5561. * for ( i=1 ; i<sData.length ; i++ ) {
  5562. * Char = sData.charAt(i);
  5563. * if (sValidChars.indexOf(Char) == -1) {
  5564. * return null;
  5565. * }
  5566. * }
  5567. *
  5568. * // Check prefixed by currency
  5569. * if ( sData.charAt(0) == '$' || sData.charAt(0) == '&pound;' ) {
  5570. * return 'currency';
  5571. * }
  5572. * return null;
  5573. * }
  5574. * );
  5575. */
  5576. "aTypes":[],
  5577. /**
  5578. * Provide a common method for plug-ins to check the version of DataTables being used,
  5579. * in order to ensure compatibility.
  5580. * @type function
  5581. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note
  5582. * that the formats "X" and "X.Y" are also acceptable.
  5583. * @returns {boolean} true if this version of DataTables is greater or equal to the
  5584. * required version, or false if this version of DataTales is not suitable
  5585. *
  5586. * @example
  5587. * $(document).ready(function() {
  5588. * var oTable = $('#example').dataTable();
  5589. * alert( oTable.fnVersionCheck( '1.9.0' ) );
  5590. * } );
  5591. */
  5592. "fnVersionCheck":DataTable.fnVersionCheck,
  5593. /**
  5594. * Index for what 'this' index API functions should use
  5595. * @type int
  5596. * @default 0
  5597. */
  5598. "iApiIndex":0,
  5599. /**
  5600. * Pre-processing of filtering data plug-ins - When you assign the sType for a column
  5601. * (or have it automatically detected for you by DataTables or a type detection plug-in),
  5602. * you will typically be using this for custom sorting, but it can also be used to provide
  5603. * custom filtering by allowing you to pre-processing the data and returning the data in
  5604. * the format that should be filtered upon. This is done by adding functions this object
  5605. * with a parameter name which matches the sType for that target column. This is the
  5606. * corollary of <i>afnSortData</i> for filtering data.
  5607. * <ul>
  5608. * <li>
  5609. * Function input parameters:
  5610. * <ul>
  5611. * <li>{*} Data from the column cell to be prepared for filtering</li>
  5612. * </ul>
  5613. * </li>
  5614. * <li>
  5615. * Function return:
  5616. * <ul>
  5617. * <li>{string|null} Formatted string that will be used for the filtering.</li>
  5618. * </ul>
  5619. * </il>
  5620. * </ul>
  5621. *
  5622. * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for
  5623. * the different uses that DataTables can put the data to. Specifically <i>mData</i> when
  5624. * used as a function will give you a 'type' (sorting, filtering etc) that you can use to
  5625. * prepare the data as required for the different types. As such, this method is deprecated.
  5626. * @type object
  5627. * @default {}
  5628. * @deprecated
  5629. *
  5630. * @example
  5631. * $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) {
  5632. * return sData.replace(/\n/g," ").replace( /<.*?>/g, "" );
  5633. * }
  5634. */
  5635. "ofnSearch":{},
  5636. /**
  5637. * Container for all private functions in DataTables so they can be exposed externally
  5638. * @type object
  5639. * @default {}
  5640. */
  5641. "oApi":{},
  5642. /**
  5643. * Storage for the various classes that DataTables uses
  5644. * @type object
  5645. * @default {}
  5646. */
  5647. "oStdClasses":{},
  5648. /**
  5649. * Storage for the various classes that DataTables uses - jQuery UI suitable
  5650. * @type object
  5651. * @default {}
  5652. */
  5653. "oJUIClasses":{},
  5654. /**
  5655. * Pagination plug-in methods - The style and controls of the pagination can significantly
  5656. * impact on how the end user interacts with the data in your table, and DataTables allows
  5657. * the addition of pagination controls by extending this object, which can then be enabled
  5658. * through the <i>sPaginationType</i> initialisation parameter. Each pagination type that
  5659. * is added is an object (the property name of which is what <i>sPaginationType</i> refers
  5660. * to) that has two properties, both methods that are used by DataTables to update the
  5661. * control's state.
  5662. * <ul>
  5663. * <li>
  5664. * fnInit - Initialisation of the paging controls. Called only during initialisation
  5665. * of the table. It is expected that this function will add the required DOM elements
  5666. * to the page for the paging controls to work. The element pointer
  5667. * 'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging
  5668. * controls (note that this is a 2D array to allow for multiple instances of each
  5669. * DataTables DOM element). It is suggested that you add the controls to this element
  5670. * as children
  5671. * <ul>
  5672. * <li>
  5673. * Function input parameters:
  5674. * <ul>
  5675. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  5676. * <li>{node} Container into which the pagination controls must be inserted</li>
  5677. * <li>{function} Draw callback function - whenever the controls cause a page
  5678. * change, this method must be called to redraw the table.</li>
  5679. * </ul>
  5680. * </li>
  5681. * <li>
  5682. * Function return:
  5683. * <ul>
  5684. * <li>No return required</li>
  5685. * </ul>
  5686. * </il>
  5687. * </ul>
  5688. * </il>
  5689. * <li>
  5690. * fnInit - This function is called whenever the paging status of the table changes and is
  5691. * typically used to update classes and/or text of the paging controls to reflex the new
  5692. * status.
  5693. * <ul>
  5694. * <li>
  5695. * Function input parameters:
  5696. * <ul>
  5697. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  5698. * <li>{function} Draw callback function - in case you need to redraw the table again
  5699. * or attach new event listeners</li>
  5700. * </ul>
  5701. * </li>
  5702. * <li>
  5703. * Function return:
  5704. * <ul>
  5705. * <li>No return required</li>
  5706. * </ul>
  5707. * </il>
  5708. * </ul>
  5709. * </il>
  5710. * </ul>
  5711. * @type object
  5712. * @default {}
  5713. *
  5714. * @example
  5715. * $.fn.dataTableExt.oPagination.four_button = {
  5716. * "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) {
  5717. * nFirst = document.createElement( 'span' );
  5718. * nPrevious = document.createElement( 'span' );
  5719. * nNext = document.createElement( 'span' );
  5720. * nLast = document.createElement( 'span' );
  5721. *
  5722. * nFirst.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sFirst ) );
  5723. * nPrevious.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sPrevious ) );
  5724. * nNext.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sNext ) );
  5725. * nLast.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sLast ) );
  5726. *
  5727. * nFirst.className = "paginate_button first";
  5728. * nPrevious.className = "paginate_button previous";
  5729. * nNext.className="paginate_button next";
  5730. * nLast.className = "paginate_button last";
  5731. *
  5732. * nPaging.appendChild( nFirst );
  5733. * nPaging.appendChild( nPrevious );
  5734. * nPaging.appendChild( nNext );
  5735. * nPaging.appendChild( nLast );
  5736. *
  5737. * $(nFirst).click( function () {
  5738. * oSettings.oApi._fnPageChange( oSettings, "first" );
  5739. * fnCallbackDraw( oSettings );
  5740. * } );
  5741. *
  5742. * $(nPrevious).click( function() {
  5743. * oSettings.oApi._fnPageChange( oSettings, "previous" );
  5744. * fnCallbackDraw( oSettings );
  5745. * } );
  5746. *
  5747. * $(nNext).click( function() {
  5748. * oSettings.oApi._fnPageChange( oSettings, "next" );
  5749. * fnCallbackDraw( oSettings );
  5750. * } );
  5751. *
  5752. * $(nLast).click( function() {
  5753. * oSettings.oApi._fnPageChange( oSettings, "last" );
  5754. * fnCallbackDraw( oSettings );
  5755. * } );
  5756. *
  5757. * $(nFirst).bind( 'selectstart', function () { return false; } );
  5758. * $(nPrevious).bind( 'selectstart', function () { return false; } );
  5759. * $(nNext).bind( 'selectstart', function () { return false; } );
  5760. * $(nLast).bind( 'selectstart', function () { return false; } );
  5761. * },
  5762. *
  5763. * "fnUpdate": function ( oSettings, fnCallbackDraw ) {
  5764. * if ( !oSettings.aanFeatures.p ) {
  5765. * return;
  5766. * }
  5767. *
  5768. * // Loop over each instance of the pager
  5769. * var an = oSettings.aanFeatures.p;
  5770. * for ( var i=0, iLen=an.length ; i<iLen ; i++ ) {
  5771. * var buttons = an[i].getElementsByTagName('span');
  5772. * if ( oSettings._iDisplayStart === 0 ) {
  5773. * buttons[0].className = "paginate_disabled_previous";
  5774. * buttons[1].className = "paginate_disabled_previous";
  5775. * }
  5776. * else {
  5777. * buttons[0].className = "paginate_enabled_previous";
  5778. * buttons[1].className = "paginate_enabled_previous";
  5779. * }
  5780. *
  5781. * if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) {
  5782. * buttons[2].className = "paginate_disabled_next";
  5783. * buttons[3].className = "paginate_disabled_next";
  5784. * }
  5785. * else {
  5786. * buttons[2].className = "paginate_enabled_next";
  5787. * buttons[3].className = "paginate_enabled_next";
  5788. * }
  5789. * }
  5790. * }
  5791. * };
  5792. */
  5793. "oPagination":{},
  5794. /**
  5795. * Sorting plug-in methods - Sorting in DataTables is based on the detected type of the
  5796. * data column (you can add your own type detection functions, or override automatic
  5797. * detection using sType). With this specific type given to the column, DataTables will
  5798. * apply the required sort from the functions in the object. Each sort type must provide
  5799. * two mandatory methods, one each for ascending and descending sorting, and can optionally
  5800. * provide a pre-formatting method that will help speed up sorting by allowing DataTables
  5801. * to pre-format the sort data only once (rather than every time the actual sort functions
  5802. * are run). The two sorting functions are typical Javascript sort methods:
  5803. * <ul>
  5804. * <li>
  5805. * Function input parameters:
  5806. * <ul>
  5807. * <li>{*} Data to compare to the second parameter</li>
  5808. * <li>{*} Data to compare to the first parameter</li>
  5809. * </ul>
  5810. * </li>
  5811. * <li>
  5812. * Function return:
  5813. * <ul>
  5814. * <li>{int} Sorting match: <0 if first parameter should be sorted lower than
  5815. * the second parameter, ===0 if the two parameters are equal and >0 if
  5816. * the first parameter should be sorted height than the second parameter.</li>
  5817. * </ul>
  5818. * </il>
  5819. * </ul>
  5820. * @type object
  5821. * @default {}
  5822. *
  5823. * @example
  5824. * // Case-sensitive string sorting, with no pre-formatting method
  5825. * $.extend( $.fn.dataTableExt.oSort, {
  5826. * "string-case-asc": function(x,y) {
  5827. * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  5828. * },
  5829. * "string-case-desc": function(x,y) {
  5830. * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  5831. * }
  5832. * } );
  5833. *
  5834. * @example
  5835. * // Case-insensitive string sorting, with pre-formatting
  5836. * $.extend( $.fn.dataTableExt.oSort, {
  5837. * "string-pre": function(x) {
  5838. * return x.toLowerCase();
  5839. * },
  5840. * "string-asc": function(x,y) {
  5841. * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  5842. * },
  5843. * "string-desc": function(x,y) {
  5844. * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  5845. * }
  5846. * } );
  5847. */
  5848. "oSort":{},
  5849. /**
  5850. * Version string for plug-ins to check compatibility. Allowed format is
  5851. * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
  5852. * e are optional
  5853. * @type string
  5854. * @default Version number
  5855. */
  5856. "sVersion":DataTable.version,
  5857. /**
  5858. * How should DataTables report an error. Can take the value 'alert' or 'throw'
  5859. * @type string
  5860. * @default alert
  5861. */
  5862. "sErrMode":"alert",
  5863. /**
  5864. * Store information for DataTables to access globally about other instances
  5865. * @namespace
  5866. * @private
  5867. */
  5868. "_oExternConfig":{
  5869. /* int:iNextUnique - next unique number for an instance */
  5870. "iNextUnique":0
  5871. }
  5872. };
  5873. /**
  5874. * Template object for the way in which DataTables holds information about
  5875. * search information for the global filter and individual column filters.
  5876. * @namespace
  5877. */
  5878. DataTable.models.oSearch = {
  5879. /**
  5880. * Flag to indicate if the filtering should be case insensitive or not
  5881. * @type boolean
  5882. * @default true
  5883. */
  5884. "bCaseInsensitive":true,
  5885. /**
  5886. * Applied search term
  5887. * @type string
  5888. * @default <i>Empty string</i>
  5889. */
  5890. "sSearch":"",
  5891. /**
  5892. * Flag to indicate if the search term should be interpreted as a
  5893. * regular expression (true) or not (false) and therefore and special
  5894. * regex characters escaped.
  5895. * @type boolean
  5896. * @default false
  5897. */
  5898. "bRegex":false,
  5899. /**
  5900. * Flag to indicate if DataTables is to use its smart filtering or not.
  5901. * @type boolean
  5902. * @default true
  5903. */
  5904. "bSmart":true
  5905. };
  5906. /**
  5907. * Template object for the way in which DataTables holds information about
  5908. * each individual row. This is the object format used for the settings
  5909. * aoData array.
  5910. * @namespace
  5911. */
  5912. DataTable.models.oRow = {
  5913. /**
  5914. * TR element for the row
  5915. * @type node
  5916. * @default null
  5917. */
  5918. "nTr":null,
  5919. /**
  5920. * Data object from the original data source for the row. This is either
  5921. * an array if using the traditional form of DataTables, or an object if
  5922. * using mData options. The exact type will depend on the passed in
  5923. * data from the data source, or will be an array if using DOM a data
  5924. * source.
  5925. * @type array|object
  5926. * @default []
  5927. */
  5928. "_aData":[],
  5929. /**
  5930. * Sorting data cache - this array is ostensibly the same length as the
  5931. * number of columns (although each index is generated only as it is
  5932. * needed), and holds the data that is used for sorting each column in the
  5933. * row. We do this cache generation at the start of the sort in order that
  5934. * the formatting of the sort data need be done only once for each cell
  5935. * per sort. This array should not be read from or written to by anything
  5936. * other than the master sorting methods.
  5937. * @type array
  5938. * @default []
  5939. * @private
  5940. */
  5941. "_aSortData":[],
  5942. /**
  5943. * Array of TD elements that are cached for hidden rows, so they can be
  5944. * reinserted into the table if a column is made visible again (or to act
  5945. * as a store if a column is made hidden). Only hidden columns have a
  5946. * reference in the array. For non-hidden columns the value is either
  5947. * undefined or null.
  5948. * @type array nodes
  5949. * @default []
  5950. * @private
  5951. */
  5952. "_anHidden":[],
  5953. /**
  5954. * Cache of the class name that DataTables has applied to the row, so we
  5955. * can quickly look at this variable rather than needing to do a DOM check
  5956. * on className for the nTr property.
  5957. * @type string
  5958. * @default <i>Empty string</i>
  5959. * @private
  5960. */
  5961. "_sRowStripe":""
  5962. };
  5963. /**
  5964. * Template object for the column information object in DataTables. This object
  5965. * is held in the settings aoColumns array and contains all the information that
  5966. * DataTables needs about each individual column.
  5967. *
  5968. * Note that this object is related to {@link DataTable.defaults.columns}
  5969. * but this one is the internal data store for DataTables's cache of columns.
  5970. * It should NOT be manipulated outside of DataTables. Any configuration should
  5971. * be done through the initialisation options.
  5972. * @namespace
  5973. */
  5974. DataTable.models.oColumn = {
  5975. /**
  5976. * A list of the columns that sorting should occur on when this column
  5977. * is sorted. That this property is an array allows multi-column sorting
  5978. * to be defined for a column (for example first name / last name columns
  5979. * would benefit from this). The values are integers pointing to the
  5980. * columns to be sorted on (typically it will be a single integer pointing
  5981. * at itself, but that doesn't need to be the case).
  5982. * @type array
  5983. */
  5984. "aDataSort":null,
  5985. /**
  5986. * Define the sorting directions that are applied to the column, in sequence
  5987. * as the column is repeatedly sorted upon - i.e. the first value is used
  5988. * as the sorting direction when the column if first sorted (clicked on).
  5989. * Sort it again (click again) and it will move on to the next index.
  5990. * Repeat until loop.
  5991. * @type array
  5992. */
  5993. "asSorting":null,
  5994. /**
  5995. * Flag to indicate if the column is searchable, and thus should be included
  5996. * in the filtering or not.
  5997. * @type boolean
  5998. */
  5999. "bSearchable":null,
  6000. /**
  6001. * Flag to indicate if the column is sortable or not.
  6002. * @type boolean
  6003. */
  6004. "bSortable":null,
  6005. /**
  6006. * <code>Deprecated</code> When using fnRender, you have two options for what
  6007. * to do with the data, and this property serves as the switch. Firstly, you
  6008. * can have the sorting and filtering use the rendered value (true - default),
  6009. * or you can have the sorting and filtering us the original value (false).
  6010. *
  6011. * Please note that this option has now been deprecated and will be removed
  6012. * in the next version of DataTables. Please use mRender / mData rather than
  6013. * fnRender.
  6014. * @type boolean
  6015. * @deprecated
  6016. */
  6017. "bUseRendered":null,
  6018. /**
  6019. * Flag to indicate if the column is currently visible in the table or not
  6020. * @type boolean
  6021. */
  6022. "bVisible":null,
  6023. /**
  6024. * Flag to indicate to the type detection method if the automatic type
  6025. * detection should be used, or if a column type (sType) has been specified
  6026. * @type boolean
  6027. * @default true
  6028. * @private
  6029. */
  6030. "_bAutoType":true,
  6031. /**
  6032. * Developer definable function that is called whenever a cell is created (Ajax source,
  6033. * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  6034. * allowing you to modify the DOM element (add background colour for example) when the
  6035. * element is available.
  6036. * @type function
  6037. * @param {element} nTd The TD node that has been created
  6038. * @param {*} sData The Data for the cell
  6039. * @param {array|object} oData The data for the whole row
  6040. * @param {int} iRow The row index for the aoData data store
  6041. * @default null
  6042. */
  6043. "fnCreatedCell":null,
  6044. /**
  6045. * Function to get data from a cell in a column. You should <b>never</b>
  6046. * access data directly through _aData internally in DataTables - always use
  6047. * the method attached to this property. It allows mData to function as
  6048. * required. This function is automatically assigned by the column
  6049. * initialisation method
  6050. * @type function
  6051. * @param {array|object} oData The data array/object for the array
  6052. * (i.e. aoData[]._aData)
  6053. * @param {string} sSpecific The specific data type you want to get -
  6054. * 'display', 'type' 'filter' 'sort'
  6055. * @returns {*} The data for the cell from the given row's data
  6056. * @default null
  6057. */
  6058. "fnGetData":null,
  6059. /**
  6060. * <code>Deprecated</code> Custom display function that will be called for the
  6061. * display of each cell in this column.
  6062. *
  6063. * Please note that this option has now been deprecated and will be removed
  6064. * in the next version of DataTables. Please use mRender / mData rather than
  6065. * fnRender.
  6066. * @type function
  6067. * @param {object} o Object with the following parameters:
  6068. * @param {int} o.iDataRow The row in aoData
  6069. * @param {int} o.iDataColumn The column in question
  6070. * @param {array} o.aData The data for the row in question
  6071. * @param {object} o.oSettings The settings object for this DataTables instance
  6072. * @returns {string} The string you which to use in the display
  6073. * @default null
  6074. * @deprecated
  6075. */
  6076. "fnRender":null,
  6077. /**
  6078. * Function to set data for a cell in the column. You should <b>never</b>
  6079. * set the data directly to _aData internally in DataTables - always use
  6080. * this method. It allows mData to function as required. This function
  6081. * is automatically assigned by the column initialisation method
  6082. * @type function
  6083. * @param {array|object} oData The data array/object for the array
  6084. * (i.e. aoData[]._aData)
  6085. * @param {*} sValue Value to set
  6086. * @default null
  6087. */
  6088. "fnSetData":null,
  6089. /**
  6090. * Property to read the value for the cells in the column from the data
  6091. * source array / object. If null, then the default content is used, if a
  6092. * function is given then the return from the function is used.
  6093. * @type function|int|string|null
  6094. * @default null
  6095. */
  6096. "mData":null,
  6097. /**
  6098. * Partner property to mData which is used (only when defined) to get
  6099. * the data - i.e. it is basically the same as mData, but without the
  6100. * 'set' option, and also the data fed to it is the result from mData.
  6101. * This is the rendering method to match the data method of mData.
  6102. * @type function|int|string|null
  6103. * @default null
  6104. */
  6105. "mRender":null,
  6106. /**
  6107. * Unique header TH/TD element for this column - this is what the sorting
  6108. * listener is attached to (if sorting is enabled.)
  6109. * @type node
  6110. * @default null
  6111. */
  6112. "nTh":null,
  6113. /**
  6114. * Unique footer TH/TD element for this column (if there is one). Not used
  6115. * in DataTables as such, but can be used for plug-ins to reference the
  6116. * footer for each column.
  6117. * @type node
  6118. * @default null
  6119. */
  6120. "nTf":null,
  6121. /**
  6122. * The class to apply to all TD elements in the table's TBODY for the column
  6123. * @type string
  6124. * @default null
  6125. */
  6126. "sClass":null,
  6127. /**
  6128. * When DataTables calculates the column widths to assign to each column,
  6129. * it finds the longest string in each column and then constructs a
  6130. * temporary table and reads the widths from that. The problem with this
  6131. * is that "mmm" is much wider then "iiii", but the latter is a longer
  6132. * string - thus the calculation can go wrong (doing it properly and putting
  6133. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  6134. * a "work around" we provide this option. It will append its value to the
  6135. * text that is found to be the longest string for the column - i.e. padding.
  6136. * @type string
  6137. */
  6138. "sContentPadding":null,
  6139. /**
  6140. * Allows a default value to be given for a column's data, and will be used
  6141. * whenever a null data source is encountered (this can be because mData
  6142. * is set to null, or because the data source itself is null).
  6143. * @type string
  6144. * @default null
  6145. */
  6146. "sDefaultContent":null,
  6147. /**
  6148. * Name for the column, allowing reference to the column by name as well as
  6149. * by index (needs a lookup to work by name).
  6150. * @type string
  6151. */
  6152. "sName":null,
  6153. /**
  6154. * Custom sorting data type - defines which of the available plug-ins in
  6155. * afnSortData the custom sorting will use - if any is defined.
  6156. * @type string
  6157. * @default std
  6158. */
  6159. "sSortDataType":'std',
  6160. /**
  6161. * Class to be applied to the header element when sorting on this column
  6162. * @type string
  6163. * @default null
  6164. */
  6165. "sSortingClass":null,
  6166. /**
  6167. * Class to be applied to the header element when sorting on this column -
  6168. * when jQuery UI theming is used.
  6169. * @type string
  6170. * @default null
  6171. */
  6172. "sSortingClassJUI":null,
  6173. /**
  6174. * Title of the column - what is seen in the TH element (nTh).
  6175. * @type string
  6176. */
  6177. "sTitle":null,
  6178. /**
  6179. * Column sorting and filtering type
  6180. * @type string
  6181. * @default null
  6182. */
  6183. "sType":null,
  6184. /**
  6185. * Width of the column
  6186. * @type string
  6187. * @default null
  6188. */
  6189. "sWidth":null,
  6190. /**
  6191. * Width of the column when it was first "encountered"
  6192. * @type string
  6193. * @default null
  6194. */
  6195. "sWidthOrig":null
  6196. };
  6197. /**
  6198. * Initialisation options that can be given to DataTables at initialisation
  6199. * time.
  6200. * @namespace
  6201. */
  6202. DataTable.defaults = {
  6203. /**
  6204. * An array of data to use for the table, passed in at initialisation which
  6205. * will be used in preference to any data which is already in the DOM. This is
  6206. * particularly useful for constructing tables purely in Javascript, for
  6207. * example with a custom Ajax call.
  6208. * @type array
  6209. * @default null
  6210. * @dtopt Option
  6211. *
  6212. * @example
  6213. * // Using a 2D array data source
  6214. * $(document).ready( function () {
  6215. * $('#example').dataTable( {
  6216. * "aaData": [
  6217. * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
  6218. * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
  6219. * ],
  6220. * "aoColumns": [
  6221. * { "sTitle": "Engine" },
  6222. * { "sTitle": "Browser" },
  6223. * { "sTitle": "Platform" },
  6224. * { "sTitle": "Version" },
  6225. * { "sTitle": "Grade" }
  6226. * ]
  6227. * } );
  6228. * } );
  6229. *
  6230. * @example
  6231. * // Using an array of objects as a data source (mData)
  6232. * $(document).ready( function () {
  6233. * $('#example').dataTable( {
  6234. * "aaData": [
  6235. * {
  6236. * "engine": "Trident",
  6237. * "browser": "Internet Explorer 4.0",
  6238. * "platform": "Win 95+",
  6239. * "version": 4,
  6240. * "grade": "X"
  6241. * },
  6242. * {
  6243. * "engine": "Trident",
  6244. * "browser": "Internet Explorer 5.0",
  6245. * "platform": "Win 95+",
  6246. * "version": 5,
  6247. * "grade": "C"
  6248. * }
  6249. * ],
  6250. * "aoColumns": [
  6251. * { "sTitle": "Engine", "mData": "engine" },
  6252. * { "sTitle": "Browser", "mData": "browser" },
  6253. * { "sTitle": "Platform", "mData": "platform" },
  6254. * { "sTitle": "Version", "mData": "version" },
  6255. * { "sTitle": "Grade", "mData": "grade" }
  6256. * ]
  6257. * } );
  6258. * } );
  6259. */
  6260. "aaData":null,
  6261. /**
  6262. * If sorting is enabled, then DataTables will perform a first pass sort on
  6263. * initialisation. You can define which column(s) the sort is performed upon,
  6264. * and the sorting direction, with this variable. The aaSorting array should
  6265. * contain an array for each column to be sorted initially containing the
  6266. * column's index and a direction string ('asc' or 'desc').
  6267. * @type array
  6268. * @default [[0,'asc']]
  6269. * @dtopt Option
  6270. *
  6271. * @example
  6272. * // Sort by 3rd column first, and then 4th column
  6273. * $(document).ready( function() {
  6274. * $('#example').dataTable( {
  6275. * "aaSorting": [[2,'asc'], [3,'desc']]
  6276. * } );
  6277. * } );
  6278. *
  6279. * // No initial sorting
  6280. * $(document).ready( function() {
  6281. * $('#example').dataTable( {
  6282. * "aaSorting": []
  6283. * } );
  6284. * } );
  6285. */
  6286. "aaSorting":[
  6287. [0, 'asc']
  6288. ],
  6289. /**
  6290. * This parameter is basically identical to the aaSorting parameter, but
  6291. * cannot be overridden by user interaction with the table. What this means
  6292. * is that you could have a column (visible or hidden) which the sorting will
  6293. * always be forced on first - any sorting after that (from the user) will
  6294. * then be performed as required. This can be useful for grouping rows
  6295. * together.
  6296. * @type array
  6297. * @default null
  6298. * @dtopt Option
  6299. *
  6300. * @example
  6301. * $(document).ready( function() {
  6302. * $('#example').dataTable( {
  6303. * "aaSortingFixed": [[0,'asc']]
  6304. * } );
  6305. * } )
  6306. */
  6307. "aaSortingFixed":null,
  6308. /**
  6309. * This parameter allows you to readily specify the entries in the length drop
  6310. * down menu that DataTables shows when pagination is enabled. It can be
  6311. * either a 1D array of options which will be used for both the displayed
  6312. * option and the value, or a 2D array which will use the array in the first
  6313. * position as the value, and the array in the second position as the
  6314. * displayed options (useful for language strings such as 'All').
  6315. * @type array
  6316. * @default [ 10, 25, 50, 100 ]
  6317. * @dtopt Option
  6318. *
  6319. * @example
  6320. * $(document).ready( function() {
  6321. * $('#example').dataTable( {
  6322. * "aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
  6323. * } );
  6324. * } );
  6325. *
  6326. * @example
  6327. * // Setting the default display length as well as length menu
  6328. * // This is likely to be wanted if you remove the '10' option which
  6329. * // is the iDisplayLength default.
  6330. * $(document).ready( function() {
  6331. * $('#example').dataTable( {
  6332. * "iDisplayLength": 25,
  6333. * "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]]
  6334. * } );
  6335. * } );
  6336. */
  6337. "aLengthMenu":[ 10, 25, 50, 100 ],
  6338. /**
  6339. * The aoColumns option in the initialisation parameter allows you to define
  6340. * details about the way individual columns behave. For a full list of
  6341. * column options that can be set, please see
  6342. * {@link DataTable.defaults.columns}. Note that if you use aoColumns to
  6343. * define your columns, you must have an entry in the array for every single
  6344. * column that you have in your table (these can be null if you don't which
  6345. * to specify any options).
  6346. * @member
  6347. */
  6348. "aoColumns":null,
  6349. /**
  6350. * Very similar to aoColumns, aoColumnDefs allows you to target a specific
  6351. * column, multiple columns, or all columns, using the aTargets property of
  6352. * each object in the array. This allows great flexibility when creating
  6353. * tables, as the aoColumnDefs arrays can be of any length, targeting the
  6354. * columns you specifically want. aoColumnDefs may use any of the column
  6355. * options available: {@link DataTable.defaults.columns}, but it _must_
  6356. * have aTargets defined in each object in the array. Values in the aTargets
  6357. * array may be:
  6358. * <ul>
  6359. * <li>a string - class name will be matched on the TH for the column</li>
  6360. * <li>0 or a positive integer - column index counting from the left</li>
  6361. * <li>a negative integer - column index counting from the right</li>
  6362. * <li>the string "_all" - all columns (i.e. assign a default)</li>
  6363. * </ul>
  6364. * @member
  6365. */
  6366. "aoColumnDefs":null,
  6367. /**
  6368. * Basically the same as oSearch, this parameter defines the individual column
  6369. * filtering state at initialisation time. The array must be of the same size
  6370. * as the number of columns, and each element be an object with the parameters
  6371. * "sSearch" and "bEscapeRegex" (the latter is optional). 'null' is also
  6372. * accepted and the default will be used.
  6373. * @type array
  6374. * @default []
  6375. * @dtopt Option
  6376. *
  6377. * @example
  6378. * $(document).ready( function() {
  6379. * $('#example').dataTable( {
  6380. * "aoSearchCols": [
  6381. * null,
  6382. * { "sSearch": "My filter" },
  6383. * null,
  6384. * { "sSearch": "^[0-9]", "bEscapeRegex": false }
  6385. * ]
  6386. * } );
  6387. * } )
  6388. */
  6389. "aoSearchCols":[],
  6390. /**
  6391. * An array of CSS classes that should be applied to displayed rows. This
  6392. * array may be of any length, and DataTables will apply each class
  6393. * sequentially, looping when required.
  6394. * @type array
  6395. * @default null <i>Will take the values determined by the oClasses.sStripe*
  6396. * options</i>
  6397. * @dtopt Option
  6398. *
  6399. * @example
  6400. * $(document).ready( function() {
  6401. * $('#example').dataTable( {
  6402. * "asStripeClasses": [ 'strip1', 'strip2', 'strip3' ]
  6403. * } );
  6404. * } )
  6405. */
  6406. "asStripeClasses":null,
  6407. /**
  6408. * Enable or disable automatic column width calculation. This can be disabled
  6409. * as an optimisation (it takes some time to calculate the widths) if the
  6410. * tables widths are passed in using aoColumns.
  6411. * @type boolean
  6412. * @default true
  6413. * @dtopt Features
  6414. *
  6415. * @example
  6416. * $(document).ready( function () {
  6417. * $('#example').dataTable( {
  6418. * "bAutoWidth": false
  6419. * } );
  6420. * } );
  6421. */
  6422. "bAutoWidth":true,
  6423. /**
  6424. * Deferred rendering can provide DataTables with a huge speed boost when you
  6425. * are using an Ajax or JS data source for the table. This option, when set to
  6426. * true, will cause DataTables to defer the creation of the table elements for
  6427. * each row until they are needed for a draw - saving a significant amount of
  6428. * time.
  6429. * @type boolean
  6430. * @default false
  6431. * @dtopt Features
  6432. *
  6433. * @example
  6434. * $(document).ready( function() {
  6435. * var oTable = $('#example').dataTable( {
  6436. * "sAjaxSource": "sources/arrays.txt",
  6437. * "bDeferRender": true
  6438. * } );
  6439. * } );
  6440. */
  6441. "bDeferRender":false,
  6442. /**
  6443. * Replace a DataTable which matches the given selector and replace it with
  6444. * one which has the properties of the new initialisation object passed. If no
  6445. * table matches the selector, then the new DataTable will be constructed as
  6446. * per normal.
  6447. * @type boolean
  6448. * @default false
  6449. * @dtopt Options
  6450. *
  6451. * @example
  6452. * $(document).ready( function() {
  6453. * $('#example').dataTable( {
  6454. * "sScrollY": "200px",
  6455. * "bPaginate": false
  6456. * } );
  6457. *
  6458. * // Some time later....
  6459. * $('#example').dataTable( {
  6460. * "bFilter": false,
  6461. * "bDestroy": true
  6462. * } );
  6463. * } );
  6464. */
  6465. "bDestroy":false,
  6466. /**
  6467. * Enable or disable filtering of data. Filtering in DataTables is "smart" in
  6468. * that it allows the end user to input multiple words (space separated) and
  6469. * will match a row containing those words, even if not in the order that was
  6470. * specified (this allow matching across multiple columns). Note that if you
  6471. * wish to use filtering in DataTables this must remain 'true' - to remove the
  6472. * default filtering input box and retain filtering abilities, please use
  6473. * {@link DataTable.defaults.sDom}.
  6474. * @type boolean
  6475. * @default true
  6476. * @dtopt Features
  6477. *
  6478. * @example
  6479. * $(document).ready( function () {
  6480. * $('#example').dataTable( {
  6481. * "bFilter": false
  6482. * } );
  6483. * } );
  6484. */
  6485. "bFilter":true,
  6486. /**
  6487. * Enable or disable the table information display. This shows information
  6488. * about the data that is currently visible on the page, including information
  6489. * about filtered data if that action is being performed.
  6490. * @type boolean
  6491. * @default true
  6492. * @dtopt Features
  6493. *
  6494. * @example
  6495. * $(document).ready( function () {
  6496. * $('#example').dataTable( {
  6497. * "bInfo": false
  6498. * } );
  6499. * } );
  6500. */
  6501. "bInfo":true,
  6502. /**
  6503. * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
  6504. * slightly different and additional mark-up from what DataTables has
  6505. * traditionally used).
  6506. * @type boolean
  6507. * @default false
  6508. * @dtopt Features
  6509. *
  6510. * @example
  6511. * $(document).ready( function() {
  6512. * $('#example').dataTable( {
  6513. * "bJQueryUI": true
  6514. * } );
  6515. * } );
  6516. */
  6517. "bJQueryUI":false,
  6518. /**
  6519. * Allows the end user to select the size of a formatted page from a select
  6520. * menu (sizes are 10, 25, 50 and 100). Requires pagination (bPaginate).
  6521. * @type boolean
  6522. * @default true
  6523. * @dtopt Features
  6524. *
  6525. * @example
  6526. * $(document).ready( function () {
  6527. * $('#example').dataTable( {
  6528. * "bLengthChange": false
  6529. * } );
  6530. * } );
  6531. */
  6532. "bLengthChange":true,
  6533. /**
  6534. * Enable or disable pagination.
  6535. * @type boolean
  6536. * @default true
  6537. * @dtopt Features
  6538. *
  6539. * @example
  6540. * $(document).ready( function () {
  6541. * $('#example').dataTable( {
  6542. * "bPaginate": false
  6543. * } );
  6544. * } );
  6545. */
  6546. "bPaginate":true,
  6547. /**
  6548. * Enable or disable the display of a 'processing' indicator when the table is
  6549. * being processed (e.g. a sort). This is particularly useful for tables with
  6550. * large amounts of data where it can take a noticeable amount of time to sort
  6551. * the entries.
  6552. * @type boolean
  6553. * @default false
  6554. * @dtopt Features
  6555. *
  6556. * @example
  6557. * $(document).ready( function () {
  6558. * $('#example').dataTable( {
  6559. * "bProcessing": true
  6560. * } );
  6561. * } );
  6562. */
  6563. "bProcessing":false,
  6564. /**
  6565. * Retrieve the DataTables object for the given selector. Note that if the
  6566. * table has already been initialised, this parameter will cause DataTables
  6567. * to simply return the object that has already been set up - it will not take
  6568. * account of any changes you might have made to the initialisation object
  6569. * passed to DataTables (setting this parameter to true is an acknowledgement
  6570. * that you understand this). bDestroy can be used to reinitialise a table if
  6571. * you need.
  6572. * @type boolean
  6573. * @default false
  6574. * @dtopt Options
  6575. *
  6576. * @example
  6577. * $(document).ready( function() {
  6578. * initTable();
  6579. * tableActions();
  6580. * } );
  6581. *
  6582. * function initTable ()
  6583. * {
  6584. * return $('#example').dataTable( {
  6585. * "sScrollY": "200px",
  6586. * "bPaginate": false,
  6587. * "bRetrieve": true
  6588. * } );
  6589. * }
  6590. *
  6591. * function tableActions ()
  6592. * {
  6593. * var oTable = initTable();
  6594. * // perform API operations with oTable
  6595. * }
  6596. */
  6597. "bRetrieve":false,
  6598. /**
  6599. * Indicate if DataTables should be allowed to set the padding / margin
  6600. * etc for the scrolling header elements or not. Typically you will want
  6601. * this.
  6602. * @type boolean
  6603. * @default true
  6604. * @dtopt Options
  6605. *
  6606. * @example
  6607. * $(document).ready( function() {
  6608. * $('#example').dataTable( {
  6609. * "bScrollAutoCss": false,
  6610. * "sScrollY": "200px"
  6611. * } );
  6612. * } );
  6613. */
  6614. "bScrollAutoCss":true,
  6615. /**
  6616. * When vertical (y) scrolling is enabled, DataTables will force the height of
  6617. * the table's viewport to the given height at all times (useful for layout).
  6618. * However, this can look odd when filtering data down to a small data set,
  6619. * and the footer is left "floating" further down. This parameter (when
  6620. * enabled) will cause DataTables to collapse the table's viewport down when
  6621. * the result set will fit within the given Y height.
  6622. * @type boolean
  6623. * @default false
  6624. * @dtopt Options
  6625. *
  6626. * @example
  6627. * $(document).ready( function() {
  6628. * $('#example').dataTable( {
  6629. * "sScrollY": "200",
  6630. * "bScrollCollapse": true
  6631. * } );
  6632. * } );
  6633. */
  6634. "bScrollCollapse":false,
  6635. /**
  6636. * Enable infinite scrolling for DataTables (to be used in combination with
  6637. * sScrollY). Infinite scrolling means that DataTables will continually load
  6638. * data as a user scrolls through a table, which is very useful for large
  6639. * dataset. This cannot be used with pagination, which is automatically
  6640. * disabled. Note - the Scroller extra for DataTables is recommended in
  6641. * in preference to this option.
  6642. * @type boolean
  6643. * @default false
  6644. * @dtopt Features
  6645. *
  6646. * @example
  6647. * $(document).ready( function() {
  6648. * $('#example').dataTable( {
  6649. * "bScrollInfinite": true,
  6650. * "bScrollCollapse": true,
  6651. * "sScrollY": "200px"
  6652. * } );
  6653. * } );
  6654. */
  6655. "bScrollInfinite":false,
  6656. /**
  6657. * Configure DataTables to use server-side processing. Note that the
  6658. * sAjaxSource parameter must also be given in order to give DataTables a
  6659. * source to obtain the required data for each draw.
  6660. * @type boolean
  6661. * @default false
  6662. * @dtopt Features
  6663. * @dtopt Server-side
  6664. *
  6665. * @example
  6666. * $(document).ready( function () {
  6667. * $('#example').dataTable( {
  6668. * "bServerSide": true,
  6669. * "sAjaxSource": "xhr.php"
  6670. * } );
  6671. * } );
  6672. */
  6673. "bServerSide":false,
  6674. /**
  6675. * Enable or disable sorting of columns. Sorting of individual columns can be
  6676. * disabled by the "bSortable" option for each column.
  6677. * @type boolean
  6678. * @default true
  6679. * @dtopt Features
  6680. *
  6681. * @example
  6682. * $(document).ready( function () {
  6683. * $('#example').dataTable( {
  6684. * "bSort": false
  6685. * } );
  6686. * } );
  6687. */
  6688. "bSort":true,
  6689. /**
  6690. * Allows control over whether DataTables should use the top (true) unique
  6691. * cell that is found for a single column, or the bottom (false - default).
  6692. * This is useful when using complex headers.
  6693. * @type boolean
  6694. * @default false
  6695. * @dtopt Options
  6696. *
  6697. * @example
  6698. * $(document).ready( function() {
  6699. * $('#example').dataTable( {
  6700. * "bSortCellsTop": true
  6701. * } );
  6702. * } );
  6703. */
  6704. "bSortCellsTop":false,
  6705. /**
  6706. * Enable or disable the addition of the classes 'sorting_1', 'sorting_2' and
  6707. * 'sorting_3' to the columns which are currently being sorted on. This is
  6708. * presented as a feature switch as it can increase processing time (while
  6709. * classes are removed and added) so for large data sets you might want to
  6710. * turn this off.
  6711. * @type boolean
  6712. * @default true
  6713. * @dtopt Features
  6714. *
  6715. * @example
  6716. * $(document).ready( function () {
  6717. * $('#example').dataTable( {
  6718. * "bSortClasses": false
  6719. * } );
  6720. * } );
  6721. */
  6722. "bSortClasses":true,
  6723. /**
  6724. * Enable or disable state saving. When enabled a cookie will be used to save
  6725. * table display information such as pagination information, display length,
  6726. * filtering and sorting. As such when the end user reloads the page the
  6727. * display display will match what thy had previously set up.
  6728. * @type boolean
  6729. * @default false
  6730. * @dtopt Features
  6731. *
  6732. * @example
  6733. * $(document).ready( function () {
  6734. * $('#example').dataTable( {
  6735. * "bStateSave": true
  6736. * } );
  6737. * } );
  6738. */
  6739. "bStateSave":false,
  6740. /**
  6741. * Customise the cookie and / or the parameters being stored when using
  6742. * DataTables with state saving enabled. This function is called whenever
  6743. * the cookie is modified, and it expects a fully formed cookie string to be
  6744. * returned. Note that the data object passed in is a Javascript object which
  6745. * must be converted to a string (JSON.stringify for example).
  6746. * @type function
  6747. * @param {string} sName Name of the cookie defined by DataTables
  6748. * @param {object} oData Data to be stored in the cookie
  6749. * @param {string} sExpires Cookie expires string
  6750. * @param {string} sPath Path of the cookie to set
  6751. * @returns {string} Cookie formatted string (which should be encoded by
  6752. * using encodeURIComponent())
  6753. * @dtopt Callbacks
  6754. *
  6755. * @example
  6756. * $(document).ready( function () {
  6757. * $('#example').dataTable( {
  6758. * "fnCookieCallback": function (sName, oData, sExpires, sPath) {
  6759. * // Customise oData or sName or whatever else here
  6760. * return sName + "="+JSON.stringify(oData)+"; expires=" + sExpires +"; path=" + sPath;
  6761. * }
  6762. * } );
  6763. * } );
  6764. */
  6765. "fnCookieCallback":null,
  6766. /**
  6767. * This function is called when a TR element is created (and all TD child
  6768. * elements have been inserted), or registered if using a DOM source, allowing
  6769. * manipulation of the TR element (adding classes etc).
  6770. * @type function
  6771. * @param {node} nRow "TR" element for the current row
  6772. * @param {array} aData Raw data array for this row
  6773. * @param {int} iDataIndex The index of this row in aoData
  6774. * @dtopt Callbacks
  6775. *
  6776. * @example
  6777. * $(document).ready( function() {
  6778. * $('#example').dataTable( {
  6779. * "fnCreatedRow": function( nRow, aData, iDataIndex ) {
  6780. * // Bold the grade for all 'A' grade browsers
  6781. * if ( aData[4] == "A" )
  6782. * {
  6783. * $('td:eq(4)', nRow).html( '<b>A</b>' );
  6784. * }
  6785. * }
  6786. * } );
  6787. * } );
  6788. */
  6789. "fnCreatedRow":null,
  6790. /**
  6791. * This function is called on every 'draw' event, and allows you to
  6792. * dynamically modify any aspect you want about the created DOM.
  6793. * @type function
  6794. * @param {object} oSettings DataTables settings object
  6795. * @dtopt Callbacks
  6796. *
  6797. * @example
  6798. * $(document).ready( function() {
  6799. * $('#example').dataTable( {
  6800. * "fnDrawCallback": function( oSettings ) {
  6801. * alert( 'DataTables has redrawn the table' );
  6802. * }
  6803. * } );
  6804. * } );
  6805. */
  6806. "fnDrawCallback":null,
  6807. /**
  6808. * Identical to fnHeaderCallback() but for the table footer this function
  6809. * allows you to modify the table footer on every 'draw' even.
  6810. * @type function
  6811. * @param {node} nFoot "TR" element for the footer
  6812. * @param {array} aData Full table data (as derived from the original HTML)
  6813. * @param {int} iStart Index for the current display starting point in the
  6814. * display array
  6815. * @param {int} iEnd Index for the current display ending point in the
  6816. * display array
  6817. * @param {array int} aiDisplay Index array to translate the visual position
  6818. * to the full data array
  6819. * @dtopt Callbacks
  6820. *
  6821. * @example
  6822. * $(document).ready( function() {
  6823. * $('#example').dataTable( {
  6824. * "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) {
  6825. * nFoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+iStart;
  6826. * }
  6827. * } );
  6828. * } )
  6829. */
  6830. "fnFooterCallback":null,
  6831. /**
  6832. * When rendering large numbers in the information element for the table
  6833. * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
  6834. * to have a comma separator for the 'thousands' units (e.g. 1 million is
  6835. * rendered as "1,000,000") to help readability for the end user. This
  6836. * function will override the default method DataTables uses.
  6837. * @type function
  6838. * @member
  6839. * @param {int} iIn number to be formatted
  6840. * @returns {string} formatted string for DataTables to show the number
  6841. * @dtopt Callbacks
  6842. *
  6843. * @example
  6844. * $(document).ready( function() {
  6845. * $('#example').dataTable( {
  6846. * "fnFormatNumber": function ( iIn ) {
  6847. * if ( iIn &lt; 1000 ) {
  6848. * return iIn;
  6849. * } else {
  6850. * var
  6851. * s=(iIn+""),
  6852. * a=s.split(""), out="",
  6853. * iLen=s.length;
  6854. *
  6855. * for ( var i=0 ; i&lt;iLen ; i++ ) {
  6856. * if ( i%3 === 0 &amp;&amp; i !== 0 ) {
  6857. * out = "'"+out;
  6858. * }
  6859. * out = a[iLen-i-1]+out;
  6860. * }
  6861. * }
  6862. * return out;
  6863. * };
  6864. * } );
  6865. * } );
  6866. */
  6867. "fnFormatNumber":function (iIn) {
  6868. if (iIn < 1000) {
  6869. // A small optimisation for what is likely to be the majority of use cases
  6870. return iIn;
  6871. }
  6872. var s = (iIn + ""), a = s.split(""), out = "", iLen = s.length;
  6873. for (var i = 0; i < iLen; i++) {
  6874. if (i % 3 === 0 && i !== 0) {
  6875. out = this.oLanguage.sInfoThousands + out;
  6876. }
  6877. out = a[iLen - i - 1] + out;
  6878. }
  6879. return out;
  6880. },
  6881. /**
  6882. * This function is called on every 'draw' event, and allows you to
  6883. * dynamically modify the header row. This can be used to calculate and
  6884. * display useful information about the table.
  6885. * @type function
  6886. * @param {node} nHead "TR" element for the header
  6887. * @param {array} aData Full table data (as derived from the original HTML)
  6888. * @param {int} iStart Index for the current display starting point in the
  6889. * display array
  6890. * @param {int} iEnd Index for the current display ending point in the
  6891. * display array
  6892. * @param {array int} aiDisplay Index array to translate the visual position
  6893. * to the full data array
  6894. * @dtopt Callbacks
  6895. *
  6896. * @example
  6897. * $(document).ready( function() {
  6898. * $('#example').dataTable( {
  6899. * "fnHeaderCallback": function( nHead, aData, iStart, iEnd, aiDisplay ) {
  6900. * nHead.getElementsByTagName('th')[0].innerHTML = "Displaying "+(iEnd-iStart)+" records";
  6901. * }
  6902. * } );
  6903. * } )
  6904. */
  6905. "fnHeaderCallback":null,
  6906. /**
  6907. * The information element can be used to convey information about the current
  6908. * state of the table. Although the internationalisation options presented by
  6909. * DataTables are quite capable of dealing with most customisations, there may
  6910. * be times where you wish to customise the string further. This callback
  6911. * allows you to do exactly that.
  6912. * @type function
  6913. * @param {object} oSettings DataTables settings object
  6914. * @param {int} iStart Starting position in data for the draw
  6915. * @param {int} iEnd End position in data for the draw
  6916. * @param {int} iMax Total number of rows in the table (regardless of
  6917. * filtering)
  6918. * @param {int} iTotal Total number of rows in the data set, after filtering
  6919. * @param {string} sPre The string that DataTables has formatted using it's
  6920. * own rules
  6921. * @returns {string} The string to be displayed in the information element.
  6922. * @dtopt Callbacks
  6923. *
  6924. * @example
  6925. * $('#example').dataTable( {
  6926. * "fnInfoCallback": function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) {
  6927. * return iStart +" to "+ iEnd;
  6928. * }
  6929. * } );
  6930. */
  6931. "fnInfoCallback":null,
  6932. /**
  6933. * Called when the table has been initialised. Normally DataTables will
  6934. * initialise sequentially and there will be no need for this function,
  6935. * however, this does not hold true when using external language information
  6936. * since that is obtained using an async XHR call.
  6937. * @type function
  6938. * @param {object} oSettings DataTables settings object
  6939. * @param {object} json The JSON object request from the server - only
  6940. * present if client-side Ajax sourced data is used
  6941. * @dtopt Callbacks
  6942. *
  6943. * @example
  6944. * $(document).ready( function() {
  6945. * $('#example').dataTable( {
  6946. * "fnInitComplete": function(oSettings, json) {
  6947. * alert( 'DataTables has finished its initialisation.' );
  6948. * }
  6949. * } );
  6950. * } )
  6951. */
  6952. "fnInitComplete":null,
  6953. /**
  6954. * Called at the very start of each table draw and can be used to cancel the
  6955. * draw by returning false, any other return (including undefined) results in
  6956. * the full draw occurring).
  6957. * @type function
  6958. * @param {object} oSettings DataTables settings object
  6959. * @returns {boolean} False will cancel the draw, anything else (including no
  6960. * return) will allow it to complete.
  6961. * @dtopt Callbacks
  6962. *
  6963. * @example
  6964. * $(document).ready( function() {
  6965. * $('#example').dataTable( {
  6966. * "fnPreDrawCallback": function( oSettings ) {
  6967. * if ( $('#test').val() == 1 ) {
  6968. * return false;
  6969. * }
  6970. * }
  6971. * } );
  6972. * } );
  6973. */
  6974. "fnPreDrawCallback":null,
  6975. /**
  6976. * This function allows you to 'post process' each row after it have been
  6977. * generated for each table draw, but before it is rendered on screen. This
  6978. * function might be used for setting the row class name etc.
  6979. * @type function
  6980. * @param {node} nRow "TR" element for the current row
  6981. * @param {array} aData Raw data array for this row
  6982. * @param {int} iDisplayIndex The display index for the current table draw
  6983. * @param {int} iDisplayIndexFull The index of the data in the full list of
  6984. * rows (after filtering)
  6985. * @dtopt Callbacks
  6986. *
  6987. * @example
  6988. * $(document).ready( function() {
  6989. * $('#example').dataTable( {
  6990. * "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
  6991. * // Bold the grade for all 'A' grade browsers
  6992. * if ( aData[4] == "A" )
  6993. * {
  6994. * $('td:eq(4)', nRow).html( '<b>A</b>' );
  6995. * }
  6996. * }
  6997. * } );
  6998. * } );
  6999. */
  7000. "fnRowCallback":null,
  7001. /**
  7002. * This parameter allows you to override the default function which obtains
  7003. * the data from the server ($.getJSON) so something more suitable for your
  7004. * application. For example you could use POST data, or pull information from
  7005. * a Gears or AIR database.
  7006. * @type function
  7007. * @member
  7008. * @param {string} sSource HTTP source to obtain the data from (sAjaxSource)
  7009. * @param {array} aoData A key/value pair object containing the data to send
  7010. * to the server
  7011. * @param {function} fnCallback to be called on completion of the data get
  7012. * process that will draw the data on the page.
  7013. * @param {object} oSettings DataTables settings object
  7014. * @dtopt Callbacks
  7015. * @dtopt Server-side
  7016. *
  7017. * @example
  7018. * // POST data to server
  7019. * $(document).ready( function() {
  7020. * $('#example').dataTable( {
  7021. * "bProcessing": true,
  7022. * "bServerSide": true,
  7023. * "sAjaxSource": "xhr.php",
  7024. * "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) {
  7025. * oSettings.jqXHR = $.ajax( {
  7026. * "dataType": 'json',
  7027. * "type": "POST",
  7028. * "url": sSource,
  7029. * "data": aoData,
  7030. * "success": fnCallback
  7031. * } );
  7032. * }
  7033. * } );
  7034. * } );
  7035. */
  7036. "fnServerData":function (sUrl, aoData, fnCallback, oSettings) {
  7037. oSettings.jqXHR = $.ajax({
  7038. "url":sUrl,
  7039. "data":aoData,
  7040. "success":function (json) {
  7041. if (json.sError) {
  7042. oSettings.oApi._fnLog(oSettings, 0, json.sError);
  7043. }
  7044. $(oSettings.oInstance).trigger('xhr', [oSettings, json]);
  7045. fnCallback(json);
  7046. },
  7047. "dataType":"json",
  7048. "cache":false,
  7049. "type":oSettings.sServerMethod,
  7050. "error":function (xhr, error, thrown) {
  7051. if (error == "parsererror") {
  7052. oSettings.oApi._fnLog(oSettings, 0, "DataTables warning: JSON data from " +
  7053. "server could not be parsed. This is caused by a JSON formatting error.");
  7054. }
  7055. }
  7056. });
  7057. },
  7058. /**
  7059. * It is often useful to send extra data to the server when making an Ajax
  7060. * request - for example custom filtering information, and this callback
  7061. * function makes it trivial to send extra information to the server. The
  7062. * passed in parameter is the data set that has been constructed by
  7063. * DataTables, and you can add to this or modify it as you require.
  7064. * @type function
  7065. * @param {array} aoData Data array (array of objects which are name/value
  7066. * pairs) that has been constructed by DataTables and will be sent to the
  7067. * server. In the case of Ajax sourced data with server-side processing
  7068. * this will be an empty array, for server-side processing there will be a
  7069. * significant number of parameters!
  7070. * @returns {undefined} Ensure that you modify the aoData array passed in,
  7071. * as this is passed by reference.
  7072. * @dtopt Callbacks
  7073. * @dtopt Server-side
  7074. *
  7075. * @example
  7076. * $(document).ready( function() {
  7077. * $('#example').dataTable( {
  7078. * "bProcessing": true,
  7079. * "bServerSide": true,
  7080. * "sAjaxSource": "scripts/server_processing.php",
  7081. * "fnServerParams": function ( aoData ) {
  7082. * aoData.push( { "name": "more_data", "value": "my_value" } );
  7083. * }
  7084. * } );
  7085. * } );
  7086. */
  7087. "fnServerParams":null,
  7088. /**
  7089. * Load the table state. With this function you can define from where, and how, the
  7090. * state of a table is loaded. By default DataTables will load from its state saving
  7091. * cookie, but you might wish to use local storage (HTML5) or a server-side database.
  7092. * @type function
  7093. * @member
  7094. * @param {object} oSettings DataTables settings object
  7095. * @return {object} The DataTables state object to be loaded
  7096. * @dtopt Callbacks
  7097. *
  7098. * @example
  7099. * $(document).ready( function() {
  7100. * $('#example').dataTable( {
  7101. * "bStateSave": true,
  7102. * "fnStateLoad": function (oSettings) {
  7103. * var o;
  7104. *
  7105. * // Send an Ajax request to the server to get the data. Note that
  7106. * // this is a synchronous request.
  7107. * $.ajax( {
  7108. * "url": "/state_load",
  7109. * "async": false,
  7110. * "dataType": "json",
  7111. * "success": function (json) {
  7112. * o = json;
  7113. * }
  7114. * } );
  7115. *
  7116. * return o;
  7117. * }
  7118. * } );
  7119. * } );
  7120. */
  7121. "fnStateLoad":function (oSettings) {
  7122. var sData = this.oApi._fnReadCookie(oSettings.sCookiePrefix + oSettings.sInstance);
  7123. var oData;
  7124. try {
  7125. oData = (typeof $.parseJSON === 'function') ?
  7126. $.parseJSON(sData) : eval('(' + sData + ')');
  7127. } catch (e) {
  7128. oData = null;
  7129. }
  7130. return oData;
  7131. },
  7132. /**
  7133. * Callback which allows modification of the saved state prior to loading that state.
  7134. * This callback is called when the table is loading state from the stored data, but
  7135. * prior to the settings object being modified by the saved state. Note that for
  7136. * plug-in authors, you should use the 'stateLoadParams' event to load parameters for
  7137. * a plug-in.
  7138. * @type function
  7139. * @param {object} oSettings DataTables settings object
  7140. * @param {object} oData The state object that is to be loaded
  7141. * @dtopt Callbacks
  7142. *
  7143. * @example
  7144. * // Remove a saved filter, so filtering is never loaded
  7145. * $(document).ready( function() {
  7146. * $('#example').dataTable( {
  7147. * "bStateSave": true,
  7148. * "fnStateLoadParams": function (oSettings, oData) {
  7149. * oData.oSearch.sSearch = "";
  7150. * }
  7151. * } );
  7152. * } );
  7153. *
  7154. * @example
  7155. * // Disallow state loading by returning false
  7156. * $(document).ready( function() {
  7157. * $('#example').dataTable( {
  7158. * "bStateSave": true,
  7159. * "fnStateLoadParams": function (oSettings, oData) {
  7160. * return false;
  7161. * }
  7162. * } );
  7163. * } );
  7164. */
  7165. "fnStateLoadParams":null,
  7166. /**
  7167. * Callback that is called when the state has been loaded from the state saving method
  7168. * and the DataTables settings object has been modified as a result of the loaded state.
  7169. * @type function
  7170. * @param {object} oSettings DataTables settings object
  7171. * @param {object} oData The state object that was loaded
  7172. * @dtopt Callbacks
  7173. *
  7174. * @example
  7175. * // Show an alert with the filtering value that was saved
  7176. * $(document).ready( function() {
  7177. * $('#example').dataTable( {
  7178. * "bStateSave": true,
  7179. * "fnStateLoaded": function (oSettings, oData) {
  7180. * alert( 'Saved filter was: '+oData.oSearch.sSearch );
  7181. * }
  7182. * } );
  7183. * } );
  7184. */
  7185. "fnStateLoaded":null,
  7186. /**
  7187. * Save the table state. This function allows you to define where and how the state
  7188. * information for the table is stored - by default it will use a cookie, but you
  7189. * might want to use local storage (HTML5) or a server-side database.
  7190. * @type function
  7191. * @member
  7192. * @param {object} oSettings DataTables settings object
  7193. * @param {object} oData The state object to be saved
  7194. * @dtopt Callbacks
  7195. *
  7196. * @example
  7197. * $(document).ready( function() {
  7198. * $('#example').dataTable( {
  7199. * "bStateSave": true,
  7200. * "fnStateSave": function (oSettings, oData) {
  7201. * // Send an Ajax request to the server with the state object
  7202. * $.ajax( {
  7203. * "url": "/state_save",
  7204. * "data": oData,
  7205. * "dataType": "json",
  7206. * "method": "POST"
  7207. * "success": function () {}
  7208. * } );
  7209. * }
  7210. * } );
  7211. * } );
  7212. */
  7213. "fnStateSave":function (oSettings, oData) {
  7214. this.oApi._fnCreateCookie(
  7215. oSettings.sCookiePrefix + oSettings.sInstance,
  7216. this.oApi._fnJsonString(oData),
  7217. oSettings.iCookieDuration,
  7218. oSettings.sCookiePrefix,
  7219. oSettings.fnCookieCallback
  7220. );
  7221. },
  7222. /**
  7223. * Callback which allows modification of the state to be saved. Called when the table
  7224. * has changed state a new state save is required. This method allows modification of
  7225. * the state saving object prior to actually doing the save, including addition or
  7226. * other state properties or modification. Note that for plug-in authors, you should
  7227. * use the 'stateSaveParams' event to save parameters for a plug-in.
  7228. * @type function
  7229. * @param {object} oSettings DataTables settings object
  7230. * @param {object} oData The state object to be saved
  7231. * @dtopt Callbacks
  7232. *
  7233. * @example
  7234. * // Remove a saved filter, so filtering is never saved
  7235. * $(document).ready( function() {
  7236. * $('#example').dataTable( {
  7237. * "bStateSave": true,
  7238. * "fnStateSaveParams": function (oSettings, oData) {
  7239. * oData.oSearch.sSearch = "";
  7240. * }
  7241. * } );
  7242. * } );
  7243. */
  7244. "fnStateSaveParams":null,
  7245. /**
  7246. * Duration of the cookie which is used for storing session information. This
  7247. * value is given in seconds.
  7248. * @type int
  7249. * @default 7200 <i>(2 hours)</i>
  7250. * @dtopt Options
  7251. *
  7252. * @example
  7253. * $(document).ready( function() {
  7254. * $('#example').dataTable( {
  7255. * "iCookieDuration": 60*60*24; // 1 day
  7256. * } );
  7257. * } )
  7258. */
  7259. "iCookieDuration":7200,
  7260. /**
  7261. * When enabled DataTables will not make a request to the server for the first
  7262. * page draw - rather it will use the data already on the page (no sorting etc
  7263. * will be applied to it), thus saving on an XHR at load time. iDeferLoading
  7264. * is used to indicate that deferred loading is required, but it is also used
  7265. * to tell DataTables how many records there are in the full table (allowing
  7266. * the information element and pagination to be displayed correctly). In the case
  7267. * where a filtering is applied to the table on initial load, this can be
  7268. * indicated by giving the parameter as an array, where the first element is
  7269. * the number of records available after filtering and the second element is the
  7270. * number of records without filtering (allowing the table information element
  7271. * to be shown correctly).
  7272. * @type int | array
  7273. * @default null
  7274. * @dtopt Options
  7275. *
  7276. * @example
  7277. * // 57 records available in the table, no filtering applied
  7278. * $(document).ready( function() {
  7279. * $('#example').dataTable( {
  7280. * "bServerSide": true,
  7281. * "sAjaxSource": "scripts/server_processing.php",
  7282. * "iDeferLoading": 57
  7283. * } );
  7284. * } );
  7285. *
  7286. * @example
  7287. * // 57 records after filtering, 100 without filtering (an initial filter applied)
  7288. * $(document).ready( function() {
  7289. * $('#example').dataTable( {
  7290. * "bServerSide": true,
  7291. * "sAjaxSource": "scripts/server_processing.php",
  7292. * "iDeferLoading": [ 57, 100 ],
  7293. * "oSearch": {
  7294. * "sSearch": "my_filter"
  7295. * }
  7296. * } );
  7297. * } );
  7298. */
  7299. "iDeferLoading":null,
  7300. /**
  7301. * Number of rows to display on a single page when using pagination. If
  7302. * feature enabled (bLengthChange) then the end user will be able to override
  7303. * this to a custom setting using a pop-up menu.
  7304. * @type int
  7305. * @default 10
  7306. * @dtopt Options
  7307. *
  7308. * @example
  7309. * $(document).ready( function() {
  7310. * $('#example').dataTable( {
  7311. * "iDisplayLength": 50
  7312. * } );
  7313. * } )
  7314. */
  7315. "iDisplayLength":10,
  7316. /**
  7317. * Define the starting point for data display when using DataTables with
  7318. * pagination. Note that this parameter is the number of records, rather than
  7319. * the page number, so if you have 10 records per page and want to start on
  7320. * the third page, it should be "20".
  7321. * @type int
  7322. * @default 0
  7323. * @dtopt Options
  7324. *
  7325. * @example
  7326. * $(document).ready( function() {
  7327. * $('#example').dataTable( {
  7328. * "iDisplayStart": 20
  7329. * } );
  7330. * } )
  7331. */
  7332. "iDisplayStart":0,
  7333. /**
  7334. * The scroll gap is the amount of scrolling that is left to go before
  7335. * DataTables will load the next 'page' of data automatically. You typically
  7336. * want a gap which is big enough that the scrolling will be smooth for the
  7337. * user, while not so large that it will load more data than need.
  7338. * @type int
  7339. * @default 100
  7340. * @dtopt Options
  7341. *
  7342. * @example
  7343. * $(document).ready( function() {
  7344. * $('#example').dataTable( {
  7345. * "bScrollInfinite": true,
  7346. * "bScrollCollapse": true,
  7347. * "sScrollY": "200px",
  7348. * "iScrollLoadGap": 50
  7349. * } );
  7350. * } );
  7351. */
  7352. "iScrollLoadGap":100,
  7353. /**
  7354. * By default DataTables allows keyboard navigation of the table (sorting, paging,
  7355. * and filtering) by adding a tabindex attribute to the required elements. This
  7356. * allows you to tab through the controls and press the enter key to activate them.
  7357. * The tabindex is default 0, meaning that the tab follows the flow of the document.
  7358. * You can overrule this using this parameter if you wish. Use a value of -1 to
  7359. * disable built-in keyboard navigation.
  7360. * @type int
  7361. * @default 0
  7362. * @dtopt Options
  7363. *
  7364. * @example
  7365. * $(document).ready( function() {
  7366. * $('#example').dataTable( {
  7367. * "iTabIndex": 1
  7368. * } );
  7369. * } );
  7370. */
  7371. "iTabIndex":0,
  7372. /**
  7373. * All strings that DataTables uses in the user interface that it creates
  7374. * are defined in this object, allowing you to modified them individually or
  7375. * completely replace them all as required.
  7376. * @namespace
  7377. */
  7378. "oLanguage":{
  7379. /**
  7380. * Strings that are used for WAI-ARIA labels and controls only (these are not
  7381. * actually visible on the page, but will be read by screenreaders, and thus
  7382. * must be internationalised as well).
  7383. * @namespace
  7384. */
  7385. "oAria":{
  7386. /**
  7387. * ARIA label that is added to the table headers when the column may be
  7388. * sorted ascending by activing the column (click or return when focused).
  7389. * Note that the column header is prefixed to this string.
  7390. * @type string
  7391. * @default : activate to sort column ascending
  7392. * @dtopt Language
  7393. *
  7394. * @example
  7395. * $(document).ready( function() {
  7396. * $('#example').dataTable( {
  7397. * "oLanguage": {
  7398. * "oAria": {
  7399. * "sSortAscending": " - click/return to sort ascending"
  7400. * }
  7401. * }
  7402. * } );
  7403. * } );
  7404. */
  7405. "sSortAscending":": activate to sort column ascending",
  7406. /**
  7407. * ARIA label that is added to the table headers when the column may be
  7408. * sorted descending by activing the column (click or return when focused).
  7409. * Note that the column header is prefixed to this string.
  7410. * @type string
  7411. * @default : activate to sort column ascending
  7412. * @dtopt Language
  7413. *
  7414. * @example
  7415. * $(document).ready( function() {
  7416. * $('#example').dataTable( {
  7417. * "oLanguage": {
  7418. * "oAria": {
  7419. * "sSortDescending": " - click/return to sort descending"
  7420. * }
  7421. * }
  7422. * } );
  7423. * } );
  7424. */
  7425. "sSortDescending":": activate to sort column descending"
  7426. },
  7427. /**
  7428. * Pagination string used by DataTables for the two built-in pagination
  7429. * control types ("two_button" and "full_numbers")
  7430. * @namespace
  7431. */
  7432. "oPaginate":{
  7433. /**
  7434. * Text to use when using the 'full_numbers' type of pagination for the
  7435. * button to take the user to the first page.
  7436. * @type string
  7437. * @default First
  7438. * @dtopt Language
  7439. *
  7440. * @example
  7441. * $(document).ready( function() {
  7442. * $('#example').dataTable( {
  7443. * "oLanguage": {
  7444. * "oPaginate": {
  7445. * "sFirst": "First page"
  7446. * }
  7447. * }
  7448. * } );
  7449. * } );
  7450. */
  7451. "sFirst":"First",
  7452. /**
  7453. * Text to use when using the 'full_numbers' type of pagination for the
  7454. * button to take the user to the last page.
  7455. * @type string
  7456. * @default Last
  7457. * @dtopt Language
  7458. *
  7459. * @example
  7460. * $(document).ready( function() {
  7461. * $('#example').dataTable( {
  7462. * "oLanguage": {
  7463. * "oPaginate": {
  7464. * "sLast": "Last page"
  7465. * }
  7466. * }
  7467. * } );
  7468. * } );
  7469. */
  7470. "sLast":"Last",
  7471. /**
  7472. * Text to use for the 'next' pagination button (to take the user to the
  7473. * next page).
  7474. * @type string
  7475. * @default Next
  7476. * @dtopt Language
  7477. *
  7478. * @example
  7479. * $(document).ready( function() {
  7480. * $('#example').dataTable( {
  7481. * "oLanguage": {
  7482. * "oPaginate": {
  7483. * "sNext": "Next page"
  7484. * }
  7485. * }
  7486. * } );
  7487. * } );
  7488. */
  7489. "sNext":"Next",
  7490. /**
  7491. * Text to use for the 'previous' pagination button (to take the user to
  7492. * the previous page).
  7493. * @type string
  7494. * @default Previous
  7495. * @dtopt Language
  7496. *
  7497. * @example
  7498. * $(document).ready( function() {
  7499. * $('#example').dataTable( {
  7500. * "oLanguage": {
  7501. * "oPaginate": {
  7502. * "sPrevious": "Previous page"
  7503. * }
  7504. * }
  7505. * } );
  7506. * } );
  7507. */
  7508. "sPrevious":"Previous"
  7509. },
  7510. /**
  7511. * This string is shown in preference to sZeroRecords when the table is
  7512. * empty of data (regardless of filtering). Note that this is an optional
  7513. * parameter - if it is not given, the value of sZeroRecords will be used
  7514. * instead (either the default or given value).
  7515. * @type string
  7516. * @default No data available in table
  7517. * @dtopt Language
  7518. *
  7519. * @example
  7520. * $(document).ready( function() {
  7521. * $('#example').dataTable( {
  7522. * "oLanguage": {
  7523. * "sEmptyTable": "No data available in table"
  7524. * }
  7525. * } );
  7526. * } );
  7527. */
  7528. "sEmptyTable":"No data available in table",
  7529. /**
  7530. * This string gives information to the end user about the information that
  7531. * is current on display on the page. The _START_, _END_ and _TOTAL_
  7532. * variables are all dynamically replaced as the table display updates, and
  7533. * can be freely moved or removed as the language requirements change.
  7534. * @type string
  7535. * @default Showing _START_ to _END_ of _TOTAL_ entries
  7536. * @dtopt Language
  7537. *
  7538. * @example
  7539. * $(document).ready( function() {
  7540. * $('#example').dataTable( {
  7541. * "oLanguage": {
  7542. * "sInfo": "Got a total of _TOTAL_ entries to show (_START_ to _END_)"
  7543. * }
  7544. * } );
  7545. * } );
  7546. */
  7547. "sInfo":"Showing _START_ to _END_ of _TOTAL_ entries",
  7548. /**
  7549. * Display information string for when the table is empty. Typically the
  7550. * format of this string should match sInfo.
  7551. * @type string
  7552. * @default Showing 0 to 0 of 0 entries
  7553. * @dtopt Language
  7554. *
  7555. * @example
  7556. * $(document).ready( function() {
  7557. * $('#example').dataTable( {
  7558. * "oLanguage": {
  7559. * "sInfoEmpty": "No entries to show"
  7560. * }
  7561. * } );
  7562. * } );
  7563. */
  7564. "sInfoEmpty":"Showing 0 to 0 of 0 entries",
  7565. /**
  7566. * When a user filters the information in a table, this string is appended
  7567. * to the information (sInfo) to give an idea of how strong the filtering
  7568. * is. The variable _MAX_ is dynamically updated.
  7569. * @type string
  7570. * @default (filtered from _MAX_ total entries)
  7571. * @dtopt Language
  7572. *
  7573. * @example
  7574. * $(document).ready( function() {
  7575. * $('#example').dataTable( {
  7576. * "oLanguage": {
  7577. * "sInfoFiltered": " - filtering from _MAX_ records"
  7578. * }
  7579. * } );
  7580. * } );
  7581. */
  7582. "sInfoFiltered":"(filtered from _MAX_ total entries)",
  7583. /**
  7584. * If can be useful to append extra information to the info string at times,
  7585. * and this variable does exactly that. This information will be appended to
  7586. * the sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are
  7587. * being used) at all times.
  7588. * @type string
  7589. * @default <i>Empty string</i>
  7590. * @dtopt Language
  7591. *
  7592. * @example
  7593. * $(document).ready( function() {
  7594. * $('#example').dataTable( {
  7595. * "oLanguage": {
  7596. * "sInfoPostFix": "All records shown are derived from real information."
  7597. * }
  7598. * } );
  7599. * } );
  7600. */
  7601. "sInfoPostFix":"",
  7602. /**
  7603. * DataTables has a build in number formatter (fnFormatNumber) which is used
  7604. * to format large numbers that are used in the table information. By
  7605. * default a comma is used, but this can be trivially changed to any
  7606. * character you wish with this parameter.
  7607. * @type string
  7608. * @default ,
  7609. * @dtopt Language
  7610. *
  7611. * @example
  7612. * $(document).ready( function() {
  7613. * $('#example').dataTable( {
  7614. * "oLanguage": {
  7615. * "sInfoThousands": "'"
  7616. * }
  7617. * } );
  7618. * } );
  7619. */
  7620. "sInfoThousands":",",
  7621. /**
  7622. * Detail the action that will be taken when the drop down menu for the
  7623. * pagination length option is changed. The '_MENU_' variable is replaced
  7624. * with a default select list of 10, 25, 50 and 100, and can be replaced
  7625. * with a custom select box if required.
  7626. * @type string
  7627. * @default Show _MENU_ entries
  7628. * @dtopt Language
  7629. *
  7630. * @example
  7631. * // Language change only
  7632. * $(document).ready( function() {
  7633. * $('#example').dataTable( {
  7634. * "oLanguage": {
  7635. * "sLengthMenu": "Display _MENU_ records"
  7636. * }
  7637. * } );
  7638. * } );
  7639. *
  7640. * @example
  7641. * // Language and options change
  7642. * $(document).ready( function() {
  7643. * $('#example').dataTable( {
  7644. * "oLanguage": {
  7645. * "sLengthMenu": 'Display <select>'+
  7646. * '<option value="10">10</option>'+
  7647. * '<option value="20">20</option>'+
  7648. * '<option value="30">30</option>'+
  7649. * '<option value="40">40</option>'+
  7650. * '<option value="50">50</option>'+
  7651. * '<option value="-1">All</option>'+
  7652. * '</select> records'
  7653. * }
  7654. * } );
  7655. * } );
  7656. */
  7657. "sLengthMenu":"Show _MENU_ entries",
  7658. /**
  7659. * When using Ajax sourced data and during the first draw when DataTables is
  7660. * gathering the data, this message is shown in an empty row in the table to
  7661. * indicate to the end user the the data is being loaded. Note that this
  7662. * parameter is not used when loading data by server-side processing, just
  7663. * Ajax sourced data with client-side processing.
  7664. * @type string
  7665. * @default Loading...
  7666. * @dtopt Language
  7667. *
  7668. * @example
  7669. * $(document).ready( function() {
  7670. * $('#example').dataTable( {
  7671. * "oLanguage": {
  7672. * "sLoadingRecords": "Please wait - loading..."
  7673. * }
  7674. * } );
  7675. * } );
  7676. */
  7677. "sLoadingRecords":"Loading...",
  7678. /**
  7679. * Text which is displayed when the table is processing a user action
  7680. * (usually a sort command or similar).
  7681. * @type string
  7682. * @default Processing...
  7683. * @dtopt Language
  7684. *
  7685. * @example
  7686. * $(document).ready( function() {
  7687. * $('#example').dataTable( {
  7688. * "oLanguage": {
  7689. * "sProcessing": "DataTables is currently busy"
  7690. * }
  7691. * } );
  7692. * } );
  7693. */
  7694. "sProcessing":"Processing...",
  7695. /**
  7696. * Details the actions that will be taken when the user types into the
  7697. * filtering input text box. The variable "_INPUT_", if used in the string,
  7698. * is replaced with the HTML text box for the filtering input allowing
  7699. * control over where it appears in the string. If "_INPUT_" is not given
  7700. * then the input box is appended to the string automatically.
  7701. * @type string
  7702. * @default Search:
  7703. * @dtopt Language
  7704. *
  7705. * @example
  7706. * // Input text box will be appended at the end automatically
  7707. * $(document).ready( function() {
  7708. * $('#example').dataTable( {
  7709. * "oLanguage": {
  7710. * "sSearch": "Filter records:"
  7711. * }
  7712. * } );
  7713. * } );
  7714. *
  7715. * @example
  7716. * // Specify where the filter should appear
  7717. * $(document).ready( function() {
  7718. * $('#example').dataTable( {
  7719. * "oLanguage": {
  7720. * "sSearch": "Apply filter _INPUT_ to table"
  7721. * }
  7722. * } );
  7723. * } );
  7724. */
  7725. "sSearch":"Search:",
  7726. /**
  7727. * All of the language information can be stored in a file on the
  7728. * server-side, which DataTables will look up if this parameter is passed.
  7729. * It must store the URL of the language file, which is in a JSON format,
  7730. * and the object has the same properties as the oLanguage object in the
  7731. * initialiser object (i.e. the above parameters). Please refer to one of
  7732. * the example language files to see how this works in action.
  7733. * @type string
  7734. * @default <i>Empty string - i.e. disabled</i>
  7735. * @dtopt Language
  7736. *
  7737. * @example
  7738. * $(document).ready( function() {
  7739. * $('#example').dataTable( {
  7740. * "oLanguage": {
  7741. * "sUrl": "http://www.sprymedia.co.uk/dataTables/lang.txt"
  7742. * }
  7743. * } );
  7744. * } );
  7745. */
  7746. "sUrl":"",
  7747. /**
  7748. * Text shown inside the table records when the is no information to be
  7749. * displayed after filtering. sEmptyTable is shown when there is simply no
  7750. * information in the table at all (regardless of filtering).
  7751. * @type string
  7752. * @default No matching records found
  7753. * @dtopt Language
  7754. *
  7755. * @example
  7756. * $(document).ready( function() {
  7757. * $('#example').dataTable( {
  7758. * "oLanguage": {
  7759. * "sZeroRecords": "No records to display"
  7760. * }
  7761. * } );
  7762. * } );
  7763. */
  7764. "sZeroRecords":"No matching records found"
  7765. },
  7766. /**
  7767. * This parameter allows you to have define the global filtering state at
  7768. * initialisation time. As an object the "sSearch" parameter must be
  7769. * defined, but all other parameters are optional. When "bRegex" is true,
  7770. * the search string will be treated as a regular expression, when false
  7771. * (default) it will be treated as a straight string. When "bSmart"
  7772. * DataTables will use it's smart filtering methods (to word match at
  7773. * any point in the data), when false this will not be done.
  7774. * @namespace
  7775. * @extends DataTable.models.oSearch
  7776. * @dtopt Options
  7777. *
  7778. * @example
  7779. * $(document).ready( function() {
  7780. * $('#example').dataTable( {
  7781. * "oSearch": {"sSearch": "Initial search"}
  7782. * } );
  7783. * } )
  7784. */
  7785. "oSearch":$.extend({}, DataTable.models.oSearch),
  7786. /**
  7787. * By default DataTables will look for the property 'aaData' when obtaining
  7788. * data from an Ajax source or for server-side processing - this parameter
  7789. * allows that property to be changed. You can use Javascript dotted object
  7790. * notation to get a data source for multiple levels of nesting.
  7791. * @type string
  7792. * @default aaData
  7793. * @dtopt Options
  7794. * @dtopt Server-side
  7795. *
  7796. * @example
  7797. * // Get data from { "data": [...] }
  7798. * $(document).ready( function() {
  7799. * var oTable = $('#example').dataTable( {
  7800. * "sAjaxSource": "sources/data.txt",
  7801. * "sAjaxDataProp": "data"
  7802. * } );
  7803. * } );
  7804. *
  7805. * @example
  7806. * // Get data from { "data": { "inner": [...] } }
  7807. * $(document).ready( function() {
  7808. * var oTable = $('#example').dataTable( {
  7809. * "sAjaxSource": "sources/data.txt",
  7810. * "sAjaxDataProp": "data.inner"
  7811. * } );
  7812. * } );
  7813. */
  7814. "sAjaxDataProp":"aaData",
  7815. /**
  7816. * You can instruct DataTables to load data from an external source using this
  7817. * parameter (use aData if you want to pass data in you already have). Simply
  7818. * provide a url a JSON object can be obtained from. This object must include
  7819. * the parameter 'aaData' which is the data source for the table.
  7820. * @type string
  7821. * @default null
  7822. * @dtopt Options
  7823. * @dtopt Server-side
  7824. *
  7825. * @example
  7826. * $(document).ready( function() {
  7827. * $('#example').dataTable( {
  7828. * "sAjaxSource": "http://www.sprymedia.co.uk/dataTables/json.php"
  7829. * } );
  7830. * } )
  7831. */
  7832. "sAjaxSource":null,
  7833. /**
  7834. * This parameter can be used to override the default prefix that DataTables
  7835. * assigns to a cookie when state saving is enabled.
  7836. * @type string
  7837. * @default SpryMedia_DataTables_
  7838. * @dtopt Options
  7839. *
  7840. * @example
  7841. * $(document).ready( function() {
  7842. * $('#example').dataTable( {
  7843. * "sCookiePrefix": "my_datatable_",
  7844. * } );
  7845. * } );
  7846. */
  7847. "sCookiePrefix":"SpryMedia_DataTables_",
  7848. /**
  7849. * This initialisation variable allows you to specify exactly where in the
  7850. * DOM you want DataTables to inject the various controls it adds to the page
  7851. * (for example you might want the pagination controls at the top of the
  7852. * table). DIV elements (with or without a custom class) can also be added to
  7853. * aid styling. The follow syntax is used:
  7854. * <ul>
  7855. * <li>The following options are allowed:
  7856. * <ul>
  7857. * <li>'l' - Length changing</li
  7858. * <li>'f' - Filtering input</li>
  7859. * <li>'t' - The table!</li>
  7860. * <li>'i' - Information</li>
  7861. * <li>'p' - Pagination</li>
  7862. * <li>'r' - pRocessing</li>
  7863. * </ul>
  7864. * </li>
  7865. * <li>The following constants are allowed:
  7866. * <ul>
  7867. * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
  7868. * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
  7869. * </ul>
  7870. * </li>
  7871. * <li>The following syntax is expected:
  7872. * <ul>
  7873. * <li>'&lt;' and '&gt;' - div elements</li>
  7874. * <li>'&lt;"class" and '&gt;' - div with a class</li>
  7875. * <li>'&lt;"#id" and '&gt;' - div with an ID</li>
  7876. * </ul>
  7877. * </li>
  7878. * <li>Examples:
  7879. * <ul>
  7880. * <li>'&lt;"wrapper"flipt&gt;'</li>
  7881. * <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
  7882. * </ul>
  7883. * </li>
  7884. * </ul>
  7885. * @type string
  7886. * @default lfrtip <i>(when bJQueryUI is false)</i> <b>or</b>
  7887. * <"H"lfr>t<"F"ip> <i>(when bJQueryUI is true)</i>
  7888. * @dtopt Options
  7889. *
  7890. * @example
  7891. * $(document).ready( function() {
  7892. * $('#example').dataTable( {
  7893. * "sDom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
  7894. * } );
  7895. * } );
  7896. */
  7897. "sDom":"lfrtip",
  7898. /**
  7899. * DataTables features two different built-in pagination interaction methods
  7900. * ('two_button' or 'full_numbers') which present different page controls to
  7901. * the end user. Further methods can be added using the API (see below).
  7902. * @type string
  7903. * @default two_button
  7904. * @dtopt Options
  7905. *
  7906. * @example
  7907. * $(document).ready( function() {
  7908. * $('#example').dataTable( {
  7909. * "sPaginationType": "full_numbers"
  7910. * } );
  7911. * } )
  7912. */
  7913. "sPaginationType":"two_button",
  7914. /**
  7915. * Enable horizontal scrolling. When a table is too wide to fit into a certain
  7916. * layout, or you have a large number of columns in the table, you can enable
  7917. * x-scrolling to show the table in a viewport, which can be scrolled. This
  7918. * property can be any CSS unit, or a number (in which case it will be treated
  7919. * as a pixel measurement).
  7920. * @type string
  7921. * @default <i>blank string - i.e. disabled</i>
  7922. * @dtopt Features
  7923. *
  7924. * @example
  7925. * $(document).ready( function() {
  7926. * $('#example').dataTable( {
  7927. * "sScrollX": "100%",
  7928. * "bScrollCollapse": true
  7929. * } );
  7930. * } );
  7931. */
  7932. "sScrollX":"",
  7933. /**
  7934. * This property can be used to force a DataTable to use more width than it
  7935. * might otherwise do when x-scrolling is enabled. For example if you have a
  7936. * table which requires to be well spaced, this parameter is useful for
  7937. * "over-sizing" the table, and thus forcing scrolling. This property can by
  7938. * any CSS unit, or a number (in which case it will be treated as a pixel
  7939. * measurement).
  7940. * @type string
  7941. * @default <i>blank string - i.e. disabled</i>
  7942. * @dtopt Options
  7943. *
  7944. * @example
  7945. * $(document).ready( function() {
  7946. * $('#example').dataTable( {
  7947. * "sScrollX": "100%",
  7948. * "sScrollXInner": "110%"
  7949. * } );
  7950. * } );
  7951. */
  7952. "sScrollXInner":"",
  7953. /**
  7954. * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
  7955. * to the given height, and enable scrolling for any data which overflows the
  7956. * current viewport. This can be used as an alternative to paging to display
  7957. * a lot of data in a small area (although paging and scrolling can both be
  7958. * enabled at the same time). This property can be any CSS unit, or a number
  7959. * (in which case it will be treated as a pixel measurement).
  7960. * @type string
  7961. * @default <i>blank string - i.e. disabled</i>
  7962. * @dtopt Features
  7963. *
  7964. * @example
  7965. * $(document).ready( function() {
  7966. * $('#example').dataTable( {
  7967. * "sScrollY": "200px",
  7968. * "bPaginate": false
  7969. * } );
  7970. * } );
  7971. */
  7972. "sScrollY":"",
  7973. /**
  7974. * Set the HTTP method that is used to make the Ajax call for server-side
  7975. * processing or Ajax sourced data.
  7976. * @type string
  7977. * @default GET
  7978. * @dtopt Options
  7979. * @dtopt Server-side
  7980. *
  7981. * @example
  7982. * $(document).ready( function() {
  7983. * $('#example').dataTable( {
  7984. * "bServerSide": true,
  7985. * "sAjaxSource": "scripts/post.php",
  7986. * "sServerMethod": "POST"
  7987. * } );
  7988. * } );
  7989. */
  7990. "sServerMethod":"GET"
  7991. };
  7992. /**
  7993. * Column options that can be given to DataTables at initialisation time.
  7994. * @namespace
  7995. */
  7996. DataTable.defaults.columns = {
  7997. /**
  7998. * Allows a column's sorting to take multiple columns into account when
  7999. * doing a sort. For example first name / last name columns make sense to
  8000. * do a multi-column sort over the two columns.
  8001. * @type array
  8002. * @default null <i>Takes the value of the column index automatically</i>
  8003. * @dtopt Columns
  8004. *
  8005. * @example
  8006. * // Using aoColumnDefs
  8007. * $(document).ready( function() {
  8008. * $('#example').dataTable( {
  8009. * "aoColumnDefs": [
  8010. * { "aDataSort": [ 0, 1 ], "aTargets": [ 0 ] },
  8011. * { "aDataSort": [ 1, 0 ], "aTargets": [ 1 ] },
  8012. * { "aDataSort": [ 2, 3, 4 ], "aTargets": [ 2 ] }
  8013. * ]
  8014. * } );
  8015. * } );
  8016. *
  8017. * @example
  8018. * // Using aoColumns
  8019. * $(document).ready( function() {
  8020. * $('#example').dataTable( {
  8021. * "aoColumns": [
  8022. * { "aDataSort": [ 0, 1 ] },
  8023. * { "aDataSort": [ 1, 0 ] },
  8024. * { "aDataSort": [ 2, 3, 4 ] },
  8025. * null,
  8026. * null
  8027. * ]
  8028. * } );
  8029. * } );
  8030. */
  8031. "aDataSort":null,
  8032. /**
  8033. * You can control the default sorting direction, and even alter the behaviour
  8034. * of the sort handler (i.e. only allow ascending sorting etc) using this
  8035. * parameter.
  8036. * @type array
  8037. * @default [ 'asc', 'desc' ]
  8038. * @dtopt Columns
  8039. *
  8040. * @example
  8041. * // Using aoColumnDefs
  8042. * $(document).ready( function() {
  8043. * $('#example').dataTable( {
  8044. * "aoColumnDefs": [
  8045. * { "asSorting": [ "asc" ], "aTargets": [ 1 ] },
  8046. * { "asSorting": [ "desc", "asc", "asc" ], "aTargets": [ 2 ] },
  8047. * { "asSorting": [ "desc" ], "aTargets": [ 3 ] }
  8048. * ]
  8049. * } );
  8050. * } );
  8051. *
  8052. * @example
  8053. * // Using aoColumns
  8054. * $(document).ready( function() {
  8055. * $('#example').dataTable( {
  8056. * "aoColumns": [
  8057. * null,
  8058. * { "asSorting": [ "asc" ] },
  8059. * { "asSorting": [ "desc", "asc", "asc" ] },
  8060. * { "asSorting": [ "desc" ] },
  8061. * null
  8062. * ]
  8063. * } );
  8064. * } );
  8065. */
  8066. "asSorting":[ 'asc', 'desc' ],
  8067. /**
  8068. * Enable or disable filtering on the data in this column.
  8069. * @type boolean
  8070. * @default true
  8071. * @dtopt Columns
  8072. *
  8073. * @example
  8074. * // Using aoColumnDefs
  8075. * $(document).ready( function() {
  8076. * $('#example').dataTable( {
  8077. * "aoColumnDefs": [
  8078. * { "bSearchable": false, "aTargets": [ 0 ] }
  8079. * ] } );
  8080. * } );
  8081. *
  8082. * @example
  8083. * // Using aoColumns
  8084. * $(document).ready( function() {
  8085. * $('#example').dataTable( {
  8086. * "aoColumns": [
  8087. * { "bSearchable": false },
  8088. * null,
  8089. * null,
  8090. * null,
  8091. * null
  8092. * ] } );
  8093. * } );
  8094. */
  8095. "bSearchable":true,
  8096. /**
  8097. * Enable or disable sorting on this column.
  8098. * @type boolean
  8099. * @default true
  8100. * @dtopt Columns
  8101. *
  8102. * @example
  8103. * // Using aoColumnDefs
  8104. * $(document).ready( function() {
  8105. * $('#example').dataTable( {
  8106. * "aoColumnDefs": [
  8107. * { "bSortable": false, "aTargets": [ 0 ] }
  8108. * ] } );
  8109. * } );
  8110. *
  8111. * @example
  8112. * // Using aoColumns
  8113. * $(document).ready( function() {
  8114. * $('#example').dataTable( {
  8115. * "aoColumns": [
  8116. * { "bSortable": false },
  8117. * null,
  8118. * null,
  8119. * null,
  8120. * null
  8121. * ] } );
  8122. * } );
  8123. */
  8124. "bSortable":true,
  8125. /**
  8126. * <code>Deprecated</code> When using fnRender() for a column, you may wish
  8127. * to use the original data (before rendering) for sorting and filtering
  8128. * (the default is to used the rendered data that the user can see). This
  8129. * may be useful for dates etc.
  8130. *
  8131. * Please note that this option has now been deprecated and will be removed
  8132. * in the next version of DataTables. Please use mRender / mData rather than
  8133. * fnRender.
  8134. * @type boolean
  8135. * @default true
  8136. * @dtopt Columns
  8137. * @deprecated
  8138. */
  8139. "bUseRendered":true,
  8140. /**
  8141. * Enable or disable the display of this column.
  8142. * @type boolean
  8143. * @default true
  8144. * @dtopt Columns
  8145. *
  8146. * @example
  8147. * // Using aoColumnDefs
  8148. * $(document).ready( function() {
  8149. * $('#example').dataTable( {
  8150. * "aoColumnDefs": [
  8151. * { "bVisible": false, "aTargets": [ 0 ] }
  8152. * ] } );
  8153. * } );
  8154. *
  8155. * @example
  8156. * // Using aoColumns
  8157. * $(document).ready( function() {
  8158. * $('#example').dataTable( {
  8159. * "aoColumns": [
  8160. * { "bVisible": false },
  8161. * null,
  8162. * null,
  8163. * null,
  8164. * null
  8165. * ] } );
  8166. * } );
  8167. */
  8168. "bVisible":true,
  8169. /**
  8170. * Developer definable function that is called whenever a cell is created (Ajax source,
  8171. * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  8172. * allowing you to modify the DOM element (add background colour for example) when the
  8173. * element is available.
  8174. * @type function
  8175. * @param {element} nTd The TD node that has been created
  8176. * @param {*} sData The Data for the cell
  8177. * @param {array|object} oData The data for the whole row
  8178. * @param {int} iRow The row index for the aoData data store
  8179. * @param {int} iCol The column index for aoColumns
  8180. * @dtopt Columns
  8181. *
  8182. * @example
  8183. * $(document).ready( function() {
  8184. * $('#example').dataTable( {
  8185. * "aoColumnDefs": [ {
  8186. * "aTargets": [3],
  8187. * "fnCreatedCell": function (nTd, sData, oData, iRow, iCol) {
  8188. * if ( sData == "1.7" ) {
  8189. * $(nTd).css('color', 'blue')
  8190. * }
  8191. * }
  8192. * } ]
  8193. * });
  8194. * } );
  8195. */
  8196. "fnCreatedCell":null,
  8197. /**
  8198. * <code>Deprecated</code> Custom display function that will be called for the
  8199. * display of each cell in this column.
  8200. *
  8201. * Please note that this option has now been deprecated and will be removed
  8202. * in the next version of DataTables. Please use mRender / mData rather than
  8203. * fnRender.
  8204. * @type function
  8205. * @param {object} o Object with the following parameters:
  8206. * @param {int} o.iDataRow The row in aoData
  8207. * @param {int} o.iDataColumn The column in question
  8208. * @param {array} o.aData The data for the row in question
  8209. * @param {object} o.oSettings The settings object for this DataTables instance
  8210. * @param {object} o.mDataProp The data property used for this column
  8211. * @param {*} val The current cell value
  8212. * @returns {string} The string you which to use in the display
  8213. * @dtopt Columns
  8214. * @deprecated
  8215. */
  8216. "fnRender":null,
  8217. /**
  8218. * The column index (starting from 0!) that you wish a sort to be performed
  8219. * upon when this column is selected for sorting. This can be used for sorting
  8220. * on hidden columns for example.
  8221. * @type int
  8222. * @default -1 <i>Use automatically calculated column index</i>
  8223. * @dtopt Columns
  8224. *
  8225. * @example
  8226. * // Using aoColumnDefs
  8227. * $(document).ready( function() {
  8228. * $('#example').dataTable( {
  8229. * "aoColumnDefs": [
  8230. * { "iDataSort": 1, "aTargets": [ 0 ] }
  8231. * ]
  8232. * } );
  8233. * } );
  8234. *
  8235. * @example
  8236. * // Using aoColumns
  8237. * $(document).ready( function() {
  8238. * $('#example').dataTable( {
  8239. * "aoColumns": [
  8240. * { "iDataSort": 1 },
  8241. * null,
  8242. * null,
  8243. * null,
  8244. * null
  8245. * ]
  8246. * } );
  8247. * } );
  8248. */
  8249. "iDataSort":-1,
  8250. /**
  8251. * This parameter has been replaced by mData in DataTables to ensure naming
  8252. * consistency. mDataProp can still be used, as there is backwards compatibility
  8253. * in DataTables for this option, but it is strongly recommended that you use
  8254. * mData in preference to mDataProp.
  8255. * @name DataTable.defaults.columns.mDataProp
  8256. */
  8257. /**
  8258. * This property can be used to read data from any JSON data source property,
  8259. * including deeply nested objects / properties. mData can be given in a
  8260. * number of different ways which effect its behaviour:
  8261. * <ul>
  8262. * <li>integer - treated as an array index for the data source. This is the
  8263. * default that DataTables uses (incrementally increased for each column).</li>
  8264. * <li>string - read an object property from the data source. Note that you can
  8265. * use Javascript dotted notation to read deep properties / arrays from the
  8266. * data source.</li>
  8267. * <li>null - the sDefaultContent option will be used for the cell (null
  8268. * by default, so you will need to specify the default content you want -
  8269. * typically an empty string). This can be useful on generated columns such
  8270. * as edit / delete action columns.</li>
  8271. * <li>function - the function given will be executed whenever DataTables
  8272. * needs to set or get the data for a cell in the column. The function
  8273. * takes three parameters:
  8274. * <ul>
  8275. * <li>{array|object} The data source for the row</li>
  8276. * <li>{string} The type call data requested - this will be 'set' when
  8277. * setting data or 'filter', 'display', 'type', 'sort' or undefined when
  8278. * gathering data. Note that when <i>undefined</i> is given for the type
  8279. * DataTables expects to get the raw data for the object back</li>
  8280. * <li>{*} Data to set when the second parameter is 'set'.</li>
  8281. * </ul>
  8282. * The return value from the function is not required when 'set' is the type
  8283. * of call, but otherwise the return is what will be used for the data
  8284. * requested.</li>
  8285. * </ul>
  8286. *
  8287. * Note that prior to DataTables 1.9.2 mData was called mDataProp. The name change
  8288. * reflects the flexibility of this property and is consistent with the naming of
  8289. * mRender. If 'mDataProp' is given, then it will still be used by DataTables, as
  8290. * it automatically maps the old name to the new if required.
  8291. * @type string|int|function|null
  8292. * @default null <i>Use automatically calculated column index</i>
  8293. * @dtopt Columns
  8294. *
  8295. * @example
  8296. * // Read table data from objects
  8297. * $(document).ready( function() {
  8298. * var oTable = $('#example').dataTable( {
  8299. * "sAjaxSource": "sources/deep.txt",
  8300. * "aoColumns": [
  8301. * { "mData": "engine" },
  8302. * { "mData": "browser" },
  8303. * { "mData": "platform.inner" },
  8304. * { "mData": "platform.details.0" },
  8305. * { "mData": "platform.details.1" }
  8306. * ]
  8307. * } );
  8308. * } );
  8309. *
  8310. * @example
  8311. * // Using mData as a function to provide different information for
  8312. * // sorting, filtering and display. In this case, currency (price)
  8313. * $(document).ready( function() {
  8314. * var oTable = $('#example').dataTable( {
  8315. * "aoColumnDefs": [ {
  8316. * "aTargets": [ 0 ],
  8317. * "mData": function ( source, type, val ) {
  8318. * if (type === 'set') {
  8319. * source.price = val;
  8320. * // Store the computed dislay and filter values for efficiency
  8321. * source.price_display = val=="" ? "" : "$"+numberFormat(val);
  8322. * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
  8323. * return;
  8324. * }
  8325. * else if (type === 'display') {
  8326. * return source.price_display;
  8327. * }
  8328. * else if (type === 'filter') {
  8329. * return source.price_filter;
  8330. * }
  8331. * // 'sort', 'type' and undefined all just use the integer
  8332. * return source.price;
  8333. * }
  8334. * } ]
  8335. * } );
  8336. * } );
  8337. */
  8338. "mData":null,
  8339. /**
  8340. * This property is the rendering partner to mData and it is suggested that
  8341. * when you want to manipulate data for display (including filtering, sorting etc)
  8342. * but not altering the underlying data for the table, use this property. mData
  8343. * can actually do everything this property can and more, but this parameter is
  8344. * easier to use since there is no 'set' option. Like mData is can be given
  8345. * in a number of different ways to effect its behaviour, with the addition of
  8346. * supporting array syntax for easy outputting of arrays (including arrays of
  8347. * objects):
  8348. * <ul>
  8349. * <li>integer - treated as an array index for the data source. This is the
  8350. * default that DataTables uses (incrementally increased for each column).</li>
  8351. * <li>string - read an object property from the data source. Note that you can
  8352. * use Javascript dotted notation to read deep properties / arrays from the
  8353. * data source and also array brackets to indicate that the data reader should
  8354. * loop over the data source array. When characters are given between the array
  8355. * brackets, these characters are used to join the data source array together.
  8356. * For example: "accounts[, ].name" would result in a comma separated list with
  8357. * the 'name' value from the 'accounts' array of objects.</li>
  8358. * <li>function - the function given will be executed whenever DataTables
  8359. * needs to set or get the data for a cell in the column. The function
  8360. * takes three parameters:
  8361. * <ul>
  8362. * <li>{array|object} The data source for the row (based on mData)</li>
  8363. * <li>{string} The type call data requested - this will be 'filter', 'display',
  8364. * 'type' or 'sort'.</li>
  8365. * <li>{array|object} The full data source for the row (not based on mData)</li>
  8366. * </ul>
  8367. * The return value from the function is what will be used for the data
  8368. * requested.</li>
  8369. * </ul>
  8370. * @type string|int|function|null
  8371. * @default null <i>Use mData</i>
  8372. * @dtopt Columns
  8373. *
  8374. * @example
  8375. * // Create a comma separated list from an array of objects
  8376. * $(document).ready( function() {
  8377. * var oTable = $('#example').dataTable( {
  8378. * "sAjaxSource": "sources/deep.txt",
  8379. * "aoColumns": [
  8380. * { "mData": "engine" },
  8381. * { "mData": "browser" },
  8382. * {
  8383. * "mData": "platform",
  8384. * "mRender": "[, ].name"
  8385. * }
  8386. * ]
  8387. * } );
  8388. * } );
  8389. *
  8390. * @example
  8391. * // Use as a function to create a link from the data source
  8392. * $(document).ready( function() {
  8393. * var oTable = $('#example').dataTable( {
  8394. * "aoColumnDefs": [
  8395. * {
  8396. * "aTargets": [ 0 ],
  8397. * "mData": "download_link",
  8398. * "mRender": function ( data, type, full ) {
  8399. * return '<a href="'+data+'">Download</a>';
  8400. * }
  8401. * ]
  8402. * } );
  8403. * } );
  8404. */
  8405. "mRender":null,
  8406. /**
  8407. * Change the cell type created for the column - either TD cells or TH cells. This
  8408. * can be useful as TH cells have semantic meaning in the table body, allowing them
  8409. * to act as a header for a row (you may wish to add scope='row' to the TH elements).
  8410. * @type string
  8411. * @default td
  8412. * @dtopt Columns
  8413. *
  8414. * @example
  8415. * // Make the first column use TH cells
  8416. * $(document).ready( function() {
  8417. * var oTable = $('#example').dataTable( {
  8418. * "aoColumnDefs": [ {
  8419. * "aTargets": [ 0 ],
  8420. * "sCellType": "th"
  8421. * } ]
  8422. * } );
  8423. * } );
  8424. */
  8425. "sCellType":"td",
  8426. /**
  8427. * Class to give to each cell in this column.
  8428. * @type string
  8429. * @default <i>Empty string</i>
  8430. * @dtopt Columns
  8431. *
  8432. * @example
  8433. * // Using aoColumnDefs
  8434. * $(document).ready( function() {
  8435. * $('#example').dataTable( {
  8436. * "aoColumnDefs": [
  8437. * { "sClass": "my_class", "aTargets": [ 0 ] }
  8438. * ]
  8439. * } );
  8440. * } );
  8441. *
  8442. * @example
  8443. * // Using aoColumns
  8444. * $(document).ready( function() {
  8445. * $('#example').dataTable( {
  8446. * "aoColumns": [
  8447. * { "sClass": "my_class" },
  8448. * null,
  8449. * null,
  8450. * null,
  8451. * null
  8452. * ]
  8453. * } );
  8454. * } );
  8455. */
  8456. "sClass":"",
  8457. /**
  8458. * When DataTables calculates the column widths to assign to each column,
  8459. * it finds the longest string in each column and then constructs a
  8460. * temporary table and reads the widths from that. The problem with this
  8461. * is that "mmm" is much wider then "iiii", but the latter is a longer
  8462. * string - thus the calculation can go wrong (doing it properly and putting
  8463. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  8464. * a "work around" we provide this option. It will append its value to the
  8465. * text that is found to be the longest string for the column - i.e. padding.
  8466. * Generally you shouldn't need this, and it is not documented on the
  8467. * general DataTables.net documentation
  8468. * @type string
  8469. * @default <i>Empty string<i>
  8470. * @dtopt Columns
  8471. *
  8472. * @example
  8473. * // Using aoColumns
  8474. * $(document).ready( function() {
  8475. * $('#example').dataTable( {
  8476. * "aoColumns": [
  8477. * null,
  8478. * null,
  8479. * null,
  8480. * {
  8481. * "sContentPadding": "mmm"
  8482. * }
  8483. * ]
  8484. * } );
  8485. * } );
  8486. */
  8487. "sContentPadding":"",
  8488. /**
  8489. * Allows a default value to be given for a column's data, and will be used
  8490. * whenever a null data source is encountered (this can be because mData
  8491. * is set to null, or because the data source itself is null).
  8492. * @type string
  8493. * @default null
  8494. * @dtopt Columns
  8495. *
  8496. * @example
  8497. * // Using aoColumnDefs
  8498. * $(document).ready( function() {
  8499. * $('#example').dataTable( {
  8500. * "aoColumnDefs": [
  8501. * {
  8502. * "mData": null,
  8503. * "sDefaultContent": "Edit",
  8504. * "aTargets": [ -1 ]
  8505. * }
  8506. * ]
  8507. * } );
  8508. * } );
  8509. *
  8510. * @example
  8511. * // Using aoColumns
  8512. * $(document).ready( function() {
  8513. * $('#example').dataTable( {
  8514. * "aoColumns": [
  8515. * null,
  8516. * null,
  8517. * null,
  8518. * {
  8519. * "mData": null,
  8520. * "sDefaultContent": "Edit"
  8521. * }
  8522. * ]
  8523. * } );
  8524. * } );
  8525. */
  8526. "sDefaultContent":null,
  8527. /**
  8528. * This parameter is only used in DataTables' server-side processing. It can
  8529. * be exceptionally useful to know what columns are being displayed on the
  8530. * client side, and to map these to database fields. When defined, the names
  8531. * also allow DataTables to reorder information from the server if it comes
  8532. * back in an unexpected order (i.e. if you switch your columns around on the
  8533. * client-side, your server-side code does not also need updating).
  8534. * @type string
  8535. * @default <i>Empty string</i>
  8536. * @dtopt Columns
  8537. *
  8538. * @example
  8539. * // Using aoColumnDefs
  8540. * $(document).ready( function() {
  8541. * $('#example').dataTable( {
  8542. * "aoColumnDefs": [
  8543. * { "sName": "engine", "aTargets": [ 0 ] },
  8544. * { "sName": "browser", "aTargets": [ 1 ] },
  8545. * { "sName": "platform", "aTargets": [ 2 ] },
  8546. * { "sName": "version", "aTargets": [ 3 ] },
  8547. * { "sName": "grade", "aTargets": [ 4 ] }
  8548. * ]
  8549. * } );
  8550. * } );
  8551. *
  8552. * @example
  8553. * // Using aoColumns
  8554. * $(document).ready( function() {
  8555. * $('#example').dataTable( {
  8556. * "aoColumns": [
  8557. * { "sName": "engine" },
  8558. * { "sName": "browser" },
  8559. * { "sName": "platform" },
  8560. * { "sName": "version" },
  8561. * { "sName": "grade" }
  8562. * ]
  8563. * } );
  8564. * } );
  8565. */
  8566. "sName":"",
  8567. /**
  8568. * Defines a data source type for the sorting which can be used to read
  8569. * real-time information from the table (updating the internally cached
  8570. * version) prior to sorting. This allows sorting to occur on user editable
  8571. * elements such as form inputs.
  8572. * @type string
  8573. * @default std
  8574. * @dtopt Columns
  8575. *
  8576. * @example
  8577. * // Using aoColumnDefs
  8578. * $(document).ready( function() {
  8579. * $('#example').dataTable( {
  8580. * "aoColumnDefs": [
  8581. * { "sSortDataType": "dom-text", "aTargets": [ 2, 3 ] },
  8582. * { "sType": "numeric", "aTargets": [ 3 ] },
  8583. * { "sSortDataType": "dom-select", "aTargets": [ 4 ] },
  8584. * { "sSortDataType": "dom-checkbox", "aTargets": [ 5 ] }
  8585. * ]
  8586. * } );
  8587. * } );
  8588. *
  8589. * @example
  8590. * // Using aoColumns
  8591. * $(document).ready( function() {
  8592. * $('#example').dataTable( {
  8593. * "aoColumns": [
  8594. * null,
  8595. * null,
  8596. * { "sSortDataType": "dom-text" },
  8597. * { "sSortDataType": "dom-text", "sType": "numeric" },
  8598. * { "sSortDataType": "dom-select" },
  8599. * { "sSortDataType": "dom-checkbox" }
  8600. * ]
  8601. * } );
  8602. * } );
  8603. */
  8604. "sSortDataType":"std",
  8605. /**
  8606. * The title of this column.
  8607. * @type string
  8608. * @default null <i>Derived from the 'TH' value for this column in the
  8609. * original HTML table.</i>
  8610. * @dtopt Columns
  8611. *
  8612. * @example
  8613. * // Using aoColumnDefs
  8614. * $(document).ready( function() {
  8615. * $('#example').dataTable( {
  8616. * "aoColumnDefs": [
  8617. * { "sTitle": "My column title", "aTargets": [ 0 ] }
  8618. * ]
  8619. * } );
  8620. * } );
  8621. *
  8622. * @example
  8623. * // Using aoColumns
  8624. * $(document).ready( function() {
  8625. * $('#example').dataTable( {
  8626. * "aoColumns": [
  8627. * { "sTitle": "My column title" },
  8628. * null,
  8629. * null,
  8630. * null,
  8631. * null
  8632. * ]
  8633. * } );
  8634. * } );
  8635. */
  8636. "sTitle":null,
  8637. /**
  8638. * The type allows you to specify how the data for this column will be sorted.
  8639. * Four types (string, numeric, date and html (which will strip HTML tags
  8640. * before sorting)) are currently available. Note that only date formats
  8641. * understood by Javascript's Date() object will be accepted as type date. For
  8642. * example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 'numeric',
  8643. * 'date' or 'html' (by default). Further types can be adding through
  8644. * plug-ins.
  8645. * @type string
  8646. * @default null <i>Auto-detected from raw data</i>
  8647. * @dtopt Columns
  8648. *
  8649. * @example
  8650. * // Using aoColumnDefs
  8651. * $(document).ready( function() {
  8652. * $('#example').dataTable( {
  8653. * "aoColumnDefs": [
  8654. * { "sType": "html", "aTargets": [ 0 ] }
  8655. * ]
  8656. * } );
  8657. * } );
  8658. *
  8659. * @example
  8660. * // Using aoColumns
  8661. * $(document).ready( function() {
  8662. * $('#example').dataTable( {
  8663. * "aoColumns": [
  8664. * { "sType": "html" },
  8665. * null,
  8666. * null,
  8667. * null,
  8668. * null
  8669. * ]
  8670. * } );
  8671. * } );
  8672. */
  8673. "sType":null,
  8674. /**
  8675. * Defining the width of the column, this parameter may take any CSS value
  8676. * (3em, 20px etc). DataTables apples 'smart' widths to columns which have not
  8677. * been given a specific width through this interface ensuring that the table
  8678. * remains readable.
  8679. * @type string
  8680. * @default null <i>Automatic</i>
  8681. * @dtopt Columns
  8682. *
  8683. * @example
  8684. * // Using aoColumnDefs
  8685. * $(document).ready( function() {
  8686. * $('#example').dataTable( {
  8687. * "aoColumnDefs": [
  8688. * { "sWidth": "20%", "aTargets": [ 0 ] }
  8689. * ]
  8690. * } );
  8691. * } );
  8692. *
  8693. * @example
  8694. * // Using aoColumns
  8695. * $(document).ready( function() {
  8696. * $('#example').dataTable( {
  8697. * "aoColumns": [
  8698. * { "sWidth": "20%" },
  8699. * null,
  8700. * null,
  8701. * null,
  8702. * null
  8703. * ]
  8704. * } );
  8705. * } );
  8706. */
  8707. "sWidth":null
  8708. };
  8709. /**
  8710. * DataTables settings object - this holds all the information needed for a
  8711. * given table, including configuration, data and current application of the
  8712. * table options. DataTables does not have a single instance for each DataTable
  8713. * with the settings attached to that instance, but rather instances of the
  8714. * DataTable "class" are created on-the-fly as needed (typically by a
  8715. * $().dataTable() call) and the settings object is then applied to that
  8716. * instance.
  8717. *
  8718. * Note that this object is related to {@link DataTable.defaults} but this
  8719. * one is the internal data store for DataTables's cache of columns. It should
  8720. * NOT be manipulated outside of DataTables. Any configuration should be done
  8721. * through the initialisation options.
  8722. * @namespace
  8723. * @todo Really should attach the settings object to individual instances so we
  8724. * don't need to create new instances on each $().dataTable() call (if the
  8725. * table already exists). It would also save passing oSettings around and
  8726. * into every single function. However, this is a very significant
  8727. * architecture change for DataTables and will almost certainly break
  8728. * backwards compatibility with older installations. This is something that
  8729. * will be done in 2.0.
  8730. */
  8731. DataTable.models.oSettings = {
  8732. /**
  8733. * Primary features of DataTables and their enablement state.
  8734. * @namespace
  8735. */
  8736. "oFeatures":{
  8737. /**
  8738. * Flag to say if DataTables should automatically try to calculate the
  8739. * optimum table and columns widths (true) or not (false).
  8740. * Note that this parameter will be set by the initialisation routine. To
  8741. * set a default use {@link DataTable.defaults}.
  8742. * @type boolean
  8743. */
  8744. "bAutoWidth":null,
  8745. /**
  8746. * Delay the creation of TR and TD elements until they are actually
  8747. * needed by a driven page draw. This can give a significant speed
  8748. * increase for Ajax source and Javascript source data, but makes no
  8749. * difference at all fro DOM and server-side processing tables.
  8750. * Note that this parameter will be set by the initialisation routine. To
  8751. * set a default use {@link DataTable.defaults}.
  8752. * @type boolean
  8753. */
  8754. "bDeferRender":null,
  8755. /**
  8756. * Enable filtering on the table or not. Note that if this is disabled
  8757. * then there is no filtering at all on the table, including fnFilter.
  8758. * To just remove the filtering input use sDom and remove the 'f' option.
  8759. * Note that this parameter will be set by the initialisation routine. To
  8760. * set a default use {@link DataTable.defaults}.
  8761. * @type boolean
  8762. */
  8763. "bFilter":null,
  8764. /**
  8765. * Table information element (the 'Showing x of y records' div) enable
  8766. * flag.
  8767. * Note that this parameter will be set by the initialisation routine. To
  8768. * set a default use {@link DataTable.defaults}.
  8769. * @type boolean
  8770. */
  8771. "bInfo":null,
  8772. /**
  8773. * Present a user control allowing the end user to change the page size
  8774. * when pagination is enabled.
  8775. * Note that this parameter will be set by the initialisation routine. To
  8776. * set a default use {@link DataTable.defaults}.
  8777. * @type boolean
  8778. */
  8779. "bLengthChange":null,
  8780. /**
  8781. * Pagination enabled or not. Note that if this is disabled then length
  8782. * changing must also be disabled.
  8783. * Note that this parameter will be set by the initialisation routine. To
  8784. * set a default use {@link DataTable.defaults}.
  8785. * @type boolean
  8786. */
  8787. "bPaginate":null,
  8788. /**
  8789. * Processing indicator enable flag whenever DataTables is enacting a
  8790. * user request - typically an Ajax request for server-side processing.
  8791. * Note that this parameter will be set by the initialisation routine. To
  8792. * set a default use {@link DataTable.defaults}.
  8793. * @type boolean
  8794. */
  8795. "bProcessing":null,
  8796. /**
  8797. * Server-side processing enabled flag - when enabled DataTables will
  8798. * get all data from the server for every draw - there is no filtering,
  8799. * sorting or paging done on the client-side.
  8800. * Note that this parameter will be set by the initialisation routine. To
  8801. * set a default use {@link DataTable.defaults}.
  8802. * @type boolean
  8803. */
  8804. "bServerSide":null,
  8805. /**
  8806. * Sorting enablement flag.
  8807. * Note that this parameter will be set by the initialisation routine. To
  8808. * set a default use {@link DataTable.defaults}.
  8809. * @type boolean
  8810. */
  8811. "bSort":null,
  8812. /**
  8813. * Apply a class to the columns which are being sorted to provide a
  8814. * visual highlight or not. This can slow things down when enabled since
  8815. * there is a lot of DOM interaction.
  8816. * Note that this parameter will be set by the initialisation routine. To
  8817. * set a default use {@link DataTable.defaults}.
  8818. * @type boolean
  8819. */
  8820. "bSortClasses":null,
  8821. /**
  8822. * State saving enablement flag.
  8823. * Note that this parameter will be set by the initialisation routine. To
  8824. * set a default use {@link DataTable.defaults}.
  8825. * @type boolean
  8826. */
  8827. "bStateSave":null
  8828. },
  8829. /**
  8830. * Scrolling settings for a table.
  8831. * @namespace
  8832. */
  8833. "oScroll":{
  8834. /**
  8835. * Indicate if DataTables should be allowed to set the padding / margin
  8836. * etc for the scrolling header elements or not. Typically you will want
  8837. * this.
  8838. * Note that this parameter will be set by the initialisation routine. To
  8839. * set a default use {@link DataTable.defaults}.
  8840. * @type boolean
  8841. */
  8842. "bAutoCss":null,
  8843. /**
  8844. * When the table is shorter in height than sScrollY, collapse the
  8845. * table container down to the height of the table (when true).
  8846. * Note that this parameter will be set by the initialisation routine. To
  8847. * set a default use {@link DataTable.defaults}.
  8848. * @type boolean
  8849. */
  8850. "bCollapse":null,
  8851. /**
  8852. * Infinite scrolling enablement flag. Now deprecated in favour of
  8853. * using the Scroller plug-in.
  8854. * Note that this parameter will be set by the initialisation routine. To
  8855. * set a default use {@link DataTable.defaults}.
  8856. * @type boolean
  8857. */
  8858. "bInfinite":null,
  8859. /**
  8860. * Width of the scrollbar for the web-browser's platform. Calculated
  8861. * during table initialisation.
  8862. * @type int
  8863. * @default 0
  8864. */
  8865. "iBarWidth":0,
  8866. /**
  8867. * Space (in pixels) between the bottom of the scrolling container and
  8868. * the bottom of the scrolling viewport before the next page is loaded
  8869. * when using infinite scrolling.
  8870. * Note that this parameter will be set by the initialisation routine. To
  8871. * set a default use {@link DataTable.defaults}.
  8872. * @type int
  8873. */
  8874. "iLoadGap":null,
  8875. /**
  8876. * Viewport width for horizontal scrolling. Horizontal scrolling is
  8877. * disabled if an empty string.
  8878. * Note that this parameter will be set by the initialisation routine. To
  8879. * set a default use {@link DataTable.defaults}.
  8880. * @type string
  8881. */
  8882. "sX":null,
  8883. /**
  8884. * Width to expand the table to when using x-scrolling. Typically you
  8885. * should not need to use this.
  8886. * Note that this parameter will be set by the initialisation routine. To
  8887. * set a default use {@link DataTable.defaults}.
  8888. * @type string
  8889. * @deprecated
  8890. */
  8891. "sXInner":null,
  8892. /**
  8893. * Viewport height for vertical scrolling. Vertical scrolling is disabled
  8894. * if an empty string.
  8895. * Note that this parameter will be set by the initialisation routine. To
  8896. * set a default use {@link DataTable.defaults}.
  8897. * @type string
  8898. */
  8899. "sY":null
  8900. },
  8901. /**
  8902. * Language information for the table.
  8903. * @namespace
  8904. * @extends DataTable.defaults.oLanguage
  8905. */
  8906. "oLanguage":{
  8907. /**
  8908. * Information callback function. See
  8909. * {@link DataTable.defaults.fnInfoCallback}
  8910. * @type function
  8911. * @default null
  8912. */
  8913. "fnInfoCallback":null
  8914. },
  8915. /**
  8916. * Browser support parameters
  8917. * @namespace
  8918. */
  8919. "oBrowser":{
  8920. /**
  8921. * Indicate if the browser incorrectly calculates width:100% inside a
  8922. * scrolling element (IE6/7)
  8923. * @type boolean
  8924. * @default false
  8925. */
  8926. "bScrollOversize":false
  8927. },
  8928. /**
  8929. * Array referencing the nodes which are used for the features. The
  8930. * parameters of this object match what is allowed by sDom - i.e.
  8931. * <ul>
  8932. * <li>'l' - Length changing</li>
  8933. * <li>'f' - Filtering input</li>
  8934. * <li>'t' - The table!</li>
  8935. * <li>'i' - Information</li>
  8936. * <li>'p' - Pagination</li>
  8937. * <li>'r' - pRocessing</li>
  8938. * </ul>
  8939. * @type array
  8940. * @default []
  8941. */
  8942. "aanFeatures":[],
  8943. /**
  8944. * Store data information - see {@link DataTable.models.oRow} for detailed
  8945. * information.
  8946. * @type array
  8947. * @default []
  8948. */
  8949. "aoData":[],
  8950. /**
  8951. * Array of indexes which are in the current display (after filtering etc)
  8952. * @type array
  8953. * @default []
  8954. */
  8955. "aiDisplay":[],
  8956. /**
  8957. * Array of indexes for display - no filtering
  8958. * @type array
  8959. * @default []
  8960. */
  8961. "aiDisplayMaster":[],
  8962. /**
  8963. * Store information about each column that is in use
  8964. * @type array
  8965. * @default []
  8966. */
  8967. "aoColumns":[],
  8968. /**
  8969. * Store information about the table's header
  8970. * @type array
  8971. * @default []
  8972. */
  8973. "aoHeader":[],
  8974. /**
  8975. * Store information about the table's footer
  8976. * @type array
  8977. * @default []
  8978. */
  8979. "aoFooter":[],
  8980. /**
  8981. * Search data array for regular expression searching
  8982. * @type array
  8983. * @default []
  8984. */
  8985. "asDataSearch":[],
  8986. /**
  8987. * Store the applied global search information in case we want to force a
  8988. * research or compare the old search to a new one.
  8989. * Note that this parameter will be set by the initialisation routine. To
  8990. * set a default use {@link DataTable.defaults}.
  8991. * @namespace
  8992. * @extends DataTable.models.oSearch
  8993. */
  8994. "oPreviousSearch":{},
  8995. /**
  8996. * Store the applied search for each column - see
  8997. * {@link DataTable.models.oSearch} for the format that is used for the
  8998. * filtering information for each column.
  8999. * @type array
  9000. * @default []
  9001. */
  9002. "aoPreSearchCols":[],
  9003. /**
  9004. * Sorting that is applied to the table. Note that the inner arrays are
  9005. * used in the following manner:
  9006. * <ul>
  9007. * <li>Index 0 - column number</li>
  9008. * <li>Index 1 - current sorting direction</li>
  9009. * <li>Index 2 - index of asSorting for this column</li>
  9010. * </ul>
  9011. * Note that this parameter will be set by the initialisation routine. To
  9012. * set a default use {@link DataTable.defaults}.
  9013. * @type array
  9014. * @todo These inner arrays should really be objects
  9015. */
  9016. "aaSorting":null,
  9017. /**
  9018. * Sorting that is always applied to the table (i.e. prefixed in front of
  9019. * aaSorting).
  9020. * Note that this parameter will be set by the initialisation routine. To
  9021. * set a default use {@link DataTable.defaults}.
  9022. * @type array|null
  9023. * @default null
  9024. */
  9025. "aaSortingFixed":null,
  9026. /**
  9027. * Classes to use for the striping of a table.
  9028. * Note that this parameter will be set by the initialisation routine. To
  9029. * set a default use {@link DataTable.defaults}.
  9030. * @type array
  9031. * @default []
  9032. */
  9033. "asStripeClasses":null,
  9034. /**
  9035. * If restoring a table - we should restore its striping classes as well
  9036. * @type array
  9037. * @default []
  9038. */
  9039. "asDestroyStripes":[],
  9040. /**
  9041. * If restoring a table - we should restore its width
  9042. * @type int
  9043. * @default 0
  9044. */
  9045. "sDestroyWidth":0,
  9046. /**
  9047. * Callback functions array for every time a row is inserted (i.e. on a draw).
  9048. * @type array
  9049. * @default []
  9050. */
  9051. "aoRowCallback":[],
  9052. /**
  9053. * Callback functions for the header on each draw.
  9054. * @type array
  9055. * @default []
  9056. */
  9057. "aoHeaderCallback":[],
  9058. /**
  9059. * Callback function for the footer on each draw.
  9060. * @type array
  9061. * @default []
  9062. */
  9063. "aoFooterCallback":[],
  9064. /**
  9065. * Array of callback functions for draw callback functions
  9066. * @type array
  9067. * @default []
  9068. */
  9069. "aoDrawCallback":[],
  9070. /**
  9071. * Array of callback functions for row created function
  9072. * @type array
  9073. * @default []
  9074. */
  9075. "aoRowCreatedCallback":[],
  9076. /**
  9077. * Callback functions for just before the table is redrawn. A return of
  9078. * false will be used to cancel the draw.
  9079. * @type array
  9080. * @default []
  9081. */
  9082. "aoPreDrawCallback":[],
  9083. /**
  9084. * Callback functions for when the table has been initialised.
  9085. * @type array
  9086. * @default []
  9087. */
  9088. "aoInitComplete":[],
  9089. /**
  9090. * Callbacks for modifying the settings to be stored for state saving, prior to
  9091. * saving state.
  9092. * @type array
  9093. * @default []
  9094. */
  9095. "aoStateSaveParams":[],
  9096. /**
  9097. * Callbacks for modifying the settings that have been stored for state saving
  9098. * prior to using the stored values to restore the state.
  9099. * @type array
  9100. * @default []
  9101. */
  9102. "aoStateLoadParams":[],
  9103. /**
  9104. * Callbacks for operating on the settings object once the saved state has been
  9105. * loaded
  9106. * @type array
  9107. * @default []
  9108. */
  9109. "aoStateLoaded":[],
  9110. /**
  9111. * Cache the table ID for quick access
  9112. * @type string
  9113. * @default <i>Empty string</i>
  9114. */
  9115. "sTableId":"",
  9116. /**
  9117. * The TABLE node for the main table
  9118. * @type node
  9119. * @default null
  9120. */
  9121. "nTable":null,
  9122. /**
  9123. * Permanent ref to the thead element
  9124. * @type node
  9125. * @default null
  9126. */
  9127. "nTHead":null,
  9128. /**
  9129. * Permanent ref to the tfoot element - if it exists
  9130. * @type node
  9131. * @default null
  9132. */
  9133. "nTFoot":null,
  9134. /**
  9135. * Permanent ref to the tbody element
  9136. * @type node
  9137. * @default null
  9138. */
  9139. "nTBody":null,
  9140. /**
  9141. * Cache the wrapper node (contains all DataTables controlled elements)
  9142. * @type node
  9143. * @default null
  9144. */
  9145. "nTableWrapper":null,
  9146. /**
  9147. * Indicate if when using server-side processing the loading of data
  9148. * should be deferred until the second draw.
  9149. * Note that this parameter will be set by the initialisation routine. To
  9150. * set a default use {@link DataTable.defaults}.
  9151. * @type boolean
  9152. * @default false
  9153. */
  9154. "bDeferLoading":false,
  9155. /**
  9156. * Indicate if all required information has been read in
  9157. * @type boolean
  9158. * @default false
  9159. */
  9160. "bInitialised":false,
  9161. /**
  9162. * Information about open rows. Each object in the array has the parameters
  9163. * 'nTr' and 'nParent'
  9164. * @type array
  9165. * @default []
  9166. */
  9167. "aoOpenRows":[],
  9168. /**
  9169. * Dictate the positioning of DataTables' control elements - see
  9170. * {@link DataTable.model.oInit.sDom}.
  9171. * Note that this parameter will be set by the initialisation routine. To
  9172. * set a default use {@link DataTable.defaults}.
  9173. * @type string
  9174. * @default null
  9175. */
  9176. "sDom":null,
  9177. /**
  9178. * Which type of pagination should be used.
  9179. * Note that this parameter will be set by the initialisation routine. To
  9180. * set a default use {@link DataTable.defaults}.
  9181. * @type string
  9182. * @default two_button
  9183. */
  9184. "sPaginationType":"two_button",
  9185. /**
  9186. * The cookie duration (for bStateSave) in seconds.
  9187. * Note that this parameter will be set by the initialisation routine. To
  9188. * set a default use {@link DataTable.defaults}.
  9189. * @type int
  9190. * @default 0
  9191. */
  9192. "iCookieDuration":0,
  9193. /**
  9194. * The cookie name prefix.
  9195. * Note that this parameter will be set by the initialisation routine. To
  9196. * set a default use {@link DataTable.defaults}.
  9197. * @type string
  9198. * @default <i>Empty string</i>
  9199. */
  9200. "sCookiePrefix":"",
  9201. /**
  9202. * Callback function for cookie creation.
  9203. * Note that this parameter will be set by the initialisation routine. To
  9204. * set a default use {@link DataTable.defaults}.
  9205. * @type function
  9206. * @default null
  9207. */
  9208. "fnCookieCallback":null,
  9209. /**
  9210. * Array of callback functions for state saving. Each array element is an
  9211. * object with the following parameters:
  9212. * <ul>
  9213. * <li>function:fn - function to call. Takes two parameters, oSettings
  9214. * and the JSON string to save that has been thus far created. Returns
  9215. * a JSON string to be inserted into a json object
  9216. * (i.e. '"param": [ 0, 1, 2]')</li>
  9217. * <li>string:sName - name of callback</li>
  9218. * </ul>
  9219. * @type array
  9220. * @default []
  9221. */
  9222. "aoStateSave":[],
  9223. /**
  9224. * Array of callback functions for state loading. Each array element is an
  9225. * object with the following parameters:
  9226. * <ul>
  9227. * <li>function:fn - function to call. Takes two parameters, oSettings
  9228. * and the object stored. May return false to cancel state loading</li>
  9229. * <li>string:sName - name of callback</li>
  9230. * </ul>
  9231. * @type array
  9232. * @default []
  9233. */
  9234. "aoStateLoad":[],
  9235. /**
  9236. * State that was loaded from the cookie. Useful for back reference
  9237. * @type object
  9238. * @default null
  9239. */
  9240. "oLoadedState":null,
  9241. /**
  9242. * Source url for AJAX data for the table.
  9243. * Note that this parameter will be set by the initialisation routine. To
  9244. * set a default use {@link DataTable.defaults}.
  9245. * @type string
  9246. * @default null
  9247. */
  9248. "sAjaxSource":null,
  9249. /**
  9250. * Property from a given object from which to read the table data from. This
  9251. * can be an empty string (when not server-side processing), in which case
  9252. * it is assumed an an array is given directly.
  9253. * Note that this parameter will be set by the initialisation routine. To
  9254. * set a default use {@link DataTable.defaults}.
  9255. * @type string
  9256. */
  9257. "sAjaxDataProp":null,
  9258. /**
  9259. * Note if draw should be blocked while getting data
  9260. * @type boolean
  9261. * @default true
  9262. */
  9263. "bAjaxDataGet":true,
  9264. /**
  9265. * The last jQuery XHR object that was used for server-side data gathering.
  9266. * This can be used for working with the XHR information in one of the
  9267. * callbacks
  9268. * @type object
  9269. * @default null
  9270. */
  9271. "jqXHR":null,
  9272. /**
  9273. * Function to get the server-side data.
  9274. * Note that this parameter will be set by the initialisation routine. To
  9275. * set a default use {@link DataTable.defaults}.
  9276. * @type function
  9277. */
  9278. "fnServerData":null,
  9279. /**
  9280. * Functions which are called prior to sending an Ajax request so extra
  9281. * parameters can easily be sent to the server
  9282. * @type array
  9283. * @default []
  9284. */
  9285. "aoServerParams":[],
  9286. /**
  9287. * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
  9288. * required).
  9289. * Note that this parameter will be set by the initialisation routine. To
  9290. * set a default use {@link DataTable.defaults}.
  9291. * @type string
  9292. */
  9293. "sServerMethod":null,
  9294. /**
  9295. * Format numbers for display.
  9296. * Note that this parameter will be set by the initialisation routine. To
  9297. * set a default use {@link DataTable.defaults}.
  9298. * @type function
  9299. */
  9300. "fnFormatNumber":null,
  9301. /**
  9302. * List of options that can be used for the user selectable length menu.
  9303. * Note that this parameter will be set by the initialisation routine. To
  9304. * set a default use {@link DataTable.defaults}.
  9305. * @type array
  9306. * @default []
  9307. */
  9308. "aLengthMenu":null,
  9309. /**
  9310. * Counter for the draws that the table does. Also used as a tracker for
  9311. * server-side processing
  9312. * @type int
  9313. * @default 0
  9314. */
  9315. "iDraw":0,
  9316. /**
  9317. * Indicate if a redraw is being done - useful for Ajax
  9318. * @type boolean
  9319. * @default false
  9320. */
  9321. "bDrawing":false,
  9322. /**
  9323. * Draw index (iDraw) of the last error when parsing the returned data
  9324. * @type int
  9325. * @default -1
  9326. */
  9327. "iDrawError":-1,
  9328. /**
  9329. * Paging display length
  9330. * @type int
  9331. * @default 10
  9332. */
  9333. "_iDisplayLength":10,
  9334. /**
  9335. * Paging start point - aiDisplay index
  9336. * @type int
  9337. * @default 0
  9338. */
  9339. "_iDisplayStart":0,
  9340. /**
  9341. * Paging end point - aiDisplay index. Use fnDisplayEnd rather than
  9342. * this property to get the end point
  9343. * @type int
  9344. * @default 10
  9345. * @private
  9346. */
  9347. "_iDisplayEnd":10,
  9348. /**
  9349. * Server-side processing - number of records in the result set
  9350. * (i.e. before filtering), Use fnRecordsTotal rather than
  9351. * this property to get the value of the number of records, regardless of
  9352. * the server-side processing setting.
  9353. * @type int
  9354. * @default 0
  9355. * @private
  9356. */
  9357. "_iRecordsTotal":0,
  9358. /**
  9359. * Server-side processing - number of records in the current display set
  9360. * (i.e. after filtering). Use fnRecordsDisplay rather than
  9361. * this property to get the value of the number of records, regardless of
  9362. * the server-side processing setting.
  9363. * @type boolean
  9364. * @default 0
  9365. * @private
  9366. */
  9367. "_iRecordsDisplay":0,
  9368. /**
  9369. * Flag to indicate if jQuery UI marking and classes should be used.
  9370. * Note that this parameter will be set by the initialisation routine. To
  9371. * set a default use {@link DataTable.defaults}.
  9372. * @type boolean
  9373. */
  9374. "bJUI":null,
  9375. /**
  9376. * The classes to use for the table
  9377. * @type object
  9378. * @default {}
  9379. */
  9380. "oClasses":{},
  9381. /**
  9382. * Flag attached to the settings object so you can check in the draw
  9383. * callback if filtering has been done in the draw. Deprecated in favour of
  9384. * events.
  9385. * @type boolean
  9386. * @default false
  9387. * @deprecated
  9388. */
  9389. "bFiltered":false,
  9390. /**
  9391. * Flag attached to the settings object so you can check in the draw
  9392. * callback if sorting has been done in the draw. Deprecated in favour of
  9393. * events.
  9394. * @type boolean
  9395. * @default false
  9396. * @deprecated
  9397. */
  9398. "bSorted":false,
  9399. /**
  9400. * Indicate that if multiple rows are in the header and there is more than
  9401. * one unique cell per column, if the top one (true) or bottom one (false)
  9402. * should be used for sorting / title by DataTables.
  9403. * Note that this parameter will be set by the initialisation routine. To
  9404. * set a default use {@link DataTable.defaults}.
  9405. * @type boolean
  9406. */
  9407. "bSortCellsTop":null,
  9408. /**
  9409. * Initialisation object that is used for the table
  9410. * @type object
  9411. * @default null
  9412. */
  9413. "oInit":null,
  9414. /**
  9415. * Destroy callback functions - for plug-ins to attach themselves to the
  9416. * destroy so they can clean up markup and events.
  9417. * @type array
  9418. * @default []
  9419. */
  9420. "aoDestroyCallback":[],
  9421. /**
  9422. * Get the number of records in the current record set, before filtering
  9423. * @type function
  9424. */
  9425. "fnRecordsTotal":function () {
  9426. if (this.oFeatures.bServerSide) {
  9427. return parseInt(this._iRecordsTotal, 10);
  9428. } else {
  9429. return this.aiDisplayMaster.length;
  9430. }
  9431. },
  9432. /**
  9433. * Get the number of records in the current record set, after filtering
  9434. * @type function
  9435. */
  9436. "fnRecordsDisplay":function () {
  9437. if (this.oFeatures.bServerSide) {
  9438. return parseInt(this._iRecordsDisplay, 10);
  9439. } else {
  9440. return this.aiDisplay.length;
  9441. }
  9442. },
  9443. /**
  9444. * Set the display end point - aiDisplay index
  9445. * @type function
  9446. * @todo Should do away with _iDisplayEnd and calculate it on-the-fly here
  9447. */
  9448. "fnDisplayEnd":function () {
  9449. if (this.oFeatures.bServerSide) {
  9450. if (this.oFeatures.bPaginate === false || this._iDisplayLength == -1) {
  9451. return this._iDisplayStart + this.aiDisplay.length;
  9452. } else {
  9453. return Math.min(this._iDisplayStart + this._iDisplayLength,
  9454. this._iRecordsDisplay);
  9455. }
  9456. } else {
  9457. return this._iDisplayEnd;
  9458. }
  9459. },
  9460. /**
  9461. * The DataTables object for this table
  9462. * @type object
  9463. * @default null
  9464. */
  9465. "oInstance":null,
  9466. /**
  9467. * Unique identifier for each instance of the DataTables object. If there
  9468. * is an ID on the table node, then it takes that value, otherwise an
  9469. * incrementing internal counter is used.
  9470. * @type string
  9471. * @default null
  9472. */
  9473. "sInstance":null,
  9474. /**
  9475. * tabindex attribute value that is added to DataTables control elements, allowing
  9476. * keyboard navigation of the table and its controls.
  9477. */
  9478. "iTabIndex":0,
  9479. /**
  9480. * DIV container for the footer scrolling table if scrolling
  9481. */
  9482. "nScrollHead":null,
  9483. /**
  9484. * DIV container for the footer scrolling table if scrolling
  9485. */
  9486. "nScrollFoot":null
  9487. };
  9488. /**
  9489. * Extension object for DataTables that is used to provide all extension options.
  9490. *
  9491. * Note that the <i>DataTable.ext</i> object is available through
  9492. * <i>jQuery.fn.dataTable.ext</i> where it may be accessed and manipulated. It is
  9493. * also aliased to <i>jQuery.fn.dataTableExt</i> for historic reasons.
  9494. * @namespace
  9495. * @extends DataTable.models.ext
  9496. */
  9497. DataTable.ext = $.extend(true, {}, DataTable.models.ext);
  9498. $.extend(DataTable.ext.oStdClasses, {
  9499. "sTable":"dataTable",
  9500. /* Two buttons buttons */
  9501. "sPagePrevEnabled":"paginate_enabled_previous",
  9502. "sPagePrevDisabled":"paginate_disabled_previous",
  9503. "sPageNextEnabled":"paginate_enabled_next",
  9504. "sPageNextDisabled":"paginate_disabled_next",
  9505. "sPageJUINext":"",
  9506. "sPageJUIPrev":"",
  9507. /* Full numbers paging buttons */
  9508. "sPageButton":"paginate_button",
  9509. "sPageButtonActive":"paginate_active",
  9510. "sPageButtonStaticDisabled":"paginate_button paginate_button_disabled",
  9511. "sPageFirst":"first",
  9512. "sPagePrevious":"previous",
  9513. "sPageNext":"next",
  9514. "sPageLast":"last",
  9515. /* Striping classes */
  9516. "sStripeOdd":"odd",
  9517. "sStripeEven":"even",
  9518. /* Empty row */
  9519. "sRowEmpty":"dataTables_empty",
  9520. /* Features */
  9521. "sWrapper":"dataTables_wrapper",
  9522. "sFilter":"dataTables_filter",
  9523. "sInfo":"dataTables_info",
  9524. "sPaging":"dataTables_paginate paging_", /* Note that the type is postfixed */
  9525. "sLength":"dataTables_length",
  9526. "sProcessing":"dataTables_processing",
  9527. /* Sorting */
  9528. "sSortAsc":"sorting_asc",
  9529. "sSortDesc":"sorting_desc",
  9530. "sSortable":"sorting", /* Sortable in both directions */
  9531. "sSortableAsc":"sorting_asc_disabled",
  9532. "sSortableDesc":"sorting_desc_disabled",
  9533. "sSortableNone":"sorting_disabled",
  9534. "sSortColumn":"sorting_", /* Note that an int is postfixed for the sorting order */
  9535. "sSortJUIAsc":"",
  9536. "sSortJUIDesc":"",
  9537. "sSortJUI":"",
  9538. "sSortJUIAscAllowed":"",
  9539. "sSortJUIDescAllowed":"",
  9540. "sSortJUIWrapper":"",
  9541. "sSortIcon":"",
  9542. /* Scrolling */
  9543. "sScrollWrapper":"dataTables_scroll",
  9544. "sScrollHead":"dataTables_scrollHead",
  9545. "sScrollHeadInner":"dataTables_scrollHeadInner",
  9546. "sScrollBody":"dataTables_scrollBody",
  9547. "sScrollFoot":"dataTables_scrollFoot",
  9548. "sScrollFootInner":"dataTables_scrollFootInner",
  9549. /* Misc */
  9550. "sFooterTH":"",
  9551. "sJUIHeader":"",
  9552. "sJUIFooter":""
  9553. });
  9554. $.extend(DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, {
  9555. /* Two buttons buttons */
  9556. "sPagePrevEnabled":"fg-button ui-button ui-state-default ui-corner-left",
  9557. "sPagePrevDisabled":"fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",
  9558. "sPageNextEnabled":"fg-button ui-button ui-state-default ui-corner-right",
  9559. "sPageNextDisabled":"fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",
  9560. "sPageJUINext":"ui-icon ui-icon-circle-arrow-e",
  9561. "sPageJUIPrev":"ui-icon ui-icon-circle-arrow-w",
  9562. /* Full numbers paging buttons */
  9563. "sPageButton":"fg-button ui-button ui-state-default",
  9564. "sPageButtonActive":"fg-button ui-button ui-state-default ui-state-disabled",
  9565. "sPageButtonStaticDisabled":"fg-button ui-button ui-state-default ui-state-disabled",
  9566. "sPageFirst":"first ui-corner-tl ui-corner-bl",
  9567. "sPageLast":"last ui-corner-tr ui-corner-br",
  9568. /* Features */
  9569. "sPaging":"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi " +
  9570. "ui-buttonset-multi paging_", /* Note that the type is postfixed */
  9571. /* Sorting */
  9572. "sSortAsc":"ui-state-default",
  9573. "sSortDesc":"ui-state-default",
  9574. "sSortable":"ui-state-default",
  9575. "sSortableAsc":"ui-state-default",
  9576. "sSortableDesc":"ui-state-default",
  9577. "sSortableNone":"ui-state-default",
  9578. "sSortJUIAsc":"css_right ui-icon ui-icon-triangle-1-n",
  9579. "sSortJUIDesc":"css_right ui-icon ui-icon-triangle-1-s",
  9580. "sSortJUI":"css_right ui-icon ui-icon-carat-2-n-s",
  9581. "sSortJUIAscAllowed":"css_right ui-icon ui-icon-carat-1-n",
  9582. "sSortJUIDescAllowed":"css_right ui-icon ui-icon-carat-1-s",
  9583. "sSortJUIWrapper":"DataTables_sort_wrapper",
  9584. "sSortIcon":"DataTables_sort_icon",
  9585. /* Scrolling */
  9586. "sScrollHead":"dataTables_scrollHead ui-state-default",
  9587. "sScrollFoot":"dataTables_scrollFoot ui-state-default",
  9588. /* Misc */
  9589. "sFooterTH":"ui-state-default",
  9590. "sJUIHeader":"fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix",
  9591. "sJUIFooter":"fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"
  9592. });
  9593. /*
  9594. * Variable: oPagination
  9595. * Purpose:
  9596. * Scope: jQuery.fn.dataTableExt
  9597. */
  9598. $.extend(DataTable.ext.oPagination, {
  9599. /*
  9600. * Variable: two_button
  9601. * Purpose: Standard two button (forward/back) pagination
  9602. * Scope: jQuery.fn.dataTableExt.oPagination
  9603. */
  9604. "two_button":{
  9605. /*
  9606. * Function: oPagination.two_button.fnInit
  9607. * Purpose: Initialise dom elements required for pagination with forward/back buttons only
  9608. * Returns: -
  9609. * Inputs: object:oSettings - dataTables settings object
  9610. * node:nPaging - the DIV which contains this pagination control
  9611. * function:fnCallbackDraw - draw function which must be called on update
  9612. */
  9613. "fnInit":function (oSettings, nPaging, fnCallbackDraw) {
  9614. var oLang = oSettings.oLanguage.oPaginate;
  9615. var oClasses = oSettings.oClasses;
  9616. var fnClickHandler = function (e) {
  9617. if (oSettings.oApi._fnPageChange(oSettings, e.data.action)) {
  9618. fnCallbackDraw(oSettings);
  9619. }
  9620. };
  9621. var sAppend = (!oSettings.bJUI) ?
  9622. '<a class="' + oSettings.oClasses.sPagePrevDisabled + '" tabindex="' + oSettings.iTabIndex + '" role="button">' + oLang.sPrevious + '</a>' +
  9623. '<a class="' + oSettings.oClasses.sPageNextDisabled + '" tabindex="' + oSettings.iTabIndex + '" role="button">' + oLang.sNext + '</a>'
  9624. :
  9625. '<a class="' + oSettings.oClasses.sPagePrevDisabled + '" tabindex="' + oSettings.iTabIndex + '" role="button"><span class="' + oSettings.oClasses.sPageJUIPrev + '"></span></a>' +
  9626. '<a class="' + oSettings.oClasses.sPageNextDisabled + '" tabindex="' + oSettings.iTabIndex + '" role="button"><span class="' + oSettings.oClasses.sPageJUINext + '"></span></a>';
  9627. $(nPaging).append(sAppend);
  9628. var els = $('a', nPaging);
  9629. var nPrevious = els[0],
  9630. nNext = els[1];
  9631. oSettings.oApi._fnBindAction(nPrevious, {action:"previous"}, fnClickHandler);
  9632. oSettings.oApi._fnBindAction(nNext, {action:"next"}, fnClickHandler);
  9633. /* ID the first elements only */
  9634. if (!oSettings.aanFeatures.p) {
  9635. nPaging.id = oSettings.sTableId + '_paginate';
  9636. nPrevious.id = oSettings.sTableId + '_previous';
  9637. nNext.id = oSettings.sTableId + '_next';
  9638. nPrevious.setAttribute('aria-controls', oSettings.sTableId);
  9639. nNext.setAttribute('aria-controls', oSettings.sTableId);
  9640. }
  9641. },
  9642. /*
  9643. * Function: oPagination.two_button.fnUpdate
  9644. * Purpose: Update the two button pagination at the end of the draw
  9645. * Returns: -
  9646. * Inputs: object:oSettings - dataTables settings object
  9647. * function:fnCallbackDraw - draw function to call on page change
  9648. */
  9649. "fnUpdate":function (oSettings, fnCallbackDraw) {
  9650. if (!oSettings.aanFeatures.p) {
  9651. return;
  9652. }
  9653. var oClasses = oSettings.oClasses;
  9654. var an = oSettings.aanFeatures.p;
  9655. var nNode;
  9656. /* Loop over each instance of the pager */
  9657. for (var i = 0, iLen = an.length; i < iLen; i++) {
  9658. nNode = an[i].firstChild;
  9659. if (nNode) {
  9660. /* Previous page */
  9661. nNode.className = ( oSettings._iDisplayStart === 0 ) ?
  9662. oClasses.sPagePrevDisabled : oClasses.sPagePrevEnabled;
  9663. /* Next page */
  9664. nNode = nNode.nextSibling;
  9665. nNode.className = ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) ?
  9666. oClasses.sPageNextDisabled : oClasses.sPageNextEnabled;
  9667. }
  9668. }
  9669. }
  9670. },
  9671. /*
  9672. * Variable: iFullNumbersShowPages
  9673. * Purpose: Change the number of pages which can be seen
  9674. * Scope: jQuery.fn.dataTableExt.oPagination
  9675. */
  9676. "iFullNumbersShowPages":5,
  9677. /*
  9678. * Variable: full_numbers
  9679. * Purpose: Full numbers pagination
  9680. * Scope: jQuery.fn.dataTableExt.oPagination
  9681. */
  9682. "full_numbers":{
  9683. /*
  9684. * Function: oPagination.full_numbers.fnInit
  9685. * Purpose: Initialise dom elements required for pagination with a list of the pages
  9686. * Returns: -
  9687. * Inputs: object:oSettings - dataTables settings object
  9688. * node:nPaging - the DIV which contains this pagination control
  9689. * function:fnCallbackDraw - draw function which must be called on update
  9690. */
  9691. "fnInit":function (oSettings, nPaging, fnCallbackDraw) {
  9692. var oLang = oSettings.oLanguage.oPaginate;
  9693. var oClasses = oSettings.oClasses;
  9694. var fnClickHandler = function (e) {
  9695. if (oSettings.oApi._fnPageChange(oSettings, e.data.action)) {
  9696. fnCallbackDraw(oSettings);
  9697. }
  9698. };
  9699. $(nPaging).append(
  9700. '<a tabindex="' + oSettings.iTabIndex + '" class="' + oClasses.sPageButton + " " + oClasses.sPageFirst + '">' + oLang.sFirst + '</a>' +
  9701. '<a tabindex="' + oSettings.iTabIndex + '" class="' + oClasses.sPageButton + " " + oClasses.sPagePrevious + '">' + oLang.sPrevious + '</a>' +
  9702. '<span></span>' +
  9703. '<a tabindex="' + oSettings.iTabIndex + '" class="' + oClasses.sPageButton + " " + oClasses.sPageNext + '">' + oLang.sNext + '</a>' +
  9704. '<a tabindex="' + oSettings.iTabIndex + '" class="' + oClasses.sPageButton + " " + oClasses.sPageLast + '">' + oLang.sLast + '</a>'
  9705. );
  9706. var els = $('a', nPaging);
  9707. var nFirst = els[0],
  9708. nPrev = els[1],
  9709. nNext = els[2],
  9710. nLast = els[3];
  9711. oSettings.oApi._fnBindAction(nFirst, {action:"first"}, fnClickHandler);
  9712. oSettings.oApi._fnBindAction(nPrev, {action:"previous"}, fnClickHandler);
  9713. oSettings.oApi._fnBindAction(nNext, {action:"next"}, fnClickHandler);
  9714. oSettings.oApi._fnBindAction(nLast, {action:"last"}, fnClickHandler);
  9715. /* ID the first elements only */
  9716. if (!oSettings.aanFeatures.p) {
  9717. nPaging.id = oSettings.sTableId + '_paginate';
  9718. nFirst.id = oSettings.sTableId + '_first';
  9719. nPrev.id = oSettings.sTableId + '_previous';
  9720. nNext.id = oSettings.sTableId + '_next';
  9721. nLast.id = oSettings.sTableId + '_last';
  9722. }
  9723. },
  9724. /*
  9725. * Function: oPagination.full_numbers.fnUpdate
  9726. * Purpose: Update the list of page buttons shows
  9727. * Returns: -
  9728. * Inputs: object:oSettings - dataTables settings object
  9729. * function:fnCallbackDraw - draw function to call on page change
  9730. */
  9731. "fnUpdate":function (oSettings, fnCallbackDraw) {
  9732. if (!oSettings.aanFeatures.p) {
  9733. return;
  9734. }
  9735. var iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages;
  9736. var iPageCountHalf = Math.floor(iPageCount / 2);
  9737. var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
  9738. var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
  9739. var sList = "";
  9740. var iStartButton, iEndButton, i, iLen;
  9741. var oClasses = oSettings.oClasses;
  9742. var anButtons, anStatic, nPaginateList, nNode;
  9743. var an = oSettings.aanFeatures.p;
  9744. var fnBind = function (j) {
  9745. oSettings.oApi._fnBindAction(this, {"page":j + iStartButton - 1}, function (e) {
  9746. /* Use the information in the element to jump to the required page */
  9747. oSettings.oApi._fnPageChange(oSettings, e.data.page);
  9748. fnCallbackDraw(oSettings);
  9749. e.preventDefault();
  9750. });
  9751. };
  9752. /* Pages calculation */
  9753. if (oSettings._iDisplayLength === -1) {
  9754. iStartButton = 1;
  9755. iEndButton = 1;
  9756. iCurrentPage = 1;
  9757. }
  9758. else if (iPages < iPageCount) {
  9759. iStartButton = 1;
  9760. iEndButton = iPages;
  9761. }
  9762. else if (iCurrentPage <= iPageCountHalf) {
  9763. iStartButton = 1;
  9764. iEndButton = iPageCount;
  9765. }
  9766. else if (iCurrentPage >= (iPages - iPageCountHalf)) {
  9767. iStartButton = iPages - iPageCount + 1;
  9768. iEndButton = iPages;
  9769. }
  9770. else {
  9771. iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
  9772. iEndButton = iStartButton + iPageCount - 1;
  9773. }
  9774. /* Build the dynamic list */
  9775. for (i = iStartButton; i <= iEndButton; i++) {
  9776. sList += (iCurrentPage !== i) ?
  9777. '<a tabindex="' + oSettings.iTabIndex + '" class="' + oClasses.sPageButton + '">' + oSettings.fnFormatNumber(i) + '</a>' :
  9778. '<a tabindex="' + oSettings.iTabIndex + '" class="' + oClasses.sPageButtonActive + '">' + oSettings.fnFormatNumber(i) + '</a>';
  9779. }
  9780. /* Loop over each instance of the pager */
  9781. for (i = 0, iLen = an.length; i < iLen; i++) {
  9782. nNode = an[i];
  9783. if (!nNode.hasChildNodes()) {
  9784. continue;
  9785. }
  9786. /* Build up the dynamic list first - html and listeners */
  9787. $('span:eq(0)', nNode)
  9788. .html(sList)
  9789. .children('a').each(fnBind);
  9790. /* Update the permanent button's classes */
  9791. anButtons = nNode.getElementsByTagName('a');
  9792. anStatic = [
  9793. anButtons[0], anButtons[1],
  9794. anButtons[anButtons.length - 2], anButtons[anButtons.length - 1]
  9795. ];
  9796. $(anStatic).removeClass(oClasses.sPageButton + " " + oClasses.sPageButtonActive + " " + oClasses.sPageButtonStaticDisabled);
  9797. $([anStatic[0], anStatic[1]]).addClass(
  9798. (iCurrentPage == 1) ?
  9799. oClasses.sPageButtonStaticDisabled :
  9800. oClasses.sPageButton
  9801. );
  9802. $([anStatic[2], anStatic[3]]).addClass(
  9803. (iPages === 0 || iCurrentPage === iPages || oSettings._iDisplayLength === -1) ?
  9804. oClasses.sPageButtonStaticDisabled :
  9805. oClasses.sPageButton
  9806. );
  9807. }
  9808. }
  9809. }
  9810. });
  9811. $.extend(DataTable.ext.oSort, {
  9812. /*
  9813. * text sorting
  9814. */
  9815. "string-pre":function (a) {
  9816. if (typeof a != 'string') {
  9817. a = (a !== null && a.toString) ? a.toString() : '';
  9818. }
  9819. return a.toLowerCase();
  9820. },
  9821. "string-asc":function (x, y) {
  9822. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  9823. },
  9824. "string-desc":function (x, y) {
  9825. return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  9826. },
  9827. /*
  9828. * html sorting (ignore html tags)
  9829. */
  9830. "html-pre":function (a) {
  9831. return a.replace(/<.*?>/g, "").toLowerCase();
  9832. },
  9833. "html-asc":function (x, y) {
  9834. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  9835. },
  9836. "html-desc":function (x, y) {
  9837. return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  9838. },
  9839. /*
  9840. * date sorting
  9841. */
  9842. "date-pre":function (a) {
  9843. var x = Date.parse(a);
  9844. if (isNaN(x) || x === "") {
  9845. x = Date.parse("01/01/1970 00:00:00");
  9846. }
  9847. return x;
  9848. },
  9849. "date-asc":function (x, y) {
  9850. return x - y;
  9851. },
  9852. "date-desc":function (x, y) {
  9853. return y - x;
  9854. },
  9855. /*
  9856. * numerical sorting
  9857. */
  9858. "numeric-pre":function (a) {
  9859. return (a == "-" || a === "") ? 0 : a * 1;
  9860. },
  9861. "numeric-asc":function (x, y) {
  9862. return x - y;
  9863. },
  9864. "numeric-desc":function (x, y) {
  9865. return y - x;
  9866. }
  9867. });
  9868. $.extend(DataTable.ext.aTypes, [
  9869. /*
  9870. * Function: -
  9871. * Purpose: Check to see if a string is numeric
  9872. * Returns: string:'numeric' or null
  9873. * Inputs: mixed:sText - string to check
  9874. */
  9875. function (sData) {
  9876. /* Allow zero length strings as a number */
  9877. if (typeof sData === 'number') {
  9878. return 'numeric';
  9879. }
  9880. else if (typeof sData !== 'string') {
  9881. return null;
  9882. }
  9883. var sValidFirstChars = "0123456789-";
  9884. var sValidChars = "0123456789.";
  9885. var Char;
  9886. var bDecimal = false;
  9887. /* Check for a valid first char (no period and allow negatives) */
  9888. Char = sData.charAt(0);
  9889. if (sValidFirstChars.indexOf(Char) == -1) {
  9890. return null;
  9891. }
  9892. /* Check all the other characters are valid */
  9893. for (var i = 1; i < sData.length; i++) {
  9894. Char = sData.charAt(i);
  9895. if (sValidChars.indexOf(Char) == -1) {
  9896. return null;
  9897. }
  9898. /* Only allowed one decimal place... */
  9899. if (Char == ".") {
  9900. if (bDecimal) {
  9901. return null;
  9902. }
  9903. bDecimal = true;
  9904. }
  9905. }
  9906. return 'numeric';
  9907. },
  9908. /*
  9909. * Function: -
  9910. * Purpose: Check to see if a string is actually a formatted date
  9911. * Returns: string:'date' or null
  9912. * Inputs: string:sText - string to check
  9913. */
  9914. function (sData) {
  9915. var iParse = Date.parse(sData);
  9916. if ((iParse !== null && !isNaN(iParse)) || (typeof sData === 'string' && sData.length === 0)) {
  9917. return 'date';
  9918. }
  9919. return null;
  9920. },
  9921. /*
  9922. * Function: -
  9923. * Purpose: Check to see if a string should be treated as an HTML string
  9924. * Returns: string:'html' or null
  9925. * Inputs: string:sText - string to check
  9926. */
  9927. function (sData) {
  9928. if (typeof sData === 'string' && sData.indexOf('<') != -1 && sData.indexOf('>') != -1) {
  9929. return 'html';
  9930. }
  9931. return null;
  9932. }
  9933. ]);
  9934. // jQuery aliases
  9935. $.fn.DataTable = DataTable;
  9936. $.fn.dataTable = DataTable;
  9937. $.fn.dataTableSettings = DataTable.settings;
  9938. $.fn.dataTableExt = DataTable.ext;
  9939. // Information about events fired by DataTables - for documentation.
  9940. /**
  9941. * Draw event, fired whenever the table is redrawn on the page, at the same point as
  9942. * fnDrawCallback. This may be useful for binding events or performing calculations when
  9943. * the table is altered at all.
  9944. * @name DataTable#draw
  9945. * @event
  9946. * @param {event} e jQuery event object
  9947. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  9948. */
  9949. /**
  9950. * Filter event, fired when the filtering applied to the table (using the build in global
  9951. * global filter, or column filters) is altered.
  9952. * @name DataTable#filter
  9953. * @event
  9954. * @param {event} e jQuery event object
  9955. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  9956. */
  9957. /**
  9958. * Page change event, fired when the paging of the table is altered.
  9959. * @name DataTable#page
  9960. * @event
  9961. * @param {event} e jQuery event object
  9962. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  9963. */
  9964. /**
  9965. * Sort event, fired when the sorting applied to the table is altered.
  9966. * @name DataTable#sort
  9967. * @event
  9968. * @param {event} e jQuery event object
  9969. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  9970. */
  9971. /**
  9972. * DataTables initialisation complete event, fired when the table is fully drawn,
  9973. * including Ajax data loaded, if Ajax data is required.
  9974. * @name DataTable#init
  9975. * @event
  9976. * @param {event} e jQuery event object
  9977. * @param {object} oSettings DataTables settings object
  9978. * @param {object} json The JSON object request from the server - only
  9979. * present if client-side Ajax sourced data is used</li></ol>
  9980. */
  9981. /**
  9982. * State save event, fired when the table has changed state a new state save is required.
  9983. * This method allows modification of the state saving object prior to actually doing the
  9984. * save, including addition or other state properties (for plug-ins) or modification
  9985. * of a DataTables core property.
  9986. * @name DataTable#stateSaveParams
  9987. * @event
  9988. * @param {event} e jQuery event object
  9989. * @param {object} oSettings DataTables settings object
  9990. * @param {object} json The state information to be saved
  9991. */
  9992. /**
  9993. * State load event, fired when the table is loading state from the stored data, but
  9994. * prior to the settings object being modified by the saved state - allowing modification
  9995. * of the saved state is required or loading of state for a plug-in.
  9996. * @name DataTable#stateLoadParams
  9997. * @event
  9998. * @param {event} e jQuery event object
  9999. * @param {object} oSettings DataTables settings object
  10000. * @param {object} json The saved state information
  10001. */
  10002. /**
  10003. * State loaded event, fired when state has been loaded from stored data and the settings
  10004. * object has been modified by the loaded data.
  10005. * @name DataTable#stateLoaded
  10006. * @event
  10007. * @param {event} e jQuery event object
  10008. * @param {object} oSettings DataTables settings object
  10009. * @param {object} json The saved state information
  10010. */
  10011. /**
  10012. * Processing event, fired when DataTables is doing some kind of processing (be it,
  10013. * sort, filter or anything else). Can be used to indicate to the end user that
  10014. * there is something happening, or that something has finished.
  10015. * @name DataTable#processing
  10016. * @event
  10017. * @param {event} e jQuery event object
  10018. * @param {object} oSettings DataTables settings object
  10019. * @param {boolean} bShow Flag for if DataTables is doing processing or not
  10020. */
  10021. /**
  10022. * Ajax (XHR) event, fired whenever an Ajax request is completed from a request to
  10023. * made to the server for new data (note that this trigger is called in fnServerData,
  10024. * if you override fnServerData and which to use this event, you need to trigger it in
  10025. * you success function).
  10026. * @name DataTable#xhr
  10027. * @event
  10028. * @param {event} e jQuery event object
  10029. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10030. * @param {object} json JSON returned from the server
  10031. */
  10032. /**
  10033. * Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing
  10034. * the bDestroy:true parameter in the initialisation object. This can be used to remove
  10035. * bound events, added DOM nodes, etc.
  10036. * @name DataTable#destroy
  10037. * @event
  10038. * @param {event} e jQuery event object
  10039. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10040. */
  10041. }));
  10042. }(window, document));