jquery.dataTables.js 420 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275
  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. for ( var i=0, len=aData.length ; i<len ; i++ ) {
  1807. aData[i] = _fnDataToSearch( aData[i], oSettings.aoColumns[i].sType );
  1808. }
  1809. var sSearch = aData.join(' ');
  1810. /* If it looks like there is an HTML entity in the string, attempt to decode it */
  1811. if (sSearch.indexOf('&') !== -1) {
  1812. sSearch = $('<div>').html(sSearch).text();
  1813. }
  1814. // Strip newline characters
  1815. return sSearch.replace(/[\n\r]/g, " ");
  1816. }
  1817. /**
  1818. * Build a regular expression object suitable for searching a table
  1819. * @param {string} sSearch string to search for
  1820. * @param {bool} bRegex treat as a regular expression or not
  1821. * @param {bool} bSmart perform smart filtering or not
  1822. * @param {bool} bCaseInsensitive Do case insensitive matching or not
  1823. * @returns {RegExp} constructed object
  1824. * @memberof DataTable#oApi
  1825. */
  1826. function _fnFilterCreateSearch(sSearch, bRegex, bSmart, bCaseInsensitive) {
  1827. var asSearch, sRegExpString;
  1828. if (bSmart) {
  1829. /* Generate the regular expression to use. Something along the lines of:
  1830. * ^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$
  1831. */
  1832. asSearch = bRegex ? sSearch.split(' ') : _fnEscapeRegex(sSearch).split(' ');
  1833. sRegExpString = '^(?=.*?' + asSearch.join(')(?=.*?') + ').*$';
  1834. return new RegExp(sRegExpString, bCaseInsensitive ? "i" : "");
  1835. }
  1836. else {
  1837. sSearch = bRegex ? sSearch : _fnEscapeRegex(sSearch);
  1838. return new RegExp(sSearch, bCaseInsensitive ? "i" : "");
  1839. }
  1840. }
  1841. /**
  1842. * Convert raw data into something that the user can search on
  1843. * @param {string} sData data to be modified
  1844. * @param {string} sType data type
  1845. * @returns {string} search string
  1846. * @memberof DataTable#oApi
  1847. */
  1848. function _fnDataToSearch(sData, sType) {
  1849. if (typeof DataTable.ext.ofnSearch[sType] === "function") {
  1850. return DataTable.ext.ofnSearch[sType](sData);
  1851. }
  1852. else if (sData === null) {
  1853. return '';
  1854. }
  1855. else if (sType == "html") {
  1856. return sData.replace(/[\r\n]/g, " ").replace(/<.*?>/g, "");
  1857. }
  1858. else if (typeof sData === "string") {
  1859. return sData.replace(/[\r\n]/g, " ");
  1860. }
  1861. return sData;
  1862. }
  1863. /**
  1864. * scape a string such that it can be used in a regular expression
  1865. * @param {string} sVal string to escape
  1866. * @returns {string} escaped string
  1867. * @memberof DataTable#oApi
  1868. */
  1869. function _fnEscapeRegex(sVal) {
  1870. var acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ];
  1871. var reReplace = new RegExp('(\\' + acEscape.join('|\\') + ')', 'g');
  1872. return sVal.replace(reReplace, '\\$1');
  1873. }
  1874. /**
  1875. * Generate the node required for the info display
  1876. * @param {object} oSettings dataTables settings object
  1877. * @returns {node} Information element
  1878. * @memberof DataTable#oApi
  1879. */
  1880. function _fnFeatureHtmlInfo(oSettings) {
  1881. var nInfo = document.createElement('div');
  1882. nInfo.className = oSettings.oClasses.sInfo;
  1883. /* Actions that are to be taken once only for this feature */
  1884. if (!oSettings.aanFeatures.i) {
  1885. /* Add draw callback */
  1886. oSettings.aoDrawCallback.push({
  1887. "fn":_fnUpdateInfo,
  1888. "sName":"information"
  1889. });
  1890. /* Add id */
  1891. nInfo.id = oSettings.sTableId + '_info';
  1892. }
  1893. oSettings.nTable.setAttribute('aria-describedby', oSettings.sTableId + '_info');
  1894. return nInfo;
  1895. }
  1896. /**
  1897. * Update the information elements in the display
  1898. * @param {object} oSettings dataTables settings object
  1899. * @memberof DataTable#oApi
  1900. */
  1901. function _fnUpdateInfo(oSettings) {
  1902. /* Show information about the table */
  1903. if (!oSettings.oFeatures.bInfo || oSettings.aanFeatures.i.length === 0) {
  1904. return;
  1905. }
  1906. var
  1907. oLang = oSettings.oLanguage,
  1908. iStart = oSettings._iDisplayStart + 1,
  1909. iEnd = oSettings.fnDisplayEnd(),
  1910. iMax = oSettings.fnRecordsTotal(),
  1911. iTotal = oSettings.fnRecordsDisplay(),
  1912. sOut;
  1913. if (iTotal === 0) {
  1914. /* Empty record set */
  1915. sOut = oLang.sInfoEmpty;
  1916. }
  1917. else {
  1918. /* Normal record set */
  1919. sOut = oLang.sInfo;
  1920. }
  1921. if (iTotal != iMax) {
  1922. /* Record set after filtering */
  1923. sOut += ' ' + oLang.sInfoFiltered;
  1924. }
  1925. // Convert the macros
  1926. sOut += oLang.sInfoPostFix;
  1927. sOut = _fnInfoMacros(oSettings, sOut);
  1928. if (oLang.fnInfoCallback !== null) {
  1929. sOut = oLang.fnInfoCallback.call(oSettings.oInstance,
  1930. oSettings, iStart, iEnd, iMax, iTotal, sOut);
  1931. }
  1932. var n = oSettings.aanFeatures.i;
  1933. for (var i = 0, iLen = n.length; i < iLen; i++) {
  1934. $(n[i]).html(sOut);
  1935. }
  1936. }
  1937. function _fnInfoMacros(oSettings, str) {
  1938. var
  1939. iStart = oSettings._iDisplayStart + 1,
  1940. sStart = oSettings.fnFormatNumber(iStart),
  1941. iEnd = oSettings.fnDisplayEnd(),
  1942. sEnd = oSettings.fnFormatNumber(iEnd),
  1943. iTotal = oSettings.fnRecordsDisplay(),
  1944. sTotal = oSettings.fnFormatNumber(iTotal),
  1945. iMax = oSettings.fnRecordsTotal(),
  1946. sMax = oSettings.fnFormatNumber(iMax);
  1947. // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
  1948. // internally
  1949. if (oSettings.oScroll.bInfinite) {
  1950. sStart = oSettings.fnFormatNumber(1);
  1951. }
  1952. return str.
  1953. replace(/_START_/g, sStart).
  1954. replace(/_END_/g, sEnd).
  1955. replace(/_TOTAL_/g, sTotal).
  1956. replace(/_MAX_/g, sMax);
  1957. }
  1958. /**
  1959. * Draw the table for the first time, adding all required features
  1960. * @param {object} oSettings dataTables settings object
  1961. * @memberof DataTable#oApi
  1962. */
  1963. function _fnInitialise(oSettings) {
  1964. var i, iLen, iAjaxStart = oSettings.iInitDisplayStart;
  1965. /* Ensure that the table data is fully initialised */
  1966. if (oSettings.bInitialised === false) {
  1967. setTimeout(function () {
  1968. _fnInitialise(oSettings);
  1969. }, 200);
  1970. return;
  1971. }
  1972. /* Show the display HTML options */
  1973. _fnAddOptionsHtml(oSettings);
  1974. /* Build and draw the header / footer for the table */
  1975. _fnBuildHead(oSettings);
  1976. _fnDrawHead(oSettings, oSettings.aoHeader);
  1977. if (oSettings.nTFoot) {
  1978. _fnDrawHead(oSettings, oSettings.aoFooter);
  1979. }
  1980. /* Okay to show that something is going on now */
  1981. _fnProcessingDisplay(oSettings, true);
  1982. /* Calculate sizes for columns */
  1983. if (oSettings.oFeatures.bAutoWidth) {
  1984. _fnCalculateColumnWidths(oSettings);
  1985. }
  1986. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  1987. if (oSettings.aoColumns[i].sWidth !== null) {
  1988. oSettings.aoColumns[i].nTh.style.width = _fnStringToCss(oSettings.aoColumns[i].sWidth);
  1989. }
  1990. }
  1991. /* If there is default sorting required - let's do it. The sort function will do the
  1992. * drawing for us. Otherwise we draw the table regardless of the Ajax source - this allows
  1993. * the table to look initialised for Ajax sourcing data (show 'loading' message possibly)
  1994. */
  1995. if (oSettings.oFeatures.bSort) {
  1996. _fnSort(oSettings);
  1997. }
  1998. else if (oSettings.oFeatures.bFilter) {
  1999. _fnFilterComplete(oSettings, oSettings.oPreviousSearch);
  2000. }
  2001. else {
  2002. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  2003. _fnCalculateEnd(oSettings);
  2004. _fnDraw(oSettings);
  2005. }
  2006. /* if there is an ajax source load the data */
  2007. if (oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide) {
  2008. var aoData = [];
  2009. _fnServerParams(oSettings, aoData);
  2010. oSettings.fnServerData.call(oSettings.oInstance, oSettings.sAjaxSource, aoData, function (json) {
  2011. var aData = (oSettings.sAjaxDataProp !== "") ?
  2012. _fnGetObjectDataFn(oSettings.sAjaxDataProp)(json) : json;
  2013. /* Got the data - add it to the table */
  2014. for (i = 0; i < aData.length; i++) {
  2015. _fnAddData(oSettings, aData[i]);
  2016. }
  2017. /* Reset the init display for cookie saving. We've already done a filter, and
  2018. * therefore cleared it before. So we need to make it appear 'fresh'
  2019. */
  2020. oSettings.iInitDisplayStart = iAjaxStart;
  2021. if (oSettings.oFeatures.bSort) {
  2022. _fnSort(oSettings);
  2023. }
  2024. else {
  2025. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  2026. _fnCalculateEnd(oSettings);
  2027. _fnDraw(oSettings);
  2028. }
  2029. _fnProcessingDisplay(oSettings, false);
  2030. _fnInitComplete(oSettings, json);
  2031. }, oSettings);
  2032. return;
  2033. }
  2034. /* Server-side processing initialisation complete is done at the end of _fnDraw */
  2035. if (!oSettings.oFeatures.bServerSide) {
  2036. _fnProcessingDisplay(oSettings, false);
  2037. _fnInitComplete(oSettings);
  2038. }
  2039. }
  2040. /**
  2041. * Draw the table for the first time, adding all required features
  2042. * @param {object} oSettings dataTables settings object
  2043. * @param {object} [json] JSON from the server that completed the table, if using Ajax source
  2044. * with client-side processing (optional)
  2045. * @memberof DataTable#oApi
  2046. */
  2047. function _fnInitComplete(oSettings, json) {
  2048. oSettings._bInitComplete = true;
  2049. _fnCallbackFire(oSettings, 'aoInitComplete', 'init', [oSettings, json]);
  2050. }
  2051. /**
  2052. * Language compatibility - when certain options are given, and others aren't, we
  2053. * need to duplicate the values over, in order to provide backwards compatibility
  2054. * with older language files.
  2055. * @param {object} oSettings dataTables settings object
  2056. * @memberof DataTable#oApi
  2057. */
  2058. function _fnLanguageCompat(oLanguage) {
  2059. var oDefaults = DataTable.defaults.oLanguage;
  2060. /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
  2061. * sZeroRecords - assuming that is given.
  2062. */
  2063. if (!oLanguage.sEmptyTable && oLanguage.sZeroRecords &&
  2064. oDefaults.sEmptyTable === "No data available in table") {
  2065. _fnMap(oLanguage, oLanguage, 'sZeroRecords', 'sEmptyTable');
  2066. }
  2067. /* Likewise with loading records */
  2068. if (!oLanguage.sLoadingRecords && oLanguage.sZeroRecords &&
  2069. oDefaults.sLoadingRecords === "Loading...") {
  2070. _fnMap(oLanguage, oLanguage, 'sZeroRecords', 'sLoadingRecords');
  2071. }
  2072. }
  2073. /**
  2074. * Generate the node required for user display length changing
  2075. * @param {object} oSettings dataTables settings object
  2076. * @returns {node} Display length feature node
  2077. * @memberof DataTable#oApi
  2078. */
  2079. function _fnFeatureHtmlLength(oSettings) {
  2080. if (oSettings.oScroll.bInfinite) {
  2081. return null;
  2082. }
  2083. /* This can be overruled by not using the _MENU_ var/macro in the language variable */
  2084. var sName = 'name="' + oSettings.sTableId + '_length"';
  2085. var sStdMenu = '<select size="1" ' + sName + '>';
  2086. var i, iLen;
  2087. var aLengthMenu = oSettings.aLengthMenu;
  2088. if (aLengthMenu.length == 2 && typeof aLengthMenu[0] === 'object' &&
  2089. typeof aLengthMenu[1] === 'object') {
  2090. for (i = 0, iLen = aLengthMenu[0].length; i < iLen; i++) {
  2091. sStdMenu += '<option value="' + aLengthMenu[0][i] + '">' + aLengthMenu[1][i] + '</option>';
  2092. }
  2093. }
  2094. else {
  2095. for (i = 0, iLen = aLengthMenu.length; i < iLen; i++) {
  2096. sStdMenu += '<option value="' + aLengthMenu[i] + '">' + aLengthMenu[i] + '</option>';
  2097. }
  2098. }
  2099. sStdMenu += '</select>';
  2100. var nLength = document.createElement('div');
  2101. if (!oSettings.aanFeatures.l) {
  2102. nLength.id = oSettings.sTableId + '_length';
  2103. }
  2104. nLength.className = oSettings.oClasses.sLength;
  2105. nLength.innerHTML = '<label>' + oSettings.oLanguage.sLengthMenu.replace('_MENU_', sStdMenu) + '</label>';
  2106. /*
  2107. * Set the length to the current display length - thanks to Andrea Pavlovic for this fix,
  2108. * and Stefan Skopnik for fixing the fix!
  2109. */
  2110. $('select option[value="' + oSettings._iDisplayLength + '"]', nLength).attr("selected", true);
  2111. $('select', nLength).bind('change.DT', function (e) {
  2112. var iVal = $(this).val();
  2113. /* Update all other length options for the new display */
  2114. var n = oSettings.aanFeatures.l;
  2115. for (i = 0, iLen = n.length; i < iLen; i++) {
  2116. if (n[i] != this.parentNode) {
  2117. $('select', n[i]).val(iVal);
  2118. }
  2119. }
  2120. /* Redraw the table */
  2121. oSettings._iDisplayLength = parseInt(iVal, 10);
  2122. _fnCalculateEnd(oSettings);
  2123. /* If we have space to show extra rows (backing up from the end point - then do so */
  2124. if (oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay()) {
  2125. oSettings._iDisplayStart = oSettings.fnDisplayEnd() - oSettings._iDisplayLength;
  2126. if (oSettings._iDisplayStart < 0) {
  2127. oSettings._iDisplayStart = 0;
  2128. }
  2129. }
  2130. if (oSettings._iDisplayLength == -1) {
  2131. oSettings._iDisplayStart = 0;
  2132. }
  2133. _fnDraw(oSettings);
  2134. });
  2135. $('select', nLength).attr('aria-controls', oSettings.sTableId);
  2136. return nLength;
  2137. }
  2138. /**
  2139. * Recalculate the end point based on the start point
  2140. * @param {object} oSettings dataTables settings object
  2141. * @memberof DataTable#oApi
  2142. */
  2143. function _fnCalculateEnd(oSettings) {
  2144. if (oSettings.oFeatures.bPaginate === false) {
  2145. oSettings._iDisplayEnd = oSettings.aiDisplay.length;
  2146. }
  2147. else {
  2148. /* Set the end point of the display - based on how many elements there are
  2149. * still to display
  2150. */
  2151. if (oSettings._iDisplayStart + oSettings._iDisplayLength > oSettings.aiDisplay.length ||
  2152. oSettings._iDisplayLength == -1) {
  2153. oSettings._iDisplayEnd = oSettings.aiDisplay.length;
  2154. }
  2155. else {
  2156. oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength;
  2157. }
  2158. }
  2159. }
  2160. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2161. * Note that most of the paging logic is done in
  2162. * DataTable.ext.oPagination
  2163. */
  2164. /**
  2165. * Generate the node required for default pagination
  2166. * @param {object} oSettings dataTables settings object
  2167. * @returns {node} Pagination feature node
  2168. * @memberof DataTable#oApi
  2169. */
  2170. function _fnFeatureHtmlPaginate(oSettings) {
  2171. if (oSettings.oScroll.bInfinite) {
  2172. return null;
  2173. }
  2174. var nPaginate = document.createElement('div');
  2175. nPaginate.className = oSettings.oClasses.sPaging + oSettings.sPaginationType;
  2176. DataTable.ext.oPagination[ oSettings.sPaginationType ].fnInit(oSettings, nPaginate,
  2177. function (oSettings) {
  2178. _fnCalculateEnd(oSettings);
  2179. _fnDraw(oSettings);
  2180. }
  2181. );
  2182. /* Add a draw callback for the pagination on first instance, to update the paging display */
  2183. if (!oSettings.aanFeatures.p) {
  2184. oSettings.aoDrawCallback.push({
  2185. "fn":function (oSettings) {
  2186. DataTable.ext.oPagination[ oSettings.sPaginationType ].fnUpdate(oSettings, function (oSettings) {
  2187. _fnCalculateEnd(oSettings);
  2188. _fnDraw(oSettings);
  2189. });
  2190. },
  2191. "sName":"pagination"
  2192. });
  2193. }
  2194. return nPaginate;
  2195. }
  2196. /**
  2197. * Alter the display settings to change the page
  2198. * @param {object} oSettings dataTables settings object
  2199. * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
  2200. * or page number to jump to (integer)
  2201. * @returns {bool} true page has changed, false - no change (no effect) eg 'first' on page 1
  2202. * @memberof DataTable#oApi
  2203. */
  2204. function _fnPageChange(oSettings, mAction) {
  2205. var iOldStart = oSettings._iDisplayStart;
  2206. if (typeof mAction === "number") {
  2207. oSettings._iDisplayStart = mAction * oSettings._iDisplayLength;
  2208. if (oSettings._iDisplayStart > oSettings.fnRecordsDisplay()) {
  2209. oSettings._iDisplayStart = 0;
  2210. }
  2211. }
  2212. else if (mAction == "first") {
  2213. oSettings._iDisplayStart = 0;
  2214. }
  2215. else if (mAction == "previous") {
  2216. oSettings._iDisplayStart = oSettings._iDisplayLength >= 0 ?
  2217. oSettings._iDisplayStart - oSettings._iDisplayLength :
  2218. 0;
  2219. /* Correct for under-run */
  2220. if (oSettings._iDisplayStart < 0) {
  2221. oSettings._iDisplayStart = 0;
  2222. }
  2223. }
  2224. else if (mAction == "next") {
  2225. if (oSettings._iDisplayLength >= 0) {
  2226. /* Make sure we are not over running the display array */
  2227. if (oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay()) {
  2228. oSettings._iDisplayStart += oSettings._iDisplayLength;
  2229. }
  2230. }
  2231. else {
  2232. oSettings._iDisplayStart = 0;
  2233. }
  2234. }
  2235. else if (mAction == "last") {
  2236. if (oSettings._iDisplayLength >= 0) {
  2237. var iPages = parseInt((oSettings.fnRecordsDisplay() - 1) / oSettings._iDisplayLength, 10) + 1;
  2238. oSettings._iDisplayStart = (iPages - 1) * oSettings._iDisplayLength;
  2239. }
  2240. else {
  2241. oSettings._iDisplayStart = 0;
  2242. }
  2243. }
  2244. else {
  2245. _fnLog(oSettings, 0, "Unknown paging action: " + mAction);
  2246. }
  2247. $(oSettings.oInstance).trigger('page', oSettings);
  2248. return iOldStart != oSettings._iDisplayStart;
  2249. }
  2250. /**
  2251. * Generate the node required for the processing node
  2252. * @param {object} oSettings dataTables settings object
  2253. * @returns {node} Processing element
  2254. * @memberof DataTable#oApi
  2255. */
  2256. function _fnFeatureHtmlProcessing(oSettings) {
  2257. var nProcessing = document.createElement('div');
  2258. if (!oSettings.aanFeatures.r) {
  2259. nProcessing.id = oSettings.sTableId + '_processing';
  2260. }
  2261. nProcessing.innerHTML = oSettings.oLanguage.sProcessing;
  2262. nProcessing.className = oSettings.oClasses.sProcessing;
  2263. oSettings.nTable.parentNode.insertBefore(nProcessing, oSettings.nTable);
  2264. return nProcessing;
  2265. }
  2266. /**
  2267. * Display or hide the processing indicator
  2268. * @param {object} oSettings dataTables settings object
  2269. * @param {bool} bShow Show the processing indicator (true) or not (false)
  2270. * @memberof DataTable#oApi
  2271. */
  2272. function _fnProcessingDisplay(oSettings, bShow) {
  2273. if (oSettings.oFeatures.bProcessing) {
  2274. var an = oSettings.aanFeatures.r;
  2275. for (var i = 0, iLen = an.length; i < iLen; i++) {
  2276. an[i].style.visibility = bShow ? "visible" : "hidden";
  2277. }
  2278. }
  2279. $(oSettings.oInstance).trigger('processing', [oSettings, bShow]);
  2280. }
  2281. /**
  2282. * Add any control elements for the table - specifically scrolling
  2283. * @param {object} oSettings dataTables settings object
  2284. * @returns {node} Node to add to the DOM
  2285. * @memberof DataTable#oApi
  2286. */
  2287. function _fnFeatureHtmlTable(oSettings) {
  2288. /* Check if scrolling is enabled or not - if not then leave the DOM unaltered */
  2289. if (oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "") {
  2290. return oSettings.nTable;
  2291. }
  2292. /*
  2293. * The HTML structure that we want to generate in this function is:
  2294. * div - nScroller
  2295. * div - nScrollHead
  2296. * div - nScrollHeadInner
  2297. * table - nScrollHeadTable
  2298. * thead - nThead
  2299. * div - nScrollBody
  2300. * table - oSettings.nTable
  2301. * thead - nTheadSize
  2302. * tbody - nTbody
  2303. * div - nScrollFoot
  2304. * div - nScrollFootInner
  2305. * table - nScrollFootTable
  2306. * tfoot - nTfoot
  2307. */
  2308. var
  2309. nScroller = document.createElement('div'),
  2310. nScrollHead = document.createElement('div'),
  2311. nScrollHeadInner = document.createElement('div'),
  2312. nScrollBody = document.createElement('div'),
  2313. nScrollFoot = document.createElement('div'),
  2314. nScrollFootInner = document.createElement('div'),
  2315. nScrollHeadTable = oSettings.nTable.cloneNode(false),
  2316. nScrollFootTable = oSettings.nTable.cloneNode(false),
  2317. nThead = oSettings.nTable.getElementsByTagName('thead')[0],
  2318. nTfoot = oSettings.nTable.getElementsByTagName('tfoot').length === 0 ? null :
  2319. oSettings.nTable.getElementsByTagName('tfoot')[0],
  2320. oClasses = oSettings.oClasses;
  2321. nScrollHead.appendChild(nScrollHeadInner);
  2322. nScrollFoot.appendChild(nScrollFootInner);
  2323. nScrollBody.appendChild(oSettings.nTable);
  2324. nScroller.appendChild(nScrollHead);
  2325. nScroller.appendChild(nScrollBody);
  2326. nScrollHeadInner.appendChild(nScrollHeadTable);
  2327. nScrollHeadTable.appendChild(nThead);
  2328. if (nTfoot !== null) {
  2329. nScroller.appendChild(nScrollFoot);
  2330. nScrollFootInner.appendChild(nScrollFootTable);
  2331. nScrollFootTable.appendChild(nTfoot);
  2332. }
  2333. nScroller.className = oClasses.sScrollWrapper;
  2334. nScrollHead.className = oClasses.sScrollHead;
  2335. nScrollHeadInner.className = oClasses.sScrollHeadInner;
  2336. nScrollBody.className = oClasses.sScrollBody;
  2337. nScrollFoot.className = oClasses.sScrollFoot;
  2338. nScrollFootInner.className = oClasses.sScrollFootInner;
  2339. if (oSettings.oScroll.bAutoCss) {
  2340. nScrollHead.style.overflow = "hidden";
  2341. nScrollHead.style.position = "relative";
  2342. nScrollFoot.style.overflow = "hidden";
  2343. nScrollBody.style.overflow = "auto";
  2344. }
  2345. nScrollHead.style.border = "0";
  2346. nScrollHead.style.width = "100%";
  2347. nScrollFoot.style.border = "0";
  2348. nScrollHeadInner.style.width = oSettings.oScroll.sXInner !== "" ?
  2349. oSettings.oScroll.sXInner : "100%";
  2350. /* will be overwritten */
  2351. /* Modify attributes to respect the clones */
  2352. nScrollHeadTable.removeAttribute('id');
  2353. nScrollHeadTable.style.marginLeft = "0";
  2354. oSettings.nTable.style.marginLeft = "0";
  2355. if (nTfoot !== null) {
  2356. nScrollFootTable.removeAttribute('id');
  2357. nScrollFootTable.style.marginLeft = "0";
  2358. }
  2359. /* Move caption elements from the body to the header, footer or leave where it is
  2360. * depending on the configuration. Note that the DTD says there can be only one caption */
  2361. var nCaption = $(oSettings.nTable).children('caption');
  2362. if (nCaption.length > 0) {
  2363. nCaption = nCaption[0];
  2364. if (nCaption._captionSide === "top") {
  2365. nScrollHeadTable.appendChild(nCaption);
  2366. }
  2367. else if (nCaption._captionSide === "bottom" && nTfoot) {
  2368. nScrollFootTable.appendChild(nCaption);
  2369. }
  2370. }
  2371. /*
  2372. * Sizing
  2373. */
  2374. /* When x-scrolling add the width and a scroller to move the header with the body */
  2375. if (oSettings.oScroll.sX !== "") {
  2376. nScrollHead.style.width = _fnStringToCss(oSettings.oScroll.sX);
  2377. nScrollBody.style.width = _fnStringToCss(oSettings.oScroll.sX);
  2378. if (nTfoot !== null) {
  2379. nScrollFoot.style.width = _fnStringToCss(oSettings.oScroll.sX);
  2380. }
  2381. /* When the body is scrolled, then we also want to scroll the headers */
  2382. $(nScrollBody).scroll(function (e) {
  2383. nScrollHead.scrollLeft = this.scrollLeft;
  2384. if (nTfoot !== null) {
  2385. nScrollFoot.scrollLeft = this.scrollLeft;
  2386. }
  2387. });
  2388. }
  2389. /* When yscrolling, add the height */
  2390. if (oSettings.oScroll.sY !== "") {
  2391. nScrollBody.style.height = _fnStringToCss(oSettings.oScroll.sY);
  2392. }
  2393. /* Redraw - align columns across the tables */
  2394. oSettings.aoDrawCallback.push({
  2395. "fn":_fnScrollDraw,
  2396. "sName":"scrolling"
  2397. });
  2398. /* Infinite scrolling event handlers */
  2399. if (oSettings.oScroll.bInfinite) {
  2400. $(nScrollBody).scroll(function () {
  2401. /* Use a blocker to stop scrolling from loading more data while other data is still loading */
  2402. if (!oSettings.bDrawing && $(this).scrollTop() !== 0) {
  2403. /* Check if we should load the next data set */
  2404. if ($(this).scrollTop() + $(this).height() >
  2405. $(oSettings.nTable).height() - oSettings.oScroll.iLoadGap) {
  2406. /* Only do the redraw if we have to - we might be at the end of the data */
  2407. if (oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay()) {
  2408. _fnPageChange(oSettings, 'next');
  2409. _fnCalculateEnd(oSettings);
  2410. _fnDraw(oSettings);
  2411. }
  2412. }
  2413. }
  2414. });
  2415. }
  2416. oSettings.nScrollHead = nScrollHead;
  2417. oSettings.nScrollFoot = nScrollFoot;
  2418. return nScroller;
  2419. }
  2420. /**
  2421. * Update the various tables for resizing. It's a bit of a pig this function, but
  2422. * basically the idea to:
  2423. * 1. Re-create the table inside the scrolling div
  2424. * 2. Take live measurements from the DOM
  2425. * 3. Apply the measurements
  2426. * 4. Clean up
  2427. * @param {object} o dataTables settings object
  2428. * @returns {node} Node to add to the DOM
  2429. * @memberof DataTable#oApi
  2430. */
  2431. function _fnScrollDraw(o) {
  2432. var
  2433. nScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0],
  2434. nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],
  2435. nScrollBody = o.nTable.parentNode,
  2436. i, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis,
  2437. nTheadSize, nTfootSize,
  2438. iWidth, aApplied = [], aAppliedFooter = [], iSanityWidth,
  2439. nScrollFootInner = (o.nTFoot !== null) ? o.nScrollFoot.getElementsByTagName('div')[0] : null,
  2440. nScrollFootTable = (o.nTFoot !== null) ? nScrollFootInner.getElementsByTagName('table')[0] : null,
  2441. ie67 = o.oBrowser.bScrollOversize,
  2442. zeroOut = function (nSizer) {
  2443. oStyle = nSizer.style;
  2444. oStyle.paddingTop = "0";
  2445. oStyle.paddingBottom = "0";
  2446. oStyle.borderTopWidth = "0";
  2447. oStyle.borderBottomWidth = "0";
  2448. oStyle.height = 0;
  2449. };
  2450. /*
  2451. * 1. Re-create the table inside the scrolling div
  2452. */
  2453. /* Remove the old minimised thead and tfoot elements in the inner table */
  2454. $(o.nTable).children('thead, tfoot').remove();
  2455. /* Clone the current header and footer elements and then place it into the inner table */
  2456. nTheadSize = $(o.nTHead).clone()[0];
  2457. o.nTable.insertBefore(nTheadSize, o.nTable.childNodes[0]);
  2458. anHeadToSize = o.nTHead.getElementsByTagName('tr');
  2459. anHeadSizers = nTheadSize.getElementsByTagName('tr');
  2460. if (o.nTFoot !== null) {
  2461. nTfootSize = $(o.nTFoot).clone()[0];
  2462. o.nTable.insertBefore(nTfootSize, o.nTable.childNodes[1]);
  2463. anFootToSize = o.nTFoot.getElementsByTagName('tr');
  2464. anFootSizers = nTfootSize.getElementsByTagName('tr');
  2465. }
  2466. /*
  2467. * 2. Take live measurements from the DOM - do not alter the DOM itself!
  2468. */
  2469. /* Remove old sizing and apply the calculated column widths
  2470. * Get the unique column headers in the newly created (cloned) header. We want to apply the
  2471. * calculated sizes to this header
  2472. */
  2473. if (o.oScroll.sX === "") {
  2474. nScrollBody.style.width = '100%';
  2475. nScrollHeadInner.parentNode.style.width = '100%';
  2476. }
  2477. var nThs = _fnGetUniqueThs(o, nTheadSize);
  2478. for (i = 0, iLen = nThs.length; i < iLen; i++) {
  2479. iVis = _fnVisibleToColumnIndex(o, i);
  2480. nThs[i].style.width = o.aoColumns[iVis].sWidth;
  2481. }
  2482. if (o.nTFoot !== null) {
  2483. _fnApplyToChildren(function (n) {
  2484. n.style.width = "";
  2485. }, anFootSizers);
  2486. }
  2487. // If scroll collapse is enabled, when we put the headers back into the body for sizing, we
  2488. // will end up forcing the scrollbar to appear, making our measurements wrong for when we
  2489. // then hide it (end of this function), so add the header height to the body scroller.
  2490. if (o.oScroll.bCollapse && o.oScroll.sY !== "") {
  2491. nScrollBody.style.height = (nScrollBody.offsetHeight + o.nTHead.offsetHeight) + "px";
  2492. }
  2493. /* Size the table as a whole */
  2494. iSanityWidth = $(o.nTable).outerWidth();
  2495. if (o.oScroll.sX === "") {
  2496. /* No x scrolling */
  2497. o.nTable.style.width = "100%";
  2498. /* I know this is rubbish - but IE7 will make the width of the table when 100% include
  2499. * the scrollbar - which is shouldn't. When there is a scrollbar we need to take this
  2500. * into account.
  2501. */
  2502. if (ie67 && ($('tbody', nScrollBody).height() > nScrollBody.offsetHeight ||
  2503. $(nScrollBody).css('overflow-y') == "scroll")) {
  2504. o.nTable.style.width = _fnStringToCss($(o.nTable).outerWidth() - o.oScroll.iBarWidth);
  2505. }
  2506. }
  2507. else {
  2508. if (o.oScroll.sXInner !== "") {
  2509. /* x scroll inner has been given - use it */
  2510. o.nTable.style.width = _fnStringToCss(o.oScroll.sXInner);
  2511. }
  2512. else if (iSanityWidth == $(nScrollBody).width() &&
  2513. $(nScrollBody).height() < $(o.nTable).height()) {
  2514. /* There is y-scrolling - try to take account of the y scroll bar */
  2515. o.nTable.style.width = _fnStringToCss(iSanityWidth - o.oScroll.iBarWidth);
  2516. if ($(o.nTable).outerWidth() > iSanityWidth - o.oScroll.iBarWidth) {
  2517. /* Not possible to take account of it */
  2518. o.nTable.style.width = _fnStringToCss(iSanityWidth);
  2519. }
  2520. }
  2521. else {
  2522. /* All else fails */
  2523. o.nTable.style.width = _fnStringToCss(iSanityWidth);
  2524. }
  2525. }
  2526. /* Recalculate the sanity width - now that we've applied the required width, before it was
  2527. * a temporary variable. This is required because the column width calculation is done
  2528. * before this table DOM is created.
  2529. */
  2530. iSanityWidth = $(o.nTable).outerWidth();
  2531. /* We want the hidden header to have zero height, so remove padding and borders. Then
  2532. * set the width based on the real headers
  2533. */
  2534. // Apply all styles in one pass. Invalidates layout only once because we don't read any
  2535. // DOM properties.
  2536. _fnApplyToChildren(zeroOut, anHeadSizers);
  2537. // Read all widths in next pass. Forces layout only once because we do not change
  2538. // any DOM properties.
  2539. _fnApplyToChildren(function (nSizer) {
  2540. aApplied.push(_fnStringToCss($(nSizer).width()));
  2541. }, anHeadSizers);
  2542. // Apply all widths in final pass. Invalidates layout only once because we do not
  2543. // read any DOM properties.
  2544. _fnApplyToChildren(function (nToSize, i) {
  2545. nToSize.style.width = aApplied[i];
  2546. }, anHeadToSize);
  2547. $(anHeadSizers).height(0);
  2548. /* Same again with the footer if we have one */
  2549. if (o.nTFoot !== null) {
  2550. _fnApplyToChildren(zeroOut, anFootSizers);
  2551. _fnApplyToChildren(function (nSizer) {
  2552. aAppliedFooter.push(_fnStringToCss($(nSizer).width()));
  2553. }, anFootSizers);
  2554. _fnApplyToChildren(function (nToSize, i) {
  2555. nToSize.style.width = aAppliedFooter[i];
  2556. }, anFootToSize);
  2557. $(anFootSizers).height(0);
  2558. }
  2559. /*
  2560. * 3. Apply the measurements
  2561. */
  2562. /* "Hide" the header and footer that we used for the sizing. We want to also fix their width
  2563. * to what they currently are
  2564. */
  2565. _fnApplyToChildren(function (nSizer, i) {
  2566. nSizer.innerHTML = "";
  2567. nSizer.style.width = aApplied[i];
  2568. }, anHeadSizers);
  2569. if (o.nTFoot !== null) {
  2570. _fnApplyToChildren(function (nSizer, i) {
  2571. nSizer.innerHTML = "";
  2572. nSizer.style.width = aAppliedFooter[i];
  2573. }, anFootSizers);
  2574. }
  2575. /* Sanity check that the table is of a sensible width. If not then we are going to get
  2576. * misalignment - try to prevent this by not allowing the table to shrink below its min width
  2577. */
  2578. if ($(o.nTable).outerWidth() < iSanityWidth) {
  2579. /* The min width depends upon if we have a vertical scrollbar visible or not */
  2580. var iCorrection = ((nScrollBody.scrollHeight > nScrollBody.offsetHeight ||
  2581. $(nScrollBody).css('overflow-y') == "scroll")) ?
  2582. iSanityWidth + o.oScroll.iBarWidth : iSanityWidth;
  2583. /* IE6/7 are a law unto themselves... */
  2584. if (ie67 && (nScrollBody.scrollHeight >
  2585. nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll")) {
  2586. o.nTable.style.width = _fnStringToCss(iCorrection - o.oScroll.iBarWidth);
  2587. }
  2588. /* Apply the calculated minimum width to the table wrappers */
  2589. nScrollBody.style.width = _fnStringToCss(iCorrection);
  2590. o.nScrollHead.style.width = _fnStringToCss(iCorrection);
  2591. if (o.nTFoot !== null) {
  2592. o.nScrollFoot.style.width = _fnStringToCss(iCorrection);
  2593. }
  2594. /* And give the user a warning that we've stopped the table getting too small */
  2595. if (o.oScroll.sX === "") {
  2596. _fnLog(o, 1, "The table cannot fit into the current element which will cause column" +
  2597. " misalignment. The table has been drawn at its minimum possible width.");
  2598. }
  2599. else if (o.oScroll.sXInner !== "") {
  2600. _fnLog(o, 1, "The table cannot fit into the current element which will cause column" +
  2601. " misalignment. Increase the sScrollXInner value or remove it to allow automatic" +
  2602. " calculation");
  2603. }
  2604. }
  2605. else {
  2606. nScrollBody.style.width = _fnStringToCss('100%');
  2607. o.nScrollHead.style.width = _fnStringToCss('100%');
  2608. if (o.nTFoot !== null) {
  2609. o.nScrollFoot.style.width = _fnStringToCss('100%');
  2610. }
  2611. }
  2612. /*
  2613. * 4. Clean up
  2614. */
  2615. if (o.oScroll.sY === "") {
  2616. /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
  2617. * the scrollbar height from the visible display, rather than adding it on. We need to
  2618. * set the height in order to sort this. Don't want to do it in any other browsers.
  2619. */
  2620. if (ie67) {
  2621. nScrollBody.style.height = _fnStringToCss(o.nTable.offsetHeight + o.oScroll.iBarWidth);
  2622. }
  2623. }
  2624. if (o.oScroll.sY !== "" && o.oScroll.bCollapse) {
  2625. nScrollBody.style.height = _fnStringToCss(o.oScroll.sY);
  2626. var iExtra = (o.oScroll.sX !== "" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ?
  2627. o.oScroll.iBarWidth : 0;
  2628. if (o.nTable.offsetHeight < nScrollBody.offsetHeight) {
  2629. nScrollBody.style.height = _fnStringToCss(o.nTable.offsetHeight + iExtra);
  2630. }
  2631. }
  2632. /* Finally set the width's of the header and footer tables */
  2633. var iOuterWidth = $(o.nTable).outerWidth();
  2634. nScrollHeadTable.style.width = _fnStringToCss(iOuterWidth);
  2635. nScrollHeadInner.style.width = _fnStringToCss(iOuterWidth);
  2636. // Figure out if there are scrollbar present - if so then we need a the header and footer to
  2637. // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
  2638. var bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll";
  2639. nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth + "px" : "0px";
  2640. if (o.nTFoot !== null) {
  2641. nScrollFootTable.style.width = _fnStringToCss(iOuterWidth);
  2642. nScrollFootInner.style.width = _fnStringToCss(iOuterWidth);
  2643. nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth + "px" : "0px";
  2644. }
  2645. /* Adjust the position of the header in case we loose the y-scrollbar */
  2646. $(nScrollBody).scroll();
  2647. /* If sorting or filtering has occurred, jump the scrolling back to the top */
  2648. if (o.bSorted || o.bFiltered) {
  2649. nScrollBody.scrollTop = 0;
  2650. }
  2651. }
  2652. /**
  2653. * Apply a given function to the display child nodes of an element array (typically
  2654. * TD children of TR rows
  2655. * @param {function} fn Method to apply to the objects
  2656. * @param array {nodes} an1 List of elements to look through for display children
  2657. * @param array {nodes} an2 Another list (identical structure to the first) - optional
  2658. * @memberof DataTable#oApi
  2659. */
  2660. function _fnApplyToChildren(fn, an1, an2) {
  2661. var index = 0, i = 0, iLen = an1.length;
  2662. var nNode1, nNode2;
  2663. while (i < iLen) {
  2664. nNode1 = an1[i].firstChild;
  2665. nNode2 = an2 ? an2[i].firstChild : null;
  2666. while (nNode1) {
  2667. if (nNode1.nodeType === 1) {
  2668. if (an2) {
  2669. fn(nNode1, nNode2, index);
  2670. }
  2671. else {
  2672. fn(nNode1, index);
  2673. }
  2674. index++;
  2675. }
  2676. nNode1 = nNode1.nextSibling;
  2677. nNode2 = an2 ? nNode2.nextSibling : null;
  2678. }
  2679. i++;
  2680. }
  2681. }
  2682. /**
  2683. * Convert a CSS unit width to pixels (e.g. 2em)
  2684. * @param {string} sWidth width to be converted
  2685. * @param {node} nParent parent to get the with for (required for relative widths) - optional
  2686. * @returns {int} iWidth width in pixels
  2687. * @memberof DataTable#oApi
  2688. */
  2689. function _fnConvertToWidth(sWidth, nParent) {
  2690. if (!sWidth || sWidth === null || sWidth === '') {
  2691. return 0;
  2692. }
  2693. if (!nParent) {
  2694. nParent = document.body;
  2695. }
  2696. var iWidth;
  2697. var nTmp = document.createElement("div");
  2698. nTmp.style.width = _fnStringToCss(sWidth);
  2699. nParent.appendChild(nTmp);
  2700. iWidth = nTmp.offsetWidth;
  2701. nParent.removeChild(nTmp);
  2702. return ( iWidth );
  2703. }
  2704. /**
  2705. * Calculate the width of columns for the table
  2706. * @param {object} oSettings dataTables settings object
  2707. * @memberof DataTable#oApi
  2708. */
  2709. function _fnCalculateColumnWidths(oSettings) {
  2710. var iTableWidth = oSettings.nTable.offsetWidth;
  2711. var iUserInputs = 0;
  2712. var iTmpWidth;
  2713. var iVisibleColumns = 0;
  2714. var iColums = oSettings.aoColumns.length;
  2715. var i, iIndex, iCorrector, iWidth;
  2716. var oHeaders = $('th', oSettings.nTHead);
  2717. var widthAttr = oSettings.nTable.getAttribute('width');
  2718. var nWrapper = oSettings.nTable.parentNode;
  2719. /* Convert any user input sizes into pixel sizes */
  2720. for (i = 0; i < iColums; i++) {
  2721. if (oSettings.aoColumns[i].bVisible) {
  2722. iVisibleColumns++;
  2723. if (oSettings.aoColumns[i].sWidth !== null) {
  2724. iTmpWidth = _fnConvertToWidth(oSettings.aoColumns[i].sWidthOrig,
  2725. nWrapper);
  2726. if (iTmpWidth !== null) {
  2727. oSettings.aoColumns[i].sWidth = _fnStringToCss(iTmpWidth);
  2728. }
  2729. iUserInputs++;
  2730. }
  2731. }
  2732. }
  2733. /* If the number of columns in the DOM equals the number that we have to process in
  2734. * DataTables, then we can use the offsets that are created by the web-browser. No custom
  2735. * sizes can be set in order for this to happen, nor scrolling used
  2736. */
  2737. if (iColums == oHeaders.length && iUserInputs === 0 && iVisibleColumns == iColums &&
  2738. oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "") {
  2739. for (i = 0; i < oSettings.aoColumns.length; i++) {
  2740. iTmpWidth = $(oHeaders[i]).width();
  2741. if (iTmpWidth !== null) {
  2742. oSettings.aoColumns[i].sWidth = _fnStringToCss(iTmpWidth);
  2743. }
  2744. }
  2745. }
  2746. else {
  2747. /* Otherwise we are going to have to do some calculations to get the width of each column.
  2748. * Construct a 1 row table with the widest node in the data, and any user defined widths,
  2749. * then insert it into the DOM and allow the browser to do all the hard work of
  2750. * calculating table widths.
  2751. */
  2752. var
  2753. nCalcTmp = oSettings.nTable.cloneNode(false),
  2754. nTheadClone = oSettings.nTHead.cloneNode(true),
  2755. nBody = document.createElement('tbody'),
  2756. nTr = document.createElement('tr'),
  2757. nDivSizing;
  2758. nCalcTmp.removeAttribute("id");
  2759. nCalcTmp.appendChild(nTheadClone);
  2760. if (oSettings.nTFoot !== null) {
  2761. nCalcTmp.appendChild(oSettings.nTFoot.cloneNode(true));
  2762. _fnApplyToChildren(function (n) {
  2763. n.style.width = "";
  2764. }, nCalcTmp.getElementsByTagName('tr'));
  2765. }
  2766. nCalcTmp.appendChild(nBody);
  2767. nBody.appendChild(nTr);
  2768. /* Remove any sizing that was previously applied by the styles */
  2769. var jqColSizing = $('thead th', nCalcTmp);
  2770. if (jqColSizing.length === 0) {
  2771. jqColSizing = $('tbody tr:eq(0)>td', nCalcTmp);
  2772. }
  2773. /* Apply custom sizing to the cloned header */
  2774. var nThs = _fnGetUniqueThs(oSettings, nTheadClone);
  2775. iCorrector = 0;
  2776. for (i = 0; i < iColums; i++) {
  2777. var oColumn = oSettings.aoColumns[i];
  2778. if (oColumn.bVisible && oColumn.sWidthOrig !== null && oColumn.sWidthOrig !== "") {
  2779. nThs[i - iCorrector].style.width = _fnStringToCss(oColumn.sWidthOrig);
  2780. }
  2781. else if (oColumn.bVisible) {
  2782. nThs[i - iCorrector].style.width = "";
  2783. }
  2784. else {
  2785. iCorrector++;
  2786. }
  2787. }
  2788. /* Find the biggest td for each column and put it into the table */
  2789. for (i = 0; i < iColums; i++) {
  2790. if (oSettings.aoColumns[i].bVisible) {
  2791. var nTd = _fnGetWidestNode(oSettings, i);
  2792. if (nTd !== null) {
  2793. nTd = nTd.cloneNode(true);
  2794. if (oSettings.aoColumns[i].sContentPadding !== "") {
  2795. nTd.innerHTML += oSettings.aoColumns[i].sContentPadding;
  2796. }
  2797. nTr.appendChild(nTd);
  2798. }
  2799. }
  2800. }
  2801. /* Build the table and 'display' it */
  2802. nWrapper.appendChild(nCalcTmp);
  2803. /* When scrolling (X or Y) we want to set the width of the table as appropriate. However,
  2804. * when not scrolling leave the table width as it is. This results in slightly different,
  2805. * but I think correct behaviour
  2806. */
  2807. if (oSettings.oScroll.sX !== "" && oSettings.oScroll.sXInner !== "") {
  2808. nCalcTmp.style.width = _fnStringToCss(oSettings.oScroll.sXInner);
  2809. }
  2810. else if (oSettings.oScroll.sX !== "") {
  2811. nCalcTmp.style.width = "";
  2812. if ($(nCalcTmp).width() < nWrapper.offsetWidth) {
  2813. nCalcTmp.style.width = _fnStringToCss(nWrapper.offsetWidth);
  2814. }
  2815. }
  2816. else if (oSettings.oScroll.sY !== "") {
  2817. nCalcTmp.style.width = _fnStringToCss(nWrapper.offsetWidth);
  2818. }
  2819. else if (widthAttr) {
  2820. nCalcTmp.style.width = _fnStringToCss(widthAttr);
  2821. }
  2822. nCalcTmp.style.visibility = "hidden";
  2823. /* Scrolling considerations */
  2824. _fnScrollingWidthAdjust(oSettings, nCalcTmp);
  2825. /* Read the width's calculated by the browser and store them for use by the caller. We
  2826. * first of all try to use the elements in the body, but it is possible that there are
  2827. * no elements there, under which circumstances we use the header elements
  2828. */
  2829. var oNodes = $("tbody tr:eq(0)", nCalcTmp).children();
  2830. if (oNodes.length === 0) {
  2831. oNodes = _fnGetUniqueThs(oSettings, $('thead', nCalcTmp)[0]);
  2832. }
  2833. /* Browsers need a bit of a hand when a width is assigned to any columns when
  2834. * x-scrolling as they tend to collapse the table to the min-width, even if
  2835. * we sent the column widths. So we need to keep track of what the table width
  2836. * should be by summing the user given values, and the automatic values
  2837. */
  2838. if (oSettings.oScroll.sX !== "") {
  2839. var iTotal = 0;
  2840. iCorrector = 0;
  2841. for (i = 0; i < oSettings.aoColumns.length; i++) {
  2842. if (oSettings.aoColumns[i].bVisible) {
  2843. if (oSettings.aoColumns[i].sWidthOrig === null) {
  2844. iTotal += $(oNodes[iCorrector]).outerWidth();
  2845. }
  2846. else {
  2847. iTotal += parseInt(oSettings.aoColumns[i].sWidth.replace('px', ''), 10) +
  2848. ($(oNodes[iCorrector]).outerWidth() - $(oNodes[iCorrector]).width());
  2849. }
  2850. iCorrector++;
  2851. }
  2852. }
  2853. nCalcTmp.style.width = _fnStringToCss(iTotal);
  2854. oSettings.nTable.style.width = _fnStringToCss(iTotal);
  2855. }
  2856. iCorrector = 0;
  2857. for (i = 0; i < oSettings.aoColumns.length; i++) {
  2858. if (oSettings.aoColumns[i].bVisible) {
  2859. iWidth = $(oNodes[iCorrector]).width();
  2860. if (iWidth !== null && iWidth > 0) {
  2861. oSettings.aoColumns[i].sWidth = _fnStringToCss(iWidth);
  2862. }
  2863. iCorrector++;
  2864. }
  2865. }
  2866. var cssWidth = $(nCalcTmp).css('width');
  2867. oSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ?
  2868. cssWidth : _fnStringToCss($(nCalcTmp).outerWidth());
  2869. nCalcTmp.parentNode.removeChild(nCalcTmp);
  2870. }
  2871. if (widthAttr) {
  2872. oSettings.nTable.style.width = _fnStringToCss(widthAttr);
  2873. }
  2874. }
  2875. /**
  2876. * Adjust a table's width to take account of scrolling
  2877. * @param {object} oSettings dataTables settings object
  2878. * @param {node} n table node
  2879. * @memberof DataTable#oApi
  2880. */
  2881. function _fnScrollingWidthAdjust(oSettings, n) {
  2882. if (oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "") {
  2883. /* When y-scrolling only, we want to remove the width of the scroll bar so the table
  2884. * + scroll bar will fit into the area avaialble.
  2885. */
  2886. var iOrigWidth = $(n).width();
  2887. n.style.width = _fnStringToCss($(n).outerWidth() - oSettings.oScroll.iBarWidth);
  2888. }
  2889. else if (oSettings.oScroll.sX !== "") {
  2890. /* When x-scrolling both ways, fix the table at it's current size, without adjusting */
  2891. n.style.width = _fnStringToCss($(n).outerWidth());
  2892. }
  2893. }
  2894. /**
  2895. * Get the widest node
  2896. * @param {object} oSettings dataTables settings object
  2897. * @param {int} iCol column of interest
  2898. * @returns {node} widest table node
  2899. * @memberof DataTable#oApi
  2900. */
  2901. function _fnGetWidestNode(oSettings, iCol) {
  2902. var iMaxIndex = _fnGetMaxLenString(oSettings, iCol);
  2903. if (iMaxIndex < 0) {
  2904. return null;
  2905. }
  2906. if (oSettings.aoData[iMaxIndex].nTr === null) {
  2907. var n = document.createElement('td');
  2908. n.innerHTML = _fnGetCellData(oSettings, iMaxIndex, iCol, '');
  2909. return n;
  2910. }
  2911. return _fnGetTdNodes(oSettings, iMaxIndex)[iCol];
  2912. }
  2913. /**
  2914. * Get the maximum strlen for each data column
  2915. * @param {object} oSettings dataTables settings object
  2916. * @param {int} iCol column of interest
  2917. * @returns {string} max string length for each column
  2918. * @memberof DataTable#oApi
  2919. */
  2920. function _fnGetMaxLenString(oSettings, iCol) {
  2921. var iMax = -1;
  2922. var iMaxIndex = -1;
  2923. for (var i = 0; i < oSettings.aoData.length; i++) {
  2924. var s = _fnGetCellData(oSettings, i, iCol, 'display') + "";
  2925. s = s.replace(/<.*?>/g, "");
  2926. if (s.length > iMax) {
  2927. iMax = s.length;
  2928. iMaxIndex = i;
  2929. }
  2930. }
  2931. return iMaxIndex;
  2932. }
  2933. /**
  2934. * Append a CSS unit (only if required) to a string
  2935. * @param {array} aArray1 first array
  2936. * @param {array} aArray2 second array
  2937. * @returns {int} 0 if match, 1 if length is different, 2 if no match
  2938. * @memberof DataTable#oApi
  2939. */
  2940. function _fnStringToCss(s) {
  2941. if (s === null) {
  2942. return "0px";
  2943. }
  2944. if (typeof s == 'number') {
  2945. if (s < 0) {
  2946. return "0px";
  2947. }
  2948. return s + "px";
  2949. }
  2950. /* Check if the last character is not 0-9 */
  2951. var c = s.charCodeAt(s.length - 1);
  2952. if (c < 0x30 || c > 0x39) {
  2953. return s;
  2954. }
  2955. return s + "px";
  2956. }
  2957. /**
  2958. * Get the width of a scroll bar in this browser being used
  2959. * @returns {int} width in pixels
  2960. * @memberof DataTable#oApi
  2961. */
  2962. function _fnScrollBarWidth() {
  2963. var inner = document.createElement('p');
  2964. var style = inner.style;
  2965. style.width = "100%";
  2966. style.height = "200px";
  2967. style.padding = "0px";
  2968. var outer = document.createElement('div');
  2969. style = outer.style;
  2970. style.position = "absolute";
  2971. style.top = "0px";
  2972. style.left = "0px";
  2973. style.visibility = "hidden";
  2974. style.width = "200px";
  2975. style.height = "150px";
  2976. style.padding = "0px";
  2977. style.overflow = "hidden";
  2978. outer.appendChild(inner);
  2979. document.body.appendChild(outer);
  2980. var w1 = inner.offsetWidth;
  2981. outer.style.overflow = 'scroll';
  2982. var w2 = inner.offsetWidth;
  2983. if (w1 == w2) {
  2984. w2 = outer.clientWidth;
  2985. }
  2986. document.body.removeChild(outer);
  2987. return (w1 - w2);
  2988. }
  2989. /**
  2990. * Change the order of the table
  2991. * @param {object} oSettings dataTables settings object
  2992. * @param {bool} bApplyClasses optional - should we apply classes or not
  2993. * @memberof DataTable#oApi
  2994. */
  2995. function _fnSort(oSettings, bApplyClasses) {
  2996. var
  2997. i, iLen, j, jLen, k, kLen,
  2998. sDataType, nTh,
  2999. aaSort = [],
  3000. aiOrig = [],
  3001. oSort = DataTable.ext.oSort,
  3002. aoData = oSettings.aoData,
  3003. aoColumns = oSettings.aoColumns,
  3004. oAria = oSettings.oLanguage.oAria;
  3005. /* No sorting required if server-side or no sorting array */
  3006. if (!oSettings.oFeatures.bServerSide &&
  3007. (oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null)) {
  3008. aaSort = ( oSettings.aaSortingFixed !== null ) ?
  3009. oSettings.aaSortingFixed.concat(oSettings.aaSorting) :
  3010. oSettings.aaSorting.slice();
  3011. /* If there is a sorting data type, and a function belonging to it, then we need to
  3012. * get the data from the developer's function and apply it for this column
  3013. */
  3014. for (i = 0; i < aaSort.length; i++) {
  3015. var iColumn = aaSort[i][0];
  3016. var iVisColumn = _fnColumnIndexToVisible(oSettings, iColumn);
  3017. sDataType = oSettings.aoColumns[ iColumn ].sSortDataType;
  3018. if (DataTable.ext.afnSortData[sDataType]) {
  3019. var aData = DataTable.ext.afnSortData[sDataType].call(
  3020. oSettings.oInstance, oSettings, iColumn, iVisColumn
  3021. );
  3022. if (aData.length === aoData.length) {
  3023. for (j = 0, jLen = aoData.length; j < jLen; j++) {
  3024. _fnSetCellData(oSettings, j, iColumn, aData[j]);
  3025. }
  3026. }
  3027. else {
  3028. _fnLog(oSettings, 0, "Returned data sort array (col " + iColumn + ") is the wrong length");
  3029. }
  3030. }
  3031. }
  3032. /* Create a value - key array of the current row positions such that we can use their
  3033. * current position during the sort, if values match, in order to perform stable sorting
  3034. */
  3035. for (i = 0, iLen = oSettings.aiDisplayMaster.length; i < iLen; i++) {
  3036. aiOrig[ oSettings.aiDisplayMaster[i] ] = i;
  3037. }
  3038. /* Build an internal data array which is specific to the sort, so we can get and prep
  3039. * the data to be sorted only once, rather than needing to do it every time the sorting
  3040. * function runs. This make the sorting function a very simple comparison
  3041. */
  3042. var iSortLen = aaSort.length;
  3043. var fnSortFormat, aDataSort;
  3044. for (i = 0, iLen = aoData.length; i < iLen; i++) {
  3045. for (j = 0; j < iSortLen; j++) {
  3046. aDataSort = aoColumns[ aaSort[j][0] ].aDataSort;
  3047. for (k = 0, kLen = aDataSort.length; k < kLen; k++) {
  3048. sDataType = aoColumns[ aDataSort[k] ].sType;
  3049. fnSortFormat = oSort[ (sDataType ? sDataType : 'string') + "-pre" ];
  3050. aoData[i]._aSortData[ aDataSort[k] ] = fnSortFormat ?
  3051. fnSortFormat(_fnGetCellData(oSettings, i, aDataSort[k], 'sort')) :
  3052. _fnGetCellData(oSettings, i, aDataSort[k], 'sort');
  3053. }
  3054. }
  3055. }
  3056. /* Do the sort - here we want multi-column sorting based on a given data source (column)
  3057. * and sorting function (from oSort) in a certain direction. It's reasonably complex to
  3058. * follow on it's own, but this is what we want (example two column sorting):
  3059. * fnLocalSorting = function(a,b){
  3060. * var iTest;
  3061. * iTest = oSort['string-asc']('data11', 'data12');
  3062. * if (iTest !== 0)
  3063. * return iTest;
  3064. * iTest = oSort['numeric-desc']('data21', 'data22');
  3065. * if (iTest !== 0)
  3066. * return iTest;
  3067. * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
  3068. * }
  3069. * Basically we have a test for each sorting column, if the data in that column is equal,
  3070. * test the next column. If all columns match, then we use a numeric sort on the row
  3071. * positions in the original data array to provide a stable sort.
  3072. */
  3073. oSettings.aiDisplayMaster.sort(function (a, b) {
  3074. var k, l, lLen, iTest, aDataSort, sDataType;
  3075. for (k = 0; k < iSortLen; k++) {
  3076. aDataSort = aoColumns[ aaSort[k][0] ].aDataSort;
  3077. for (l = 0, lLen = aDataSort.length; l < lLen; l++) {
  3078. sDataType = aoColumns[ aDataSort[l] ].sType;
  3079. iTest = oSort[ (sDataType ? sDataType : 'string') + "-" + aaSort[k][1] ](
  3080. aoData[a]._aSortData[ aDataSort[l] ],
  3081. aoData[b]._aSortData[ aDataSort[l] ]
  3082. );
  3083. if (iTest !== 0) {
  3084. return iTest;
  3085. }
  3086. }
  3087. }
  3088. return oSort['numeric-asc'](aiOrig[a], aiOrig[b]);
  3089. });
  3090. }
  3091. /* Alter the sorting classes to take account of the changes */
  3092. if ((bApplyClasses === undefined || bApplyClasses) && !oSettings.oFeatures.bDeferRender) {
  3093. _fnSortingClasses(oSettings);
  3094. }
  3095. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  3096. var sTitle = aoColumns[i].sTitle.replace(/<.*?>/g, "");
  3097. nTh = aoColumns[i].nTh;
  3098. nTh.removeAttribute('aria-sort');
  3099. nTh.removeAttribute('aria-label');
  3100. /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
  3101. if (aoColumns[i].bSortable) {
  3102. if (aaSort.length > 0 && aaSort[0][0] == i) {
  3103. nTh.setAttribute('aria-sort', aaSort[0][1] == "asc" ? "ascending" : "descending");
  3104. var nextSort = (aoColumns[i].asSorting[ aaSort[0][2] + 1 ]) ?
  3105. aoColumns[i].asSorting[ aaSort[0][2] + 1 ] : aoColumns[i].asSorting[0];
  3106. nTh.setAttribute('aria-label', sTitle +
  3107. (nextSort == "asc" ? oAria.sSortAscending : oAria.sSortDescending));
  3108. }
  3109. else {
  3110. nTh.setAttribute('aria-label', sTitle +
  3111. (aoColumns[i].asSorting[0] == "asc" ? oAria.sSortAscending : oAria.sSortDescending));
  3112. }
  3113. }
  3114. else {
  3115. nTh.setAttribute('aria-label', sTitle);
  3116. }
  3117. }
  3118. /* Tell the draw function that we have sorted the data */
  3119. oSettings.bSorted = true;
  3120. $(oSettings.oInstance).trigger('sort', oSettings);
  3121. /* Copy the master data into the draw array and re-draw */
  3122. if (oSettings.oFeatures.bFilter) {
  3123. /* _fnFilter() will redraw the table for us */
  3124. _fnFilterComplete(oSettings, oSettings.oPreviousSearch, 1);
  3125. }
  3126. else {
  3127. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  3128. oSettings._iDisplayStart = 0;
  3129. /* reset display back to page 0 */
  3130. _fnCalculateEnd(oSettings);
  3131. _fnDraw(oSettings);
  3132. }
  3133. }
  3134. /**
  3135. * Attach a sort handler (click) to a node
  3136. * @param {object} oSettings dataTables settings object
  3137. * @param {node} nNode node to attach the handler to
  3138. * @param {int} iDataIndex column sorting index
  3139. * @param {function} [fnCallback] callback function
  3140. * @memberof DataTable#oApi
  3141. */
  3142. function _fnSortAttachListener(oSettings, nNode, iDataIndex, fnCallback) {
  3143. _fnBindAction(nNode, {}, function (e) {
  3144. /* If the column is not sortable - don't to anything */
  3145. if (oSettings.aoColumns[iDataIndex].bSortable === false) {
  3146. return;
  3147. }
  3148. /*
  3149. * This is a little bit odd I admit... I declare a temporary function inside the scope of
  3150. * _fnBuildHead and the click handler in order that the code presented here can be used
  3151. * twice - once for when bProcessing is enabled, and another time for when it is
  3152. * disabled, as we need to perform slightly different actions.
  3153. * Basically the issue here is that the Javascript engine in modern browsers don't
  3154. * appear to allow the rendering engine to update the display while it is still executing
  3155. * it's thread (well - it does but only after long intervals). This means that the
  3156. * 'processing' display doesn't appear for a table sort. To break the js thread up a bit
  3157. * I force an execution break by using setTimeout - but this breaks the expected
  3158. * thread continuation for the end-developer's point of view (their code would execute
  3159. * too early), so we only do it when we absolutely have to.
  3160. */
  3161. var fnInnerSorting = function () {
  3162. var iColumn, iNextSort;
  3163. /* If the shift key is pressed then we are multiple column sorting */
  3164. if (e.shiftKey) {
  3165. /* Are we already doing some kind of sort on this column? */
  3166. var bFound = false;
  3167. for (var i = 0; i < oSettings.aaSorting.length; i++) {
  3168. if (oSettings.aaSorting[i][0] == iDataIndex) {
  3169. bFound = true;
  3170. iColumn = oSettings.aaSorting[i][0];
  3171. iNextSort = oSettings.aaSorting[i][2] + 1;
  3172. if (!oSettings.aoColumns[iColumn].asSorting[iNextSort]) {
  3173. /* Reached the end of the sorting options, remove from multi-col sort */
  3174. oSettings.aaSorting.splice(i, 1);
  3175. }
  3176. else {
  3177. /* Move onto next sorting direction */
  3178. oSettings.aaSorting[i][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];
  3179. oSettings.aaSorting[i][2] = iNextSort;
  3180. }
  3181. break;
  3182. }
  3183. }
  3184. /* No sort yet - add it in */
  3185. if (bFound === false) {
  3186. oSettings.aaSorting.push([ iDataIndex,
  3187. oSettings.aoColumns[iDataIndex].asSorting[0], 0 ]);
  3188. }
  3189. }
  3190. else {
  3191. /* If no shift key then single column sort */
  3192. if (oSettings.aaSorting.length == 1 && oSettings.aaSorting[0][0] == iDataIndex) {
  3193. iColumn = oSettings.aaSorting[0][0];
  3194. iNextSort = oSettings.aaSorting[0][2] + 1;
  3195. if (!oSettings.aoColumns[iColumn].asSorting[iNextSort]) {
  3196. iNextSort = 0;
  3197. }
  3198. oSettings.aaSorting[0][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];
  3199. oSettings.aaSorting[0][2] = iNextSort;
  3200. }
  3201. else {
  3202. oSettings.aaSorting.splice(0, oSettings.aaSorting.length);
  3203. oSettings.aaSorting.push([ iDataIndex,
  3204. oSettings.aoColumns[iDataIndex].asSorting[0], 0 ]);
  3205. }
  3206. }
  3207. /* Run the sort */
  3208. _fnSort(oSettings);
  3209. };
  3210. /* /fnInnerSorting */
  3211. if (!oSettings.oFeatures.bProcessing) {
  3212. fnInnerSorting();
  3213. }
  3214. else {
  3215. _fnProcessingDisplay(oSettings, true);
  3216. setTimeout(function () {
  3217. fnInnerSorting();
  3218. if (!oSettings.oFeatures.bServerSide) {
  3219. _fnProcessingDisplay(oSettings, false);
  3220. }
  3221. }, 0);
  3222. }
  3223. /* Call the user specified callback function - used for async user interaction */
  3224. if (typeof fnCallback == 'function') {
  3225. fnCallback(oSettings);
  3226. }
  3227. });
  3228. }
  3229. /**
  3230. * Set the sorting classes on the header, Note: it is safe to call this function
  3231. * when bSort and bSortClasses are false
  3232. * @param {object} oSettings dataTables settings object
  3233. * @memberof DataTable#oApi
  3234. */
  3235. function _fnSortingClasses(oSettings) {
  3236. var i, iLen, j, jLen, iFound;
  3237. var aaSort, sClass;
  3238. var iColumns = oSettings.aoColumns.length;
  3239. var oClasses = oSettings.oClasses;
  3240. for (i = 0; i < iColumns; i++) {
  3241. if (oSettings.aoColumns[i].bSortable) {
  3242. $(oSettings.aoColumns[i].nTh).removeClass(oClasses.sSortAsc + " " + oClasses.sSortDesc +
  3243. " " + oSettings.aoColumns[i].sSortingClass);
  3244. }
  3245. }
  3246. if (oSettings.aaSortingFixed !== null) {
  3247. aaSort = oSettings.aaSortingFixed.concat(oSettings.aaSorting);
  3248. }
  3249. else {
  3250. aaSort = oSettings.aaSorting.slice();
  3251. }
  3252. /* Apply the required classes to the header */
  3253. for (i = 0; i < oSettings.aoColumns.length; i++) {
  3254. if (oSettings.aoColumns[i].bSortable) {
  3255. sClass = oSettings.aoColumns[i].sSortingClass;
  3256. iFound = -1;
  3257. for (j = 0; j < aaSort.length; j++) {
  3258. if (aaSort[j][0] == i) {
  3259. sClass = ( aaSort[j][1] == "asc" ) ?
  3260. oClasses.sSortAsc : oClasses.sSortDesc;
  3261. iFound = j;
  3262. break;
  3263. }
  3264. }
  3265. $(oSettings.aoColumns[i].nTh).addClass(sClass);
  3266. if (oSettings.bJUI) {
  3267. /* jQuery UI uses extra markup */
  3268. var jqSpan = $("span." + oClasses.sSortIcon, oSettings.aoColumns[i].nTh);
  3269. jqSpan.removeClass(oClasses.sSortJUIAsc + " " + oClasses.sSortJUIDesc + " " +
  3270. oClasses.sSortJUI + " " + oClasses.sSortJUIAscAllowed + " " + oClasses.sSortJUIDescAllowed);
  3271. var sSpanClass;
  3272. if (iFound == -1) {
  3273. sSpanClass = oSettings.aoColumns[i].sSortingClassJUI;
  3274. }
  3275. else if (aaSort[iFound][1] == "asc") {
  3276. sSpanClass = oClasses.sSortJUIAsc;
  3277. }
  3278. else {
  3279. sSpanClass = oClasses.sSortJUIDesc;
  3280. }
  3281. jqSpan.addClass(sSpanClass);
  3282. }
  3283. }
  3284. else {
  3285. /* No sorting on this column, so add the base class. This will have been assigned by
  3286. * _fnAddColumn
  3287. */
  3288. $(oSettings.aoColumns[i].nTh).addClass(oSettings.aoColumns[i].sSortingClass);
  3289. }
  3290. }
  3291. /*
  3292. * Apply the required classes to the table body
  3293. * Note that this is given as a feature switch since it can significantly slow down a sort
  3294. * on large data sets (adding and removing of classes is always slow at the best of times..)
  3295. * Further to this, note that this code is admittedly fairly ugly. It could be made a lot
  3296. * simpler using jQuery selectors and add/removeClass, but that is significantly slower
  3297. * (on the order of 5 times slower) - hence the direct DOM manipulation here.
  3298. * Note that for deferred drawing we do use jQuery - the reason being that taking the first
  3299. * row found to see if the whole column needs processed can miss classes since the first
  3300. * column might be new.
  3301. */
  3302. sClass = oClasses.sSortColumn;
  3303. if (oSettings.oFeatures.bSort && oSettings.oFeatures.bSortClasses) {
  3304. var nTds = _fnGetTdNodes(oSettings);
  3305. /* Determine what the sorting class for each column should be */
  3306. var iClass, iTargetCol;
  3307. var asClasses = [];
  3308. for (i = 0; i < iColumns; i++) {
  3309. asClasses.push("");
  3310. }
  3311. for (i = 0, iClass = 1; i < aaSort.length; i++) {
  3312. iTargetCol = parseInt(aaSort[i][0], 10);
  3313. asClasses[iTargetCol] = sClass + iClass;
  3314. if (iClass < 3) {
  3315. iClass++;
  3316. }
  3317. }
  3318. /* Make changes to the classes for each cell as needed */
  3319. var reClass = new RegExp(sClass + "[123]");
  3320. var sTmpClass, sCurrentClass, sNewClass;
  3321. for (i = 0, iLen = nTds.length; i < iLen; i++) {
  3322. /* Determine which column we're looking at */
  3323. iTargetCol = i % iColumns;
  3324. /* What is the full list of classes now */
  3325. sCurrentClass = nTds[i].className;
  3326. /* What sorting class should be applied? */
  3327. sNewClass = asClasses[iTargetCol];
  3328. /* What would the new full list be if we did a replacement? */
  3329. sTmpClass = sCurrentClass.replace(reClass, sNewClass);
  3330. if (sTmpClass != sCurrentClass) {
  3331. /* We changed something */
  3332. nTds[i].className = $.trim(sTmpClass);
  3333. }
  3334. else if (sNewClass.length > 0 && sCurrentClass.indexOf(sNewClass) == -1) {
  3335. /* We need to add a class */
  3336. nTds[i].className = sCurrentClass + " " + sNewClass;
  3337. }
  3338. }
  3339. }
  3340. }
  3341. /**
  3342. * Save the state of a table in a cookie such that the page can be reloaded
  3343. * @param {object} oSettings dataTables settings object
  3344. * @memberof DataTable#oApi
  3345. */
  3346. function _fnSaveState(oSettings) {
  3347. if (!oSettings.oFeatures.bStateSave || oSettings.bDestroying) {
  3348. return;
  3349. }
  3350. /* Store the interesting variables */
  3351. var i, iLen, bInfinite = oSettings.oScroll.bInfinite;
  3352. var oState = {
  3353. "iCreate":new Date().getTime(),
  3354. "iStart":(bInfinite ? 0 : oSettings._iDisplayStart),
  3355. "iEnd":(bInfinite ? oSettings._iDisplayLength : oSettings._iDisplayEnd),
  3356. "iLength":oSettings._iDisplayLength,
  3357. "aaSorting":$.extend(true, [], oSettings.aaSorting),
  3358. "oSearch":$.extend(true, {}, oSettings.oPreviousSearch),
  3359. "aoSearchCols":$.extend(true, [], oSettings.aoPreSearchCols),
  3360. "abVisCols":[]
  3361. };
  3362. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  3363. oState.abVisCols.push(oSettings.aoColumns[i].bVisible);
  3364. }
  3365. _fnCallbackFire(oSettings, "aoStateSaveParams", 'stateSaveParams', [oSettings, oState]);
  3366. oSettings.fnStateSave.call(oSettings.oInstance, oSettings, oState);
  3367. }
  3368. /**
  3369. * Attempt to load a saved table state from a cookie
  3370. * @param {object} oSettings dataTables settings object
  3371. * @param {object} oInit DataTables init object so we can override settings
  3372. * @memberof DataTable#oApi
  3373. */
  3374. function _fnLoadState(oSettings, oInit) {
  3375. if (!oSettings.oFeatures.bStateSave) {
  3376. return;
  3377. }
  3378. var oData = oSettings.fnStateLoad.call(oSettings.oInstance, oSettings);
  3379. if (!oData) {
  3380. return;
  3381. }
  3382. /* Allow custom and plug-in manipulation functions to alter the saved data set and
  3383. * cancelling of loading by returning false
  3384. */
  3385. var abStateLoad = _fnCallbackFire(oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData]);
  3386. if ($.inArray(false, abStateLoad) !== -1) {
  3387. return;
  3388. }
  3389. /* Store the saved state so it might be accessed at any time */
  3390. oSettings.oLoadedState = $.extend(true, {}, oData);
  3391. /* Restore key features */
  3392. oSettings._iDisplayStart = oData.iStart;
  3393. oSettings.iInitDisplayStart = oData.iStart;
  3394. oSettings._iDisplayEnd = oData.iEnd;
  3395. oSettings._iDisplayLength = oData.iLength;
  3396. oSettings.aaSorting = oData.aaSorting.slice();
  3397. oSettings.saved_aaSorting = oData.aaSorting.slice();
  3398. /* Search filtering */
  3399. $.extend(oSettings.oPreviousSearch, oData.oSearch);
  3400. $.extend(true, oSettings.aoPreSearchCols, oData.aoSearchCols);
  3401. /* Column visibility state
  3402. * Pass back visibility settings to the init handler, but to do not here override
  3403. * the init object that the user might have passed in
  3404. */
  3405. oInit.saved_aoColumns = [];
  3406. for (var i = 0; i < oData.abVisCols.length; i++) {
  3407. oInit.saved_aoColumns[i] = {};
  3408. oInit.saved_aoColumns[i].bVisible = oData.abVisCols[i];
  3409. }
  3410. _fnCallbackFire(oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData]);
  3411. }
  3412. /**
  3413. * Create a new cookie with a value to store the state of a table
  3414. * @param {string} sName name of the cookie to create
  3415. * @param {string} sValue the value the cookie should take
  3416. * @param {int} iSecs duration of the cookie
  3417. * @param {string} sBaseName sName is made up of the base + file name - this is the base
  3418. * @param {function} fnCallback User definable function to modify the cookie
  3419. * @memberof DataTable#oApi
  3420. */
  3421. function _fnCreateCookie(sName, sValue, iSecs, sBaseName, fnCallback) {
  3422. var date = new Date();
  3423. date.setTime(date.getTime() + (iSecs * 1000));
  3424. /*
  3425. * Shocking but true - it would appear IE has major issues with having the path not having
  3426. * a trailing slash on it. We need the cookie to be available based on the path, so we
  3427. * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the
  3428. * patch to use at least some of the path
  3429. */
  3430. var aParts = window.location.pathname.split('/');
  3431. var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g, "").toLowerCase();
  3432. var sFullCookie, oData;
  3433. if (fnCallback !== null) {
  3434. oData = (typeof $.parseJSON === 'function') ?
  3435. $.parseJSON(sValue) : eval('(' + sValue + ')');
  3436. sFullCookie = fnCallback(sNameFile, oData, date.toGMTString(),
  3437. aParts.join('/') + "/");
  3438. }
  3439. else {
  3440. sFullCookie = sNameFile + "=" + encodeURIComponent(sValue) +
  3441. "; expires=" + date.toGMTString() + "; path=" + aParts.join('/') + "/";
  3442. }
  3443. /* Are we going to go over the cookie limit of 4KiB? If so, try to delete a cookies
  3444. * belonging to DataTables.
  3445. */
  3446. var
  3447. aCookies = document.cookie.split(';'),
  3448. iNewCookieLen = sFullCookie.split(';')[0].length,
  3449. aOldCookies = [];
  3450. if (iNewCookieLen + document.cookie.length + 10 > 4096) /* Magic 10 for padding */
  3451. {
  3452. for (var i = 0, iLen = aCookies.length; i < iLen; i++) {
  3453. if (aCookies[i].indexOf(sBaseName) != -1) {
  3454. /* It's a DataTables cookie, so eval it and check the time stamp */
  3455. var aSplitCookie = aCookies[i].split('=');
  3456. try {
  3457. oData = eval('(' + decodeURIComponent(aSplitCookie[1]) + ')');
  3458. if (oData && oData.iCreate) {
  3459. aOldCookies.push({
  3460. "name":aSplitCookie[0],
  3461. "time":oData.iCreate
  3462. });
  3463. }
  3464. }
  3465. catch (e) {
  3466. }
  3467. }
  3468. }
  3469. // Make sure we delete the oldest ones first
  3470. aOldCookies.sort(function (a, b) {
  3471. return b.time - a.time;
  3472. });
  3473. // Eliminate as many old DataTables cookies as we need to
  3474. while (iNewCookieLen + document.cookie.length + 10 > 4096) {
  3475. if (aOldCookies.length === 0) {
  3476. // Deleted all DT cookies and still not enough space. Can't state save
  3477. return;
  3478. }
  3479. var old = aOldCookies.pop();
  3480. document.cookie = old.name + "=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path=" +
  3481. aParts.join('/') + "/";
  3482. }
  3483. }
  3484. document.cookie = sFullCookie;
  3485. }
  3486. /**
  3487. * Read an old cookie to get a cookie with an old table state
  3488. * @param {string} sName name of the cookie to read
  3489. * @returns {string} contents of the cookie - or null if no cookie with that name found
  3490. * @memberof DataTable#oApi
  3491. */
  3492. function _fnReadCookie(sName) {
  3493. var
  3494. aParts = window.location.pathname.split('/'),
  3495. sNameEQ = sName + '_' + aParts[aParts.length - 1].replace(/[\/:]/g, "").toLowerCase() + '=',
  3496. sCookieContents = document.cookie.split(';');
  3497. for (var i = 0; i < sCookieContents.length; i++) {
  3498. var c = sCookieContents[i];
  3499. while (c.charAt(0) == ' ') {
  3500. c = c.substring(1, c.length);
  3501. }
  3502. if (c.indexOf(sNameEQ) === 0) {
  3503. return decodeURIComponent(c.substring(sNameEQ.length, c.length));
  3504. }
  3505. }
  3506. return null;
  3507. }
  3508. /**
  3509. * Return the settings object for a particular table
  3510. * @param {node} nTable table we are using as a dataTable
  3511. * @returns {object} Settings object - or null if not found
  3512. * @memberof DataTable#oApi
  3513. */
  3514. function _fnSettingsFromNode(nTable) {
  3515. for (var i = 0; i < DataTable.settings.length; i++) {
  3516. if (DataTable.settings[i].nTable === nTable) {
  3517. return DataTable.settings[i];
  3518. }
  3519. }
  3520. return null;
  3521. }
  3522. /**
  3523. * Return an array with the TR nodes for the table
  3524. * @param {object} oSettings dataTables settings object
  3525. * @returns {array} TR array
  3526. * @memberof DataTable#oApi
  3527. */
  3528. function _fnGetTrNodes(oSettings) {
  3529. var aNodes = [];
  3530. var aoData = oSettings.aoData;
  3531. for (var i = 0, iLen = aoData.length; i < iLen; i++) {
  3532. if (aoData[i].nTr !== null) {
  3533. aNodes.push(aoData[i].nTr);
  3534. }
  3535. }
  3536. return aNodes;
  3537. }
  3538. /**
  3539. * Return an flat array with all TD nodes for the table, or row
  3540. * @param {object} oSettings dataTables settings object
  3541. * @param {int} [iIndividualRow] aoData index to get the nodes for - optional
  3542. * if not given then the return array will contain all nodes for the table
  3543. * @returns {array} TD array
  3544. * @memberof DataTable#oApi
  3545. */
  3546. function _fnGetTdNodes(oSettings, iIndividualRow) {
  3547. var anReturn = [];
  3548. var iCorrector;
  3549. var anTds, nTd;
  3550. var iRow, iRows = oSettings.aoData.length,
  3551. iColumn, iColumns, oData, sNodeName, iStart = 0, iEnd = iRows;
  3552. /* Allow the collection to be limited to just one row */
  3553. if (iIndividualRow !== undefined) {
  3554. iStart = iIndividualRow;
  3555. iEnd = iIndividualRow + 1;
  3556. }
  3557. for (iRow = iStart; iRow < iEnd; iRow++) {
  3558. oData = oSettings.aoData[iRow];
  3559. if (oData.nTr !== null) {
  3560. /* get the TD child nodes - taking into account text etc nodes */
  3561. anTds = [];
  3562. nTd = oData.nTr.firstChild;
  3563. while (nTd) {
  3564. sNodeName = nTd.nodeName.toLowerCase();
  3565. if (sNodeName == 'td' || sNodeName == 'th') {
  3566. anTds.push(nTd);
  3567. }
  3568. nTd = nTd.nextSibling;
  3569. }
  3570. iCorrector = 0;
  3571. for (iColumn = 0, iColumns = oSettings.aoColumns.length; iColumn < iColumns; iColumn++) {
  3572. if (oSettings.aoColumns[iColumn].bVisible) {
  3573. anReturn.push(anTds[iColumn - iCorrector]);
  3574. }
  3575. else {
  3576. anReturn.push(oData._anHidden[iColumn]);
  3577. iCorrector++;
  3578. }
  3579. }
  3580. }
  3581. }
  3582. return anReturn;
  3583. }
  3584. /**
  3585. * Log an error message
  3586. * @param {object} oSettings dataTables settings object
  3587. * @param {int} iLevel log error messages, or display them to the user
  3588. * @param {string} sMesg error message
  3589. * @memberof DataTable#oApi
  3590. */
  3591. function _fnLog(oSettings, iLevel, sMesg) {
  3592. var sAlert = (oSettings === null) ?
  3593. "DataTables warning: " + sMesg :
  3594. "DataTables warning (table id = '" + oSettings.sTableId + "'): " + sMesg;
  3595. if (iLevel === 0) {
  3596. if (DataTable.ext.sErrMode == 'alert') {
  3597. alert(sAlert);
  3598. }
  3599. else {
  3600. throw new Error(sAlert);
  3601. }
  3602. return;
  3603. }
  3604. else if (window.console && console.log) {
  3605. console.log(sAlert);
  3606. }
  3607. }
  3608. /**
  3609. * See if a property is defined on one object, if so assign it to the other object
  3610. * @param {object} oRet target object
  3611. * @param {object} oSrc source object
  3612. * @param {string} sName property
  3613. * @param {string} [sMappedName] name to map too - optional, sName used if not given
  3614. * @memberof DataTable#oApi
  3615. */
  3616. function _fnMap(oRet, oSrc, sName, sMappedName) {
  3617. if (sMappedName === undefined) {
  3618. sMappedName = sName;
  3619. }
  3620. if (oSrc[sName] !== undefined) {
  3621. oRet[sMappedName] = oSrc[sName];
  3622. }
  3623. }
  3624. /**
  3625. * Extend objects - very similar to jQuery.extend, but deep copy objects, and shallow
  3626. * copy arrays. The reason we need to do this, is that we don't want to deep copy array
  3627. * init values (such as aaSorting) since the dev wouldn't be able to override them, but
  3628. * we do want to deep copy arrays.
  3629. * @param {object} oOut Object to extend
  3630. * @param {object} oExtender Object from which the properties will be applied to oOut
  3631. * @returns {object} oOut Reference, just for convenience - oOut === the return.
  3632. * @memberof DataTable#oApi
  3633. * @todo This doesn't take account of arrays inside the deep copied objects.
  3634. */
  3635. function _fnExtend(oOut, oExtender) {
  3636. var val;
  3637. for (var prop in oExtender) {
  3638. if (oExtender.hasOwnProperty(prop)) {
  3639. val = oExtender[prop];
  3640. if (typeof oInit[prop] === 'object' && val !== null && $.isArray(val) === false) {
  3641. $.extend(true, oOut[prop], val);
  3642. }
  3643. else {
  3644. oOut[prop] = val;
  3645. }
  3646. }
  3647. }
  3648. return oOut;
  3649. }
  3650. /**
  3651. * Bind an event handers to allow a click or return key to activate the callback.
  3652. * This is good for accessibility since a return on the keyboard will have the
  3653. * same effect as a click, if the element has focus.
  3654. * @param {element} n Element to bind the action to
  3655. * @param {object} oData Data object to pass to the triggered function
  3656. * @param {function} fn Callback function for when the event is triggered
  3657. * @memberof DataTable#oApi
  3658. */
  3659. function _fnBindAction(n, oData, fn) {
  3660. $(n)
  3661. .bind('click.DT', oData, function (e) {
  3662. n.blur(); // Remove focus outline for mouse users
  3663. fn(e);
  3664. })
  3665. .bind('keypress.DT', oData, function (e) {
  3666. if (e.which === 13) {
  3667. fn(e);
  3668. }
  3669. })
  3670. .bind('selectstart.DT', function () {
  3671. /* Take the brutal approach to cancelling text selection */
  3672. return false;
  3673. });
  3674. }
  3675. /**
  3676. * Register a callback function. Easily allows a callback function to be added to
  3677. * an array store of callback functions that can then all be called together.
  3678. * @param {object} oSettings dataTables settings object
  3679. * @param {string} sStore Name of the array storage for the callbacks in oSettings
  3680. * @param {function} fn Function to be called back
  3681. * @param {string} sName Identifying name for the callback (i.e. a label)
  3682. * @memberof DataTable#oApi
  3683. */
  3684. function _fnCallbackReg(oSettings, sStore, fn, sName) {
  3685. if (fn) {
  3686. oSettings[sStore].push({
  3687. "fn":fn,
  3688. "sName":sName
  3689. });
  3690. }
  3691. }
  3692. /**
  3693. * Fire callback functions and trigger events. Note that the loop over the callback
  3694. * array store is done backwards! Further note that you do not want to fire off triggers
  3695. * in time sensitive applications (for example cell creation) as its slow.
  3696. * @param {object} oSettings dataTables settings object
  3697. * @param {string} sStore Name of the array storage for the callbacks in oSettings
  3698. * @param {string} sTrigger Name of the jQuery custom event to trigger. If null no trigger
  3699. * is fired
  3700. * @param {array} aArgs Array of arguments to pass to the callback function / trigger
  3701. * @memberof DataTable#oApi
  3702. */
  3703. function _fnCallbackFire(oSettings, sStore, sTrigger, aArgs) {
  3704. var aoStore = oSettings[sStore];
  3705. var aRet = [];
  3706. for (var i = aoStore.length - 1; i >= 0; i--) {
  3707. aRet.push(aoStore[i].fn.apply(oSettings.oInstance, aArgs));
  3708. }
  3709. if (sTrigger !== null) {
  3710. $(oSettings.oInstance).trigger(sTrigger, aArgs);
  3711. }
  3712. return aRet;
  3713. }
  3714. /**
  3715. * JSON stringify. If JSON.stringify it provided by the browser, json2.js or any other
  3716. * library, then we use that as it is fast, safe and accurate. If the function isn't
  3717. * available then we need to built it ourselves - the inspiration for this function comes
  3718. * from Craig Buckler ( http://www.sitepoint.com/javascript-json-serialization/ ). It is
  3719. * not perfect and absolutely should not be used as a replacement to json2.js - but it does
  3720. * do what we need, without requiring a dependency for DataTables.
  3721. * @param {object} o JSON object to be converted
  3722. * @returns {string} JSON string
  3723. * @memberof DataTable#oApi
  3724. */
  3725. var _fnJsonString = (window.JSON) ? JSON.stringify : function (o) {
  3726. /* Not an object or array */
  3727. var sType = typeof o;
  3728. if (sType !== "object" || o === null) {
  3729. // simple data type
  3730. if (sType === "string") {
  3731. o = '"' + o + '"';
  3732. }
  3733. return o + "";
  3734. }
  3735. /* If object or array, need to recurse over it */
  3736. var
  3737. sProp, mValue,
  3738. json = [],
  3739. bArr = $.isArray(o);
  3740. for (sProp in o) {
  3741. mValue = o[sProp];
  3742. sType = typeof mValue;
  3743. if (sType === "string") {
  3744. mValue = '"' + mValue + '"';
  3745. }
  3746. else if (sType === "object" && mValue !== null) {
  3747. mValue = _fnJsonString(mValue);
  3748. }
  3749. json.push((bArr ? "" : '"' + sProp + '":') + mValue);
  3750. }
  3751. return (bArr ? "[" : "{") + json + (bArr ? "]" : "}");
  3752. };
  3753. /**
  3754. * From some browsers (specifically IE6/7) we need special handling to work around browser
  3755. * bugs - this function is used to detect when these workarounds are needed.
  3756. * @param {object} oSettings dataTables settings object
  3757. * @memberof DataTable#oApi
  3758. */
  3759. function _fnBrowserDetect(oSettings) {
  3760. /* IE6/7 will oversize a width 100% element inside a scrolling element, to include the
  3761. * width of the scrollbar, while other browsers ensure the inner element is contained
  3762. * without forcing scrolling
  3763. */
  3764. var n = $(
  3765. '<div style="position:absolute; top:0; left:0; height:1px; width:1px; overflow:hidden">' +
  3766. '<div style="position:absolute; top:1px; left:1px; width:100px; overflow:scroll;">' +
  3767. '<div id="DT_BrowserTest" style="width:100%; height:10px;"></div>' +
  3768. '</div>' +
  3769. '</div>')[0];
  3770. document.body.appendChild(n);
  3771. oSettings.oBrowser.bScrollOversize = $('#DT_BrowserTest', n)[0].offsetWidth === 100 ? true : false;
  3772. document.body.removeChild(n);
  3773. }
  3774. /**
  3775. * Perform a jQuery selector action on the table's TR elements (from the tbody) and
  3776. * return the resulting jQuery object.
  3777. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  3778. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  3779. * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
  3780. * criterion ("applied") or all TR elements (i.e. no filter).
  3781. * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
  3782. * Can be either 'current', whereby the current sorting of the table is used, or
  3783. * 'original' whereby the original order the data was read into the table is used.
  3784. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  3785. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  3786. * 'current' and filter is 'applied', regardless of what they might be given as.
  3787. * @returns {object} jQuery object, filtered by the given selector.
  3788. * @dtopt API
  3789. *
  3790. * @example
  3791. * $(document).ready(function() {
  3792. * var oTable = $('#example').dataTable();
  3793. *
  3794. * // Highlight every second row
  3795. * oTable.$('tr:odd').css('backgroundColor', 'blue');
  3796. * } );
  3797. *
  3798. * @example
  3799. * $(document).ready(function() {
  3800. * var oTable = $('#example').dataTable();
  3801. *
  3802. * // Filter to rows with 'Webkit' in them, add a background colour and then
  3803. * // remove the filter, thus highlighting the 'Webkit' rows only.
  3804. * oTable.fnFilter('Webkit');
  3805. * oTable.$('tr', {"filter": "applied"}).css('backgroundColor', 'blue');
  3806. * oTable.fnFilter('');
  3807. * } );
  3808. */
  3809. this.$ = function (sSelector, oOpts) {
  3810. var i, iLen, a = [], tr;
  3811. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  3812. var aoData = oSettings.aoData;
  3813. var aiDisplay = oSettings.aiDisplay;
  3814. var aiDisplayMaster = oSettings.aiDisplayMaster;
  3815. if (!oOpts) {
  3816. oOpts = {};
  3817. }
  3818. oOpts = $.extend({}, {
  3819. "filter":"none", // applied
  3820. "order":"current", // "original"
  3821. "page":"all" // current
  3822. }, oOpts);
  3823. // Current page implies that order=current and fitler=applied, since it is fairly
  3824. // senseless otherwise
  3825. if (oOpts.page == 'current') {
  3826. for (i = oSettings._iDisplayStart, iLen = oSettings.fnDisplayEnd(); i < iLen; i++) {
  3827. tr = aoData[ aiDisplay[i] ].nTr;
  3828. if (tr) {
  3829. a.push(tr);
  3830. }
  3831. }
  3832. }
  3833. else if (oOpts.order == "current" && oOpts.filter == "none") {
  3834. for (i = 0, iLen = aiDisplayMaster.length; i < iLen; i++) {
  3835. tr = aoData[ aiDisplayMaster[i] ].nTr;
  3836. if (tr) {
  3837. a.push(tr);
  3838. }
  3839. }
  3840. }
  3841. else if (oOpts.order == "current" && oOpts.filter == "applied") {
  3842. for (i = 0, iLen = aiDisplay.length; i < iLen; i++) {
  3843. tr = aoData[ aiDisplay[i] ].nTr;
  3844. if (tr) {
  3845. a.push(tr);
  3846. }
  3847. }
  3848. }
  3849. else if (oOpts.order == "original" && oOpts.filter == "none") {
  3850. for (i = 0, iLen = aoData.length; i < iLen; i++) {
  3851. tr = aoData[ i ].nTr;
  3852. if (tr) {
  3853. a.push(tr);
  3854. }
  3855. }
  3856. }
  3857. else if (oOpts.order == "original" && oOpts.filter == "applied") {
  3858. for (i = 0, iLen = aoData.length; i < iLen; i++) {
  3859. tr = aoData[ i ].nTr;
  3860. if ($.inArray(i, aiDisplay) !== -1 && tr) {
  3861. a.push(tr);
  3862. }
  3863. }
  3864. }
  3865. else {
  3866. _fnLog(oSettings, 1, "Unknown selection options");
  3867. }
  3868. /* We need to filter on the TR elements and also 'find' in their descendants
  3869. * to make the selector act like it would in a full table - so we need
  3870. * to build both results and then combine them together
  3871. */
  3872. var jqA = $(a);
  3873. var jqTRs = jqA.filter(sSelector);
  3874. var jqDescendants = jqA.find(sSelector);
  3875. return $([].concat($.makeArray(jqTRs), $.makeArray(jqDescendants)));
  3876. };
  3877. /**
  3878. * Almost identical to $ in operation, but in this case returns the data for the matched
  3879. * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
  3880. * rather than any descendants, so the data can be obtained for the row/cell. If matching
  3881. * rows are found, the data returned is the original data array/object that was used to
  3882. * create the row (or a generated array if from a DOM source).
  3883. *
  3884. * This method is often useful in-combination with $ where both functions are given the
  3885. * same parameters and the array indexes will match identically.
  3886. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  3887. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  3888. * @param {string} [oOpts.filter=none] Select elements that meet the current filter
  3889. * criterion ("applied") or all elements (i.e. no filter).
  3890. * @param {string} [oOpts.order=current] Order of the data in the processed array.
  3891. * Can be either 'current', whereby the current sorting of the table is used, or
  3892. * 'original' whereby the original order the data was read into the table is used.
  3893. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  3894. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  3895. * 'current' and filter is 'applied', regardless of what they might be given as.
  3896. * @returns {array} Data for the matched elements. If any elements, as a result of the
  3897. * selector, were not TR, TD or TH elements in the DataTable, they will have a null
  3898. * entry in the array.
  3899. * @dtopt API
  3900. *
  3901. * @example
  3902. * $(document).ready(function() {
  3903. * var oTable = $('#example').dataTable();
  3904. *
  3905. * // Get the data from the first row in the table
  3906. * var data = oTable._('tr:first');
  3907. *
  3908. * // Do something useful with the data
  3909. * alert( "First cell is: "+data[0] );
  3910. * } );
  3911. *
  3912. * @example
  3913. * $(document).ready(function() {
  3914. * var oTable = $('#example').dataTable();
  3915. *
  3916. * // Filter to 'Webkit' and get all data for
  3917. * oTable.fnFilter('Webkit');
  3918. * var data = oTable._('tr', {"filter": "applied"});
  3919. *
  3920. * // Do something with the data
  3921. * alert( data.length+" rows matched the filter" );
  3922. * } );
  3923. */
  3924. this._ = function (sSelector, oOpts) {
  3925. var aOut = [];
  3926. var i, iLen, iIndex;
  3927. var aTrs = this.$(sSelector, oOpts);
  3928. for (i = 0, iLen = aTrs.length; i < iLen; i++) {
  3929. aOut.push(this.fnGetData(aTrs[i]));
  3930. }
  3931. return aOut;
  3932. };
  3933. /**
  3934. * Add a single new row or multiple rows of data to the table. Please note
  3935. * that this is suitable for client-side processing only - if you are using
  3936. * server-side processing (i.e. "bServerSide": true), then to add data, you
  3937. * must add it to the data source, i.e. the server-side, through an Ajax call.
  3938. * @param {array|object} mData The data to be added to the table. This can be:
  3939. * <ul>
  3940. * <li>1D array of data - add a single row with the data provided</li>
  3941. * <li>2D array of arrays - add multiple rows in a single call</li>
  3942. * <li>object - data object when using <i>mData</i></li>
  3943. * <li>array of objects - multiple data objects when using <i>mData</i></li>
  3944. * </ul>
  3945. * @param {bool} [bRedraw=true] redraw the table or not
  3946. * @returns {array} An array of integers, representing the list of indexes in
  3947. * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
  3948. * the table.
  3949. * @dtopt API
  3950. *
  3951. * @example
  3952. * // Global var for counter
  3953. * var giCount = 2;
  3954. *
  3955. * $(document).ready(function() {
  3956. * $('#example').dataTable();
  3957. * } );
  3958. *
  3959. * function fnClickAddRow() {
  3960. * $('#example').dataTable().fnAddData( [
  3961. * giCount+".1",
  3962. * giCount+".2",
  3963. * giCount+".3",
  3964. * giCount+".4" ]
  3965. * );
  3966. *
  3967. * giCount++;
  3968. * }
  3969. */
  3970. this.fnAddData = function (mData, bRedraw) {
  3971. if (mData.length === 0) {
  3972. return [];
  3973. }
  3974. var aiReturn = [];
  3975. var iTest;
  3976. /* Find settings from table node */
  3977. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  3978. /* Check if we want to add multiple rows or not */
  3979. if (typeof mData[0] === "object" && mData[0] !== null) {
  3980. for (var i = 0; i < mData.length; i++) {
  3981. iTest = _fnAddData(oSettings, mData[i]);
  3982. if (iTest == -1) {
  3983. return aiReturn;
  3984. }
  3985. aiReturn.push(iTest);
  3986. }
  3987. }
  3988. else {
  3989. iTest = _fnAddData(oSettings, mData);
  3990. if (iTest == -1) {
  3991. return aiReturn;
  3992. }
  3993. aiReturn.push(iTest);
  3994. }
  3995. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  3996. if (bRedraw === undefined || bRedraw) {
  3997. _fnReDraw(oSettings);
  3998. }
  3999. return aiReturn;
  4000. };
  4001. /**
  4002. * This function will make DataTables recalculate the column sizes, based on the data
  4003. * contained in the table and the sizes applied to the columns (in the DOM, CSS or
  4004. * through the sWidth parameter). This can be useful when the width of the table's
  4005. * parent element changes (for example a window resize).
  4006. * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
  4007. * @dtopt API
  4008. *
  4009. * @example
  4010. * $(document).ready(function() {
  4011. * var oTable = $('#example').dataTable( {
  4012. * "sScrollY": "200px",
  4013. * "bPaginate": false
  4014. * } );
  4015. *
  4016. * $(window).bind('resize', function () {
  4017. * oTable.fnAdjustColumnSizing();
  4018. * } );
  4019. * } );
  4020. */
  4021. this.fnAdjustColumnSizing = function (bRedraw) {
  4022. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4023. _fnAdjustColumnSizing(oSettings);
  4024. if (bRedraw === undefined || bRedraw) {
  4025. this.fnDraw(false);
  4026. }
  4027. else if (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") {
  4028. /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
  4029. this.oApi._fnScrollDraw(oSettings);
  4030. }
  4031. };
  4032. /**
  4033. * Quickly and simply clear a table
  4034. * @param {bool} [bRedraw=true] redraw the table or not
  4035. * @dtopt API
  4036. *
  4037. * @example
  4038. * $(document).ready(function() {
  4039. * var oTable = $('#example').dataTable();
  4040. *
  4041. * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
  4042. * oTable.fnClearTable();
  4043. * } );
  4044. */
  4045. this.fnClearTable = function (bRedraw) {
  4046. /* Find settings from table node */
  4047. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4048. _fnClearTable(oSettings);
  4049. if (bRedraw === undefined || bRedraw) {
  4050. _fnDraw(oSettings);
  4051. }
  4052. };
  4053. /**
  4054. * The exact opposite of 'opening' a row, this function will close any rows which
  4055. * are currently 'open'.
  4056. * @param {node} nTr the table row to 'close'
  4057. * @returns {int} 0 on success, or 1 if failed (can't find the row)
  4058. * @dtopt API
  4059. *
  4060. * @example
  4061. * $(document).ready(function() {
  4062. * var oTable;
  4063. *
  4064. * // 'open' an information row when a row is clicked on
  4065. * $('#example tbody tr').click( function () {
  4066. * if ( oTable.fnIsOpen(this) ) {
  4067. * oTable.fnClose( this );
  4068. * } else {
  4069. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  4070. * }
  4071. * } );
  4072. *
  4073. * oTable = $('#example').dataTable();
  4074. * } );
  4075. */
  4076. this.fnClose = function (nTr) {
  4077. /* Find settings from table node */
  4078. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4079. for (var i = 0; i < oSettings.aoOpenRows.length; i++) {
  4080. if (oSettings.aoOpenRows[i].nParent == nTr) {
  4081. var nTrParent = oSettings.aoOpenRows[i].nTr.parentNode;
  4082. if (nTrParent) {
  4083. /* Remove it if it is currently on display */
  4084. nTrParent.removeChild(oSettings.aoOpenRows[i].nTr);
  4085. }
  4086. oSettings.aoOpenRows.splice(i, 1);
  4087. return 0;
  4088. }
  4089. }
  4090. return 1;
  4091. };
  4092. /**
  4093. * Remove a row for the table
  4094. * @param {mixed} mTarget The index of the row from aoData to be deleted, or
  4095. * the TR element you want to delete
  4096. * @param {function|null} [fnCallBack] Callback function
  4097. * @param {bool} [bRedraw=true] Redraw the table or not
  4098. * @returns {array} The row that was deleted
  4099. * @dtopt API
  4100. *
  4101. * @example
  4102. * $(document).ready(function() {
  4103. * var oTable = $('#example').dataTable();
  4104. *
  4105. * // Immediately remove the first row
  4106. * oTable.fnDeleteRow( 0 );
  4107. * } );
  4108. */
  4109. this.fnDeleteRow = function (mTarget, fnCallBack, bRedraw) {
  4110. /* Find settings from table node */
  4111. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4112. var i, iLen, iAODataIndex;
  4113. iAODataIndex = (typeof mTarget === 'object') ?
  4114. _fnNodeToDataIndex(oSettings, mTarget) : mTarget;
  4115. /* Return the data array from this row */
  4116. var oData = oSettings.aoData.splice(iAODataIndex, 1);
  4117. /* Update the _DT_RowIndex parameter */
  4118. for (i = 0, iLen = oSettings.aoData.length; i < iLen; i++) {
  4119. if (oSettings.aoData[i].nTr !== null) {
  4120. oSettings.aoData[i].nTr._DT_RowIndex = i;
  4121. }
  4122. }
  4123. /* Remove the target row from the search array */
  4124. var iDisplayIndex = $.inArray(iAODataIndex, oSettings.aiDisplay);
  4125. oSettings.asDataSearch.splice(iDisplayIndex, 1);
  4126. /* Delete from the display arrays */
  4127. _fnDeleteIndex(oSettings.aiDisplayMaster, iAODataIndex);
  4128. _fnDeleteIndex(oSettings.aiDisplay, iAODataIndex);
  4129. /* If there is a user callback function - call it */
  4130. if (typeof fnCallBack === "function") {
  4131. fnCallBack.call(this, oSettings, oData);
  4132. }
  4133. /* Check for an 'overflow' they case for displaying the table */
  4134. if (oSettings._iDisplayStart >= oSettings.fnRecordsDisplay()) {
  4135. oSettings._iDisplayStart -= oSettings._iDisplayLength;
  4136. if (oSettings._iDisplayStart < 0) {
  4137. oSettings._iDisplayStart = 0;
  4138. }
  4139. }
  4140. if (bRedraw === undefined || bRedraw) {
  4141. _fnCalculateEnd(oSettings);
  4142. _fnDraw(oSettings);
  4143. }
  4144. return oData;
  4145. };
  4146. /**
  4147. * Restore the table to it's original state in the DOM by removing all of DataTables
  4148. * enhancements, alterations to the DOM structure of the table and event listeners.
  4149. * @param {boolean} [bRemove=false] Completely remove the table from the DOM
  4150. * @dtopt API
  4151. *
  4152. * @example
  4153. * $(document).ready(function() {
  4154. * // This example is fairly pointless in reality, but shows how fnDestroy can be used
  4155. * var oTable = $('#example').dataTable();
  4156. * oTable.fnDestroy();
  4157. * } );
  4158. */
  4159. this.fnDestroy = function (bRemove) {
  4160. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4161. var nOrig = oSettings.nTableWrapper.parentNode;
  4162. var nBody = oSettings.nTBody;
  4163. var i, iLen;
  4164. bRemove = (bRemove === undefined) ? false : bRemove;
  4165. /* Flag to note that the table is currently being destroyed - no action should be taken */
  4166. oSettings.bDestroying = true;
  4167. /* Fire off the destroy callbacks for plug-ins etc */
  4168. _fnCallbackFire(oSettings, "aoDestroyCallback", "destroy", [oSettings]);
  4169. /* If the table is not being removed, restore the hidden columns */
  4170. if (!bRemove) {
  4171. for (i = 0, iLen = oSettings.aoColumns.length; i < iLen; i++) {
  4172. if (oSettings.aoColumns[i].bVisible === false) {
  4173. this.fnSetColumnVis(i, true);
  4174. }
  4175. }
  4176. }
  4177. /* Blitz all DT events */
  4178. $(oSettings.nTableWrapper).find('*').andSelf().unbind('.DT');
  4179. /* If there is an 'empty' indicator row, remove it */
  4180. $('tbody>tr>td.' + oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove();
  4181. /* When scrolling we had to break the table up - restore it */
  4182. if (oSettings.nTable != oSettings.nTHead.parentNode) {
  4183. $(oSettings.nTable).children('thead').remove();
  4184. oSettings.nTable.appendChild(oSettings.nTHead);
  4185. }
  4186. if (oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode) {
  4187. $(oSettings.nTable).children('tfoot').remove();
  4188. oSettings.nTable.appendChild(oSettings.nTFoot);
  4189. }
  4190. /* Remove the DataTables generated nodes, events and classes */
  4191. oSettings.nTable.parentNode.removeChild(oSettings.nTable);
  4192. $(oSettings.nTableWrapper).remove();
  4193. oSettings.aaSorting = [];
  4194. oSettings.aaSortingFixed = [];
  4195. _fnSortingClasses(oSettings);
  4196. $(_fnGetTrNodes(oSettings)).removeClass(oSettings.asStripeClasses.join(' '));
  4197. $('th, td', oSettings.nTHead).removeClass([
  4198. oSettings.oClasses.sSortable,
  4199. oSettings.oClasses.sSortableAsc,
  4200. oSettings.oClasses.sSortableDesc,
  4201. oSettings.oClasses.sSortableNone ].join(' ')
  4202. );
  4203. if (oSettings.bJUI) {
  4204. $('th span.' + oSettings.oClasses.sSortIcon
  4205. + ', td span.' + oSettings.oClasses.sSortIcon, oSettings.nTHead).remove();
  4206. $('th, td', oSettings.nTHead).each(function () {
  4207. var jqWrapper = $('div.' + oSettings.oClasses.sSortJUIWrapper, this);
  4208. var kids = jqWrapper.contents();
  4209. $(this).append(kids);
  4210. jqWrapper.remove();
  4211. });
  4212. }
  4213. /* Add the TR elements back into the table in their original order */
  4214. if (!bRemove && oSettings.nTableReinsertBefore) {
  4215. nOrig.insertBefore(oSettings.nTable, oSettings.nTableReinsertBefore);
  4216. }
  4217. else if (!bRemove) {
  4218. nOrig.appendChild(oSettings.nTable);
  4219. }
  4220. for (i = 0, iLen = oSettings.aoData.length; i < iLen; i++) {
  4221. if (oSettings.aoData[i].nTr !== null) {
  4222. nBody.appendChild(oSettings.aoData[i].nTr);
  4223. }
  4224. }
  4225. /* Restore the width of the original table */
  4226. if (oSettings.oFeatures.bAutoWidth === true) {
  4227. oSettings.nTable.style.width = _fnStringToCss(oSettings.sDestroyWidth);
  4228. }
  4229. /* If the were originally stripe classes - then we add them back here. Note
  4230. * this is not fool proof (for example if not all rows had stripe classes - but
  4231. * it's a good effort without getting carried away
  4232. */
  4233. iLen = oSettings.asDestroyStripes.length;
  4234. if (iLen) {
  4235. var anRows = $(nBody).children('tr');
  4236. for (i = 0; i < iLen; i++) {
  4237. anRows.filter(':nth-child(' + iLen + 'n + ' + i + ')').addClass(oSettings.asDestroyStripes[i]);
  4238. }
  4239. }
  4240. /* Remove the settings object from the settings array */
  4241. for (i = 0, iLen = DataTable.settings.length; i < iLen; i++) {
  4242. if (DataTable.settings[i] == oSettings) {
  4243. DataTable.settings.splice(i, 1);
  4244. }
  4245. }
  4246. /* End it all */
  4247. oSettings = null;
  4248. oInit = null;
  4249. };
  4250. /**
  4251. * Redraw the table
  4252. * @param {bool} [bComplete=true] Re-filter and resort (if enabled) the table before the draw.
  4253. * @dtopt API
  4254. *
  4255. * @example
  4256. * $(document).ready(function() {
  4257. * var oTable = $('#example').dataTable();
  4258. *
  4259. * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
  4260. * oTable.fnDraw();
  4261. * } );
  4262. */
  4263. this.fnDraw = function (bComplete) {
  4264. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4265. if (bComplete === false) {
  4266. _fnCalculateEnd(oSettings);
  4267. _fnDraw(oSettings);
  4268. }
  4269. else {
  4270. _fnReDraw(oSettings);
  4271. }
  4272. };
  4273. /**
  4274. * Filter the input based on data
  4275. * @param {string} sInput String to filter the table on
  4276. * @param {int|null} [iColumn] Column to limit filtering to
  4277. * @param {bool} [bRegex=false] Treat as regular expression or not
  4278. * @param {bool} [bSmart=true] Perform smart filtering or not
  4279. * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
  4280. * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
  4281. * @dtopt API
  4282. *
  4283. * @example
  4284. * $(document).ready(function() {
  4285. * var oTable = $('#example').dataTable();
  4286. *
  4287. * // Sometime later - filter...
  4288. * oTable.fnFilter( 'test string' );
  4289. * } );
  4290. */
  4291. this.fnFilter = function (sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive) {
  4292. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4293. if (!oSettings.oFeatures.bFilter) {
  4294. return;
  4295. }
  4296. if (bRegex === undefined || bRegex === null) {
  4297. bRegex = false;
  4298. }
  4299. if (bSmart === undefined || bSmart === null) {
  4300. bSmart = true;
  4301. }
  4302. if (bShowGlobal === undefined || bShowGlobal === null) {
  4303. bShowGlobal = true;
  4304. }
  4305. if (bCaseInsensitive === undefined || bCaseInsensitive === null) {
  4306. bCaseInsensitive = true;
  4307. }
  4308. if (iColumn === undefined || iColumn === null) {
  4309. /* Global filter */
  4310. _fnFilterComplete(oSettings, {
  4311. "sSearch":sInput + "",
  4312. "bRegex":bRegex,
  4313. "bSmart":bSmart,
  4314. "bCaseInsensitive":bCaseInsensitive
  4315. }, 1);
  4316. if (bShowGlobal && oSettings.aanFeatures.f) {
  4317. var n = oSettings.aanFeatures.f;
  4318. for (var i = 0, iLen = n.length; i < iLen; i++) {
  4319. // IE9 throws an 'unknown error' if document.activeElement is used
  4320. // inside an iframe or frame...
  4321. try {
  4322. if (n[i]._DT_Input != document.activeElement) {
  4323. $(n[i]._DT_Input).val(sInput);
  4324. }
  4325. }
  4326. catch (e) {
  4327. $(n[i]._DT_Input).val(sInput);
  4328. }
  4329. }
  4330. }
  4331. }
  4332. else {
  4333. /* Single column filter */
  4334. $.extend(oSettings.aoPreSearchCols[ iColumn ], {
  4335. "sSearch":sInput + "",
  4336. "bRegex":bRegex,
  4337. "bSmart":bSmart,
  4338. "bCaseInsensitive":bCaseInsensitive
  4339. });
  4340. _fnFilterComplete(oSettings, oSettings.oPreviousSearch, 1);
  4341. }
  4342. };
  4343. /**
  4344. * Get the data for the whole table, an individual row or an individual cell based on the
  4345. * provided parameters.
  4346. * @param {int|node} [mRow] A TR row node, TD/TH cell node or an integer. If given as
  4347. * a TR node then the data source for the whole row will be returned. If given as a
  4348. * TD/TH cell node then iCol will be automatically calculated and the data for the
  4349. * cell returned. If given as an integer, then this is treated as the aoData internal
  4350. * data index for the row (see fnGetPosition) and the data for that row used.
  4351. * @param {int} [iCol] Optional column index that you want the data of.
  4352. * @returns {array|object|string} If mRow is undefined, then the data for all rows is
  4353. * returned. If mRow is defined, just data for that row, and is iCol is
  4354. * defined, only data for the designated cell is returned.
  4355. * @dtopt API
  4356. *
  4357. * @example
  4358. * // Row data
  4359. * $(document).ready(function() {
  4360. * oTable = $('#example').dataTable();
  4361. *
  4362. * oTable.$('tr').click( function () {
  4363. * var data = oTable.fnGetData( this );
  4364. * // ... do something with the array / object of data for the row
  4365. * } );
  4366. * } );
  4367. *
  4368. * @example
  4369. * // Individual cell data
  4370. * $(document).ready(function() {
  4371. * oTable = $('#example').dataTable();
  4372. *
  4373. * oTable.$('td').click( function () {
  4374. * var sData = oTable.fnGetData( this );
  4375. * alert( 'The cell clicked on had the value of '+sData );
  4376. * } );
  4377. * } );
  4378. */
  4379. this.fnGetData = function (mRow, iCol) {
  4380. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4381. if (mRow !== undefined) {
  4382. var iRow = mRow;
  4383. if (typeof mRow === 'object') {
  4384. var sNode = mRow.nodeName.toLowerCase();
  4385. if (sNode === "tr") {
  4386. iRow = _fnNodeToDataIndex(oSettings, mRow);
  4387. }
  4388. else if (sNode === "td") {
  4389. iRow = _fnNodeToDataIndex(oSettings, mRow.parentNode);
  4390. iCol = _fnNodeToColumnIndex(oSettings, iRow, mRow);
  4391. }
  4392. }
  4393. if (iCol !== undefined) {
  4394. return _fnGetCellData(oSettings, iRow, iCol, '');
  4395. }
  4396. return (oSettings.aoData[iRow] !== undefined) ?
  4397. oSettings.aoData[iRow]._aData : null;
  4398. }
  4399. return _fnGetDataMaster(oSettings);
  4400. };
  4401. /**
  4402. * Get an array of the TR nodes that are used in the table's body. Note that you will
  4403. * typically want to use the '$' API method in preference to this as it is more
  4404. * flexible.
  4405. * @param {int} [iRow] Optional row index for the TR element you want
  4406. * @returns {array|node} If iRow is undefined, returns an array of all TR elements
  4407. * in the table's body, or iRow is defined, just the TR element requested.
  4408. * @dtopt API
  4409. *
  4410. * @example
  4411. * $(document).ready(function() {
  4412. * var oTable = $('#example').dataTable();
  4413. *
  4414. * // Get the nodes from the table
  4415. * var nNodes = oTable.fnGetNodes( );
  4416. * } );
  4417. */
  4418. this.fnGetNodes = function (iRow) {
  4419. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4420. if (iRow !== undefined) {
  4421. return (oSettings.aoData[iRow] !== undefined) ?
  4422. oSettings.aoData[iRow].nTr : null;
  4423. }
  4424. return _fnGetTrNodes(oSettings);
  4425. };
  4426. /**
  4427. * Get the array indexes of a particular cell from it's DOM element
  4428. * and column index including hidden columns
  4429. * @param {node} nNode this can either be a TR, TD or TH in the table's body
  4430. * @returns {int} If nNode is given as a TR, then a single index is returned, or
  4431. * if given as a cell, an array of [row index, column index (visible),
  4432. * column index (all)] is given.
  4433. * @dtopt API
  4434. *
  4435. * @example
  4436. * $(document).ready(function() {
  4437. * $('#example tbody td').click( function () {
  4438. * // Get the position of the current data from the node
  4439. * var aPos = oTable.fnGetPosition( this );
  4440. *
  4441. * // Get the data array for this row
  4442. * var aData = oTable.fnGetData( aPos[0] );
  4443. *
  4444. * // Update the data array and return the value
  4445. * aData[ aPos[1] ] = 'clicked';
  4446. * this.innerHTML = 'clicked';
  4447. * } );
  4448. *
  4449. * // Init DataTables
  4450. * oTable = $('#example').dataTable();
  4451. * } );
  4452. */
  4453. this.fnGetPosition = function (nNode) {
  4454. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4455. var sNodeName = nNode.nodeName.toUpperCase();
  4456. if (sNodeName == "TR") {
  4457. return _fnNodeToDataIndex(oSettings, nNode);
  4458. }
  4459. else if (sNodeName == "TD" || sNodeName == "TH") {
  4460. var iDataIndex = _fnNodeToDataIndex(oSettings, nNode.parentNode);
  4461. var iColumnIndex = _fnNodeToColumnIndex(oSettings, iDataIndex, nNode);
  4462. return [ iDataIndex, _fnColumnIndexToVisible(oSettings, iColumnIndex), iColumnIndex ];
  4463. }
  4464. return null;
  4465. };
  4466. /**
  4467. * Check to see if a row is 'open' or not.
  4468. * @param {node} nTr the table row to check
  4469. * @returns {boolean} true if the row is currently open, false otherwise
  4470. * @dtopt API
  4471. *
  4472. * @example
  4473. * $(document).ready(function() {
  4474. * var oTable;
  4475. *
  4476. * // 'open' an information row when a row is clicked on
  4477. * $('#example tbody tr').click( function () {
  4478. * if ( oTable.fnIsOpen(this) ) {
  4479. * oTable.fnClose( this );
  4480. * } else {
  4481. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  4482. * }
  4483. * } );
  4484. *
  4485. * oTable = $('#example').dataTable();
  4486. * } );
  4487. */
  4488. this.fnIsOpen = function (nTr) {
  4489. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4490. var aoOpenRows = oSettings.aoOpenRows;
  4491. for (var i = 0; i < oSettings.aoOpenRows.length; i++) {
  4492. if (oSettings.aoOpenRows[i].nParent == nTr) {
  4493. return true;
  4494. }
  4495. }
  4496. return false;
  4497. };
  4498. /**
  4499. * This function will place a new row directly after a row which is currently
  4500. * on display on the page, with the HTML contents that is passed into the
  4501. * function. This can be used, for example, to ask for confirmation that a
  4502. * particular record should be deleted.
  4503. * @param {node} nTr The table row to 'open'
  4504. * @param {string|node|jQuery} mHtml The HTML to put into the row
  4505. * @param {string} sClass Class to give the new TD cell
  4506. * @returns {node} The row opened. Note that if the table row passed in as the
  4507. * first parameter, is not found in the table, this method will silently
  4508. * return.
  4509. * @dtopt API
  4510. *
  4511. * @example
  4512. * $(document).ready(function() {
  4513. * var oTable;
  4514. *
  4515. * // 'open' an information row when a row is clicked on
  4516. * $('#example tbody tr').click( function () {
  4517. * if ( oTable.fnIsOpen(this) ) {
  4518. * oTable.fnClose( this );
  4519. * } else {
  4520. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  4521. * }
  4522. * } );
  4523. *
  4524. * oTable = $('#example').dataTable();
  4525. * } );
  4526. */
  4527. this.fnOpen = function (nTr, mHtml, sClass) {
  4528. /* Find settings from table node */
  4529. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4530. /* Check that the row given is in the table */
  4531. var nTableRows = _fnGetTrNodes(oSettings);
  4532. if ($.inArray(nTr, nTableRows) === -1) {
  4533. return;
  4534. }
  4535. /* the old open one if there is one */
  4536. this.fnClose(nTr);
  4537. var nNewRow = document.createElement("tr");
  4538. var nNewCell = document.createElement("td");
  4539. nNewRow.appendChild(nNewCell);
  4540. nNewCell.className = sClass;
  4541. nNewCell.colSpan = _fnVisbleColumns(oSettings);
  4542. if (typeof mHtml === "string") {
  4543. nNewCell.innerHTML = mHtml;
  4544. }
  4545. else {
  4546. $(nNewCell).html(mHtml);
  4547. }
  4548. /* If the nTr isn't on the page at the moment - then we don't insert at the moment */
  4549. var nTrs = $('tr', oSettings.nTBody);
  4550. if ($.inArray(nTr, nTrs) != -1) {
  4551. $(nNewRow).insertAfter(nTr);
  4552. }
  4553. oSettings.aoOpenRows.push({
  4554. "nTr":nNewRow,
  4555. "nParent":nTr
  4556. });
  4557. return nNewRow;
  4558. };
  4559. /**
  4560. * Change the pagination - provides the internal logic for pagination in a simple API
  4561. * function. With this function you can have a DataTables table go to the next,
  4562. * previous, first or last pages.
  4563. * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
  4564. * or page number to jump to (integer), note that page 0 is the first page.
  4565. * @param {bool} [bRedraw=true] Redraw the table or not
  4566. * @dtopt API
  4567. *
  4568. * @example
  4569. * $(document).ready(function() {
  4570. * var oTable = $('#example').dataTable();
  4571. * oTable.fnPageChange( 'next' );
  4572. * } );
  4573. */
  4574. this.fnPageChange = function (mAction, bRedraw) {
  4575. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4576. _fnPageChange(oSettings, mAction);
  4577. _fnCalculateEnd(oSettings);
  4578. if (bRedraw === undefined || bRedraw) {
  4579. _fnDraw(oSettings);
  4580. }
  4581. };
  4582. /**
  4583. * Show a particular column
  4584. * @param {int} iCol The column whose display should be changed
  4585. * @param {bool} bShow Show (true) or hide (false) the column
  4586. * @param {bool} [bRedraw=true] Redraw the table or not
  4587. * @dtopt API
  4588. *
  4589. * @example
  4590. * $(document).ready(function() {
  4591. * var oTable = $('#example').dataTable();
  4592. *
  4593. * // Hide the second column after initialisation
  4594. * oTable.fnSetColumnVis( 1, false );
  4595. * } );
  4596. */
  4597. this.fnSetColumnVis = function (iCol, bShow, bRedraw) {
  4598. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4599. var i, iLen;
  4600. var aoColumns = oSettings.aoColumns;
  4601. var aoData = oSettings.aoData;
  4602. var nTd, bAppend, iBefore;
  4603. /* No point in doing anything if we are requesting what is already true */
  4604. if (aoColumns[iCol].bVisible == bShow) {
  4605. return;
  4606. }
  4607. /* Show the column */
  4608. if (bShow) {
  4609. var iInsert = 0;
  4610. for (i = 0; i < iCol; i++) {
  4611. if (aoColumns[i].bVisible) {
  4612. iInsert++;
  4613. }
  4614. }
  4615. /* Need to decide if we should use appendChild or insertBefore */
  4616. bAppend = (iInsert >= _fnVisbleColumns(oSettings));
  4617. /* Which coloumn should we be inserting before? */
  4618. if (!bAppend) {
  4619. for (i = iCol; i < aoColumns.length; i++) {
  4620. if (aoColumns[i].bVisible) {
  4621. iBefore = i;
  4622. break;
  4623. }
  4624. }
  4625. }
  4626. for (i = 0, iLen = aoData.length; i < iLen; i++) {
  4627. if (aoData[i].nTr !== null) {
  4628. if (bAppend) {
  4629. aoData[i].nTr.appendChild(
  4630. aoData[i]._anHidden[iCol]
  4631. );
  4632. }
  4633. else {
  4634. aoData[i].nTr.insertBefore(
  4635. aoData[i]._anHidden[iCol],
  4636. _fnGetTdNodes(oSettings, i)[iBefore]);
  4637. }
  4638. }
  4639. }
  4640. }
  4641. else {
  4642. /* Remove a column from display */
  4643. for (i = 0, iLen = aoData.length; i < iLen; i++) {
  4644. if (aoData[i].nTr !== null) {
  4645. nTd = _fnGetTdNodes(oSettings, i)[iCol];
  4646. aoData[i]._anHidden[iCol] = nTd;
  4647. nTd.parentNode.removeChild(nTd);
  4648. }
  4649. }
  4650. }
  4651. /* Clear to set the visible flag */
  4652. aoColumns[iCol].bVisible = bShow;
  4653. /* Redraw the header and footer based on the new column visibility */
  4654. _fnDrawHead(oSettings, oSettings.aoHeader);
  4655. if (oSettings.nTFoot) {
  4656. _fnDrawHead(oSettings, oSettings.aoFooter);
  4657. }
  4658. /* If there are any 'open' rows, then we need to alter the colspan for this col change */
  4659. for (i = 0, iLen = oSettings.aoOpenRows.length; i < iLen; i++) {
  4660. oSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns(oSettings);
  4661. }
  4662. /* Do a redraw incase anything depending on the table columns needs it
  4663. * (built-in: scrolling)
  4664. */
  4665. if (bRedraw === undefined || bRedraw) {
  4666. _fnAdjustColumnSizing(oSettings);
  4667. _fnDraw(oSettings);
  4668. }
  4669. _fnSaveState(oSettings);
  4670. };
  4671. /**
  4672. * Get the settings for a particular table for external manipulation
  4673. * @returns {object} DataTables settings object. See
  4674. * {@link DataTable.models.oSettings}
  4675. * @dtopt API
  4676. *
  4677. * @example
  4678. * $(document).ready(function() {
  4679. * var oTable = $('#example').dataTable();
  4680. * var oSettings = oTable.fnSettings();
  4681. *
  4682. * // Show an example parameter from the settings
  4683. * alert( oSettings._iDisplayStart );
  4684. * } );
  4685. */
  4686. this.fnSettings = function () {
  4687. return _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4688. };
  4689. /**
  4690. * Sort the table by a particular column
  4691. * @param {int} iCol the data index to sort on. Note that this will not match the
  4692. * 'display index' if you have hidden data entries
  4693. * @dtopt API
  4694. *
  4695. * @example
  4696. * $(document).ready(function() {
  4697. * var oTable = $('#example').dataTable();
  4698. *
  4699. * // Sort immediately with columns 0 and 1
  4700. * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
  4701. * } );
  4702. */
  4703. this.fnSort = function (aaSort) {
  4704. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4705. oSettings.aaSorting = aaSort;
  4706. _fnSort(oSettings);
  4707. };
  4708. /**
  4709. * Attach a sort listener to an element for a given column
  4710. * @param {node} nNode the element to attach the sort listener to
  4711. * @param {int} iColumn the column that a click on this node will sort on
  4712. * @param {function} [fnCallback] callback function when sort is run
  4713. * @dtopt API
  4714. *
  4715. * @example
  4716. * $(document).ready(function() {
  4717. * var oTable = $('#example').dataTable();
  4718. *
  4719. * // Sort on column 1, when 'sorter' is clicked on
  4720. * oTable.fnSortListener( document.getElementById('sorter'), 1 );
  4721. * } );
  4722. */
  4723. this.fnSortListener = function (nNode, iColumn, fnCallback) {
  4724. _fnSortAttachListener(_fnSettingsFromNode(this[DataTable.ext.iApiIndex]), nNode, iColumn,
  4725. fnCallback);
  4726. };
  4727. /**
  4728. * Update a table cell or row - this method will accept either a single value to
  4729. * update the cell with, an array of values with one element for each column or
  4730. * an object in the same format as the original data source. The function is
  4731. * self-referencing in order to make the multi column updates easier.
  4732. * @param {object|array|string} mData Data to update the cell/row with
  4733. * @param {node|int} mRow TR element you want to update or the aoData index
  4734. * @param {int} [iColumn] The column to update (not used of mData is an array or object)
  4735. * @param {bool} [bRedraw=true] Redraw the table or not
  4736. * @param {bool} [bAction=true] Perform pre-draw actions or not
  4737. * @returns {int} 0 on success, 1 on error
  4738. * @dtopt API
  4739. *
  4740. * @example
  4741. * $(document).ready(function() {
  4742. * var oTable = $('#example').dataTable();
  4743. * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
  4744. * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], 1, 0 ); // Row
  4745. * } );
  4746. */
  4747. this.fnUpdate = function (mData, mRow, iColumn, bRedraw, bAction) {
  4748. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4749. var i, iLen, sDisplay;
  4750. var iRow = (typeof mRow === 'object') ?
  4751. _fnNodeToDataIndex(oSettings, mRow) : mRow;
  4752. if ($.isArray(mData) && iColumn === undefined) {
  4753. /* Array update - update the whole row */
  4754. oSettings.aoData[iRow]._aData = mData.slice();
  4755. /* Flag to the function that we are recursing */
  4756. for (i = 0; i < oSettings.aoColumns.length; i++) {
  4757. this.fnUpdate(_fnGetCellData(oSettings, iRow, i), iRow, i, false, false);
  4758. }
  4759. }
  4760. else if ($.isPlainObject(mData) && iColumn === undefined) {
  4761. /* Object update - update the whole row - assume the developer gets the object right */
  4762. oSettings.aoData[iRow]._aData = $.extend(true, {}, mData);
  4763. for (i = 0; i < oSettings.aoColumns.length; i++) {
  4764. this.fnUpdate(_fnGetCellData(oSettings, iRow, i), iRow, i, false, false);
  4765. }
  4766. }
  4767. else {
  4768. /* Individual cell update */
  4769. _fnSetCellData(oSettings, iRow, iColumn, mData);
  4770. sDisplay = _fnGetCellData(oSettings, iRow, iColumn, 'display');
  4771. var oCol = oSettings.aoColumns[iColumn];
  4772. if (oCol.fnRender !== null) {
  4773. sDisplay = _fnRender(oSettings, iRow, iColumn);
  4774. if (oCol.bUseRendered) {
  4775. _fnSetCellData(oSettings, iRow, iColumn, sDisplay);
  4776. }
  4777. }
  4778. if (oSettings.aoData[iRow].nTr !== null) {
  4779. /* Do the actual HTML update */
  4780. _fnGetTdNodes(oSettings, iRow)[iColumn].innerHTML = sDisplay;
  4781. }
  4782. }
  4783. /* Modify the search index for this row (strictly this is likely not needed, since fnReDraw
  4784. * will rebuild the search array - however, the redraw might be disabled by the user)
  4785. */
  4786. var iDisplayIndex = $.inArray(iRow, oSettings.aiDisplay);
  4787. oSettings.asDataSearch[iDisplayIndex] = _fnBuildSearchRow(
  4788. oSettings,
  4789. _fnGetRowData(oSettings, iRow, 'filter', _fnGetColumns(oSettings, 'bSearchable'))
  4790. );
  4791. /* Perform pre-draw actions */
  4792. if (bAction === undefined || bAction) {
  4793. _fnAdjustColumnSizing(oSettings);
  4794. }
  4795. /* Redraw the table */
  4796. if (bRedraw === undefined || bRedraw) {
  4797. _fnReDraw(oSettings);
  4798. }
  4799. return 0;
  4800. };
  4801. /**
  4802. * Provide a common method for plug-ins to check the version of DataTables being used, in order
  4803. * to ensure compatibility.
  4804. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
  4805. * formats "X" and "X.Y" are also acceptable.
  4806. * @returns {boolean} true if this version of DataTables is greater or equal to the required
  4807. * version, or false if this version of DataTales is not suitable
  4808. * @method
  4809. * @dtopt API
  4810. *
  4811. * @example
  4812. * $(document).ready(function() {
  4813. * var oTable = $('#example').dataTable();
  4814. * alert( oTable.fnVersionCheck( '1.9.0' ) );
  4815. * } );
  4816. */
  4817. this.fnVersionCheck = DataTable.ext.fnVersionCheck;
  4818. /*
  4819. * This is really a good bit rubbish this method of exposing the internal methods
  4820. * publicly... - To be fixed in 2.0 using methods on the prototype
  4821. */
  4822. /**
  4823. * Create a wrapper function for exporting an internal functions to an external API.
  4824. * @param {string} sFunc API function name
  4825. * @returns {function} wrapped function
  4826. * @memberof DataTable#oApi
  4827. */
  4828. function _fnExternApiFunc(sFunc) {
  4829. return function () {
  4830. var aArgs = [_fnSettingsFromNode(this[DataTable.ext.iApiIndex])].concat(
  4831. Array.prototype.slice.call(arguments));
  4832. return DataTable.ext.oApi[sFunc].apply(this, aArgs);
  4833. };
  4834. }
  4835. /**
  4836. * Reference to internal functions for use by plug-in developers. Note that these
  4837. * methods are references to internal functions and are considered to be private.
  4838. * If you use these methods, be aware that they are liable to change between versions
  4839. * (check the upgrade notes).
  4840. * @namespace
  4841. */
  4842. this.oApi = {
  4843. "_fnExternApiFunc":_fnExternApiFunc,
  4844. "_fnInitialise":_fnInitialise,
  4845. "_fnInitComplete":_fnInitComplete,
  4846. "_fnLanguageCompat":_fnLanguageCompat,
  4847. "_fnAddColumn":_fnAddColumn,
  4848. "_fnColumnOptions":_fnColumnOptions,
  4849. "_fnAddData":_fnAddData,
  4850. "_fnCreateTr":_fnCreateTr,
  4851. "_fnGatherData":_fnGatherData,
  4852. "_fnBuildHead":_fnBuildHead,
  4853. "_fnDrawHead":_fnDrawHead,
  4854. "_fnDraw":_fnDraw,
  4855. "_fnReDraw":_fnReDraw,
  4856. "_fnAjaxUpdate":_fnAjaxUpdate,
  4857. "_fnAjaxParameters":_fnAjaxParameters,
  4858. "_fnAjaxUpdateDraw":_fnAjaxUpdateDraw,
  4859. "_fnServerParams":_fnServerParams,
  4860. "_fnAddOptionsHtml":_fnAddOptionsHtml,
  4861. "_fnFeatureHtmlTable":_fnFeatureHtmlTable,
  4862. "_fnScrollDraw":_fnScrollDraw,
  4863. "_fnAdjustColumnSizing":_fnAdjustColumnSizing,
  4864. "_fnFeatureHtmlFilter":_fnFeatureHtmlFilter,
  4865. "_fnFilterComplete":_fnFilterComplete,
  4866. "_fnFilterCustom":_fnFilterCustom,
  4867. "_fnFilterColumn":_fnFilterColumn,
  4868. "_fnFilter":_fnFilter,
  4869. "_fnBuildSearchArray":_fnBuildSearchArray,
  4870. "_fnBuildSearchRow":_fnBuildSearchRow,
  4871. "_fnFilterCreateSearch":_fnFilterCreateSearch,
  4872. "_fnDataToSearch":_fnDataToSearch,
  4873. "_fnSort":_fnSort,
  4874. "_fnSortAttachListener":_fnSortAttachListener,
  4875. "_fnSortingClasses":_fnSortingClasses,
  4876. "_fnFeatureHtmlPaginate":_fnFeatureHtmlPaginate,
  4877. "_fnPageChange":_fnPageChange,
  4878. "_fnFeatureHtmlInfo":_fnFeatureHtmlInfo,
  4879. "_fnUpdateInfo":_fnUpdateInfo,
  4880. "_fnFeatureHtmlLength":_fnFeatureHtmlLength,
  4881. "_fnFeatureHtmlProcessing":_fnFeatureHtmlProcessing,
  4882. "_fnProcessingDisplay":_fnProcessingDisplay,
  4883. "_fnVisibleToColumnIndex":_fnVisibleToColumnIndex,
  4884. "_fnColumnIndexToVisible":_fnColumnIndexToVisible,
  4885. "_fnNodeToDataIndex":_fnNodeToDataIndex,
  4886. "_fnVisbleColumns":_fnVisbleColumns,
  4887. "_fnCalculateEnd":_fnCalculateEnd,
  4888. "_fnConvertToWidth":_fnConvertToWidth,
  4889. "_fnCalculateColumnWidths":_fnCalculateColumnWidths,
  4890. "_fnScrollingWidthAdjust":_fnScrollingWidthAdjust,
  4891. "_fnGetWidestNode":_fnGetWidestNode,
  4892. "_fnGetMaxLenString":_fnGetMaxLenString,
  4893. "_fnStringToCss":_fnStringToCss,
  4894. "_fnDetectType":_fnDetectType,
  4895. "_fnSettingsFromNode":_fnSettingsFromNode,
  4896. "_fnGetDataMaster":_fnGetDataMaster,
  4897. "_fnGetTrNodes":_fnGetTrNodes,
  4898. "_fnGetTdNodes":_fnGetTdNodes,
  4899. "_fnEscapeRegex":_fnEscapeRegex,
  4900. "_fnDeleteIndex":_fnDeleteIndex,
  4901. "_fnReOrderIndex":_fnReOrderIndex,
  4902. "_fnColumnOrdering":_fnColumnOrdering,
  4903. "_fnLog":_fnLog,
  4904. "_fnClearTable":_fnClearTable,
  4905. "_fnSaveState":_fnSaveState,
  4906. "_fnLoadState":_fnLoadState,
  4907. "_fnCreateCookie":_fnCreateCookie,
  4908. "_fnReadCookie":_fnReadCookie,
  4909. "_fnDetectHeader":_fnDetectHeader,
  4910. "_fnGetUniqueThs":_fnGetUniqueThs,
  4911. "_fnScrollBarWidth":_fnScrollBarWidth,
  4912. "_fnApplyToChildren":_fnApplyToChildren,
  4913. "_fnMap":_fnMap,
  4914. "_fnGetRowData":_fnGetRowData,
  4915. "_fnGetCellData":_fnGetCellData,
  4916. "_fnSetCellData":_fnSetCellData,
  4917. "_fnGetObjectDataFn":_fnGetObjectDataFn,
  4918. "_fnSetObjectDataFn":_fnSetObjectDataFn,
  4919. "_fnApplyColumnDefs":_fnApplyColumnDefs,
  4920. "_fnBindAction":_fnBindAction,
  4921. "_fnExtend":_fnExtend,
  4922. "_fnCallbackReg":_fnCallbackReg,
  4923. "_fnCallbackFire":_fnCallbackFire,
  4924. "_fnJsonString":_fnJsonString,
  4925. "_fnRender":_fnRender,
  4926. "_fnNodeToColumnIndex":_fnNodeToColumnIndex,
  4927. "_fnInfoMacros":_fnInfoMacros,
  4928. "_fnBrowserDetect":_fnBrowserDetect,
  4929. "_fnGetColumns":_fnGetColumns
  4930. };
  4931. $.extend(DataTable.ext.oApi, this.oApi);
  4932. for (var sFunc in DataTable.ext.oApi) {
  4933. if (sFunc) {
  4934. this[sFunc] = _fnExternApiFunc(sFunc);
  4935. }
  4936. }
  4937. var _that = this;
  4938. this.each(function () {
  4939. var i = 0, iLen, j, jLen, k, kLen;
  4940. var sId = this.getAttribute('id');
  4941. var bInitHandedOff = false;
  4942. var bUsePassedData = false;
  4943. /* Sanity check */
  4944. if (this.nodeName.toLowerCase() != 'table') {
  4945. _fnLog(null, 0, "Attempted to initialise DataTables on a node which is not a " +
  4946. "table: " + this.nodeName);
  4947. return;
  4948. }
  4949. /* Check to see if we are re-initialising a table */
  4950. for (i = 0, iLen = DataTable.settings.length; i < iLen; i++) {
  4951. /* Base check on table node */
  4952. if (DataTable.settings[i].nTable == this) {
  4953. if (oInit === undefined || oInit.bRetrieve) {
  4954. return DataTable.settings[i].oInstance;
  4955. }
  4956. else if (oInit.bDestroy) {
  4957. DataTable.settings[i].oInstance.fnDestroy();
  4958. break;
  4959. }
  4960. else {
  4961. _fnLog(DataTable.settings[i], 0, "Cannot reinitialise DataTable.\n\n" +
  4962. "To retrieve the DataTables object for this table, pass no arguments or see " +
  4963. "the docs for bRetrieve and bDestroy");
  4964. return;
  4965. }
  4966. }
  4967. /* If the element we are initialising has the same ID as a table which was previously
  4968. * initialised, but the table nodes don't match (from before) then we destroy the old
  4969. * instance by simply deleting it. This is under the assumption that the table has been
  4970. * destroyed by other methods. Anyone using non-id selectors will need to do this manually
  4971. */
  4972. if (DataTable.settings[i].sTableId == this.id) {
  4973. DataTable.settings.splice(i, 1);
  4974. break;
  4975. }
  4976. }
  4977. /* Ensure the table has an ID - required for accessibility */
  4978. if (sId === null || sId === "") {
  4979. sId = "DataTables_Table_" + (DataTable.ext._oExternConfig.iNextUnique++);
  4980. this.id = sId;
  4981. }
  4982. /* Create the settings object for this table and set some of the default parameters */
  4983. var oSettings = $.extend(true, {}, DataTable.models.oSettings, {
  4984. "nTable":this,
  4985. "oApi":_that.oApi,
  4986. "oInit":oInit,
  4987. "sDestroyWidth":$(this).width(),
  4988. "sInstance":sId,
  4989. "sTableId":sId
  4990. });
  4991. DataTable.settings.push(oSettings);
  4992. // Need to add the instance after the instance after the settings object has been added
  4993. // to the settings array, so we can self reference the table instance if more than one
  4994. oSettings.oInstance = (_that.length === 1) ? _that : $(this).dataTable();
  4995. /* Setting up the initialisation object */
  4996. if (!oInit) {
  4997. oInit = {};
  4998. }
  4999. // Backwards compatibility, before we apply all the defaults
  5000. if (oInit.oLanguage) {
  5001. _fnLanguageCompat(oInit.oLanguage);
  5002. }
  5003. oInit = _fnExtend($.extend(true, {}, DataTable.defaults), oInit);
  5004. // Map the initialisation options onto the settings object
  5005. _fnMap(oSettings.oFeatures, oInit, "bPaginate");
  5006. _fnMap(oSettings.oFeatures, oInit, "bLengthChange");
  5007. _fnMap(oSettings.oFeatures, oInit, "bFilter");
  5008. _fnMap(oSettings.oFeatures, oInit, "bSort");
  5009. _fnMap(oSettings.oFeatures, oInit, "bInfo");
  5010. _fnMap(oSettings.oFeatures, oInit, "bProcessing");
  5011. _fnMap(oSettings.oFeatures, oInit, "bAutoWidth");
  5012. _fnMap(oSettings.oFeatures, oInit, "bSortClasses");
  5013. _fnMap(oSettings.oFeatures, oInit, "bServerSide");
  5014. _fnMap(oSettings.oFeatures, oInit, "bDeferRender");
  5015. _fnMap(oSettings.oScroll, oInit, "sScrollX", "sX");
  5016. _fnMap(oSettings.oScroll, oInit, "sScrollXInner", "sXInner");
  5017. _fnMap(oSettings.oScroll, oInit, "sScrollY", "sY");
  5018. _fnMap(oSettings.oScroll, oInit, "bScrollCollapse", "bCollapse");
  5019. _fnMap(oSettings.oScroll, oInit, "bScrollInfinite", "bInfinite");
  5020. _fnMap(oSettings.oScroll, oInit, "iScrollLoadGap", "iLoadGap");
  5021. _fnMap(oSettings.oScroll, oInit, "bScrollAutoCss", "bAutoCss");
  5022. _fnMap(oSettings, oInit, "asStripeClasses");
  5023. _fnMap(oSettings, oInit, "asStripClasses", "asStripeClasses"); // legacy
  5024. _fnMap(oSettings, oInit, "fnServerData");
  5025. _fnMap(oSettings, oInit, "fnFormatNumber");
  5026. _fnMap(oSettings, oInit, "sServerMethod");
  5027. _fnMap(oSettings, oInit, "aaSorting");
  5028. _fnMap(oSettings, oInit, "aaSortingFixed");
  5029. _fnMap(oSettings, oInit, "aLengthMenu");
  5030. _fnMap(oSettings, oInit, "sPaginationType");
  5031. _fnMap(oSettings, oInit, "sAjaxSource");
  5032. _fnMap(oSettings, oInit, "sAjaxDataProp");
  5033. _fnMap(oSettings, oInit, "iCookieDuration");
  5034. _fnMap(oSettings, oInit, "sCookiePrefix");
  5035. _fnMap(oSettings, oInit, "sDom");
  5036. _fnMap(oSettings, oInit, "bSortCellsTop");
  5037. _fnMap(oSettings, oInit, "iTabIndex");
  5038. _fnMap(oSettings, oInit, "oSearch", "oPreviousSearch");
  5039. _fnMap(oSettings, oInit, "aoSearchCols", "aoPreSearchCols");
  5040. _fnMap(oSettings, oInit, "iDisplayLength", "_iDisplayLength");
  5041. _fnMap(oSettings, oInit, "bJQueryUI", "bJUI");
  5042. _fnMap(oSettings, oInit, "fnCookieCallback");
  5043. _fnMap(oSettings, oInit, "fnStateLoad");
  5044. _fnMap(oSettings, oInit, "fnStateSave");
  5045. _fnMap(oSettings.oLanguage, oInit, "fnInfoCallback");
  5046. /* Callback functions which are array driven */
  5047. _fnCallbackReg(oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user');
  5048. _fnCallbackReg(oSettings, 'aoServerParams', oInit.fnServerParams, 'user');
  5049. _fnCallbackReg(oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user');
  5050. _fnCallbackReg(oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user');
  5051. _fnCallbackReg(oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user');
  5052. _fnCallbackReg(oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user');
  5053. _fnCallbackReg(oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user');
  5054. _fnCallbackReg(oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user');
  5055. _fnCallbackReg(oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user');
  5056. _fnCallbackReg(oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user');
  5057. _fnCallbackReg(oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user');
  5058. if (oSettings.oFeatures.bServerSide && oSettings.oFeatures.bSort &&
  5059. oSettings.oFeatures.bSortClasses) {
  5060. /* Enable sort classes for server-side processing. Safe to do it here, since server-side
  5061. * processing must be enabled by the developer
  5062. */
  5063. _fnCallbackReg(oSettings, 'aoDrawCallback', _fnSortingClasses, 'server_side_sort_classes');
  5064. }
  5065. else if (oSettings.oFeatures.bDeferRender) {
  5066. _fnCallbackReg(oSettings, 'aoDrawCallback', _fnSortingClasses, 'defer_sort_classes');
  5067. }
  5068. if (oInit.bJQueryUI) {
  5069. /* Use the JUI classes object for display. You could clone the oStdClasses object if
  5070. * you want to have multiple tables with multiple independent classes
  5071. */
  5072. $.extend(oSettings.oClasses, DataTable.ext.oJUIClasses);
  5073. if (oInit.sDom === DataTable.defaults.sDom && DataTable.defaults.sDom === "lfrtip") {
  5074. /* Set the DOM to use a layout suitable for jQuery UI's theming */
  5075. oSettings.sDom = '<"H"lfr>t<"F"ip>';
  5076. }
  5077. }
  5078. else {
  5079. $.extend(oSettings.oClasses, DataTable.ext.oStdClasses);
  5080. }
  5081. $(this).addClass(oSettings.oClasses.sTable);
  5082. /* Calculate the scroll bar width and cache it for use later on */
  5083. if (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") {
  5084. oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
  5085. }
  5086. if (oSettings.iInitDisplayStart === undefined) {
  5087. /* Display start point, taking into account the save saving */
  5088. oSettings.iInitDisplayStart = oInit.iDisplayStart;
  5089. oSettings._iDisplayStart = oInit.iDisplayStart;
  5090. }
  5091. /* Must be done after everything which can be overridden by a cookie! */
  5092. if (oInit.bStateSave) {
  5093. oSettings.oFeatures.bStateSave = true;
  5094. _fnLoadState(oSettings, oInit);
  5095. _fnCallbackReg(oSettings, 'aoDrawCallback', _fnSaveState, 'state_save');
  5096. }
  5097. if (oInit.iDeferLoading !== null) {
  5098. oSettings.bDeferLoading = true;
  5099. var tmp = $.isArray(oInit.iDeferLoading);
  5100. oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
  5101. oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
  5102. }
  5103. if (oInit.aaData !== null) {
  5104. bUsePassedData = true;
  5105. }
  5106. /* Language definitions */
  5107. if (oInit.oLanguage.sUrl !== "") {
  5108. /* Get the language definitions from a file - because this Ajax call makes the language
  5109. * get async to the remainder of this function we use bInitHandedOff to indicate that
  5110. * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
  5111. */
  5112. oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;
  5113. $.getJSON(oSettings.oLanguage.sUrl, null, function (json) {
  5114. _fnLanguageCompat(json);
  5115. $.extend(true, oSettings.oLanguage, oInit.oLanguage, json);
  5116. _fnInitialise(oSettings);
  5117. });
  5118. bInitHandedOff = true;
  5119. }
  5120. else {
  5121. $.extend(true, oSettings.oLanguage, oInit.oLanguage);
  5122. }
  5123. /*
  5124. * Stripes
  5125. */
  5126. if (oInit.asStripeClasses === null) {
  5127. oSettings.asStripeClasses = [
  5128. oSettings.oClasses.sStripeOdd,
  5129. oSettings.oClasses.sStripeEven
  5130. ];
  5131. }
  5132. /* Remove row stripe classes if they are already on the table row */
  5133. iLen = oSettings.asStripeClasses.length;
  5134. oSettings.asDestroyStripes = [];
  5135. if (iLen) {
  5136. var bStripeRemove = false;
  5137. var anRows = $(this).children('tbody').children('tr:lt(' + iLen + ')');
  5138. for (i = 0; i < iLen; i++) {
  5139. if (anRows.hasClass(oSettings.asStripeClasses[i])) {
  5140. bStripeRemove = true;
  5141. /* Store the classes which we are about to remove so they can be re-added on destroy */
  5142. oSettings.asDestroyStripes.push(oSettings.asStripeClasses[i]);
  5143. }
  5144. }
  5145. if (bStripeRemove) {
  5146. anRows.removeClass(oSettings.asStripeClasses.join(' '));
  5147. }
  5148. }
  5149. /*
  5150. * Columns
  5151. * See if we should load columns automatically or use defined ones
  5152. */
  5153. var anThs = [];
  5154. var aoColumnsInit;
  5155. var nThead = this.getElementsByTagName('thead');
  5156. if (nThead.length !== 0) {
  5157. _fnDetectHeader(oSettings.aoHeader, nThead[0]);
  5158. anThs = _fnGetUniqueThs(oSettings);
  5159. }
  5160. /* If not given a column array, generate one with nulls */
  5161. if (oInit.aoColumns === null) {
  5162. aoColumnsInit = [];
  5163. for (i = 0, iLen = anThs.length; i < iLen; i++) {
  5164. aoColumnsInit.push(null);
  5165. }
  5166. }
  5167. else {
  5168. aoColumnsInit = oInit.aoColumns;
  5169. }
  5170. /* Add the columns */
  5171. for (i = 0, iLen = aoColumnsInit.length; i < iLen; i++) {
  5172. /* Short cut - use the loop to check if we have column visibility state to restore */
  5173. if (oInit.saved_aoColumns !== undefined && oInit.saved_aoColumns.length == iLen) {
  5174. if (aoColumnsInit[i] === null) {
  5175. aoColumnsInit[i] = {};
  5176. }
  5177. aoColumnsInit[i].bVisible = oInit.saved_aoColumns[i].bVisible;
  5178. }
  5179. _fnAddColumn(oSettings, anThs ? anThs[i] : null);
  5180. }
  5181. /* Apply the column definitions */
  5182. _fnApplyColumnDefs(oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
  5183. _fnColumnOptions(oSettings, iCol, oDef);
  5184. });
  5185. /*
  5186. * Sorting
  5187. * Check the aaSorting array
  5188. */
  5189. for (i = 0, iLen = oSettings.aaSorting.length; i < iLen; i++) {
  5190. if (oSettings.aaSorting[i][0] >= oSettings.aoColumns.length) {
  5191. oSettings.aaSorting[i][0] = 0;
  5192. }
  5193. var oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ];
  5194. /* Add a default sorting index */
  5195. if (oSettings.aaSorting[i][2] === undefined) {
  5196. oSettings.aaSorting[i][2] = 0;
  5197. }
  5198. /* If aaSorting is not defined, then we use the first indicator in asSorting */
  5199. if (oInit.aaSorting === undefined && oSettings.saved_aaSorting === undefined) {
  5200. oSettings.aaSorting[i][1] = oColumn.asSorting[0];
  5201. }
  5202. /* Set the current sorting index based on aoColumns.asSorting */
  5203. for (j = 0, jLen = oColumn.asSorting.length; j < jLen; j++) {
  5204. if (oSettings.aaSorting[i][1] == oColumn.asSorting[j]) {
  5205. oSettings.aaSorting[i][2] = j;
  5206. break;
  5207. }
  5208. }
  5209. }
  5210. /* Do a first pass on the sorting classes (allows any size changes to be taken into
  5211. * account, and also will apply sorting disabled classes if disabled
  5212. */
  5213. _fnSortingClasses(oSettings);
  5214. /*
  5215. * Final init
  5216. * Cache the header, body and footer as required, creating them if needed
  5217. */
  5218. /* Browser support detection */
  5219. _fnBrowserDetect(oSettings);
  5220. // Work around for Webkit bug 83867 - store the caption-side before removing from doc
  5221. var captions = $(this).children('caption').each(function () {
  5222. this._captionSide = $(this).css('caption-side');
  5223. });
  5224. var thead = $(this).children('thead');
  5225. if (thead.length === 0) {
  5226. thead = [ document.createElement('thead') ];
  5227. this.appendChild(thead[0]);
  5228. }
  5229. oSettings.nTHead = thead[0];
  5230. var tbody = $(this).children('tbody');
  5231. if (tbody.length === 0) {
  5232. tbody = [ document.createElement('tbody') ];
  5233. this.appendChild(tbody[0]);
  5234. }
  5235. oSettings.nTBody = tbody[0];
  5236. oSettings.nTBody.setAttribute("role", "alert");
  5237. oSettings.nTBody.setAttribute("aria-live", "polite");
  5238. oSettings.nTBody.setAttribute("aria-relevant", "all");
  5239. var tfoot = $(this).children('tfoot');
  5240. if (tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "")) {
  5241. // If we are a scrolling table, and no footer has been given, then we need to create
  5242. // a tfoot element for the caption element to be appended to
  5243. tfoot = [ document.createElement('tfoot') ];
  5244. this.appendChild(tfoot[0]);
  5245. }
  5246. if (tfoot.length > 0) {
  5247. oSettings.nTFoot = tfoot[0];
  5248. _fnDetectHeader(oSettings.aoFooter, oSettings.nTFoot);
  5249. }
  5250. /* Check if there is data passing into the constructor */
  5251. if (bUsePassedData) {
  5252. for (i = 0; i < oInit.aaData.length; i++) {
  5253. _fnAddData(oSettings, oInit.aaData[ i ]);
  5254. }
  5255. }
  5256. else {
  5257. /* Grab the data from the page */
  5258. _fnGatherData(oSettings);
  5259. }
  5260. /* Copy the data index array */
  5261. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  5262. /* Initialisation complete - table can be drawn */
  5263. oSettings.bInitialised = true;
  5264. /* Check if we need to initialise the table (it might not have been handed off to the
  5265. * language processor)
  5266. */
  5267. if (bInitHandedOff === false) {
  5268. _fnInitialise(oSettings);
  5269. }
  5270. });
  5271. _that = null;
  5272. return this;
  5273. };
  5274. /**
  5275. * Provide a common method for plug-ins to check the version of DataTables being used, in order
  5276. * to ensure compatibility.
  5277. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
  5278. * formats "X" and "X.Y" are also acceptable.
  5279. * @returns {boolean} true if this version of DataTables is greater or equal to the required
  5280. * version, or false if this version of DataTales is not suitable
  5281. * @static
  5282. * @dtopt API-Static
  5283. *
  5284. * @example
  5285. * alert( $.fn.dataTable.fnVersionCheck( '1.9.0' ) );
  5286. */
  5287. DataTable.fnVersionCheck = function (sVersion) {
  5288. /* This is cheap, but effective */
  5289. var fnZPad = function (Zpad, count) {
  5290. while (Zpad.length < count) {
  5291. Zpad += '0';
  5292. }
  5293. return Zpad;
  5294. };
  5295. var aThis = DataTable.ext.sVersion.split('.');
  5296. var aThat = sVersion.split('.');
  5297. var sThis = '', sThat = '';
  5298. for (var i = 0, iLen = aThat.length; i < iLen; i++) {
  5299. sThis += fnZPad(aThis[i], 3);
  5300. sThat += fnZPad(aThat[i], 3);
  5301. }
  5302. return parseInt(sThis, 10) >= parseInt(sThat, 10);
  5303. };
  5304. /**
  5305. * Check if a TABLE node is a DataTable table already or not.
  5306. * @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other
  5307. * node types can be passed in, but will always return false).
  5308. * @returns {boolean} true the table given is a DataTable, or false otherwise
  5309. * @static
  5310. * @dtopt API-Static
  5311. *
  5312. * @example
  5313. * var ex = document.getElementById('example');
  5314. * if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) {
  5315. * $(ex).dataTable();
  5316. * }
  5317. */
  5318. DataTable.fnIsDataTable = function (nTable) {
  5319. var o = DataTable.settings;
  5320. for (var i = 0; i < o.length; i++) {
  5321. if (o[i].nTable === nTable || o[i].nScrollHead === nTable || o[i].nScrollFoot === nTable) {
  5322. return true;
  5323. }
  5324. }
  5325. return false;
  5326. };
  5327. /**
  5328. * Get all DataTable tables that have been initialised - optionally you can select to
  5329. * get only currently visible tables.
  5330. * @param {boolean} [bVisible=false] Flag to indicate if you want all (default) or
  5331. * visible tables only.
  5332. * @returns {array} Array of TABLE nodes (not DataTable instances) which are DataTables
  5333. * @static
  5334. * @dtopt API-Static
  5335. *
  5336. * @example
  5337. * var table = $.fn.dataTable.fnTables(true);
  5338. * if ( table.length > 0 ) {
  5339. * $(table).dataTable().fnAdjustColumnSizing();
  5340. * }
  5341. */
  5342. DataTable.fnTables = function (bVisible) {
  5343. var out = [];
  5344. jQuery.each(DataTable.settings, function (i, o) {
  5345. if (!bVisible || (bVisible === true && $(o.nTable).is(':visible'))) {
  5346. out.push(o.nTable);
  5347. }
  5348. });
  5349. return out;
  5350. };
  5351. /**
  5352. * Version string for plug-ins to check compatibility. Allowed format is
  5353. * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
  5354. * e are optional
  5355. * @member
  5356. * @type string
  5357. * @default Version number
  5358. */
  5359. DataTable.version = "1.9.4";
  5360. /**
  5361. * Private data store, containing all of the settings objects that are created for the
  5362. * tables on a given page.
  5363. *
  5364. * Note that the <i>DataTable.settings</i> object is aliased to <i>jQuery.fn.dataTableExt</i>
  5365. * through which it may be accessed and manipulated, or <i>jQuery.fn.dataTable.settings</i>.
  5366. * @member
  5367. * @type array
  5368. * @default []
  5369. * @private
  5370. */
  5371. DataTable.settings = [];
  5372. /**
  5373. * Object models container, for the various models that DataTables has available
  5374. * to it. These models define the objects that are used to hold the active state
  5375. * and configuration of the table.
  5376. * @namespace
  5377. */
  5378. DataTable.models = {};
  5379. /**
  5380. * DataTables extension options and plug-ins. This namespace acts as a collection "area"
  5381. * for plug-ins that can be used to extend the default DataTables behaviour - indeed many
  5382. * of the build in methods use this method to provide their own capabilities (sorting methods
  5383. * for example).
  5384. *
  5385. * Note that this namespace is aliased to jQuery.fn.dataTableExt so it can be readily accessed
  5386. * and modified by plug-ins.
  5387. * @namespace
  5388. */
  5389. DataTable.models.ext = {
  5390. /**
  5391. * Plug-in filtering functions - this method of filtering is complimentary to the default
  5392. * type based filtering, and a lot more comprehensive as it allows you complete control
  5393. * over the filtering logic. Each element in this array is a function (parameters
  5394. * described below) that is called for every row in the table, and your logic decides if
  5395. * it should be included in the filtered data set or not.
  5396. * <ul>
  5397. * <li>
  5398. * Function input parameters:
  5399. * <ul>
  5400. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  5401. * <li>{array|object} Data for the row to be processed (same as the original format
  5402. * that was passed in as the data source, or an array from a DOM data source</li>
  5403. * <li>{int} Row index in aoData ({@link DataTable.models.oSettings.aoData}), which can
  5404. * be useful to retrieve the TR element if you need DOM interaction.</li>
  5405. * </ul>
  5406. * </li>
  5407. * <li>
  5408. * Function return:
  5409. * <ul>
  5410. * <li>{boolean} Include the row in the filtered result set (true) or not (false)</li>
  5411. * </ul>
  5412. * </il>
  5413. * </ul>
  5414. * @type array
  5415. * @default []
  5416. *
  5417. * @example
  5418. * // The following example shows custom filtering being applied to the fourth column (i.e.
  5419. * // the aData[3] index) based on two input values from the end-user, matching the data in
  5420. * // a certain range.
  5421. * $.fn.dataTableExt.afnFiltering.push(
  5422. * function( oSettings, aData, iDataIndex ) {
  5423. * var iMin = document.getElementById('min').value * 1;
  5424. * var iMax = document.getElementById('max').value * 1;
  5425. * var iVersion = aData[3] == "-" ? 0 : aData[3]*1;
  5426. * if ( iMin == "" && iMax == "" ) {
  5427. * return true;
  5428. * }
  5429. * else if ( iMin == "" && iVersion < iMax ) {
  5430. * return true;
  5431. * }
  5432. * else if ( iMin < iVersion && "" == iMax ) {
  5433. * return true;
  5434. * }
  5435. * else if ( iMin < iVersion && iVersion < iMax ) {
  5436. * return true;
  5437. * }
  5438. * return false;
  5439. * }
  5440. * );
  5441. */
  5442. "afnFiltering":[],
  5443. /**
  5444. * Plug-in sorting functions - this method of sorting is complimentary to the default type
  5445. * based sorting that DataTables does automatically, allowing much greater control over the
  5446. * the data that is being used to sort a column. This is useful if you want to do sorting
  5447. * based on live data (for example the contents of an 'input' element) rather than just the
  5448. * static string that DataTables knows of. The way these plug-ins work is that you create
  5449. * an array of the values you wish to be sorted for the column in question and then return
  5450. * that array. Which pre-sorting function is run here depends on the sSortDataType parameter
  5451. * that is used for the column (if any). This is the corollary of <i>ofnSearch</i> for sort
  5452. * data.
  5453. * <ul>
  5454. * <li>
  5455. * Function input parameters:
  5456. * <ul>
  5457. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  5458. * <li>{int} Target column index</li>
  5459. * </ul>
  5460. * </li>
  5461. * <li>
  5462. * Function return:
  5463. * <ul>
  5464. * <li>{array} Data for the column to be sorted upon</li>
  5465. * </ul>
  5466. * </il>
  5467. * </ul>
  5468. *
  5469. * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for
  5470. * the different uses that DataTables can put the data to. Specifically <i>mData</i> when
  5471. * used as a function will give you a 'type' (sorting, filtering etc) that you can use to
  5472. * prepare the data as required for the different types. As such, this method is deprecated.
  5473. * @type array
  5474. * @default []
  5475. * @deprecated
  5476. *
  5477. * @example
  5478. * // Updating the cached sorting information with user entered values in HTML input elements
  5479. * jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn )
  5480. * {
  5481. * var aData = [];
  5482. * $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
  5483. * aData.push( this.value );
  5484. * } );
  5485. * return aData;
  5486. * }
  5487. */
  5488. "afnSortData":[],
  5489. /**
  5490. * Feature plug-ins - This is an array of objects which describe the feature plug-ins that are
  5491. * available to DataTables. These feature plug-ins are accessible through the sDom initialisation
  5492. * option. As such, each feature plug-in must describe a function that is used to initialise
  5493. * itself (fnInit), a character so the feature can be enabled by sDom (cFeature) and the name
  5494. * of the feature (sFeature). Thus the objects attached to this method must provide:
  5495. * <ul>
  5496. * <li>{function} fnInit Initialisation of the plug-in
  5497. * <ul>
  5498. * <li>
  5499. * Function input parameters:
  5500. * <ul>
  5501. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  5502. * </ul>
  5503. * </li>
  5504. * <li>
  5505. * Function return:
  5506. * <ul>
  5507. * <li>{node|null} The element which contains your feature. Note that the return
  5508. * may also be void if your plug-in does not require to inject any DOM elements
  5509. * into DataTables control (sDom) - for example this might be useful when
  5510. * developing a plug-in which allows table control via keyboard entry.</li>
  5511. * </ul>
  5512. * </il>
  5513. * </ul>
  5514. * </li>
  5515. * <li>{character} cFeature Character that will be matched in sDom - case sensitive</li>
  5516. * <li>{string} sFeature Feature name</li>
  5517. * </ul>
  5518. * @type array
  5519. * @default []
  5520. *
  5521. * @example
  5522. * // How TableTools initialises itself.
  5523. * $.fn.dataTableExt.aoFeatures.push( {
  5524. * "fnInit": function( oSettings ) {
  5525. * return new TableTools( { "oDTSettings": oSettings } );
  5526. * },
  5527. * "cFeature": "T",
  5528. * "sFeature": "TableTools"
  5529. * } );
  5530. */
  5531. "aoFeatures":[],
  5532. /**
  5533. * Type detection plug-in functions - DataTables utilises types to define how sorting and
  5534. * filtering behave, and types can be either be defined by the developer (sType for the
  5535. * column) or they can be automatically detected by the methods in this array. The functions
  5536. * defined in the array are quite simple, taking a single parameter (the data to analyse)
  5537. * and returning the type if it is a known type, or null otherwise.
  5538. * <ul>
  5539. * <li>
  5540. * Function input parameters:
  5541. * <ul>
  5542. * <li>{*} Data from the column cell to be analysed</li>
  5543. * </ul>
  5544. * </li>
  5545. * <li>
  5546. * Function return:
  5547. * <ul>
  5548. * <li>{string|null} Data type detected, or null if unknown (and thus pass it
  5549. * on to the other type detection functions.</li>
  5550. * </ul>
  5551. * </il>
  5552. * </ul>
  5553. * @type array
  5554. * @default []
  5555. *
  5556. * @example
  5557. * // Currency type detection plug-in:
  5558. * jQuery.fn.dataTableExt.aTypes.push(
  5559. * function ( sData ) {
  5560. * var sValidChars = "0123456789.-";
  5561. * var Char;
  5562. *
  5563. * // Check the numeric part
  5564. * for ( i=1 ; i<sData.length ; i++ ) {
  5565. * Char = sData.charAt(i);
  5566. * if (sValidChars.indexOf(Char) == -1) {
  5567. * return null;
  5568. * }
  5569. * }
  5570. *
  5571. * // Check prefixed by currency
  5572. * if ( sData.charAt(0) == '$' || sData.charAt(0) == '&pound;' ) {
  5573. * return 'currency';
  5574. * }
  5575. * return null;
  5576. * }
  5577. * );
  5578. */
  5579. "aTypes":[],
  5580. /**
  5581. * Provide a common method for plug-ins to check the version of DataTables being used,
  5582. * in order to ensure compatibility.
  5583. * @type function
  5584. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note
  5585. * that the formats "X" and "X.Y" are also acceptable.
  5586. * @returns {boolean} true if this version of DataTables is greater or equal to the
  5587. * required version, or false if this version of DataTales is not suitable
  5588. *
  5589. * @example
  5590. * $(document).ready(function() {
  5591. * var oTable = $('#example').dataTable();
  5592. * alert( oTable.fnVersionCheck( '1.9.0' ) );
  5593. * } );
  5594. */
  5595. "fnVersionCheck":DataTable.fnVersionCheck,
  5596. /**
  5597. * Index for what 'this' index API functions should use
  5598. * @type int
  5599. * @default 0
  5600. */
  5601. "iApiIndex":0,
  5602. /**
  5603. * Pre-processing of filtering data plug-ins - When you assign the sType for a column
  5604. * (or have it automatically detected for you by DataTables or a type detection plug-in),
  5605. * you will typically be using this for custom sorting, but it can also be used to provide
  5606. * custom filtering by allowing you to pre-processing the data and returning the data in
  5607. * the format that should be filtered upon. This is done by adding functions this object
  5608. * with a parameter name which matches the sType for that target column. This is the
  5609. * corollary of <i>afnSortData</i> for filtering data.
  5610. * <ul>
  5611. * <li>
  5612. * Function input parameters:
  5613. * <ul>
  5614. * <li>{*} Data from the column cell to be prepared for filtering</li>
  5615. * </ul>
  5616. * </li>
  5617. * <li>
  5618. * Function return:
  5619. * <ul>
  5620. * <li>{string|null} Formatted string that will be used for the filtering.</li>
  5621. * </ul>
  5622. * </il>
  5623. * </ul>
  5624. *
  5625. * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for
  5626. * the different uses that DataTables can put the data to. Specifically <i>mData</i> when
  5627. * used as a function will give you a 'type' (sorting, filtering etc) that you can use to
  5628. * prepare the data as required for the different types. As such, this method is deprecated.
  5629. * @type object
  5630. * @default {}
  5631. * @deprecated
  5632. *
  5633. * @example
  5634. * $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) {
  5635. * return sData.replace(/\n/g," ").replace( /<.*?>/g, "" );
  5636. * }
  5637. */
  5638. "ofnSearch":{},
  5639. /**
  5640. * Container for all private functions in DataTables so they can be exposed externally
  5641. * @type object
  5642. * @default {}
  5643. */
  5644. "oApi":{},
  5645. /**
  5646. * Storage for the various classes that DataTables uses
  5647. * @type object
  5648. * @default {}
  5649. */
  5650. "oStdClasses":{},
  5651. /**
  5652. * Storage for the various classes that DataTables uses - jQuery UI suitable
  5653. * @type object
  5654. * @default {}
  5655. */
  5656. "oJUIClasses":{},
  5657. /**
  5658. * Pagination plug-in methods - The style and controls of the pagination can significantly
  5659. * impact on how the end user interacts with the data in your table, and DataTables allows
  5660. * the addition of pagination controls by extending this object, which can then be enabled
  5661. * through the <i>sPaginationType</i> initialisation parameter. Each pagination type that
  5662. * is added is an object (the property name of which is what <i>sPaginationType</i> refers
  5663. * to) that has two properties, both methods that are used by DataTables to update the
  5664. * control's state.
  5665. * <ul>
  5666. * <li>
  5667. * fnInit - Initialisation of the paging controls. Called only during initialisation
  5668. * of the table. It is expected that this function will add the required DOM elements
  5669. * to the page for the paging controls to work. The element pointer
  5670. * 'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging
  5671. * controls (note that this is a 2D array to allow for multiple instances of each
  5672. * DataTables DOM element). It is suggested that you add the controls to this element
  5673. * as children
  5674. * <ul>
  5675. * <li>
  5676. * Function input parameters:
  5677. * <ul>
  5678. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  5679. * <li>{node} Container into which the pagination controls must be inserted</li>
  5680. * <li>{function} Draw callback function - whenever the controls cause a page
  5681. * change, this method must be called to redraw the table.</li>
  5682. * </ul>
  5683. * </li>
  5684. * <li>
  5685. * Function return:
  5686. * <ul>
  5687. * <li>No return required</li>
  5688. * </ul>
  5689. * </il>
  5690. * </ul>
  5691. * </il>
  5692. * <li>
  5693. * fnInit - This function is called whenever the paging status of the table changes and is
  5694. * typically used to update classes and/or text of the paging controls to reflex the new
  5695. * status.
  5696. * <ul>
  5697. * <li>
  5698. * Function input parameters:
  5699. * <ul>
  5700. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  5701. * <li>{function} Draw callback function - in case you need to redraw the table again
  5702. * or attach new event listeners</li>
  5703. * </ul>
  5704. * </li>
  5705. * <li>
  5706. * Function return:
  5707. * <ul>
  5708. * <li>No return required</li>
  5709. * </ul>
  5710. * </il>
  5711. * </ul>
  5712. * </il>
  5713. * </ul>
  5714. * @type object
  5715. * @default {}
  5716. *
  5717. * @example
  5718. * $.fn.dataTableExt.oPagination.four_button = {
  5719. * "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) {
  5720. * nFirst = document.createElement( 'span' );
  5721. * nPrevious = document.createElement( 'span' );
  5722. * nNext = document.createElement( 'span' );
  5723. * nLast = document.createElement( 'span' );
  5724. *
  5725. * nFirst.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sFirst ) );
  5726. * nPrevious.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sPrevious ) );
  5727. * nNext.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sNext ) );
  5728. * nLast.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sLast ) );
  5729. *
  5730. * nFirst.className = "paginate_button first";
  5731. * nPrevious.className = "paginate_button previous";
  5732. * nNext.className="paginate_button next";
  5733. * nLast.className = "paginate_button last";
  5734. *
  5735. * nPaging.appendChild( nFirst );
  5736. * nPaging.appendChild( nPrevious );
  5737. * nPaging.appendChild( nNext );
  5738. * nPaging.appendChild( nLast );
  5739. *
  5740. * $(nFirst).click( function () {
  5741. * oSettings.oApi._fnPageChange( oSettings, "first" );
  5742. * fnCallbackDraw( oSettings );
  5743. * } );
  5744. *
  5745. * $(nPrevious).click( function() {
  5746. * oSettings.oApi._fnPageChange( oSettings, "previous" );
  5747. * fnCallbackDraw( oSettings );
  5748. * } );
  5749. *
  5750. * $(nNext).click( function() {
  5751. * oSettings.oApi._fnPageChange( oSettings, "next" );
  5752. * fnCallbackDraw( oSettings );
  5753. * } );
  5754. *
  5755. * $(nLast).click( function() {
  5756. * oSettings.oApi._fnPageChange( oSettings, "last" );
  5757. * fnCallbackDraw( oSettings );
  5758. * } );
  5759. *
  5760. * $(nFirst).bind( 'selectstart', function () { return false; } );
  5761. * $(nPrevious).bind( 'selectstart', function () { return false; } );
  5762. * $(nNext).bind( 'selectstart', function () { return false; } );
  5763. * $(nLast).bind( 'selectstart', function () { return false; } );
  5764. * },
  5765. *
  5766. * "fnUpdate": function ( oSettings, fnCallbackDraw ) {
  5767. * if ( !oSettings.aanFeatures.p ) {
  5768. * return;
  5769. * }
  5770. *
  5771. * // Loop over each instance of the pager
  5772. * var an = oSettings.aanFeatures.p;
  5773. * for ( var i=0, iLen=an.length ; i<iLen ; i++ ) {
  5774. * var buttons = an[i].getElementsByTagName('span');
  5775. * if ( oSettings._iDisplayStart === 0 ) {
  5776. * buttons[0].className = "paginate_disabled_previous";
  5777. * buttons[1].className = "paginate_disabled_previous";
  5778. * }
  5779. * else {
  5780. * buttons[0].className = "paginate_enabled_previous";
  5781. * buttons[1].className = "paginate_enabled_previous";
  5782. * }
  5783. *
  5784. * if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) {
  5785. * buttons[2].className = "paginate_disabled_next";
  5786. * buttons[3].className = "paginate_disabled_next";
  5787. * }
  5788. * else {
  5789. * buttons[2].className = "paginate_enabled_next";
  5790. * buttons[3].className = "paginate_enabled_next";
  5791. * }
  5792. * }
  5793. * }
  5794. * };
  5795. */
  5796. "oPagination":{},
  5797. /**
  5798. * Sorting plug-in methods - Sorting in DataTables is based on the detected type of the
  5799. * data column (you can add your own type detection functions, or override automatic
  5800. * detection using sType). With this specific type given to the column, DataTables will
  5801. * apply the required sort from the functions in the object. Each sort type must provide
  5802. * two mandatory methods, one each for ascending and descending sorting, and can optionally
  5803. * provide a pre-formatting method that will help speed up sorting by allowing DataTables
  5804. * to pre-format the sort data only once (rather than every time the actual sort functions
  5805. * are run). The two sorting functions are typical Javascript sort methods:
  5806. * <ul>
  5807. * <li>
  5808. * Function input parameters:
  5809. * <ul>
  5810. * <li>{*} Data to compare to the second parameter</li>
  5811. * <li>{*} Data to compare to the first parameter</li>
  5812. * </ul>
  5813. * </li>
  5814. * <li>
  5815. * Function return:
  5816. * <ul>
  5817. * <li>{int} Sorting match: <0 if first parameter should be sorted lower than
  5818. * the second parameter, ===0 if the two parameters are equal and >0 if
  5819. * the first parameter should be sorted height than the second parameter.</li>
  5820. * </ul>
  5821. * </il>
  5822. * </ul>
  5823. * @type object
  5824. * @default {}
  5825. *
  5826. * @example
  5827. * // Case-sensitive string sorting, with no pre-formatting method
  5828. * $.extend( $.fn.dataTableExt.oSort, {
  5829. * "string-case-asc": function(x,y) {
  5830. * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  5831. * },
  5832. * "string-case-desc": function(x,y) {
  5833. * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  5834. * }
  5835. * } );
  5836. *
  5837. * @example
  5838. * // Case-insensitive string sorting, with pre-formatting
  5839. * $.extend( $.fn.dataTableExt.oSort, {
  5840. * "string-pre": function(x) {
  5841. * return x.toLowerCase();
  5842. * },
  5843. * "string-asc": function(x,y) {
  5844. * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  5845. * },
  5846. * "string-desc": function(x,y) {
  5847. * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  5848. * }
  5849. * } );
  5850. */
  5851. "oSort":{},
  5852. /**
  5853. * Version string for plug-ins to check compatibility. Allowed format is
  5854. * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
  5855. * e are optional
  5856. * @type string
  5857. * @default Version number
  5858. */
  5859. "sVersion":DataTable.version,
  5860. /**
  5861. * How should DataTables report an error. Can take the value 'alert' or 'throw'
  5862. * @type string
  5863. * @default alert
  5864. */
  5865. "sErrMode":"alert",
  5866. /**
  5867. * Store information for DataTables to access globally about other instances
  5868. * @namespace
  5869. * @private
  5870. */
  5871. "_oExternConfig":{
  5872. /* int:iNextUnique - next unique number for an instance */
  5873. "iNextUnique":0
  5874. }
  5875. };
  5876. /**
  5877. * Template object for the way in which DataTables holds information about
  5878. * search information for the global filter and individual column filters.
  5879. * @namespace
  5880. */
  5881. DataTable.models.oSearch = {
  5882. /**
  5883. * Flag to indicate if the filtering should be case insensitive or not
  5884. * @type boolean
  5885. * @default true
  5886. */
  5887. "bCaseInsensitive":true,
  5888. /**
  5889. * Applied search term
  5890. * @type string
  5891. * @default <i>Empty string</i>
  5892. */
  5893. "sSearch":"",
  5894. /**
  5895. * Flag to indicate if the search term should be interpreted as a
  5896. * regular expression (true) or not (false) and therefore and special
  5897. * regex characters escaped.
  5898. * @type boolean
  5899. * @default false
  5900. */
  5901. "bRegex":false,
  5902. /**
  5903. * Flag to indicate if DataTables is to use its smart filtering or not.
  5904. * @type boolean
  5905. * @default true
  5906. */
  5907. "bSmart":true
  5908. };
  5909. /**
  5910. * Template object for the way in which DataTables holds information about
  5911. * each individual row. This is the object format used for the settings
  5912. * aoData array.
  5913. * @namespace
  5914. */
  5915. DataTable.models.oRow = {
  5916. /**
  5917. * TR element for the row
  5918. * @type node
  5919. * @default null
  5920. */
  5921. "nTr":null,
  5922. /**
  5923. * Data object from the original data source for the row. This is either
  5924. * an array if using the traditional form of DataTables, or an object if
  5925. * using mData options. The exact type will depend on the passed in
  5926. * data from the data source, or will be an array if using DOM a data
  5927. * source.
  5928. * @type array|object
  5929. * @default []
  5930. */
  5931. "_aData":[],
  5932. /**
  5933. * Sorting data cache - this array is ostensibly the same length as the
  5934. * number of columns (although each index is generated only as it is
  5935. * needed), and holds the data that is used for sorting each column in the
  5936. * row. We do this cache generation at the start of the sort in order that
  5937. * the formatting of the sort data need be done only once for each cell
  5938. * per sort. This array should not be read from or written to by anything
  5939. * other than the master sorting methods.
  5940. * @type array
  5941. * @default []
  5942. * @private
  5943. */
  5944. "_aSortData":[],
  5945. /**
  5946. * Array of TD elements that are cached for hidden rows, so they can be
  5947. * reinserted into the table if a column is made visible again (or to act
  5948. * as a store if a column is made hidden). Only hidden columns have a
  5949. * reference in the array. For non-hidden columns the value is either
  5950. * undefined or null.
  5951. * @type array nodes
  5952. * @default []
  5953. * @private
  5954. */
  5955. "_anHidden":[],
  5956. /**
  5957. * Cache of the class name that DataTables has applied to the row, so we
  5958. * can quickly look at this variable rather than needing to do a DOM check
  5959. * on className for the nTr property.
  5960. * @type string
  5961. * @default <i>Empty string</i>
  5962. * @private
  5963. */
  5964. "_sRowStripe":""
  5965. };
  5966. /**
  5967. * Template object for the column information object in DataTables. This object
  5968. * is held in the settings aoColumns array and contains all the information that
  5969. * DataTables needs about each individual column.
  5970. *
  5971. * Note that this object is related to {@link DataTable.defaults.columns}
  5972. * but this one is the internal data store for DataTables's cache of columns.
  5973. * It should NOT be manipulated outside of DataTables. Any configuration should
  5974. * be done through the initialisation options.
  5975. * @namespace
  5976. */
  5977. DataTable.models.oColumn = {
  5978. /**
  5979. * A list of the columns that sorting should occur on when this column
  5980. * is sorted. That this property is an array allows multi-column sorting
  5981. * to be defined for a column (for example first name / last name columns
  5982. * would benefit from this). The values are integers pointing to the
  5983. * columns to be sorted on (typically it will be a single integer pointing
  5984. * at itself, but that doesn't need to be the case).
  5985. * @type array
  5986. */
  5987. "aDataSort":null,
  5988. /**
  5989. * Define the sorting directions that are applied to the column, in sequence
  5990. * as the column is repeatedly sorted upon - i.e. the first value is used
  5991. * as the sorting direction when the column if first sorted (clicked on).
  5992. * Sort it again (click again) and it will move on to the next index.
  5993. * Repeat until loop.
  5994. * @type array
  5995. */
  5996. "asSorting":null,
  5997. /**
  5998. * Flag to indicate if the column is searchable, and thus should be included
  5999. * in the filtering or not.
  6000. * @type boolean
  6001. */
  6002. "bSearchable":null,
  6003. /**
  6004. * Flag to indicate if the column is sortable or not.
  6005. * @type boolean
  6006. */
  6007. "bSortable":null,
  6008. /**
  6009. * <code>Deprecated</code> When using fnRender, you have two options for what
  6010. * to do with the data, and this property serves as the switch. Firstly, you
  6011. * can have the sorting and filtering use the rendered value (true - default),
  6012. * or you can have the sorting and filtering us the original value (false).
  6013. *
  6014. * Please note that this option has now been deprecated and will be removed
  6015. * in the next version of DataTables. Please use mRender / mData rather than
  6016. * fnRender.
  6017. * @type boolean
  6018. * @deprecated
  6019. */
  6020. "bUseRendered":null,
  6021. /**
  6022. * Flag to indicate if the column is currently visible in the table or not
  6023. * @type boolean
  6024. */
  6025. "bVisible":null,
  6026. /**
  6027. * Flag to indicate to the type detection method if the automatic type
  6028. * detection should be used, or if a column type (sType) has been specified
  6029. * @type boolean
  6030. * @default true
  6031. * @private
  6032. */
  6033. "_bAutoType":true,
  6034. /**
  6035. * Developer definable function that is called whenever a cell is created (Ajax source,
  6036. * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  6037. * allowing you to modify the DOM element (add background colour for example) when the
  6038. * element is available.
  6039. * @type function
  6040. * @param {element} nTd The TD node that has been created
  6041. * @param {*} sData The Data for the cell
  6042. * @param {array|object} oData The data for the whole row
  6043. * @param {int} iRow The row index for the aoData data store
  6044. * @default null
  6045. */
  6046. "fnCreatedCell":null,
  6047. /**
  6048. * Function to get data from a cell in a column. You should <b>never</b>
  6049. * access data directly through _aData internally in DataTables - always use
  6050. * the method attached to this property. It allows mData to function as
  6051. * required. This function is automatically assigned by the column
  6052. * initialisation method
  6053. * @type function
  6054. * @param {array|object} oData The data array/object for the array
  6055. * (i.e. aoData[]._aData)
  6056. * @param {string} sSpecific The specific data type you want to get -
  6057. * 'display', 'type' 'filter' 'sort'
  6058. * @returns {*} The data for the cell from the given row's data
  6059. * @default null
  6060. */
  6061. "fnGetData":null,
  6062. /**
  6063. * <code>Deprecated</code> Custom display function that will be called for the
  6064. * display of each cell in this column.
  6065. *
  6066. * Please note that this option has now been deprecated and will be removed
  6067. * in the next version of DataTables. Please use mRender / mData rather than
  6068. * fnRender.
  6069. * @type function
  6070. * @param {object} o Object with the following parameters:
  6071. * @param {int} o.iDataRow The row in aoData
  6072. * @param {int} o.iDataColumn The column in question
  6073. * @param {array} o.aData The data for the row in question
  6074. * @param {object} o.oSettings The settings object for this DataTables instance
  6075. * @returns {string} The string you which to use in the display
  6076. * @default null
  6077. * @deprecated
  6078. */
  6079. "fnRender":null,
  6080. /**
  6081. * Function to set data for a cell in the column. You should <b>never</b>
  6082. * set the data directly to _aData internally in DataTables - always use
  6083. * this method. It allows mData to function as required. This function
  6084. * is automatically assigned by the column initialisation method
  6085. * @type function
  6086. * @param {array|object} oData The data array/object for the array
  6087. * (i.e. aoData[]._aData)
  6088. * @param {*} sValue Value to set
  6089. * @default null
  6090. */
  6091. "fnSetData":null,
  6092. /**
  6093. * Property to read the value for the cells in the column from the data
  6094. * source array / object. If null, then the default content is used, if a
  6095. * function is given then the return from the function is used.
  6096. * @type function|int|string|null
  6097. * @default null
  6098. */
  6099. "mData":null,
  6100. /**
  6101. * Partner property to mData which is used (only when defined) to get
  6102. * the data - i.e. it is basically the same as mData, but without the
  6103. * 'set' option, and also the data fed to it is the result from mData.
  6104. * This is the rendering method to match the data method of mData.
  6105. * @type function|int|string|null
  6106. * @default null
  6107. */
  6108. "mRender":null,
  6109. /**
  6110. * Unique header TH/TD element for this column - this is what the sorting
  6111. * listener is attached to (if sorting is enabled.)
  6112. * @type node
  6113. * @default null
  6114. */
  6115. "nTh":null,
  6116. /**
  6117. * Unique footer TH/TD element for this column (if there is one). Not used
  6118. * in DataTables as such, but can be used for plug-ins to reference the
  6119. * footer for each column.
  6120. * @type node
  6121. * @default null
  6122. */
  6123. "nTf":null,
  6124. /**
  6125. * The class to apply to all TD elements in the table's TBODY for the column
  6126. * @type string
  6127. * @default null
  6128. */
  6129. "sClass":null,
  6130. /**
  6131. * When DataTables calculates the column widths to assign to each column,
  6132. * it finds the longest string in each column and then constructs a
  6133. * temporary table and reads the widths from that. The problem with this
  6134. * is that "mmm" is much wider then "iiii", but the latter is a longer
  6135. * string - thus the calculation can go wrong (doing it properly and putting
  6136. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  6137. * a "work around" we provide this option. It will append its value to the
  6138. * text that is found to be the longest string for the column - i.e. padding.
  6139. * @type string
  6140. */
  6141. "sContentPadding":null,
  6142. /**
  6143. * Allows a default value to be given for a column's data, and will be used
  6144. * whenever a null data source is encountered (this can be because mData
  6145. * is set to null, or because the data source itself is null).
  6146. * @type string
  6147. * @default null
  6148. */
  6149. "sDefaultContent":null,
  6150. /**
  6151. * Name for the column, allowing reference to the column by name as well as
  6152. * by index (needs a lookup to work by name).
  6153. * @type string
  6154. */
  6155. "sName":null,
  6156. /**
  6157. * Custom sorting data type - defines which of the available plug-ins in
  6158. * afnSortData the custom sorting will use - if any is defined.
  6159. * @type string
  6160. * @default std
  6161. */
  6162. "sSortDataType":'std',
  6163. /**
  6164. * Class to be applied to the header element when sorting on this column
  6165. * @type string
  6166. * @default null
  6167. */
  6168. "sSortingClass":null,
  6169. /**
  6170. * Class to be applied to the header element when sorting on this column -
  6171. * when jQuery UI theming is used.
  6172. * @type string
  6173. * @default null
  6174. */
  6175. "sSortingClassJUI":null,
  6176. /**
  6177. * Title of the column - what is seen in the TH element (nTh).
  6178. * @type string
  6179. */
  6180. "sTitle":null,
  6181. /**
  6182. * Column sorting and filtering type
  6183. * @type string
  6184. * @default null
  6185. */
  6186. "sType":null,
  6187. /**
  6188. * Width of the column
  6189. * @type string
  6190. * @default null
  6191. */
  6192. "sWidth":null,
  6193. /**
  6194. * Width of the column when it was first "encountered"
  6195. * @type string
  6196. * @default null
  6197. */
  6198. "sWidthOrig":null
  6199. };
  6200. /**
  6201. * Initialisation options that can be given to DataTables at initialisation
  6202. * time.
  6203. * @namespace
  6204. */
  6205. DataTable.defaults = {
  6206. /**
  6207. * An array of data to use for the table, passed in at initialisation which
  6208. * will be used in preference to any data which is already in the DOM. This is
  6209. * particularly useful for constructing tables purely in Javascript, for
  6210. * example with a custom Ajax call.
  6211. * @type array
  6212. * @default null
  6213. * @dtopt Option
  6214. *
  6215. * @example
  6216. * // Using a 2D array data source
  6217. * $(document).ready( function () {
  6218. * $('#example').dataTable( {
  6219. * "aaData": [
  6220. * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
  6221. * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
  6222. * ],
  6223. * "aoColumns": [
  6224. * { "sTitle": "Engine" },
  6225. * { "sTitle": "Browser" },
  6226. * { "sTitle": "Platform" },
  6227. * { "sTitle": "Version" },
  6228. * { "sTitle": "Grade" }
  6229. * ]
  6230. * } );
  6231. * } );
  6232. *
  6233. * @example
  6234. * // Using an array of objects as a data source (mData)
  6235. * $(document).ready( function () {
  6236. * $('#example').dataTable( {
  6237. * "aaData": [
  6238. * {
  6239. * "engine": "Trident",
  6240. * "browser": "Internet Explorer 4.0",
  6241. * "platform": "Win 95+",
  6242. * "version": 4,
  6243. * "grade": "X"
  6244. * },
  6245. * {
  6246. * "engine": "Trident",
  6247. * "browser": "Internet Explorer 5.0",
  6248. * "platform": "Win 95+",
  6249. * "version": 5,
  6250. * "grade": "C"
  6251. * }
  6252. * ],
  6253. * "aoColumns": [
  6254. * { "sTitle": "Engine", "mData": "engine" },
  6255. * { "sTitle": "Browser", "mData": "browser" },
  6256. * { "sTitle": "Platform", "mData": "platform" },
  6257. * { "sTitle": "Version", "mData": "version" },
  6258. * { "sTitle": "Grade", "mData": "grade" }
  6259. * ]
  6260. * } );
  6261. * } );
  6262. */
  6263. "aaData":null,
  6264. /**
  6265. * If sorting is enabled, then DataTables will perform a first pass sort on
  6266. * initialisation. You can define which column(s) the sort is performed upon,
  6267. * and the sorting direction, with this variable. The aaSorting array should
  6268. * contain an array for each column to be sorted initially containing the
  6269. * column's index and a direction string ('asc' or 'desc').
  6270. * @type array
  6271. * @default [[0,'asc']]
  6272. * @dtopt Option
  6273. *
  6274. * @example
  6275. * // Sort by 3rd column first, and then 4th column
  6276. * $(document).ready( function() {
  6277. * $('#example').dataTable( {
  6278. * "aaSorting": [[2,'asc'], [3,'desc']]
  6279. * } );
  6280. * } );
  6281. *
  6282. * // No initial sorting
  6283. * $(document).ready( function() {
  6284. * $('#example').dataTable( {
  6285. * "aaSorting": []
  6286. * } );
  6287. * } );
  6288. */
  6289. "aaSorting":[
  6290. [0, 'asc']
  6291. ],
  6292. /**
  6293. * This parameter is basically identical to the aaSorting parameter, but
  6294. * cannot be overridden by user interaction with the table. What this means
  6295. * is that you could have a column (visible or hidden) which the sorting will
  6296. * always be forced on first - any sorting after that (from the user) will
  6297. * then be performed as required. This can be useful for grouping rows
  6298. * together.
  6299. * @type array
  6300. * @default null
  6301. * @dtopt Option
  6302. *
  6303. * @example
  6304. * $(document).ready( function() {
  6305. * $('#example').dataTable( {
  6306. * "aaSortingFixed": [[0,'asc']]
  6307. * } );
  6308. * } )
  6309. */
  6310. "aaSortingFixed":null,
  6311. /**
  6312. * This parameter allows you to readily specify the entries in the length drop
  6313. * down menu that DataTables shows when pagination is enabled. It can be
  6314. * either a 1D array of options which will be used for both the displayed
  6315. * option and the value, or a 2D array which will use the array in the first
  6316. * position as the value, and the array in the second position as the
  6317. * displayed options (useful for language strings such as 'All').
  6318. * @type array
  6319. * @default [ 10, 25, 50, 100 ]
  6320. * @dtopt Option
  6321. *
  6322. * @example
  6323. * $(document).ready( function() {
  6324. * $('#example').dataTable( {
  6325. * "aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
  6326. * } );
  6327. * } );
  6328. *
  6329. * @example
  6330. * // Setting the default display length as well as length menu
  6331. * // This is likely to be wanted if you remove the '10' option which
  6332. * // is the iDisplayLength default.
  6333. * $(document).ready( function() {
  6334. * $('#example').dataTable( {
  6335. * "iDisplayLength": 25,
  6336. * "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]]
  6337. * } );
  6338. * } );
  6339. */
  6340. "aLengthMenu":[ 10, 25, 50, 100 ],
  6341. /**
  6342. * The aoColumns option in the initialisation parameter allows you to define
  6343. * details about the way individual columns behave. For a full list of
  6344. * column options that can be set, please see
  6345. * {@link DataTable.defaults.columns}. Note that if you use aoColumns to
  6346. * define your columns, you must have an entry in the array for every single
  6347. * column that you have in your table (these can be null if you don't which
  6348. * to specify any options).
  6349. * @member
  6350. */
  6351. "aoColumns":null,
  6352. /**
  6353. * Very similar to aoColumns, aoColumnDefs allows you to target a specific
  6354. * column, multiple columns, or all columns, using the aTargets property of
  6355. * each object in the array. This allows great flexibility when creating
  6356. * tables, as the aoColumnDefs arrays can be of any length, targeting the
  6357. * columns you specifically want. aoColumnDefs may use any of the column
  6358. * options available: {@link DataTable.defaults.columns}, but it _must_
  6359. * have aTargets defined in each object in the array. Values in the aTargets
  6360. * array may be:
  6361. * <ul>
  6362. * <li>a string - class name will be matched on the TH for the column</li>
  6363. * <li>0 or a positive integer - column index counting from the left</li>
  6364. * <li>a negative integer - column index counting from the right</li>
  6365. * <li>the string "_all" - all columns (i.e. assign a default)</li>
  6366. * </ul>
  6367. * @member
  6368. */
  6369. "aoColumnDefs":null,
  6370. /**
  6371. * Basically the same as oSearch, this parameter defines the individual column
  6372. * filtering state at initialisation time. The array must be of the same size
  6373. * as the number of columns, and each element be an object with the parameters
  6374. * "sSearch" and "bEscapeRegex" (the latter is optional). 'null' is also
  6375. * accepted and the default will be used.
  6376. * @type array
  6377. * @default []
  6378. * @dtopt Option
  6379. *
  6380. * @example
  6381. * $(document).ready( function() {
  6382. * $('#example').dataTable( {
  6383. * "aoSearchCols": [
  6384. * null,
  6385. * { "sSearch": "My filter" },
  6386. * null,
  6387. * { "sSearch": "^[0-9]", "bEscapeRegex": false }
  6388. * ]
  6389. * } );
  6390. * } )
  6391. */
  6392. "aoSearchCols":[],
  6393. /**
  6394. * An array of CSS classes that should be applied to displayed rows. This
  6395. * array may be of any length, and DataTables will apply each class
  6396. * sequentially, looping when required.
  6397. * @type array
  6398. * @default null <i>Will take the values determined by the oClasses.sStripe*
  6399. * options</i>
  6400. * @dtopt Option
  6401. *
  6402. * @example
  6403. * $(document).ready( function() {
  6404. * $('#example').dataTable( {
  6405. * "asStripeClasses": [ 'strip1', 'strip2', 'strip3' ]
  6406. * } );
  6407. * } )
  6408. */
  6409. "asStripeClasses":null,
  6410. /**
  6411. * Enable or disable automatic column width calculation. This can be disabled
  6412. * as an optimisation (it takes some time to calculate the widths) if the
  6413. * tables widths are passed in using aoColumns.
  6414. * @type boolean
  6415. * @default true
  6416. * @dtopt Features
  6417. *
  6418. * @example
  6419. * $(document).ready( function () {
  6420. * $('#example').dataTable( {
  6421. * "bAutoWidth": false
  6422. * } );
  6423. * } );
  6424. */
  6425. "bAutoWidth":true,
  6426. /**
  6427. * Deferred rendering can provide DataTables with a huge speed boost when you
  6428. * are using an Ajax or JS data source for the table. This option, when set to
  6429. * true, will cause DataTables to defer the creation of the table elements for
  6430. * each row until they are needed for a draw - saving a significant amount of
  6431. * time.
  6432. * @type boolean
  6433. * @default false
  6434. * @dtopt Features
  6435. *
  6436. * @example
  6437. * $(document).ready( function() {
  6438. * var oTable = $('#example').dataTable( {
  6439. * "sAjaxSource": "sources/arrays.txt",
  6440. * "bDeferRender": true
  6441. * } );
  6442. * } );
  6443. */
  6444. "bDeferRender":false,
  6445. /**
  6446. * Replace a DataTable which matches the given selector and replace it with
  6447. * one which has the properties of the new initialisation object passed. If no
  6448. * table matches the selector, then the new DataTable will be constructed as
  6449. * per normal.
  6450. * @type boolean
  6451. * @default false
  6452. * @dtopt Options
  6453. *
  6454. * @example
  6455. * $(document).ready( function() {
  6456. * $('#example').dataTable( {
  6457. * "sScrollY": "200px",
  6458. * "bPaginate": false
  6459. * } );
  6460. *
  6461. * // Some time later....
  6462. * $('#example').dataTable( {
  6463. * "bFilter": false,
  6464. * "bDestroy": true
  6465. * } );
  6466. * } );
  6467. */
  6468. "bDestroy":false,
  6469. /**
  6470. * Enable or disable filtering of data. Filtering in DataTables is "smart" in
  6471. * that it allows the end user to input multiple words (space separated) and
  6472. * will match a row containing those words, even if not in the order that was
  6473. * specified (this allow matching across multiple columns). Note that if you
  6474. * wish to use filtering in DataTables this must remain 'true' - to remove the
  6475. * default filtering input box and retain filtering abilities, please use
  6476. * {@link DataTable.defaults.sDom}.
  6477. * @type boolean
  6478. * @default true
  6479. * @dtopt Features
  6480. *
  6481. * @example
  6482. * $(document).ready( function () {
  6483. * $('#example').dataTable( {
  6484. * "bFilter": false
  6485. * } );
  6486. * } );
  6487. */
  6488. "bFilter":true,
  6489. /**
  6490. * Enable or disable the table information display. This shows information
  6491. * about the data that is currently visible on the page, including information
  6492. * about filtered data if that action is being performed.
  6493. * @type boolean
  6494. * @default true
  6495. * @dtopt Features
  6496. *
  6497. * @example
  6498. * $(document).ready( function () {
  6499. * $('#example').dataTable( {
  6500. * "bInfo": false
  6501. * } );
  6502. * } );
  6503. */
  6504. "bInfo":true,
  6505. /**
  6506. * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
  6507. * slightly different and additional mark-up from what DataTables has
  6508. * traditionally used).
  6509. * @type boolean
  6510. * @default false
  6511. * @dtopt Features
  6512. *
  6513. * @example
  6514. * $(document).ready( function() {
  6515. * $('#example').dataTable( {
  6516. * "bJQueryUI": true
  6517. * } );
  6518. * } );
  6519. */
  6520. "bJQueryUI":false,
  6521. /**
  6522. * Allows the end user to select the size of a formatted page from a select
  6523. * menu (sizes are 10, 25, 50 and 100). Requires pagination (bPaginate).
  6524. * @type boolean
  6525. * @default true
  6526. * @dtopt Features
  6527. *
  6528. * @example
  6529. * $(document).ready( function () {
  6530. * $('#example').dataTable( {
  6531. * "bLengthChange": false
  6532. * } );
  6533. * } );
  6534. */
  6535. "bLengthChange":true,
  6536. /**
  6537. * Enable or disable pagination.
  6538. * @type boolean
  6539. * @default true
  6540. * @dtopt Features
  6541. *
  6542. * @example
  6543. * $(document).ready( function () {
  6544. * $('#example').dataTable( {
  6545. * "bPaginate": false
  6546. * } );
  6547. * } );
  6548. */
  6549. "bPaginate":true,
  6550. /**
  6551. * Enable or disable the display of a 'processing' indicator when the table is
  6552. * being processed (e.g. a sort). This is particularly useful for tables with
  6553. * large amounts of data where it can take a noticeable amount of time to sort
  6554. * the entries.
  6555. * @type boolean
  6556. * @default false
  6557. * @dtopt Features
  6558. *
  6559. * @example
  6560. * $(document).ready( function () {
  6561. * $('#example').dataTable( {
  6562. * "bProcessing": true
  6563. * } );
  6564. * } );
  6565. */
  6566. "bProcessing":false,
  6567. /**
  6568. * Retrieve the DataTables object for the given selector. Note that if the
  6569. * table has already been initialised, this parameter will cause DataTables
  6570. * to simply return the object that has already been set up - it will not take
  6571. * account of any changes you might have made to the initialisation object
  6572. * passed to DataTables (setting this parameter to true is an acknowledgement
  6573. * that you understand this). bDestroy can be used to reinitialise a table if
  6574. * you need.
  6575. * @type boolean
  6576. * @default false
  6577. * @dtopt Options
  6578. *
  6579. * @example
  6580. * $(document).ready( function() {
  6581. * initTable();
  6582. * tableActions();
  6583. * } );
  6584. *
  6585. * function initTable ()
  6586. * {
  6587. * return $('#example').dataTable( {
  6588. * "sScrollY": "200px",
  6589. * "bPaginate": false,
  6590. * "bRetrieve": true
  6591. * } );
  6592. * }
  6593. *
  6594. * function tableActions ()
  6595. * {
  6596. * var oTable = initTable();
  6597. * // perform API operations with oTable
  6598. * }
  6599. */
  6600. "bRetrieve":false,
  6601. /**
  6602. * Indicate if DataTables should be allowed to set the padding / margin
  6603. * etc for the scrolling header elements or not. Typically you will want
  6604. * this.
  6605. * @type boolean
  6606. * @default true
  6607. * @dtopt Options
  6608. *
  6609. * @example
  6610. * $(document).ready( function() {
  6611. * $('#example').dataTable( {
  6612. * "bScrollAutoCss": false,
  6613. * "sScrollY": "200px"
  6614. * } );
  6615. * } );
  6616. */
  6617. "bScrollAutoCss":true,
  6618. /**
  6619. * When vertical (y) scrolling is enabled, DataTables will force the height of
  6620. * the table's viewport to the given height at all times (useful for layout).
  6621. * However, this can look odd when filtering data down to a small data set,
  6622. * and the footer is left "floating" further down. This parameter (when
  6623. * enabled) will cause DataTables to collapse the table's viewport down when
  6624. * the result set will fit within the given Y height.
  6625. * @type boolean
  6626. * @default false
  6627. * @dtopt Options
  6628. *
  6629. * @example
  6630. * $(document).ready( function() {
  6631. * $('#example').dataTable( {
  6632. * "sScrollY": "200",
  6633. * "bScrollCollapse": true
  6634. * } );
  6635. * } );
  6636. */
  6637. "bScrollCollapse":false,
  6638. /**
  6639. * Enable infinite scrolling for DataTables (to be used in combination with
  6640. * sScrollY). Infinite scrolling means that DataTables will continually load
  6641. * data as a user scrolls through a table, which is very useful for large
  6642. * dataset. This cannot be used with pagination, which is automatically
  6643. * disabled. Note - the Scroller extra for DataTables is recommended in
  6644. * in preference to this option.
  6645. * @type boolean
  6646. * @default false
  6647. * @dtopt Features
  6648. *
  6649. * @example
  6650. * $(document).ready( function() {
  6651. * $('#example').dataTable( {
  6652. * "bScrollInfinite": true,
  6653. * "bScrollCollapse": true,
  6654. * "sScrollY": "200px"
  6655. * } );
  6656. * } );
  6657. */
  6658. "bScrollInfinite":false,
  6659. /**
  6660. * Configure DataTables to use server-side processing. Note that the
  6661. * sAjaxSource parameter must also be given in order to give DataTables a
  6662. * source to obtain the required data for each draw.
  6663. * @type boolean
  6664. * @default false
  6665. * @dtopt Features
  6666. * @dtopt Server-side
  6667. *
  6668. * @example
  6669. * $(document).ready( function () {
  6670. * $('#example').dataTable( {
  6671. * "bServerSide": true,
  6672. * "sAjaxSource": "xhr.php"
  6673. * } );
  6674. * } );
  6675. */
  6676. "bServerSide":false,
  6677. /**
  6678. * Enable or disable sorting of columns. Sorting of individual columns can be
  6679. * disabled by the "bSortable" option for each column.
  6680. * @type boolean
  6681. * @default true
  6682. * @dtopt Features
  6683. *
  6684. * @example
  6685. * $(document).ready( function () {
  6686. * $('#example').dataTable( {
  6687. * "bSort": false
  6688. * } );
  6689. * } );
  6690. */
  6691. "bSort":true,
  6692. /**
  6693. * Allows control over whether DataTables should use the top (true) unique
  6694. * cell that is found for a single column, or the bottom (false - default).
  6695. * This is useful when using complex headers.
  6696. * @type boolean
  6697. * @default false
  6698. * @dtopt Options
  6699. *
  6700. * @example
  6701. * $(document).ready( function() {
  6702. * $('#example').dataTable( {
  6703. * "bSortCellsTop": true
  6704. * } );
  6705. * } );
  6706. */
  6707. "bSortCellsTop":false,
  6708. /**
  6709. * Enable or disable the addition of the classes 'sorting_1', 'sorting_2' and
  6710. * 'sorting_3' to the columns which are currently being sorted on. This is
  6711. * presented as a feature switch as it can increase processing time (while
  6712. * classes are removed and added) so for large data sets you might want to
  6713. * turn this off.
  6714. * @type boolean
  6715. * @default true
  6716. * @dtopt Features
  6717. *
  6718. * @example
  6719. * $(document).ready( function () {
  6720. * $('#example').dataTable( {
  6721. * "bSortClasses": false
  6722. * } );
  6723. * } );
  6724. */
  6725. "bSortClasses":true,
  6726. /**
  6727. * Enable or disable state saving. When enabled a cookie will be used to save
  6728. * table display information such as pagination information, display length,
  6729. * filtering and sorting. As such when the end user reloads the page the
  6730. * display display will match what thy had previously set up.
  6731. * @type boolean
  6732. * @default false
  6733. * @dtopt Features
  6734. *
  6735. * @example
  6736. * $(document).ready( function () {
  6737. * $('#example').dataTable( {
  6738. * "bStateSave": true
  6739. * } );
  6740. * } );
  6741. */
  6742. "bStateSave":false,
  6743. /**
  6744. * Customise the cookie and / or the parameters being stored when using
  6745. * DataTables with state saving enabled. This function is called whenever
  6746. * the cookie is modified, and it expects a fully formed cookie string to be
  6747. * returned. Note that the data object passed in is a Javascript object which
  6748. * must be converted to a string (JSON.stringify for example).
  6749. * @type function
  6750. * @param {string} sName Name of the cookie defined by DataTables
  6751. * @param {object} oData Data to be stored in the cookie
  6752. * @param {string} sExpires Cookie expires string
  6753. * @param {string} sPath Path of the cookie to set
  6754. * @returns {string} Cookie formatted string (which should be encoded by
  6755. * using encodeURIComponent())
  6756. * @dtopt Callbacks
  6757. *
  6758. * @example
  6759. * $(document).ready( function () {
  6760. * $('#example').dataTable( {
  6761. * "fnCookieCallback": function (sName, oData, sExpires, sPath) {
  6762. * // Customise oData or sName or whatever else here
  6763. * return sName + "="+JSON.stringify(oData)+"; expires=" + sExpires +"; path=" + sPath;
  6764. * }
  6765. * } );
  6766. * } );
  6767. */
  6768. "fnCookieCallback":null,
  6769. /**
  6770. * This function is called when a TR element is created (and all TD child
  6771. * elements have been inserted), or registered if using a DOM source, allowing
  6772. * manipulation of the TR element (adding classes etc).
  6773. * @type function
  6774. * @param {node} nRow "TR" element for the current row
  6775. * @param {array} aData Raw data array for this row
  6776. * @param {int} iDataIndex The index of this row in aoData
  6777. * @dtopt Callbacks
  6778. *
  6779. * @example
  6780. * $(document).ready( function() {
  6781. * $('#example').dataTable( {
  6782. * "fnCreatedRow": function( nRow, aData, iDataIndex ) {
  6783. * // Bold the grade for all 'A' grade browsers
  6784. * if ( aData[4] == "A" )
  6785. * {
  6786. * $('td:eq(4)', nRow).html( '<b>A</b>' );
  6787. * }
  6788. * }
  6789. * } );
  6790. * } );
  6791. */
  6792. "fnCreatedRow":null,
  6793. /**
  6794. * This function is called on every 'draw' event, and allows you to
  6795. * dynamically modify any aspect you want about the created DOM.
  6796. * @type function
  6797. * @param {object} oSettings DataTables settings object
  6798. * @dtopt Callbacks
  6799. *
  6800. * @example
  6801. * $(document).ready( function() {
  6802. * $('#example').dataTable( {
  6803. * "fnDrawCallback": function( oSettings ) {
  6804. * alert( 'DataTables has redrawn the table' );
  6805. * }
  6806. * } );
  6807. * } );
  6808. */
  6809. "fnDrawCallback":null,
  6810. /**
  6811. * Identical to fnHeaderCallback() but for the table footer this function
  6812. * allows you to modify the table footer on every 'draw' even.
  6813. * @type function
  6814. * @param {node} nFoot "TR" element for the footer
  6815. * @param {array} aData Full table data (as derived from the original HTML)
  6816. * @param {int} iStart Index for the current display starting point in the
  6817. * display array
  6818. * @param {int} iEnd Index for the current display ending point in the
  6819. * display array
  6820. * @param {array int} aiDisplay Index array to translate the visual position
  6821. * to the full data array
  6822. * @dtopt Callbacks
  6823. *
  6824. * @example
  6825. * $(document).ready( function() {
  6826. * $('#example').dataTable( {
  6827. * "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) {
  6828. * nFoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+iStart;
  6829. * }
  6830. * } );
  6831. * } )
  6832. */
  6833. "fnFooterCallback":null,
  6834. /**
  6835. * When rendering large numbers in the information element for the table
  6836. * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
  6837. * to have a comma separator for the 'thousands' units (e.g. 1 million is
  6838. * rendered as "1,000,000") to help readability for the end user. This
  6839. * function will override the default method DataTables uses.
  6840. * @type function
  6841. * @member
  6842. * @param {int} iIn number to be formatted
  6843. * @returns {string} formatted string for DataTables to show the number
  6844. * @dtopt Callbacks
  6845. *
  6846. * @example
  6847. * $(document).ready( function() {
  6848. * $('#example').dataTable( {
  6849. * "fnFormatNumber": function ( iIn ) {
  6850. * if ( iIn &lt; 1000 ) {
  6851. * return iIn;
  6852. * } else {
  6853. * var
  6854. * s=(iIn+""),
  6855. * a=s.split(""), out="",
  6856. * iLen=s.length;
  6857. *
  6858. * for ( var i=0 ; i&lt;iLen ; i++ ) {
  6859. * if ( i%3 === 0 &amp;&amp; i !== 0 ) {
  6860. * out = "'"+out;
  6861. * }
  6862. * out = a[iLen-i-1]+out;
  6863. * }
  6864. * }
  6865. * return out;
  6866. * };
  6867. * } );
  6868. * } );
  6869. */
  6870. "fnFormatNumber":function (iIn) {
  6871. if (iIn < 1000) {
  6872. // A small optimisation for what is likely to be the majority of use cases
  6873. return iIn;
  6874. }
  6875. var s = (iIn + ""), a = s.split(""), out = "", iLen = s.length;
  6876. for (var i = 0; i < iLen; i++) {
  6877. if (i % 3 === 0 && i !== 0) {
  6878. out = this.oLanguage.sInfoThousands + out;
  6879. }
  6880. out = a[iLen - i - 1] + out;
  6881. }
  6882. return out;
  6883. },
  6884. /**
  6885. * This function is called on every 'draw' event, and allows you to
  6886. * dynamically modify the header row. This can be used to calculate and
  6887. * display useful information about the table.
  6888. * @type function
  6889. * @param {node} nHead "TR" element for the header
  6890. * @param {array} aData Full table data (as derived from the original HTML)
  6891. * @param {int} iStart Index for the current display starting point in the
  6892. * display array
  6893. * @param {int} iEnd Index for the current display ending point in the
  6894. * display array
  6895. * @param {array int} aiDisplay Index array to translate the visual position
  6896. * to the full data array
  6897. * @dtopt Callbacks
  6898. *
  6899. * @example
  6900. * $(document).ready( function() {
  6901. * $('#example').dataTable( {
  6902. * "fnHeaderCallback": function( nHead, aData, iStart, iEnd, aiDisplay ) {
  6903. * nHead.getElementsByTagName('th')[0].innerHTML = "Displaying "+(iEnd-iStart)+" records";
  6904. * }
  6905. * } );
  6906. * } )
  6907. */
  6908. "fnHeaderCallback":null,
  6909. /**
  6910. * The information element can be used to convey information about the current
  6911. * state of the table. Although the internationalisation options presented by
  6912. * DataTables are quite capable of dealing with most customisations, there may
  6913. * be times where you wish to customise the string further. This callback
  6914. * allows you to do exactly that.
  6915. * @type function
  6916. * @param {object} oSettings DataTables settings object
  6917. * @param {int} iStart Starting position in data for the draw
  6918. * @param {int} iEnd End position in data for the draw
  6919. * @param {int} iMax Total number of rows in the table (regardless of
  6920. * filtering)
  6921. * @param {int} iTotal Total number of rows in the data set, after filtering
  6922. * @param {string} sPre The string that DataTables has formatted using it's
  6923. * own rules
  6924. * @returns {string} The string to be displayed in the information element.
  6925. * @dtopt Callbacks
  6926. *
  6927. * @example
  6928. * $('#example').dataTable( {
  6929. * "fnInfoCallback": function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) {
  6930. * return iStart +" to "+ iEnd;
  6931. * }
  6932. * } );
  6933. */
  6934. "fnInfoCallback":null,
  6935. /**
  6936. * Called when the table has been initialised. Normally DataTables will
  6937. * initialise sequentially and there will be no need for this function,
  6938. * however, this does not hold true when using external language information
  6939. * since that is obtained using an async XHR call.
  6940. * @type function
  6941. * @param {object} oSettings DataTables settings object
  6942. * @param {object} json The JSON object request from the server - only
  6943. * present if client-side Ajax sourced data is used
  6944. * @dtopt Callbacks
  6945. *
  6946. * @example
  6947. * $(document).ready( function() {
  6948. * $('#example').dataTable( {
  6949. * "fnInitComplete": function(oSettings, json) {
  6950. * alert( 'DataTables has finished its initialisation.' );
  6951. * }
  6952. * } );
  6953. * } )
  6954. */
  6955. "fnInitComplete":null,
  6956. /**
  6957. * Called at the very start of each table draw and can be used to cancel the
  6958. * draw by returning false, any other return (including undefined) results in
  6959. * the full draw occurring).
  6960. * @type function
  6961. * @param {object} oSettings DataTables settings object
  6962. * @returns {boolean} False will cancel the draw, anything else (including no
  6963. * return) will allow it to complete.
  6964. * @dtopt Callbacks
  6965. *
  6966. * @example
  6967. * $(document).ready( function() {
  6968. * $('#example').dataTable( {
  6969. * "fnPreDrawCallback": function( oSettings ) {
  6970. * if ( $('#test').val() == 1 ) {
  6971. * return false;
  6972. * }
  6973. * }
  6974. * } );
  6975. * } );
  6976. */
  6977. "fnPreDrawCallback":null,
  6978. /**
  6979. * This function allows you to 'post process' each row after it have been
  6980. * generated for each table draw, but before it is rendered on screen. This
  6981. * function might be used for setting the row class name etc.
  6982. * @type function
  6983. * @param {node} nRow "TR" element for the current row
  6984. * @param {array} aData Raw data array for this row
  6985. * @param {int} iDisplayIndex The display index for the current table draw
  6986. * @param {int} iDisplayIndexFull The index of the data in the full list of
  6987. * rows (after filtering)
  6988. * @dtopt Callbacks
  6989. *
  6990. * @example
  6991. * $(document).ready( function() {
  6992. * $('#example').dataTable( {
  6993. * "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
  6994. * // Bold the grade for all 'A' grade browsers
  6995. * if ( aData[4] == "A" )
  6996. * {
  6997. * $('td:eq(4)', nRow).html( '<b>A</b>' );
  6998. * }
  6999. * }
  7000. * } );
  7001. * } );
  7002. */
  7003. "fnRowCallback":null,
  7004. /**
  7005. * This parameter allows you to override the default function which obtains
  7006. * the data from the server ($.getJSON) so something more suitable for your
  7007. * application. For example you could use POST data, or pull information from
  7008. * a Gears or AIR database.
  7009. * @type function
  7010. * @member
  7011. * @param {string} sSource HTTP source to obtain the data from (sAjaxSource)
  7012. * @param {array} aoData A key/value pair object containing the data to send
  7013. * to the server
  7014. * @param {function} fnCallback to be called on completion of the data get
  7015. * process that will draw the data on the page.
  7016. * @param {object} oSettings DataTables settings object
  7017. * @dtopt Callbacks
  7018. * @dtopt Server-side
  7019. *
  7020. * @example
  7021. * // POST data to server
  7022. * $(document).ready( function() {
  7023. * $('#example').dataTable( {
  7024. * "bProcessing": true,
  7025. * "bServerSide": true,
  7026. * "sAjaxSource": "xhr.php",
  7027. * "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) {
  7028. * oSettings.jqXHR = $.ajax( {
  7029. * "dataType": 'json',
  7030. * "type": "POST",
  7031. * "url": sSource,
  7032. * "data": aoData,
  7033. * "success": fnCallback
  7034. * } );
  7035. * }
  7036. * } );
  7037. * } );
  7038. */
  7039. "fnServerData":function (sUrl, aoData, fnCallback, oSettings) {
  7040. oSettings.jqXHR = $.ajax({
  7041. "url":sUrl,
  7042. "data":aoData,
  7043. "success":function (json) {
  7044. if (json.sError) {
  7045. oSettings.oApi._fnLog(oSettings, 0, json.sError);
  7046. }
  7047. $(oSettings.oInstance).trigger('xhr', [oSettings, json]);
  7048. fnCallback(json);
  7049. },
  7050. "dataType":"json",
  7051. "cache":false,
  7052. "type":oSettings.sServerMethod,
  7053. "error":function (xhr, error, thrown) {
  7054. if (error == "parsererror") {
  7055. oSettings.oApi._fnLog(oSettings, 0, "DataTables warning: JSON data from " +
  7056. "server could not be parsed. This is caused by a JSON formatting error.");
  7057. }
  7058. }
  7059. });
  7060. },
  7061. /**
  7062. * It is often useful to send extra data to the server when making an Ajax
  7063. * request - for example custom filtering information, and this callback
  7064. * function makes it trivial to send extra information to the server. The
  7065. * passed in parameter is the data set that has been constructed by
  7066. * DataTables, and you can add to this or modify it as you require.
  7067. * @type function
  7068. * @param {array} aoData Data array (array of objects which are name/value
  7069. * pairs) that has been constructed by DataTables and will be sent to the
  7070. * server. In the case of Ajax sourced data with server-side processing
  7071. * this will be an empty array, for server-side processing there will be a
  7072. * significant number of parameters!
  7073. * @returns {undefined} Ensure that you modify the aoData array passed in,
  7074. * as this is passed by reference.
  7075. * @dtopt Callbacks
  7076. * @dtopt Server-side
  7077. *
  7078. * @example
  7079. * $(document).ready( function() {
  7080. * $('#example').dataTable( {
  7081. * "bProcessing": true,
  7082. * "bServerSide": true,
  7083. * "sAjaxSource": "scripts/server_processing.php",
  7084. * "fnServerParams": function ( aoData ) {
  7085. * aoData.push( { "name": "more_data", "value": "my_value" } );
  7086. * }
  7087. * } );
  7088. * } );
  7089. */
  7090. "fnServerParams":null,
  7091. /**
  7092. * Load the table state. With this function you can define from where, and how, the
  7093. * state of a table is loaded. By default DataTables will load from its state saving
  7094. * cookie, but you might wish to use local storage (HTML5) or a server-side database.
  7095. * @type function
  7096. * @member
  7097. * @param {object} oSettings DataTables settings object
  7098. * @return {object} The DataTables state object to be loaded
  7099. * @dtopt Callbacks
  7100. *
  7101. * @example
  7102. * $(document).ready( function() {
  7103. * $('#example').dataTable( {
  7104. * "bStateSave": true,
  7105. * "fnStateLoad": function (oSettings) {
  7106. * var o;
  7107. *
  7108. * // Send an Ajax request to the server to get the data. Note that
  7109. * // this is a synchronous request.
  7110. * $.ajax( {
  7111. * "url": "/state_load",
  7112. * "async": false,
  7113. * "dataType": "json",
  7114. * "success": function (json) {
  7115. * o = json;
  7116. * }
  7117. * } );
  7118. *
  7119. * return o;
  7120. * }
  7121. * } );
  7122. * } );
  7123. */
  7124. "fnStateLoad":function (oSettings) {
  7125. var sData = this.oApi._fnReadCookie(oSettings.sCookiePrefix + oSettings.sInstance);
  7126. var oData;
  7127. try {
  7128. oData = (typeof $.parseJSON === 'function') ?
  7129. $.parseJSON(sData) : eval('(' + sData + ')');
  7130. } catch (e) {
  7131. oData = null;
  7132. }
  7133. return oData;
  7134. },
  7135. /**
  7136. * Callback which allows modification of the saved state prior to loading that state.
  7137. * This callback is called when the table is loading state from the stored data, but
  7138. * prior to the settings object being modified by the saved state. Note that for
  7139. * plug-in authors, you should use the 'stateLoadParams' event to load parameters for
  7140. * a plug-in.
  7141. * @type function
  7142. * @param {object} oSettings DataTables settings object
  7143. * @param {object} oData The state object that is to be loaded
  7144. * @dtopt Callbacks
  7145. *
  7146. * @example
  7147. * // Remove a saved filter, so filtering is never loaded
  7148. * $(document).ready( function() {
  7149. * $('#example').dataTable( {
  7150. * "bStateSave": true,
  7151. * "fnStateLoadParams": function (oSettings, oData) {
  7152. * oData.oSearch.sSearch = "";
  7153. * }
  7154. * } );
  7155. * } );
  7156. *
  7157. * @example
  7158. * // Disallow state loading by returning false
  7159. * $(document).ready( function() {
  7160. * $('#example').dataTable( {
  7161. * "bStateSave": true,
  7162. * "fnStateLoadParams": function (oSettings, oData) {
  7163. * return false;
  7164. * }
  7165. * } );
  7166. * } );
  7167. */
  7168. "fnStateLoadParams":null,
  7169. /**
  7170. * Callback that is called when the state has been loaded from the state saving method
  7171. * and the DataTables settings object has been modified as a result of the loaded state.
  7172. * @type function
  7173. * @param {object} oSettings DataTables settings object
  7174. * @param {object} oData The state object that was loaded
  7175. * @dtopt Callbacks
  7176. *
  7177. * @example
  7178. * // Show an alert with the filtering value that was saved
  7179. * $(document).ready( function() {
  7180. * $('#example').dataTable( {
  7181. * "bStateSave": true,
  7182. * "fnStateLoaded": function (oSettings, oData) {
  7183. * alert( 'Saved filter was: '+oData.oSearch.sSearch );
  7184. * }
  7185. * } );
  7186. * } );
  7187. */
  7188. "fnStateLoaded":null,
  7189. /**
  7190. * Save the table state. This function allows you to define where and how the state
  7191. * information for the table is stored - by default it will use a cookie, but you
  7192. * might want to use local storage (HTML5) or a server-side database.
  7193. * @type function
  7194. * @member
  7195. * @param {object} oSettings DataTables settings object
  7196. * @param {object} oData The state object to be saved
  7197. * @dtopt Callbacks
  7198. *
  7199. * @example
  7200. * $(document).ready( function() {
  7201. * $('#example').dataTable( {
  7202. * "bStateSave": true,
  7203. * "fnStateSave": function (oSettings, oData) {
  7204. * // Send an Ajax request to the server with the state object
  7205. * $.ajax( {
  7206. * "url": "/state_save",
  7207. * "data": oData,
  7208. * "dataType": "json",
  7209. * "method": "POST"
  7210. * "success": function () {}
  7211. * } );
  7212. * }
  7213. * } );
  7214. * } );
  7215. */
  7216. "fnStateSave":function (oSettings, oData) {
  7217. this.oApi._fnCreateCookie(
  7218. oSettings.sCookiePrefix + oSettings.sInstance,
  7219. this.oApi._fnJsonString(oData),
  7220. oSettings.iCookieDuration,
  7221. oSettings.sCookiePrefix,
  7222. oSettings.fnCookieCallback
  7223. );
  7224. },
  7225. /**
  7226. * Callback which allows modification of the state to be saved. Called when the table
  7227. * has changed state a new state save is required. This method allows modification of
  7228. * the state saving object prior to actually doing the save, including addition or
  7229. * other state properties or modification. Note that for plug-in authors, you should
  7230. * use the 'stateSaveParams' event to save parameters for a plug-in.
  7231. * @type function
  7232. * @param {object} oSettings DataTables settings object
  7233. * @param {object} oData The state object to be saved
  7234. * @dtopt Callbacks
  7235. *
  7236. * @example
  7237. * // Remove a saved filter, so filtering is never saved
  7238. * $(document).ready( function() {
  7239. * $('#example').dataTable( {
  7240. * "bStateSave": true,
  7241. * "fnStateSaveParams": function (oSettings, oData) {
  7242. * oData.oSearch.sSearch = "";
  7243. * }
  7244. * } );
  7245. * } );
  7246. */
  7247. "fnStateSaveParams":null,
  7248. /**
  7249. * Duration of the cookie which is used for storing session information. This
  7250. * value is given in seconds.
  7251. * @type int
  7252. * @default 7200 <i>(2 hours)</i>
  7253. * @dtopt Options
  7254. *
  7255. * @example
  7256. * $(document).ready( function() {
  7257. * $('#example').dataTable( {
  7258. * "iCookieDuration": 60*60*24; // 1 day
  7259. * } );
  7260. * } )
  7261. */
  7262. "iCookieDuration":7200,
  7263. /**
  7264. * When enabled DataTables will not make a request to the server for the first
  7265. * page draw - rather it will use the data already on the page (no sorting etc
  7266. * will be applied to it), thus saving on an XHR at load time. iDeferLoading
  7267. * is used to indicate that deferred loading is required, but it is also used
  7268. * to tell DataTables how many records there are in the full table (allowing
  7269. * the information element and pagination to be displayed correctly). In the case
  7270. * where a filtering is applied to the table on initial load, this can be
  7271. * indicated by giving the parameter as an array, where the first element is
  7272. * the number of records available after filtering and the second element is the
  7273. * number of records without filtering (allowing the table information element
  7274. * to be shown correctly).
  7275. * @type int | array
  7276. * @default null
  7277. * @dtopt Options
  7278. *
  7279. * @example
  7280. * // 57 records available in the table, no filtering applied
  7281. * $(document).ready( function() {
  7282. * $('#example').dataTable( {
  7283. * "bServerSide": true,
  7284. * "sAjaxSource": "scripts/server_processing.php",
  7285. * "iDeferLoading": 57
  7286. * } );
  7287. * } );
  7288. *
  7289. * @example
  7290. * // 57 records after filtering, 100 without filtering (an initial filter applied)
  7291. * $(document).ready( function() {
  7292. * $('#example').dataTable( {
  7293. * "bServerSide": true,
  7294. * "sAjaxSource": "scripts/server_processing.php",
  7295. * "iDeferLoading": [ 57, 100 ],
  7296. * "oSearch": {
  7297. * "sSearch": "my_filter"
  7298. * }
  7299. * } );
  7300. * } );
  7301. */
  7302. "iDeferLoading":null,
  7303. /**
  7304. * Number of rows to display on a single page when using pagination. If
  7305. * feature enabled (bLengthChange) then the end user will be able to override
  7306. * this to a custom setting using a pop-up menu.
  7307. * @type int
  7308. * @default 10
  7309. * @dtopt Options
  7310. *
  7311. * @example
  7312. * $(document).ready( function() {
  7313. * $('#example').dataTable( {
  7314. * "iDisplayLength": 50
  7315. * } );
  7316. * } )
  7317. */
  7318. "iDisplayLength":10,
  7319. /**
  7320. * Define the starting point for data display when using DataTables with
  7321. * pagination. Note that this parameter is the number of records, rather than
  7322. * the page number, so if you have 10 records per page and want to start on
  7323. * the third page, it should be "20".
  7324. * @type int
  7325. * @default 0
  7326. * @dtopt Options
  7327. *
  7328. * @example
  7329. * $(document).ready( function() {
  7330. * $('#example').dataTable( {
  7331. * "iDisplayStart": 20
  7332. * } );
  7333. * } )
  7334. */
  7335. "iDisplayStart":0,
  7336. /**
  7337. * The scroll gap is the amount of scrolling that is left to go before
  7338. * DataTables will load the next 'page' of data automatically. You typically
  7339. * want a gap which is big enough that the scrolling will be smooth for the
  7340. * user, while not so large that it will load more data than need.
  7341. * @type int
  7342. * @default 100
  7343. * @dtopt Options
  7344. *
  7345. * @example
  7346. * $(document).ready( function() {
  7347. * $('#example').dataTable( {
  7348. * "bScrollInfinite": true,
  7349. * "bScrollCollapse": true,
  7350. * "sScrollY": "200px",
  7351. * "iScrollLoadGap": 50
  7352. * } );
  7353. * } );
  7354. */
  7355. "iScrollLoadGap":100,
  7356. /**
  7357. * By default DataTables allows keyboard navigation of the table (sorting, paging,
  7358. * and filtering) by adding a tabindex attribute to the required elements. This
  7359. * allows you to tab through the controls and press the enter key to activate them.
  7360. * The tabindex is default 0, meaning that the tab follows the flow of the document.
  7361. * You can overrule this using this parameter if you wish. Use a value of -1 to
  7362. * disable built-in keyboard navigation.
  7363. * @type int
  7364. * @default 0
  7365. * @dtopt Options
  7366. *
  7367. * @example
  7368. * $(document).ready( function() {
  7369. * $('#example').dataTable( {
  7370. * "iTabIndex": 1
  7371. * } );
  7372. * } );
  7373. */
  7374. "iTabIndex":0,
  7375. /**
  7376. * All strings that DataTables uses in the user interface that it creates
  7377. * are defined in this object, allowing you to modified them individually or
  7378. * completely replace them all as required.
  7379. * @namespace
  7380. */
  7381. "oLanguage":{
  7382. /**
  7383. * Strings that are used for WAI-ARIA labels and controls only (these are not
  7384. * actually visible on the page, but will be read by screenreaders, and thus
  7385. * must be internationalised as well).
  7386. * @namespace
  7387. */
  7388. "oAria":{
  7389. /**
  7390. * ARIA label that is added to the table headers when the column may be
  7391. * sorted ascending by activing the column (click or return when focused).
  7392. * Note that the column header is prefixed to this string.
  7393. * @type string
  7394. * @default : activate to sort column ascending
  7395. * @dtopt Language
  7396. *
  7397. * @example
  7398. * $(document).ready( function() {
  7399. * $('#example').dataTable( {
  7400. * "oLanguage": {
  7401. * "oAria": {
  7402. * "sSortAscending": " - click/return to sort ascending"
  7403. * }
  7404. * }
  7405. * } );
  7406. * } );
  7407. */
  7408. "sSortAscending":": activate to sort column ascending",
  7409. /**
  7410. * ARIA label that is added to the table headers when the column may be
  7411. * sorted descending by activing the column (click or return when focused).
  7412. * Note that the column header is prefixed to this string.
  7413. * @type string
  7414. * @default : activate to sort column ascending
  7415. * @dtopt Language
  7416. *
  7417. * @example
  7418. * $(document).ready( function() {
  7419. * $('#example').dataTable( {
  7420. * "oLanguage": {
  7421. * "oAria": {
  7422. * "sSortDescending": " - click/return to sort descending"
  7423. * }
  7424. * }
  7425. * } );
  7426. * } );
  7427. */
  7428. "sSortDescending":": activate to sort column descending"
  7429. },
  7430. /**
  7431. * Pagination string used by DataTables for the two built-in pagination
  7432. * control types ("two_button" and "full_numbers")
  7433. * @namespace
  7434. */
  7435. "oPaginate":{
  7436. /**
  7437. * Text to use when using the 'full_numbers' type of pagination for the
  7438. * button to take the user to the first page.
  7439. * @type string
  7440. * @default First
  7441. * @dtopt Language
  7442. *
  7443. * @example
  7444. * $(document).ready( function() {
  7445. * $('#example').dataTable( {
  7446. * "oLanguage": {
  7447. * "oPaginate": {
  7448. * "sFirst": "First page"
  7449. * }
  7450. * }
  7451. * } );
  7452. * } );
  7453. */
  7454. "sFirst":"First",
  7455. /**
  7456. * Text to use when using the 'full_numbers' type of pagination for the
  7457. * button to take the user to the last page.
  7458. * @type string
  7459. * @default Last
  7460. * @dtopt Language
  7461. *
  7462. * @example
  7463. * $(document).ready( function() {
  7464. * $('#example').dataTable( {
  7465. * "oLanguage": {
  7466. * "oPaginate": {
  7467. * "sLast": "Last page"
  7468. * }
  7469. * }
  7470. * } );
  7471. * } );
  7472. */
  7473. "sLast":"Last",
  7474. /**
  7475. * Text to use for the 'next' pagination button (to take the user to the
  7476. * next page).
  7477. * @type string
  7478. * @default Next
  7479. * @dtopt Language
  7480. *
  7481. * @example
  7482. * $(document).ready( function() {
  7483. * $('#example').dataTable( {
  7484. * "oLanguage": {
  7485. * "oPaginate": {
  7486. * "sNext": "Next page"
  7487. * }
  7488. * }
  7489. * } );
  7490. * } );
  7491. */
  7492. "sNext":"Next",
  7493. /**
  7494. * Text to use for the 'previous' pagination button (to take the user to
  7495. * the previous page).
  7496. * @type string
  7497. * @default Previous
  7498. * @dtopt Language
  7499. *
  7500. * @example
  7501. * $(document).ready( function() {
  7502. * $('#example').dataTable( {
  7503. * "oLanguage": {
  7504. * "oPaginate": {
  7505. * "sPrevious": "Previous page"
  7506. * }
  7507. * }
  7508. * } );
  7509. * } );
  7510. */
  7511. "sPrevious":"Previous"
  7512. },
  7513. /**
  7514. * This string is shown in preference to sZeroRecords when the table is
  7515. * empty of data (regardless of filtering). Note that this is an optional
  7516. * parameter - if it is not given, the value of sZeroRecords will be used
  7517. * instead (either the default or given value).
  7518. * @type string
  7519. * @default No data available in table
  7520. * @dtopt Language
  7521. *
  7522. * @example
  7523. * $(document).ready( function() {
  7524. * $('#example').dataTable( {
  7525. * "oLanguage": {
  7526. * "sEmptyTable": "No data available in table"
  7527. * }
  7528. * } );
  7529. * } );
  7530. */
  7531. "sEmptyTable":"No data available in table",
  7532. /**
  7533. * This string gives information to the end user about the information that
  7534. * is current on display on the page. The _START_, _END_ and _TOTAL_
  7535. * variables are all dynamically replaced as the table display updates, and
  7536. * can be freely moved or removed as the language requirements change.
  7537. * @type string
  7538. * @default Showing _START_ to _END_ of _TOTAL_ entries
  7539. * @dtopt Language
  7540. *
  7541. * @example
  7542. * $(document).ready( function() {
  7543. * $('#example').dataTable( {
  7544. * "oLanguage": {
  7545. * "sInfo": "Got a total of _TOTAL_ entries to show (_START_ to _END_)"
  7546. * }
  7547. * } );
  7548. * } );
  7549. */
  7550. "sInfo":"Showing _START_ to _END_ of _TOTAL_ entries",
  7551. /**
  7552. * Display information string for when the table is empty. Typically the
  7553. * format of this string should match sInfo.
  7554. * @type string
  7555. * @default Showing 0 to 0 of 0 entries
  7556. * @dtopt Language
  7557. *
  7558. * @example
  7559. * $(document).ready( function() {
  7560. * $('#example').dataTable( {
  7561. * "oLanguage": {
  7562. * "sInfoEmpty": "No entries to show"
  7563. * }
  7564. * } );
  7565. * } );
  7566. */
  7567. "sInfoEmpty":"Showing 0 to 0 of 0 entries",
  7568. /**
  7569. * When a user filters the information in a table, this string is appended
  7570. * to the information (sInfo) to give an idea of how strong the filtering
  7571. * is. The variable _MAX_ is dynamically updated.
  7572. * @type string
  7573. * @default (filtered from _MAX_ total entries)
  7574. * @dtopt Language
  7575. *
  7576. * @example
  7577. * $(document).ready( function() {
  7578. * $('#example').dataTable( {
  7579. * "oLanguage": {
  7580. * "sInfoFiltered": " - filtering from _MAX_ records"
  7581. * }
  7582. * } );
  7583. * } );
  7584. */
  7585. "sInfoFiltered":"(filtered from _MAX_ total entries)",
  7586. /**
  7587. * If can be useful to append extra information to the info string at times,
  7588. * and this variable does exactly that. This information will be appended to
  7589. * the sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are
  7590. * being used) at all times.
  7591. * @type string
  7592. * @default <i>Empty string</i>
  7593. * @dtopt Language
  7594. *
  7595. * @example
  7596. * $(document).ready( function() {
  7597. * $('#example').dataTable( {
  7598. * "oLanguage": {
  7599. * "sInfoPostFix": "All records shown are derived from real information."
  7600. * }
  7601. * } );
  7602. * } );
  7603. */
  7604. "sInfoPostFix":"",
  7605. /**
  7606. * DataTables has a build in number formatter (fnFormatNumber) which is used
  7607. * to format large numbers that are used in the table information. By
  7608. * default a comma is used, but this can be trivially changed to any
  7609. * character you wish with this parameter.
  7610. * @type string
  7611. * @default ,
  7612. * @dtopt Language
  7613. *
  7614. * @example
  7615. * $(document).ready( function() {
  7616. * $('#example').dataTable( {
  7617. * "oLanguage": {
  7618. * "sInfoThousands": "'"
  7619. * }
  7620. * } );
  7621. * } );
  7622. */
  7623. "sInfoThousands":",",
  7624. /**
  7625. * Detail the action that will be taken when the drop down menu for the
  7626. * pagination length option is changed. The '_MENU_' variable is replaced
  7627. * with a default select list of 10, 25, 50 and 100, and can be replaced
  7628. * with a custom select box if required.
  7629. * @type string
  7630. * @default Show _MENU_ entries
  7631. * @dtopt Language
  7632. *
  7633. * @example
  7634. * // Language change only
  7635. * $(document).ready( function() {
  7636. * $('#example').dataTable( {
  7637. * "oLanguage": {
  7638. * "sLengthMenu": "Display _MENU_ records"
  7639. * }
  7640. * } );
  7641. * } );
  7642. *
  7643. * @example
  7644. * // Language and options change
  7645. * $(document).ready( function() {
  7646. * $('#example').dataTable( {
  7647. * "oLanguage": {
  7648. * "sLengthMenu": 'Display <select>'+
  7649. * '<option value="10">10</option>'+
  7650. * '<option value="20">20</option>'+
  7651. * '<option value="30">30</option>'+
  7652. * '<option value="40">40</option>'+
  7653. * '<option value="50">50</option>'+
  7654. * '<option value="-1">All</option>'+
  7655. * '</select> records'
  7656. * }
  7657. * } );
  7658. * } );
  7659. */
  7660. "sLengthMenu":"Show _MENU_ entries",
  7661. /**
  7662. * When using Ajax sourced data and during the first draw when DataTables is
  7663. * gathering the data, this message is shown in an empty row in the table to
  7664. * indicate to the end user the the data is being loaded. Note that this
  7665. * parameter is not used when loading data by server-side processing, just
  7666. * Ajax sourced data with client-side processing.
  7667. * @type string
  7668. * @default Loading...
  7669. * @dtopt Language
  7670. *
  7671. * @example
  7672. * $(document).ready( function() {
  7673. * $('#example').dataTable( {
  7674. * "oLanguage": {
  7675. * "sLoadingRecords": "Please wait - loading..."
  7676. * }
  7677. * } );
  7678. * } );
  7679. */
  7680. "sLoadingRecords":"Loading...",
  7681. /**
  7682. * Text which is displayed when the table is processing a user action
  7683. * (usually a sort command or similar).
  7684. * @type string
  7685. * @default Processing...
  7686. * @dtopt Language
  7687. *
  7688. * @example
  7689. * $(document).ready( function() {
  7690. * $('#example').dataTable( {
  7691. * "oLanguage": {
  7692. * "sProcessing": "DataTables is currently busy"
  7693. * }
  7694. * } );
  7695. * } );
  7696. */
  7697. "sProcessing":"Processing...",
  7698. /**
  7699. * Details the actions that will be taken when the user types into the
  7700. * filtering input text box. The variable "_INPUT_", if used in the string,
  7701. * is replaced with the HTML text box for the filtering input allowing
  7702. * control over where it appears in the string. If "_INPUT_" is not given
  7703. * then the input box is appended to the string automatically.
  7704. * @type string
  7705. * @default Search:
  7706. * @dtopt Language
  7707. *
  7708. * @example
  7709. * // Input text box will be appended at the end automatically
  7710. * $(document).ready( function() {
  7711. * $('#example').dataTable( {
  7712. * "oLanguage": {
  7713. * "sSearch": "Filter records:"
  7714. * }
  7715. * } );
  7716. * } );
  7717. *
  7718. * @example
  7719. * // Specify where the filter should appear
  7720. * $(document).ready( function() {
  7721. * $('#example').dataTable( {
  7722. * "oLanguage": {
  7723. * "sSearch": "Apply filter _INPUT_ to table"
  7724. * }
  7725. * } );
  7726. * } );
  7727. */
  7728. "sSearch":"Search:",
  7729. /**
  7730. * All of the language information can be stored in a file on the
  7731. * server-side, which DataTables will look up if this parameter is passed.
  7732. * It must store the URL of the language file, which is in a JSON format,
  7733. * and the object has the same properties as the oLanguage object in the
  7734. * initialiser object (i.e. the above parameters). Please refer to one of
  7735. * the example language files to see how this works in action.
  7736. * @type string
  7737. * @default <i>Empty string - i.e. disabled</i>
  7738. * @dtopt Language
  7739. *
  7740. * @example
  7741. * $(document).ready( function() {
  7742. * $('#example').dataTable( {
  7743. * "oLanguage": {
  7744. * "sUrl": "http://www.sprymedia.co.uk/dataTables/lang.txt"
  7745. * }
  7746. * } );
  7747. * } );
  7748. */
  7749. "sUrl":"",
  7750. /**
  7751. * Text shown inside the table records when the is no information to be
  7752. * displayed after filtering. sEmptyTable is shown when there is simply no
  7753. * information in the table at all (regardless of filtering).
  7754. * @type string
  7755. * @default No matching records found
  7756. * @dtopt Language
  7757. *
  7758. * @example
  7759. * $(document).ready( function() {
  7760. * $('#example').dataTable( {
  7761. * "oLanguage": {
  7762. * "sZeroRecords": "No records to display"
  7763. * }
  7764. * } );
  7765. * } );
  7766. */
  7767. "sZeroRecords":"No matching records found"
  7768. },
  7769. /**
  7770. * This parameter allows you to have define the global filtering state at
  7771. * initialisation time. As an object the "sSearch" parameter must be
  7772. * defined, but all other parameters are optional. When "bRegex" is true,
  7773. * the search string will be treated as a regular expression, when false
  7774. * (default) it will be treated as a straight string. When "bSmart"
  7775. * DataTables will use it's smart filtering methods (to word match at
  7776. * any point in the data), when false this will not be done.
  7777. * @namespace
  7778. * @extends DataTable.models.oSearch
  7779. * @dtopt Options
  7780. *
  7781. * @example
  7782. * $(document).ready( function() {
  7783. * $('#example').dataTable( {
  7784. * "oSearch": {"sSearch": "Initial search"}
  7785. * } );
  7786. * } )
  7787. */
  7788. "oSearch":$.extend({}, DataTable.models.oSearch),
  7789. /**
  7790. * By default DataTables will look for the property 'aaData' when obtaining
  7791. * data from an Ajax source or for server-side processing - this parameter
  7792. * allows that property to be changed. You can use Javascript dotted object
  7793. * notation to get a data source for multiple levels of nesting.
  7794. * @type string
  7795. * @default aaData
  7796. * @dtopt Options
  7797. * @dtopt Server-side
  7798. *
  7799. * @example
  7800. * // Get data from { "data": [...] }
  7801. * $(document).ready( function() {
  7802. * var oTable = $('#example').dataTable( {
  7803. * "sAjaxSource": "sources/data.txt",
  7804. * "sAjaxDataProp": "data"
  7805. * } );
  7806. * } );
  7807. *
  7808. * @example
  7809. * // Get data from { "data": { "inner": [...] } }
  7810. * $(document).ready( function() {
  7811. * var oTable = $('#example').dataTable( {
  7812. * "sAjaxSource": "sources/data.txt",
  7813. * "sAjaxDataProp": "data.inner"
  7814. * } );
  7815. * } );
  7816. */
  7817. "sAjaxDataProp":"aaData",
  7818. /**
  7819. * You can instruct DataTables to load data from an external source using this
  7820. * parameter (use aData if you want to pass data in you already have). Simply
  7821. * provide a url a JSON object can be obtained from. This object must include
  7822. * the parameter 'aaData' which is the data source for the table.
  7823. * @type string
  7824. * @default null
  7825. * @dtopt Options
  7826. * @dtopt Server-side
  7827. *
  7828. * @example
  7829. * $(document).ready( function() {
  7830. * $('#example').dataTable( {
  7831. * "sAjaxSource": "http://www.sprymedia.co.uk/dataTables/json.php"
  7832. * } );
  7833. * } )
  7834. */
  7835. "sAjaxSource":null,
  7836. /**
  7837. * This parameter can be used to override the default prefix that DataTables
  7838. * assigns to a cookie when state saving is enabled.
  7839. * @type string
  7840. * @default SpryMedia_DataTables_
  7841. * @dtopt Options
  7842. *
  7843. * @example
  7844. * $(document).ready( function() {
  7845. * $('#example').dataTable( {
  7846. * "sCookiePrefix": "my_datatable_",
  7847. * } );
  7848. * } );
  7849. */
  7850. "sCookiePrefix":"SpryMedia_DataTables_",
  7851. /**
  7852. * This initialisation variable allows you to specify exactly where in the
  7853. * DOM you want DataTables to inject the various controls it adds to the page
  7854. * (for example you might want the pagination controls at the top of the
  7855. * table). DIV elements (with or without a custom class) can also be added to
  7856. * aid styling. The follow syntax is used:
  7857. * <ul>
  7858. * <li>The following options are allowed:
  7859. * <ul>
  7860. * <li>'l' - Length changing</li
  7861. * <li>'f' - Filtering input</li>
  7862. * <li>'t' - The table!</li>
  7863. * <li>'i' - Information</li>
  7864. * <li>'p' - Pagination</li>
  7865. * <li>'r' - pRocessing</li>
  7866. * </ul>
  7867. * </li>
  7868. * <li>The following constants are allowed:
  7869. * <ul>
  7870. * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
  7871. * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
  7872. * </ul>
  7873. * </li>
  7874. * <li>The following syntax is expected:
  7875. * <ul>
  7876. * <li>'&lt;' and '&gt;' - div elements</li>
  7877. * <li>'&lt;"class" and '&gt;' - div with a class</li>
  7878. * <li>'&lt;"#id" and '&gt;' - div with an ID</li>
  7879. * </ul>
  7880. * </li>
  7881. * <li>Examples:
  7882. * <ul>
  7883. * <li>'&lt;"wrapper"flipt&gt;'</li>
  7884. * <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
  7885. * </ul>
  7886. * </li>
  7887. * </ul>
  7888. * @type string
  7889. * @default lfrtip <i>(when bJQueryUI is false)</i> <b>or</b>
  7890. * <"H"lfr>t<"F"ip> <i>(when bJQueryUI is true)</i>
  7891. * @dtopt Options
  7892. *
  7893. * @example
  7894. * $(document).ready( function() {
  7895. * $('#example').dataTable( {
  7896. * "sDom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
  7897. * } );
  7898. * } );
  7899. */
  7900. "sDom":"lfrtip",
  7901. /**
  7902. * DataTables features two different built-in pagination interaction methods
  7903. * ('two_button' or 'full_numbers') which present different page controls to
  7904. * the end user. Further methods can be added using the API (see below).
  7905. * @type string
  7906. * @default two_button
  7907. * @dtopt Options
  7908. *
  7909. * @example
  7910. * $(document).ready( function() {
  7911. * $('#example').dataTable( {
  7912. * "sPaginationType": "full_numbers"
  7913. * } );
  7914. * } )
  7915. */
  7916. "sPaginationType":"two_button",
  7917. /**
  7918. * Enable horizontal scrolling. When a table is too wide to fit into a certain
  7919. * layout, or you have a large number of columns in the table, you can enable
  7920. * x-scrolling to show the table in a viewport, which can be scrolled. This
  7921. * property can be any CSS unit, or a number (in which case it will be treated
  7922. * as a pixel measurement).
  7923. * @type string
  7924. * @default <i>blank string - i.e. disabled</i>
  7925. * @dtopt Features
  7926. *
  7927. * @example
  7928. * $(document).ready( function() {
  7929. * $('#example').dataTable( {
  7930. * "sScrollX": "100%",
  7931. * "bScrollCollapse": true
  7932. * } );
  7933. * } );
  7934. */
  7935. "sScrollX":"",
  7936. /**
  7937. * This property can be used to force a DataTable to use more width than it
  7938. * might otherwise do when x-scrolling is enabled. For example if you have a
  7939. * table which requires to be well spaced, this parameter is useful for
  7940. * "over-sizing" the table, and thus forcing scrolling. This property can by
  7941. * any CSS unit, or a number (in which case it will be treated as a pixel
  7942. * measurement).
  7943. * @type string
  7944. * @default <i>blank string - i.e. disabled</i>
  7945. * @dtopt Options
  7946. *
  7947. * @example
  7948. * $(document).ready( function() {
  7949. * $('#example').dataTable( {
  7950. * "sScrollX": "100%",
  7951. * "sScrollXInner": "110%"
  7952. * } );
  7953. * } );
  7954. */
  7955. "sScrollXInner":"",
  7956. /**
  7957. * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
  7958. * to the given height, and enable scrolling for any data which overflows the
  7959. * current viewport. This can be used as an alternative to paging to display
  7960. * a lot of data in a small area (although paging and scrolling can both be
  7961. * enabled at the same time). This property can be any CSS unit, or a number
  7962. * (in which case it will be treated as a pixel measurement).
  7963. * @type string
  7964. * @default <i>blank string - i.e. disabled</i>
  7965. * @dtopt Features
  7966. *
  7967. * @example
  7968. * $(document).ready( function() {
  7969. * $('#example').dataTable( {
  7970. * "sScrollY": "200px",
  7971. * "bPaginate": false
  7972. * } );
  7973. * } );
  7974. */
  7975. "sScrollY":"",
  7976. /**
  7977. * Set the HTTP method that is used to make the Ajax call for server-side
  7978. * processing or Ajax sourced data.
  7979. * @type string
  7980. * @default GET
  7981. * @dtopt Options
  7982. * @dtopt Server-side
  7983. *
  7984. * @example
  7985. * $(document).ready( function() {
  7986. * $('#example').dataTable( {
  7987. * "bServerSide": true,
  7988. * "sAjaxSource": "scripts/post.php",
  7989. * "sServerMethod": "POST"
  7990. * } );
  7991. * } );
  7992. */
  7993. "sServerMethod":"GET"
  7994. };
  7995. /**
  7996. * Column options that can be given to DataTables at initialisation time.
  7997. * @namespace
  7998. */
  7999. DataTable.defaults.columns = {
  8000. /**
  8001. * Allows a column's sorting to take multiple columns into account when
  8002. * doing a sort. For example first name / last name columns make sense to
  8003. * do a multi-column sort over the two columns.
  8004. * @type array
  8005. * @default null <i>Takes the value of the column index automatically</i>
  8006. * @dtopt Columns
  8007. *
  8008. * @example
  8009. * // Using aoColumnDefs
  8010. * $(document).ready( function() {
  8011. * $('#example').dataTable( {
  8012. * "aoColumnDefs": [
  8013. * { "aDataSort": [ 0, 1 ], "aTargets": [ 0 ] },
  8014. * { "aDataSort": [ 1, 0 ], "aTargets": [ 1 ] },
  8015. * { "aDataSort": [ 2, 3, 4 ], "aTargets": [ 2 ] }
  8016. * ]
  8017. * } );
  8018. * } );
  8019. *
  8020. * @example
  8021. * // Using aoColumns
  8022. * $(document).ready( function() {
  8023. * $('#example').dataTable( {
  8024. * "aoColumns": [
  8025. * { "aDataSort": [ 0, 1 ] },
  8026. * { "aDataSort": [ 1, 0 ] },
  8027. * { "aDataSort": [ 2, 3, 4 ] },
  8028. * null,
  8029. * null
  8030. * ]
  8031. * } );
  8032. * } );
  8033. */
  8034. "aDataSort":null,
  8035. /**
  8036. * You can control the default sorting direction, and even alter the behaviour
  8037. * of the sort handler (i.e. only allow ascending sorting etc) using this
  8038. * parameter.
  8039. * @type array
  8040. * @default [ 'asc', 'desc' ]
  8041. * @dtopt Columns
  8042. *
  8043. * @example
  8044. * // Using aoColumnDefs
  8045. * $(document).ready( function() {
  8046. * $('#example').dataTable( {
  8047. * "aoColumnDefs": [
  8048. * { "asSorting": [ "asc" ], "aTargets": [ 1 ] },
  8049. * { "asSorting": [ "desc", "asc", "asc" ], "aTargets": [ 2 ] },
  8050. * { "asSorting": [ "desc" ], "aTargets": [ 3 ] }
  8051. * ]
  8052. * } );
  8053. * } );
  8054. *
  8055. * @example
  8056. * // Using aoColumns
  8057. * $(document).ready( function() {
  8058. * $('#example').dataTable( {
  8059. * "aoColumns": [
  8060. * null,
  8061. * { "asSorting": [ "asc" ] },
  8062. * { "asSorting": [ "desc", "asc", "asc" ] },
  8063. * { "asSorting": [ "desc" ] },
  8064. * null
  8065. * ]
  8066. * } );
  8067. * } );
  8068. */
  8069. "asSorting":[ 'asc', 'desc' ],
  8070. /**
  8071. * Enable or disable filtering on the data in this column.
  8072. * @type boolean
  8073. * @default true
  8074. * @dtopt Columns
  8075. *
  8076. * @example
  8077. * // Using aoColumnDefs
  8078. * $(document).ready( function() {
  8079. * $('#example').dataTable( {
  8080. * "aoColumnDefs": [
  8081. * { "bSearchable": false, "aTargets": [ 0 ] }
  8082. * ] } );
  8083. * } );
  8084. *
  8085. * @example
  8086. * // Using aoColumns
  8087. * $(document).ready( function() {
  8088. * $('#example').dataTable( {
  8089. * "aoColumns": [
  8090. * { "bSearchable": false },
  8091. * null,
  8092. * null,
  8093. * null,
  8094. * null
  8095. * ] } );
  8096. * } );
  8097. */
  8098. "bSearchable":true,
  8099. /**
  8100. * Enable or disable sorting on this column.
  8101. * @type boolean
  8102. * @default true
  8103. * @dtopt Columns
  8104. *
  8105. * @example
  8106. * // Using aoColumnDefs
  8107. * $(document).ready( function() {
  8108. * $('#example').dataTable( {
  8109. * "aoColumnDefs": [
  8110. * { "bSortable": false, "aTargets": [ 0 ] }
  8111. * ] } );
  8112. * } );
  8113. *
  8114. * @example
  8115. * // Using aoColumns
  8116. * $(document).ready( function() {
  8117. * $('#example').dataTable( {
  8118. * "aoColumns": [
  8119. * { "bSortable": false },
  8120. * null,
  8121. * null,
  8122. * null,
  8123. * null
  8124. * ] } );
  8125. * } );
  8126. */
  8127. "bSortable":true,
  8128. /**
  8129. * <code>Deprecated</code> When using fnRender() for a column, you may wish
  8130. * to use the original data (before rendering) for sorting and filtering
  8131. * (the default is to used the rendered data that the user can see). This
  8132. * may be useful for dates etc.
  8133. *
  8134. * Please note that this option has now been deprecated and will be removed
  8135. * in the next version of DataTables. Please use mRender / mData rather than
  8136. * fnRender.
  8137. * @type boolean
  8138. * @default true
  8139. * @dtopt Columns
  8140. * @deprecated
  8141. */
  8142. "bUseRendered":true,
  8143. /**
  8144. * Enable or disable the display of this column.
  8145. * @type boolean
  8146. * @default true
  8147. * @dtopt Columns
  8148. *
  8149. * @example
  8150. * // Using aoColumnDefs
  8151. * $(document).ready( function() {
  8152. * $('#example').dataTable( {
  8153. * "aoColumnDefs": [
  8154. * { "bVisible": false, "aTargets": [ 0 ] }
  8155. * ] } );
  8156. * } );
  8157. *
  8158. * @example
  8159. * // Using aoColumns
  8160. * $(document).ready( function() {
  8161. * $('#example').dataTable( {
  8162. * "aoColumns": [
  8163. * { "bVisible": false },
  8164. * null,
  8165. * null,
  8166. * null,
  8167. * null
  8168. * ] } );
  8169. * } );
  8170. */
  8171. "bVisible":true,
  8172. /**
  8173. * Developer definable function that is called whenever a cell is created (Ajax source,
  8174. * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  8175. * allowing you to modify the DOM element (add background colour for example) when the
  8176. * element is available.
  8177. * @type function
  8178. * @param {element} nTd The TD node that has been created
  8179. * @param {*} sData The Data for the cell
  8180. * @param {array|object} oData The data for the whole row
  8181. * @param {int} iRow The row index for the aoData data store
  8182. * @param {int} iCol The column index for aoColumns
  8183. * @dtopt Columns
  8184. *
  8185. * @example
  8186. * $(document).ready( function() {
  8187. * $('#example').dataTable( {
  8188. * "aoColumnDefs": [ {
  8189. * "aTargets": [3],
  8190. * "fnCreatedCell": function (nTd, sData, oData, iRow, iCol) {
  8191. * if ( sData == "1.7" ) {
  8192. * $(nTd).css('color', 'blue')
  8193. * }
  8194. * }
  8195. * } ]
  8196. * });
  8197. * } );
  8198. */
  8199. "fnCreatedCell":null,
  8200. /**
  8201. * <code>Deprecated</code> Custom display function that will be called for the
  8202. * display of each cell in this column.
  8203. *
  8204. * Please note that this option has now been deprecated and will be removed
  8205. * in the next version of DataTables. Please use mRender / mData rather than
  8206. * fnRender.
  8207. * @type function
  8208. * @param {object} o Object with the following parameters:
  8209. * @param {int} o.iDataRow The row in aoData
  8210. * @param {int} o.iDataColumn The column in question
  8211. * @param {array} o.aData The data for the row in question
  8212. * @param {object} o.oSettings The settings object for this DataTables instance
  8213. * @param {object} o.mDataProp The data property used for this column
  8214. * @param {*} val The current cell value
  8215. * @returns {string} The string you which to use in the display
  8216. * @dtopt Columns
  8217. * @deprecated
  8218. */
  8219. "fnRender":null,
  8220. /**
  8221. * The column index (starting from 0!) that you wish a sort to be performed
  8222. * upon when this column is selected for sorting. This can be used for sorting
  8223. * on hidden columns for example.
  8224. * @type int
  8225. * @default -1 <i>Use automatically calculated column index</i>
  8226. * @dtopt Columns
  8227. *
  8228. * @example
  8229. * // Using aoColumnDefs
  8230. * $(document).ready( function() {
  8231. * $('#example').dataTable( {
  8232. * "aoColumnDefs": [
  8233. * { "iDataSort": 1, "aTargets": [ 0 ] }
  8234. * ]
  8235. * } );
  8236. * } );
  8237. *
  8238. * @example
  8239. * // Using aoColumns
  8240. * $(document).ready( function() {
  8241. * $('#example').dataTable( {
  8242. * "aoColumns": [
  8243. * { "iDataSort": 1 },
  8244. * null,
  8245. * null,
  8246. * null,
  8247. * null
  8248. * ]
  8249. * } );
  8250. * } );
  8251. */
  8252. "iDataSort":-1,
  8253. /**
  8254. * This parameter has been replaced by mData in DataTables to ensure naming
  8255. * consistency. mDataProp can still be used, as there is backwards compatibility
  8256. * in DataTables for this option, but it is strongly recommended that you use
  8257. * mData in preference to mDataProp.
  8258. * @name DataTable.defaults.columns.mDataProp
  8259. */
  8260. /**
  8261. * This property can be used to read data from any JSON data source property,
  8262. * including deeply nested objects / properties. mData can be given in a
  8263. * number of different ways which effect its behaviour:
  8264. * <ul>
  8265. * <li>integer - treated as an array index for the data source. This is the
  8266. * default that DataTables uses (incrementally increased for each column).</li>
  8267. * <li>string - read an object property from the data source. Note that you can
  8268. * use Javascript dotted notation to read deep properties / arrays from the
  8269. * data source.</li>
  8270. * <li>null - the sDefaultContent option will be used for the cell (null
  8271. * by default, so you will need to specify the default content you want -
  8272. * typically an empty string). This can be useful on generated columns such
  8273. * as edit / delete action columns.</li>
  8274. * <li>function - the function given will be executed whenever DataTables
  8275. * needs to set or get the data for a cell in the column. The function
  8276. * takes three parameters:
  8277. * <ul>
  8278. * <li>{array|object} The data source for the row</li>
  8279. * <li>{string} The type call data requested - this will be 'set' when
  8280. * setting data or 'filter', 'display', 'type', 'sort' or undefined when
  8281. * gathering data. Note that when <i>undefined</i> is given for the type
  8282. * DataTables expects to get the raw data for the object back</li>
  8283. * <li>{*} Data to set when the second parameter is 'set'.</li>
  8284. * </ul>
  8285. * The return value from the function is not required when 'set' is the type
  8286. * of call, but otherwise the return is what will be used for the data
  8287. * requested.</li>
  8288. * </ul>
  8289. *
  8290. * Note that prior to DataTables 1.9.2 mData was called mDataProp. The name change
  8291. * reflects the flexibility of this property and is consistent with the naming of
  8292. * mRender. If 'mDataProp' is given, then it will still be used by DataTables, as
  8293. * it automatically maps the old name to the new if required.
  8294. * @type string|int|function|null
  8295. * @default null <i>Use automatically calculated column index</i>
  8296. * @dtopt Columns
  8297. *
  8298. * @example
  8299. * // Read table data from objects
  8300. * $(document).ready( function() {
  8301. * var oTable = $('#example').dataTable( {
  8302. * "sAjaxSource": "sources/deep.txt",
  8303. * "aoColumns": [
  8304. * { "mData": "engine" },
  8305. * { "mData": "browser" },
  8306. * { "mData": "platform.inner" },
  8307. * { "mData": "platform.details.0" },
  8308. * { "mData": "platform.details.1" }
  8309. * ]
  8310. * } );
  8311. * } );
  8312. *
  8313. * @example
  8314. * // Using mData as a function to provide different information for
  8315. * // sorting, filtering and display. In this case, currency (price)
  8316. * $(document).ready( function() {
  8317. * var oTable = $('#example').dataTable( {
  8318. * "aoColumnDefs": [ {
  8319. * "aTargets": [ 0 ],
  8320. * "mData": function ( source, type, val ) {
  8321. * if (type === 'set') {
  8322. * source.price = val;
  8323. * // Store the computed dislay and filter values for efficiency
  8324. * source.price_display = val=="" ? "" : "$"+numberFormat(val);
  8325. * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
  8326. * return;
  8327. * }
  8328. * else if (type === 'display') {
  8329. * return source.price_display;
  8330. * }
  8331. * else if (type === 'filter') {
  8332. * return source.price_filter;
  8333. * }
  8334. * // 'sort', 'type' and undefined all just use the integer
  8335. * return source.price;
  8336. * }
  8337. * } ]
  8338. * } );
  8339. * } );
  8340. */
  8341. "mData":null,
  8342. /**
  8343. * This property is the rendering partner to mData and it is suggested that
  8344. * when you want to manipulate data for display (including filtering, sorting etc)
  8345. * but not altering the underlying data for the table, use this property. mData
  8346. * can actually do everything this property can and more, but this parameter is
  8347. * easier to use since there is no 'set' option. Like mData is can be given
  8348. * in a number of different ways to effect its behaviour, with the addition of
  8349. * supporting array syntax for easy outputting of arrays (including arrays of
  8350. * objects):
  8351. * <ul>
  8352. * <li>integer - treated as an array index for the data source. This is the
  8353. * default that DataTables uses (incrementally increased for each column).</li>
  8354. * <li>string - read an object property from the data source. Note that you can
  8355. * use Javascript dotted notation to read deep properties / arrays from the
  8356. * data source and also array brackets to indicate that the data reader should
  8357. * loop over the data source array. When characters are given between the array
  8358. * brackets, these characters are used to join the data source array together.
  8359. * For example: "accounts[, ].name" would result in a comma separated list with
  8360. * the 'name' value from the 'accounts' array of objects.</li>
  8361. * <li>function - the function given will be executed whenever DataTables
  8362. * needs to set or get the data for a cell in the column. The function
  8363. * takes three parameters:
  8364. * <ul>
  8365. * <li>{array|object} The data source for the row (based on mData)</li>
  8366. * <li>{string} The type call data requested - this will be 'filter', 'display',
  8367. * 'type' or 'sort'.</li>
  8368. * <li>{array|object} The full data source for the row (not based on mData)</li>
  8369. * </ul>
  8370. * The return value from the function is what will be used for the data
  8371. * requested.</li>
  8372. * </ul>
  8373. * @type string|int|function|null
  8374. * @default null <i>Use mData</i>
  8375. * @dtopt Columns
  8376. *
  8377. * @example
  8378. * // Create a comma separated list from an array of objects
  8379. * $(document).ready( function() {
  8380. * var oTable = $('#example').dataTable( {
  8381. * "sAjaxSource": "sources/deep.txt",
  8382. * "aoColumns": [
  8383. * { "mData": "engine" },
  8384. * { "mData": "browser" },
  8385. * {
  8386. * "mData": "platform",
  8387. * "mRender": "[, ].name"
  8388. * }
  8389. * ]
  8390. * } );
  8391. * } );
  8392. *
  8393. * @example
  8394. * // Use as a function to create a link from the data source
  8395. * $(document).ready( function() {
  8396. * var oTable = $('#example').dataTable( {
  8397. * "aoColumnDefs": [
  8398. * {
  8399. * "aTargets": [ 0 ],
  8400. * "mData": "download_link",
  8401. * "mRender": function ( data, type, full ) {
  8402. * return '<a href="'+data+'">Download</a>';
  8403. * }
  8404. * ]
  8405. * } );
  8406. * } );
  8407. */
  8408. "mRender":null,
  8409. /**
  8410. * Change the cell type created for the column - either TD cells or TH cells. This
  8411. * can be useful as TH cells have semantic meaning in the table body, allowing them
  8412. * to act as a header for a row (you may wish to add scope='row' to the TH elements).
  8413. * @type string
  8414. * @default td
  8415. * @dtopt Columns
  8416. *
  8417. * @example
  8418. * // Make the first column use TH cells
  8419. * $(document).ready( function() {
  8420. * var oTable = $('#example').dataTable( {
  8421. * "aoColumnDefs": [ {
  8422. * "aTargets": [ 0 ],
  8423. * "sCellType": "th"
  8424. * } ]
  8425. * } );
  8426. * } );
  8427. */
  8428. "sCellType":"td",
  8429. /**
  8430. * Class to give to each cell in this column.
  8431. * @type string
  8432. * @default <i>Empty string</i>
  8433. * @dtopt Columns
  8434. *
  8435. * @example
  8436. * // Using aoColumnDefs
  8437. * $(document).ready( function() {
  8438. * $('#example').dataTable( {
  8439. * "aoColumnDefs": [
  8440. * { "sClass": "my_class", "aTargets": [ 0 ] }
  8441. * ]
  8442. * } );
  8443. * } );
  8444. *
  8445. * @example
  8446. * // Using aoColumns
  8447. * $(document).ready( function() {
  8448. * $('#example').dataTable( {
  8449. * "aoColumns": [
  8450. * { "sClass": "my_class" },
  8451. * null,
  8452. * null,
  8453. * null,
  8454. * null
  8455. * ]
  8456. * } );
  8457. * } );
  8458. */
  8459. "sClass":"",
  8460. /**
  8461. * When DataTables calculates the column widths to assign to each column,
  8462. * it finds the longest string in each column and then constructs a
  8463. * temporary table and reads the widths from that. The problem with this
  8464. * is that "mmm" is much wider then "iiii", but the latter is a longer
  8465. * string - thus the calculation can go wrong (doing it properly and putting
  8466. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  8467. * a "work around" we provide this option. It will append its value to the
  8468. * text that is found to be the longest string for the column - i.e. padding.
  8469. * Generally you shouldn't need this, and it is not documented on the
  8470. * general DataTables.net documentation
  8471. * @type string
  8472. * @default <i>Empty string<i>
  8473. * @dtopt Columns
  8474. *
  8475. * @example
  8476. * // Using aoColumns
  8477. * $(document).ready( function() {
  8478. * $('#example').dataTable( {
  8479. * "aoColumns": [
  8480. * null,
  8481. * null,
  8482. * null,
  8483. * {
  8484. * "sContentPadding": "mmm"
  8485. * }
  8486. * ]
  8487. * } );
  8488. * } );
  8489. */
  8490. "sContentPadding":"",
  8491. /**
  8492. * Allows a default value to be given for a column's data, and will be used
  8493. * whenever a null data source is encountered (this can be because mData
  8494. * is set to null, or because the data source itself is null).
  8495. * @type string
  8496. * @default null
  8497. * @dtopt Columns
  8498. *
  8499. * @example
  8500. * // Using aoColumnDefs
  8501. * $(document).ready( function() {
  8502. * $('#example').dataTable( {
  8503. * "aoColumnDefs": [
  8504. * {
  8505. * "mData": null,
  8506. * "sDefaultContent": "Edit",
  8507. * "aTargets": [ -1 ]
  8508. * }
  8509. * ]
  8510. * } );
  8511. * } );
  8512. *
  8513. * @example
  8514. * // Using aoColumns
  8515. * $(document).ready( function() {
  8516. * $('#example').dataTable( {
  8517. * "aoColumns": [
  8518. * null,
  8519. * null,
  8520. * null,
  8521. * {
  8522. * "mData": null,
  8523. * "sDefaultContent": "Edit"
  8524. * }
  8525. * ]
  8526. * } );
  8527. * } );
  8528. */
  8529. "sDefaultContent":null,
  8530. /**
  8531. * This parameter is only used in DataTables' server-side processing. It can
  8532. * be exceptionally useful to know what columns are being displayed on the
  8533. * client side, and to map these to database fields. When defined, the names
  8534. * also allow DataTables to reorder information from the server if it comes
  8535. * back in an unexpected order (i.e. if you switch your columns around on the
  8536. * client-side, your server-side code does not also need updating).
  8537. * @type string
  8538. * @default <i>Empty string</i>
  8539. * @dtopt Columns
  8540. *
  8541. * @example
  8542. * // Using aoColumnDefs
  8543. * $(document).ready( function() {
  8544. * $('#example').dataTable( {
  8545. * "aoColumnDefs": [
  8546. * { "sName": "engine", "aTargets": [ 0 ] },
  8547. * { "sName": "browser", "aTargets": [ 1 ] },
  8548. * { "sName": "platform", "aTargets": [ 2 ] },
  8549. * { "sName": "version", "aTargets": [ 3 ] },
  8550. * { "sName": "grade", "aTargets": [ 4 ] }
  8551. * ]
  8552. * } );
  8553. * } );
  8554. *
  8555. * @example
  8556. * // Using aoColumns
  8557. * $(document).ready( function() {
  8558. * $('#example').dataTable( {
  8559. * "aoColumns": [
  8560. * { "sName": "engine" },
  8561. * { "sName": "browser" },
  8562. * { "sName": "platform" },
  8563. * { "sName": "version" },
  8564. * { "sName": "grade" }
  8565. * ]
  8566. * } );
  8567. * } );
  8568. */
  8569. "sName":"",
  8570. /**
  8571. * Defines a data source type for the sorting which can be used to read
  8572. * real-time information from the table (updating the internally cached
  8573. * version) prior to sorting. This allows sorting to occur on user editable
  8574. * elements such as form inputs.
  8575. * @type string
  8576. * @default std
  8577. * @dtopt Columns
  8578. *
  8579. * @example
  8580. * // Using aoColumnDefs
  8581. * $(document).ready( function() {
  8582. * $('#example').dataTable( {
  8583. * "aoColumnDefs": [
  8584. * { "sSortDataType": "dom-text", "aTargets": [ 2, 3 ] },
  8585. * { "sType": "numeric", "aTargets": [ 3 ] },
  8586. * { "sSortDataType": "dom-select", "aTargets": [ 4 ] },
  8587. * { "sSortDataType": "dom-checkbox", "aTargets": [ 5 ] }
  8588. * ]
  8589. * } );
  8590. * } );
  8591. *
  8592. * @example
  8593. * // Using aoColumns
  8594. * $(document).ready( function() {
  8595. * $('#example').dataTable( {
  8596. * "aoColumns": [
  8597. * null,
  8598. * null,
  8599. * { "sSortDataType": "dom-text" },
  8600. * { "sSortDataType": "dom-text", "sType": "numeric" },
  8601. * { "sSortDataType": "dom-select" },
  8602. * { "sSortDataType": "dom-checkbox" }
  8603. * ]
  8604. * } );
  8605. * } );
  8606. */
  8607. "sSortDataType":"std",
  8608. /**
  8609. * The title of this column.
  8610. * @type string
  8611. * @default null <i>Derived from the 'TH' value for this column in the
  8612. * original HTML table.</i>
  8613. * @dtopt Columns
  8614. *
  8615. * @example
  8616. * // Using aoColumnDefs
  8617. * $(document).ready( function() {
  8618. * $('#example').dataTable( {
  8619. * "aoColumnDefs": [
  8620. * { "sTitle": "My column title", "aTargets": [ 0 ] }
  8621. * ]
  8622. * } );
  8623. * } );
  8624. *
  8625. * @example
  8626. * // Using aoColumns
  8627. * $(document).ready( function() {
  8628. * $('#example').dataTable( {
  8629. * "aoColumns": [
  8630. * { "sTitle": "My column title" },
  8631. * null,
  8632. * null,
  8633. * null,
  8634. * null
  8635. * ]
  8636. * } );
  8637. * } );
  8638. */
  8639. "sTitle":null,
  8640. /**
  8641. * The type allows you to specify how the data for this column will be sorted.
  8642. * Four types (string, numeric, date and html (which will strip HTML tags
  8643. * before sorting)) are currently available. Note that only date formats
  8644. * understood by Javascript's Date() object will be accepted as type date. For
  8645. * example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 'numeric',
  8646. * 'date' or 'html' (by default). Further types can be adding through
  8647. * plug-ins.
  8648. * @type string
  8649. * @default null <i>Auto-detected from raw data</i>
  8650. * @dtopt Columns
  8651. *
  8652. * @example
  8653. * // Using aoColumnDefs
  8654. * $(document).ready( function() {
  8655. * $('#example').dataTable( {
  8656. * "aoColumnDefs": [
  8657. * { "sType": "html", "aTargets": [ 0 ] }
  8658. * ]
  8659. * } );
  8660. * } );
  8661. *
  8662. * @example
  8663. * // Using aoColumns
  8664. * $(document).ready( function() {
  8665. * $('#example').dataTable( {
  8666. * "aoColumns": [
  8667. * { "sType": "html" },
  8668. * null,
  8669. * null,
  8670. * null,
  8671. * null
  8672. * ]
  8673. * } );
  8674. * } );
  8675. */
  8676. "sType":null,
  8677. /**
  8678. * Defining the width of the column, this parameter may take any CSS value
  8679. * (3em, 20px etc). DataTables apples 'smart' widths to columns which have not
  8680. * been given a specific width through this interface ensuring that the table
  8681. * remains readable.
  8682. * @type string
  8683. * @default null <i>Automatic</i>
  8684. * @dtopt Columns
  8685. *
  8686. * @example
  8687. * // Using aoColumnDefs
  8688. * $(document).ready( function() {
  8689. * $('#example').dataTable( {
  8690. * "aoColumnDefs": [
  8691. * { "sWidth": "20%", "aTargets": [ 0 ] }
  8692. * ]
  8693. * } );
  8694. * } );
  8695. *
  8696. * @example
  8697. * // Using aoColumns
  8698. * $(document).ready( function() {
  8699. * $('#example').dataTable( {
  8700. * "aoColumns": [
  8701. * { "sWidth": "20%" },
  8702. * null,
  8703. * null,
  8704. * null,
  8705. * null
  8706. * ]
  8707. * } );
  8708. * } );
  8709. */
  8710. "sWidth":null
  8711. };
  8712. /**
  8713. * DataTables settings object - this holds all the information needed for a
  8714. * given table, including configuration, data and current application of the
  8715. * table options. DataTables does not have a single instance for each DataTable
  8716. * with the settings attached to that instance, but rather instances of the
  8717. * DataTable "class" are created on-the-fly as needed (typically by a
  8718. * $().dataTable() call) and the settings object is then applied to that
  8719. * instance.
  8720. *
  8721. * Note that this object is related to {@link DataTable.defaults} but this
  8722. * one is the internal data store for DataTables's cache of columns. It should
  8723. * NOT be manipulated outside of DataTables. Any configuration should be done
  8724. * through the initialisation options.
  8725. * @namespace
  8726. * @todo Really should attach the settings object to individual instances so we
  8727. * don't need to create new instances on each $().dataTable() call (if the
  8728. * table already exists). It would also save passing oSettings around and
  8729. * into every single function. However, this is a very significant
  8730. * architecture change for DataTables and will almost certainly break
  8731. * backwards compatibility with older installations. This is something that
  8732. * will be done in 2.0.
  8733. */
  8734. DataTable.models.oSettings = {
  8735. /**
  8736. * Primary features of DataTables and their enablement state.
  8737. * @namespace
  8738. */
  8739. "oFeatures":{
  8740. /**
  8741. * Flag to say if DataTables should automatically try to calculate the
  8742. * optimum table and columns widths (true) or not (false).
  8743. * Note that this parameter will be set by the initialisation routine. To
  8744. * set a default use {@link DataTable.defaults}.
  8745. * @type boolean
  8746. */
  8747. "bAutoWidth":null,
  8748. /**
  8749. * Delay the creation of TR and TD elements until they are actually
  8750. * needed by a driven page draw. This can give a significant speed
  8751. * increase for Ajax source and Javascript source data, but makes no
  8752. * difference at all fro DOM and server-side processing tables.
  8753. * Note that this parameter will be set by the initialisation routine. To
  8754. * set a default use {@link DataTable.defaults}.
  8755. * @type boolean
  8756. */
  8757. "bDeferRender":null,
  8758. /**
  8759. * Enable filtering on the table or not. Note that if this is disabled
  8760. * then there is no filtering at all on the table, including fnFilter.
  8761. * To just remove the filtering input use sDom and remove the 'f' option.
  8762. * Note that this parameter will be set by the initialisation routine. To
  8763. * set a default use {@link DataTable.defaults}.
  8764. * @type boolean
  8765. */
  8766. "bFilter":null,
  8767. /**
  8768. * Table information element (the 'Showing x of y records' div) enable
  8769. * flag.
  8770. * Note that this parameter will be set by the initialisation routine. To
  8771. * set a default use {@link DataTable.defaults}.
  8772. * @type boolean
  8773. */
  8774. "bInfo":null,
  8775. /**
  8776. * Present a user control allowing the end user to change the page size
  8777. * when pagination is enabled.
  8778. * Note that this parameter will be set by the initialisation routine. To
  8779. * set a default use {@link DataTable.defaults}.
  8780. * @type boolean
  8781. */
  8782. "bLengthChange":null,
  8783. /**
  8784. * Pagination enabled or not. Note that if this is disabled then length
  8785. * changing must also be disabled.
  8786. * Note that this parameter will be set by the initialisation routine. To
  8787. * set a default use {@link DataTable.defaults}.
  8788. * @type boolean
  8789. */
  8790. "bPaginate":null,
  8791. /**
  8792. * Processing indicator enable flag whenever DataTables is enacting a
  8793. * user request - typically an Ajax request for server-side processing.
  8794. * Note that this parameter will be set by the initialisation routine. To
  8795. * set a default use {@link DataTable.defaults}.
  8796. * @type boolean
  8797. */
  8798. "bProcessing":null,
  8799. /**
  8800. * Server-side processing enabled flag - when enabled DataTables will
  8801. * get all data from the server for every draw - there is no filtering,
  8802. * sorting or paging done on the client-side.
  8803. * Note that this parameter will be set by the initialisation routine. To
  8804. * set a default use {@link DataTable.defaults}.
  8805. * @type boolean
  8806. */
  8807. "bServerSide":null,
  8808. /**
  8809. * Sorting enablement flag.
  8810. * Note that this parameter will be set by the initialisation routine. To
  8811. * set a default use {@link DataTable.defaults}.
  8812. * @type boolean
  8813. */
  8814. "bSort":null,
  8815. /**
  8816. * Apply a class to the columns which are being sorted to provide a
  8817. * visual highlight or not. This can slow things down when enabled since
  8818. * there is a lot of DOM interaction.
  8819. * Note that this parameter will be set by the initialisation routine. To
  8820. * set a default use {@link DataTable.defaults}.
  8821. * @type boolean
  8822. */
  8823. "bSortClasses":null,
  8824. /**
  8825. * State saving enablement flag.
  8826. * Note that this parameter will be set by the initialisation routine. To
  8827. * set a default use {@link DataTable.defaults}.
  8828. * @type boolean
  8829. */
  8830. "bStateSave":null
  8831. },
  8832. /**
  8833. * Scrolling settings for a table.
  8834. * @namespace
  8835. */
  8836. "oScroll":{
  8837. /**
  8838. * Indicate if DataTables should be allowed to set the padding / margin
  8839. * etc for the scrolling header elements or not. Typically you will want
  8840. * this.
  8841. * Note that this parameter will be set by the initialisation routine. To
  8842. * set a default use {@link DataTable.defaults}.
  8843. * @type boolean
  8844. */
  8845. "bAutoCss":null,
  8846. /**
  8847. * When the table is shorter in height than sScrollY, collapse the
  8848. * table container down to the height of the table (when true).
  8849. * Note that this parameter will be set by the initialisation routine. To
  8850. * set a default use {@link DataTable.defaults}.
  8851. * @type boolean
  8852. */
  8853. "bCollapse":null,
  8854. /**
  8855. * Infinite scrolling enablement flag. Now deprecated in favour of
  8856. * using the Scroller plug-in.
  8857. * Note that this parameter will be set by the initialisation routine. To
  8858. * set a default use {@link DataTable.defaults}.
  8859. * @type boolean
  8860. */
  8861. "bInfinite":null,
  8862. /**
  8863. * Width of the scrollbar for the web-browser's platform. Calculated
  8864. * during table initialisation.
  8865. * @type int
  8866. * @default 0
  8867. */
  8868. "iBarWidth":0,
  8869. /**
  8870. * Space (in pixels) between the bottom of the scrolling container and
  8871. * the bottom of the scrolling viewport before the next page is loaded
  8872. * when using infinite scrolling.
  8873. * Note that this parameter will be set by the initialisation routine. To
  8874. * set a default use {@link DataTable.defaults}.
  8875. * @type int
  8876. */
  8877. "iLoadGap":null,
  8878. /**
  8879. * Viewport width for horizontal scrolling. Horizontal scrolling is
  8880. * disabled if an empty string.
  8881. * Note that this parameter will be set by the initialisation routine. To
  8882. * set a default use {@link DataTable.defaults}.
  8883. * @type string
  8884. */
  8885. "sX":null,
  8886. /**
  8887. * Width to expand the table to when using x-scrolling. Typically you
  8888. * should not need to use this.
  8889. * Note that this parameter will be set by the initialisation routine. To
  8890. * set a default use {@link DataTable.defaults}.
  8891. * @type string
  8892. * @deprecated
  8893. */
  8894. "sXInner":null,
  8895. /**
  8896. * Viewport height for vertical scrolling. Vertical scrolling is disabled
  8897. * if an empty string.
  8898. * Note that this parameter will be set by the initialisation routine. To
  8899. * set a default use {@link DataTable.defaults}.
  8900. * @type string
  8901. */
  8902. "sY":null
  8903. },
  8904. /**
  8905. * Language information for the table.
  8906. * @namespace
  8907. * @extends DataTable.defaults.oLanguage
  8908. */
  8909. "oLanguage":{
  8910. /**
  8911. * Information callback function. See
  8912. * {@link DataTable.defaults.fnInfoCallback}
  8913. * @type function
  8914. * @default null
  8915. */
  8916. "fnInfoCallback":null
  8917. },
  8918. /**
  8919. * Browser support parameters
  8920. * @namespace
  8921. */
  8922. "oBrowser":{
  8923. /**
  8924. * Indicate if the browser incorrectly calculates width:100% inside a
  8925. * scrolling element (IE6/7)
  8926. * @type boolean
  8927. * @default false
  8928. */
  8929. "bScrollOversize":false
  8930. },
  8931. /**
  8932. * Array referencing the nodes which are used for the features. The
  8933. * parameters of this object match what is allowed by sDom - i.e.
  8934. * <ul>
  8935. * <li>'l' - Length changing</li>
  8936. * <li>'f' - Filtering input</li>
  8937. * <li>'t' - The table!</li>
  8938. * <li>'i' - Information</li>
  8939. * <li>'p' - Pagination</li>
  8940. * <li>'r' - pRocessing</li>
  8941. * </ul>
  8942. * @type array
  8943. * @default []
  8944. */
  8945. "aanFeatures":[],
  8946. /**
  8947. * Store data information - see {@link DataTable.models.oRow} for detailed
  8948. * information.
  8949. * @type array
  8950. * @default []
  8951. */
  8952. "aoData":[],
  8953. /**
  8954. * Array of indexes which are in the current display (after filtering etc)
  8955. * @type array
  8956. * @default []
  8957. */
  8958. "aiDisplay":[],
  8959. /**
  8960. * Array of indexes for display - no filtering
  8961. * @type array
  8962. * @default []
  8963. */
  8964. "aiDisplayMaster":[],
  8965. /**
  8966. * Store information about each column that is in use
  8967. * @type array
  8968. * @default []
  8969. */
  8970. "aoColumns":[],
  8971. /**
  8972. * Store information about the table's header
  8973. * @type array
  8974. * @default []
  8975. */
  8976. "aoHeader":[],
  8977. /**
  8978. * Store information about the table's footer
  8979. * @type array
  8980. * @default []
  8981. */
  8982. "aoFooter":[],
  8983. /**
  8984. * Search data array for regular expression searching
  8985. * @type array
  8986. * @default []
  8987. */
  8988. "asDataSearch":[],
  8989. /**
  8990. * Store the applied global search information in case we want to force a
  8991. * research or compare the old search to a new one.
  8992. * Note that this parameter will be set by the initialisation routine. To
  8993. * set a default use {@link DataTable.defaults}.
  8994. * @namespace
  8995. * @extends DataTable.models.oSearch
  8996. */
  8997. "oPreviousSearch":{},
  8998. /**
  8999. * Store the applied search for each column - see
  9000. * {@link DataTable.models.oSearch} for the format that is used for the
  9001. * filtering information for each column.
  9002. * @type array
  9003. * @default []
  9004. */
  9005. "aoPreSearchCols":[],
  9006. /**
  9007. * Sorting that is applied to the table. Note that the inner arrays are
  9008. * used in the following manner:
  9009. * <ul>
  9010. * <li>Index 0 - column number</li>
  9011. * <li>Index 1 - current sorting direction</li>
  9012. * <li>Index 2 - index of asSorting for this column</li>
  9013. * </ul>
  9014. * Note that this parameter will be set by the initialisation routine. To
  9015. * set a default use {@link DataTable.defaults}.
  9016. * @type array
  9017. * @todo These inner arrays should really be objects
  9018. */
  9019. "aaSorting":null,
  9020. /**
  9021. * Sorting that is always applied to the table (i.e. prefixed in front of
  9022. * aaSorting).
  9023. * Note that this parameter will be set by the initialisation routine. To
  9024. * set a default use {@link DataTable.defaults}.
  9025. * @type array|null
  9026. * @default null
  9027. */
  9028. "aaSortingFixed":null,
  9029. /**
  9030. * Classes to use for the striping of a table.
  9031. * Note that this parameter will be set by the initialisation routine. To
  9032. * set a default use {@link DataTable.defaults}.
  9033. * @type array
  9034. * @default []
  9035. */
  9036. "asStripeClasses":null,
  9037. /**
  9038. * If restoring a table - we should restore its striping classes as well
  9039. * @type array
  9040. * @default []
  9041. */
  9042. "asDestroyStripes":[],
  9043. /**
  9044. * If restoring a table - we should restore its width
  9045. * @type int
  9046. * @default 0
  9047. */
  9048. "sDestroyWidth":0,
  9049. /**
  9050. * Callback functions array for every time a row is inserted (i.e. on a draw).
  9051. * @type array
  9052. * @default []
  9053. */
  9054. "aoRowCallback":[],
  9055. /**
  9056. * Callback functions for the header on each draw.
  9057. * @type array
  9058. * @default []
  9059. */
  9060. "aoHeaderCallback":[],
  9061. /**
  9062. * Callback function for the footer on each draw.
  9063. * @type array
  9064. * @default []
  9065. */
  9066. "aoFooterCallback":[],
  9067. /**
  9068. * Array of callback functions for draw callback functions
  9069. * @type array
  9070. * @default []
  9071. */
  9072. "aoDrawCallback":[],
  9073. /**
  9074. * Array of callback functions for row created function
  9075. * @type array
  9076. * @default []
  9077. */
  9078. "aoRowCreatedCallback":[],
  9079. /**
  9080. * Callback functions for just before the table is redrawn. A return of
  9081. * false will be used to cancel the draw.
  9082. * @type array
  9083. * @default []
  9084. */
  9085. "aoPreDrawCallback":[],
  9086. /**
  9087. * Callback functions for when the table has been initialised.
  9088. * @type array
  9089. * @default []
  9090. */
  9091. "aoInitComplete":[],
  9092. /**
  9093. * Callbacks for modifying the settings to be stored for state saving, prior to
  9094. * saving state.
  9095. * @type array
  9096. * @default []
  9097. */
  9098. "aoStateSaveParams":[],
  9099. /**
  9100. * Callbacks for modifying the settings that have been stored for state saving
  9101. * prior to using the stored values to restore the state.
  9102. * @type array
  9103. * @default []
  9104. */
  9105. "aoStateLoadParams":[],
  9106. /**
  9107. * Callbacks for operating on the settings object once the saved state has been
  9108. * loaded
  9109. * @type array
  9110. * @default []
  9111. */
  9112. "aoStateLoaded":[],
  9113. /**
  9114. * Cache the table ID for quick access
  9115. * @type string
  9116. * @default <i>Empty string</i>
  9117. */
  9118. "sTableId":"",
  9119. /**
  9120. * The TABLE node for the main table
  9121. * @type node
  9122. * @default null
  9123. */
  9124. "nTable":null,
  9125. /**
  9126. * Permanent ref to the thead element
  9127. * @type node
  9128. * @default null
  9129. */
  9130. "nTHead":null,
  9131. /**
  9132. * Permanent ref to the tfoot element - if it exists
  9133. * @type node
  9134. * @default null
  9135. */
  9136. "nTFoot":null,
  9137. /**
  9138. * Permanent ref to the tbody element
  9139. * @type node
  9140. * @default null
  9141. */
  9142. "nTBody":null,
  9143. /**
  9144. * Cache the wrapper node (contains all DataTables controlled elements)
  9145. * @type node
  9146. * @default null
  9147. */
  9148. "nTableWrapper":null,
  9149. /**
  9150. * Indicate if when using server-side processing the loading of data
  9151. * should be deferred until the second draw.
  9152. * Note that this parameter will be set by the initialisation routine. To
  9153. * set a default use {@link DataTable.defaults}.
  9154. * @type boolean
  9155. * @default false
  9156. */
  9157. "bDeferLoading":false,
  9158. /**
  9159. * Indicate if all required information has been read in
  9160. * @type boolean
  9161. * @default false
  9162. */
  9163. "bInitialised":false,
  9164. /**
  9165. * Information about open rows. Each object in the array has the parameters
  9166. * 'nTr' and 'nParent'
  9167. * @type array
  9168. * @default []
  9169. */
  9170. "aoOpenRows":[],
  9171. /**
  9172. * Dictate the positioning of DataTables' control elements - see
  9173. * {@link DataTable.model.oInit.sDom}.
  9174. * Note that this parameter will be set by the initialisation routine. To
  9175. * set a default use {@link DataTable.defaults}.
  9176. * @type string
  9177. * @default null
  9178. */
  9179. "sDom":null,
  9180. /**
  9181. * Which type of pagination should be used.
  9182. * Note that this parameter will be set by the initialisation routine. To
  9183. * set a default use {@link DataTable.defaults}.
  9184. * @type string
  9185. * @default two_button
  9186. */
  9187. "sPaginationType":"two_button",
  9188. /**
  9189. * The cookie duration (for bStateSave) in seconds.
  9190. * Note that this parameter will be set by the initialisation routine. To
  9191. * set a default use {@link DataTable.defaults}.
  9192. * @type int
  9193. * @default 0
  9194. */
  9195. "iCookieDuration":0,
  9196. /**
  9197. * The cookie name prefix.
  9198. * Note that this parameter will be set by the initialisation routine. To
  9199. * set a default use {@link DataTable.defaults}.
  9200. * @type string
  9201. * @default <i>Empty string</i>
  9202. */
  9203. "sCookiePrefix":"",
  9204. /**
  9205. * Callback function for cookie creation.
  9206. * Note that this parameter will be set by the initialisation routine. To
  9207. * set a default use {@link DataTable.defaults}.
  9208. * @type function
  9209. * @default null
  9210. */
  9211. "fnCookieCallback":null,
  9212. /**
  9213. * Array of callback functions for state saving. Each array element is an
  9214. * object with the following parameters:
  9215. * <ul>
  9216. * <li>function:fn - function to call. Takes two parameters, oSettings
  9217. * and the JSON string to save that has been thus far created. Returns
  9218. * a JSON string to be inserted into a json object
  9219. * (i.e. '"param": [ 0, 1, 2]')</li>
  9220. * <li>string:sName - name of callback</li>
  9221. * </ul>
  9222. * @type array
  9223. * @default []
  9224. */
  9225. "aoStateSave":[],
  9226. /**
  9227. * Array of callback functions for state loading. Each array element is an
  9228. * object with the following parameters:
  9229. * <ul>
  9230. * <li>function:fn - function to call. Takes two parameters, oSettings
  9231. * and the object stored. May return false to cancel state loading</li>
  9232. * <li>string:sName - name of callback</li>
  9233. * </ul>
  9234. * @type array
  9235. * @default []
  9236. */
  9237. "aoStateLoad":[],
  9238. /**
  9239. * State that was loaded from the cookie. Useful for back reference
  9240. * @type object
  9241. * @default null
  9242. */
  9243. "oLoadedState":null,
  9244. /**
  9245. * Source url for AJAX data for the table.
  9246. * Note that this parameter will be set by the initialisation routine. To
  9247. * set a default use {@link DataTable.defaults}.
  9248. * @type string
  9249. * @default null
  9250. */
  9251. "sAjaxSource":null,
  9252. /**
  9253. * Property from a given object from which to read the table data from. This
  9254. * can be an empty string (when not server-side processing), in which case
  9255. * it is assumed an an array is given directly.
  9256. * Note that this parameter will be set by the initialisation routine. To
  9257. * set a default use {@link DataTable.defaults}.
  9258. * @type string
  9259. */
  9260. "sAjaxDataProp":null,
  9261. /**
  9262. * Note if draw should be blocked while getting data
  9263. * @type boolean
  9264. * @default true
  9265. */
  9266. "bAjaxDataGet":true,
  9267. /**
  9268. * The last jQuery XHR object that was used for server-side data gathering.
  9269. * This can be used for working with the XHR information in one of the
  9270. * callbacks
  9271. * @type object
  9272. * @default null
  9273. */
  9274. "jqXHR":null,
  9275. /**
  9276. * Function to get the server-side data.
  9277. * Note that this parameter will be set by the initialisation routine. To
  9278. * set a default use {@link DataTable.defaults}.
  9279. * @type function
  9280. */
  9281. "fnServerData":null,
  9282. /**
  9283. * Functions which are called prior to sending an Ajax request so extra
  9284. * parameters can easily be sent to the server
  9285. * @type array
  9286. * @default []
  9287. */
  9288. "aoServerParams":[],
  9289. /**
  9290. * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
  9291. * required).
  9292. * Note that this parameter will be set by the initialisation routine. To
  9293. * set a default use {@link DataTable.defaults}.
  9294. * @type string
  9295. */
  9296. "sServerMethod":null,
  9297. /**
  9298. * Format numbers for display.
  9299. * Note that this parameter will be set by the initialisation routine. To
  9300. * set a default use {@link DataTable.defaults}.
  9301. * @type function
  9302. */
  9303. "fnFormatNumber":null,
  9304. /**
  9305. * List of options that can be used for the user selectable length menu.
  9306. * Note that this parameter will be set by the initialisation routine. To
  9307. * set a default use {@link DataTable.defaults}.
  9308. * @type array
  9309. * @default []
  9310. */
  9311. "aLengthMenu":null,
  9312. /**
  9313. * Counter for the draws that the table does. Also used as a tracker for
  9314. * server-side processing
  9315. * @type int
  9316. * @default 0
  9317. */
  9318. "iDraw":0,
  9319. /**
  9320. * Indicate if a redraw is being done - useful for Ajax
  9321. * @type boolean
  9322. * @default false
  9323. */
  9324. "bDrawing":false,
  9325. /**
  9326. * Draw index (iDraw) of the last error when parsing the returned data
  9327. * @type int
  9328. * @default -1
  9329. */
  9330. "iDrawError":-1,
  9331. /**
  9332. * Paging display length
  9333. * @type int
  9334. * @default 10
  9335. */
  9336. "_iDisplayLength":10,
  9337. /**
  9338. * Paging start point - aiDisplay index
  9339. * @type int
  9340. * @default 0
  9341. */
  9342. "_iDisplayStart":0,
  9343. /**
  9344. * Paging end point - aiDisplay index. Use fnDisplayEnd rather than
  9345. * this property to get the end point
  9346. * @type int
  9347. * @default 10
  9348. * @private
  9349. */
  9350. "_iDisplayEnd":10,
  9351. /**
  9352. * Server-side processing - number of records in the result set
  9353. * (i.e. before filtering), Use fnRecordsTotal rather than
  9354. * this property to get the value of the number of records, regardless of
  9355. * the server-side processing setting.
  9356. * @type int
  9357. * @default 0
  9358. * @private
  9359. */
  9360. "_iRecordsTotal":0,
  9361. /**
  9362. * Server-side processing - number of records in the current display set
  9363. * (i.e. after filtering). Use fnRecordsDisplay rather than
  9364. * this property to get the value of the number of records, regardless of
  9365. * the server-side processing setting.
  9366. * @type boolean
  9367. * @default 0
  9368. * @private
  9369. */
  9370. "_iRecordsDisplay":0,
  9371. /**
  9372. * Flag to indicate if jQuery UI marking and classes should be used.
  9373. * Note that this parameter will be set by the initialisation routine. To
  9374. * set a default use {@link DataTable.defaults}.
  9375. * @type boolean
  9376. */
  9377. "bJUI":null,
  9378. /**
  9379. * The classes to use for the table
  9380. * @type object
  9381. * @default {}
  9382. */
  9383. "oClasses":{},
  9384. /**
  9385. * Flag attached to the settings object so you can check in the draw
  9386. * callback if filtering has been done in the draw. Deprecated in favour of
  9387. * events.
  9388. * @type boolean
  9389. * @default false
  9390. * @deprecated
  9391. */
  9392. "bFiltered":false,
  9393. /**
  9394. * Flag attached to the settings object so you can check in the draw
  9395. * callback if sorting has been done in the draw. Deprecated in favour of
  9396. * events.
  9397. * @type boolean
  9398. * @default false
  9399. * @deprecated
  9400. */
  9401. "bSorted":false,
  9402. /**
  9403. * Indicate that if multiple rows are in the header and there is more than
  9404. * one unique cell per column, if the top one (true) or bottom one (false)
  9405. * should be used for sorting / title by DataTables.
  9406. * Note that this parameter will be set by the initialisation routine. To
  9407. * set a default use {@link DataTable.defaults}.
  9408. * @type boolean
  9409. */
  9410. "bSortCellsTop":null,
  9411. /**
  9412. * Initialisation object that is used for the table
  9413. * @type object
  9414. * @default null
  9415. */
  9416. "oInit":null,
  9417. /**
  9418. * Destroy callback functions - for plug-ins to attach themselves to the
  9419. * destroy so they can clean up markup and events.
  9420. * @type array
  9421. * @default []
  9422. */
  9423. "aoDestroyCallback":[],
  9424. /**
  9425. * Get the number of records in the current record set, before filtering
  9426. * @type function
  9427. */
  9428. "fnRecordsTotal":function () {
  9429. if (this.oFeatures.bServerSide) {
  9430. return parseInt(this._iRecordsTotal, 10);
  9431. } else {
  9432. return this.aiDisplayMaster.length;
  9433. }
  9434. },
  9435. /**
  9436. * Get the number of records in the current record set, after filtering
  9437. * @type function
  9438. */
  9439. "fnRecordsDisplay":function () {
  9440. if (this.oFeatures.bServerSide) {
  9441. return parseInt(this._iRecordsDisplay, 10);
  9442. } else {
  9443. return this.aiDisplay.length;
  9444. }
  9445. },
  9446. /**
  9447. * Set the display end point - aiDisplay index
  9448. * @type function
  9449. * @todo Should do away with _iDisplayEnd and calculate it on-the-fly here
  9450. */
  9451. "fnDisplayEnd":function () {
  9452. if (this.oFeatures.bServerSide) {
  9453. if (this.oFeatures.bPaginate === false || this._iDisplayLength == -1) {
  9454. return this._iDisplayStart + this.aiDisplay.length;
  9455. } else {
  9456. return Math.min(this._iDisplayStart + this._iDisplayLength,
  9457. this._iRecordsDisplay);
  9458. }
  9459. } else {
  9460. return this._iDisplayEnd;
  9461. }
  9462. },
  9463. /**
  9464. * The DataTables object for this table
  9465. * @type object
  9466. * @default null
  9467. */
  9468. "oInstance":null,
  9469. /**
  9470. * Unique identifier for each instance of the DataTables object. If there
  9471. * is an ID on the table node, then it takes that value, otherwise an
  9472. * incrementing internal counter is used.
  9473. * @type string
  9474. * @default null
  9475. */
  9476. "sInstance":null,
  9477. /**
  9478. * tabindex attribute value that is added to DataTables control elements, allowing
  9479. * keyboard navigation of the table and its controls.
  9480. */
  9481. "iTabIndex":0,
  9482. /**
  9483. * DIV container for the footer scrolling table if scrolling
  9484. */
  9485. "nScrollHead":null,
  9486. /**
  9487. * DIV container for the footer scrolling table if scrolling
  9488. */
  9489. "nScrollFoot":null
  9490. };
  9491. /**
  9492. * Extension object for DataTables that is used to provide all extension options.
  9493. *
  9494. * Note that the <i>DataTable.ext</i> object is available through
  9495. * <i>jQuery.fn.dataTable.ext</i> where it may be accessed and manipulated. It is
  9496. * also aliased to <i>jQuery.fn.dataTableExt</i> for historic reasons.
  9497. * @namespace
  9498. * @extends DataTable.models.ext
  9499. */
  9500. DataTable.ext = $.extend(true, {}, DataTable.models.ext);
  9501. $.extend(DataTable.ext.oStdClasses, {
  9502. "sTable":"dataTable",
  9503. /* Two buttons buttons */
  9504. "sPagePrevEnabled":"paginate_enabled_previous",
  9505. "sPagePrevDisabled":"paginate_disabled_previous",
  9506. "sPageNextEnabled":"paginate_enabled_next",
  9507. "sPageNextDisabled":"paginate_disabled_next",
  9508. "sPageJUINext":"",
  9509. "sPageJUIPrev":"",
  9510. /* Full numbers paging buttons */
  9511. "sPageButton":"paginate_button",
  9512. "sPageButtonActive":"paginate_active",
  9513. "sPageButtonStaticDisabled":"paginate_button paginate_button_disabled",
  9514. "sPageFirst":"first",
  9515. "sPagePrevious":"previous",
  9516. "sPageNext":"next",
  9517. "sPageLast":"last",
  9518. /* Striping classes */
  9519. "sStripeOdd":"odd",
  9520. "sStripeEven":"even",
  9521. /* Empty row */
  9522. "sRowEmpty":"dataTables_empty",
  9523. /* Features */
  9524. "sWrapper":"dataTables_wrapper",
  9525. "sFilter":"dataTables_filter",
  9526. "sInfo":"dataTables_info",
  9527. "sPaging":"dataTables_paginate paging_", /* Note that the type is postfixed */
  9528. "sLength":"dataTables_length",
  9529. "sProcessing":"dataTables_processing",
  9530. /* Sorting */
  9531. "sSortAsc":"sorting_asc",
  9532. "sSortDesc":"sorting_desc",
  9533. "sSortable":"sorting", /* Sortable in both directions */
  9534. "sSortableAsc":"sorting_asc_disabled",
  9535. "sSortableDesc":"sorting_desc_disabled",
  9536. "sSortableNone":"sorting_disabled",
  9537. "sSortColumn":"sorting_", /* Note that an int is postfixed for the sorting order */
  9538. "sSortJUIAsc":"",
  9539. "sSortJUIDesc":"",
  9540. "sSortJUI":"",
  9541. "sSortJUIAscAllowed":"",
  9542. "sSortJUIDescAllowed":"",
  9543. "sSortJUIWrapper":"",
  9544. "sSortIcon":"",
  9545. /* Scrolling */
  9546. "sScrollWrapper":"dataTables_scroll",
  9547. "sScrollHead":"dataTables_scrollHead",
  9548. "sScrollHeadInner":"dataTables_scrollHeadInner",
  9549. "sScrollBody":"dataTables_scrollBody",
  9550. "sScrollFoot":"dataTables_scrollFoot",
  9551. "sScrollFootInner":"dataTables_scrollFootInner",
  9552. /* Misc */
  9553. "sFooterTH":"",
  9554. "sJUIHeader":"",
  9555. "sJUIFooter":""
  9556. });
  9557. $.extend(DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, {
  9558. /* Two buttons buttons */
  9559. "sPagePrevEnabled":"fg-button ui-button ui-state-default ui-corner-left",
  9560. "sPagePrevDisabled":"fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",
  9561. "sPageNextEnabled":"fg-button ui-button ui-state-default ui-corner-right",
  9562. "sPageNextDisabled":"fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",
  9563. "sPageJUINext":"ui-icon ui-icon-circle-arrow-e",
  9564. "sPageJUIPrev":"ui-icon ui-icon-circle-arrow-w",
  9565. /* Full numbers paging buttons */
  9566. "sPageButton":"fg-button ui-button ui-state-default",
  9567. "sPageButtonActive":"fg-button ui-button ui-state-default ui-state-disabled",
  9568. "sPageButtonStaticDisabled":"fg-button ui-button ui-state-default ui-state-disabled",
  9569. "sPageFirst":"first ui-corner-tl ui-corner-bl",
  9570. "sPageLast":"last ui-corner-tr ui-corner-br",
  9571. /* Features */
  9572. "sPaging":"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi " +
  9573. "ui-buttonset-multi paging_", /* Note that the type is postfixed */
  9574. /* Sorting */
  9575. "sSortAsc":"ui-state-default",
  9576. "sSortDesc":"ui-state-default",
  9577. "sSortable":"ui-state-default",
  9578. "sSortableAsc":"ui-state-default",
  9579. "sSortableDesc":"ui-state-default",
  9580. "sSortableNone":"ui-state-default",
  9581. "sSortJUIAsc":"css_right ui-icon ui-icon-triangle-1-n",
  9582. "sSortJUIDesc":"css_right ui-icon ui-icon-triangle-1-s",
  9583. "sSortJUI":"css_right ui-icon ui-icon-carat-2-n-s",
  9584. "sSortJUIAscAllowed":"css_right ui-icon ui-icon-carat-1-n",
  9585. "sSortJUIDescAllowed":"css_right ui-icon ui-icon-carat-1-s",
  9586. "sSortJUIWrapper":"DataTables_sort_wrapper",
  9587. "sSortIcon":"DataTables_sort_icon",
  9588. /* Scrolling */
  9589. "sScrollHead":"dataTables_scrollHead ui-state-default",
  9590. "sScrollFoot":"dataTables_scrollFoot ui-state-default",
  9591. /* Misc */
  9592. "sFooterTH":"ui-state-default",
  9593. "sJUIHeader":"fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix",
  9594. "sJUIFooter":"fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"
  9595. });
  9596. /*
  9597. * Variable: oPagination
  9598. * Purpose:
  9599. * Scope: jQuery.fn.dataTableExt
  9600. */
  9601. $.extend(DataTable.ext.oPagination, {
  9602. /*
  9603. * Variable: two_button
  9604. * Purpose: Standard two button (forward/back) pagination
  9605. * Scope: jQuery.fn.dataTableExt.oPagination
  9606. */
  9607. "two_button":{
  9608. /*
  9609. * Function: oPagination.two_button.fnInit
  9610. * Purpose: Initialise dom elements required for pagination with forward/back buttons only
  9611. * Returns: -
  9612. * Inputs: object:oSettings - dataTables settings object
  9613. * node:nPaging - the DIV which contains this pagination control
  9614. * function:fnCallbackDraw - draw function which must be called on update
  9615. */
  9616. "fnInit":function (oSettings, nPaging, fnCallbackDraw) {
  9617. var oLang = oSettings.oLanguage.oPaginate;
  9618. var oClasses = oSettings.oClasses;
  9619. var fnClickHandler = function (e) {
  9620. if (oSettings.oApi._fnPageChange(oSettings, e.data.action)) {
  9621. fnCallbackDraw(oSettings);
  9622. }
  9623. };
  9624. var sAppend = (!oSettings.bJUI) ?
  9625. '<a class="' + oSettings.oClasses.sPagePrevDisabled + '" tabindex="' + oSettings.iTabIndex + '" role="button">' + oLang.sPrevious + '</a>' +
  9626. '<a class="' + oSettings.oClasses.sPageNextDisabled + '" tabindex="' + oSettings.iTabIndex + '" role="button">' + oLang.sNext + '</a>'
  9627. :
  9628. '<a class="' + oSettings.oClasses.sPagePrevDisabled + '" tabindex="' + oSettings.iTabIndex + '" role="button"><span class="' + oSettings.oClasses.sPageJUIPrev + '"></span></a>' +
  9629. '<a class="' + oSettings.oClasses.sPageNextDisabled + '" tabindex="' + oSettings.iTabIndex + '" role="button"><span class="' + oSettings.oClasses.sPageJUINext + '"></span></a>';
  9630. $(nPaging).append(sAppend);
  9631. var els = $('a', nPaging);
  9632. var nPrevious = els[0],
  9633. nNext = els[1];
  9634. oSettings.oApi._fnBindAction(nPrevious, {action:"previous"}, fnClickHandler);
  9635. oSettings.oApi._fnBindAction(nNext, {action:"next"}, fnClickHandler);
  9636. /* ID the first elements only */
  9637. if (!oSettings.aanFeatures.p) {
  9638. nPaging.id = oSettings.sTableId + '_paginate';
  9639. nPrevious.id = oSettings.sTableId + '_previous';
  9640. nNext.id = oSettings.sTableId + '_next';
  9641. nPrevious.setAttribute('aria-controls', oSettings.sTableId);
  9642. nNext.setAttribute('aria-controls', oSettings.sTableId);
  9643. }
  9644. },
  9645. /*
  9646. * Function: oPagination.two_button.fnUpdate
  9647. * Purpose: Update the two button pagination at the end of the draw
  9648. * Returns: -
  9649. * Inputs: object:oSettings - dataTables settings object
  9650. * function:fnCallbackDraw - draw function to call on page change
  9651. */
  9652. "fnUpdate":function (oSettings, fnCallbackDraw) {
  9653. if (!oSettings.aanFeatures.p) {
  9654. return;
  9655. }
  9656. var oClasses = oSettings.oClasses;
  9657. var an = oSettings.aanFeatures.p;
  9658. var nNode;
  9659. /* Loop over each instance of the pager */
  9660. for (var i = 0, iLen = an.length; i < iLen; i++) {
  9661. nNode = an[i].firstChild;
  9662. if (nNode) {
  9663. /* Previous page */
  9664. nNode.className = ( oSettings._iDisplayStart === 0 ) ?
  9665. oClasses.sPagePrevDisabled : oClasses.sPagePrevEnabled;
  9666. /* Next page */
  9667. nNode = nNode.nextSibling;
  9668. nNode.className = ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) ?
  9669. oClasses.sPageNextDisabled : oClasses.sPageNextEnabled;
  9670. }
  9671. }
  9672. }
  9673. },
  9674. /*
  9675. * Variable: iFullNumbersShowPages
  9676. * Purpose: Change the number of pages which can be seen
  9677. * Scope: jQuery.fn.dataTableExt.oPagination
  9678. */
  9679. "iFullNumbersShowPages":5,
  9680. /*
  9681. * Variable: full_numbers
  9682. * Purpose: Full numbers pagination
  9683. * Scope: jQuery.fn.dataTableExt.oPagination
  9684. */
  9685. "full_numbers":{
  9686. /*
  9687. * Function: oPagination.full_numbers.fnInit
  9688. * Purpose: Initialise dom elements required for pagination with a list of the pages
  9689. * Returns: -
  9690. * Inputs: object:oSettings - dataTables settings object
  9691. * node:nPaging - the DIV which contains this pagination control
  9692. * function:fnCallbackDraw - draw function which must be called on update
  9693. */
  9694. "fnInit":function (oSettings, nPaging, fnCallbackDraw) {
  9695. var oLang = oSettings.oLanguage.oPaginate;
  9696. var oClasses = oSettings.oClasses;
  9697. var fnClickHandler = function (e) {
  9698. if (oSettings.oApi._fnPageChange(oSettings, e.data.action)) {
  9699. fnCallbackDraw(oSettings);
  9700. }
  9701. };
  9702. $(nPaging).append(
  9703. '<a tabindex="' + oSettings.iTabIndex + '" class="' + oClasses.sPageButton + " " + oClasses.sPageFirst + '">' + oLang.sFirst + '</a>' +
  9704. '<a tabindex="' + oSettings.iTabIndex + '" class="' + oClasses.sPageButton + " " + oClasses.sPagePrevious + '">' + oLang.sPrevious + '</a>' +
  9705. '<span></span>' +
  9706. '<a tabindex="' + oSettings.iTabIndex + '" class="' + oClasses.sPageButton + " " + oClasses.sPageNext + '">' + oLang.sNext + '</a>' +
  9707. '<a tabindex="' + oSettings.iTabIndex + '" class="' + oClasses.sPageButton + " " + oClasses.sPageLast + '">' + oLang.sLast + '</a>'
  9708. );
  9709. var els = $('a', nPaging);
  9710. var nFirst = els[0],
  9711. nPrev = els[1],
  9712. nNext = els[2],
  9713. nLast = els[3];
  9714. oSettings.oApi._fnBindAction(nFirst, {action:"first"}, fnClickHandler);
  9715. oSettings.oApi._fnBindAction(nPrev, {action:"previous"}, fnClickHandler);
  9716. oSettings.oApi._fnBindAction(nNext, {action:"next"}, fnClickHandler);
  9717. oSettings.oApi._fnBindAction(nLast, {action:"last"}, fnClickHandler);
  9718. /* ID the first elements only */
  9719. if (!oSettings.aanFeatures.p) {
  9720. nPaging.id = oSettings.sTableId + '_paginate';
  9721. nFirst.id = oSettings.sTableId + '_first';
  9722. nPrev.id = oSettings.sTableId + '_previous';
  9723. nNext.id = oSettings.sTableId + '_next';
  9724. nLast.id = oSettings.sTableId + '_last';
  9725. }
  9726. },
  9727. /*
  9728. * Function: oPagination.full_numbers.fnUpdate
  9729. * Purpose: Update the list of page buttons shows
  9730. * Returns: -
  9731. * Inputs: object:oSettings - dataTables settings object
  9732. * function:fnCallbackDraw - draw function to call on page change
  9733. */
  9734. "fnUpdate":function (oSettings, fnCallbackDraw) {
  9735. if (!oSettings.aanFeatures.p) {
  9736. return;
  9737. }
  9738. var iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages;
  9739. var iPageCountHalf = Math.floor(iPageCount / 2);
  9740. var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
  9741. var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
  9742. var sList = "";
  9743. var iStartButton, iEndButton, i, iLen;
  9744. var oClasses = oSettings.oClasses;
  9745. var anButtons, anStatic, nPaginateList, nNode;
  9746. var an = oSettings.aanFeatures.p;
  9747. var fnBind = function (j) {
  9748. oSettings.oApi._fnBindAction(this, {"page":j + iStartButton - 1}, function (e) {
  9749. /* Use the information in the element to jump to the required page */
  9750. oSettings.oApi._fnPageChange(oSettings, e.data.page);
  9751. fnCallbackDraw(oSettings);
  9752. e.preventDefault();
  9753. });
  9754. };
  9755. /* Pages calculation */
  9756. if (oSettings._iDisplayLength === -1) {
  9757. iStartButton = 1;
  9758. iEndButton = 1;
  9759. iCurrentPage = 1;
  9760. }
  9761. else if (iPages < iPageCount) {
  9762. iStartButton = 1;
  9763. iEndButton = iPages;
  9764. }
  9765. else if (iCurrentPage <= iPageCountHalf) {
  9766. iStartButton = 1;
  9767. iEndButton = iPageCount;
  9768. }
  9769. else if (iCurrentPage >= (iPages - iPageCountHalf)) {
  9770. iStartButton = iPages - iPageCount + 1;
  9771. iEndButton = iPages;
  9772. }
  9773. else {
  9774. iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
  9775. iEndButton = iStartButton + iPageCount - 1;
  9776. }
  9777. /* Build the dynamic list */
  9778. for (i = iStartButton; i <= iEndButton; i++) {
  9779. sList += (iCurrentPage !== i) ?
  9780. '<a tabindex="' + oSettings.iTabIndex + '" class="' + oClasses.sPageButton + '">' + oSettings.fnFormatNumber(i) + '</a>' :
  9781. '<a tabindex="' + oSettings.iTabIndex + '" class="' + oClasses.sPageButtonActive + '">' + oSettings.fnFormatNumber(i) + '</a>';
  9782. }
  9783. /* Loop over each instance of the pager */
  9784. for (i = 0, iLen = an.length; i < iLen; i++) {
  9785. nNode = an[i];
  9786. if (!nNode.hasChildNodes()) {
  9787. continue;
  9788. }
  9789. /* Build up the dynamic list first - html and listeners */
  9790. $('span:eq(0)', nNode)
  9791. .html(sList)
  9792. .children('a').each(fnBind);
  9793. /* Update the permanent button's classes */
  9794. anButtons = nNode.getElementsByTagName('a');
  9795. anStatic = [
  9796. anButtons[0], anButtons[1],
  9797. anButtons[anButtons.length - 2], anButtons[anButtons.length - 1]
  9798. ];
  9799. $(anStatic).removeClass(oClasses.sPageButton + " " + oClasses.sPageButtonActive + " " + oClasses.sPageButtonStaticDisabled);
  9800. $([anStatic[0], anStatic[1]]).addClass(
  9801. (iCurrentPage == 1) ?
  9802. oClasses.sPageButtonStaticDisabled :
  9803. oClasses.sPageButton
  9804. );
  9805. $([anStatic[2], anStatic[3]]).addClass(
  9806. (iPages === 0 || iCurrentPage === iPages || oSettings._iDisplayLength === -1) ?
  9807. oClasses.sPageButtonStaticDisabled :
  9808. oClasses.sPageButton
  9809. );
  9810. }
  9811. }
  9812. }
  9813. });
  9814. $.extend(DataTable.ext.oSort, {
  9815. /*
  9816. * text sorting
  9817. */
  9818. "string-pre":function (a) {
  9819. if (typeof a != 'string') {
  9820. a = (a !== null && a.toString) ? a.toString() : '';
  9821. }
  9822. return a.toLowerCase();
  9823. },
  9824. "string-asc":function (x, y) {
  9825. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  9826. },
  9827. "string-desc":function (x, y) {
  9828. return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  9829. },
  9830. /*
  9831. * html sorting (ignore html tags)
  9832. */
  9833. "html-pre":function (a) {
  9834. return a.replace(/<.*?>/g, "").toLowerCase();
  9835. },
  9836. "html-asc":function (x, y) {
  9837. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  9838. },
  9839. "html-desc":function (x, y) {
  9840. return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  9841. },
  9842. /*
  9843. * date sorting
  9844. */
  9845. "date-pre":function (a) {
  9846. var x = Date.parse(a);
  9847. if (isNaN(x) || x === "") {
  9848. x = Date.parse("01/01/1970 00:00:00");
  9849. }
  9850. return x;
  9851. },
  9852. "date-asc":function (x, y) {
  9853. return x - y;
  9854. },
  9855. "date-desc":function (x, y) {
  9856. return y - x;
  9857. },
  9858. /*
  9859. * numerical sorting
  9860. */
  9861. "numeric-pre":function (a) {
  9862. return (a == "-" || a === "") ? 0 : a * 1;
  9863. },
  9864. "numeric-asc":function (x, y) {
  9865. return x - y;
  9866. },
  9867. "numeric-desc":function (x, y) {
  9868. return y - x;
  9869. }
  9870. });
  9871. $.extend(DataTable.ext.aTypes, [
  9872. /*
  9873. * Function: -
  9874. * Purpose: Check to see if a string is numeric
  9875. * Returns: string:'numeric' or null
  9876. * Inputs: mixed:sText - string to check
  9877. */
  9878. function (sData) {
  9879. /* Allow zero length strings as a number */
  9880. if (typeof sData === 'number') {
  9881. return 'numeric';
  9882. }
  9883. else if (typeof sData !== 'string') {
  9884. return null;
  9885. }
  9886. var sValidFirstChars = "0123456789-";
  9887. var sValidChars = "0123456789.";
  9888. var Char;
  9889. var bDecimal = false;
  9890. /* Check for a valid first char (no period and allow negatives) */
  9891. Char = sData.charAt(0);
  9892. if (sValidFirstChars.indexOf(Char) == -1) {
  9893. return null;
  9894. }
  9895. /* Check all the other characters are valid */
  9896. for (var i = 1; i < sData.length; i++) {
  9897. Char = sData.charAt(i);
  9898. if (sValidChars.indexOf(Char) == -1) {
  9899. return null;
  9900. }
  9901. /* Only allowed one decimal place... */
  9902. if (Char == ".") {
  9903. if (bDecimal) {
  9904. return null;
  9905. }
  9906. bDecimal = true;
  9907. }
  9908. }
  9909. return 'numeric';
  9910. },
  9911. /*
  9912. * Function: -
  9913. * Purpose: Check to see if a string is actually a formatted date
  9914. * Returns: string:'date' or null
  9915. * Inputs: string:sText - string to check
  9916. */
  9917. function (sData) {
  9918. var iParse = Date.parse(sData);
  9919. if ((iParse !== null && !isNaN(iParse)) || (typeof sData === 'string' && sData.length === 0)) {
  9920. return 'date';
  9921. }
  9922. return null;
  9923. },
  9924. /*
  9925. * Function: -
  9926. * Purpose: Check to see if a string should be treated as an HTML string
  9927. * Returns: string:'html' or null
  9928. * Inputs: string:sText - string to check
  9929. */
  9930. function (sData) {
  9931. if (typeof sData === 'string' && sData.indexOf('<') != -1 && sData.indexOf('>') != -1) {
  9932. return 'html';
  9933. }
  9934. return null;
  9935. }
  9936. ]);
  9937. // jQuery aliases
  9938. $.fn.DataTable = DataTable;
  9939. $.fn.dataTable = DataTable;
  9940. $.fn.dataTableSettings = DataTable.settings;
  9941. $.fn.dataTableExt = DataTable.ext;
  9942. // Information about events fired by DataTables - for documentation.
  9943. /**
  9944. * Draw event, fired whenever the table is redrawn on the page, at the same point as
  9945. * fnDrawCallback. This may be useful for binding events or performing calculations when
  9946. * the table is altered at all.
  9947. * @name DataTable#draw
  9948. * @event
  9949. * @param {event} e jQuery event object
  9950. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  9951. */
  9952. /**
  9953. * Filter event, fired when the filtering applied to the table (using the build in global
  9954. * global filter, or column filters) is altered.
  9955. * @name DataTable#filter
  9956. * @event
  9957. * @param {event} e jQuery event object
  9958. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  9959. */
  9960. /**
  9961. * Page change event, fired when the paging of the table is altered.
  9962. * @name DataTable#page
  9963. * @event
  9964. * @param {event} e jQuery event object
  9965. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  9966. */
  9967. /**
  9968. * Sort event, fired when the sorting applied to the table is altered.
  9969. * @name DataTable#sort
  9970. * @event
  9971. * @param {event} e jQuery event object
  9972. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  9973. */
  9974. /**
  9975. * DataTables initialisation complete event, fired when the table is fully drawn,
  9976. * including Ajax data loaded, if Ajax data is required.
  9977. * @name DataTable#init
  9978. * @event
  9979. * @param {event} e jQuery event object
  9980. * @param {object} oSettings DataTables settings object
  9981. * @param {object} json The JSON object request from the server - only
  9982. * present if client-side Ajax sourced data is used</li></ol>
  9983. */
  9984. /**
  9985. * State save event, fired when the table has changed state a new state save is required.
  9986. * This method allows modification of the state saving object prior to actually doing the
  9987. * save, including addition or other state properties (for plug-ins) or modification
  9988. * of a DataTables core property.
  9989. * @name DataTable#stateSaveParams
  9990. * @event
  9991. * @param {event} e jQuery event object
  9992. * @param {object} oSettings DataTables settings object
  9993. * @param {object} json The state information to be saved
  9994. */
  9995. /**
  9996. * State load event, fired when the table is loading state from the stored data, but
  9997. * prior to the settings object being modified by the saved state - allowing modification
  9998. * of the saved state is required or loading of state for a plug-in.
  9999. * @name DataTable#stateLoadParams
  10000. * @event
  10001. * @param {event} e jQuery event object
  10002. * @param {object} oSettings DataTables settings object
  10003. * @param {object} json The saved state information
  10004. */
  10005. /**
  10006. * State loaded event, fired when state has been loaded from stored data and the settings
  10007. * object has been modified by the loaded data.
  10008. * @name DataTable#stateLoaded
  10009. * @event
  10010. * @param {event} e jQuery event object
  10011. * @param {object} oSettings DataTables settings object
  10012. * @param {object} json The saved state information
  10013. */
  10014. /**
  10015. * Processing event, fired when DataTables is doing some kind of processing (be it,
  10016. * sort, filter or anything else). Can be used to indicate to the end user that
  10017. * there is something happening, or that something has finished.
  10018. * @name DataTable#processing
  10019. * @event
  10020. * @param {event} e jQuery event object
  10021. * @param {object} oSettings DataTables settings object
  10022. * @param {boolean} bShow Flag for if DataTables is doing processing or not
  10023. */
  10024. /**
  10025. * Ajax (XHR) event, fired whenever an Ajax request is completed from a request to
  10026. * made to the server for new data (note that this trigger is called in fnServerData,
  10027. * if you override fnServerData and which to use this event, you need to trigger it in
  10028. * you success function).
  10029. * @name DataTable#xhr
  10030. * @event
  10031. * @param {event} e jQuery event object
  10032. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10033. * @param {object} json JSON returned from the server
  10034. */
  10035. /**
  10036. * Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing
  10037. * the bDestroy:true parameter in the initialisation object. This can be used to remove
  10038. * bound events, added DOM nodes, etc.
  10039. * @name DataTable#destroy
  10040. * @event
  10041. * @param {event} e jQuery event object
  10042. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10043. */
  10044. }));
  10045. }(window, document));