jquery.dataTables.js 360 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863
  1. /**
  2. * @summary DataTables
  3. * @description Paginate, search and sort HTML tables
  4. * @version 1.9.2
  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,_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*/
  24. (/** @lends <global> */function($, window, document, undefined) {
  25. /**
  26. * DataTables is a plug-in for the jQuery Javascript library. It is a
  27. * highly flexible tool, based upon the foundations of progressive
  28. * enhancement, which will add advanced interaction controls to any
  29. * HTML table. For a full list of features please refer to
  30. * <a href="http://datatables.net">DataTables.net</a>.
  31. *
  32. * Note that the <i>DataTable</i> object is not a global variable but is
  33. * aliased to <i>jQuery.fn.DataTable</i> and <i>jQuery.fn.dataTable</i> through which
  34. * it may be accessed.
  35. *
  36. * @class
  37. * @param {object} [oInit={}] Configuration object for DataTables. Options
  38. * are defined by {@link DataTable.defaults}
  39. * @requires jQuery 1.3+
  40. *
  41. * @example
  42. * // Basic initialisation
  43. * $(document).ready( function {
  44. * $('#example').dataTable();
  45. * } );
  46. *
  47. * @example
  48. * // Initialisation with configuration options - in this case, disable
  49. * // pagination and sorting.
  50. * $(document).ready( function {
  51. * $('#example').dataTable( {
  52. * "bPaginate": false,
  53. * "bSort": false
  54. * } );
  55. * } );
  56. */
  57. var DataTable = function( oInit )
  58. {
  59. /**
  60. * Add a column to the list used for the table with default values
  61. * @param {object} oSettings dataTables settings object
  62. * @param {node} nTh The th element for this column
  63. * @memberof DataTable#oApi
  64. */
  65. function _fnAddColumn( oSettings, nTh )
  66. {
  67. var oDefaults = DataTable.defaults.columns;
  68. var iCol = oSettings.aoColumns.length;
  69. var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
  70. "sSortingClass": oSettings.oClasses.sSortable,
  71. "sSortingClassJUI": oSettings.oClasses.sSortJUI,
  72. "nTh": nTh ? nTh : document.createElement('th'),
  73. "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',
  74. "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
  75. "mDataProp": oDefaults.mDataProp ? oDefaults.oDefaults : iCol
  76. } );
  77. oSettings.aoColumns.push( oCol );
  78. /* Add a column specific filter */
  79. if ( oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null )
  80. {
  81. oSettings.aoPreSearchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch );
  82. }
  83. else
  84. {
  85. var oPre = oSettings.aoPreSearchCols[ iCol ];
  86. /* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */
  87. if ( oPre.bRegex === undefined )
  88. {
  89. oPre.bRegex = true;
  90. }
  91. if ( oPre.bSmart === undefined )
  92. {
  93. oPre.bSmart = true;
  94. }
  95. if ( oPre.bCaseInsensitive === undefined )
  96. {
  97. oPre.bCaseInsensitive = true;
  98. }
  99. }
  100. /* Use the column options function to initialise classes etc */
  101. _fnColumnOptions( oSettings, iCol, null );
  102. }
  103. /**
  104. * Apply options for a column
  105. * @param {object} oSettings dataTables settings object
  106. * @param {int} iCol column index to consider
  107. * @param {object} oOptions object with sType, bVisible and bSearchable
  108. * @memberof DataTable#oApi
  109. */
  110. function _fnColumnOptions( oSettings, iCol, oOptions )
  111. {
  112. var oCol = oSettings.aoColumns[ iCol ];
  113. /* User specified column options */
  114. if ( oOptions !== undefined && oOptions !== null )
  115. {
  116. if ( oOptions.sType !== undefined )
  117. {
  118. oCol.sType = oOptions.sType;
  119. oCol._bAutoType = false;
  120. }
  121. $.extend( oCol, oOptions );
  122. _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
  123. /* iDataSort to be applied (backwards compatibility), but aDataSort will take
  124. * priority if defined
  125. */
  126. if ( oOptions.iDataSort !== undefined )
  127. {
  128. oCol.aDataSort = [ oOptions.iDataSort ];
  129. }
  130. _fnMap( oCol, oOptions, "aDataSort" );
  131. }
  132. /* Cache the data get and set functions for speed */
  133. oCol.fnGetData = _fnGetObjectDataFn( oCol.mDataProp );
  134. oCol.fnSetData = _fnSetObjectDataFn( oCol.mDataProp );
  135. /* Feature sorting overrides column specific when off */
  136. if ( !oSettings.oFeatures.bSort )
  137. {
  138. oCol.bSortable = false;
  139. }
  140. /* Check that the class assignment is correct for sorting */
  141. if ( !oCol.bSortable ||
  142. ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) )
  143. {
  144. oCol.sSortingClass = oSettings.oClasses.sSortableNone;
  145. oCol.sSortingClassJUI = "";
  146. }
  147. else if ( oCol.bSortable ||
  148. ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) )
  149. {
  150. oCol.sSortingClass = oSettings.oClasses.sSortable;
  151. oCol.sSortingClassJUI = oSettings.oClasses.sSortJUI;
  152. }
  153. else if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 )
  154. {
  155. oCol.sSortingClass = oSettings.oClasses.sSortableAsc;
  156. oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed;
  157. }
  158. else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 )
  159. {
  160. oCol.sSortingClass = oSettings.oClasses.sSortableDesc;
  161. oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed;
  162. }
  163. }
  164. /**
  165. * Adjust the table column widths for new data. Note: you would probably want to
  166. * do a redraw after calling this function!
  167. * @param {object} oSettings dataTables settings object
  168. * @memberof DataTable#oApi
  169. */
  170. function _fnAdjustColumnSizing ( oSettings )
  171. {
  172. /* Not interested in doing column width calculation if autowidth is disabled */
  173. if ( oSettings.oFeatures.bAutoWidth === false )
  174. {
  175. return false;
  176. }
  177. _fnCalculateColumnWidths( oSettings );
  178. for ( var i=0 , iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  179. {
  180. oSettings.aoColumns[i].nTh.style.width = oSettings.aoColumns[i].sWidth;
  181. }
  182. }
  183. /**
  184. * Covert the index of a visible column to the index in the data array (take account
  185. * of hidden columns)
  186. * @param {object} oSettings dataTables settings object
  187. * @param {int} iMatch Visible column index to lookup
  188. * @returns {int} i the data index
  189. * @memberof DataTable#oApi
  190. */
  191. function _fnVisibleToColumnIndex( oSettings, iMatch )
  192. {
  193. var iColumn = -1;
  194. for ( var i=0 ; i<oSettings.aoColumns.length ; i++ )
  195. {
  196. if ( oSettings.aoColumns[i].bVisible === true )
  197. {
  198. iColumn++;
  199. }
  200. if ( iColumn == iMatch )
  201. {
  202. return i;
  203. }
  204. }
  205. return null;
  206. }
  207. /**
  208. * Covert the index of an index in the data array and convert it to the visible
  209. * column index (take account of hidden columns)
  210. * @param {int} iMatch Column index to lookup
  211. * @param {object} oSettings dataTables settings object
  212. * @returns {int} i the data index
  213. * @memberof DataTable#oApi
  214. */
  215. function _fnColumnIndexToVisible( oSettings, iMatch )
  216. {
  217. var iVisible = -1;
  218. for ( var i=0 ; i<oSettings.aoColumns.length ; i++ )
  219. {
  220. if ( oSettings.aoColumns[i].bVisible === true )
  221. {
  222. iVisible++;
  223. }
  224. if ( i == iMatch )
  225. {
  226. return oSettings.aoColumns[i].bVisible === true ? iVisible : null;
  227. }
  228. }
  229. return null;
  230. }
  231. /**
  232. * Get the number of visible columns
  233. * @returns {int} i the number of visible columns
  234. * @param {object} oS dataTables settings object
  235. * @memberof DataTable#oApi
  236. */
  237. function _fnVisbleColumns( oS )
  238. {
  239. var iVis = 0;
  240. for ( var i=0 ; i<oS.aoColumns.length ; i++ )
  241. {
  242. if ( oS.aoColumns[i].bVisible === true )
  243. {
  244. iVis++;
  245. }
  246. }
  247. return iVis;
  248. }
  249. /**
  250. * Get the sort type based on an input string
  251. * @param {string} sData data we wish to know the type of
  252. * @returns {string} type (defaults to 'string' if no type can be detected)
  253. * @memberof DataTable#oApi
  254. */
  255. function _fnDetectType( sData )
  256. {
  257. var aTypes = DataTable.ext.aTypes;
  258. var iLen = aTypes.length;
  259. for ( var i=0 ; i<iLen ; i++ )
  260. {
  261. var sType = aTypes[i]( sData );
  262. if ( sType !== null )
  263. {
  264. return sType;
  265. }
  266. }
  267. return 'string';
  268. }
  269. /**
  270. * Figure out how to reorder a display list
  271. * @param {object} oSettings dataTables settings object
  272. * @returns array {int} aiReturn index list for reordering
  273. * @memberof DataTable#oApi
  274. */
  275. function _fnReOrderIndex ( oSettings, sColumns )
  276. {
  277. var aColumns = sColumns.split(',');
  278. var aiReturn = [];
  279. for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  280. {
  281. for ( var j=0 ; j<iLen ; j++ )
  282. {
  283. if ( oSettings.aoColumns[i].sName == aColumns[j] )
  284. {
  285. aiReturn.push( j );
  286. break;
  287. }
  288. }
  289. }
  290. return aiReturn;
  291. }
  292. /**
  293. * Get the column ordering that DataTables expects
  294. * @param {object} oSettings dataTables settings object
  295. * @returns {string} comma separated list of names
  296. * @memberof DataTable#oApi
  297. */
  298. function _fnColumnOrdering ( oSettings )
  299. {
  300. var sNames = '';
  301. for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  302. {
  303. sNames += oSettings.aoColumns[i].sName+',';
  304. }
  305. if ( sNames.length == iLen )
  306. {
  307. return "";
  308. }
  309. return sNames.slice(0, -1);
  310. }
  311. /**
  312. * Take the column definitions and static columns arrays and calculate how
  313. * they relate to column indexes. The callback function will then apply the
  314. * definition found for a column to a suitable configuration object.
  315. * @param {object} oSettings dataTables settings object
  316. * @param {array} aoColDefs The aoColumnDefs array that is to be applied
  317. * @param {array} aoCols The aoColumns array that defines columns individually
  318. * @param {function} fn Callback function - takes two parameters, the calculated
  319. * column index and the definition for that column.
  320. * @memberof DataTable#oApi
  321. */
  322. function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
  323. {
  324. var i, iLen, j, jLen, k, kLen;
  325. // Column definitions with aTargets
  326. if ( aoColDefs )
  327. {
  328. /* Loop over the definitions array - loop in reverse so first instance has priority */
  329. for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
  330. {
  331. /* Each definition can target multiple columns, as it is an array */
  332. var aTargets = aoColDefs[i].aTargets;
  333. if ( !$.isArray( aTargets ) )
  334. {
  335. _fnLog( oSettings, 1, 'aTargets must be an array of targets, not a '+(typeof aTargets) );
  336. }
  337. for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
  338. {
  339. if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
  340. {
  341. /* Add columns that we don't yet know about */
  342. while( oSettings.aoColumns.length <= aTargets[j] )
  343. {
  344. _fnAddColumn( oSettings );
  345. }
  346. /* Integer, basic index */
  347. fn( aTargets[j], aoColDefs[i] );
  348. }
  349. else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
  350. {
  351. /* Negative integer, right to left column counting */
  352. fn( oSettings.aoColumns.length+aTargets[j], aoColDefs[i] );
  353. }
  354. else if ( typeof aTargets[j] === 'string' )
  355. {
  356. /* Class name matching on TH element */
  357. for ( k=0, kLen=oSettings.aoColumns.length ; k<kLen ; k++ )
  358. {
  359. if ( aTargets[j] == "_all" ||
  360. $(oSettings.aoColumns[k].nTh).hasClass( aTargets[j] ) )
  361. {
  362. fn( k, aoColDefs[i] );
  363. }
  364. }
  365. }
  366. }
  367. }
  368. }
  369. // Statically defined columns array
  370. if ( aoCols )
  371. {
  372. for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
  373. {
  374. fn( i, aoCols[i] );
  375. }
  376. }
  377. }
  378. /**
  379. * Add a data array to the table, creating DOM node etc. This is the parallel to
  380. * _fnGatherData, but for adding rows from a Javascript source, rather than a
  381. * DOM source.
  382. * @param {object} oSettings dataTables settings object
  383. * @param {array} aData data array to be added
  384. * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
  385. * @memberof DataTable#oApi
  386. */
  387. function _fnAddData ( oSettings, aDataSupplied )
  388. {
  389. var oCol;
  390. /* Take an independent copy of the data source so we can bash it about as we wish */
  391. var aDataIn = ($.isArray(aDataSupplied)) ?
  392. aDataSupplied.slice() :
  393. $.extend( true, {}, aDataSupplied );
  394. /* Create the object for storing information about this new row */
  395. var iRow = oSettings.aoData.length;
  396. var oData = $.extend( true, {}, DataTable.models.oRow );
  397. oData._aData = aDataIn;
  398. oSettings.aoData.push( oData );
  399. /* Create the cells */
  400. var nTd, sThisType;
  401. for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  402. {
  403. oCol = oSettings.aoColumns[i];
  404. /* Use rendered data for filtering/sorting */
  405. if ( typeof oCol.fnRender === 'function' && oCol.bUseRendered && oCol.mDataProp !== null )
  406. {
  407. _fnSetCellData( oSettings, iRow, i, _fnRender(oSettings, iRow, i) );
  408. }
  409. else
  410. {
  411. _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
  412. }
  413. /* See if we should auto-detect the column type */
  414. if ( oCol._bAutoType && oCol.sType != 'string' )
  415. {
  416. /* Attempt to auto detect the type - same as _fnGatherData() */
  417. var sVarType = _fnGetCellData( oSettings, iRow, i, 'type' );
  418. if ( sVarType !== null && sVarType !== '' )
  419. {
  420. sThisType = _fnDetectType( sVarType );
  421. if ( oCol.sType === null )
  422. {
  423. oCol.sType = sThisType;
  424. }
  425. else if ( oCol.sType != sThisType && oCol.sType != "html" )
  426. {
  427. /* String is always the 'fallback' option */
  428. oCol.sType = 'string';
  429. }
  430. }
  431. }
  432. }
  433. /* Add to the display array */
  434. oSettings.aiDisplayMaster.push( iRow );
  435. /* Create the DOM imformation */
  436. if ( !oSettings.oFeatures.bDeferRender )
  437. {
  438. _fnCreateTr( oSettings, iRow );
  439. }
  440. return iRow;
  441. }
  442. /**
  443. * Read in the data from the target table from the DOM
  444. * @param {object} oSettings dataTables settings object
  445. * @memberof DataTable#oApi
  446. */
  447. function _fnGatherData( oSettings )
  448. {
  449. var iLoop, i, iLen, j, jLen, jInner,
  450. nTds, nTrs, nTd, aLocalData, iThisIndex,
  451. iRow, iRows, iColumn, iColumns, sNodeName,
  452. oCol, oData;
  453. /*
  454. * Process by row first
  455. * Add the data object for the whole table - storing the tr node. Note - no point in getting
  456. * DOM based data if we are going to go and replace it with Ajax source data.
  457. */
  458. if ( oSettings.bDeferLoading || oSettings.sAjaxSource === null )
  459. {
  460. nTrs = oSettings.nTBody.childNodes;
  461. for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  462. {
  463. if ( nTrs[i].nodeName.toUpperCase() == "TR" )
  464. {
  465. iThisIndex = oSettings.aoData.length;
  466. nTrs[i]._DT_RowIndex = iThisIndex;
  467. oSettings.aoData.push( $.extend( true, {}, DataTable.models.oRow, {
  468. "nTr": nTrs[i]
  469. } ) );
  470. oSettings.aiDisplayMaster.push( iThisIndex );
  471. nTds = nTrs[i].childNodes;
  472. jInner = 0;
  473. for ( j=0, jLen=nTds.length ; j<jLen ; j++ )
  474. {
  475. sNodeName = nTds[j].nodeName.toUpperCase();
  476. if ( sNodeName == "TD" || sNodeName == "TH" )
  477. {
  478. _fnSetCellData( oSettings, iThisIndex, jInner, $.trim(nTds[j].innerHTML) );
  479. jInner++;
  480. }
  481. }
  482. }
  483. }
  484. }
  485. /* Gather in the TD elements of the Table - note that this is basically the same as
  486. * fnGetTdNodes, but that function takes account of hidden columns, which we haven't yet
  487. * setup!
  488. */
  489. nTrs = _fnGetTrNodes( oSettings );
  490. nTds = [];
  491. for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  492. {
  493. for ( j=0, jLen=nTrs[i].childNodes.length ; j<jLen ; j++ )
  494. {
  495. nTd = nTrs[i].childNodes[j];
  496. sNodeName = nTd.nodeName.toUpperCase();
  497. if ( sNodeName == "TD" || sNodeName == "TH" )
  498. {
  499. nTds.push( nTd );
  500. }
  501. }
  502. }
  503. /* Now process by column */
  504. for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ )
  505. {
  506. oCol = oSettings.aoColumns[iColumn];
  507. /* Get the title of the column - unless there is a user set one */
  508. if ( oCol.sTitle === null )
  509. {
  510. oCol.sTitle = oCol.nTh.innerHTML;
  511. }
  512. var
  513. bAutoType = oCol._bAutoType,
  514. bRender = typeof oCol.fnRender === 'function',
  515. bClass = oCol.sClass !== null,
  516. bVisible = oCol.bVisible,
  517. nCell, sThisType, sRendered, sValType;
  518. /* A single loop to rule them all (and be more efficient) */
  519. if ( bAutoType || bRender || bClass || !bVisible )
  520. {
  521. for ( iRow=0, iRows=oSettings.aoData.length ; iRow<iRows ; iRow++ )
  522. {
  523. oData = oSettings.aoData[iRow];
  524. nCell = nTds[ (iRow*iColumns) + iColumn ];
  525. /* Type detection */
  526. if ( bAutoType && oCol.sType != 'string' )
  527. {
  528. sValType = _fnGetCellData( oSettings, iRow, iColumn, 'type' );
  529. if ( sValType !== '' )
  530. {
  531. sThisType = _fnDetectType( sValType );
  532. if ( oCol.sType === null )
  533. {
  534. oCol.sType = sThisType;
  535. }
  536. else if ( oCol.sType != sThisType &&
  537. oCol.sType != "html" )
  538. {
  539. /* String is always the 'fallback' option */
  540. oCol.sType = 'string';
  541. }
  542. }
  543. }
  544. if ( typeof oCol.mDataProp === 'function' )
  545. {
  546. nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' );
  547. }
  548. /* Rendering */
  549. if ( bRender )
  550. {
  551. sRendered = _fnRender( oSettings, iRow, iColumn );
  552. nCell.innerHTML = sRendered;
  553. if ( oCol.bUseRendered )
  554. {
  555. /* Use the rendered data for filtering/sorting */
  556. _fnSetCellData( oSettings, iRow, iColumn, sRendered );
  557. }
  558. }
  559. /* Classes */
  560. if ( bClass )
  561. {
  562. nCell.className += ' '+oCol.sClass;
  563. }
  564. /* Column visability */
  565. if ( !bVisible )
  566. {
  567. oData._anHidden[iColumn] = nCell;
  568. nCell.parentNode.removeChild( nCell );
  569. }
  570. else
  571. {
  572. oData._anHidden[iColumn] = null;
  573. }
  574. if ( oCol.fnCreatedCell )
  575. {
  576. oCol.fnCreatedCell.call( oSettings.oInstance,
  577. nCell, _fnGetCellData( oSettings, iRow, iColumn, 'display' ), oData._aData, iRow, iColumn
  578. );
  579. }
  580. }
  581. }
  582. }
  583. /* Row created callbacks */
  584. if ( oSettings.aoRowCreatedCallback.length !== 0 )
  585. {
  586. for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
  587. {
  588. oData = oSettings.aoData[i];
  589. _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, i] );
  590. }
  591. }
  592. }
  593. /**
  594. * Take a TR element and convert it to an index in aoData
  595. * @param {object} oSettings dataTables settings object
  596. * @param {node} n the TR element to find
  597. * @returns {int} index if the node is found, null if not
  598. * @memberof DataTable#oApi
  599. */
  600. function _fnNodeToDataIndex( oSettings, n )
  601. {
  602. return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
  603. }
  604. /**
  605. * Take a TD element and convert it into a column data index (not the visible index)
  606. * @param {object} oSettings dataTables settings object
  607. * @param {int} iRow The row number the TD/TH can be found in
  608. * @param {node} n The TD/TH element to find
  609. * @returns {int} index if the node is found, -1 if not
  610. * @memberof DataTable#oApi
  611. */
  612. function _fnNodeToColumnIndex( oSettings, iRow, n )
  613. {
  614. var anCells = _fnGetTdNodes( oSettings, iRow );
  615. for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  616. {
  617. if ( anCells[i] === n )
  618. {
  619. return i;
  620. }
  621. }
  622. return -1;
  623. }
  624. /**
  625. * Get an array of data for a given row from the internal data cache
  626. * @param {object} oSettings dataTables settings object
  627. * @param {int} iRow aoData row id
  628. * @param {string} sSpecific data get type ('type' 'filter' 'sort')
  629. * @returns {array} Data array
  630. * @memberof DataTable#oApi
  631. */
  632. function _fnGetRowData( oSettings, iRow, sSpecific )
  633. {
  634. var out = [];
  635. for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  636. {
  637. out.push( _fnGetCellData( oSettings, iRow, i, sSpecific ) );
  638. }
  639. return out;
  640. }
  641. /**
  642. * Get the data for a given cell from the internal cache, taking into account data mapping
  643. * @param {object} oSettings dataTables settings object
  644. * @param {int} iRow aoData row id
  645. * @param {int} iCol Column index
  646. * @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort')
  647. * @returns {*} Cell data
  648. * @memberof DataTable#oApi
  649. */
  650. function _fnGetCellData( oSettings, iRow, iCol, sSpecific )
  651. {
  652. var sData;
  653. var oCol = oSettings.aoColumns[iCol];
  654. var oData = oSettings.aoData[iRow]._aData;
  655. if ( (sData=oCol.fnGetData( oData, sSpecific )) === undefined )
  656. {
  657. if ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null )
  658. {
  659. _fnLog( oSettings, 0, "Requested unknown parameter "+
  660. (typeof oCol.mDataProp=='function' ? '{mDataprop function}' : "'"+oCol.mDataProp+"'")+
  661. " from the data source for row "+iRow );
  662. oSettings.iDrawError = oSettings.iDraw;
  663. }
  664. return oCol.sDefaultContent;
  665. }
  666. /* When the data source is null, we can use default column data */
  667. if ( sData === null && oCol.sDefaultContent !== null )
  668. {
  669. sData = oCol.sDefaultContent;
  670. }
  671. else if ( typeof sData === 'function' )
  672. {
  673. /* If the data source is a function, then we run it and use the return */
  674. return sData();
  675. }
  676. if ( sSpecific == 'display' && sData === null )
  677. {
  678. return '';
  679. }
  680. return sData;
  681. }
  682. /**
  683. * Set the value for a specific cell, into the internal data cache
  684. * @param {object} oSettings dataTables settings object
  685. * @param {int} iRow aoData row id
  686. * @param {int} iCol Column index
  687. * @param {*} val Value to set
  688. * @memberof DataTable#oApi
  689. */
  690. function _fnSetCellData( oSettings, iRow, iCol, val )
  691. {
  692. var oCol = oSettings.aoColumns[iCol];
  693. var oData = oSettings.aoData[iRow]._aData;
  694. oCol.fnSetData( oData, val );
  695. }
  696. /**
  697. * Return a function that can be used to get data from a source object, taking
  698. * into account the ability to use nested objects as a source
  699. * @param {string|int|function} mSource The data source for the object
  700. * @returns {function} Data get function
  701. * @memberof DataTable#oApi
  702. */
  703. function _fnGetObjectDataFn( mSource )
  704. {
  705. if ( mSource === null )
  706. {
  707. /* Give an empty string for rendering / sorting etc */
  708. return function (data, type) {
  709. return null;
  710. };
  711. }
  712. else if ( typeof mSource === 'function' )
  713. {
  714. return function (data, type) {
  715. return mSource( data, type );
  716. };
  717. }
  718. else if ( typeof mSource === 'string' && mSource.indexOf('.') != -1 )
  719. {
  720. /* If there is a . in the source string then the data source is in a
  721. * nested object so we loop over the data for each level to get the next
  722. * level down. On each loop we test for undefined, and if found immediatly
  723. * return. This allows entire objects to be missing and sDefaultContent to
  724. * be used if defined, rather than throwing an error
  725. */
  726. var a = mSource.split('.');
  727. return function (data, type) {
  728. for ( var i=0, iLen=a.length ; i<iLen ; i++ )
  729. {
  730. data = data[ a[i] ];
  731. if ( data === undefined )
  732. {
  733. return undefined;
  734. }
  735. }
  736. return data;
  737. };
  738. }
  739. else
  740. {
  741. /* Array or flat object mapping */
  742. return function (data, type) {
  743. return data[mSource];
  744. };
  745. }
  746. }
  747. /**
  748. * Return a function that can be used to set data from a source object, taking
  749. * into account the ability to use nested objects as a source
  750. * @param {string|int|function} mSource The data source for the object
  751. * @returns {function} Data set function
  752. * @memberof DataTable#oApi
  753. */
  754. function _fnSetObjectDataFn( mSource )
  755. {
  756. if ( mSource === null )
  757. {
  758. /* Nothing to do when the data source is null */
  759. return function (data, val) {};
  760. }
  761. else if ( typeof mSource === 'function' )
  762. {
  763. return function (data, val) {
  764. mSource( data, 'set', val );
  765. };
  766. }
  767. else if ( typeof mSource === 'string' && mSource.indexOf('.') != -1 )
  768. {
  769. /* Like the get, we need to get data from a nested object. */
  770. var a = mSource.split('.');
  771. return function (data, val) {
  772. for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
  773. {
  774. // If the nested object doesn't currently exist - since we are
  775. // trying to set the value - create it
  776. if ( data[ a[i] ] === undefined )
  777. {
  778. data[ a[i] ] = {};
  779. }
  780. data = data[ a[i] ];
  781. }
  782. data[ a[a.length-1] ] = val;
  783. };
  784. }
  785. else
  786. {
  787. /* Array or flat object mapping */
  788. return function (data, val) {
  789. data[mSource] = val;
  790. };
  791. }
  792. }
  793. /**
  794. * Return an array with the full table data
  795. * @param {object} oSettings dataTables settings object
  796. * @returns array {array} aData Master data array
  797. * @memberof DataTable#oApi
  798. */
  799. function _fnGetDataMaster ( oSettings )
  800. {
  801. var aData = [];
  802. var iLen = oSettings.aoData.length;
  803. for ( var i=0 ; i<iLen; i++ )
  804. {
  805. aData.push( oSettings.aoData[i]._aData );
  806. }
  807. return aData;
  808. }
  809. /**
  810. * Nuke the table
  811. * @param {object} oSettings dataTables settings object
  812. * @memberof DataTable#oApi
  813. */
  814. function _fnClearTable( oSettings )
  815. {
  816. oSettings.aoData.splice( 0, oSettings.aoData.length );
  817. oSettings.aiDisplayMaster.splice( 0, oSettings.aiDisplayMaster.length );
  818. oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length );
  819. _fnCalculateEnd( oSettings );
  820. }
  821. /**
  822. * Take an array of integers (index array) and remove a target integer (value - not
  823. * the key!)
  824. * @param {array} a Index array to target
  825. * @param {int} iTarget value to find
  826. * @memberof DataTable#oApi
  827. */
  828. function _fnDeleteIndex( a, iTarget )
  829. {
  830. var iTargetIndex = -1;
  831. for ( var i=0, iLen=a.length ; i<iLen ; i++ )
  832. {
  833. if ( a[i] == iTarget )
  834. {
  835. iTargetIndex = i;
  836. }
  837. else if ( a[i] > iTarget )
  838. {
  839. a[i]--;
  840. }
  841. }
  842. if ( iTargetIndex != -1 )
  843. {
  844. a.splice( iTargetIndex, 1 );
  845. }
  846. }
  847. /**
  848. * Call the developer defined fnRender function for a given cell (row/column) with
  849. * the required parameters and return the result.
  850. * @param {object} oSettings dataTables settings object
  851. * @param {int} iRow aoData index for the row
  852. * @param {int} iCol aoColumns index for the column
  853. * @returns {*} Return of the developer's fnRender function
  854. * @memberof DataTable#oApi
  855. */
  856. function _fnRender( oSettings, iRow, iCol )
  857. {
  858. var oCol = oSettings.aoColumns[iCol];
  859. return oCol.fnRender( {
  860. "iDataRow": iRow,
  861. "iDataColumn": iCol,
  862. "oSettings": oSettings,
  863. "aData": oSettings.aoData[iRow]._aData,
  864. "mDataProp": oCol.mDataProp
  865. }, _fnGetCellData(oSettings, iRow, iCol, 'display') );
  866. }
  867. /**
  868. * Create a new TR element (and it's TD children) for a row
  869. * @param {object} oSettings dataTables settings object
  870. * @param {int} iRow Row to consider
  871. * @memberof DataTable#oApi
  872. */
  873. function _fnCreateTr ( oSettings, iRow )
  874. {
  875. var oData = oSettings.aoData[iRow];
  876. var nTd;
  877. if ( oData.nTr === null )
  878. {
  879. oData.nTr = document.createElement('tr');
  880. /* Use a private property on the node to allow reserve mapping from the node
  881. * to the aoData array for fast look up
  882. */
  883. oData.nTr._DT_RowIndex = iRow;
  884. /* Special parameters can be given by the data source to be used on the row */
  885. if ( oData._aData.DT_RowId )
  886. {
  887. oData.nTr.id = oData._aData.DT_RowId;
  888. }
  889. if ( oData._aData.DT_RowClass )
  890. {
  891. $(oData.nTr).addClass( oData._aData.DT_RowClass );
  892. }
  893. /* Process each column */
  894. for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  895. {
  896. var oCol = oSettings.aoColumns[i];
  897. nTd = document.createElement( oCol.sCellType );
  898. /* Render if needed - if bUseRendered is true then we already have the rendered
  899. * value in the data source - so can just use that
  900. */
  901. nTd.innerHTML = (typeof oCol.fnRender === 'function' && (!oCol.bUseRendered || oCol.mDataProp === null)) ?
  902. _fnRender( oSettings, iRow, i ) :
  903. _fnGetCellData( oSettings, iRow, i, 'display' );
  904. /* Add user defined class */
  905. if ( oCol.sClass !== null )
  906. {
  907. nTd.className = oCol.sClass;
  908. }
  909. if ( oCol.bVisible )
  910. {
  911. oData.nTr.appendChild( nTd );
  912. oData._anHidden[i] = null;
  913. }
  914. else
  915. {
  916. oData._anHidden[i] = nTd;
  917. }
  918. if ( oCol.fnCreatedCell )
  919. {
  920. oCol.fnCreatedCell.call( oSettings.oInstance,
  921. nTd, _fnGetCellData( oSettings, iRow, i, 'display' ), oData._aData, iRow, i
  922. );
  923. }
  924. }
  925. _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, iRow] );
  926. }
  927. }
  928. /**
  929. * Create the HTML header for the table
  930. * @param {object} oSettings dataTables settings object
  931. * @memberof DataTable#oApi
  932. */
  933. function _fnBuildHead( oSettings )
  934. {
  935. var i, nTh, iLen, j, jLen;
  936. var iThs = oSettings.nTHead.getElementsByTagName('th').length;
  937. var iCorrector = 0;
  938. var jqChildren;
  939. /* If there is a header in place - then use it - otherwise it's going to get nuked... */
  940. if ( iThs !== 0 )
  941. {
  942. /* We've got a thead from the DOM, so remove hidden columns and apply width to vis cols */
  943. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  944. {
  945. nTh = oSettings.aoColumns[i].nTh;
  946. nTh.setAttribute('role', 'columnheader');
  947. if ( oSettings.aoColumns[i].bSortable )
  948. {
  949. nTh.setAttribute('tabindex', oSettings.iTabIndex);
  950. nTh.setAttribute('aria-controls', oSettings.sTableId);
  951. }
  952. if ( oSettings.aoColumns[i].sClass !== null )
  953. {
  954. $(nTh).addClass( oSettings.aoColumns[i].sClass );
  955. }
  956. /* Set the title of the column if it is user defined (not what was auto detected) */
  957. if ( oSettings.aoColumns[i].sTitle != nTh.innerHTML )
  958. {
  959. nTh.innerHTML = oSettings.aoColumns[i].sTitle;
  960. }
  961. }
  962. }
  963. else
  964. {
  965. /* We don't have a header in the DOM - so we are going to have to create one */
  966. var nTr = document.createElement( "tr" );
  967. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  968. {
  969. nTh = oSettings.aoColumns[i].nTh;
  970. nTh.innerHTML = oSettings.aoColumns[i].sTitle;
  971. nTh.setAttribute('tabindex', '0');
  972. if ( oSettings.aoColumns[i].sClass !== null )
  973. {
  974. $(nTh).addClass( oSettings.aoColumns[i].sClass );
  975. }
  976. nTr.appendChild( nTh );
  977. }
  978. $(oSettings.nTHead).html( '' )[0].appendChild( nTr );
  979. _fnDetectHeader( oSettings.aoHeader, oSettings.nTHead );
  980. }
  981. /* ARIA role for the rows */
  982. $(oSettings.nTHead).children('tr').attr('role', 'row');
  983. /* Add the extra markup needed by jQuery UI's themes */
  984. if ( oSettings.bJUI )
  985. {
  986. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  987. {
  988. nTh = oSettings.aoColumns[i].nTh;
  989. var nDiv = document.createElement('div');
  990. nDiv.className = oSettings.oClasses.sSortJUIWrapper;
  991. $(nTh).contents().appendTo(nDiv);
  992. var nSpan = document.createElement('span');
  993. nSpan.className = oSettings.oClasses.sSortIcon;
  994. nDiv.appendChild( nSpan );
  995. nTh.appendChild( nDiv );
  996. }
  997. }
  998. if ( oSettings.oFeatures.bSort )
  999. {
  1000. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  1001. {
  1002. if ( oSettings.aoColumns[i].bSortable !== false )
  1003. {
  1004. _fnSortAttachListener( oSettings, oSettings.aoColumns[i].nTh, i );
  1005. }
  1006. else
  1007. {
  1008. $(oSettings.aoColumns[i].nTh).addClass( oSettings.oClasses.sSortableNone );
  1009. }
  1010. }
  1011. }
  1012. /* Deal with the footer - add classes if required */
  1013. if ( oSettings.oClasses.sFooterTH !== "" )
  1014. {
  1015. $(oSettings.nTFoot).children('tr').children('th').addClass( oSettings.oClasses.sFooterTH );
  1016. }
  1017. /* Cache the footer elements */
  1018. if ( oSettings.nTFoot !== null )
  1019. {
  1020. var anCells = _fnGetUniqueThs( oSettings, null, oSettings.aoFooter );
  1021. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  1022. {
  1023. if ( anCells[i] )
  1024. {
  1025. oSettings.aoColumns[i].nTf = anCells[i];
  1026. if ( oSettings.aoColumns[i].sClass )
  1027. {
  1028. $(anCells[i]).addClass( oSettings.aoColumns[i].sClass );
  1029. }
  1030. }
  1031. }
  1032. }
  1033. }
  1034. /**
  1035. * Draw the header (or footer) element based on the column visibility states. The
  1036. * methodology here is to use the layout array from _fnDetectHeader, modified for
  1037. * the instantaneous column visibility, to construct the new layout. The grid is
  1038. * traversed over cell at a time in a rows x columns grid fashion, although each
  1039. * cell insert can cover multiple elements in the grid - which is tracks using the
  1040. * aApplied array. Cell inserts in the grid will only occur where there isn't
  1041. * already a cell in that position.
  1042. * @param {object} oSettings dataTables settings object
  1043. * @param array {objects} aoSource Layout array from _fnDetectHeader
  1044. * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
  1045. * @memberof DataTable#oApi
  1046. */
  1047. function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
  1048. {
  1049. var i, iLen, j, jLen, k, kLen, n, nLocalTr;
  1050. var aoLocal = [];
  1051. var aApplied = [];
  1052. var iColumns = oSettings.aoColumns.length;
  1053. var iRowspan, iColspan;
  1054. if ( bIncludeHidden === undefined )
  1055. {
  1056. bIncludeHidden = false;
  1057. }
  1058. /* Make a copy of the master layout array, but without the visible columns in it */
  1059. for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
  1060. {
  1061. aoLocal[i] = aoSource[i].slice();
  1062. aoLocal[i].nTr = aoSource[i].nTr;
  1063. /* Remove any columns which are currently hidden */
  1064. for ( j=iColumns-1 ; j>=0 ; j-- )
  1065. {
  1066. if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
  1067. {
  1068. aoLocal[i].splice( j, 1 );
  1069. }
  1070. }
  1071. /* Prep the applied array - it needs an element for each row */
  1072. aApplied.push( [] );
  1073. }
  1074. for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
  1075. {
  1076. nLocalTr = aoLocal[i].nTr;
  1077. /* All cells are going to be replaced, so empty out the row */
  1078. if ( nLocalTr )
  1079. {
  1080. while( (n = nLocalTr.firstChild) )
  1081. {
  1082. nLocalTr.removeChild( n );
  1083. }
  1084. }
  1085. for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
  1086. {
  1087. iRowspan = 1;
  1088. iColspan = 1;
  1089. /* Check to see if there is already a cell (row/colspan) covering our target
  1090. * insert point. If there is, then there is nothing to do.
  1091. */
  1092. if ( aApplied[i][j] === undefined )
  1093. {
  1094. nLocalTr.appendChild( aoLocal[i][j].cell );
  1095. aApplied[i][j] = 1;
  1096. /* Expand the cell to cover as many rows as needed */
  1097. while ( aoLocal[i+iRowspan] !== undefined &&
  1098. aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
  1099. {
  1100. aApplied[i+iRowspan][j] = 1;
  1101. iRowspan++;
  1102. }
  1103. /* Expand the cell to cover as many columns as needed */
  1104. while ( aoLocal[i][j+iColspan] !== undefined &&
  1105. aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
  1106. {
  1107. /* Must update the applied array over the rows for the columns */
  1108. for ( k=0 ; k<iRowspan ; k++ )
  1109. {
  1110. aApplied[i+k][j+iColspan] = 1;
  1111. }
  1112. iColspan++;
  1113. }
  1114. /* Do the actual expansion in the DOM */
  1115. aoLocal[i][j].cell.rowSpan = iRowspan;
  1116. aoLocal[i][j].cell.colSpan = iColspan;
  1117. }
  1118. }
  1119. }
  1120. }
  1121. /**
  1122. * Insert the required TR nodes into the table for display
  1123. * @param {object} oSettings dataTables settings object
  1124. * @memberof DataTable#oApi
  1125. */
  1126. function _fnDraw( oSettings )
  1127. {
  1128. /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
  1129. var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
  1130. if ( $.inArray( false, aPreDraw ) !== -1 )
  1131. {
  1132. _fnProcessingDisplay( oSettings, false );
  1133. return;
  1134. }
  1135. var i, iLen, n;
  1136. var anRows = [];
  1137. var iRowCount = 0;
  1138. var iStripes = oSettings.asStripeClasses.length;
  1139. var iOpenRows = oSettings.aoOpenRows.length;
  1140. oSettings.bDrawing = true;
  1141. /* Check and see if we have an initial draw position from state saving */
  1142. if ( oSettings.iInitDisplayStart !== undefined && oSettings.iInitDisplayStart != -1 )
  1143. {
  1144. if ( oSettings.oFeatures.bServerSide )
  1145. {
  1146. oSettings._iDisplayStart = oSettings.iInitDisplayStart;
  1147. }
  1148. else
  1149. {
  1150. oSettings._iDisplayStart = (oSettings.iInitDisplayStart >= oSettings.fnRecordsDisplay()) ?
  1151. 0 : oSettings.iInitDisplayStart;
  1152. }
  1153. oSettings.iInitDisplayStart = -1;
  1154. _fnCalculateEnd( oSettings );
  1155. }
  1156. /* Server-side processing draw intercept */
  1157. if ( oSettings.bDeferLoading )
  1158. {
  1159. oSettings.bDeferLoading = false;
  1160. oSettings.iDraw++;
  1161. }
  1162. else if ( !oSettings.oFeatures.bServerSide )
  1163. {
  1164. oSettings.iDraw++;
  1165. }
  1166. else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
  1167. {
  1168. return;
  1169. }
  1170. if ( oSettings.aiDisplay.length !== 0 )
  1171. {
  1172. var iStart = oSettings._iDisplayStart;
  1173. var iEnd = oSettings._iDisplayEnd;
  1174. if ( oSettings.oFeatures.bServerSide )
  1175. {
  1176. iStart = 0;
  1177. iEnd = oSettings.aoData.length;
  1178. }
  1179. for ( var j=iStart ; j<iEnd ; j++ )
  1180. {
  1181. var aoData = oSettings.aoData[ oSettings.aiDisplay[j] ];
  1182. if ( aoData.nTr === null )
  1183. {
  1184. _fnCreateTr( oSettings, oSettings.aiDisplay[j] );
  1185. }
  1186. var nRow = aoData.nTr;
  1187. /* Remove the old striping classes and then add the new one */
  1188. if ( iStripes !== 0 )
  1189. {
  1190. var sStripe = oSettings.asStripeClasses[ iRowCount % iStripes ];
  1191. if ( aoData._sRowStripe != sStripe )
  1192. {
  1193. $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
  1194. aoData._sRowStripe = sStripe;
  1195. }
  1196. }
  1197. /* Row callback functions - might want to manipule the row */
  1198. _fnCallbackFire( oSettings, 'aoRowCallback', null,
  1199. [nRow, oSettings.aoData[ oSettings.aiDisplay[j] ]._aData, iRowCount, j] );
  1200. anRows.push( nRow );
  1201. iRowCount++;
  1202. /* If there is an open row - and it is attached to this parent - attach it on redraw */
  1203. if ( iOpenRows !== 0 )
  1204. {
  1205. for ( var k=0 ; k<iOpenRows ; k++ )
  1206. {
  1207. if ( nRow == oSettings.aoOpenRows[k].nParent )
  1208. {
  1209. anRows.push( oSettings.aoOpenRows[k].nTr );
  1210. break;
  1211. }
  1212. }
  1213. }
  1214. }
  1215. }
  1216. else
  1217. {
  1218. /* Table is empty - create a row with an empty message in it */
  1219. anRows[ 0 ] = document.createElement( 'tr' );
  1220. if ( oSettings.asStripeClasses[0] )
  1221. {
  1222. anRows[ 0 ].className = oSettings.asStripeClasses[0];
  1223. }
  1224. var oLang = oSettings.oLanguage;
  1225. var sZero = oLang.sZeroRecords;
  1226. if ( oSettings.iDraw == 1 && oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )
  1227. {
  1228. sZero = oLang.sLoadingRecords;
  1229. }
  1230. else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
  1231. {
  1232. sZero = oLang.sEmptyTable;
  1233. }
  1234. var nTd = document.createElement( 'td' );
  1235. nTd.setAttribute( 'valign', "top" );
  1236. nTd.colSpan = _fnVisbleColumns( oSettings );
  1237. nTd.className = oSettings.oClasses.sRowEmpty;
  1238. nTd.innerHTML = _fnInfoMacros( oSettings, sZero );
  1239. anRows[ iRowCount ].appendChild( nTd );
  1240. }
  1241. /* Header and footer callbacks */
  1242. _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
  1243. _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] );
  1244. _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
  1245. _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] );
  1246. /*
  1247. * Need to remove any old row from the display - note we can't just empty the tbody using
  1248. * $().html('') since this will unbind the jQuery event handlers (even although the node
  1249. * still exists!) - equally we can't use innerHTML, since IE throws an exception.
  1250. */
  1251. var
  1252. nAddFrag = document.createDocumentFragment(),
  1253. nRemoveFrag = document.createDocumentFragment(),
  1254. nBodyPar, nTrs;
  1255. if ( oSettings.nTBody )
  1256. {
  1257. nBodyPar = oSettings.nTBody.parentNode;
  1258. nRemoveFrag.appendChild( oSettings.nTBody );
  1259. /* When doing infinite scrolling, only remove child rows when sorting, filtering or start
  1260. * up. When not infinite scroll, always do it.
  1261. */
  1262. if ( !oSettings.oScroll.bInfinite || !oSettings._bInitComplete ||
  1263. oSettings.bSorted || oSettings.bFiltered )
  1264. {
  1265. while( (n = oSettings.nTBody.firstChild) )
  1266. {
  1267. oSettings.nTBody.removeChild( n );
  1268. }
  1269. }
  1270. /* Put the draw table into the dom */
  1271. for ( i=0, iLen=anRows.length ; i<iLen ; i++ )
  1272. {
  1273. nAddFrag.appendChild( anRows[i] );
  1274. }
  1275. oSettings.nTBody.appendChild( nAddFrag );
  1276. if ( nBodyPar !== null )
  1277. {
  1278. nBodyPar.appendChild( oSettings.nTBody );
  1279. }
  1280. }
  1281. /* Call all required callback functions for the end of a draw */
  1282. _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
  1283. /* Draw is complete, sorting and filtering must be as well */
  1284. oSettings.bSorted = false;
  1285. oSettings.bFiltered = false;
  1286. oSettings.bDrawing = false;
  1287. if ( oSettings.oFeatures.bServerSide )
  1288. {
  1289. _fnProcessingDisplay( oSettings, false );
  1290. if ( !oSettings._bInitComplete )
  1291. {
  1292. _fnInitComplete( oSettings );
  1293. }
  1294. }
  1295. }
  1296. /**
  1297. * Redraw the table - taking account of the various features which are enabled
  1298. * @param {object} oSettings dataTables settings object
  1299. * @memberof DataTable#oApi
  1300. */
  1301. function _fnReDraw( oSettings )
  1302. {
  1303. if ( oSettings.oFeatures.bSort )
  1304. {
  1305. /* Sorting will refilter and draw for us */
  1306. _fnSort( oSettings, oSettings.oPreviousSearch );
  1307. }
  1308. else if ( oSettings.oFeatures.bFilter )
  1309. {
  1310. /* Filtering will redraw for us */
  1311. _fnFilterComplete( oSettings, oSettings.oPreviousSearch );
  1312. }
  1313. else
  1314. {
  1315. _fnCalculateEnd( oSettings );
  1316. _fnDraw( oSettings );
  1317. }
  1318. }
  1319. /**
  1320. * Add the options to the page HTML for the table
  1321. * @param {object} oSettings dataTables settings object
  1322. * @memberof DataTable#oApi
  1323. */
  1324. function _fnAddOptionsHtml ( oSettings )
  1325. {
  1326. /*
  1327. * Create a temporary, empty, div which we can later on replace with what we have generated
  1328. * we do it this way to rendering the 'options' html offline - speed :-)
  1329. */
  1330. var nHolding = $('<div></div>')[0];
  1331. oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable );
  1332. /*
  1333. * All DataTables are wrapped in a div
  1334. */
  1335. oSettings.nTableWrapper = $('<div id="'+oSettings.sTableId+'_wrapper" class="'+oSettings.oClasses.sWrapper+'" role="grid"></div>')[0];
  1336. oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
  1337. /* Track where we want to insert the option */
  1338. var nInsertNode = oSettings.nTableWrapper;
  1339. /* Loop over the user set positioning and place the elements as needed */
  1340. var aDom = oSettings.sDom.split('');
  1341. var nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j;
  1342. for ( var i=0 ; i<aDom.length ; i++ )
  1343. {
  1344. iPushFeature = 0;
  1345. cOption = aDom[i];
  1346. if ( cOption == '<' )
  1347. {
  1348. /* New container div */
  1349. nNewNode = $('<div></div>')[0];
  1350. /* Check to see if we should append an id and/or a class name to the container */
  1351. cNext = aDom[i+1];
  1352. if ( cNext == "'" || cNext == '"' )
  1353. {
  1354. sAttr = "";
  1355. j = 2;
  1356. while ( aDom[i+j] != cNext )
  1357. {
  1358. sAttr += aDom[i+j];
  1359. j++;
  1360. }
  1361. /* Replace jQuery UI constants */
  1362. if ( sAttr == "H" )
  1363. {
  1364. sAttr = oSettings.oClasses.sJUIHeader;
  1365. }
  1366. else if ( sAttr == "F" )
  1367. {
  1368. sAttr = oSettings.oClasses.sJUIFooter;
  1369. }
  1370. /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
  1371. * breaks the string into parts and applies them as needed
  1372. */
  1373. if ( sAttr.indexOf('.') != -1 )
  1374. {
  1375. var aSplit = sAttr.split('.');
  1376. nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
  1377. nNewNode.className = aSplit[1];
  1378. }
  1379. else if ( sAttr.charAt(0) == "#" )
  1380. {
  1381. nNewNode.id = sAttr.substr(1, sAttr.length-1);
  1382. }
  1383. else
  1384. {
  1385. nNewNode.className = sAttr;
  1386. }
  1387. i += j; /* Move along the position array */
  1388. }
  1389. nInsertNode.appendChild( nNewNode );
  1390. nInsertNode = nNewNode;
  1391. }
  1392. else if ( cOption == '>' )
  1393. {
  1394. /* End container div */
  1395. nInsertNode = nInsertNode.parentNode;
  1396. }
  1397. else if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange )
  1398. {
  1399. /* Length */
  1400. nTmp = _fnFeatureHtmlLength( oSettings );
  1401. iPushFeature = 1;
  1402. }
  1403. else if ( cOption == 'f' && oSettings.oFeatures.bFilter )
  1404. {
  1405. /* Filter */
  1406. nTmp = _fnFeatureHtmlFilter( oSettings );
  1407. iPushFeature = 1;
  1408. }
  1409. else if ( cOption == 'r' && oSettings.oFeatures.bProcessing )
  1410. {
  1411. /* pRocessing */
  1412. nTmp = _fnFeatureHtmlProcessing( oSettings );
  1413. iPushFeature = 1;
  1414. }
  1415. else if ( cOption == 't' )
  1416. {
  1417. /* Table */
  1418. nTmp = _fnFeatureHtmlTable( oSettings );
  1419. iPushFeature = 1;
  1420. }
  1421. else if ( cOption == 'i' && oSettings.oFeatures.bInfo )
  1422. {
  1423. /* Info */
  1424. nTmp = _fnFeatureHtmlInfo( oSettings );
  1425. iPushFeature = 1;
  1426. }
  1427. else if ( cOption == 'p' && oSettings.oFeatures.bPaginate )
  1428. {
  1429. /* Pagination */
  1430. nTmp = _fnFeatureHtmlPaginate( oSettings );
  1431. iPushFeature = 1;
  1432. }
  1433. else if ( DataTable.ext.aoFeatures.length !== 0 )
  1434. {
  1435. /* Plug-in features */
  1436. var aoFeatures = DataTable.ext.aoFeatures;
  1437. for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
  1438. {
  1439. if ( cOption == aoFeatures[k].cFeature )
  1440. {
  1441. nTmp = aoFeatures[k].fnInit( oSettings );
  1442. if ( nTmp )
  1443. {
  1444. iPushFeature = 1;
  1445. }
  1446. break;
  1447. }
  1448. }
  1449. }
  1450. /* Add to the 2D features array */
  1451. if ( iPushFeature == 1 && nTmp !== null )
  1452. {
  1453. if ( typeof oSettings.aanFeatures[cOption] !== 'object' )
  1454. {
  1455. oSettings.aanFeatures[cOption] = [];
  1456. }
  1457. oSettings.aanFeatures[cOption].push( nTmp );
  1458. nInsertNode.appendChild( nTmp );
  1459. }
  1460. }
  1461. /* Built our DOM structure - replace the holding div with what we want */
  1462. nHolding.parentNode.replaceChild( oSettings.nTableWrapper, nHolding );
  1463. }
  1464. /**
  1465. * Use the DOM source to create up an array of header cells. The idea here is to
  1466. * create a layout grid (array) of rows x columns, which contains a reference
  1467. * to the cell that that point in the grid (regardless of col/rowspan), such that
  1468. * any column / row could be removed and the new grid constructed
  1469. * @param array {object} aLayout Array to store the calculated layout in
  1470. * @param {node} nThead The header/footer element for the table
  1471. * @memberof DataTable#oApi
  1472. */
  1473. function _fnDetectHeader ( aLayout, nThead )
  1474. {
  1475. var nTrs = $(nThead).children('tr');
  1476. var nCell;
  1477. var i, j, k, l, iLen, jLen, iColShifted;
  1478. var fnShiftCol = function ( a, i, j ) {
  1479. while ( a[i][j] ) {
  1480. j++;
  1481. }
  1482. return j;
  1483. };
  1484. aLayout.splice( 0, aLayout.length );
  1485. /* We know how many rows there are in the layout - so prep it */
  1486. for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  1487. {
  1488. aLayout.push( [] );
  1489. }
  1490. /* Calculate a layout array */
  1491. for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  1492. {
  1493. var iColumn = 0;
  1494. /* For every cell in the row... */
  1495. for ( j=0, jLen=nTrs[i].childNodes.length ; j<jLen ; j++ )
  1496. {
  1497. nCell = nTrs[i].childNodes[j];
  1498. if ( nCell.nodeName.toUpperCase() == "TD" ||
  1499. nCell.nodeName.toUpperCase() == "TH" )
  1500. {
  1501. /* Get the col and rowspan attributes from the DOM and sanitise them */
  1502. var iColspan = nCell.getAttribute('colspan') * 1;
  1503. var iRowspan = nCell.getAttribute('rowspan') * 1;
  1504. iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
  1505. iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
  1506. /* There might be colspan cells already in this row, so shift our target
  1507. * accordingly
  1508. */
  1509. iColShifted = fnShiftCol( aLayout, i, iColumn );
  1510. /* If there is col / rowspan, copy the information into the layout grid */
  1511. for ( l=0 ; l<iColspan ; l++ )
  1512. {
  1513. for ( k=0 ; k<iRowspan ; k++ )
  1514. {
  1515. aLayout[i+k][iColShifted+l] = {
  1516. "cell": nCell,
  1517. "unique": iColspan == 1 ? true : false
  1518. };
  1519. aLayout[i+k].nTr = nTrs[i];
  1520. }
  1521. }
  1522. }
  1523. }
  1524. }
  1525. }
  1526. /**
  1527. * Get an array of unique th elements, one for each column
  1528. * @param {object} oSettings dataTables settings object
  1529. * @param {node} nHeader automatically detect the layout from this node - optional
  1530. * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
  1531. * @returns array {node} aReturn list of unique ths
  1532. * @memberof DataTable#oApi
  1533. */
  1534. function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
  1535. {
  1536. var aReturn = [];
  1537. if ( !aLayout )
  1538. {
  1539. aLayout = oSettings.aoHeader;
  1540. if ( nHeader )
  1541. {
  1542. aLayout = [];
  1543. _fnDetectHeader( aLayout, nHeader );
  1544. }
  1545. }
  1546. for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
  1547. {
  1548. for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
  1549. {
  1550. if ( aLayout[i][j].unique &&
  1551. (!aReturn[j] || !oSettings.bSortCellsTop) )
  1552. {
  1553. aReturn[j] = aLayout[i][j].cell;
  1554. }
  1555. }
  1556. }
  1557. return aReturn;
  1558. }
  1559. /**
  1560. * Update the table using an Ajax call
  1561. * @param {object} oSettings dataTables settings object
  1562. * @returns {boolean} Block the table drawing or not
  1563. * @memberof DataTable#oApi
  1564. */
  1565. function _fnAjaxUpdate( oSettings )
  1566. {
  1567. if ( oSettings.bAjaxDataGet )
  1568. {
  1569. oSettings.iDraw++;
  1570. _fnProcessingDisplay( oSettings, true );
  1571. var iColumns = oSettings.aoColumns.length;
  1572. var aoData = _fnAjaxParameters( oSettings );
  1573. _fnServerParams( oSettings, aoData );
  1574. oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData,
  1575. function(json) {
  1576. _fnAjaxUpdateDraw( oSettings, json );
  1577. }, oSettings );
  1578. return false;
  1579. }
  1580. else
  1581. {
  1582. return true;
  1583. }
  1584. }
  1585. /**
  1586. * Build up the parameters in an object needed for a server-side processing request
  1587. * @param {object} oSettings dataTables settings object
  1588. * @returns {bool} block the table drawing or not
  1589. * @memberof DataTable#oApi
  1590. */
  1591. function _fnAjaxParameters( oSettings )
  1592. {
  1593. var iColumns = oSettings.aoColumns.length;
  1594. var aoData = [], mDataProp, aaSort, aDataSort;
  1595. var i, j;
  1596. aoData.push( { "name": "sEcho", "value": oSettings.iDraw } );
  1597. aoData.push( { "name": "iColumns", "value": iColumns } );
  1598. aoData.push( { "name": "sColumns", "value": _fnColumnOrdering(oSettings) } );
  1599. aoData.push( { "name": "iDisplayStart", "value": oSettings._iDisplayStart } );
  1600. aoData.push( { "name": "iDisplayLength", "value": oSettings.oFeatures.bPaginate !== false ?
  1601. oSettings._iDisplayLength : -1 } );
  1602. for ( i=0 ; i<iColumns ; i++ )
  1603. {
  1604. mDataProp = oSettings.aoColumns[i].mDataProp;
  1605. aoData.push( { "name": "mDataProp_"+i, "value": typeof(mDataProp)==="function" ? 'function' : mDataProp } );
  1606. }
  1607. /* Filtering */
  1608. if ( oSettings.oFeatures.bFilter !== false )
  1609. {
  1610. aoData.push( { "name": "sSearch", "value": oSettings.oPreviousSearch.sSearch } );
  1611. aoData.push( { "name": "bRegex", "value": oSettings.oPreviousSearch.bRegex } );
  1612. for ( i=0 ; i<iColumns ; i++ )
  1613. {
  1614. aoData.push( { "name": "sSearch_"+i, "value": oSettings.aoPreSearchCols[i].sSearch } );
  1615. aoData.push( { "name": "bRegex_"+i, "value": oSettings.aoPreSearchCols[i].bRegex } );
  1616. aoData.push( { "name": "bSearchable_"+i, "value": oSettings.aoColumns[i].bSearchable } );
  1617. }
  1618. }
  1619. /* Sorting */
  1620. if ( oSettings.oFeatures.bSort !== false )
  1621. {
  1622. var iCounter = 0;
  1623. aaSort = ( oSettings.aaSortingFixed !== null ) ?
  1624. oSettings.aaSortingFixed.concat( oSettings.aaSorting ) :
  1625. oSettings.aaSorting.slice();
  1626. for ( i=0 ; i<aaSort.length ; i++ )
  1627. {
  1628. aDataSort = oSettings.aoColumns[ aaSort[i][0] ].aDataSort;
  1629. for ( j=0 ; j<aDataSort.length ; j++ )
  1630. {
  1631. aoData.push( { "name": "iSortCol_"+iCounter, "value": aDataSort[j] } );
  1632. aoData.push( { "name": "sSortDir_"+iCounter, "value": aaSort[i][1] } );
  1633. iCounter++;
  1634. }
  1635. }
  1636. aoData.push( { "name": "iSortingCols", "value": iCounter } );
  1637. for ( i=0 ; i<iColumns ; i++ )
  1638. {
  1639. aoData.push( { "name": "bSortable_"+i, "value": oSettings.aoColumns[i].bSortable } );
  1640. }
  1641. }
  1642. return aoData;
  1643. }
  1644. /**
  1645. * Add Ajax parameters from plugins
  1646. * @param {object} oSettings dataTables settings object
  1647. * @param array {objects} aoData name/value pairs to send to the server
  1648. * @memberof DataTable#oApi
  1649. */
  1650. function _fnServerParams( oSettings, aoData )
  1651. {
  1652. _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [aoData] );
  1653. }
  1654. /**
  1655. * Data the data from the server (nuking the old) and redraw the table
  1656. * @param {object} oSettings dataTables settings object
  1657. * @param {object} json json data return from the server.
  1658. * @param {string} json.sEcho Tracking flag for DataTables to match requests
  1659. * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
  1660. * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
  1661. * @param {array} json.aaData The data to display on this page
  1662. * @param {string} [json.sColumns] Column ordering (sName, comma separated)
  1663. * @memberof DataTable#oApi
  1664. */
  1665. function _fnAjaxUpdateDraw ( oSettings, json )
  1666. {
  1667. if ( json.sEcho !== undefined )
  1668. {
  1669. /* Protect against old returns over-writing a new one. Possible when you get
  1670. * very fast interaction, and later queires are completed much faster
  1671. */
  1672. if ( json.sEcho*1 < oSettings.iDraw )
  1673. {
  1674. return;
  1675. }
  1676. else
  1677. {
  1678. oSettings.iDraw = json.sEcho * 1;
  1679. }
  1680. }
  1681. if ( !oSettings.oScroll.bInfinite ||
  1682. (oSettings.oScroll.bInfinite && (oSettings.bSorted || oSettings.bFiltered)) )
  1683. {
  1684. _fnClearTable( oSettings );
  1685. }
  1686. oSettings._iRecordsTotal = parseInt(json.iTotalRecords, 10);
  1687. oSettings._iRecordsDisplay = parseInt(json.iTotalDisplayRecords, 10);
  1688. /* Determine if reordering is required */
  1689. var sOrdering = _fnColumnOrdering(oSettings);
  1690. var bReOrder = (json.sColumns !== undefined && sOrdering !== "" && json.sColumns != sOrdering );
  1691. var aiIndex;
  1692. if ( bReOrder )
  1693. {
  1694. aiIndex = _fnReOrderIndex( oSettings, json.sColumns );
  1695. }
  1696. var aData = _fnGetObjectDataFn( oSettings.sAjaxDataProp )( json );
  1697. for ( var i=0, iLen=aData.length ; i<iLen ; i++ )
  1698. {
  1699. if ( bReOrder )
  1700. {
  1701. /* If we need to re-order, then create a new array with the correct order and add it */
  1702. var aDataSorted = [];
  1703. for ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ )
  1704. {
  1705. aDataSorted.push( aData[i][ aiIndex[j] ] );
  1706. }
  1707. _fnAddData( oSettings, aDataSorted );
  1708. }
  1709. else
  1710. {
  1711. /* No re-order required, sever got it "right" - just straight add */
  1712. _fnAddData( oSettings, aData[i] );
  1713. }
  1714. }
  1715. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  1716. oSettings.bAjaxDataGet = false;
  1717. _fnDraw( oSettings );
  1718. oSettings.bAjaxDataGet = true;
  1719. _fnProcessingDisplay( oSettings, false );
  1720. }
  1721. /**
  1722. * Generate the node required for filtering text
  1723. * @returns {node} Filter control element
  1724. * @param {object} oSettings dataTables settings object
  1725. * @memberof DataTable#oApi
  1726. */
  1727. function _fnFeatureHtmlFilter ( oSettings )
  1728. {
  1729. var oPreviousSearch = oSettings.oPreviousSearch;
  1730. var sSearchStr = oSettings.oLanguage.sSearch;
  1731. sSearchStr = (sSearchStr.indexOf('_INPUT_') !== -1) ?
  1732. sSearchStr.replace('_INPUT_', '<input type="text" />') :
  1733. sSearchStr==="" ? '<input type="text" />' : sSearchStr+' <input type="text" />';
  1734. var nFilter = document.createElement( 'div' );
  1735. nFilter.className = oSettings.oClasses.sFilter;
  1736. nFilter.innerHTML = '<label>'+sSearchStr+'</label>';
  1737. if ( !oSettings.aanFeatures.f )
  1738. {
  1739. nFilter.id = oSettings.sTableId+'_filter';
  1740. }
  1741. var jqFilter = $('input[type="text"]', nFilter);
  1742. // Store a reference to the input element, so other input elements could be
  1743. // added to the filter wrapper if needed (submit button for example)
  1744. nFilter._DT_Input = jqFilter[0];
  1745. jqFilter.val( oPreviousSearch.sSearch.replace('"','&quot;') );
  1746. jqFilter.bind( 'keyup.DT', function(e) {
  1747. /* Update all other filter input elements for the new display */
  1748. var n = oSettings.aanFeatures.f;
  1749. var val = this.value==="" ? "" : this.value; // mental IE8 fix :-(
  1750. for ( var i=0, iLen=n.length ; i<iLen ; i++ )
  1751. {
  1752. if ( n[i] != $(this).parents('div.dataTables_filter')[0] )
  1753. {
  1754. $(n[i]._DT_Input).val( val );
  1755. }
  1756. }
  1757. /* Now do the filter */
  1758. if ( val != oPreviousSearch.sSearch )
  1759. {
  1760. _fnFilterComplete( oSettings, {
  1761. "sSearch": val,
  1762. "bRegex": oPreviousSearch.bRegex,
  1763. "bSmart": oPreviousSearch.bSmart ,
  1764. "bCaseInsensitive": oPreviousSearch.bCaseInsensitive
  1765. } );
  1766. }
  1767. } );
  1768. jqFilter
  1769. .attr('aria-controls', oSettings.sTableId)
  1770. .bind( 'keypress.DT', function(e) {
  1771. /* Prevent form submission */
  1772. if ( e.keyCode == 13 )
  1773. {
  1774. return false;
  1775. }
  1776. }
  1777. );
  1778. return nFilter;
  1779. }
  1780. /**
  1781. * Filter the table using both the global filter and column based filtering
  1782. * @param {object} oSettings dataTables settings object
  1783. * @param {object} oSearch search information
  1784. * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
  1785. * @memberof DataTable#oApi
  1786. */
  1787. function _fnFilterComplete ( oSettings, oInput, iForce )
  1788. {
  1789. var oPrevSearch = oSettings.oPreviousSearch;
  1790. var aoPrevSearch = oSettings.aoPreSearchCols;
  1791. var fnSaveFilter = function ( oFilter ) {
  1792. /* Save the filtering values */
  1793. oPrevSearch.sSearch = oFilter.sSearch;
  1794. oPrevSearch.bRegex = oFilter.bRegex;
  1795. oPrevSearch.bSmart = oFilter.bSmart;
  1796. oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
  1797. };
  1798. /* In server-side processing all filtering is done by the server, so no point hanging around here */
  1799. if ( !oSettings.oFeatures.bServerSide )
  1800. {
  1801. /* Global filter */
  1802. _fnFilter( oSettings, oInput.sSearch, iForce, oInput.bRegex, oInput.bSmart, oInput.bCaseInsensitive );
  1803. fnSaveFilter( oInput );
  1804. /* Now do the individual column filter */
  1805. for ( var i=0 ; i<oSettings.aoPreSearchCols.length ; i++ )
  1806. {
  1807. _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, aoPrevSearch[i].bRegex,
  1808. aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
  1809. }
  1810. /* Custom filtering */
  1811. _fnFilterCustom( oSettings );
  1812. }
  1813. else
  1814. {
  1815. fnSaveFilter( oInput );
  1816. }
  1817. /* Tell the draw function we have been filtering */
  1818. oSettings.bFiltered = true;
  1819. $(oSettings.oInstance).trigger('filter', oSettings);
  1820. /* Redraw the table */
  1821. oSettings._iDisplayStart = 0;
  1822. _fnCalculateEnd( oSettings );
  1823. _fnDraw( oSettings );
  1824. /* Rebuild search array 'offline' */
  1825. _fnBuildSearchArray( oSettings, 0 );
  1826. }
  1827. /**
  1828. * Apply custom filtering functions
  1829. * @param {object} oSettings dataTables settings object
  1830. * @memberof DataTable#oApi
  1831. */
  1832. function _fnFilterCustom( oSettings )
  1833. {
  1834. var afnFilters = DataTable.ext.afnFiltering;
  1835. for ( var i=0, iLen=afnFilters.length ; i<iLen ; i++ )
  1836. {
  1837. var iCorrector = 0;
  1838. for ( var j=0, jLen=oSettings.aiDisplay.length ; j<jLen ; j++ )
  1839. {
  1840. var iDisIndex = oSettings.aiDisplay[j-iCorrector];
  1841. /* Check if we should use this row based on the filtering function */
  1842. if ( !afnFilters[i]( oSettings, _fnGetRowData( oSettings, iDisIndex, 'filter' ), iDisIndex ) )
  1843. {
  1844. oSettings.aiDisplay.splice( j-iCorrector, 1 );
  1845. iCorrector++;
  1846. }
  1847. }
  1848. }
  1849. }
  1850. /**
  1851. * Filter the table on a per-column basis
  1852. * @param {object} oSettings dataTables settings object
  1853. * @param {string} sInput string to filter on
  1854. * @param {int} iColumn column to filter
  1855. * @param {bool} bRegex treat search string as a regular expression or not
  1856. * @param {bool} bSmart use smart filtering or not
  1857. * @param {bool} bCaseInsensitive Do case insenstive matching or not
  1858. * @memberof DataTable#oApi
  1859. */
  1860. function _fnFilterColumn ( oSettings, sInput, iColumn, bRegex, bSmart, bCaseInsensitive )
  1861. {
  1862. if ( sInput === "" )
  1863. {
  1864. return;
  1865. }
  1866. var iIndexCorrector = 0;
  1867. var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );
  1868. for ( var i=oSettings.aiDisplay.length-1 ; i>=0 ; i-- )
  1869. {
  1870. var sData = _fnDataToSearch( _fnGetCellData( oSettings, oSettings.aiDisplay[i], iColumn, 'filter' ),
  1871. oSettings.aoColumns[iColumn].sType );
  1872. if ( ! rpSearch.test( sData ) )
  1873. {
  1874. oSettings.aiDisplay.splice( i, 1 );
  1875. iIndexCorrector++;
  1876. }
  1877. }
  1878. }
  1879. /**
  1880. * Filter the data table based on user input and draw the table
  1881. * @param {object} oSettings dataTables settings object
  1882. * @param {string} sInput string to filter on
  1883. * @param {int} iForce optional - force a research of the master array (1) or not (undefined or 0)
  1884. * @param {bool} bRegex treat as a regular expression or not
  1885. * @param {bool} bSmart perform smart filtering or not
  1886. * @param {bool} bCaseInsensitive Do case insenstive matching or not
  1887. * @memberof DataTable#oApi
  1888. */
  1889. function _fnFilter( oSettings, sInput, iForce, bRegex, bSmart, bCaseInsensitive )
  1890. {
  1891. var i;
  1892. var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );
  1893. var oPrevSearch = oSettings.oPreviousSearch;
  1894. /* Check if we are forcing or not - optional parameter */
  1895. if ( !iForce )
  1896. {
  1897. iForce = 0;
  1898. }
  1899. /* Need to take account of custom filtering functions - always filter */
  1900. if ( DataTable.ext.afnFiltering.length !== 0 )
  1901. {
  1902. iForce = 1;
  1903. }
  1904. /*
  1905. * If the input is blank - we want the full data set
  1906. */
  1907. if ( sInput.length <= 0 )
  1908. {
  1909. oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
  1910. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  1911. }
  1912. else
  1913. {
  1914. /*
  1915. * We are starting a new search or the new search string is smaller
  1916. * then the old one (i.e. delete). Search from the master array
  1917. */
  1918. if ( oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length ||
  1919. oPrevSearch.sSearch.length > sInput.length || iForce == 1 ||
  1920. sInput.indexOf(oPrevSearch.sSearch) !== 0 )
  1921. {
  1922. /* Nuke the old display array - we are going to rebuild it */
  1923. oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
  1924. /* Force a rebuild of the search array */
  1925. _fnBuildSearchArray( oSettings, 1 );
  1926. /* Search through all records to populate the search array
  1927. * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1
  1928. * mapping
  1929. */
  1930. for ( i=0 ; i<oSettings.aiDisplayMaster.length ; i++ )
  1931. {
  1932. if ( rpSearch.test(oSettings.asDataSearch[i]) )
  1933. {
  1934. oSettings.aiDisplay.push( oSettings.aiDisplayMaster[i] );
  1935. }
  1936. }
  1937. }
  1938. else
  1939. {
  1940. /* Using old search array - refine it - do it this way for speed
  1941. * Don't have to search the whole master array again
  1942. */
  1943. var iIndexCorrector = 0;
  1944. /* Search the current results */
  1945. for ( i=0 ; i<oSettings.asDataSearch.length ; i++ )
  1946. {
  1947. if ( ! rpSearch.test(oSettings.asDataSearch[i]) )
  1948. {
  1949. oSettings.aiDisplay.splice( i-iIndexCorrector, 1 );
  1950. iIndexCorrector++;
  1951. }
  1952. }
  1953. }
  1954. }
  1955. }
  1956. /**
  1957. * Create an array which can be quickly search through
  1958. * @param {object} oSettings dataTables settings object
  1959. * @param {int} iMaster use the master data array - optional
  1960. * @memberof DataTable#oApi
  1961. */
  1962. function _fnBuildSearchArray ( oSettings, iMaster )
  1963. {
  1964. if ( !oSettings.oFeatures.bServerSide )
  1965. {
  1966. /* Clear out the old data */
  1967. oSettings.asDataSearch.splice( 0, oSettings.asDataSearch.length );
  1968. var aArray = (iMaster && iMaster===1) ?
  1969. oSettings.aiDisplayMaster : oSettings.aiDisplay;
  1970. for ( var i=0, iLen=aArray.length ; i<iLen ; i++ )
  1971. {
  1972. oSettings.asDataSearch[i] = _fnBuildSearchRow( oSettings,
  1973. _fnGetRowData( oSettings, aArray[i], 'filter' ) );
  1974. }
  1975. }
  1976. }
  1977. /**
  1978. * Create a searchable string from a single data row
  1979. * @param {object} oSettings dataTables settings object
  1980. * @param {array} aData Row data array to use for the data to search
  1981. * @memberof DataTable#oApi
  1982. */
  1983. function _fnBuildSearchRow( oSettings, aData )
  1984. {
  1985. var sSearch = '';
  1986. if ( oSettings.__nTmpFilter === undefined )
  1987. {
  1988. oSettings.__nTmpFilter = document.createElement('div');
  1989. }
  1990. var nTmp = oSettings.__nTmpFilter;
  1991. for ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ )
  1992. {
  1993. if ( oSettings.aoColumns[j].bSearchable )
  1994. {
  1995. var sData = aData[j];
  1996. sSearch += _fnDataToSearch( sData, oSettings.aoColumns[j].sType )+' ';
  1997. }
  1998. }
  1999. /* If it looks like there is an HTML entity in the string, attempt to decode it */
  2000. if ( sSearch.indexOf('&') !== -1 )
  2001. {
  2002. nTmp.innerHTML = sSearch;
  2003. sSearch = nTmp.textContent ? nTmp.textContent : nTmp.innerText;
  2004. /* IE and Opera appear to put an newline where there is a <br> tag - remove it */
  2005. sSearch = sSearch.replace(/\n/g," ").replace(/\r/g,"");
  2006. }
  2007. return sSearch;
  2008. }
  2009. /**
  2010. * Build a regular expression object suitable for searching a table
  2011. * @param {string} sSearch string to search for
  2012. * @param {bool} bRegex treat as a regular expression or not
  2013. * @param {bool} bSmart perform smart filtering or not
  2014. * @param {bool} bCaseInsensitive Do case insenstive matching or not
  2015. * @returns {RegExp} constructed object
  2016. * @memberof DataTable#oApi
  2017. */
  2018. function _fnFilterCreateSearch( sSearch, bRegex, bSmart, bCaseInsensitive )
  2019. {
  2020. var asSearch, sRegExpString;
  2021. if ( bSmart )
  2022. {
  2023. /* Generate the regular expression to use. Something along the lines of:
  2024. * ^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$
  2025. */
  2026. asSearch = bRegex ? sSearch.split( ' ' ) : _fnEscapeRegex( sSearch ).split( ' ' );
  2027. sRegExpString = '^(?=.*?'+asSearch.join( ')(?=.*?' )+').*$';
  2028. return new RegExp( sRegExpString, bCaseInsensitive ? "i" : "" );
  2029. }
  2030. else
  2031. {
  2032. sSearch = bRegex ? sSearch : _fnEscapeRegex( sSearch );
  2033. return new RegExp( sSearch, bCaseInsensitive ? "i" : "" );
  2034. }
  2035. }
  2036. /**
  2037. * Convert raw data into something that the user can search on
  2038. * @param {string} sData data to be modified
  2039. * @param {string} sType data type
  2040. * @returns {string} search string
  2041. * @memberof DataTable#oApi
  2042. */
  2043. function _fnDataToSearch ( sData, sType )
  2044. {
  2045. if ( typeof DataTable.ext.ofnSearch[sType] === "function" )
  2046. {
  2047. return DataTable.ext.ofnSearch[sType]( sData );
  2048. }
  2049. else if ( sData === null )
  2050. {
  2051. return '';
  2052. }
  2053. else if ( sType == "html" )
  2054. {
  2055. return sData.replace(/[\r\n]/g," ").replace( /<.*?>/g, "" );
  2056. }
  2057. else if ( typeof sData === "string" )
  2058. {
  2059. return sData.replace(/[\r\n]/g," ");
  2060. }
  2061. return sData;
  2062. }
  2063. /**
  2064. * scape a string stuch that it can be used in a regular expression
  2065. * @param {string} sVal string to escape
  2066. * @returns {string} escaped string
  2067. * @memberof DataTable#oApi
  2068. */
  2069. function _fnEscapeRegex ( sVal )
  2070. {
  2071. var acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ];
  2072. var reReplace = new RegExp( '(\\' + acEscape.join('|\\') + ')', 'g' );
  2073. return sVal.replace(reReplace, '\\$1');
  2074. }
  2075. /**
  2076. * Generate the node required for the info display
  2077. * @param {object} oSettings dataTables settings object
  2078. * @returns {node} Information element
  2079. * @memberof DataTable#oApi
  2080. */
  2081. function _fnFeatureHtmlInfo ( oSettings )
  2082. {
  2083. var nInfo = document.createElement( 'div' );
  2084. nInfo.className = oSettings.oClasses.sInfo;
  2085. /* Actions that are to be taken once only for this feature */
  2086. if ( !oSettings.aanFeatures.i )
  2087. {
  2088. /* Add draw callback */
  2089. oSettings.aoDrawCallback.push( {
  2090. "fn": _fnUpdateInfo,
  2091. "sName": "information"
  2092. } );
  2093. /* Add id */
  2094. nInfo.id = oSettings.sTableId+'_info';
  2095. }
  2096. oSettings.nTable.setAttribute( 'aria-describedby', oSettings.sTableId+'_info' );
  2097. return nInfo;
  2098. }
  2099. /**
  2100. * Update the information elements in the display
  2101. * @param {object} oSettings dataTables settings object
  2102. * @memberof DataTable#oApi
  2103. */
  2104. function _fnUpdateInfo ( oSettings )
  2105. {
  2106. /* Show information about the table */
  2107. if ( !oSettings.oFeatures.bInfo || oSettings.aanFeatures.i.length === 0 )
  2108. {
  2109. return;
  2110. }
  2111. var
  2112. oLang = oSettings.oLanguage,
  2113. iStart = oSettings._iDisplayStart+1,
  2114. iEnd = oSettings.fnDisplayEnd(),
  2115. iMax = oSettings.fnRecordsTotal(),
  2116. iTotal = oSettings.fnRecordsDisplay(),
  2117. sOut;
  2118. if ( iTotal === 0 && iTotal == iMax )
  2119. {
  2120. /* Empty record set */
  2121. sOut = oLang.sInfoEmpty;
  2122. }
  2123. else if ( iTotal === 0 )
  2124. {
  2125. /* Empty record set after filtering */
  2126. sOut = oLang.sInfoEmpty +' '+ oLang.sInfoFiltered;
  2127. }
  2128. else if ( iTotal == iMax )
  2129. {
  2130. /* Normal record set */
  2131. sOut = oLang.sInfo;
  2132. }
  2133. else
  2134. {
  2135. /* Record set after filtering */
  2136. sOut = oLang.sInfo +' '+ oLang.sInfoFiltered;
  2137. }
  2138. // Convert the macros
  2139. sOut += oLang.sInfoPostFix;
  2140. sOut = _fnInfoMacros( oSettings, sOut );
  2141. if ( oLang.fnInfoCallback !== null )
  2142. {
  2143. sOut = oLang.fnInfoCallback.call( oSettings.oInstance,
  2144. oSettings, iStart, iEnd, iMax, iTotal, sOut );
  2145. }
  2146. var n = oSettings.aanFeatures.i;
  2147. for ( var i=0, iLen=n.length ; i<iLen ; i++ )
  2148. {
  2149. $(n[i]).html( sOut );
  2150. }
  2151. }
  2152. function _fnInfoMacros ( oSettings, str )
  2153. {
  2154. var
  2155. iStart = oSettings._iDisplayStart+1,
  2156. sStart = oSettings.fnFormatNumber( iStart ),
  2157. iEnd = oSettings.fnDisplayEnd(),
  2158. sEnd = oSettings.fnFormatNumber( iEnd ),
  2159. iTotal = oSettings.fnRecordsDisplay(),
  2160. sTotal = oSettings.fnFormatNumber( iTotal ),
  2161. iMax = oSettings.fnRecordsTotal(),
  2162. sMax = oSettings.fnFormatNumber( iMax );
  2163. // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
  2164. // internally
  2165. if ( oSettings.oScroll.bInfinite )
  2166. {
  2167. sStart = oSettings.fnFormatNumber( 1 );
  2168. }
  2169. return str.
  2170. replace('_START_', sStart).
  2171. replace('_END_', sEnd).
  2172. replace('_TOTAL_', sTotal).
  2173. replace('_MAX_', sMax);
  2174. }
  2175. /**
  2176. * Draw the table for the first time, adding all required features
  2177. * @param {object} oSettings dataTables settings object
  2178. * @memberof DataTable#oApi
  2179. */
  2180. function _fnInitialise ( oSettings )
  2181. {
  2182. var i, iLen, iAjaxStart=oSettings.iInitDisplayStart;
  2183. /* Ensure that the table data is fully initialised */
  2184. if ( oSettings.bInitialised === false )
  2185. {
  2186. setTimeout( function(){ _fnInitialise( oSettings ); }, 200 );
  2187. return;
  2188. }
  2189. /* Show the display HTML options */
  2190. _fnAddOptionsHtml( oSettings );
  2191. /* Build and draw the header / footer for the table */
  2192. _fnBuildHead( oSettings );
  2193. _fnDrawHead( oSettings, oSettings.aoHeader );
  2194. if ( oSettings.nTFoot )
  2195. {
  2196. _fnDrawHead( oSettings, oSettings.aoFooter );
  2197. }
  2198. /* Okay to show that something is going on now */
  2199. _fnProcessingDisplay( oSettings, true );
  2200. /* Calculate sizes for columns */
  2201. if ( oSettings.oFeatures.bAutoWidth )
  2202. {
  2203. _fnCalculateColumnWidths( oSettings );
  2204. }
  2205. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  2206. {
  2207. if ( oSettings.aoColumns[i].sWidth !== null )
  2208. {
  2209. oSettings.aoColumns[i].nTh.style.width = _fnStringToCss( oSettings.aoColumns[i].sWidth );
  2210. }
  2211. }
  2212. /* If there is default sorting required - let's do it. The sort function will do the
  2213. * drawing for us. Otherwise we draw the table regardless of the Ajax source - this allows
  2214. * the table to look initialised for Ajax sourcing data (show 'loading' message possibly)
  2215. */
  2216. if ( oSettings.oFeatures.bSort )
  2217. {
  2218. _fnSort( oSettings );
  2219. }
  2220. else if ( oSettings.oFeatures.bFilter )
  2221. {
  2222. _fnFilterComplete( oSettings, oSettings.oPreviousSearch );
  2223. }
  2224. else
  2225. {
  2226. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  2227. _fnCalculateEnd( oSettings );
  2228. _fnDraw( oSettings );
  2229. }
  2230. /* if there is an ajax source load the data */
  2231. if ( oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )
  2232. {
  2233. var aoData = [];
  2234. _fnServerParams( oSettings, aoData );
  2235. oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData, function(json) {
  2236. var aData = (oSettings.sAjaxDataProp !== "") ?
  2237. _fnGetObjectDataFn( oSettings.sAjaxDataProp )(json) : json;
  2238. /* Got the data - add it to the table */
  2239. for ( i=0 ; i<aData.length ; i++ )
  2240. {
  2241. _fnAddData( oSettings, aData[i] );
  2242. }
  2243. /* Reset the init display for cookie saving. We've already done a filter, and
  2244. * therefore cleared it before. So we need to make it appear 'fresh'
  2245. */
  2246. oSettings.iInitDisplayStart = iAjaxStart;
  2247. if ( oSettings.oFeatures.bSort )
  2248. {
  2249. _fnSort( oSettings );
  2250. }
  2251. else
  2252. {
  2253. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  2254. _fnCalculateEnd( oSettings );
  2255. _fnDraw( oSettings );
  2256. }
  2257. _fnProcessingDisplay( oSettings, false );
  2258. _fnInitComplete( oSettings, json );
  2259. }, oSettings );
  2260. return;
  2261. }
  2262. /* Server-side processing initialisation complete is done at the end of _fnDraw */
  2263. if ( !oSettings.oFeatures.bServerSide )
  2264. {
  2265. _fnProcessingDisplay( oSettings, false );
  2266. _fnInitComplete( oSettings );
  2267. }
  2268. }
  2269. /**
  2270. * Draw the table for the first time, adding all required features
  2271. * @param {object} oSettings dataTables settings object
  2272. * @param {object} [json] JSON from the server that completed the table, if using Ajax source
  2273. * with client-side processing (optional)
  2274. * @memberof DataTable#oApi
  2275. */
  2276. function _fnInitComplete ( oSettings, json )
  2277. {
  2278. oSettings._bInitComplete = true;
  2279. _fnCallbackFire( oSettings, 'aoInitComplete', 'init', [oSettings, json] );
  2280. }
  2281. /**
  2282. * Language compatibility - when certain options are given, and others aren't, we
  2283. * need to duplicate the values over, in order to provide backwards compatibility
  2284. * with older language files.
  2285. * @param {object} oSettings dataTables settings object
  2286. * @memberof DataTable#oApi
  2287. */
  2288. function _fnLanguageCompat( oLanguage )
  2289. {
  2290. var oDefaults = DataTable.defaults.oLanguage;
  2291. /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
  2292. * sZeroRecords - assuming that is given.
  2293. */
  2294. if ( !oLanguage.sEmptyTable && oLanguage.sZeroRecords &&
  2295. oDefaults.sEmptyTable === "No data available in table" )
  2296. {
  2297. _fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sEmptyTable' );
  2298. }
  2299. /* Likewise with loading records */
  2300. if ( !oLanguage.sLoadingRecords && oLanguage.sZeroRecords &&
  2301. oDefaults.sLoadingRecords === "Loading..." )
  2302. {
  2303. _fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sLoadingRecords' );
  2304. }
  2305. }
  2306. /**
  2307. * Generate the node required for user display length changing
  2308. * @param {object} oSettings dataTables settings object
  2309. * @returns {node} Display length feature node
  2310. * @memberof DataTable#oApi
  2311. */
  2312. function _fnFeatureHtmlLength ( oSettings )
  2313. {
  2314. if ( oSettings.oScroll.bInfinite )
  2315. {
  2316. return null;
  2317. }
  2318. /* This can be overruled by not using the _MENU_ var/macro in the language variable */
  2319. var sName = 'name="'+oSettings.sTableId+'_length"';
  2320. var sStdMenu = '<select size="1" '+sName+'>';
  2321. var i, iLen;
  2322. var aLengthMenu = oSettings.aLengthMenu;
  2323. if ( aLengthMenu.length == 2 && typeof aLengthMenu[0] === 'object' &&
  2324. typeof aLengthMenu[1] === 'object' )
  2325. {
  2326. for ( i=0, iLen=aLengthMenu[0].length ; i<iLen ; i++ )
  2327. {
  2328. sStdMenu += '<option value="'+aLengthMenu[0][i]+'">'+aLengthMenu[1][i]+'</option>';
  2329. }
  2330. }
  2331. else
  2332. {
  2333. for ( i=0, iLen=aLengthMenu.length ; i<iLen ; i++ )
  2334. {
  2335. sStdMenu += '<option value="'+aLengthMenu[i]+'">'+aLengthMenu[i]+'</option>';
  2336. }
  2337. }
  2338. sStdMenu += '</select>';
  2339. var nLength = document.createElement( 'div' );
  2340. if ( !oSettings.aanFeatures.l )
  2341. {
  2342. nLength.id = oSettings.sTableId+'_length';
  2343. }
  2344. nLength.className = oSettings.oClasses.sLength;
  2345. nLength.innerHTML = '<label>'+oSettings.oLanguage.sLengthMenu.replace( '_MENU_', sStdMenu )+'</label>';
  2346. /*
  2347. * Set the length to the current display length - thanks to Andrea Pavlovic for this fix,
  2348. * and Stefan Skopnik for fixing the fix!
  2349. */
  2350. $('select option[value="'+oSettings._iDisplayLength+'"]', nLength).attr("selected", true);
  2351. $('select', nLength).bind( 'change.DT', function(e) {
  2352. var iVal = $(this).val();
  2353. /* Update all other length options for the new display */
  2354. var n = oSettings.aanFeatures.l;
  2355. for ( i=0, iLen=n.length ; i<iLen ; i++ )
  2356. {
  2357. if ( n[i] != this.parentNode )
  2358. {
  2359. $('select', n[i]).val( iVal );
  2360. }
  2361. }
  2362. /* Redraw the table */
  2363. oSettings._iDisplayLength = parseInt(iVal, 10);
  2364. _fnCalculateEnd( oSettings );
  2365. /* If we have space to show extra rows (backing up from the end point - then do so */
  2366. if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() )
  2367. {
  2368. oSettings._iDisplayStart = oSettings.fnDisplayEnd() - oSettings._iDisplayLength;
  2369. if ( oSettings._iDisplayStart < 0 )
  2370. {
  2371. oSettings._iDisplayStart = 0;
  2372. }
  2373. }
  2374. if ( oSettings._iDisplayLength == -1 )
  2375. {
  2376. oSettings._iDisplayStart = 0;
  2377. }
  2378. _fnDraw( oSettings );
  2379. } );
  2380. $('select', nLength).attr('aria-controls', oSettings.sTableId);
  2381. return nLength;
  2382. }
  2383. /**
  2384. * Rcalculate the end point based on the start point
  2385. * @param {object} oSettings dataTables settings object
  2386. * @memberof DataTable#oApi
  2387. */
  2388. function _fnCalculateEnd( oSettings )
  2389. {
  2390. if ( oSettings.oFeatures.bPaginate === false )
  2391. {
  2392. oSettings._iDisplayEnd = oSettings.aiDisplay.length;
  2393. }
  2394. else
  2395. {
  2396. /* Set the end point of the display - based on how many elements there are
  2397. * still to display
  2398. */
  2399. if ( oSettings._iDisplayStart + oSettings._iDisplayLength > oSettings.aiDisplay.length ||
  2400. oSettings._iDisplayLength == -1 )
  2401. {
  2402. oSettings._iDisplayEnd = oSettings.aiDisplay.length;
  2403. }
  2404. else
  2405. {
  2406. oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength;
  2407. }
  2408. }
  2409. }
  2410. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2411. * Note that most of the paging logic is done in
  2412. * DataTable.ext.oPagination
  2413. */
  2414. /**
  2415. * Generate the node required for default pagination
  2416. * @param {object} oSettings dataTables settings object
  2417. * @returns {node} Pagination feature node
  2418. * @memberof DataTable#oApi
  2419. */
  2420. function _fnFeatureHtmlPaginate ( oSettings )
  2421. {
  2422. if ( oSettings.oScroll.bInfinite )
  2423. {
  2424. return null;
  2425. }
  2426. var nPaginate = document.createElement( 'div' );
  2427. nPaginate.className = oSettings.oClasses.sPaging+oSettings.sPaginationType;
  2428. DataTable.ext.oPagination[ oSettings.sPaginationType ].fnInit( oSettings, nPaginate,
  2429. function( oSettings ) {
  2430. _fnCalculateEnd( oSettings );
  2431. _fnDraw( oSettings );
  2432. }
  2433. );
  2434. /* Add a draw callback for the pagination on first instance, to update the paging display */
  2435. if ( !oSettings.aanFeatures.p )
  2436. {
  2437. oSettings.aoDrawCallback.push( {
  2438. "fn": function( oSettings ) {
  2439. DataTable.ext.oPagination[ oSettings.sPaginationType ].fnUpdate( oSettings, function( oSettings ) {
  2440. _fnCalculateEnd( oSettings );
  2441. _fnDraw( oSettings );
  2442. } );
  2443. },
  2444. "sName": "pagination"
  2445. } );
  2446. }
  2447. return nPaginate;
  2448. }
  2449. /**
  2450. * Alter the display settings to change the page
  2451. * @param {object} oSettings dataTables settings object
  2452. * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
  2453. * or page number to jump to (integer)
  2454. * @returns {bool} true page has changed, false - no change (no effect) eg 'first' on page 1
  2455. * @memberof DataTable#oApi
  2456. */
  2457. function _fnPageChange ( oSettings, mAction )
  2458. {
  2459. var iOldStart = oSettings._iDisplayStart;
  2460. if ( typeof mAction === "number" )
  2461. {
  2462. oSettings._iDisplayStart = mAction * oSettings._iDisplayLength;
  2463. if ( oSettings._iDisplayStart > oSettings.fnRecordsDisplay() )
  2464. {
  2465. oSettings._iDisplayStart = 0;
  2466. }
  2467. }
  2468. else if ( mAction == "first" )
  2469. {
  2470. oSettings._iDisplayStart = 0;
  2471. }
  2472. else if ( mAction == "previous" )
  2473. {
  2474. oSettings._iDisplayStart = oSettings._iDisplayLength>=0 ?
  2475. oSettings._iDisplayStart - oSettings._iDisplayLength :
  2476. 0;
  2477. /* Correct for underrun */
  2478. if ( oSettings._iDisplayStart < 0 )
  2479. {
  2480. oSettings._iDisplayStart = 0;
  2481. }
  2482. }
  2483. else if ( mAction == "next" )
  2484. {
  2485. if ( oSettings._iDisplayLength >= 0 )
  2486. {
  2487. /* Make sure we are not over running the display array */
  2488. if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() )
  2489. {
  2490. oSettings._iDisplayStart += oSettings._iDisplayLength;
  2491. }
  2492. }
  2493. else
  2494. {
  2495. oSettings._iDisplayStart = 0;
  2496. }
  2497. }
  2498. else if ( mAction == "last" )
  2499. {
  2500. if ( oSettings._iDisplayLength >= 0 )
  2501. {
  2502. var iPages = parseInt( (oSettings.fnRecordsDisplay()-1) / oSettings._iDisplayLength, 10 ) + 1;
  2503. oSettings._iDisplayStart = (iPages-1) * oSettings._iDisplayLength;
  2504. }
  2505. else
  2506. {
  2507. oSettings._iDisplayStart = 0;
  2508. }
  2509. }
  2510. else
  2511. {
  2512. _fnLog( oSettings, 0, "Unknown paging action: "+mAction );
  2513. }
  2514. $(oSettings.oInstance).trigger('page', oSettings);
  2515. return iOldStart != oSettings._iDisplayStart;
  2516. }
  2517. /**
  2518. * Generate the node required for the processing node
  2519. * @param {object} oSettings dataTables settings object
  2520. * @returns {node} Processing element
  2521. * @memberof DataTable#oApi
  2522. */
  2523. function _fnFeatureHtmlProcessing ( oSettings )
  2524. {
  2525. var nProcessing = document.createElement( 'div' );
  2526. if ( !oSettings.aanFeatures.r )
  2527. {
  2528. nProcessing.id = oSettings.sTableId+'_processing';
  2529. }
  2530. nProcessing.innerHTML = oSettings.oLanguage.sProcessing;
  2531. nProcessing.className = oSettings.oClasses.sProcessing;
  2532. oSettings.nTable.parentNode.insertBefore( nProcessing, oSettings.nTable );
  2533. return nProcessing;
  2534. }
  2535. /**
  2536. * Display or hide the processing indicator
  2537. * @param {object} oSettings dataTables settings object
  2538. * @param {bool} bShow Show the processing indicator (true) or not (false)
  2539. * @memberof DataTable#oApi
  2540. */
  2541. function _fnProcessingDisplay ( oSettings, bShow )
  2542. {
  2543. if ( oSettings.oFeatures.bProcessing )
  2544. {
  2545. var an = oSettings.aanFeatures.r;
  2546. for ( var i=0, iLen=an.length ; i<iLen ; i++ )
  2547. {
  2548. an[i].style.visibility = bShow ? "visible" : "hidden";
  2549. }
  2550. }
  2551. $(oSettings.oInstance).trigger('processing', [oSettings, bShow]);
  2552. }
  2553. /**
  2554. * Add any control elements for the table - specifically scrolling
  2555. * @param {object} oSettings dataTables settings object
  2556. * @returns {node} Node to add to the DOM
  2557. * @memberof DataTable#oApi
  2558. */
  2559. function _fnFeatureHtmlTable ( oSettings )
  2560. {
  2561. /* Check if scrolling is enabled or not - if not then leave the DOM unaltered */
  2562. if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" )
  2563. {
  2564. return oSettings.nTable;
  2565. }
  2566. /*
  2567. * The HTML structure that we want to generate in this function is:
  2568. * div - nScroller
  2569. * div - nScrollHead
  2570. * div - nScrollHeadInner
  2571. * table - nScrollHeadTable
  2572. * thead - nThead
  2573. * div - nScrollBody
  2574. * table - oSettings.nTable
  2575. * thead - nTheadSize
  2576. * tbody - nTbody
  2577. * div - nScrollFoot
  2578. * div - nScrollFootInner
  2579. * table - nScrollFootTable
  2580. * tfoot - nTfoot
  2581. */
  2582. var
  2583. nScroller = document.createElement('div'),
  2584. nScrollHead = document.createElement('div'),
  2585. nScrollHeadInner = document.createElement('div'),
  2586. nScrollBody = document.createElement('div'),
  2587. nScrollFoot = document.createElement('div'),
  2588. nScrollFootInner = document.createElement('div'),
  2589. nScrollHeadTable = oSettings.nTable.cloneNode(false),
  2590. nScrollFootTable = oSettings.nTable.cloneNode(false),
  2591. nThead = oSettings.nTable.getElementsByTagName('thead')[0],
  2592. nTfoot = oSettings.nTable.getElementsByTagName('tfoot').length === 0 ? null :
  2593. oSettings.nTable.getElementsByTagName('tfoot')[0],
  2594. oClasses = oSettings.oClasses;
  2595. nScrollHead.appendChild( nScrollHeadInner );
  2596. nScrollFoot.appendChild( nScrollFootInner );
  2597. nScrollBody.appendChild( oSettings.nTable );
  2598. nScroller.appendChild( nScrollHead );
  2599. nScroller.appendChild( nScrollBody );
  2600. nScrollHeadInner.appendChild( nScrollHeadTable );
  2601. nScrollHeadTable.appendChild( nThead );
  2602. if ( nTfoot !== null )
  2603. {
  2604. nScroller.appendChild( nScrollFoot );
  2605. nScrollFootInner.appendChild( nScrollFootTable );
  2606. nScrollFootTable.appendChild( nTfoot );
  2607. }
  2608. nScroller.className = oClasses.sScrollWrapper;
  2609. nScrollHead.className = oClasses.sScrollHead;
  2610. nScrollHeadInner.className = oClasses.sScrollHeadInner;
  2611. nScrollBody.className = oClasses.sScrollBody;
  2612. nScrollFoot.className = oClasses.sScrollFoot;
  2613. nScrollFootInner.className = oClasses.sScrollFootInner;
  2614. if ( oSettings.oScroll.bAutoCss )
  2615. {
  2616. nScrollHead.style.overflow = "hidden";
  2617. nScrollHead.style.position = "relative";
  2618. nScrollFoot.style.overflow = "hidden";
  2619. nScrollBody.style.overflow = "auto";
  2620. }
  2621. nScrollHead.style.border = "0";
  2622. nScrollHead.style.width = "100%";
  2623. nScrollFoot.style.border = "0";
  2624. nScrollHeadInner.style.width = oSettings.oScroll.sXInner !== "" ?
  2625. oSettings.oScroll.sXInner : "100%"; /* will be overwritten */
  2626. /* Modify attributes to respect the clones */
  2627. nScrollHeadTable.removeAttribute('id');
  2628. nScrollHeadTable.style.marginLeft = "0";
  2629. oSettings.nTable.style.marginLeft = "0";
  2630. if ( nTfoot !== null )
  2631. {
  2632. nScrollFootTable.removeAttribute('id');
  2633. nScrollFootTable.style.marginLeft = "0";
  2634. }
  2635. /* Move caption elements from the body to the header, footer or leave where it is
  2636. * depending on the configuration. Note that the DTD says there can be only one caption */
  2637. var nCaption = $(oSettings.nTable).children('caption');
  2638. if ( nCaption.length > 0 )
  2639. {
  2640. nCaption = nCaption[0];
  2641. if ( nCaption._captionSide === "top" )
  2642. {
  2643. nScrollHeadTable.appendChild( nCaption );
  2644. }
  2645. else if ( nCaption._captionSide === "bottom" && nTfoot )
  2646. {
  2647. nScrollFootTable.appendChild( nCaption );
  2648. }
  2649. }
  2650. /*
  2651. * Sizing
  2652. */
  2653. /* When xscrolling add the width and a scroller to move the header with the body */
  2654. if ( oSettings.oScroll.sX !== "" )
  2655. {
  2656. nScrollHead.style.width = _fnStringToCss( oSettings.oScroll.sX );
  2657. nScrollBody.style.width = _fnStringToCss( oSettings.oScroll.sX );
  2658. if ( nTfoot !== null )
  2659. {
  2660. nScrollFoot.style.width = _fnStringToCss( oSettings.oScroll.sX );
  2661. }
  2662. /* When the body is scrolled, then we also want to scroll the headers */
  2663. $(nScrollBody).scroll( function (e) {
  2664. nScrollHead.scrollLeft = this.scrollLeft;
  2665. if ( nTfoot !== null )
  2666. {
  2667. nScrollFoot.scrollLeft = this.scrollLeft;
  2668. }
  2669. } );
  2670. }
  2671. /* When yscrolling, add the height */
  2672. if ( oSettings.oScroll.sY !== "" )
  2673. {
  2674. nScrollBody.style.height = _fnStringToCss( oSettings.oScroll.sY );
  2675. }
  2676. /* Redraw - align columns across the tables */
  2677. oSettings.aoDrawCallback.push( {
  2678. "fn": _fnScrollDraw,
  2679. "sName": "scrolling"
  2680. } );
  2681. /* Infinite scrolling event handlers */
  2682. if ( oSettings.oScroll.bInfinite )
  2683. {
  2684. $(nScrollBody).scroll( function() {
  2685. /* Use a blocker to stop scrolling from loading more data while other data is still loading */
  2686. if ( !oSettings.bDrawing && $(this).scrollTop() !== 0 )
  2687. {
  2688. /* Check if we should load the next data set */
  2689. if ( $(this).scrollTop() + $(this).height() >
  2690. $(oSettings.nTable).height() - oSettings.oScroll.iLoadGap )
  2691. {
  2692. /* Only do the redraw if we have to - we might be at the end of the data */
  2693. if ( oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay() )
  2694. {
  2695. _fnPageChange( oSettings, 'next' );
  2696. _fnCalculateEnd( oSettings );
  2697. _fnDraw( oSettings );
  2698. }
  2699. }
  2700. }
  2701. } );
  2702. }
  2703. oSettings.nScrollHead = nScrollHead;
  2704. oSettings.nScrollFoot = nScrollFoot;
  2705. return nScroller;
  2706. }
  2707. /**
  2708. * Update the various tables for resizing. It's a bit of a pig this function, but
  2709. * basically the idea to:
  2710. * 1. Re-create the table inside the scrolling div
  2711. * 2. Take live measurements from the DOM
  2712. * 3. Apply the measurements
  2713. * 4. Clean up
  2714. * @param {object} o dataTables settings object
  2715. * @returns {node} Node to add to the DOM
  2716. * @memberof DataTable#oApi
  2717. */
  2718. function _fnScrollDraw ( o )
  2719. {
  2720. var
  2721. nScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0],
  2722. nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],
  2723. nScrollBody = o.nTable.parentNode,
  2724. i, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis,
  2725. nTheadSize, nTfootSize,
  2726. iWidth, aApplied=[], iSanityWidth,
  2727. nScrollFootInner = (o.nTFoot !== null) ? o.nScrollFoot.getElementsByTagName('div')[0] : null,
  2728. nScrollFootTable = (o.nTFoot !== null) ? nScrollFootInner.getElementsByTagName('table')[0] : null,
  2729. ie67 = $.browser.msie && $.browser.version <= 7;
  2730. /*
  2731. * 1. Re-create the table inside the scrolling div
  2732. */
  2733. /* Remove the old minimised thead and tfoot elements in the inner table */
  2734. $(o.nTable).children('thead, tfoot').remove();
  2735. /* Clone the current header and footer elements and then place it into the inner table */
  2736. nTheadSize = $(o.nTHead).clone()[0];
  2737. o.nTable.insertBefore( nTheadSize, o.nTable.childNodes[0] );
  2738. if ( o.nTFoot !== null )
  2739. {
  2740. nTfootSize = $(o.nTFoot).clone()[0];
  2741. o.nTable.insertBefore( nTfootSize, o.nTable.childNodes[1] );
  2742. }
  2743. /*
  2744. * 2. Take live measurements from the DOM - do not alter the DOM itself!
  2745. */
  2746. /* Remove old sizing and apply the calculated column widths
  2747. * Get the unique column headers in the newly created (cloned) header. We want to apply the
  2748. * calclated sizes to this header
  2749. */
  2750. if ( o.oScroll.sX === "" )
  2751. {
  2752. nScrollBody.style.width = '100%';
  2753. nScrollHeadInner.parentNode.style.width = '100%';
  2754. }
  2755. var nThs = _fnGetUniqueThs( o, nTheadSize );
  2756. for ( i=0, iLen=nThs.length ; i<iLen ; i++ )
  2757. {
  2758. iVis = _fnVisibleToColumnIndex( o, i );
  2759. nThs[i].style.width = o.aoColumns[iVis].sWidth;
  2760. }
  2761. if ( o.nTFoot !== null )
  2762. {
  2763. _fnApplyToChildren( function(n) {
  2764. n.style.width = "";
  2765. }, nTfootSize.getElementsByTagName('tr') );
  2766. }
  2767. // If scroll collapse is enabled, when we put the headers back into the body for sizing, we
  2768. // will end up forcing the scrollbar to appear, making our measurements wrong for when we
  2769. // then hide it (end of this function), so add the header height to the body scroller.
  2770. if ( o.oScroll.bCollapse && o.oScroll.sY !== "" )
  2771. {
  2772. nScrollBody.style.height = (nScrollBody.offsetHeight + o.nTHead.offsetHeight)+"px";
  2773. }
  2774. /* Size the table as a whole */
  2775. iSanityWidth = $(o.nTable).outerWidth();
  2776. if ( o.oScroll.sX === "" )
  2777. {
  2778. /* No x scrolling */
  2779. o.nTable.style.width = "100%";
  2780. /* I know this is rubbish - but IE7 will make the width of the table when 100% include
  2781. * the scrollbar - which is shouldn't. When there is a scrollbar we need to take this
  2782. * into account.
  2783. */
  2784. if ( ie67 && ($('tbody', nScrollBody).height() > nScrollBody.offsetHeight ||
  2785. $(nScrollBody).css('overflow-y') == "scroll") )
  2786. {
  2787. o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth() - o.oScroll.iBarWidth);
  2788. }
  2789. }
  2790. else
  2791. {
  2792. if ( o.oScroll.sXInner !== "" )
  2793. {
  2794. /* x scroll inner has been given - use it */
  2795. o.nTable.style.width = _fnStringToCss(o.oScroll.sXInner);
  2796. }
  2797. else if ( iSanityWidth == $(nScrollBody).width() &&
  2798. $(nScrollBody).height() < $(o.nTable).height() )
  2799. {
  2800. /* There is y-scrolling - try to take account of the y scroll bar */
  2801. o.nTable.style.width = _fnStringToCss( iSanityWidth-o.oScroll.iBarWidth );
  2802. if ( $(o.nTable).outerWidth() > iSanityWidth-o.oScroll.iBarWidth )
  2803. {
  2804. /* Not possible to take account of it */
  2805. o.nTable.style.width = _fnStringToCss( iSanityWidth );
  2806. }
  2807. }
  2808. else
  2809. {
  2810. /* All else fails */
  2811. o.nTable.style.width = _fnStringToCss( iSanityWidth );
  2812. }
  2813. }
  2814. /* Recalculate the sanity width - now that we've applied the required width, before it was
  2815. * a temporary variable. This is required because the column width calculation is done
  2816. * before this table DOM is created.
  2817. */
  2818. iSanityWidth = $(o.nTable).outerWidth();
  2819. /* We want the hidden header to have zero height, so remove padding and borders. Then
  2820. * set the width based on the real headers
  2821. */
  2822. anHeadToSize = o.nTHead.getElementsByTagName('tr');
  2823. anHeadSizers = nTheadSize.getElementsByTagName('tr');
  2824. _fnApplyToChildren( function(nSizer, nToSize) {
  2825. oStyle = nSizer.style;
  2826. oStyle.paddingTop = "0";
  2827. oStyle.paddingBottom = "0";
  2828. oStyle.borderTopWidth = "0";
  2829. oStyle.borderBottomWidth = "0";
  2830. oStyle.height = 0;
  2831. iWidth = $(nSizer).width();
  2832. nToSize.style.width = _fnStringToCss( iWidth );
  2833. aApplied.push( iWidth );
  2834. }, anHeadSizers, anHeadToSize );
  2835. $(anHeadSizers).height(0);
  2836. if ( o.nTFoot !== null )
  2837. {
  2838. /* Clone the current footer and then place it into the body table as a "hidden header" */
  2839. anFootSizers = nTfootSize.getElementsByTagName('tr');
  2840. anFootToSize = o.nTFoot.getElementsByTagName('tr');
  2841. _fnApplyToChildren( function(nSizer, nToSize) {
  2842. oStyle = nSizer.style;
  2843. oStyle.paddingTop = "0";
  2844. oStyle.paddingBottom = "0";
  2845. oStyle.borderTopWidth = "0";
  2846. oStyle.borderBottomWidth = "0";
  2847. oStyle.height = 0;
  2848. iWidth = $(nSizer).width();
  2849. nToSize.style.width = _fnStringToCss( iWidth );
  2850. aApplied.push( iWidth );
  2851. }, anFootSizers, anFootToSize );
  2852. $(anFootSizers).height(0);
  2853. }
  2854. /*
  2855. * 3. Apply the measurements
  2856. */
  2857. /* "Hide" the header and footer that we used for the sizing. We want to also fix their width
  2858. * to what they currently are
  2859. */
  2860. _fnApplyToChildren( function(nSizer) {
  2861. nSizer.innerHTML = "";
  2862. nSizer.style.width = _fnStringToCss( aApplied.shift() );
  2863. }, anHeadSizers );
  2864. if ( o.nTFoot !== null )
  2865. {
  2866. _fnApplyToChildren( function(nSizer) {
  2867. nSizer.innerHTML = "";
  2868. nSizer.style.width = _fnStringToCss( aApplied.shift() );
  2869. }, anFootSizers );
  2870. }
  2871. /* Sanity check that the table is of a sensible width. If not then we are going to get
  2872. * misalignment - try to prevent this by not allowing the table to shrink below its min width
  2873. */
  2874. if ( $(o.nTable).outerWidth() < iSanityWidth )
  2875. {
  2876. /* The min width depends upon if we have a vertical scrollbar visible or not */
  2877. var iCorrection = ((nScrollBody.scrollHeight > nScrollBody.offsetHeight ||
  2878. $(nScrollBody).css('overflow-y') == "scroll")) ?
  2879. iSanityWidth+o.oScroll.iBarWidth : iSanityWidth;
  2880. /* IE6/7 are a law unto themselves... */
  2881. if ( ie67 && (nScrollBody.scrollHeight >
  2882. nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll") )
  2883. {
  2884. o.nTable.style.width = _fnStringToCss( iCorrection-o.oScroll.iBarWidth );
  2885. }
  2886. /* Apply the calculated minimum width to the table wrappers */
  2887. nScrollBody.style.width = _fnStringToCss( iCorrection );
  2888. nScrollHeadInner.parentNode.style.width = _fnStringToCss( iCorrection );
  2889. if ( o.nTFoot !== null )
  2890. {
  2891. nScrollFootInner.parentNode.style.width = _fnStringToCss( iCorrection );
  2892. }
  2893. /* And give the user a warning that we've stopped the table getting too small */
  2894. if ( o.oScroll.sX === "" )
  2895. {
  2896. _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
  2897. " misalignment. The table has been drawn at its minimum possible width." );
  2898. }
  2899. else if ( o.oScroll.sXInner !== "" )
  2900. {
  2901. _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
  2902. " misalignment. Increase the sScrollXInner value or remove it to allow automatic"+
  2903. " calculation" );
  2904. }
  2905. }
  2906. else
  2907. {
  2908. nScrollBody.style.width = _fnStringToCss( '100%' );
  2909. nScrollHeadInner.parentNode.style.width = _fnStringToCss( '100%' );
  2910. if ( o.nTFoot !== null )
  2911. {
  2912. nScrollFootInner.parentNode.style.width = _fnStringToCss( '100%' );
  2913. }
  2914. }
  2915. /*
  2916. * 4. Clean up
  2917. */
  2918. if ( o.oScroll.sY === "" )
  2919. {
  2920. /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
  2921. * the scrollbar height from the visible display, rather than adding it on. We need to
  2922. * set the height in order to sort this. Don't want to do it in any other browsers.
  2923. */
  2924. if ( ie67 )
  2925. {
  2926. nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+o.oScroll.iBarWidth );
  2927. }
  2928. }
  2929. if ( o.oScroll.sY !== "" && o.oScroll.bCollapse )
  2930. {
  2931. nScrollBody.style.height = _fnStringToCss( o.oScroll.sY );
  2932. var iExtra = (o.oScroll.sX !== "" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ?
  2933. o.oScroll.iBarWidth : 0;
  2934. if ( o.nTable.offsetHeight < nScrollBody.offsetHeight )
  2935. {
  2936. nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+iExtra );
  2937. }
  2938. }
  2939. /* Finally set the width's of the header and footer tables */
  2940. var iOuterWidth = $(o.nTable).outerWidth();
  2941. nScrollHeadTable.style.width = _fnStringToCss( iOuterWidth );
  2942. nScrollHeadInner.style.width = _fnStringToCss( iOuterWidth );
  2943. // Figure out if there are scrollbar present - if so then we need a the header and footer to
  2944. // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
  2945. var bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll";
  2946. nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
  2947. if ( o.nTFoot !== null )
  2948. {
  2949. nScrollFootTable.style.width = _fnStringToCss( iOuterWidth );
  2950. nScrollFootInner.style.width = _fnStringToCss( iOuterWidth );
  2951. nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
  2952. }
  2953. /* Adjust the position of the header incase we loose the y-scrollbar */
  2954. $(nScrollBody).scroll();
  2955. /* If sorting or filtering has occurred, jump the scrolling back to the top */
  2956. if ( o.bSorted || o.bFiltered )
  2957. {
  2958. nScrollBody.scrollTop = 0;
  2959. }
  2960. }
  2961. /**
  2962. * Apply a given function to the display child nodes of an element array (typically
  2963. * TD children of TR rows
  2964. * @param {function} fn Method to apply to the objects
  2965. * @param array {nodes} an1 List of elements to look through for display children
  2966. * @param array {nodes} an2 Another list (identical structure to the first) - optional
  2967. * @memberof DataTable#oApi
  2968. */
  2969. function _fnApplyToChildren( fn, an1, an2 )
  2970. {
  2971. for ( var i=0, iLen=an1.length ; i<iLen ; i++ )
  2972. {
  2973. for ( var j=0, jLen=an1[i].childNodes.length ; j<jLen ; j++ )
  2974. {
  2975. if ( an1[i].childNodes[j].nodeType == 1 )
  2976. {
  2977. if ( an2 )
  2978. {
  2979. fn( an1[i].childNodes[j], an2[i].childNodes[j] );
  2980. }
  2981. else
  2982. {
  2983. fn( an1[i].childNodes[j] );
  2984. }
  2985. }
  2986. }
  2987. }
  2988. }
  2989. /**
  2990. * Convert a CSS unit width to pixels (e.g. 2em)
  2991. * @param {string} sWidth width to be converted
  2992. * @param {node} nParent parent to get the with for (required for relative widths) - optional
  2993. * @returns {int} iWidth width in pixels
  2994. * @memberof DataTable#oApi
  2995. */
  2996. function _fnConvertToWidth ( sWidth, nParent )
  2997. {
  2998. if ( !sWidth || sWidth === null || sWidth === '' )
  2999. {
  3000. return 0;
  3001. }
  3002. if ( !nParent )
  3003. {
  3004. nParent = document.getElementsByTagName('body')[0];
  3005. }
  3006. var iWidth;
  3007. var nTmp = document.createElement( "div" );
  3008. nTmp.style.width = _fnStringToCss( sWidth );
  3009. nParent.appendChild( nTmp );
  3010. iWidth = nTmp.offsetWidth;
  3011. nParent.removeChild( nTmp );
  3012. return ( iWidth );
  3013. }
  3014. /**
  3015. * Calculate the width of columns for the table
  3016. * @param {object} oSettings dataTables settings object
  3017. * @memberof DataTable#oApi
  3018. */
  3019. function _fnCalculateColumnWidths ( oSettings )
  3020. {
  3021. var iTableWidth = oSettings.nTable.offsetWidth;
  3022. var iUserInputs = 0;
  3023. var iTmpWidth;
  3024. var iVisibleColumns = 0;
  3025. var iColums = oSettings.aoColumns.length;
  3026. var i, iIndex, iCorrector, iWidth;
  3027. var oHeaders = $('th', oSettings.nTHead);
  3028. var widthAttr = oSettings.nTable.getAttribute('width');
  3029. /* Convert any user input sizes into pixel sizes */
  3030. for ( i=0 ; i<iColums ; i++ )
  3031. {
  3032. if ( oSettings.aoColumns[i].bVisible )
  3033. {
  3034. iVisibleColumns++;
  3035. if ( oSettings.aoColumns[i].sWidth !== null )
  3036. {
  3037. iTmpWidth = _fnConvertToWidth( oSettings.aoColumns[i].sWidthOrig,
  3038. oSettings.nTable.parentNode );
  3039. if ( iTmpWidth !== null )
  3040. {
  3041. oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth );
  3042. }
  3043. iUserInputs++;
  3044. }
  3045. }
  3046. }
  3047. /* If the number of columns in the DOM equals the number that we have to process in
  3048. * DataTables, then we can use the offsets that are created by the web-browser. No custom
  3049. * sizes can be set in order for this to happen, nor scrolling used
  3050. */
  3051. if ( iColums == oHeaders.length && iUserInputs === 0 && iVisibleColumns == iColums &&
  3052. oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" )
  3053. {
  3054. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  3055. {
  3056. iTmpWidth = $(oHeaders[i]).width();
  3057. if ( iTmpWidth !== null )
  3058. {
  3059. oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth );
  3060. }
  3061. }
  3062. }
  3063. else
  3064. {
  3065. /* Otherwise we are going to have to do some calculations to get the width of each column.
  3066. * Construct a 1 row table with the widest node in the data, and any user defined widths,
  3067. * then insert it into the DOM and allow the browser to do all the hard work of
  3068. * calculating table widths.
  3069. */
  3070. var
  3071. nCalcTmp = oSettings.nTable.cloneNode( false ),
  3072. nTheadClone = oSettings.nTHead.cloneNode(true),
  3073. nBody = document.createElement( 'tbody' ),
  3074. nTr = document.createElement( 'tr' ),
  3075. nDivSizing;
  3076. nCalcTmp.removeAttribute( "id" );
  3077. nCalcTmp.appendChild( nTheadClone );
  3078. if ( oSettings.nTFoot !== null )
  3079. {
  3080. nCalcTmp.appendChild( oSettings.nTFoot.cloneNode(true) );
  3081. _fnApplyToChildren( function(n) {
  3082. n.style.width = "";
  3083. }, nCalcTmp.getElementsByTagName('tr') );
  3084. }
  3085. nCalcTmp.appendChild( nBody );
  3086. nBody.appendChild( nTr );
  3087. /* Remove any sizing that was previously applied by the styles */
  3088. var jqColSizing = $('thead th', nCalcTmp);
  3089. if ( jqColSizing.length === 0 )
  3090. {
  3091. jqColSizing = $('tbody tr:eq(0)>td', nCalcTmp);
  3092. }
  3093. /* Apply custom sizing to the cloned header */
  3094. var nThs = _fnGetUniqueThs( oSettings, nTheadClone );
  3095. iCorrector = 0;
  3096. for ( i=0 ; i<iColums ; i++ )
  3097. {
  3098. var oColumn = oSettings.aoColumns[i];
  3099. if ( oColumn.bVisible && oColumn.sWidthOrig !== null && oColumn.sWidthOrig !== "" )
  3100. {
  3101. nThs[i-iCorrector].style.width = _fnStringToCss( oColumn.sWidthOrig );
  3102. }
  3103. else if ( oColumn.bVisible )
  3104. {
  3105. nThs[i-iCorrector].style.width = "";
  3106. }
  3107. else
  3108. {
  3109. iCorrector++;
  3110. }
  3111. }
  3112. /* Find the biggest td for each column and put it into the table */
  3113. for ( i=0 ; i<iColums ; i++ )
  3114. {
  3115. if ( oSettings.aoColumns[i].bVisible )
  3116. {
  3117. var nTd = _fnGetWidestNode( oSettings, i );
  3118. if ( nTd !== null )
  3119. {
  3120. nTd = nTd.cloneNode(true);
  3121. if ( oSettings.aoColumns[i].sContentPadding !== "" )
  3122. {
  3123. nTd.innerHTML += oSettings.aoColumns[i].sContentPadding;
  3124. }
  3125. nTr.appendChild( nTd );
  3126. }
  3127. }
  3128. }
  3129. /* Build the table and 'display' it */
  3130. var nWrapper = oSettings.nTable.parentNode;
  3131. nWrapper.appendChild( nCalcTmp );
  3132. /* When scrolling (X or Y) we want to set the width of the table as appropriate. However,
  3133. * when not scrolling leave the table width as it is. This results in slightly different,
  3134. * but I think correct behaviour
  3135. */
  3136. if ( oSettings.oScroll.sX !== "" && oSettings.oScroll.sXInner !== "" )
  3137. {
  3138. nCalcTmp.style.width = _fnStringToCss(oSettings.oScroll.sXInner);
  3139. }
  3140. else if ( oSettings.oScroll.sX !== "" )
  3141. {
  3142. nCalcTmp.style.width = "";
  3143. if ( $(nCalcTmp).width() < nWrapper.offsetWidth )
  3144. {
  3145. nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth );
  3146. }
  3147. }
  3148. else if ( oSettings.oScroll.sY !== "" )
  3149. {
  3150. nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth );
  3151. }
  3152. else if ( widthAttr )
  3153. {
  3154. nCalcTmp.style.width = _fnStringToCss( widthAttr );
  3155. }
  3156. nCalcTmp.style.visibility = "hidden";
  3157. /* Scrolling considerations */
  3158. _fnScrollingWidthAdjust( oSettings, nCalcTmp );
  3159. /* Read the width's calculated by the browser and store them for use by the caller. We
  3160. * first of all try to use the elements in the body, but it is possible that there are
  3161. * no elements there, under which circumstances we use the header elements
  3162. */
  3163. var oNodes = $("tbody tr:eq(0)", nCalcTmp).children();
  3164. if ( oNodes.length === 0 )
  3165. {
  3166. oNodes = _fnGetUniqueThs( oSettings, $('thead', nCalcTmp)[0] );
  3167. }
  3168. /* Browsers need a bit of a hand when a width is assigned to any columns when
  3169. * x-scrolling as they tend to collapse the table to the min-width, even if
  3170. * we sent the column widths. So we need to keep track of what the table width
  3171. * should be by summing the user given values, and the automatic values
  3172. */
  3173. if ( oSettings.oScroll.sX !== "" )
  3174. {
  3175. var iTotal = 0;
  3176. iCorrector = 0;
  3177. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  3178. {
  3179. if ( oSettings.aoColumns[i].bVisible )
  3180. {
  3181. if ( oSettings.aoColumns[i].sWidthOrig === null )
  3182. {
  3183. iTotal += $(oNodes[iCorrector]).outerWidth();
  3184. }
  3185. else
  3186. {
  3187. iTotal += parseInt(oSettings.aoColumns[i].sWidth.replace('px',''), 10) +
  3188. ($(oNodes[iCorrector]).outerWidth() - $(oNodes[iCorrector]).width());
  3189. }
  3190. iCorrector++;
  3191. }
  3192. }
  3193. nCalcTmp.style.width = _fnStringToCss( iTotal );
  3194. oSettings.nTable.style.width = _fnStringToCss( iTotal );
  3195. }
  3196. iCorrector = 0;
  3197. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  3198. {
  3199. if ( oSettings.aoColumns[i].bVisible )
  3200. {
  3201. iWidth = $(oNodes[iCorrector]).width();
  3202. if ( iWidth !== null && iWidth > 0 )
  3203. {
  3204. oSettings.aoColumns[i].sWidth = _fnStringToCss( iWidth );
  3205. }
  3206. iCorrector++;
  3207. }
  3208. }
  3209. var cssWidth = $(nCalcTmp).css('width');
  3210. oSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ?
  3211. cssWidth : _fnStringToCss( $(nCalcTmp).outerWidth() );
  3212. nCalcTmp.parentNode.removeChild( nCalcTmp );
  3213. }
  3214. if ( widthAttr )
  3215. {
  3216. oSettings.nTable.style.width = _fnStringToCss( widthAttr );
  3217. }
  3218. }
  3219. /**
  3220. * Adjust a table's width to take account of scrolling
  3221. * @param {object} oSettings dataTables settings object
  3222. * @param {node} n table node
  3223. * @memberof DataTable#oApi
  3224. */
  3225. function _fnScrollingWidthAdjust ( oSettings, n )
  3226. {
  3227. if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "" )
  3228. {
  3229. /* When y-scrolling only, we want to remove the width of the scroll bar so the table
  3230. * + scroll bar will fit into the area avaialble.
  3231. */
  3232. var iOrigWidth = $(n).width();
  3233. n.style.width = _fnStringToCss( $(n).outerWidth()-oSettings.oScroll.iBarWidth );
  3234. }
  3235. else if ( oSettings.oScroll.sX !== "" )
  3236. {
  3237. /* When x-scrolling both ways, fix the table at it's current size, without adjusting */
  3238. n.style.width = _fnStringToCss( $(n).outerWidth() );
  3239. }
  3240. }
  3241. /**
  3242. * Get the widest node
  3243. * @param {object} oSettings dataTables settings object
  3244. * @param {int} iCol column of interest
  3245. * @returns {string} max strlens for each column
  3246. * @memberof DataTable#oApi
  3247. */
  3248. function _fnGetWidestNode( oSettings, iCol )
  3249. {
  3250. var iMaxIndex = _fnGetMaxLenString( oSettings, iCol );
  3251. if ( iMaxIndex < 0 )
  3252. {
  3253. return null;
  3254. }
  3255. if ( oSettings.aoData[iMaxIndex].nTr === null )
  3256. {
  3257. var n = document.createElement('td');
  3258. n.innerHTML = _fnGetCellData( oSettings, iMaxIndex, iCol, '' );
  3259. return n;
  3260. }
  3261. return _fnGetTdNodes(oSettings, iMaxIndex)[iCol];
  3262. }
  3263. /**
  3264. * Get the maximum strlen for each data column
  3265. * @param {object} oSettings dataTables settings object
  3266. * @param {int} iCol column of interest
  3267. * @returns {string} max strlens for each column
  3268. * @memberof DataTable#oApi
  3269. */
  3270. function _fnGetMaxLenString( oSettings, iCol )
  3271. {
  3272. var iMax = -1;
  3273. var iMaxIndex = -1;
  3274. for ( var i=0 ; i<oSettings.aoData.length ; i++ )
  3275. {
  3276. var s = _fnGetCellData( oSettings, i, iCol, 'display' )+"";
  3277. s = s.replace( /<.*?>/g, "" );
  3278. if ( s.length > iMax )
  3279. {
  3280. iMax = s.length;
  3281. iMaxIndex = i;
  3282. }
  3283. }
  3284. return iMaxIndex;
  3285. }
  3286. /**
  3287. * Append a CSS unit (only if required) to a string
  3288. * @param {array} aArray1 first array
  3289. * @param {array} aArray2 second array
  3290. * @returns {int} 0 if match, 1 if length is different, 2 if no match
  3291. * @memberof DataTable#oApi
  3292. */
  3293. function _fnStringToCss( s )
  3294. {
  3295. if ( s === null )
  3296. {
  3297. return "0px";
  3298. }
  3299. if ( typeof s == 'number' )
  3300. {
  3301. if ( s < 0 )
  3302. {
  3303. return "0px";
  3304. }
  3305. return s+"px";
  3306. }
  3307. /* Check if the last character is not 0-9 */
  3308. var c = s.charCodeAt( s.length-1 );
  3309. if (c < 0x30 || c > 0x39)
  3310. {
  3311. return s;
  3312. }
  3313. return s+"px";
  3314. }
  3315. /**
  3316. * Get the width of a scroll bar in this browser being used
  3317. * @returns {int} width in pixels
  3318. * @memberof DataTable#oApi
  3319. */
  3320. function _fnScrollBarWidth ()
  3321. {
  3322. var inner = document.createElement('p');
  3323. var style = inner.style;
  3324. style.width = "100%";
  3325. style.height = "200px";
  3326. style.padding = "0px";
  3327. var outer = document.createElement('div');
  3328. style = outer.style;
  3329. style.position = "absolute";
  3330. style.top = "0px";
  3331. style.left = "0px";
  3332. style.visibility = "hidden";
  3333. style.width = "200px";
  3334. style.height = "150px";
  3335. style.padding = "0px";
  3336. style.overflow = "hidden";
  3337. outer.appendChild(inner);
  3338. document.body.appendChild(outer);
  3339. var w1 = inner.offsetWidth;
  3340. outer.style.overflow = 'scroll';
  3341. var w2 = inner.offsetWidth;
  3342. if ( w1 == w2 )
  3343. {
  3344. w2 = outer.clientWidth;
  3345. }
  3346. document.body.removeChild(outer);
  3347. return (w1 - w2);
  3348. }
  3349. /**
  3350. * Change the order of the table
  3351. * @param {object} oSettings dataTables settings object
  3352. * @param {bool} bApplyClasses optional - should we apply classes or not
  3353. * @memberof DataTable#oApi
  3354. */
  3355. function _fnSort ( oSettings, bApplyClasses )
  3356. {
  3357. var
  3358. i, iLen, j, jLen, k, kLen,
  3359. sDataType, nTh,
  3360. aaSort = [],
  3361. aiOrig = [],
  3362. oSort = DataTable.ext.oSort,
  3363. aoData = oSettings.aoData,
  3364. aoColumns = oSettings.aoColumns,
  3365. oAria = oSettings.oLanguage.oAria;
  3366. /* No sorting required if server-side or no sorting array */
  3367. if ( !oSettings.oFeatures.bServerSide &&
  3368. (oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null) )
  3369. {
  3370. aaSort = ( oSettings.aaSortingFixed !== null ) ?
  3371. oSettings.aaSortingFixed.concat( oSettings.aaSorting ) :
  3372. oSettings.aaSorting.slice();
  3373. /* If there is a sorting data type, and a fuction belonging to it, then we need to
  3374. * get the data from the developer's function and apply it for this column
  3375. */
  3376. for ( i=0 ; i<aaSort.length ; i++ )
  3377. {
  3378. var iColumn = aaSort[i][0];
  3379. var iVisColumn = _fnColumnIndexToVisible( oSettings, iColumn );
  3380. sDataType = oSettings.aoColumns[ iColumn ].sSortDataType;
  3381. if ( DataTable.ext.afnSortData[sDataType] )
  3382. {
  3383. var aData = DataTable.ext.afnSortData[sDataType].call(
  3384. oSettings.oInstance, oSettings, iColumn, iVisColumn
  3385. );
  3386. if ( aData.length === aoData.length )
  3387. {
  3388. for ( j=0, jLen=aoData.length ; j<jLen ; j++ )
  3389. {
  3390. _fnSetCellData( oSettings, j, iColumn, aData[j] );
  3391. }
  3392. }
  3393. else
  3394. {
  3395. _fnLog( oSettings, 0, "Returned data sort array (col "+iColumn+") is the wrong length" );
  3396. }
  3397. }
  3398. }
  3399. /* Create a value - key array of the current row positions such that we can use their
  3400. * current position during the sort, if values match, in order to perform stable sorting
  3401. */
  3402. for ( i=0, iLen=oSettings.aiDisplayMaster.length ; i<iLen ; i++ )
  3403. {
  3404. aiOrig[ oSettings.aiDisplayMaster[i] ] = i;
  3405. }
  3406. /* Build an internal data array which is specific to the sort, so we can get and prep
  3407. * the data to be sorted only once, rather than needing to do it every time the sorting
  3408. * function runs. This make the sorting function a very simple comparison
  3409. */
  3410. var iSortLen = aaSort.length;
  3411. var fnSortFormat, aDataSort;
  3412. for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
  3413. {
  3414. for ( j=0 ; j<iSortLen ; j++ )
  3415. {
  3416. aDataSort = aoColumns[ aaSort[j][0] ].aDataSort;
  3417. for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
  3418. {
  3419. sDataType = aoColumns[ aDataSort[k] ].sType;
  3420. fnSortFormat = oSort[ (sDataType ? sDataType : 'string')+"-pre" ];
  3421. aoData[i]._aSortData[ aDataSort[k] ] = fnSortFormat ?
  3422. fnSortFormat( _fnGetCellData( oSettings, i, aDataSort[k], 'sort' ) ) :
  3423. _fnGetCellData( oSettings, i, aDataSort[k], 'sort' );
  3424. }
  3425. }
  3426. }
  3427. /* Do the sort - here we want multi-column sorting based on a given data source (column)
  3428. * and sorting function (from oSort) in a certain direction. It's reasonably complex to
  3429. * follow on it's own, but this is what we want (example two column sorting):
  3430. * fnLocalSorting = function(a,b){
  3431. * var iTest;
  3432. * iTest = oSort['string-asc']('data11', 'data12');
  3433. * if (iTest !== 0)
  3434. * return iTest;
  3435. * iTest = oSort['numeric-desc']('data21', 'data22');
  3436. * if (iTest !== 0)
  3437. * return iTest;
  3438. * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
  3439. * }
  3440. * Basically we have a test for each sorting column, if the data in that column is equal,
  3441. * test the next column. If all columns match, then we use a numeric sort on the row
  3442. * positions in the original data array to provide a stable sort.
  3443. */
  3444. oSettings.aiDisplayMaster.sort( function ( a, b ) {
  3445. var k, l, lLen, iTest, aDataSort, sDataType;
  3446. for ( k=0 ; k<iSortLen ; k++ )
  3447. {
  3448. aDataSort = aoColumns[ aaSort[k][0] ].aDataSort;
  3449. for ( l=0, lLen=aDataSort.length ; l<lLen ; l++ )
  3450. {
  3451. sDataType = aoColumns[ aDataSort[l] ].sType;
  3452. iTest = oSort[ (sDataType ? sDataType : 'string')+"-"+aaSort[k][1] ](
  3453. aoData[a]._aSortData[ aDataSort[l] ],
  3454. aoData[b]._aSortData[ aDataSort[l] ]
  3455. );
  3456. if ( iTest !== 0 )
  3457. {
  3458. return iTest;
  3459. }
  3460. }
  3461. }
  3462. return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
  3463. } );
  3464. }
  3465. /* Alter the sorting classes to take account of the changes */
  3466. if ( (bApplyClasses === undefined || bApplyClasses) && !oSettings.oFeatures.bDeferRender )
  3467. {
  3468. _fnSortingClasses( oSettings );
  3469. }
  3470. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  3471. {
  3472. var sTitle = aoColumns[i].sTitle.replace( /<.*?>/g, "" );
  3473. nTh = aoColumns[i].nTh;
  3474. nTh.removeAttribute('aria-sort');
  3475. nTh.removeAttribute('aria-label');
  3476. /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
  3477. if ( aoColumns[i].bSortable )
  3478. {
  3479. if ( aaSort.length > 0 && aaSort[0][0] == i )
  3480. {
  3481. nTh.setAttribute('aria-sort', aaSort[0][1]=="asc" ? "ascending" : "descending" );
  3482. var nextSort = (aoColumns[i].asSorting[ aaSort[0][2]+1 ]) ?
  3483. aoColumns[i].asSorting[ aaSort[0][2]+1 ] : aoColumns[i].asSorting[0];
  3484. nTh.setAttribute('aria-label', sTitle+
  3485. (nextSort=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
  3486. }
  3487. else
  3488. {
  3489. nTh.setAttribute('aria-label', sTitle+
  3490. (aoColumns[i].asSorting[0]=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
  3491. }
  3492. }
  3493. else
  3494. {
  3495. nTh.setAttribute('aria-label', sTitle);
  3496. }
  3497. }
  3498. /* Tell the draw function that we have sorted the data */
  3499. oSettings.bSorted = true;
  3500. $(oSettings.oInstance).trigger('sort', oSettings);
  3501. /* Copy the master data into the draw array and re-draw */
  3502. if ( oSettings.oFeatures.bFilter )
  3503. {
  3504. /* _fnFilter() will redraw the table for us */
  3505. _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
  3506. }
  3507. else
  3508. {
  3509. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  3510. oSettings._iDisplayStart = 0; /* reset display back to page 0 */
  3511. _fnCalculateEnd( oSettings );
  3512. _fnDraw( oSettings );
  3513. }
  3514. }
  3515. /**
  3516. * Attach a sort handler (click) to a node
  3517. * @param {object} oSettings dataTables settings object
  3518. * @param {node} nNode node to attach the handler to
  3519. * @param {int} iDataIndex column sorting index
  3520. * @param {function} [fnCallback] callback function
  3521. * @memberof DataTable#oApi
  3522. */
  3523. function _fnSortAttachListener ( oSettings, nNode, iDataIndex, fnCallback )
  3524. {
  3525. _fnBindAction( nNode, {}, function (e) {
  3526. /* If the column is not sortable - don't to anything */
  3527. if ( oSettings.aoColumns[iDataIndex].bSortable === false )
  3528. {
  3529. return;
  3530. }
  3531. /*
  3532. * This is a little bit odd I admit... I declare a temporary function inside the scope of
  3533. * _fnBuildHead and the click handler in order that the code presented here can be used
  3534. * twice - once for when bProcessing is enabled, and another time for when it is
  3535. * disabled, as we need to perform slightly different actions.
  3536. * Basically the issue here is that the Javascript engine in modern browsers don't
  3537. * appear to allow the rendering engine to update the display while it is still excuting
  3538. * it's thread (well - it does but only after long intervals). This means that the
  3539. * 'processing' display doesn't appear for a table sort. To break the js thread up a bit
  3540. * I force an execution break by using setTimeout - but this breaks the expected
  3541. * thread continuation for the end-developer's point of view (their code would execute
  3542. * too early), so we on;y do it when we absolutely have to.
  3543. */
  3544. var fnInnerSorting = function () {
  3545. var iColumn, iNextSort;
  3546. /* If the shift key is pressed then we are multipe column sorting */
  3547. if ( e.shiftKey )
  3548. {
  3549. /* Are we already doing some kind of sort on this column? */
  3550. var bFound = false;
  3551. for ( var i=0 ; i<oSettings.aaSorting.length ; i++ )
  3552. {
  3553. if ( oSettings.aaSorting[i][0] == iDataIndex )
  3554. {
  3555. bFound = true;
  3556. iColumn = oSettings.aaSorting[i][0];
  3557. iNextSort = oSettings.aaSorting[i][2]+1;
  3558. if ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] )
  3559. {
  3560. /* Reached the end of the sorting options, remove from multi-col sort */
  3561. oSettings.aaSorting.splice( i, 1 );
  3562. }
  3563. else
  3564. {
  3565. /* Move onto next sorting direction */
  3566. oSettings.aaSorting[i][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];
  3567. oSettings.aaSorting[i][2] = iNextSort;
  3568. }
  3569. break;
  3570. }
  3571. }
  3572. /* No sort yet - add it in */
  3573. if ( bFound === false )
  3574. {
  3575. oSettings.aaSorting.push( [ iDataIndex,
  3576. oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] );
  3577. }
  3578. }
  3579. else
  3580. {
  3581. /* If no shift key then single column sort */
  3582. if ( oSettings.aaSorting.length == 1 && oSettings.aaSorting[0][0] == iDataIndex )
  3583. {
  3584. iColumn = oSettings.aaSorting[0][0];
  3585. iNextSort = oSettings.aaSorting[0][2]+1;
  3586. if ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] )
  3587. {
  3588. iNextSort = 0;
  3589. }
  3590. oSettings.aaSorting[0][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];
  3591. oSettings.aaSorting[0][2] = iNextSort;
  3592. }
  3593. else
  3594. {
  3595. oSettings.aaSorting.splice( 0, oSettings.aaSorting.length );
  3596. oSettings.aaSorting.push( [ iDataIndex,
  3597. oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] );
  3598. }
  3599. }
  3600. /* Run the sort */
  3601. _fnSort( oSettings );
  3602. }; /* /fnInnerSorting */
  3603. if ( !oSettings.oFeatures.bProcessing )
  3604. {
  3605. fnInnerSorting();
  3606. }
  3607. else
  3608. {
  3609. _fnProcessingDisplay( oSettings, true );
  3610. setTimeout( function() {
  3611. fnInnerSorting();
  3612. if ( !oSettings.oFeatures.bServerSide )
  3613. {
  3614. _fnProcessingDisplay( oSettings, false );
  3615. }
  3616. }, 0 );
  3617. }
  3618. /* Call the user specified callback function - used for async user interaction */
  3619. if ( typeof fnCallback == 'function' )
  3620. {
  3621. fnCallback( oSettings );
  3622. }
  3623. } );
  3624. }
  3625. /**
  3626. * Set the sorting classes on the header, Note: it is safe to call this function
  3627. * when bSort and bSortClasses are false
  3628. * @param {object} oSettings dataTables settings object
  3629. * @memberof DataTable#oApi
  3630. */
  3631. function _fnSortingClasses( oSettings )
  3632. {
  3633. var i, iLen, j, jLen, iFound;
  3634. var aaSort, sClass;
  3635. var iColumns = oSettings.aoColumns.length;
  3636. var oClasses = oSettings.oClasses;
  3637. for ( i=0 ; i<iColumns ; i++ )
  3638. {
  3639. if ( oSettings.aoColumns[i].bSortable )
  3640. {
  3641. $(oSettings.aoColumns[i].nTh).removeClass( oClasses.sSortAsc +" "+ oClasses.sSortDesc +
  3642. " "+ oSettings.aoColumns[i].sSortingClass );
  3643. }
  3644. }
  3645. if ( oSettings.aaSortingFixed !== null )
  3646. {
  3647. aaSort = oSettings.aaSortingFixed.concat( oSettings.aaSorting );
  3648. }
  3649. else
  3650. {
  3651. aaSort = oSettings.aaSorting.slice();
  3652. }
  3653. /* Apply the required classes to the header */
  3654. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  3655. {
  3656. if ( oSettings.aoColumns[i].bSortable )
  3657. {
  3658. sClass = oSettings.aoColumns[i].sSortingClass;
  3659. iFound = -1;
  3660. for ( j=0 ; j<aaSort.length ; j++ )
  3661. {
  3662. if ( aaSort[j][0] == i )
  3663. {
  3664. sClass = ( aaSort[j][1] == "asc" ) ?
  3665. oClasses.sSortAsc : oClasses.sSortDesc;
  3666. iFound = j;
  3667. break;
  3668. }
  3669. }
  3670. $(oSettings.aoColumns[i].nTh).addClass( sClass );
  3671. if ( oSettings.bJUI )
  3672. {
  3673. /* jQuery UI uses extra markup */
  3674. var jqSpan = $("span."+oClasses.sSortIcon, oSettings.aoColumns[i].nTh);
  3675. jqSpan.removeClass(oClasses.sSortJUIAsc +" "+ oClasses.sSortJUIDesc +" "+
  3676. oClasses.sSortJUI +" "+ oClasses.sSortJUIAscAllowed +" "+ oClasses.sSortJUIDescAllowed );
  3677. var sSpanClass;
  3678. if ( iFound == -1 )
  3679. {
  3680. sSpanClass = oSettings.aoColumns[i].sSortingClassJUI;
  3681. }
  3682. else if ( aaSort[iFound][1] == "asc" )
  3683. {
  3684. sSpanClass = oClasses.sSortJUIAsc;
  3685. }
  3686. else
  3687. {
  3688. sSpanClass = oClasses.sSortJUIDesc;
  3689. }
  3690. jqSpan.addClass( sSpanClass );
  3691. }
  3692. }
  3693. else
  3694. {
  3695. /* No sorting on this column, so add the base class. This will have been assigned by
  3696. * _fnAddColumn
  3697. */
  3698. $(oSettings.aoColumns[i].nTh).addClass( oSettings.aoColumns[i].sSortingClass );
  3699. }
  3700. }
  3701. /*
  3702. * Apply the required classes to the table body
  3703. * Note that this is given as a feature switch since it can significantly slow down a sort
  3704. * on large data sets (adding and removing of classes is always slow at the best of times..)
  3705. * Further to this, note that this code is admitadly fairly ugly. It could be made a lot
  3706. * simpiler using jQuery selectors and add/removeClass, but that is significantly slower
  3707. * (on the order of 5 times slower) - hence the direct DOM manipulation here.
  3708. * Note that for defered drawing we do use jQuery - the reason being that taking the first
  3709. * row found to see if the whole column needs processed can miss classes since the first
  3710. * column might be new.
  3711. */
  3712. sClass = oClasses.sSortColumn;
  3713. if ( oSettings.oFeatures.bSort && oSettings.oFeatures.bSortClasses )
  3714. {
  3715. var nTds = _fnGetTdNodes( oSettings );
  3716. /* Remove the old classes */
  3717. if ( oSettings.oFeatures.bDeferRender )
  3718. {
  3719. $(nTds).removeClass(sClass+'1 '+sClass+'2 '+sClass+'3');
  3720. }
  3721. else if ( nTds.length >= iColumns )
  3722. {
  3723. for ( i=0 ; i<iColumns ; i++ )
  3724. {
  3725. if ( nTds[i].className.indexOf(sClass+"1") != -1 )
  3726. {
  3727. for ( j=0, jLen=(nTds.length/iColumns) ; j<jLen ; j++ )
  3728. {
  3729. nTds[(iColumns*j)+i].className =
  3730. $.trim( nTds[(iColumns*j)+i].className.replace( sClass+"1", "" ) );
  3731. }
  3732. }
  3733. else if ( nTds[i].className.indexOf(sClass+"2") != -1 )
  3734. {
  3735. for ( j=0, jLen=(nTds.length/iColumns) ; j<jLen ; j++ )
  3736. {
  3737. nTds[(iColumns*j)+i].className =
  3738. $.trim( nTds[(iColumns*j)+i].className.replace( sClass+"2", "" ) );
  3739. }
  3740. }
  3741. else if ( nTds[i].className.indexOf(sClass+"3") != -1 )
  3742. {
  3743. for ( j=0, jLen=(nTds.length/iColumns) ; j<jLen ; j++ )
  3744. {
  3745. nTds[(iColumns*j)+i].className =
  3746. $.trim( nTds[(iColumns*j)+i].className.replace( " "+sClass+"3", "" ) );
  3747. }
  3748. }
  3749. }
  3750. }
  3751. /* Add the new classes to the table */
  3752. var iClass = 1, iTargetCol;
  3753. for ( i=0 ; i<aaSort.length ; i++ )
  3754. {
  3755. iTargetCol = parseInt( aaSort[i][0], 10 );
  3756. for ( j=0, jLen=(nTds.length/iColumns) ; j<jLen ; j++ )
  3757. {
  3758. nTds[(iColumns*j)+iTargetCol].className += " "+sClass+iClass;
  3759. }
  3760. if ( iClass < 3 )
  3761. {
  3762. iClass++;
  3763. }
  3764. }
  3765. }
  3766. }
  3767. /**
  3768. * Save the state of a table in a cookie such that the page can be reloaded
  3769. * @param {object} oSettings dataTables settings object
  3770. * @memberof DataTable#oApi
  3771. */
  3772. function _fnSaveState ( oSettings )
  3773. {
  3774. if ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying )
  3775. {
  3776. return;
  3777. }
  3778. /* Store the interesting variables */
  3779. var i, iLen, bInfinite=oSettings.oScroll.bInfinite;
  3780. var oState = {
  3781. "iCreate": new Date().getTime(),
  3782. "iStart": (bInfinite ? 0 : oSettings._iDisplayStart),
  3783. "iEnd": (bInfinite ? oSettings._iDisplayLength : oSettings._iDisplayEnd),
  3784. "iLength": oSettings._iDisplayLength,
  3785. "aaSorting": $.extend( true, [], oSettings.aaSorting ),
  3786. "oSearch": $.extend( true, {}, oSettings.oPreviousSearch ),
  3787. "aoSearchCols": $.extend( true, [], oSettings.aoPreSearchCols ),
  3788. "abVisCols": []
  3789. };
  3790. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  3791. {
  3792. oState.abVisCols.push( oSettings.aoColumns[i].bVisible );
  3793. }
  3794. _fnCallbackFire( oSettings, "aoStateSaveParams", 'stateSaveParams', [oSettings, oState] );
  3795. oSettings.fnStateSave.call( oSettings.oInstance, oSettings, oState );
  3796. }
  3797. /**
  3798. * Attempt to load a saved table state from a cookie
  3799. * @param {object} oSettings dataTables settings object
  3800. * @param {object} oInit DataTables init object so we can override settings
  3801. * @memberof DataTable#oApi
  3802. */
  3803. function _fnLoadState ( oSettings, oInit )
  3804. {
  3805. if ( !oSettings.oFeatures.bStateSave )
  3806. {
  3807. return;
  3808. }
  3809. var oData = oSettings.fnStateLoad.call( oSettings.oInstance, oSettings );
  3810. if ( !oData )
  3811. {
  3812. return;
  3813. }
  3814. /* Allow custom and plug-in manipulation functions to alter the saved data set and
  3815. * cancelling of loading by returning false
  3816. */
  3817. var abStateLoad = _fnCallbackFire( oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData] );
  3818. if ( $.inArray( false, abStateLoad ) !== -1 )
  3819. {
  3820. return;
  3821. }
  3822. /* Store the saved state so it might be accessed at any time */
  3823. oSettings.oLoadedState = $.extend( true, {}, oData );
  3824. /* Restore key features */
  3825. oSettings._iDisplayStart = oData.iStart;
  3826. oSettings.iInitDisplayStart = oData.iStart;
  3827. oSettings._iDisplayEnd = oData.iEnd;
  3828. oSettings._iDisplayLength = oData.iLength;
  3829. oSettings.aaSorting = oData.aaSorting.slice();
  3830. oSettings.saved_aaSorting = oData.aaSorting.slice();
  3831. /* Search filtering */
  3832. $.extend( oSettings.oPreviousSearch, oData.oSearch );
  3833. $.extend( true, oSettings.aoPreSearchCols, oData.aoSearchCols );
  3834. /* Column visibility state
  3835. * Pass back visibiliy settings to the init handler, but to do not here override
  3836. * the init object that the user might have passed in
  3837. */
  3838. oInit.saved_aoColumns = [];
  3839. for ( var i=0 ; i<oData.abVisCols.length ; i++ )
  3840. {
  3841. oInit.saved_aoColumns[i] = {};
  3842. oInit.saved_aoColumns[i].bVisible = oData.abVisCols[i];
  3843. }
  3844. _fnCallbackFire( oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData] );
  3845. }
  3846. /**
  3847. * Create a new cookie with a value to store the state of a table
  3848. * @param {string} sName name of the cookie to create
  3849. * @param {string} sValue the value the cookie should take
  3850. * @param {int} iSecs duration of the cookie
  3851. * @param {string} sBaseName sName is made up of the base + file name - this is the base
  3852. * @param {function} fnCallback User definable function to modify the cookie
  3853. * @memberof DataTable#oApi
  3854. */
  3855. function _fnCreateCookie ( sName, sValue, iSecs, sBaseName, fnCallback )
  3856. {
  3857. var date = new Date();
  3858. date.setTime( date.getTime()+(iSecs*1000) );
  3859. /*
  3860. * Shocking but true - it would appear IE has major issues with having the path not having
  3861. * a trailing slash on it. We need the cookie to be available based on the path, so we
  3862. * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the
  3863. * patch to use at least some of the path
  3864. */
  3865. var aParts = window.location.pathname.split('/');
  3866. var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g,"").toLowerCase();
  3867. var sFullCookie, oData;
  3868. if ( fnCallback !== null )
  3869. {
  3870. oData = (typeof $.parseJSON === 'function') ?
  3871. $.parseJSON( sValue ) : eval( '('+sValue+')' );
  3872. sFullCookie = fnCallback( sNameFile, oData, date.toGMTString(),
  3873. aParts.join('/')+"/" );
  3874. }
  3875. else
  3876. {
  3877. sFullCookie = sNameFile + "=" + encodeURIComponent(sValue) +
  3878. "; expires=" + date.toGMTString() +"; path=" + aParts.join('/')+"/";
  3879. }
  3880. /* Are we going to go over the cookie limit of 4KiB? If so, try to delete a cookies
  3881. * belonging to DataTables. This is FAR from bullet proof
  3882. */
  3883. var sOldName="", iOldTime=9999999999999;
  3884. var iLength = _fnReadCookie( sNameFile )!==null ? document.cookie.length :
  3885. sFullCookie.length + document.cookie.length;
  3886. if ( iLength+10 > 4096 ) /* Magic 10 for padding */
  3887. {
  3888. var aCookies =document.cookie.split(';');
  3889. for ( var i=0, iLen=aCookies.length ; i<iLen ; i++ )
  3890. {
  3891. if ( aCookies[i].indexOf( sBaseName ) != -1 )
  3892. {
  3893. /* It's a DataTables cookie, so eval it and check the time stamp */
  3894. var aSplitCookie = aCookies[i].split('=');
  3895. try { oData = eval( '('+decodeURIComponent(aSplitCookie[1])+')' ); }
  3896. catch( e ) { continue; }
  3897. if ( oData.iCreate && oData.iCreate < iOldTime )
  3898. {
  3899. sOldName = aSplitCookie[0];
  3900. iOldTime = oData.iCreate;
  3901. }
  3902. }
  3903. }
  3904. if ( sOldName !== "" )
  3905. {
  3906. document.cookie = sOldName+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+
  3907. aParts.join('/') + "/";
  3908. }
  3909. }
  3910. document.cookie = sFullCookie;
  3911. }
  3912. /**
  3913. * Read an old cookie to get a cookie with an old table state
  3914. * @param {string} sName name of the cookie to read
  3915. * @returns {string} contents of the cookie - or null if no cookie with that name found
  3916. * @memberof DataTable#oApi
  3917. */
  3918. function _fnReadCookie ( sName )
  3919. {
  3920. var
  3921. aParts = window.location.pathname.split('/'),
  3922. sNameEQ = sName + '_' + aParts[aParts.length-1].replace(/[\/:]/g,"").toLowerCase() + '=',
  3923. sCookieContents = document.cookie.split(';');
  3924. for( var i=0 ; i<sCookieContents.length ; i++ )
  3925. {
  3926. var c = sCookieContents[i];
  3927. while (c.charAt(0)==' ')
  3928. {
  3929. c = c.substring(1,c.length);
  3930. }
  3931. if (c.indexOf(sNameEQ) === 0)
  3932. {
  3933. return decodeURIComponent( c.substring(sNameEQ.length,c.length) );
  3934. }
  3935. }
  3936. return null;
  3937. }
  3938. /**
  3939. * Return the settings object for a particular table
  3940. * @param {node} nTable table we are using as a dataTable
  3941. * @returns {object} Settings object - or null if not found
  3942. * @memberof DataTable#oApi
  3943. */
  3944. function _fnSettingsFromNode ( nTable )
  3945. {
  3946. for ( var i=0 ; i<DataTable.settings.length ; i++ )
  3947. {
  3948. if ( DataTable.settings[i].nTable === nTable )
  3949. {
  3950. return DataTable.settings[i];
  3951. }
  3952. }
  3953. return null;
  3954. }
  3955. /**
  3956. * Return an array with the TR nodes for the table
  3957. * @param {object} oSettings dataTables settings object
  3958. * @returns {array} TR array
  3959. * @memberof DataTable#oApi
  3960. */
  3961. function _fnGetTrNodes ( oSettings )
  3962. {
  3963. var aNodes = [];
  3964. var aoData = oSettings.aoData;
  3965. for ( var i=0, iLen=aoData.length ; i<iLen ; i++ )
  3966. {
  3967. if ( aoData[i].nTr !== null )
  3968. {
  3969. aNodes.push( aoData[i].nTr );
  3970. }
  3971. }
  3972. return aNodes;
  3973. }
  3974. /**
  3975. * Return an flat array with all TD nodes for the table, or row
  3976. * @param {object} oSettings dataTables settings object
  3977. * @param {int} [iIndividualRow] aoData index to get the nodes for - optional
  3978. * if not given then the return array will contain all nodes for the table
  3979. * @returns {array} TD array
  3980. * @memberof DataTable#oApi
  3981. */
  3982. function _fnGetTdNodes ( oSettings, iIndividualRow )
  3983. {
  3984. var anReturn = [];
  3985. var iCorrector;
  3986. var anTds;
  3987. var iRow, iRows=oSettings.aoData.length,
  3988. iColumn, iColumns, oData, sNodeName, iStart=0, iEnd=iRows;
  3989. /* Allow the collection to be limited to just one row */
  3990. if ( iIndividualRow !== undefined )
  3991. {
  3992. iStart = iIndividualRow;
  3993. iEnd = iIndividualRow+1;
  3994. }
  3995. for ( iRow=iStart ; iRow<iEnd ; iRow++ )
  3996. {
  3997. oData = oSettings.aoData[iRow];
  3998. if ( oData.nTr !== null )
  3999. {
  4000. /* get the TD child nodes - taking into account text etc nodes */
  4001. anTds = [];
  4002. for ( iColumn=0, iColumns=oData.nTr.childNodes.length ; iColumn<iColumns ; iColumn++ )
  4003. {
  4004. sNodeName = oData.nTr.childNodes[iColumn].nodeName.toLowerCase();
  4005. if ( sNodeName == 'td' || sNodeName == 'th' )
  4006. {
  4007. anTds.push( oData.nTr.childNodes[iColumn] );
  4008. }
  4009. }
  4010. iCorrector = 0;
  4011. for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ )
  4012. {
  4013. if ( oSettings.aoColumns[iColumn].bVisible )
  4014. {
  4015. anReturn.push( anTds[iColumn-iCorrector] );
  4016. }
  4017. else
  4018. {
  4019. anReturn.push( oData._anHidden[iColumn] );
  4020. iCorrector++;
  4021. }
  4022. }
  4023. }
  4024. }
  4025. return anReturn;
  4026. }
  4027. /**
  4028. * Log an error message
  4029. * @param {object} oSettings dataTables settings object
  4030. * @param {int} iLevel log error messages, or display them to the user
  4031. * @param {string} sMesg error message
  4032. * @memberof DataTable#oApi
  4033. */
  4034. function _fnLog( oSettings, iLevel, sMesg )
  4035. {
  4036. var sAlert = (oSettings===null) ?
  4037. "DataTables warning: "+sMesg :
  4038. "DataTables warning (table id = '"+oSettings.sTableId+"'): "+sMesg;
  4039. if ( iLevel === 0 )
  4040. {
  4041. if ( DataTable.ext.sErrMode == 'alert' )
  4042. {
  4043. alert( sAlert );
  4044. }
  4045. else
  4046. {
  4047. throw new Error(sAlert);
  4048. }
  4049. return;
  4050. }
  4051. else if ( window.console && console.log )
  4052. {
  4053. console.log( sAlert );
  4054. }
  4055. }
  4056. /**
  4057. * See if a property is defined on one object, if so assign it to the other object
  4058. * @param {object} oRet target object
  4059. * @param {object} oSrc source object
  4060. * @param {string} sName property
  4061. * @param {string} [sMappedName] name to map too - optional, sName used if not given
  4062. * @memberof DataTable#oApi
  4063. */
  4064. function _fnMap( oRet, oSrc, sName, sMappedName )
  4065. {
  4066. if ( sMappedName === undefined )
  4067. {
  4068. sMappedName = sName;
  4069. }
  4070. if ( oSrc[sName] !== undefined )
  4071. {
  4072. oRet[sMappedName] = oSrc[sName];
  4073. }
  4074. }
  4075. /**
  4076. * Extend objects - very similar to jQuery.extend, but deep copy objects, and shallow
  4077. * copy arrays. The reason we need to do this, is that we don't want to deep copy array
  4078. * init values (such as aaSorting) since the dev wouldn't be able to override them, but
  4079. * we do want to deep copy arrays.
  4080. * @param {object} oOut Object to extend
  4081. * @param {object} oExtender Object from which the properties will be applied to oOut
  4082. * @returns {object} oOut Reference, just for convenience - oOut === the return.
  4083. * @memberof DataTable#oApi
  4084. * @todo This doesn't take account of arrays inside the deep copied objects.
  4085. */
  4086. function _fnExtend( oOut, oExtender )
  4087. {
  4088. for ( var prop in oExtender )
  4089. {
  4090. if ( oExtender.hasOwnProperty(prop) )
  4091. {
  4092. if ( typeof oInit[prop] === 'object' && $.isArray(oExtender[prop]) === false )
  4093. {
  4094. $.extend( true, oOut[prop], oExtender[prop] );
  4095. }
  4096. else
  4097. {
  4098. oOut[prop] = oExtender[prop];
  4099. }
  4100. }
  4101. }
  4102. return oOut;
  4103. }
  4104. /**
  4105. * Bind an event handers to allow a click or return key to activate the callback.
  4106. * This is good for accessability since a return on the keyboard will have the
  4107. * same effect as a click, if the element has focus.
  4108. * @param {element} n Element to bind the action to
  4109. * @param {object} oData Data object to pass to the triggered function
  4110. * @param {function} fn Callback function for when the event is triggered
  4111. * @memberof DataTable#oApi
  4112. */
  4113. function _fnBindAction( n, oData, fn )
  4114. {
  4115. $(n)
  4116. .bind( 'click.DT', oData, function (e) {
  4117. n.blur(); // Remove focus outline for mouse users
  4118. fn(e);
  4119. } )
  4120. .bind( 'keypress.DT', oData, function (e){
  4121. if ( e.which === 13 ) {
  4122. fn(e);
  4123. } } )
  4124. .bind( 'selectstart.DT', function () {
  4125. /* Take the brutal approach to cancelling text selection */
  4126. return false;
  4127. } );
  4128. }
  4129. /**
  4130. * Register a callback function. Easily allows a callback function to be added to
  4131. * an array store of callback functions that can then all be called together.
  4132. * @param {object} oSettings dataTables settings object
  4133. * @param {string} sStore Name of the array storeage for the callbacks in oSettings
  4134. * @param {function} fn Function to be called back
  4135. * @param {string} sName Identifying name for the callback (i.e. a label)
  4136. * @memberof DataTable#oApi
  4137. */
  4138. function _fnCallbackReg( oSettings, sStore, fn, sName )
  4139. {
  4140. if ( fn )
  4141. {
  4142. oSettings[sStore].push( {
  4143. "fn": fn,
  4144. "sName": sName
  4145. } );
  4146. }
  4147. }
  4148. /**
  4149. * Fire callback functions and trigger events. Note that the loop over the callback
  4150. * array store is done backwards! Further note that you do not want to fire off triggers
  4151. * in time sensitive applications (for example cell creation) as its slow.
  4152. * @param {object} oSettings dataTables settings object
  4153. * @param {string} sStore Name of the array storeage for the callbacks in oSettings
  4154. * @param {string} sTrigger Name of the jQuery custom event to trigger. If null no trigger
  4155. * is fired
  4156. * @param {array} aArgs Array of arguments to pass to the callback function / trigger
  4157. * @memberof DataTable#oApi
  4158. */
  4159. function _fnCallbackFire( oSettings, sStore, sTrigger, aArgs )
  4160. {
  4161. var aoStore = oSettings[sStore];
  4162. var aRet =[];
  4163. for ( var i=aoStore.length-1 ; i>=0 ; i-- )
  4164. {
  4165. aRet.push( aoStore[i].fn.apply( oSettings.oInstance, aArgs ) );
  4166. }
  4167. if ( sTrigger !== null )
  4168. {
  4169. $(oSettings.oInstance).trigger(sTrigger, aArgs);
  4170. }
  4171. return aRet;
  4172. }
  4173. /**
  4174. * JSON stringify. If JSON.stringify it provided by the browser, json2.js or any other
  4175. * library, then we use that as it is fast, safe and accurate. If the function isn't
  4176. * available then we need to built it ourselves - the insperation for this function comes
  4177. * from Craig Buckler ( http://www.sitepoint.com/javascript-json-serialization/ ). It is
  4178. * not perfect and absolutely should not be used as a replacement to json2.js - but it does
  4179. * do what we need, without requiring a dependency for DataTables.
  4180. * @param {object} o JSON object to be converted
  4181. * @returns {string} JSON string
  4182. * @memberof DataTable#oApi
  4183. */
  4184. var _fnJsonString = (window.JSON) ? JSON.stringify : function( o )
  4185. {
  4186. /* Not an object or array */
  4187. var sType = typeof o;
  4188. if (sType !== "object" || o === null)
  4189. {
  4190. // simple data type
  4191. if (sType === "string")
  4192. {
  4193. o = '"'+o+'"';
  4194. }
  4195. return o+"";
  4196. }
  4197. /* If object or array, need to recurse over it */
  4198. var
  4199. sProp, mValue,
  4200. json = [],
  4201. bArr = $.isArray(o);
  4202. for (sProp in o)
  4203. {
  4204. mValue = o[sProp];
  4205. sType = typeof mValue;
  4206. if (sType === "string")
  4207. {
  4208. mValue = '"'+mValue+'"';
  4209. }
  4210. else if (sType === "object" && mValue !== null)
  4211. {
  4212. mValue = _fnJsonString(mValue);
  4213. }
  4214. json.push((bArr ? "" : '"'+sProp+'":') + mValue);
  4215. }
  4216. return (bArr ? "[" : "{") + json + (bArr ? "]" : "}");
  4217. };
  4218. /**
  4219. * Perform a jQuery selector action on the table's TR elements (from the tbody) and
  4220. * return the resulting jQuery object.
  4221. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  4222. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  4223. * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
  4224. * criterion ("applied") or all TR elements (i.e. no filter).
  4225. * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
  4226. * Can be either 'current', whereby the current sorting of the table is used, or
  4227. * 'original' whereby the original order the data was read into the table is used.
  4228. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  4229. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  4230. * 'current' and filter is 'applied', regardless of what they might be given as.
  4231. * @returns {object} jQuery object, filtered by the given selector.
  4232. * @dtopt API
  4233. *
  4234. * @example
  4235. * $(document).ready(function() {
  4236. * var oTable = $('#example').dataTable();
  4237. *
  4238. * // Highlight every second row
  4239. * oTable.$('tr:odd').css('backgroundColor', 'blue');
  4240. * } );
  4241. *
  4242. * @example
  4243. * $(document).ready(function() {
  4244. * var oTable = $('#example').dataTable();
  4245. *
  4246. * // Filter to rows with 'Webkit' in them, add a background colour and then
  4247. * // remove the filter, thus highlighting the 'Webkit' rows only.
  4248. * oTable.fnFilter('Webkit');
  4249. * oTable.$('tr', {"filter": "applied"}).css('backgroundColor', 'blue');
  4250. * oTable.fnFilter('');
  4251. * } );
  4252. */
  4253. this.$ = function ( sSelector, oOpts )
  4254. {
  4255. var i, iLen, a = [], tr;
  4256. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4257. var aoData = oSettings.aoData;
  4258. var aiDisplay = oSettings.aiDisplay;
  4259. var aiDisplayMaster = oSettings.aiDisplayMaster;
  4260. if ( !oOpts )
  4261. {
  4262. oOpts = {};
  4263. }
  4264. oOpts = $.extend( {}, {
  4265. "filter": "none", // applied
  4266. "order": "current", // "original"
  4267. "page": "all" // current
  4268. }, oOpts );
  4269. // Current page implies that order=current and fitler=applied, since it is fairly
  4270. // senseless otherwise
  4271. if ( oOpts.page == 'current' )
  4272. {
  4273. for ( i=oSettings._iDisplayStart, iLen=oSettings.fnDisplayEnd() ; i<iLen ; i++ )
  4274. {
  4275. tr = aoData[ aiDisplay[i] ].nTr;
  4276. if ( tr )
  4277. {
  4278. a.push( tr );
  4279. }
  4280. }
  4281. }
  4282. else if ( oOpts.order == "current" && oOpts.filter == "none" )
  4283. {
  4284. for ( i=0, iLen=aiDisplayMaster.length ; i<iLen ; i++ )
  4285. {
  4286. tr = aoData[ aiDisplayMaster[i] ].nTr;
  4287. if ( tr )
  4288. {
  4289. a.push( tr );
  4290. }
  4291. }
  4292. }
  4293. else if ( oOpts.order == "current" && oOpts.filter == "applied" )
  4294. {
  4295. for ( i=0, iLen=aiDisplay.length ; i<iLen ; i++ )
  4296. {
  4297. tr = aoData[ aiDisplay[i] ].nTr;
  4298. if ( tr )
  4299. {
  4300. a.push( tr );
  4301. }
  4302. }
  4303. }
  4304. else if ( oOpts.order == "original" && oOpts.filter == "none" )
  4305. {
  4306. for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
  4307. {
  4308. tr = aoData[ i ].nTr ;
  4309. if ( tr )
  4310. {
  4311. a.push( tr );
  4312. }
  4313. }
  4314. }
  4315. else if ( oOpts.order == "original" && oOpts.filter == "applied" )
  4316. {
  4317. for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
  4318. {
  4319. tr = aoData[ i ].nTr;
  4320. if ( $.inArray( i, aiDisplay ) !== -1 && tr )
  4321. {
  4322. a.push( tr );
  4323. }
  4324. }
  4325. }
  4326. else
  4327. {
  4328. _fnLog( oSettings, 1, "Unknown selection options" );
  4329. }
  4330. /* We need to filter on the TR elements and also 'find' in their descendants
  4331. * to make the selector act like it would in a full table - so we need
  4332. * to build both results and then combine them together
  4333. */
  4334. var jqA = $(a);
  4335. var jqTRs = jqA.filter( sSelector );
  4336. var jqDescendants = jqA.find( sSelector );
  4337. return $( [].concat($.makeArray(jqTRs), $.makeArray(jqDescendants)) );
  4338. };
  4339. /**
  4340. * Almost identical to $ in operation, but in this case returns the data for the matched
  4341. * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
  4342. * rather than any decendents, so the data can be obtained for the row/cell. If matching
  4343. * rows are found, the data returned is the original data array/object that was used to
  4344. * create the row (or a generated array if from a DOM source).
  4345. *
  4346. * This method is often useful incombination with $ where both functions are given the
  4347. * same parameters and the array indexes will match identically.
  4348. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  4349. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  4350. * @param {string} [oOpts.filter=none] Select elements that meet the current filter
  4351. * criterion ("applied") or all elements (i.e. no filter).
  4352. * @param {string} [oOpts.order=current] Order of the data in the processed array.
  4353. * Can be either 'current', whereby the current sorting of the table is used, or
  4354. * 'original' whereby the original order the data was read into the table is used.
  4355. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  4356. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  4357. * 'current' and filter is 'applied', regardless of what they might be given as.
  4358. * @returns {array} Data for the matched elements. If any elements, as a result of the
  4359. * selector, were not TR, TD or TH elements in the DataTable, they will have a null
  4360. * entry in the array.
  4361. * @dtopt API
  4362. *
  4363. * @example
  4364. * $(document).ready(function() {
  4365. * var oTable = $('#example').dataTable();
  4366. *
  4367. * // Get the data from the first row in the table
  4368. * var data = oTable._('tr:first');
  4369. *
  4370. * // Do something useful with the data
  4371. * alert( "First cell is: "+data[0] );
  4372. * } );
  4373. *
  4374. * @example
  4375. * $(document).ready(function() {
  4376. * var oTable = $('#example').dataTable();
  4377. *
  4378. * // Filter to 'Webkit' and get all data for
  4379. * oTable.fnFilter('Webkit');
  4380. * var data = oTable._('tr', {"filter": "applied"});
  4381. *
  4382. * // Do something with the data
  4383. * alert( data.length+" rows matched the filter" );
  4384. * } );
  4385. */
  4386. this._ = function ( sSelector, oOpts )
  4387. {
  4388. var aOut = [];
  4389. var i, iLen, iIndex;
  4390. var aTrs = this.$( sSelector, oOpts );
  4391. for ( i=0, iLen=aTrs.length ; i<iLen ; i++ )
  4392. {
  4393. aOut.push( this.fnGetData(aTrs[i]) );
  4394. }
  4395. return aOut;
  4396. };
  4397. /**
  4398. * Add a single new row or multiple rows of data to the table. Please note
  4399. * that this is suitable for client-side processing only - if you are using
  4400. * server-side processing (i.e. "bServerSide": true), then to add data, you
  4401. * must add it to the data source, i.e. the server-side, through an Ajax call.
  4402. * @param {array|object} mData The data to be added to the table. This can be:
  4403. * <ul>
  4404. * <li>1D array of data - add a single row with the data provided</li>
  4405. * <li>2D array of arrays - add multiple rows in a single call</li>
  4406. * <li>object - data object when using <i>mDataProp</i></li>
  4407. * <li>array of objects - multiple data objects when using <i>mDataProp</i></li>
  4408. * </ul>
  4409. * @param {bool} [bRedraw=true] redraw the table or not
  4410. * @returns {array} An array of integers, representing the list of indexes in
  4411. * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
  4412. * the table.
  4413. * @dtopt API
  4414. *
  4415. * @example
  4416. * // Global var for counter
  4417. * var giCount = 2;
  4418. *
  4419. * $(document).ready(function() {
  4420. * $('#example').dataTable();
  4421. * } );
  4422. *
  4423. * function fnClickAddRow() {
  4424. * $('#example').dataTable().fnAddData( [
  4425. * giCount+".1",
  4426. * giCount+".2",
  4427. * giCount+".3",
  4428. * giCount+".4" ]
  4429. * );
  4430. *
  4431. * giCount++;
  4432. * }
  4433. */
  4434. this.fnAddData = function( mData, bRedraw )
  4435. {
  4436. if ( mData.length === 0 )
  4437. {
  4438. return [];
  4439. }
  4440. var aiReturn = [];
  4441. var iTest;
  4442. /* Find settings from table node */
  4443. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4444. /* Check if we want to add multiple rows or not */
  4445. if ( typeof mData[0] === "object" && mData[0] !== null )
  4446. {
  4447. for ( var i=0 ; i<mData.length ; i++ )
  4448. {
  4449. iTest = _fnAddData( oSettings, mData[i] );
  4450. if ( iTest == -1 )
  4451. {
  4452. return aiReturn;
  4453. }
  4454. aiReturn.push( iTest );
  4455. }
  4456. }
  4457. else
  4458. {
  4459. iTest = _fnAddData( oSettings, mData );
  4460. if ( iTest == -1 )
  4461. {
  4462. return aiReturn;
  4463. }
  4464. aiReturn.push( iTest );
  4465. }
  4466. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  4467. if ( bRedraw === undefined || bRedraw )
  4468. {
  4469. _fnReDraw( oSettings );
  4470. }
  4471. return aiReturn;
  4472. };
  4473. /**
  4474. * This function will make DataTables recalculate the column sizes, based on the data
  4475. * contained in the table and the sizes applied to the columns (in the DOM, CSS or
  4476. * through the sWidth parameter). This can be useful when the width of the table's
  4477. * parent element changes (for example a window resize).
  4478. * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
  4479. * @dtopt API
  4480. *
  4481. * @example
  4482. * $(document).ready(function() {
  4483. * var oTable = $('#example').dataTable( {
  4484. * "sScrollY": "200px",
  4485. * "bPaginate": false
  4486. * } );
  4487. *
  4488. * $(window).bind('resize', function () {
  4489. * oTable.fnAdjustColumnSizing();
  4490. * } );
  4491. * } );
  4492. */
  4493. this.fnAdjustColumnSizing = function ( bRedraw )
  4494. {
  4495. var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
  4496. _fnAdjustColumnSizing( oSettings );
  4497. if ( bRedraw === undefined || bRedraw )
  4498. {
  4499. this.fnDraw( false );
  4500. }
  4501. else if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
  4502. {
  4503. /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
  4504. this.oApi._fnScrollDraw(oSettings);
  4505. }
  4506. };
  4507. /**
  4508. * Quickly and simply clear a table
  4509. * @param {bool} [bRedraw=true] redraw the table or not
  4510. * @dtopt API
  4511. *
  4512. * @example
  4513. * $(document).ready(function() {
  4514. * var oTable = $('#example').dataTable();
  4515. *
  4516. * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
  4517. * oTable.fnClearTable();
  4518. * } );
  4519. */
  4520. this.fnClearTable = function( bRedraw )
  4521. {
  4522. /* Find settings from table node */
  4523. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4524. _fnClearTable( oSettings );
  4525. if ( bRedraw === undefined || bRedraw )
  4526. {
  4527. _fnDraw( oSettings );
  4528. }
  4529. };
  4530. /**
  4531. * The exact opposite of 'opening' a row, this function will close any rows which
  4532. * are currently 'open'.
  4533. * @param {node} nTr the table row to 'close'
  4534. * @returns {int} 0 on success, or 1 if failed (can't find the row)
  4535. * @dtopt API
  4536. *
  4537. * @example
  4538. * $(document).ready(function() {
  4539. * var oTable;
  4540. *
  4541. * // 'open' an information row when a row is clicked on
  4542. * $('#example tbody tr').click( function () {
  4543. * if ( oTable.fnIsOpen(this) ) {
  4544. * oTable.fnClose( this );
  4545. * } else {
  4546. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  4547. * }
  4548. * } );
  4549. *
  4550. * oTable = $('#example').dataTable();
  4551. * } );
  4552. */
  4553. this.fnClose = function( nTr )
  4554. {
  4555. /* Find settings from table node */
  4556. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4557. for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ )
  4558. {
  4559. if ( oSettings.aoOpenRows[i].nParent == nTr )
  4560. {
  4561. var nTrParent = oSettings.aoOpenRows[i].nTr.parentNode;
  4562. if ( nTrParent )
  4563. {
  4564. /* Remove it if it is currently on display */
  4565. nTrParent.removeChild( oSettings.aoOpenRows[i].nTr );
  4566. }
  4567. oSettings.aoOpenRows.splice( i, 1 );
  4568. return 0;
  4569. }
  4570. }
  4571. return 1;
  4572. };
  4573. /**
  4574. * Remove a row for the table
  4575. * @param {mixed} mTarget The index of the row from aoData to be deleted, or
  4576. * the TR element you want to delete
  4577. * @param {function|null} [fnCallBack] Callback function
  4578. * @param {bool} [bRedraw=true] Redraw the table or not
  4579. * @returns {array} The row that was deleted
  4580. * @dtopt API
  4581. *
  4582. * @example
  4583. * $(document).ready(function() {
  4584. * var oTable = $('#example').dataTable();
  4585. *
  4586. * // Immediately remove the first row
  4587. * oTable.fnDeleteRow( 0 );
  4588. * } );
  4589. */
  4590. this.fnDeleteRow = function( mTarget, fnCallBack, bRedraw )
  4591. {
  4592. /* Find settings from table node */
  4593. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4594. var i, iLen, iAODataIndex;
  4595. iAODataIndex = (typeof mTarget === 'object') ?
  4596. _fnNodeToDataIndex(oSettings, mTarget) : mTarget;
  4597. /* Return the data array from this row */
  4598. var oData = oSettings.aoData.splice( iAODataIndex, 1 );
  4599. /* Update the _DT_RowIndex parameter */
  4600. for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
  4601. {
  4602. if ( oSettings.aoData[i].nTr !== null )
  4603. {
  4604. oSettings.aoData[i].nTr._DT_RowIndex = i;
  4605. }
  4606. }
  4607. /* Remove the target row from the search array */
  4608. var iDisplayIndex = $.inArray( iAODataIndex, oSettings.aiDisplay );
  4609. oSettings.asDataSearch.splice( iDisplayIndex, 1 );
  4610. /* Delete from the display arrays */
  4611. _fnDeleteIndex( oSettings.aiDisplayMaster, iAODataIndex );
  4612. _fnDeleteIndex( oSettings.aiDisplay, iAODataIndex );
  4613. /* If there is a user callback function - call it */
  4614. if ( typeof fnCallBack === "function" )
  4615. {
  4616. fnCallBack.call( this, oSettings, oData );
  4617. }
  4618. /* Check for an 'overflow' they case for displaying the table */
  4619. if ( oSettings._iDisplayStart >= oSettings.fnRecordsDisplay() )
  4620. {
  4621. oSettings._iDisplayStart -= oSettings._iDisplayLength;
  4622. if ( oSettings._iDisplayStart < 0 )
  4623. {
  4624. oSettings._iDisplayStart = 0;
  4625. }
  4626. }
  4627. if ( bRedraw === undefined || bRedraw )
  4628. {
  4629. _fnCalculateEnd( oSettings );
  4630. _fnDraw( oSettings );
  4631. }
  4632. return oData;
  4633. };
  4634. /**
  4635. * Restore the table to it's original state in the DOM by removing all of DataTables
  4636. * enhancements, alterations to the DOM structure of the table and event listeners.
  4637. * @param {boolean} [bRemove=false] Completely remove the table from the DOM
  4638. * @dtopt API
  4639. *
  4640. * @example
  4641. * $(document).ready(function() {
  4642. * // This example is fairly pointless in reality, but shows how fnDestroy can be used
  4643. * var oTable = $('#example').dataTable();
  4644. * oTable.fnDestroy();
  4645. * } );
  4646. */
  4647. this.fnDestroy = function ( bRemove )
  4648. {
  4649. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4650. var nOrig = oSettings.nTableWrapper.parentNode;
  4651. var nBody = oSettings.nTBody;
  4652. var i, iLen;
  4653. bRemove = (bRemove===undefined) ? false : true;
  4654. /* Flag to note that the table is currently being destroyed - no action should be taken */
  4655. oSettings.bDestroying = true;
  4656. /* Fire off the destroy callbacks for plug-ins etc */
  4657. _fnCallbackFire( oSettings, "aoDestroyCallback", "destroy", [oSettings] );
  4658. /* Restore hidden columns */
  4659. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  4660. {
  4661. if ( oSettings.aoColumns[i].bVisible === false )
  4662. {
  4663. this.fnSetColumnVis( i, true );
  4664. }
  4665. }
  4666. /* Blitz all DT events */
  4667. $(oSettings.nTableWrapper).find('*').andSelf().unbind('.DT');
  4668. /* If there is an 'empty' indicator row, remove it */
  4669. $('tbody>tr>td.'+oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove();
  4670. /* When scrolling we had to break the table up - restore it */
  4671. if ( oSettings.nTable != oSettings.nTHead.parentNode )
  4672. {
  4673. $(oSettings.nTable).children('thead').remove();
  4674. oSettings.nTable.appendChild( oSettings.nTHead );
  4675. }
  4676. if ( oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode )
  4677. {
  4678. $(oSettings.nTable).children('tfoot').remove();
  4679. oSettings.nTable.appendChild( oSettings.nTFoot );
  4680. }
  4681. /* Remove the DataTables generated nodes, events and classes */
  4682. oSettings.nTable.parentNode.removeChild( oSettings.nTable );
  4683. $(oSettings.nTableWrapper).remove();
  4684. oSettings.aaSorting = [];
  4685. oSettings.aaSortingFixed = [];
  4686. _fnSortingClasses( oSettings );
  4687. $(_fnGetTrNodes( oSettings )).removeClass( oSettings.asStripeClasses.join(' ') );
  4688. $('th, td', oSettings.nTHead).removeClass( [
  4689. oSettings.oClasses.sSortable,
  4690. oSettings.oClasses.sSortableAsc,
  4691. oSettings.oClasses.sSortableDesc,
  4692. oSettings.oClasses.sSortableNone ].join(' ')
  4693. );
  4694. if ( oSettings.bJUI )
  4695. {
  4696. $('th span.'+oSettings.oClasses.sSortIcon
  4697. + ', td span.'+oSettings.oClasses.sSortIcon, oSettings.nTHead).remove();
  4698. $('th, td', oSettings.nTHead).each( function () {
  4699. var jqWrapper = $('div.'+oSettings.oClasses.sSortJUIWrapper, this);
  4700. var kids = jqWrapper.contents();
  4701. $(this).append( kids );
  4702. jqWrapper.remove();
  4703. } );
  4704. }
  4705. /* Add the TR elements back into the table in their original order */
  4706. if ( !bRemove && oSettings.nTableReinsertBefore )
  4707. {
  4708. nOrig.insertBefore( oSettings.nTable, oSettings.nTableReinsertBefore );
  4709. }
  4710. else if ( !bRemove )
  4711. {
  4712. nOrig.appendChild( oSettings.nTable );
  4713. }
  4714. for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
  4715. {
  4716. if ( oSettings.aoData[i].nTr !== null )
  4717. {
  4718. nBody.appendChild( oSettings.aoData[i].nTr );
  4719. }
  4720. }
  4721. /* Restore the width of the original table */
  4722. if ( oSettings.oFeatures.bAutoWidth === true )
  4723. {
  4724. oSettings.nTable.style.width = _fnStringToCss(oSettings.sDestroyWidth);
  4725. }
  4726. /* If the were originally odd/even type classes - then we add them back here. Note
  4727. * this is not fool proof (for example if not all rows as odd/even classes - but
  4728. * it's a good effort without getting carried away
  4729. */
  4730. $(nBody).children('tr:even').addClass( oSettings.asDestroyStripes[0] );
  4731. $(nBody).children('tr:odd').addClass( oSettings.asDestroyStripes[1] );
  4732. /* Remove the settings object from the settings array */
  4733. for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ )
  4734. {
  4735. if ( DataTable.settings[i] == oSettings )
  4736. {
  4737. DataTable.settings.splice( i, 1 );
  4738. }
  4739. }
  4740. /* End it all */
  4741. oSettings = null;
  4742. };
  4743. /**
  4744. * Redraw the table
  4745. * @param {bool} [bComplete=true] Re-filter and resort (if enabled) the table before the draw.
  4746. * @dtopt API
  4747. *
  4748. * @example
  4749. * $(document).ready(function() {
  4750. * var oTable = $('#example').dataTable();
  4751. *
  4752. * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
  4753. * oTable.fnDraw();
  4754. * } );
  4755. */
  4756. this.fnDraw = function( bComplete )
  4757. {
  4758. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4759. if ( bComplete === false )
  4760. {
  4761. _fnCalculateEnd( oSettings );
  4762. _fnDraw( oSettings );
  4763. }
  4764. else
  4765. {
  4766. _fnReDraw( oSettings );
  4767. }
  4768. };
  4769. /**
  4770. * Filter the input based on data
  4771. * @param {string} sInput String to filter the table on
  4772. * @param {int|null} [iColumn] Column to limit filtering to
  4773. * @param {bool} [bRegex=false] Treat as regular expression or not
  4774. * @param {bool} [bSmart=true] Perform smart filtering or not
  4775. * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
  4776. * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
  4777. * @dtopt API
  4778. *
  4779. * @example
  4780. * $(document).ready(function() {
  4781. * var oTable = $('#example').dataTable();
  4782. *
  4783. * // Sometime later - filter...
  4784. * oTable.fnFilter( 'test string' );
  4785. * } );
  4786. */
  4787. this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
  4788. {
  4789. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4790. if ( !oSettings.oFeatures.bFilter )
  4791. {
  4792. return;
  4793. }
  4794. if ( bRegex === undefined || bRegex === null )
  4795. {
  4796. bRegex = false;
  4797. }
  4798. if ( bSmart === undefined || bSmart === null )
  4799. {
  4800. bSmart = true;
  4801. }
  4802. if ( bShowGlobal === undefined || bShowGlobal === null )
  4803. {
  4804. bShowGlobal = true;
  4805. }
  4806. if ( bCaseInsensitive === undefined || bCaseInsensitive === null )
  4807. {
  4808. bCaseInsensitive = true;
  4809. }
  4810. if ( iColumn === undefined || iColumn === null )
  4811. {
  4812. /* Global filter */
  4813. _fnFilterComplete( oSettings, {
  4814. "sSearch":sInput+"",
  4815. "bRegex": bRegex,
  4816. "bSmart": bSmart,
  4817. "bCaseInsensitive": bCaseInsensitive
  4818. }, 1 );
  4819. if ( bShowGlobal && oSettings.aanFeatures.f )
  4820. {
  4821. var n = oSettings.aanFeatures.f;
  4822. for ( var i=0, iLen=n.length ; i<iLen ; i++ )
  4823. {
  4824. $(n[i]._DT_Input).val( sInput );
  4825. }
  4826. }
  4827. }
  4828. else
  4829. {
  4830. /* Single column filter */
  4831. $.extend( oSettings.aoPreSearchCols[ iColumn ], {
  4832. "sSearch": sInput+"",
  4833. "bRegex": bRegex,
  4834. "bSmart": bSmart,
  4835. "bCaseInsensitive": bCaseInsensitive
  4836. } );
  4837. _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
  4838. }
  4839. };
  4840. /**
  4841. * Get the data for the whole table, an individual row or an individual cell based on the
  4842. * provided parameters.
  4843. * @param {int|node} [mRow] A TR row node, TD/TH cell node or an integer. If given as
  4844. * a TR node then the data source for the whole row will be returned. If given as a
  4845. * TD/TH cell node then iCol will be automatically calculated and the data for the
  4846. * cell returned. If given as an integer, then this is treated as the aoData internal
  4847. * data index for the row (see fnGetPosition) and the data for that row used.
  4848. * @param {int} [iCol] Optional column index that you want the data of.
  4849. * @returns {array|object|string} If mRow is undefined, then the data for all rows is
  4850. * returned. If mRow is defined, just data for that row, and is iCol is
  4851. * defined, only data for the designated cell is returned.
  4852. * @dtopt API
  4853. *
  4854. * @example
  4855. * // Row data
  4856. * $(document).ready(function() {
  4857. * oTable = $('#example').dataTable();
  4858. *
  4859. * oTable.$('tr').click( function () {
  4860. * var data = oTable.fnGetData( this );
  4861. * // ... do something with the array / object of data for the row
  4862. * } );
  4863. * } );
  4864. *
  4865. * @example
  4866. * // Individual cell data
  4867. * $(document).ready(function() {
  4868. * oTable = $('#example').dataTable();
  4869. *
  4870. * oTable.$('td').click( function () {
  4871. * var sData = oTable.fnGetData( this );
  4872. * alert( 'The cell clicked on had the value of '+sData );
  4873. * } );
  4874. * } );
  4875. */
  4876. this.fnGetData = function( mRow, iCol )
  4877. {
  4878. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4879. if ( mRow !== undefined )
  4880. {
  4881. var iRow = mRow;
  4882. if ( typeof mRow === 'object' )
  4883. {
  4884. var sNode = mRow.nodeName.toLowerCase();
  4885. if (sNode === "tr" )
  4886. {
  4887. iRow = _fnNodeToDataIndex(oSettings, mRow);
  4888. }
  4889. else if ( sNode === "td" )
  4890. {
  4891. iRow = _fnNodeToDataIndex(oSettings, mRow.parentNode);
  4892. iCol = _fnNodeToColumnIndex( oSettings, iRow, mRow );
  4893. }
  4894. }
  4895. if ( iCol !== undefined )
  4896. {
  4897. return _fnGetCellData( oSettings, iRow, iCol, '' );
  4898. }
  4899. return (oSettings.aoData[iRow]!==undefined) ?
  4900. oSettings.aoData[iRow]._aData : null;
  4901. }
  4902. return _fnGetDataMaster( oSettings );
  4903. };
  4904. /**
  4905. * Get an array of the TR nodes that are used in the table's body. Note that you will
  4906. * typically want to use the '$' API method in preference to this as it is more
  4907. * flexible.
  4908. * @param {int} [iRow] Optional row index for the TR element you want
  4909. * @returns {array|node} If iRow is undefined, returns an array of all TR elements
  4910. * in the table's body, or iRow is defined, just the TR element requested.
  4911. * @dtopt API
  4912. *
  4913. * @example
  4914. * $(document).ready(function() {
  4915. * var oTable = $('#example').dataTable();
  4916. *
  4917. * // Get the nodes from the table
  4918. * var nNodes = oTable.fnGetNodes( );
  4919. * } );
  4920. */
  4921. this.fnGetNodes = function( iRow )
  4922. {
  4923. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4924. if ( iRow !== undefined ) {
  4925. return (oSettings.aoData[iRow]!==undefined) ?
  4926. oSettings.aoData[iRow].nTr : null;
  4927. }
  4928. return _fnGetTrNodes( oSettings );
  4929. };
  4930. /**
  4931. * Get the array indexes of a particular cell from it's DOM element
  4932. * and column index including hidden columns
  4933. * @param {node} nNode this can either be a TR, TD or TH in the table's body
  4934. * @returns {int} If nNode is given as a TR, then a single index is returned, or
  4935. * if given as a cell, an array of [row index, column index (visible)] is given.
  4936. * @dtopt API
  4937. *
  4938. * @example
  4939. * $(document).ready(function() {
  4940. * $('#example tbody td').click( function () {
  4941. * // Get the position of the current data from the node
  4942. * var aPos = oTable.fnGetPosition( this );
  4943. *
  4944. * // Get the data array for this row
  4945. * var aData = oTable.fnGetData( aPos[0] );
  4946. *
  4947. * // Update the data array and return the value
  4948. * aData[ aPos[1] ] = 'clicked';
  4949. * this.innerHTML = 'clicked';
  4950. * } );
  4951. *
  4952. * // Init DataTables
  4953. * oTable = $('#example').dataTable();
  4954. * } );
  4955. */
  4956. this.fnGetPosition = function( nNode )
  4957. {
  4958. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4959. var sNodeName = nNode.nodeName.toUpperCase();
  4960. if ( sNodeName == "TR" )
  4961. {
  4962. return _fnNodeToDataIndex(oSettings, nNode);
  4963. }
  4964. else if ( sNodeName == "TD" || sNodeName == "TH" )
  4965. {
  4966. var iDataIndex = _fnNodeToDataIndex( oSettings, nNode.parentNode );
  4967. var iColumnIndex = _fnNodeToColumnIndex( oSettings, iDataIndex, nNode );
  4968. return [ iDataIndex, _fnColumnIndexToVisible(oSettings, iColumnIndex ), iColumnIndex ];
  4969. }
  4970. return null;
  4971. };
  4972. /**
  4973. * Check to see if a row is 'open' or not.
  4974. * @param {node} nTr the table row to check
  4975. * @returns {boolean} true if the row is currently open, false otherwise
  4976. * @dtopt API
  4977. *
  4978. * @example
  4979. * $(document).ready(function() {
  4980. * var oTable;
  4981. *
  4982. * // 'open' an information row when a row is clicked on
  4983. * $('#example tbody tr').click( function () {
  4984. * if ( oTable.fnIsOpen(this) ) {
  4985. * oTable.fnClose( this );
  4986. * } else {
  4987. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  4988. * }
  4989. * } );
  4990. *
  4991. * oTable = $('#example').dataTable();
  4992. * } );
  4993. */
  4994. this.fnIsOpen = function( nTr )
  4995. {
  4996. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  4997. var aoOpenRows = oSettings.aoOpenRows;
  4998. for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ )
  4999. {
  5000. if ( oSettings.aoOpenRows[i].nParent == nTr )
  5001. {
  5002. return true;
  5003. }
  5004. }
  5005. return false;
  5006. };
  5007. /**
  5008. * This function will place a new row directly after a row which is currently
  5009. * on display on the page, with the HTML contents that is passed into the
  5010. * function. This can be used, for example, to ask for confirmation that a
  5011. * particular record should be deleted.
  5012. * @param {node} nTr The table row to 'open'
  5013. * @param {string|node|jQuery} mHtml The HTML to put into the row
  5014. * @param {string} sClass Class to give the new TD cell
  5015. * @returns {node} The row opened. Note that if the table row passed in as the
  5016. * first parameter, is not found in the table, this method will silently
  5017. * return.
  5018. * @dtopt API
  5019. *
  5020. * @example
  5021. * $(document).ready(function() {
  5022. * var oTable;
  5023. *
  5024. * // 'open' an information row when a row is clicked on
  5025. * $('#example tbody tr').click( function () {
  5026. * if ( oTable.fnIsOpen(this) ) {
  5027. * oTable.fnClose( this );
  5028. * } else {
  5029. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  5030. * }
  5031. * } );
  5032. *
  5033. * oTable = $('#example').dataTable();
  5034. * } );
  5035. */
  5036. this.fnOpen = function( nTr, mHtml, sClass )
  5037. {
  5038. /* Find settings from table node */
  5039. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5040. /* Check that the row given is in the table */
  5041. var nTableRows = _fnGetTrNodes( oSettings );
  5042. if ( $.inArray(nTr, nTableRows) === -1 )
  5043. {
  5044. return;
  5045. }
  5046. /* the old open one if there is one */
  5047. this.fnClose( nTr );
  5048. var nNewRow = document.createElement("tr");
  5049. var nNewCell = document.createElement("td");
  5050. nNewRow.appendChild( nNewCell );
  5051. nNewCell.className = sClass;
  5052. nNewCell.colSpan = _fnVisbleColumns( oSettings );
  5053. if (typeof mHtml === "string")
  5054. {
  5055. nNewCell.innerHTML = mHtml;
  5056. }
  5057. else
  5058. {
  5059. $(nNewCell).html( mHtml );
  5060. }
  5061. /* If the nTr isn't on the page at the moment - then we don't insert at the moment */
  5062. var nTrs = $('tr', oSettings.nTBody);
  5063. if ( $.inArray(nTr, nTrs) != -1 )
  5064. {
  5065. $(nNewRow).insertAfter(nTr);
  5066. }
  5067. oSettings.aoOpenRows.push( {
  5068. "nTr": nNewRow,
  5069. "nParent": nTr
  5070. } );
  5071. return nNewRow;
  5072. };
  5073. /**
  5074. * Change the pagination - provides the internal logic for pagination in a simple API
  5075. * function. With this function you can have a DataTables table go to the next,
  5076. * previous, first or last pages.
  5077. * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
  5078. * or page number to jump to (integer), note that page 0 is the first page.
  5079. * @param {bool} [bRedraw=true] Redraw the table or not
  5080. * @dtopt API
  5081. *
  5082. * @example
  5083. * $(document).ready(function() {
  5084. * var oTable = $('#example').dataTable();
  5085. * oTable.fnPageChange( 'next' );
  5086. * } );
  5087. */
  5088. this.fnPageChange = function ( mAction, bRedraw )
  5089. {
  5090. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5091. _fnPageChange( oSettings, mAction );
  5092. _fnCalculateEnd( oSettings );
  5093. if ( bRedraw === undefined || bRedraw )
  5094. {
  5095. _fnDraw( oSettings );
  5096. }
  5097. };
  5098. /**
  5099. * Show a particular column
  5100. * @param {int} iCol The column whose display should be changed
  5101. * @param {bool} bShow Show (true) or hide (false) the column
  5102. * @param {bool} [bRedraw=true] Redraw the table or not
  5103. * @dtopt API
  5104. *
  5105. * @example
  5106. * $(document).ready(function() {
  5107. * var oTable = $('#example').dataTable();
  5108. *
  5109. * // Hide the second column after initialisation
  5110. * oTable.fnSetColumnVis( 1, false );
  5111. * } );
  5112. */
  5113. this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
  5114. {
  5115. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5116. var i, iLen;
  5117. var aoColumns = oSettings.aoColumns;
  5118. var aoData = oSettings.aoData;
  5119. var nTd, bAppend, iBefore;
  5120. /* No point in doing anything if we are requesting what is already true */
  5121. if ( aoColumns[iCol].bVisible == bShow )
  5122. {
  5123. return;
  5124. }
  5125. /* Show the column */
  5126. if ( bShow )
  5127. {
  5128. var iInsert = 0;
  5129. for ( i=0 ; i<iCol ; i++ )
  5130. {
  5131. if ( aoColumns[i].bVisible )
  5132. {
  5133. iInsert++;
  5134. }
  5135. }
  5136. /* Need to decide if we should use appendChild or insertBefore */
  5137. bAppend = (iInsert >= _fnVisbleColumns( oSettings ));
  5138. /* Which coloumn should we be inserting before? */
  5139. if ( !bAppend )
  5140. {
  5141. for ( i=iCol ; i<aoColumns.length ; i++ )
  5142. {
  5143. if ( aoColumns[i].bVisible )
  5144. {
  5145. iBefore = i;
  5146. break;
  5147. }
  5148. }
  5149. }
  5150. for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
  5151. {
  5152. if ( aoData[i].nTr !== null )
  5153. {
  5154. if ( bAppend )
  5155. {
  5156. aoData[i].nTr.appendChild(
  5157. aoData[i]._anHidden[iCol]
  5158. );
  5159. }
  5160. else
  5161. {
  5162. aoData[i].nTr.insertBefore(
  5163. aoData[i]._anHidden[iCol],
  5164. _fnGetTdNodes( oSettings, i )[iBefore] );
  5165. }
  5166. }
  5167. }
  5168. }
  5169. else
  5170. {
  5171. /* Remove a column from display */
  5172. for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
  5173. {
  5174. if ( aoData[i].nTr !== null )
  5175. {
  5176. nTd = _fnGetTdNodes( oSettings, i )[iCol];
  5177. aoData[i]._anHidden[iCol] = nTd;
  5178. nTd.parentNode.removeChild( nTd );
  5179. }
  5180. }
  5181. }
  5182. /* Clear to set the visible flag */
  5183. aoColumns[iCol].bVisible = bShow;
  5184. /* Redraw the header and footer based on the new column visibility */
  5185. _fnDrawHead( oSettings, oSettings.aoHeader );
  5186. if ( oSettings.nTFoot )
  5187. {
  5188. _fnDrawHead( oSettings, oSettings.aoFooter );
  5189. }
  5190. /* If there are any 'open' rows, then we need to alter the colspan for this col change */
  5191. for ( i=0, iLen=oSettings.aoOpenRows.length ; i<iLen ; i++ )
  5192. {
  5193. oSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns( oSettings );
  5194. }
  5195. /* Do a redraw incase anything depending on the table columns needs it
  5196. * (built-in: scrolling)
  5197. */
  5198. if ( bRedraw === undefined || bRedraw )
  5199. {
  5200. _fnAdjustColumnSizing( oSettings );
  5201. _fnDraw( oSettings );
  5202. }
  5203. _fnSaveState( oSettings );
  5204. };
  5205. /**
  5206. * Get the settings for a particular table for external manipulation
  5207. * @returns {object} DataTables settings object. See
  5208. * {@link DataTable.models.oSettings}
  5209. * @dtopt API
  5210. *
  5211. * @example
  5212. * $(document).ready(function() {
  5213. * var oTable = $('#example').dataTable();
  5214. * var oSettings = oTable.fnSettings();
  5215. *
  5216. * // Show an example parameter from the settings
  5217. * alert( oSettings._iDisplayStart );
  5218. * } );
  5219. */
  5220. this.fnSettings = function()
  5221. {
  5222. return _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5223. };
  5224. /**
  5225. * Sort the table by a particular column
  5226. * @param {int} iCol the data index to sort on. Note that this will not match the
  5227. * 'display index' if you have hidden data entries
  5228. * @dtopt API
  5229. *
  5230. * @example
  5231. * $(document).ready(function() {
  5232. * var oTable = $('#example').dataTable();
  5233. *
  5234. * // Sort immediately with columns 0 and 1
  5235. * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
  5236. * } );
  5237. */
  5238. this.fnSort = function( aaSort )
  5239. {
  5240. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5241. oSettings.aaSorting = aaSort;
  5242. _fnSort( oSettings );
  5243. };
  5244. /**
  5245. * Attach a sort listener to an element for a given column
  5246. * @param {node} nNode the element to attach the sort listener to
  5247. * @param {int} iColumn the column that a click on this node will sort on
  5248. * @param {function} [fnCallback] callback function when sort is run
  5249. * @dtopt API
  5250. *
  5251. * @example
  5252. * $(document).ready(function() {
  5253. * var oTable = $('#example').dataTable();
  5254. *
  5255. * // Sort on column 1, when 'sorter' is clicked on
  5256. * oTable.fnSortListener( document.getElementById('sorter'), 1 );
  5257. * } );
  5258. */
  5259. this.fnSortListener = function( nNode, iColumn, fnCallback )
  5260. {
  5261. _fnSortAttachListener( _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ), nNode, iColumn,
  5262. fnCallback );
  5263. };
  5264. /**
  5265. * Update a table cell or row - this method will accept either a single value to
  5266. * update the cell with, an array of values with one element for each column or
  5267. * an object in the same format as the original data source. The function is
  5268. * self-referencing in order to make the multi column updates easier.
  5269. * @param {object|array|string} mData Data to update the cell/row with
  5270. * @param {node|int} mRow TR element you want to update or the aoData index
  5271. * @param {int} [iColumn] The column to update (not used of mData is an array or object)
  5272. * @param {bool} [bRedraw=true] Redraw the table or not
  5273. * @param {bool} [bAction=true] Perform predraw actions or not
  5274. * @returns {int} 0 on success, 1 on error
  5275. * @dtopt API
  5276. *
  5277. * @example
  5278. * $(document).ready(function() {
  5279. * var oTable = $('#example').dataTable();
  5280. * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
  5281. * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], 1, 0 ); // Row
  5282. * } );
  5283. */
  5284. this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
  5285. {
  5286. var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
  5287. var i, iLen, sDisplay;
  5288. var iRow = (typeof mRow === 'object') ?
  5289. _fnNodeToDataIndex(oSettings, mRow) : mRow;
  5290. if ( oSettings.__fnUpdateDeep === undefined && $.isArray(mData) && typeof mData === 'object' )
  5291. {
  5292. /* Array update - update the whole row */
  5293. oSettings.aoData[iRow]._aData = mData.slice();
  5294. /* Flag to the function that we are recursing */
  5295. oSettings.__fnUpdateDeep = true;
  5296. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  5297. {
  5298. this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false );
  5299. }
  5300. oSettings.__fnUpdateDeep = undefined;
  5301. }
  5302. else if ( oSettings.__fnUpdateDeep === undefined && mData !== null && typeof mData === 'object' )
  5303. {
  5304. /* Object update - update the whole row - assume the developer gets the object right */
  5305. oSettings.aoData[iRow]._aData = $.extend( true, {}, mData );
  5306. oSettings.__fnUpdateDeep = true;
  5307. for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
  5308. {
  5309. this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false );
  5310. }
  5311. oSettings.__fnUpdateDeep = undefined;
  5312. }
  5313. else
  5314. {
  5315. /* Individual cell update */
  5316. _fnSetCellData( oSettings, iRow, iColumn, mData );
  5317. sDisplay = _fnGetCellData( oSettings, iRow, iColumn, 'display' );
  5318. var oCol = oSettings.aoColumns[iColumn];
  5319. if ( oCol.fnRender !== null )
  5320. {
  5321. sDisplay = _fnRender( oSettings, iRow, iColumn );
  5322. if ( oCol.bUseRendered )
  5323. {
  5324. _fnSetCellData( oSettings, iRow, iColumn, sDisplay );
  5325. }
  5326. }
  5327. if ( oSettings.aoData[iRow].nTr !== null )
  5328. {
  5329. /* Do the actual HTML update */
  5330. _fnGetTdNodes( oSettings, iRow )[iColumn].innerHTML = sDisplay;
  5331. }
  5332. }
  5333. /* Modify the search index for this row (strictly this is likely not needed, since fnReDraw
  5334. * will rebuild the search array - however, the redraw might be disabled by the user)
  5335. */
  5336. var iDisplayIndex = $.inArray( iRow, oSettings.aiDisplay );
  5337. oSettings.asDataSearch[iDisplayIndex] = _fnBuildSearchRow( oSettings,
  5338. _fnGetRowData( oSettings, iRow, 'filter' ) );
  5339. /* Perform pre-draw actions */
  5340. if ( bAction === undefined || bAction )
  5341. {
  5342. _fnAdjustColumnSizing( oSettings );
  5343. }
  5344. /* Redraw the table */
  5345. if ( bRedraw === undefined || bRedraw )
  5346. {
  5347. _fnReDraw( oSettings );
  5348. }
  5349. return 0;
  5350. };
  5351. /**
  5352. * Provide a common method for plug-ins to check the version of DataTables being used, in order
  5353. * to ensure compatibility.
  5354. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
  5355. * formats "X" and "X.Y" are also acceptable.
  5356. * @returns {boolean} true if this version of DataTables is greater or equal to the required
  5357. * version, or false if this version of DataTales is not suitable
  5358. * @method
  5359. * @dtopt API
  5360. *
  5361. * @example
  5362. * $(document).ready(function() {
  5363. * var oTable = $('#example').dataTable();
  5364. * alert( oTable.fnVersionCheck( '1.9.0' ) );
  5365. * } );
  5366. */
  5367. this.fnVersionCheck = DataTable.ext.fnVersionCheck;
  5368. /*
  5369. * This is really a good bit rubbish this method of exposing the internal methods
  5370. * publically... - To be fixed in 2.0 using methods on the prototype
  5371. */
  5372. /**
  5373. * Create a wrapper function for exporting an internal functions to an external API.
  5374. * @param {string} sFunc API function name
  5375. * @returns {function} wrapped function
  5376. * @memberof DataTable#oApi
  5377. */
  5378. function _fnExternApiFunc (sFunc)
  5379. {
  5380. return function() {
  5381. var aArgs = [_fnSettingsFromNode(this[DataTable.ext.iApiIndex])].concat(
  5382. Array.prototype.slice.call(arguments) );
  5383. return DataTable.ext.oApi[sFunc].apply( this, aArgs );
  5384. };
  5385. }
  5386. /**
  5387. * Reference to internal functions for use by plug-in developers. Note that these
  5388. * methods are references to internal functions and are considered to be private.
  5389. * If you use these methods, be aware that they are liable to change between versions
  5390. * (check the upgrade notes).
  5391. * @namespace
  5392. */
  5393. this.oApi = {
  5394. "_fnExternApiFunc": _fnExternApiFunc,
  5395. "_fnInitialise": _fnInitialise,
  5396. "_fnInitComplete": _fnInitComplete,
  5397. "_fnLanguageCompat": _fnLanguageCompat,
  5398. "_fnAddColumn": _fnAddColumn,
  5399. "_fnColumnOptions": _fnColumnOptions,
  5400. "_fnAddData": _fnAddData,
  5401. "_fnCreateTr": _fnCreateTr,
  5402. "_fnGatherData": _fnGatherData,
  5403. "_fnBuildHead": _fnBuildHead,
  5404. "_fnDrawHead": _fnDrawHead,
  5405. "_fnDraw": _fnDraw,
  5406. "_fnReDraw": _fnReDraw,
  5407. "_fnAjaxUpdate": _fnAjaxUpdate,
  5408. "_fnAjaxParameters": _fnAjaxParameters,
  5409. "_fnAjaxUpdateDraw": _fnAjaxUpdateDraw,
  5410. "_fnServerParams": _fnServerParams,
  5411. "_fnAddOptionsHtml": _fnAddOptionsHtml,
  5412. "_fnFeatureHtmlTable": _fnFeatureHtmlTable,
  5413. "_fnScrollDraw": _fnScrollDraw,
  5414. "_fnAdjustColumnSizing": _fnAdjustColumnSizing,
  5415. "_fnFeatureHtmlFilter": _fnFeatureHtmlFilter,
  5416. "_fnFilterComplete": _fnFilterComplete,
  5417. "_fnFilterCustom": _fnFilterCustom,
  5418. "_fnFilterColumn": _fnFilterColumn,
  5419. "_fnFilter": _fnFilter,
  5420. "_fnBuildSearchArray": _fnBuildSearchArray,
  5421. "_fnBuildSearchRow": _fnBuildSearchRow,
  5422. "_fnFilterCreateSearch": _fnFilterCreateSearch,
  5423. "_fnDataToSearch": _fnDataToSearch,
  5424. "_fnSort": _fnSort,
  5425. "_fnSortAttachListener": _fnSortAttachListener,
  5426. "_fnSortingClasses": _fnSortingClasses,
  5427. "_fnFeatureHtmlPaginate": _fnFeatureHtmlPaginate,
  5428. "_fnPageChange": _fnPageChange,
  5429. "_fnFeatureHtmlInfo": _fnFeatureHtmlInfo,
  5430. "_fnUpdateInfo": _fnUpdateInfo,
  5431. "_fnFeatureHtmlLength": _fnFeatureHtmlLength,
  5432. "_fnFeatureHtmlProcessing": _fnFeatureHtmlProcessing,
  5433. "_fnProcessingDisplay": _fnProcessingDisplay,
  5434. "_fnVisibleToColumnIndex": _fnVisibleToColumnIndex,
  5435. "_fnColumnIndexToVisible": _fnColumnIndexToVisible,
  5436. "_fnNodeToDataIndex": _fnNodeToDataIndex,
  5437. "_fnVisbleColumns": _fnVisbleColumns,
  5438. "_fnCalculateEnd": _fnCalculateEnd,
  5439. "_fnConvertToWidth": _fnConvertToWidth,
  5440. "_fnCalculateColumnWidths": _fnCalculateColumnWidths,
  5441. "_fnScrollingWidthAdjust": _fnScrollingWidthAdjust,
  5442. "_fnGetWidestNode": _fnGetWidestNode,
  5443. "_fnGetMaxLenString": _fnGetMaxLenString,
  5444. "_fnStringToCss": _fnStringToCss,
  5445. "_fnDetectType": _fnDetectType,
  5446. "_fnSettingsFromNode": _fnSettingsFromNode,
  5447. "_fnGetDataMaster": _fnGetDataMaster,
  5448. "_fnGetTrNodes": _fnGetTrNodes,
  5449. "_fnGetTdNodes": _fnGetTdNodes,
  5450. "_fnEscapeRegex": _fnEscapeRegex,
  5451. "_fnDeleteIndex": _fnDeleteIndex,
  5452. "_fnReOrderIndex": _fnReOrderIndex,
  5453. "_fnColumnOrdering": _fnColumnOrdering,
  5454. "_fnLog": _fnLog,
  5455. "_fnClearTable": _fnClearTable,
  5456. "_fnSaveState": _fnSaveState,
  5457. "_fnLoadState": _fnLoadState,
  5458. "_fnCreateCookie": _fnCreateCookie,
  5459. "_fnReadCookie": _fnReadCookie,
  5460. "_fnDetectHeader": _fnDetectHeader,
  5461. "_fnGetUniqueThs": _fnGetUniqueThs,
  5462. "_fnScrollBarWidth": _fnScrollBarWidth,
  5463. "_fnApplyToChildren": _fnApplyToChildren,
  5464. "_fnMap": _fnMap,
  5465. "_fnGetRowData": _fnGetRowData,
  5466. "_fnGetCellData": _fnGetCellData,
  5467. "_fnSetCellData": _fnSetCellData,
  5468. "_fnGetObjectDataFn": _fnGetObjectDataFn,
  5469. "_fnSetObjectDataFn": _fnSetObjectDataFn,
  5470. "_fnApplyColumnDefs": _fnApplyColumnDefs,
  5471. "_fnBindAction": _fnBindAction,
  5472. "_fnExtend": _fnExtend,
  5473. "_fnCallbackReg": _fnCallbackReg,
  5474. "_fnCallbackFire": _fnCallbackFire,
  5475. "_fnJsonString": _fnJsonString,
  5476. "_fnRender": _fnRender,
  5477. "_fnNodeToColumnIndex": _fnNodeToColumnIndex,
  5478. "_fnInfoMacros": _fnInfoMacros
  5479. };
  5480. $.extend( DataTable.ext.oApi, this.oApi );
  5481. for ( var sFunc in DataTable.ext.oApi )
  5482. {
  5483. if ( sFunc )
  5484. {
  5485. this[sFunc] = _fnExternApiFunc(sFunc);
  5486. }
  5487. }
  5488. var _that = this;
  5489. return this.each(function() {
  5490. var i=0, iLen, j, jLen, k, kLen;
  5491. var sId = this.getAttribute( 'id' );
  5492. var bInitHandedOff = false;
  5493. var bUsePassedData = false;
  5494. /* Sanity check */
  5495. if ( this.nodeName.toLowerCase() != 'table' )
  5496. {
  5497. _fnLog( null, 0, "Attempted to initialise DataTables on a node which is not a "+
  5498. "table: "+this.nodeName );
  5499. return;
  5500. }
  5501. /* Check to see if we are re-initialising a table */
  5502. for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ )
  5503. {
  5504. /* Base check on table node */
  5505. if ( DataTable.settings[i].nTable == this )
  5506. {
  5507. if ( oInit === undefined || oInit.bRetrieve )
  5508. {
  5509. return DataTable.settings[i].oInstance;
  5510. }
  5511. else if ( oInit.bDestroy )
  5512. {
  5513. DataTable.settings[i].oInstance.fnDestroy();
  5514. break;
  5515. }
  5516. else
  5517. {
  5518. _fnLog( DataTable.settings[i], 0, "Cannot reinitialise DataTable.\n\n"+
  5519. "To retrieve the DataTables object for this table, pass no arguments or see "+
  5520. "the docs for bRetrieve and bDestroy" );
  5521. return;
  5522. }
  5523. }
  5524. /* If the element we are initialising has the same ID as a table which was previously
  5525. * initialised, but the table nodes don't match (from before) then we destroy the old
  5526. * instance by simply deleting it. This is under the assumption that the table has been
  5527. * destroyed by other methods. Anyone using non-id selectors will need to do this manually
  5528. */
  5529. if ( DataTable.settings[i].sTableId == this.id )
  5530. {
  5531. DataTable.settings.splice( i, 1 );
  5532. break;
  5533. }
  5534. }
  5535. /* Ensure the table has an ID - required for accessibility */
  5536. if ( sId === null || sId === "" )
  5537. {
  5538. sId = "DataTables_Table_"+(DataTable.ext._oExternConfig.iNextUnique++);
  5539. this.id = sId;
  5540. }
  5541. /* Create the settings object for this table and set some of the default parameters */
  5542. var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
  5543. "nTable": this,
  5544. "oApi": _that.oApi,
  5545. "oInit": oInit,
  5546. "sDestroyWidth": $(this).width(),
  5547. "sInstance": sId,
  5548. "sTableId": sId
  5549. } );
  5550. DataTable.settings.push( oSettings );
  5551. // Need to add the instance after the instance after the settings object has been added
  5552. // to the settings array, so we can self reference the table instance if more than one
  5553. oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable();
  5554. /* Setting up the initialisation object */
  5555. if ( !oInit )
  5556. {
  5557. oInit = {};
  5558. }
  5559. // Backwards compatibility, before we apply all the defaults
  5560. if ( oInit.oLanguage )
  5561. {
  5562. _fnLanguageCompat( oInit.oLanguage );
  5563. }
  5564. oInit = _fnExtend( $.extend(true, {}, DataTable.defaults), oInit );
  5565. // Map the initialisation options onto the settings object
  5566. _fnMap( oSettings.oFeatures, oInit, "bPaginate" );
  5567. _fnMap( oSettings.oFeatures, oInit, "bLengthChange" );
  5568. _fnMap( oSettings.oFeatures, oInit, "bFilter" );
  5569. _fnMap( oSettings.oFeatures, oInit, "bSort" );
  5570. _fnMap( oSettings.oFeatures, oInit, "bInfo" );
  5571. _fnMap( oSettings.oFeatures, oInit, "bProcessing" );
  5572. _fnMap( oSettings.oFeatures, oInit, "bAutoWidth" );
  5573. _fnMap( oSettings.oFeatures, oInit, "bSortClasses" );
  5574. _fnMap( oSettings.oFeatures, oInit, "bServerSide" );
  5575. _fnMap( oSettings.oFeatures, oInit, "bDeferRender" );
  5576. _fnMap( oSettings.oScroll, oInit, "sScrollX", "sX" );
  5577. _fnMap( oSettings.oScroll, oInit, "sScrollXInner", "sXInner" );
  5578. _fnMap( oSettings.oScroll, oInit, "sScrollY", "sY" );
  5579. _fnMap( oSettings.oScroll, oInit, "bScrollCollapse", "bCollapse" );
  5580. _fnMap( oSettings.oScroll, oInit, "bScrollInfinite", "bInfinite" );
  5581. _fnMap( oSettings.oScroll, oInit, "iScrollLoadGap", "iLoadGap" );
  5582. _fnMap( oSettings.oScroll, oInit, "bScrollAutoCss", "bAutoCss" );
  5583. _fnMap( oSettings, oInit, "asStripeClasses" );
  5584. _fnMap( oSettings, oInit, "asStripClasses", "asStripeClasses" ); // legacy
  5585. _fnMap( oSettings, oInit, "fnServerData" );
  5586. _fnMap( oSettings, oInit, "fnFormatNumber" );
  5587. _fnMap( oSettings, oInit, "sServerMethod" );
  5588. _fnMap( oSettings, oInit, "aaSorting" );
  5589. _fnMap( oSettings, oInit, "aaSortingFixed" );
  5590. _fnMap( oSettings, oInit, "aLengthMenu" );
  5591. _fnMap( oSettings, oInit, "sPaginationType" );
  5592. _fnMap( oSettings, oInit, "sAjaxSource" );
  5593. _fnMap( oSettings, oInit, "sAjaxDataProp" );
  5594. _fnMap( oSettings, oInit, "iCookieDuration" );
  5595. _fnMap( oSettings, oInit, "sCookiePrefix" );
  5596. _fnMap( oSettings, oInit, "sDom" );
  5597. _fnMap( oSettings, oInit, "bSortCellsTop" );
  5598. _fnMap( oSettings, oInit, "iTabIndex" );
  5599. _fnMap( oSettings, oInit, "oSearch", "oPreviousSearch" );
  5600. _fnMap( oSettings, oInit, "aoSearchCols", "aoPreSearchCols" );
  5601. _fnMap( oSettings, oInit, "iDisplayLength", "_iDisplayLength" );
  5602. _fnMap( oSettings, oInit, "bJQueryUI", "bJUI" );
  5603. _fnMap( oSettings, oInit, "fnCookieCallback" );
  5604. _fnMap( oSettings, oInit, "fnStateLoad" );
  5605. _fnMap( oSettings, oInit, "fnStateSave" );
  5606. _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
  5607. /* Callback functions which are array driven */
  5608. _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' );
  5609. _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' );
  5610. _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' );
  5611. _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' );
  5612. _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' );
  5613. _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' );
  5614. _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' );
  5615. _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' );
  5616. _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' );
  5617. _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' );
  5618. _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' );
  5619. if ( oSettings.oFeatures.bServerSide && oSettings.oFeatures.bSort &&
  5620. oSettings.oFeatures.bSortClasses )
  5621. {
  5622. /* Enable sort classes for server-side processing. Safe to do it here, since server-side
  5623. * processing must be enabled by the developer
  5624. */
  5625. _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'server_side_sort_classes' );
  5626. }
  5627. else if ( oSettings.oFeatures.bDeferRender )
  5628. {
  5629. _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'defer_sort_classes' );
  5630. }
  5631. if ( oInit.bJQueryUI )
  5632. {
  5633. /* Use the JUI classes object for display. You could clone the oStdClasses object if
  5634. * you want to have multiple tables with multiple independent classes
  5635. */
  5636. $.extend( oSettings.oClasses, DataTable.ext.oJUIClasses );
  5637. if ( oInit.sDom === DataTable.defaults.sDom && DataTable.defaults.sDom === "lfrtip" )
  5638. {
  5639. /* Set the DOM to use a layout suitable for jQuery UI's theming */
  5640. oSettings.sDom = '<"H"lfr>t<"F"ip>';
  5641. }
  5642. }
  5643. else
  5644. {
  5645. $.extend( oSettings.oClasses, DataTable.ext.oStdClasses );
  5646. }
  5647. $(this).addClass( oSettings.oClasses.sTable );
  5648. /* Calculate the scroll bar width and cache it for use later on */
  5649. if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
  5650. {
  5651. oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
  5652. }
  5653. if ( oSettings.iInitDisplayStart === undefined )
  5654. {
  5655. /* Display start point, taking into account the save saving */
  5656. oSettings.iInitDisplayStart = oInit.iDisplayStart;
  5657. oSettings._iDisplayStart = oInit.iDisplayStart;
  5658. }
  5659. /* Must be done after everything which can be overridden by a cookie! */
  5660. if ( oInit.bStateSave )
  5661. {
  5662. oSettings.oFeatures.bStateSave = true;
  5663. _fnLoadState( oSettings, oInit );
  5664. _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
  5665. }
  5666. if ( oInit.iDeferLoading !== null )
  5667. {
  5668. oSettings.bDeferLoading = true;
  5669. var tmp = $.isArray( oInit.iDeferLoading );
  5670. oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
  5671. oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
  5672. }
  5673. if ( oInit.aaData !== null )
  5674. {
  5675. bUsePassedData = true;
  5676. }
  5677. /* Language definitions */
  5678. if ( oInit.oLanguage.sUrl !== "" )
  5679. {
  5680. /* Get the language definitions from a file - because this Ajax call makes the language
  5681. * get async to the remainder of this function we use bInitHandedOff to indicate that
  5682. * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
  5683. */
  5684. oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;
  5685. $.getJSON( oSettings.oLanguage.sUrl, null, function( json ) {
  5686. _fnLanguageCompat( json );
  5687. $.extend( true, oSettings.oLanguage, oInit.oLanguage, json );
  5688. _fnInitialise( oSettings );
  5689. } );
  5690. bInitHandedOff = true;
  5691. }
  5692. else
  5693. {
  5694. $.extend( true, oSettings.oLanguage, oInit.oLanguage );
  5695. }
  5696. /*
  5697. * Stripes
  5698. */
  5699. if ( oInit.asStripeClasses === null )
  5700. {
  5701. oSettings.asStripeClasses =[
  5702. oSettings.oClasses.sStripeOdd,
  5703. oSettings.oClasses.sStripeEven
  5704. ];
  5705. }
  5706. /* Remove row stripe classes if they are already on the table row */
  5707. var bStripeRemove = false;
  5708. var anRows = $(this).children('tbody').children('tr');
  5709. for ( i=0, iLen=oSettings.asStripeClasses.length ; i<iLen ; i++ )
  5710. {
  5711. if ( anRows.filter(":lt(2)").hasClass( oSettings.asStripeClasses[i]) )
  5712. {
  5713. bStripeRemove = true;
  5714. break;
  5715. }
  5716. }
  5717. if ( bStripeRemove )
  5718. {
  5719. /* Store the classes which we are about to remove so they can be readded on destroy */
  5720. oSettings.asDestroyStripes = [ '', '' ];
  5721. if ( $(anRows[0]).hasClass(oSettings.oClasses.sStripeOdd) )
  5722. {
  5723. oSettings.asDestroyStripes[0] += oSettings.oClasses.sStripeOdd+" ";
  5724. }
  5725. if ( $(anRows[0]).hasClass(oSettings.oClasses.sStripeEven) )
  5726. {
  5727. oSettings.asDestroyStripes[0] += oSettings.oClasses.sStripeEven;
  5728. }
  5729. if ( $(anRows[1]).hasClass(oSettings.oClasses.sStripeOdd) )
  5730. {
  5731. oSettings.asDestroyStripes[1] += oSettings.oClasses.sStripeOdd+" ";
  5732. }
  5733. if ( $(anRows[1]).hasClass(oSettings.oClasses.sStripeEven) )
  5734. {
  5735. oSettings.asDestroyStripes[1] += oSettings.oClasses.sStripeEven;
  5736. }
  5737. anRows.removeClass( oSettings.asStripeClasses.join(' ') );
  5738. }
  5739. /*
  5740. * Columns
  5741. * See if we should load columns automatically or use defined ones
  5742. */
  5743. var anThs = [];
  5744. var aoColumnsInit;
  5745. var nThead = this.getElementsByTagName('thead');
  5746. if ( nThead.length !== 0 )
  5747. {
  5748. _fnDetectHeader( oSettings.aoHeader, nThead[0] );
  5749. anThs = _fnGetUniqueThs( oSettings );
  5750. }
  5751. /* If not given a column array, generate one with nulls */
  5752. if ( oInit.aoColumns === null )
  5753. {
  5754. aoColumnsInit = [];
  5755. for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
  5756. {
  5757. aoColumnsInit.push( null );
  5758. }
  5759. }
  5760. else
  5761. {
  5762. aoColumnsInit = oInit.aoColumns;
  5763. }
  5764. /* Add the columns */
  5765. for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
  5766. {
  5767. /* Short cut - use the loop to check if we have column visibility state to restore */
  5768. if ( oInit.saved_aoColumns !== undefined && oInit.saved_aoColumns.length == iLen )
  5769. {
  5770. if ( aoColumnsInit[i] === null )
  5771. {
  5772. aoColumnsInit[i] = {};
  5773. }
  5774. aoColumnsInit[i].bVisible = oInit.saved_aoColumns[i].bVisible;
  5775. }
  5776. _fnAddColumn( oSettings, anThs ? anThs[i] : null );
  5777. }
  5778. /* Apply the column definitions */
  5779. _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
  5780. _fnColumnOptions( oSettings, iCol, oDef );
  5781. } );
  5782. /*
  5783. * Sorting
  5784. * Check the aaSorting array
  5785. */
  5786. for ( i=0, iLen=oSettings.aaSorting.length ; i<iLen ; i++ )
  5787. {
  5788. if ( oSettings.aaSorting[i][0] >= oSettings.aoColumns.length )
  5789. {
  5790. oSettings.aaSorting[i][0] = 0;
  5791. }
  5792. var oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ];
  5793. /* Add a default sorting index */
  5794. if ( oSettings.aaSorting[i][2] === undefined )
  5795. {
  5796. oSettings.aaSorting[i][2] = 0;
  5797. }
  5798. /* If aaSorting is not defined, then we use the first indicator in asSorting */
  5799. if ( oInit.aaSorting === undefined && oSettings.saved_aaSorting === undefined )
  5800. {
  5801. oSettings.aaSorting[i][1] = oColumn.asSorting[0];
  5802. }
  5803. /* Set the current sorting index based on aoColumns.asSorting */
  5804. for ( j=0, jLen=oColumn.asSorting.length ; j<jLen ; j++ )
  5805. {
  5806. if ( oSettings.aaSorting[i][1] == oColumn.asSorting[j] )
  5807. {
  5808. oSettings.aaSorting[i][2] = j;
  5809. break;
  5810. }
  5811. }
  5812. }
  5813. /* Do a first pass on the sorting classes (allows any size changes to be taken into
  5814. * account, and also will apply sorting disabled classes if disabled
  5815. */
  5816. _fnSortingClasses( oSettings );
  5817. /*
  5818. * Final init
  5819. * Cache the header, body and footer as required, creating them if needed
  5820. */
  5821. // Work around for Webkit bug 83867 - store the caption-side before removing from doc
  5822. var captions = $(this).children('caption').each( function () {
  5823. this._captionSide = $(this).css('caption-side');
  5824. } );
  5825. var thead = $(this).children('thead');
  5826. if ( thead.length === 0 )
  5827. {
  5828. thead = [ document.createElement( 'thead' ) ];
  5829. this.appendChild( thead[0] );
  5830. }
  5831. oSettings.nTHead = thead[0];
  5832. var tbody = $(this).children('tbody');
  5833. if ( tbody.length === 0 )
  5834. {
  5835. tbody = [ document.createElement( 'tbody' ) ];
  5836. this.appendChild( tbody[0] );
  5837. }
  5838. oSettings.nTBody = tbody[0];
  5839. oSettings.nTBody.setAttribute( "role", "alert" );
  5840. oSettings.nTBody.setAttribute( "aria-live", "polite" );
  5841. oSettings.nTBody.setAttribute( "aria-relevant", "all" );
  5842. var tfoot = $(this).children('tfoot');
  5843. if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
  5844. {
  5845. // If we are a scrolling table, and no footer has been given, then we need to create
  5846. // a tfoot element for the caption element to be appended to
  5847. tfoot = [ document.createElement( 'tfoot' ) ];
  5848. this.appendChild( tfoot[0] );
  5849. }
  5850. if ( tfoot.length > 0 )
  5851. {
  5852. oSettings.nTFoot = tfoot[0];
  5853. _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
  5854. }
  5855. /* Check if there is data passing into the constructor */
  5856. if ( bUsePassedData )
  5857. {
  5858. for ( i=0 ; i<oInit.aaData.length ; i++ )
  5859. {
  5860. _fnAddData( oSettings, oInit.aaData[ i ] );
  5861. }
  5862. }
  5863. else
  5864. {
  5865. /* Grab the data from the page */
  5866. _fnGatherData( oSettings );
  5867. }
  5868. /* Copy the data index array */
  5869. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  5870. /* Initialisation complete - table can be drawn */
  5871. oSettings.bInitialised = true;
  5872. /* Check if we need to initialise the table (it might not have been handed off to the
  5873. * language processor)
  5874. */
  5875. if ( bInitHandedOff === false )
  5876. {
  5877. _fnInitialise( oSettings );
  5878. }
  5879. } );
  5880. };
  5881. /**
  5882. * Provide a common method for plug-ins to check the version of DataTables being used, in order
  5883. * to ensure compatibility.
  5884. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
  5885. * formats "X" and "X.Y" are also acceptable.
  5886. * @returns {boolean} true if this version of DataTables is greater or equal to the required
  5887. * version, or false if this version of DataTales is not suitable
  5888. * @static
  5889. * @dtopt API-Static
  5890. *
  5891. * @example
  5892. * alert( $.fn.dataTable.fnVersionCheck( '1.9.0' ) );
  5893. */
  5894. DataTable.fnVersionCheck = function( sVersion )
  5895. {
  5896. /* This is cheap, but effective */
  5897. var fnZPad = function (Zpad, count)
  5898. {
  5899. while(Zpad.length < count) {
  5900. Zpad += '0';
  5901. }
  5902. return Zpad;
  5903. };
  5904. var aThis = DataTable.ext.sVersion.split('.');
  5905. var aThat = sVersion.split('.');
  5906. var sThis = '', sThat = '';
  5907. for ( var i=0, iLen=aThat.length ; i<iLen ; i++ )
  5908. {
  5909. sThis += fnZPad( aThis[i], 3 );
  5910. sThat += fnZPad( aThat[i], 3 );
  5911. }
  5912. return parseInt(sThis, 10) >= parseInt(sThat, 10);
  5913. };
  5914. /**
  5915. * Check if a TABLE node is a DataTable table already or not.
  5916. * @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other
  5917. * node types can be passed in, but will always return false).
  5918. * @returns {boolean} true the table given is a DataTable, or false otherwise
  5919. * @static
  5920. * @dtopt API-Static
  5921. *
  5922. * @example
  5923. * var ex = document.getElementById('example');
  5924. * if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) {
  5925. * $(ex).dataTable();
  5926. * }
  5927. */
  5928. DataTable.fnIsDataTable = function ( nTable )
  5929. {
  5930. var o = DataTable.settings;
  5931. for ( var i=0 ; i<o.length ; i++ )
  5932. {
  5933. if ( o[i].nTable === nTable || o[i].nScrollHead === nTable || o[i].nScrollFoot === nTable )
  5934. {
  5935. return true;
  5936. }
  5937. }
  5938. return false;
  5939. };
  5940. /**
  5941. * Get all DataTable tables that have been initialised - optionally you can select to
  5942. * get only currently visible tables.
  5943. * @param {boolean} [bVisible=false] Flag to indicate if you want all (default) or
  5944. * visible tables only.
  5945. * @returns {array} Array of TABLE nodes (not DataTable instances) which are DataTables
  5946. * @static
  5947. * @dtopt API-Static
  5948. *
  5949. * @example
  5950. * var table = $.fn.dataTable.fnTables(true);
  5951. * if ( table.length > 0 ) {
  5952. * $(table).dataTable().fnAdjustColumnSizing();
  5953. * }
  5954. */
  5955. DataTable.fnTables = function ( bVisible )
  5956. {
  5957. var out = [];
  5958. jQuery.each( DataTable.settings, function (i, o) {
  5959. if ( !bVisible || (bVisible === true && $(o.nTable).is(':visible')) )
  5960. {
  5961. out.push( o.nTable );
  5962. }
  5963. } );
  5964. return out;
  5965. };
  5966. /**
  5967. * Version string for plug-ins to check compatibility. Allowed format is
  5968. * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
  5969. * e are optional
  5970. * @member
  5971. * @type string
  5972. * @default Version number
  5973. */
  5974. DataTable.version = "1.9.2";
  5975. /**
  5976. * Private data store, containing all of the settings objects that are created for the
  5977. * tables on a given page.
  5978. *
  5979. * Note that the <i>DataTable.settings</i> object is aliased to <i>jQuery.fn.dataTableExt</i>
  5980. * through which it may be accessed and manipulated, or <i>jQuery.fn.dataTable.settings</i>.
  5981. * @member
  5982. * @type array
  5983. * @default []
  5984. * @private
  5985. */
  5986. DataTable.settings = [];
  5987. /**
  5988. * Object models container, for the various models that DataTables has available
  5989. * to it. These models define the objects that are used to hold the active state
  5990. * and configuration of the table.
  5991. * @namespace
  5992. */
  5993. DataTable.models = {};
  5994. /**
  5995. * DataTables extension options and plug-ins. This namespace acts as a collection "area"
  5996. * for plug-ins that can be used to extend the default DataTables behaviour - indeed many
  5997. * of the build in methods use this method to provide their own capabilities (sorting methods
  5998. * for example).
  5999. *
  6000. * Note that this namespace is aliased to jQuery.fn.dataTableExt so it can be readily accessed
  6001. * and modified by plug-ins.
  6002. * @namespace
  6003. */
  6004. DataTable.models.ext = {
  6005. /**
  6006. * Plug-in filtering functions - this method of filtering is complimentary to the default
  6007. * type based filtering, and a lot more comprehensive as it allows you complete control
  6008. * over the filtering logic. Each element in this array is a function (parameters
  6009. * described below) that is called for every row in the table, and your logic decides if
  6010. * it should be included in the filtered data set or not.
  6011. * <ul>
  6012. * <li>
  6013. * Function input parameters:
  6014. * <ul>
  6015. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  6016. * <li>{array|object} Data for the row to be processed (same as the original format
  6017. * that was passed in as the data source, or an array from a DOM data source</li>
  6018. * <li>{int} Row index in aoData ({@link DataTable.models.oSettings.aoData}), which can
  6019. * be useful to retrieve the TR element if you need DOM interaction.</li>
  6020. * </ul>
  6021. * </li>
  6022. * <li>
  6023. * Function return:
  6024. * <ul>
  6025. * <li>{boolean} Include the row in the filtered result set (true) or not (false)</li>
  6026. * </ul>
  6027. * </il>
  6028. * </ul>
  6029. * @type array
  6030. * @default []
  6031. *
  6032. * @example
  6033. * // The following example shows custom filtering being applied to the fourth column (i.e.
  6034. * // the aData[3] index) based on two input values from the end-user, matching the data in
  6035. * // a certain range.
  6036. * $.fn.dataTableExt.afnFiltering.push(
  6037. * function( oSettings, aData, iDataIndex ) {
  6038. * var iMin = document.getElementById('min').value * 1;
  6039. * var iMax = document.getElementById('max').value * 1;
  6040. * var iVersion = aData[3] == "-" ? 0 : aData[3]*1;
  6041. * if ( iMin == "" && iMax == "" ) {
  6042. * return true;
  6043. * }
  6044. * else if ( iMin == "" && iVersion < iMax ) {
  6045. * return true;
  6046. * }
  6047. * else if ( iMin < iVersion && "" == iMax ) {
  6048. * return true;
  6049. * }
  6050. * else if ( iMin < iVersion && iVersion < iMax ) {
  6051. * return true;
  6052. * }
  6053. * return false;
  6054. * }
  6055. * );
  6056. */
  6057. "afnFiltering": [],
  6058. /**
  6059. * Plug-in sorting functions - this method of sorting is complimentary to the default type
  6060. * based sorting that DataTables does automatically, allowing much greater control over the
  6061. * the data that is being used to sort a column. This is useful if you want to do sorting
  6062. * based on live data (for example the contents of an 'input' element) rather than just the
  6063. * static string that DataTables knows of. The way these plug-ins work is that you create
  6064. * an array of the values you wish to be sorted for the column in question and then return
  6065. * that array. Which pre-sorting function is run here depends on the sSortDataType parameter
  6066. * that is used for the column (if any). This is the corollary of <i>ofnSearch</i> for sort
  6067. * data.
  6068. * <ul>
  6069. * <li>
  6070. * Function input parameters:
  6071. * <ul>
  6072. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  6073. * <li>{int} Target column index</li>
  6074. * </ul>
  6075. * </li>
  6076. * <li>
  6077. * Function return:
  6078. * <ul>
  6079. * <li>{array} Data for the column to be sorted upon</li>
  6080. * </ul>
  6081. * </il>
  6082. * </ul>
  6083. *
  6084. * Note that as of v1.9, it is typically preferable to use <i>mDataProp</i> to prepare data for
  6085. * the different uses that DataTables can put the data to. Specifically <i>mDataProp</i> when
  6086. * used as a function will give you a 'type' (sorting, filtering etc) that you can use to
  6087. * prepare the data as required for the different types. As such, this method is deprecated.
  6088. * @type array
  6089. * @default []
  6090. * @deprecated
  6091. *
  6092. * @example
  6093. * // Updating the cached sorting information with user entered values in HTML input elements
  6094. * jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn )
  6095. * {
  6096. * var aData = [];
  6097. * $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
  6098. * aData.push( this.value );
  6099. * } );
  6100. * return aData;
  6101. * }
  6102. */
  6103. "afnSortData": [],
  6104. /**
  6105. * Feature plug-ins - This is an array of objects which describe the feature plug-ins that are
  6106. * available to DataTables. These feature plug-ins are accessible through the sDom initialisation
  6107. * option. As such, each feature plug-in must describe a function that is used to initialise
  6108. * itself (fnInit), a character so the feature can be enabled by sDom (cFeature) and the name
  6109. * of the feature (sFeature). Thus the objects attached to this method must provide:
  6110. * <ul>
  6111. * <li>{function} fnInit Initialisation of the plug-in
  6112. * <ul>
  6113. * <li>
  6114. * Function input parameters:
  6115. * <ul>
  6116. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  6117. * </ul>
  6118. * </li>
  6119. * <li>
  6120. * Function return:
  6121. * <ul>
  6122. * <li>{node|null} The element which contains your feature. Note that the return
  6123. * may also be void if your plug-in does not require to inject any DOM elements
  6124. * into DataTables control (sDom) - for example this might be useful when
  6125. * developing a plug-in which allows table control via keyboard entry.</li>
  6126. * </ul>
  6127. * </il>
  6128. * </ul>
  6129. * </li>
  6130. * <li>{character} cFeature Character that will be matched in sDom - case sensitive</li>
  6131. * <li>{string} sFeature Feature name</li>
  6132. * </ul>
  6133. * @type array
  6134. * @default []
  6135. *
  6136. * @example
  6137. * // How TableTools initialises itself.
  6138. * $.fn.dataTableExt.aoFeatures.push( {
  6139. * "fnInit": function( oSettings ) {
  6140. * return new TableTools( { "oDTSettings": oSettings } );
  6141. * },
  6142. * "cFeature": "T",
  6143. * "sFeature": "TableTools"
  6144. * } );
  6145. */
  6146. "aoFeatures": [],
  6147. /**
  6148. * Type detection plug-in functions - DataTables utilises types to define how sorting and
  6149. * filtering behave, and types can be either be defined by the developer (sType for the
  6150. * column) or they can be automatically detected by the methods in this array. The functions
  6151. * defined in the array are quite simple, taking a single parameter (the data to analyse)
  6152. * and returning the type if it is a known type, or null otherwise.
  6153. * <ul>
  6154. * <li>
  6155. * Function input parameters:
  6156. * <ul>
  6157. * <li>{*} Data from the column cell to be analysed</li>
  6158. * </ul>
  6159. * </li>
  6160. * <li>
  6161. * Function return:
  6162. * <ul>
  6163. * <li>{string|null} Data type detected, or null if unknown (and thus pass it
  6164. * on to the other type detection functions.</li>
  6165. * </ul>
  6166. * </il>
  6167. * </ul>
  6168. * @type array
  6169. * @default []
  6170. *
  6171. * @example
  6172. * // Currency type detection plug-in:
  6173. * jQuery.fn.dataTableExt.aTypes.push(
  6174. * function ( sData ) {
  6175. * var sValidChars = "0123456789.-";
  6176. * var Char;
  6177. *
  6178. * // Check the numeric part
  6179. * for ( i=1 ; i<sData.length ; i++ ) {
  6180. * Char = sData.charAt(i);
  6181. * if (sValidChars.indexOf(Char) == -1) {
  6182. * return null;
  6183. * }
  6184. * }
  6185. *
  6186. * // Check prefixed by currency
  6187. * if ( sData.charAt(0) == '$' || sData.charAt(0) == '&pound;' ) {
  6188. * return 'currency';
  6189. * }
  6190. * return null;
  6191. * }
  6192. * );
  6193. */
  6194. "aTypes": [],
  6195. /**
  6196. * Provide a common method for plug-ins to check the version of DataTables being used,
  6197. * in order to ensure compatibility.
  6198. * @type function
  6199. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note
  6200. * that the formats "X" and "X.Y" are also acceptable.
  6201. * @returns {boolean} true if this version of DataTables is greater or equal to the
  6202. * required version, or false if this version of DataTales is not suitable
  6203. *
  6204. * @example
  6205. * $(document).ready(function() {
  6206. * var oTable = $('#example').dataTable();
  6207. * alert( oTable.fnVersionCheck( '1.9.0' ) );
  6208. * } );
  6209. */
  6210. "fnVersionCheck": DataTable.fnVersionCheck,
  6211. /**
  6212. * Index for what 'this' index API functions should use
  6213. * @type int
  6214. * @default 0
  6215. */
  6216. "iApiIndex": 0,
  6217. /**
  6218. * Pre-processing of filtering data plug-ins - When you assign the sType for a column
  6219. * (or have it automatically detected for you by DataTables or a type detection plug-in),
  6220. * you will typically be using this for custom sorting, but it can also be used to provide
  6221. * custom filtering by allowing you to pre-processing the data and returning the data in
  6222. * the format that should be filtered upon. This is done by adding functions this object
  6223. * with a parameter name which matches the sType for that target column. This is the
  6224. * corollary of <i>afnSortData</i> for filtering data.
  6225. * <ul>
  6226. * <li>
  6227. * Function input parameters:
  6228. * <ul>
  6229. * <li>{*} Data from the column cell to be prepared for filtering</li>
  6230. * </ul>
  6231. * </li>
  6232. * <li>
  6233. * Function return:
  6234. * <ul>
  6235. * <li>{string|null} Formatted string that will be used for the filtering.</li>
  6236. * </ul>
  6237. * </il>
  6238. * </ul>
  6239. *
  6240. * Note that as of v1.9, it is typically preferable to use <i>mDataProp</i> to prepare data for
  6241. * the different uses that DataTables can put the data to. Specifically <i>mDataProp</i> when
  6242. * used as a function will give you a 'type' (sorting, filtering etc) that you can use to
  6243. * prepare the data as required for the different types. As such, this method is deprecated.
  6244. * @type object
  6245. * @default {}
  6246. * @deprecated
  6247. *
  6248. * @example
  6249. * $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) {
  6250. * return sData.replace(/\n/g," ").replace( /<.*?>/g, "" );
  6251. * }
  6252. */
  6253. "ofnSearch": {},
  6254. /**
  6255. * Container for all private functions in DataTables so they can be exposed externally
  6256. * @type object
  6257. * @default {}
  6258. */
  6259. "oApi": {},
  6260. /**
  6261. * Storage for the various classes that DataTables uses
  6262. * @type object
  6263. * @default {}
  6264. */
  6265. "oStdClasses": {},
  6266. /**
  6267. * Storage for the various classes that DataTables uses - jQuery UI suitable
  6268. * @type object
  6269. * @default {}
  6270. */
  6271. "oJUIClasses": {},
  6272. /**
  6273. * Pagination plug-in methods - The style and controls of the pagination can significantly
  6274. * impact on how the end user interacts with the data in your table, and DataTables allows
  6275. * the addition of pagination controls by extending this object, which can then be enabled
  6276. * through the <i>sPaginationType</i> initialisation parameter. Each pagination type that
  6277. * is added is an object (the property name of which is what <i>sPaginationType</i> refers
  6278. * to) that has two properties, both methods that are used by DataTables to update the
  6279. * control's state.
  6280. * <ul>
  6281. * <li>
  6282. * fnInit - Initialisation of the paging controls. Called only during initialisation
  6283. * of the table. It is expected that this function will add the required DOM elements
  6284. * to the page for the paging controls to work. The element pointer
  6285. * 'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging
  6286. * controls (note that this is a 2D array to allow for multiple instances of each
  6287. * DataTables DOM element). It is suggested that you add the controls to this element
  6288. * as children
  6289. * <ul>
  6290. * <li>
  6291. * Function input parameters:
  6292. * <ul>
  6293. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  6294. * <li>{node} Container into which the pagination controls must be inserted</li>
  6295. * <li>{function} Draw callback function - whenever the controls cause a page
  6296. * change, this method must be called to redraw the table.</li>
  6297. * </ul>
  6298. * </li>
  6299. * <li>
  6300. * Function return:
  6301. * <ul>
  6302. * <li>No return required</li>
  6303. * </ul>
  6304. * </il>
  6305. * </ul>
  6306. * </il>
  6307. * <li>
  6308. * fnInit - This function is called whenever the paging status of the table changes and is
  6309. * typically used to update classes and/or text of the paging controls to reflex the new
  6310. * status.
  6311. * <ul>
  6312. * <li>
  6313. * Function input parameters:
  6314. * <ul>
  6315. * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
  6316. * <li>{function} Draw callback function - in case you need to redraw the table again
  6317. * or attach new event listeners</li>
  6318. * </ul>
  6319. * </li>
  6320. * <li>
  6321. * Function return:
  6322. * <ul>
  6323. * <li>No return required</li>
  6324. * </ul>
  6325. * </il>
  6326. * </ul>
  6327. * </il>
  6328. * </ul>
  6329. * @type object
  6330. * @default {}
  6331. *
  6332. * @example
  6333. * $.fn.dataTableExt.oPagination.four_button = {
  6334. * "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) {
  6335. * nFirst = document.createElement( 'span' );
  6336. * nPrevious = document.createElement( 'span' );
  6337. * nNext = document.createElement( 'span' );
  6338. * nLast = document.createElement( 'span' );
  6339. *
  6340. * nFirst.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sFirst ) );
  6341. * nPrevious.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sPrevious ) );
  6342. * nNext.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sNext ) );
  6343. * nLast.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sLast ) );
  6344. *
  6345. * nFirst.className = "paginate_button first";
  6346. * nPrevious.className = "paginate_button previous";
  6347. * nNext.className="paginate_button next";
  6348. * nLast.className = "paginate_button last";
  6349. *
  6350. * nPaging.appendChild( nFirst );
  6351. * nPaging.appendChild( nPrevious );
  6352. * nPaging.appendChild( nNext );
  6353. * nPaging.appendChild( nLast );
  6354. *
  6355. * $(nFirst).click( function () {
  6356. * oSettings.oApi._fnPageChange( oSettings, "first" );
  6357. * fnCallbackDraw( oSettings );
  6358. * } );
  6359. *
  6360. * $(nPrevious).click( function() {
  6361. * oSettings.oApi._fnPageChange( oSettings, "previous" );
  6362. * fnCallbackDraw( oSettings );
  6363. * } );
  6364. *
  6365. * $(nNext).click( function() {
  6366. * oSettings.oApi._fnPageChange( oSettings, "next" );
  6367. * fnCallbackDraw( oSettings );
  6368. * } );
  6369. *
  6370. * $(nLast).click( function() {
  6371. * oSettings.oApi._fnPageChange( oSettings, "last" );
  6372. * fnCallbackDraw( oSettings );
  6373. * } );
  6374. *
  6375. * $(nFirst).bind( 'selectstart', function () { return false; } );
  6376. * $(nPrevious).bind( 'selectstart', function () { return false; } );
  6377. * $(nNext).bind( 'selectstart', function () { return false; } );
  6378. * $(nLast).bind( 'selectstart', function () { return false; } );
  6379. * },
  6380. *
  6381. * "fnUpdate": function ( oSettings, fnCallbackDraw ) {
  6382. * if ( !oSettings.aanFeatures.p ) {
  6383. * return;
  6384. * }
  6385. *
  6386. * // Loop over each instance of the pager
  6387. * var an = oSettings.aanFeatures.p;
  6388. * for ( var i=0, iLen=an.length ; i<iLen ; i++ ) {
  6389. * var buttons = an[i].getElementsByTagName('span');
  6390. * if ( oSettings._iDisplayStart === 0 ) {
  6391. * buttons[0].className = "paginate_disabled_previous";
  6392. * buttons[1].className = "paginate_disabled_previous";
  6393. * }
  6394. * else {
  6395. * buttons[0].className = "paginate_enabled_previous";
  6396. * buttons[1].className = "paginate_enabled_previous";
  6397. * }
  6398. *
  6399. * if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) {
  6400. * buttons[2].className = "paginate_disabled_next";
  6401. * buttons[3].className = "paginate_disabled_next";
  6402. * }
  6403. * else {
  6404. * buttons[2].className = "paginate_enabled_next";
  6405. * buttons[3].className = "paginate_enabled_next";
  6406. * }
  6407. * }
  6408. * }
  6409. * };
  6410. */
  6411. "oPagination": {},
  6412. /**
  6413. * Sorting plug-in methods - Sorting in DataTables is based on the detected type of the
  6414. * data column (you can add your own type detection functions, or override automatic
  6415. * detection using sType). With this specific type given to the column, DataTables will
  6416. * apply the required sort from the functions in the object. Each sort type must provide
  6417. * two mandatory methods, one each for ascending and descending sorting, and can optionally
  6418. * provide a pre-formatting method that will help speed up sorting by allowing DataTables
  6419. * to pre-format the sort data only once (rather than every time the actual sort functions
  6420. * are run). The two sorting functions are typical Javascript sort methods:
  6421. * <ul>
  6422. * <li>
  6423. * Function input parameters:
  6424. * <ul>
  6425. * <li>{*} Data to compare to the second parameter</li>
  6426. * <li>{*} Data to compare to the first parameter</li>
  6427. * </ul>
  6428. * </li>
  6429. * <li>
  6430. * Function return:
  6431. * <ul>
  6432. * <li>{int} Sorting match: <0 if first parameter should be sorted lower than
  6433. * the second parameter, ===0 if the two parameters are equal and >0 if
  6434. * the first parameter should be sorted height than the second parameter.</li>
  6435. * </ul>
  6436. * </il>
  6437. * </ul>
  6438. * @type object
  6439. * @default {}
  6440. *
  6441. * @example
  6442. * // Case-sensitive string sorting, with no pre-formatting method
  6443. * $.extend( $.fn.dataTableExt.oSort, {
  6444. * "string-case-asc": function(x,y) {
  6445. * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  6446. * },
  6447. * "string-case-desc": function(x,y) {
  6448. * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  6449. * }
  6450. * } );
  6451. *
  6452. * @example
  6453. * // Case-insensitive string sorting, with pre-formatting
  6454. * $.extend( $.fn.dataTableExt.oSort, {
  6455. * "string-pre": function(x) {
  6456. * return x.toLowerCase();
  6457. * },
  6458. * "string-asc": function(x,y) {
  6459. * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  6460. * },
  6461. * "string-desc": function(x,y) {
  6462. * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  6463. * }
  6464. * } );
  6465. */
  6466. "oSort": {},
  6467. /**
  6468. * Version string for plug-ins to check compatibility. Allowed format is
  6469. * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
  6470. * e are optional
  6471. * @type string
  6472. * @default Version number
  6473. */
  6474. "sVersion": DataTable.version,
  6475. /**
  6476. * How should DataTables report an error. Can take the value 'alert' or 'throw'
  6477. * @type string
  6478. * @default alert
  6479. */
  6480. "sErrMode": "alert",
  6481. /**
  6482. * Store information for DataTables to access globally about other instances
  6483. * @namespace
  6484. * @private
  6485. */
  6486. "_oExternConfig": {
  6487. /* int:iNextUnique - next unique number for an instance */
  6488. "iNextUnique": 0
  6489. }
  6490. };
  6491. /**
  6492. * Template object for the way in which DataTables holds information about
  6493. * search information for the global filter and individual column filters.
  6494. * @namespace
  6495. */
  6496. DataTable.models.oSearch = {
  6497. /**
  6498. * Flag to indicate if the filtering should be case insensitive or not
  6499. * @type boolean
  6500. * @default true
  6501. */
  6502. "bCaseInsensitive": true,
  6503. /**
  6504. * Applied search term
  6505. * @type string
  6506. * @default <i>Empty string</i>
  6507. */
  6508. "sSearch": "",
  6509. /**
  6510. * Flag to indicate if the search term should be interpreted as a
  6511. * regular expression (true) or not (false) and therefore and special
  6512. * regex characters escaped.
  6513. * @type boolean
  6514. * @default false
  6515. */
  6516. "bRegex": false,
  6517. /**
  6518. * Flag to indicate if DataTables is to use its smart filtering or not.
  6519. * @type boolean
  6520. * @default true
  6521. */
  6522. "bSmart": true
  6523. };
  6524. /**
  6525. * Template object for the way in which DataTables holds information about
  6526. * each individual row. This is the object format used for the settings
  6527. * aoData array.
  6528. * @namespace
  6529. */
  6530. DataTable.models.oRow = {
  6531. /**
  6532. * TR element for the row
  6533. * @type node
  6534. * @default null
  6535. */
  6536. "nTr": null,
  6537. /**
  6538. * Data object from the original data source for the row. This is either
  6539. * an array if using the traditional form of DataTables, or an object if
  6540. * using mDataProp options. The exact type will depend on the passed in
  6541. * data from the data source, or will be an array if using DOM a data
  6542. * source.
  6543. * @type array|object
  6544. * @default []
  6545. */
  6546. "_aData": [],
  6547. /**
  6548. * Sorting data cache - this array is ostensibly the same length as the
  6549. * number of columns (although each index is generated only as it is
  6550. * needed), and holds the data that is used for sorting each column in the
  6551. * row. We do this cache generation at the start of the sort in order that
  6552. * the formatting of the sort data need be done only once for each cell
  6553. * per sort. This array should not be read from or written to by anything
  6554. * other than the master sorting methods.
  6555. * @type array
  6556. * @default []
  6557. * @private
  6558. */
  6559. "_aSortData": [],
  6560. /**
  6561. * Array of TD elements that are cached for hidden rows, so they can be
  6562. * reinserted into the table if a column is made visible again (or to act
  6563. * as a store if a column is made hidden). Only hidden columns have a
  6564. * reference in the array. For non-hidden columns the value is either
  6565. * undefined or null.
  6566. * @type array nodes
  6567. * @default []
  6568. * @private
  6569. */
  6570. "_anHidden": [],
  6571. /**
  6572. * Cache of the class name that DataTables has applied to the row, so we
  6573. * can quickly look at this variable rather than needing to do a DOM check
  6574. * on className for the nTr property.
  6575. * @type string
  6576. * @default <i>Empty string</i>
  6577. * @private
  6578. */
  6579. "_sRowStripe": ""
  6580. };
  6581. /**
  6582. * Template object for the column information object in DataTables. This object
  6583. * is held in the settings aoColumns array and contains all the information that
  6584. * DataTables needs about each individual column.
  6585. *
  6586. * Note that this object is related to {@link DataTable.defaults.columns}
  6587. * but this one is the internal data store for DataTables's cache of columns.
  6588. * It should NOT be manipulated outside of DataTables. Any configuration should
  6589. * be done through the initialisation options.
  6590. * @namespace
  6591. */
  6592. DataTable.models.oColumn = {
  6593. /**
  6594. * A list of the columns that sorting should occur on when this column
  6595. * is sorted. That this property is an array allows multi-column sorting
  6596. * to be defined for a column (for example first name / last name columns
  6597. * would benefit from this). The values are integers pointing to the
  6598. * columns to be sorted on (typically it will be a single integer pointing
  6599. * at itself, but that doesn't need to be the case).
  6600. * @type array
  6601. */
  6602. "aDataSort": null,
  6603. /**
  6604. * Define the sorting directions that are applied to the column, in sequence
  6605. * as the column is repeatedly sorted upon - i.e. the first value is used
  6606. * as the sorting direction when the column if first sorted (clicked on).
  6607. * Sort it again (click again) and it will move on to the next index.
  6608. * Repeat until loop.
  6609. * @type array
  6610. */
  6611. "asSorting": null,
  6612. /**
  6613. * Flag to indicate if the column is searchable, and thus should be included
  6614. * in the filtering or not.
  6615. * @type boolean
  6616. */
  6617. "bSearchable": null,
  6618. /**
  6619. * Flag to indicate if the column is sortable or not.
  6620. * @type boolean
  6621. */
  6622. "bSortable": null,
  6623. /**
  6624. * When using fnRender, you have two options for what to do with the data,
  6625. * and this property serves as the switch. Firstly, you can have the sorting
  6626. * and filtering use the rendered value (true - default), or you can have
  6627. * the sorting and filtering us the original value (false).
  6628. *
  6629. * *NOTE* It is it is advisable now to use mDataProp as a function and make
  6630. * use of the 'type' that it gives, allowing (potentially) different data to
  6631. * be used for sorting, filtering, display and type detection.
  6632. * @type boolean
  6633. * @deprecated
  6634. */
  6635. "bUseRendered": null,
  6636. /**
  6637. * Flag to indicate if the column is currently visible in the table or not
  6638. * @type boolean
  6639. */
  6640. "bVisible": null,
  6641. /**
  6642. * Flag to indicate to the type detection method if the automatic type
  6643. * detection should be used, or if a column type (sType) has been specified
  6644. * @type boolean
  6645. * @default true
  6646. * @private
  6647. */
  6648. "_bAutoType": true,
  6649. /**
  6650. * Developer definable function that is called whenever a cell is created (Ajax source,
  6651. * etc) or processed for input (DOM source). This can be used as a compliment to fnRender
  6652. * allowing you to modify the DOM element (add background colour for example) when the
  6653. * element is available (since it is not when fnRender is called).
  6654. * @type function
  6655. * @param {element} nTd The TD node that has been created
  6656. * @param {*} sData The Data for the cell
  6657. * @param {array|object} oData The data for the whole row
  6658. * @param {int} iRow The row index for the aoData data store
  6659. * @default null
  6660. */
  6661. "fnCreatedCell": null,
  6662. /**
  6663. * Function to get data from a cell in a column. You should <b>never</b>
  6664. * access data directly through _aData internally in DataTables - always use
  6665. * the method attached to this property. It allows mDataProp to function as
  6666. * required. This function is automatically assigned by the column
  6667. * initialisation method
  6668. * @type function
  6669. * @param {array|object} oData The data array/object for the array
  6670. * (i.e. aoData[]._aData)
  6671. * @param {string} sSpecific The specific data type you want to get -
  6672. * 'display', 'type' 'filter' 'sort'
  6673. * @returns {*} The data for the cell from the given row's data
  6674. * @default null
  6675. */
  6676. "fnGetData": null,
  6677. /**
  6678. * Custom display function that will be called for the display of each cell
  6679. * in this column.
  6680. * @type function
  6681. * @param {object} o Object with the following parameters:
  6682. * @param {int} o.iDataRow The row in aoData
  6683. * @param {int} o.iDataColumn The column in question
  6684. * @param {array} o.aData The data for the row in question
  6685. * @param {object} o.oSettings The settings object for this DataTables instance
  6686. * @returns {string} The string you which to use in the display
  6687. * @default null
  6688. */
  6689. "fnRender": null,
  6690. /**
  6691. * Function to set data for a cell in the column. You should <b>never</b>
  6692. * set the data directly to _aData internally in DataTables - always use
  6693. * this method. It allows mDataProp to function as required. This function
  6694. * is automatically assigned by the column initialisation method
  6695. * @type function
  6696. * @param {array|object} oData The data array/object for the array
  6697. * (i.e. aoData[]._aData)
  6698. * @param {*} sValue Value to set
  6699. * @default null
  6700. */
  6701. "fnSetData": null,
  6702. /**
  6703. * Property to read the value for the cells in the column from the data
  6704. * source array / object. If null, then the default content is used, if a
  6705. * function is given then the return from the function is used.
  6706. * @type function|int|string|null
  6707. * @default null
  6708. */
  6709. "mDataProp": null,
  6710. /**
  6711. * Unique header TH/TD element for this column - this is what the sorting
  6712. * listener is attached to (if sorting is enabled.)
  6713. * @type node
  6714. * @default null
  6715. */
  6716. "nTh": null,
  6717. /**
  6718. * Unique footer TH/TD element for this column (if there is one). Not used
  6719. * in DataTables as such, but can be used for plug-ins to reference the
  6720. * footer for each column.
  6721. * @type node
  6722. * @default null
  6723. */
  6724. "nTf": null,
  6725. /**
  6726. * The class to apply to all TD elements in the table's TBODY for the column
  6727. * @type string
  6728. * @default null
  6729. */
  6730. "sClass": null,
  6731. /**
  6732. * When DataTables calculates the column widths to assign to each column,
  6733. * it finds the longest string in each column and then constructs a
  6734. * temporary table and reads the widths from that. The problem with this
  6735. * is that "mmm" is much wider then "iiii", but the latter is a longer
  6736. * string - thus the calculation can go wrong (doing it properly and putting
  6737. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  6738. * a "work around" we provide this option. It will append its value to the
  6739. * text that is found to be the longest string for the column - i.e. padding.
  6740. * @type string
  6741. */
  6742. "sContentPadding": null,
  6743. /**
  6744. * Allows a default value to be given for a column's data, and will be used
  6745. * whenever a null data source is encountered (this can be because mDataProp
  6746. * is set to null, or because the data source itself is null).
  6747. * @type string
  6748. * @default null
  6749. */
  6750. "sDefaultContent": null,
  6751. /**
  6752. * Name for the column, allowing reference to the column by name as well as
  6753. * by index (needs a lookup to work by name).
  6754. * @type string
  6755. */
  6756. "sName": null,
  6757. /**
  6758. * Custom sorting data type - defines which of the available plug-ins in
  6759. * afnSortData the custom sorting will use - if any is defined.
  6760. * @type string
  6761. * @default std
  6762. */
  6763. "sSortDataType": 'std',
  6764. /**
  6765. * Class to be applied to the header element when sorting on this column
  6766. * @type string
  6767. * @default null
  6768. */
  6769. "sSortingClass": null,
  6770. /**
  6771. * Class to be applied to the header element when sorting on this column -
  6772. * when jQuery UI theming is used.
  6773. * @type string
  6774. * @default null
  6775. */
  6776. "sSortingClassJUI": null,
  6777. /**
  6778. * Title of the column - what is seen in the TH element (nTh).
  6779. * @type string
  6780. */
  6781. "sTitle": null,
  6782. /**
  6783. * Column sorting and filtering type
  6784. * @type string
  6785. * @default null
  6786. */
  6787. "sType": null,
  6788. /**
  6789. * Width of the column
  6790. * @type string
  6791. * @default null
  6792. */
  6793. "sWidth": null,
  6794. /**
  6795. * Width of the column when it was first "encountered"
  6796. * @type string
  6797. * @default null
  6798. */
  6799. "sWidthOrig": null
  6800. };
  6801. /**
  6802. * Initialisation options that can be given to DataTables at initialisation
  6803. * time.
  6804. * @namespace
  6805. */
  6806. DataTable.defaults = {
  6807. /**
  6808. * An array of data to use for the table, passed in at initialisation which
  6809. * will be used in preference to any data which is already in the DOM. This is
  6810. * particularly useful for constructing tables purely in Javascript, for
  6811. * example with a custom Ajax call.
  6812. * @type array
  6813. * @default null
  6814. * @dtopt Option
  6815. *
  6816. * @example
  6817. * // Using a 2D array data source
  6818. * $(document).ready( function () {
  6819. * $('#example').dataTable( {
  6820. * "aaData": [
  6821. * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
  6822. * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
  6823. * ],
  6824. * "aoColumns": [
  6825. * { "sTitle": "Engine" },
  6826. * { "sTitle": "Browser" },
  6827. * { "sTitle": "Platform" },
  6828. * { "sTitle": "Version" },
  6829. * { "sTitle": "Grade" }
  6830. * ]
  6831. * } );
  6832. * } );
  6833. *
  6834. * @example
  6835. * // Using an array of objects as a data source (mDataProp)
  6836. * $(document).ready( function () {
  6837. * $('#example').dataTable( {
  6838. * "aaData": [
  6839. * {
  6840. * "engine": "Trident",
  6841. * "browser": "Internet Explorer 4.0",
  6842. * "platform": "Win 95+",
  6843. * "version": 4,
  6844. * "grade": "X"
  6845. * },
  6846. * {
  6847. * "engine": "Trident",
  6848. * "browser": "Internet Explorer 5.0",
  6849. * "platform": "Win 95+",
  6850. * "version": 5,
  6851. * "grade": "C"
  6852. * }
  6853. * ],
  6854. * "aoColumns": [
  6855. * { "sTitle": "Engine", "mDataProp": "engine" },
  6856. * { "sTitle": "Browser", "mDataProp": "browser" },
  6857. * { "sTitle": "Platform", "mDataProp": "platform" },
  6858. * { "sTitle": "Version", "mDataProp": "version" },
  6859. * { "sTitle": "Grade", "mDataProp": "grade" }
  6860. * ]
  6861. * } );
  6862. * } );
  6863. */
  6864. "aaData": null,
  6865. /**
  6866. * If sorting is enabled, then DataTables will perform a first pass sort on
  6867. * initialisation. You can define which column(s) the sort is performed upon,
  6868. * and the sorting direction, with this variable. The aaSorting array should
  6869. * contain an array for each column to be sorted initially containing the
  6870. * column's index and a direction string ('asc' or 'desc').
  6871. * @type array
  6872. * @default [[0,'asc']]
  6873. * @dtopt Option
  6874. *
  6875. * @example
  6876. * // Sort by 3rd column first, and then 4th column
  6877. * $(document).ready( function() {
  6878. * $('#example').dataTable( {
  6879. * "aaSorting": [[2,'asc'], [3,'desc']]
  6880. * } );
  6881. * } );
  6882. *
  6883. * // No initial sorting
  6884. * $(document).ready( function() {
  6885. * $('#example').dataTable( {
  6886. * "aaSorting": []
  6887. * } );
  6888. * } );
  6889. */
  6890. "aaSorting": [[0,'asc']],
  6891. /**
  6892. * This parameter is basically identical to the aaSorting parameter, but
  6893. * cannot be overridden by user interaction with the table. What this means
  6894. * is that you could have a column (visible or hidden) which the sorting will
  6895. * always be forced on first - any sorting after that (from the user) will
  6896. * then be performed as required. This can be useful for grouping rows
  6897. * together.
  6898. * @type array
  6899. * @default null
  6900. * @dtopt Option
  6901. *
  6902. * @example
  6903. * $(document).ready( function() {
  6904. * $('#example').dataTable( {
  6905. * "aaSortingFixed": [[0,'asc']]
  6906. * } );
  6907. * } )
  6908. */
  6909. "aaSortingFixed": null,
  6910. /**
  6911. * This parameter allows you to readily specify the entries in the length drop
  6912. * down menu that DataTables shows when pagination is enabled. It can be
  6913. * either a 1D array of options which will be used for both the displayed
  6914. * option and the value, or a 2D array which will use the array in the first
  6915. * position as the value, and the array in the second position as the
  6916. * displayed options (useful for language strings such as 'All').
  6917. * @type array
  6918. * @default [ 10, 25, 50, 100 ]
  6919. * @dtopt Option
  6920. *
  6921. * @example
  6922. * $(document).ready(function() {
  6923. * $('#example').dataTable( {
  6924. * "aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
  6925. * } );
  6926. * } );
  6927. *
  6928. * @example
  6929. * // Setting the default display length as well as length menu
  6930. * // This is likely to be wanted if you remove the '10' option which
  6931. * // is the iDisplayLength default.
  6932. * $(document).ready(function() {
  6933. * $('#example').dataTable( {
  6934. * "iDisplayLength": 25,
  6935. * "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]]
  6936. * } );
  6937. * } );
  6938. */
  6939. "aLengthMenu": [ 10, 25, 50, 100 ],
  6940. /**
  6941. * The aoColumns option in the initialisation parameter allows you to define
  6942. * details about the way individual columns behave. For a full list of
  6943. * column options that can be set, please see
  6944. * {@link DataTable.defaults.columns}. Note that if you use aoColumns to
  6945. * define your columns, you must have an entry in the array for every single
  6946. * column that you have in your table (these can be null if you don't which
  6947. * to specify any options).
  6948. * @member
  6949. */
  6950. "aoColumns": null,
  6951. /**
  6952. * Very similar to aoColumns, aoColumnDefs allows you to target a specific
  6953. * column, multiple columns, or all columns, using the aTargets property of
  6954. * each object in the array. This allows great flexibility when creating
  6955. * tables, as the aoColumnDefs arrays can be of any length, targeting the
  6956. * columns you specifically want. aoColumnDefs may use any of the column
  6957. * options available: {@link DataTable.defaults.columns}, but it _must_
  6958. * have aTargets defined in each object in the array. Values in the aTargets
  6959. * array may be:
  6960. * <ul>
  6961. * <li>a string - class name will be matched on the TH for the column</li>
  6962. * <li>0 or a positive integer - column index counting from the left</li>
  6963. * <li>a negative integer - column index counting from the right</li>
  6964. * <li>the string "_all" - all columns (i.e. assign a default)</li>
  6965. * </ul>
  6966. * @member
  6967. */
  6968. "aoColumnDefs": null,
  6969. /**
  6970. * Basically the same as oSearch, this parameter defines the individual column
  6971. * filtering state at initialisation time. The array must be of the same size
  6972. * as the number of columns, and each element be an object with the parameters
  6973. * "sSearch" and "bEscapeRegex" (the latter is optional). 'null' is also
  6974. * accepted and the default will be used.
  6975. * @type array
  6976. * @default []
  6977. * @dtopt Option
  6978. *
  6979. * @example
  6980. * $(document).ready( function() {
  6981. * $('#example').dataTable( {
  6982. * "aoSearchCols": [
  6983. * null,
  6984. * { "sSearch": "My filter" },
  6985. * null,
  6986. * { "sSearch": "^[0-9]", "bEscapeRegex": false }
  6987. * ]
  6988. * } );
  6989. * } )
  6990. */
  6991. "aoSearchCols": [],
  6992. /**
  6993. * An array of CSS classes that should be applied to displayed rows. This
  6994. * array may be of any length, and DataTables will apply each class
  6995. * sequentially, looping when required.
  6996. * @type array
  6997. * @default null <i>Will take the values determinted by the oClasses.sStripe*
  6998. * options</i>
  6999. * @dtopt Option
  7000. *
  7001. * @example
  7002. * $(document).ready( function() {
  7003. * $('#example').dataTable( {
  7004. * "asStripeClasses": [ 'strip1', 'strip2', 'strip3' ]
  7005. * } );
  7006. * } )
  7007. */
  7008. "asStripeClasses": null,
  7009. /**
  7010. * Enable or disable automatic column width calculation. This can be disabled
  7011. * as an optimisation (it takes some time to calculate the widths) if the
  7012. * tables widths are passed in using aoColumns.
  7013. * @type boolean
  7014. * @default true
  7015. * @dtopt Features
  7016. *
  7017. * @example
  7018. * $(document).ready( function () {
  7019. * $('#example').dataTable( {
  7020. * "bAutoWidth": false
  7021. * } );
  7022. * } );
  7023. */
  7024. "bAutoWidth": true,
  7025. /**
  7026. * Deferred rendering can provide DataTables with a huge speed boost when you
  7027. * are using an Ajax or JS data source for the table. This option, when set to
  7028. * true, will cause DataTables to defer the creation of the table elements for
  7029. * each row until they are needed for a draw - saving a significant amount of
  7030. * time.
  7031. * @type boolean
  7032. * @default false
  7033. * @dtopt Features
  7034. *
  7035. * @example
  7036. * $(document).ready(function() {
  7037. * var oTable = $('#example').dataTable( {
  7038. * "sAjaxSource": "sources/arrays.txt",
  7039. * "bDeferRender": true
  7040. * } );
  7041. * } );
  7042. */
  7043. "bDeferRender": false,
  7044. /**
  7045. * Replace a DataTable which matches the given selector and replace it with
  7046. * one which has the properties of the new initialisation object passed. If no
  7047. * table matches the selector, then the new DataTable will be constructed as
  7048. * per normal.
  7049. * @type boolean
  7050. * @default false
  7051. * @dtopt Options
  7052. *
  7053. * @example
  7054. * $(document).ready(function() {
  7055. * $('#example').dataTable( {
  7056. * "sScrollY": "200px",
  7057. * "bPaginate": false
  7058. * } );
  7059. *
  7060. * // Some time later....
  7061. * $('#example').dataTable( {
  7062. * "bFilter": false,
  7063. * "bDestroy": true
  7064. * } );
  7065. * } );
  7066. */
  7067. "bDestroy": false,
  7068. /**
  7069. * Enable or disable filtering of data. Filtering in DataTables is "smart" in
  7070. * that it allows the end user to input multiple words (space separated) and
  7071. * will match a row containing those words, even if not in the order that was
  7072. * specified (this allow matching across multiple columns). Note that if you
  7073. * wish to use filtering in DataTables this must remain 'true' - to remove the
  7074. * default filtering input box and retain filtering abilities, please use
  7075. * {@link DataTable.defaults.sDom}.
  7076. * @type boolean
  7077. * @default true
  7078. * @dtopt Features
  7079. *
  7080. * @example
  7081. * $(document).ready( function () {
  7082. * $('#example').dataTable( {
  7083. * "bFilter": false
  7084. * } );
  7085. * } );
  7086. */
  7087. "bFilter": true,
  7088. /**
  7089. * Enable or disable the table information display. This shows information
  7090. * about the data that is currently visible on the page, including information
  7091. * about filtered data if that action is being performed.
  7092. * @type boolean
  7093. * @default true
  7094. * @dtopt Features
  7095. *
  7096. * @example
  7097. * $(document).ready( function () {
  7098. * $('#example').dataTable( {
  7099. * "bInfo": false
  7100. * } );
  7101. * } );
  7102. */
  7103. "bInfo": true,
  7104. /**
  7105. * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
  7106. * slightly different and additional mark-up from what DataTables has
  7107. * traditionally used).
  7108. * @type boolean
  7109. * @default false
  7110. * @dtopt Features
  7111. *
  7112. * @example
  7113. * $(document).ready( function() {
  7114. * $('#example').dataTable( {
  7115. * "bJQueryUI": true
  7116. * } );
  7117. * } );
  7118. */
  7119. "bJQueryUI": false,
  7120. /**
  7121. * Allows the end user to select the size of a formatted page from a select
  7122. * menu (sizes are 10, 25, 50 and 100). Requires pagination (bPaginate).
  7123. * @type boolean
  7124. * @default true
  7125. * @dtopt Features
  7126. *
  7127. * @example
  7128. * $(document).ready( function () {
  7129. * $('#example').dataTable( {
  7130. * "bLengthChange": false
  7131. * } );
  7132. * } );
  7133. */
  7134. "bLengthChange": true,
  7135. /**
  7136. * Enable or disable pagination.
  7137. * @type boolean
  7138. * @default true
  7139. * @dtopt Features
  7140. *
  7141. * @example
  7142. * $(document).ready( function () {
  7143. * $('#example').dataTable( {
  7144. * "bPaginate": false
  7145. * } );
  7146. * } );
  7147. */
  7148. "bPaginate": true,
  7149. /**
  7150. * Enable or disable the display of a 'processing' indicator when the table is
  7151. * being processed (e.g. a sort). This is particularly useful for tables with
  7152. * large amounts of data where it can take a noticeable amount of time to sort
  7153. * the entries.
  7154. * @type boolean
  7155. * @default false
  7156. * @dtopt Features
  7157. *
  7158. * @example
  7159. * $(document).ready( function () {
  7160. * $('#example').dataTable( {
  7161. * "bProcessing": true
  7162. * } );
  7163. * } );
  7164. */
  7165. "bProcessing": false,
  7166. /**
  7167. * Retrieve the DataTables object for the given selector. Note that if the
  7168. * table has already been initialised, this parameter will cause DataTables
  7169. * to simply return the object that has already been set up - it will not take
  7170. * account of any changes you might have made to the initialisation object
  7171. * passed to DataTables (setting this parameter to true is an acknowledgement
  7172. * that you understand this). bDestroy can be used to reinitialise a table if
  7173. * you need.
  7174. * @type boolean
  7175. * @default false
  7176. * @dtopt Options
  7177. *
  7178. * @example
  7179. * $(document).ready(function() {
  7180. * initTable();
  7181. * tableActions();
  7182. * } );
  7183. *
  7184. * function initTable ()
  7185. * {
  7186. * return $('#example').dataTable( {
  7187. * "sScrollY": "200px",
  7188. * "bPaginate": false,
  7189. * "bRetrieve": true
  7190. * } );
  7191. * }
  7192. *
  7193. * function tableActions ()
  7194. * {
  7195. * var oTable = initTable();
  7196. * // perform API operations with oTable
  7197. * }
  7198. */
  7199. "bRetrieve": false,
  7200. /**
  7201. * Indicate if DataTables should be allowed to set the padding / margin
  7202. * etc for the scrolling header elements or not. Typically you will want
  7203. * this.
  7204. * @type boolean
  7205. * @default true
  7206. * @dtopt Options
  7207. *
  7208. * @example
  7209. * $(document).ready(function() {
  7210. * $('#example').dataTable( {
  7211. * "bScrollAutoCss": false,
  7212. * "sScrollY": "200px"
  7213. * } );
  7214. * } );
  7215. */
  7216. "bScrollAutoCss": true,
  7217. /**
  7218. * When vertical (y) scrolling is enabled, DataTables will force the height of
  7219. * the table's viewport to the given height at all times (useful for layout).
  7220. * However, this can look odd when filtering data down to a small data set,
  7221. * and the footer is left "floating" further down. This parameter (when
  7222. * enabled) will cause DataTables to collapse the table's viewport down when
  7223. * the result set will fit within the given Y height.
  7224. * @type boolean
  7225. * @default false
  7226. * @dtopt Options
  7227. *
  7228. * @example
  7229. * $(document).ready(function() {
  7230. * $('#example').dataTable( {
  7231. * "sScrollY": "200",
  7232. * "bScrollCollapse": true
  7233. * } );
  7234. * } );
  7235. */
  7236. "bScrollCollapse": false,
  7237. /**
  7238. * Enable infinite scrolling for DataTables (to be used in combination with
  7239. * sScrollY). Infinite scrolling means that DataTables will continually load
  7240. * data as a user scrolls through a table, which is very useful for large
  7241. * dataset. This cannot be used with pagination, which is automatically
  7242. * disabled. Note - the Scroller extra for DataTables is recommended in
  7243. * in preference to this option.
  7244. * @type boolean
  7245. * @default false
  7246. * @dtopt Features
  7247. *
  7248. * @example
  7249. * $(document).ready(function() {
  7250. * $('#example').dataTable( {
  7251. * "bScrollInfinite": true,
  7252. * "bScrollCollapse": true,
  7253. * "sScrollY": "200px"
  7254. * } );
  7255. * } );
  7256. */
  7257. "bScrollInfinite": false,
  7258. /**
  7259. * Configure DataTables to use server-side processing. Note that the
  7260. * sAjaxSource parameter must also be given in order to give DataTables a
  7261. * source to obtain the required data for each draw.
  7262. * @type boolean
  7263. * @default false
  7264. * @dtopt Features
  7265. * @dtopt Server-side
  7266. *
  7267. * @example
  7268. * $(document).ready( function () {
  7269. * $('#example').dataTable( {
  7270. * "bServerSide": true,
  7271. * "sAjaxSource": "xhr.php"
  7272. * } );
  7273. * } );
  7274. */
  7275. "bServerSide": false,
  7276. /**
  7277. * Enable or disable sorting of columns. Sorting of individual columns can be
  7278. * disabled by the "bSortable" option for each column.
  7279. * @type boolean
  7280. * @default true
  7281. * @dtopt Features
  7282. *
  7283. * @example
  7284. * $(document).ready( function () {
  7285. * $('#example').dataTable( {
  7286. * "bSort": false
  7287. * } );
  7288. * } );
  7289. */
  7290. "bSort": true,
  7291. /**
  7292. * Allows control over whether DataTables should use the top (true) unique
  7293. * cell that is found for a single column, or the bottom (false - default).
  7294. * This is useful when using complex headers.
  7295. * @type boolean
  7296. * @default false
  7297. * @dtopt Options
  7298. *
  7299. * @example
  7300. * $(document).ready(function() {
  7301. * $('#example').dataTable( {
  7302. * "bSortCellsTop": true
  7303. * } );
  7304. * } );
  7305. */
  7306. "bSortCellsTop": false,
  7307. /**
  7308. * Enable or disable the addition of the classes 'sorting_1', 'sorting_2' and
  7309. * 'sorting_3' to the columns which are currently being sorted on. This is
  7310. * presented as a feature switch as it can increase processing time (while
  7311. * classes are removed and added) so for large data sets you might want to
  7312. * turn this off.
  7313. * @type boolean
  7314. * @default true
  7315. * @dtopt Features
  7316. *
  7317. * @example
  7318. * $(document).ready( function () {
  7319. * $('#example').dataTable( {
  7320. * "bSortClasses": false
  7321. * } );
  7322. * } );
  7323. */
  7324. "bSortClasses": true,
  7325. /**
  7326. * Enable or disable state saving. When enabled a cookie will be used to save
  7327. * table display information such as pagination information, display length,
  7328. * filtering and sorting. As such when the end user reloads the page the
  7329. * display display will match what thy had previously set up.
  7330. * @type boolean
  7331. * @default false
  7332. * @dtopt Features
  7333. *
  7334. * @example
  7335. * $(document).ready( function () {
  7336. * $('#example').dataTable( {
  7337. * "bStateSave": true
  7338. * } );
  7339. * } );
  7340. */
  7341. "bStateSave": false,
  7342. /**
  7343. * Customise the cookie and / or the parameters being stored when using
  7344. * DataTables with state saving enabled. This function is called whenever
  7345. * the cookie is modified, and it expects a fully formed cookie string to be
  7346. * returned. Note that the data object passed in is a Javascript object which
  7347. * must be converted to a string (JSON.stringify for example).
  7348. * @type function
  7349. * @param {string} sName Name of the cookie defined by DataTables
  7350. * @param {object} oData Data to be stored in the cookie
  7351. * @param {string} sExpires Cookie expires string
  7352. * @param {string} sPath Path of the cookie to set
  7353. * @returns {string} Cookie formatted string (which should be encoded by
  7354. * using encodeURIComponent())
  7355. * @dtopt Callbacks
  7356. *
  7357. * @example
  7358. * $(document).ready( function () {
  7359. * $('#example').dataTable( {
  7360. * "fnCookieCallback": function (sName, oData, sExpires, sPath) {
  7361. * // Customise oData or sName or whatever else here
  7362. * return sName + "="+JSON.stringify(oData)+"; expires=" + sExpires +"; path=" + sPath;
  7363. * }
  7364. * } );
  7365. * } );
  7366. */
  7367. "fnCookieCallback": null,
  7368. /**
  7369. * This function is called when a TR element is created (and all TD child
  7370. * elements have been inserted), or registered if using a DOM source, allowing
  7371. * manipulation of the TR element (adding classes etc).
  7372. * @type function
  7373. * @param {node} nRow "TR" element for the current row
  7374. * @param {array} aData Raw data array for this row
  7375. * @param {int} iDataIndex The index of this row in aoData
  7376. * @dtopt Callbacks
  7377. *
  7378. * @example
  7379. * $(document).ready(function() {
  7380. * $('#example').dataTable( {
  7381. * "fnCreatedRow": function( nRow, aData, iDataIndex ) {
  7382. * // Bold the grade for all 'A' grade browsers
  7383. * if ( aData[4] == "A" )
  7384. * {
  7385. * $('td:eq(4)', nRow).html( '<b>A</b>' );
  7386. * }
  7387. * }
  7388. * } );
  7389. * } );
  7390. */
  7391. "fnCreatedRow": null,
  7392. /**
  7393. * This function is called on every 'draw' event, and allows you to
  7394. * dynamically modify any aspect you want about the created DOM.
  7395. * @type function
  7396. * @param {object} oSettings DataTables settings object
  7397. * @dtopt Callbacks
  7398. *
  7399. * @example
  7400. * $(document).ready( function() {
  7401. * $('#example').dataTable( {
  7402. * "fnDrawCallback": function( oSettings ) {
  7403. * alert( 'DataTables has redrawn the table' );
  7404. * }
  7405. * } );
  7406. * } );
  7407. */
  7408. "fnDrawCallback": null,
  7409. /**
  7410. * Identical to fnHeaderCallback() but for the table footer this function
  7411. * allows you to modify the table footer on every 'draw' even.
  7412. * @type function
  7413. * @param {node} nFoot "TR" element for the footer
  7414. * @param {array} aData Full table data (as derived from the original HTML)
  7415. * @param {int} iStart Index for the current display starting point in the
  7416. * display array
  7417. * @param {int} iEnd Index for the current display ending point in the
  7418. * display array
  7419. * @param {array int} aiDisplay Index array to translate the visual position
  7420. * to the full data array
  7421. * @dtopt Callbacks
  7422. *
  7423. * @example
  7424. * $(document).ready( function() {
  7425. * $('#example').dataTable( {
  7426. * "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) {
  7427. * nFoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+iStart;
  7428. * }
  7429. * } );
  7430. * } )
  7431. */
  7432. "fnFooterCallback": null,
  7433. /**
  7434. * When rendering large numbers in the information element for the table
  7435. * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
  7436. * to have a comma separator for the 'thousands' units (e.g. 1 million is
  7437. * rendered as "1,000,000") to help readability for the end user. This
  7438. * function will override the default method DataTables uses.
  7439. * @type function
  7440. * @member
  7441. * @param {int} iIn number to be formatted
  7442. * @returns {string} formatted string for DataTables to show the number
  7443. * @dtopt Callbacks
  7444. *
  7445. * @example
  7446. * $(document).ready(function() {
  7447. * $('#example').dataTable( {
  7448. * "fnFormatNumber": function ( iIn ) {
  7449. * if ( iIn &lt; 1000 ) {
  7450. * return iIn;
  7451. * } else {
  7452. * var
  7453. * s=(iIn+""),
  7454. * a=s.split(""), out="",
  7455. * iLen=s.length;
  7456. *
  7457. * for ( var i=0 ; i&lt;iLen ; i++ ) {
  7458. * if ( i%3 === 0 &amp;&amp; i !== 0 ) {
  7459. * out = "'"+out;
  7460. * }
  7461. * out = a[iLen-i-1]+out;
  7462. * }
  7463. * }
  7464. * return out;
  7465. * };
  7466. * } );
  7467. * } );
  7468. */
  7469. "fnFormatNumber": function ( iIn ) {
  7470. if ( iIn < 1000 )
  7471. {
  7472. // A small optimisation for what is likely to be the majority of use cases
  7473. return iIn;
  7474. }
  7475. var s=(iIn+""), a=s.split(""), out="", iLen=s.length;
  7476. for ( var i=0 ; i<iLen ; i++ )
  7477. {
  7478. if ( i%3 === 0 && i !== 0 )
  7479. {
  7480. out = this.oLanguage.sInfoThousands+out;
  7481. }
  7482. out = a[iLen-i-1]+out;
  7483. }
  7484. return out;
  7485. },
  7486. /**
  7487. * This function is called on every 'draw' event, and allows you to
  7488. * dynamically modify the header row. This can be used to calculate and
  7489. * display useful information about the table.
  7490. * @type function
  7491. * @param {node} nHead "TR" element for the header
  7492. * @param {array} aData Full table data (as derived from the original HTML)
  7493. * @param {int} iStart Index for the current display starting point in the
  7494. * display array
  7495. * @param {int} iEnd Index for the current display ending point in the
  7496. * display array
  7497. * @param {array int} aiDisplay Index array to translate the visual position
  7498. * to the full data array
  7499. * @dtopt Callbacks
  7500. *
  7501. * @example
  7502. * $(document).ready( function() {
  7503. * $('#example').dataTable( {
  7504. * "fnHeaderCallback": function( nHead, aData, iStart, iEnd, aiDisplay ) {
  7505. * nHead.getElementsByTagName('th')[0].innerHTML = "Displaying "+(iEnd-iStart)+" records";
  7506. * }
  7507. * } );
  7508. * } )
  7509. */
  7510. "fnHeaderCallback": null,
  7511. /**
  7512. * The information element can be used to convey information about the current
  7513. * state of the table. Although the internationalisation options presented by
  7514. * DataTables are quite capable of dealing with most customisations, there may
  7515. * be times where you wish to customise the string further. This callback
  7516. * allows you to do exactly that.
  7517. * @type function
  7518. * @param {object} oSettings DataTables settings object
  7519. * @param {int} iStart Starting position in data for the draw
  7520. * @param {int} iEnd End position in data for the draw
  7521. * @param {int} iMax Total number of rows in the table (regardless of
  7522. * filtering)
  7523. * @param {int} iTotal Total number of rows in the data set, after filtering
  7524. * @param {string} sPre The string that DataTables has formatted using it's
  7525. * own rules
  7526. * @returns {string} The string to be displayed in the information element.
  7527. * @dtopt Callbacks
  7528. *
  7529. * @example
  7530. * $('#example').dataTable( {
  7531. * "fnInfoCallback": function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) {
  7532. * return iStart +" to "+ iEnd;
  7533. * }
  7534. * } );
  7535. */
  7536. "fnInfoCallback": null,
  7537. /**
  7538. * Called when the table has been initialised. Normally DataTables will
  7539. * initialise sequentially and there will be no need for this function,
  7540. * however, this does not hold true when using external language information
  7541. * since that is obtained using an async XHR call.
  7542. * @type function
  7543. * @param {object} oSettings DataTables settings object
  7544. * @param {object} json The JSON object request from the server - only
  7545. * present if client-side Ajax sourced data is used
  7546. * @dtopt Callbacks
  7547. *
  7548. * @example
  7549. * $(document).ready( function() {
  7550. * $('#example').dataTable( {
  7551. * "fnInitComplete": function(oSettings, json) {
  7552. * alert( 'DataTables has finished its initialisation.' );
  7553. * }
  7554. * } );
  7555. * } )
  7556. */
  7557. "fnInitComplete": null,
  7558. /**
  7559. * Called at the very start of each table draw and can be used to cancel the
  7560. * draw by returning false, any other return (including undefined) results in
  7561. * the full draw occurring).
  7562. * @type function
  7563. * @param {object} oSettings DataTables settings object
  7564. * @returns {boolean} False will cancel the draw, anything else (including no
  7565. * return) will allow it to complete.
  7566. * @dtopt Callbacks
  7567. *
  7568. * @example
  7569. * $(document).ready( function() {
  7570. * $('#example').dataTable( {
  7571. * "fnPreDrawCallback": function( oSettings ) {
  7572. * if ( $('#test').val() == 1 ) {
  7573. * return false;
  7574. * }
  7575. * }
  7576. * } );
  7577. * } );
  7578. */
  7579. "fnPreDrawCallback": null,
  7580. /**
  7581. * This function allows you to 'post process' each row after it have been
  7582. * generated for each table draw, but before it is rendered on screen. This
  7583. * function might be used for setting the row class name etc.
  7584. * @type function
  7585. * @param {node} nRow "TR" element for the current row
  7586. * @param {array} aData Raw data array for this row
  7587. * @param {int} iDisplayIndex The display index for the current table draw
  7588. * @param {int} iDisplayIndexFull The index of the data in the full list of
  7589. * rows (after filtering)
  7590. * @dtopt Callbacks
  7591. *
  7592. * @example
  7593. * $(document).ready(function() {
  7594. * $('#example').dataTable( {
  7595. * "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
  7596. * // Bold the grade for all 'A' grade browsers
  7597. * if ( aData[4] == "A" )
  7598. * {
  7599. * $('td:eq(4)', nRow).html( '<b>A</b>' );
  7600. * }
  7601. * }
  7602. * } );
  7603. * } );
  7604. */
  7605. "fnRowCallback": null,
  7606. /**
  7607. * This parameter allows you to override the default function which obtains
  7608. * the data from the server ($.getJSON) so something more suitable for your
  7609. * application. For example you could use POST data, or pull information from
  7610. * a Gears or AIR database.
  7611. * @type function
  7612. * @member
  7613. * @param {string} sSource HTTP source to obtain the data from (sAjaxSource)
  7614. * @param {array} aoData A key/value pair object containing the data to send
  7615. * to the server
  7616. * @param {function} fnCallback to be called on completion of the data get
  7617. * process that will draw the data on the page.
  7618. * @param {object} oSettings DataTables settings object
  7619. * @dtopt Callbacks
  7620. * @dtopt Server-side
  7621. *
  7622. * @example
  7623. * // POST data to server
  7624. * $(document).ready(function() {
  7625. * $('#example').dataTable( {
  7626. * "bProcessing": true,
  7627. * "bServerSide": true,
  7628. * "sAjaxSource": "xhr.php",
  7629. * "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) {
  7630. * oSettings.jqXHR = $.ajax( {
  7631. * "dataType": 'json',
  7632. * "type": "POST",
  7633. * "url": sSource,
  7634. * "data": aoData,
  7635. * "success": fnCallback
  7636. * } );
  7637. * }
  7638. * } );
  7639. * } );
  7640. */
  7641. "fnServerData": function ( sUrl, aoData, fnCallback, oSettings ) {
  7642. oSettings.jqXHR = $.ajax( {
  7643. "url": sUrl,
  7644. "data": aoData,
  7645. "success": function (json) {
  7646. $(oSettings.oInstance).trigger('xhr', oSettings);
  7647. fnCallback( json );
  7648. },
  7649. "dataType": "json",
  7650. "cache": false,
  7651. "type": oSettings.sServerMethod,
  7652. "error": function (xhr, error, thrown) {
  7653. if ( error == "parsererror" ) {
  7654. oSettings.oApi._fnLog( oSettings, 0, "DataTables warning: JSON data from "+
  7655. "server could not be parsed. This is caused by a JSON formatting error." );
  7656. }
  7657. }
  7658. } );
  7659. },
  7660. /**
  7661. * It is often useful to send extra data to the server when making an Ajax
  7662. * request - for example custom filtering information, and this callback
  7663. * function makes it trivial to send extra information to the server. The
  7664. * passed in parameter is the data set that has been constructed by
  7665. * DataTables, and you can add to this or modify it as you require.
  7666. * @type function
  7667. * @param {array} aoData Data array (array of objects which are name/value
  7668. * pairs) that has been constructed by DataTables and will be sent to the
  7669. * server. In the case of Ajax sourced data with server-side processing
  7670. * this will be an empty array, for server-side processing there will be a
  7671. * significant number of parameters!
  7672. * @returns {undefined} Ensure that you modify the aoData array passed in,
  7673. * as this is passed by reference.
  7674. * @dtopt Callbacks
  7675. * @dtopt Server-side
  7676. *
  7677. * @example
  7678. * $(document).ready(function() {
  7679. * $('#example').dataTable( {
  7680. * "bProcessing": true,
  7681. * "bServerSide": true,
  7682. * "sAjaxSource": "scripts/server_processing.php",
  7683. * "fnServerParams": function ( aoData ) {
  7684. * aoData.push( { "name": "more_data", "value": "my_value" } );
  7685. * }
  7686. * } );
  7687. * } );
  7688. */
  7689. "fnServerParams": null,
  7690. /**
  7691. * Load the table state. With this function you can define from where, and how, the
  7692. * state of a table is loaded. By default DataTables will load from its state saving
  7693. * cookie, but you might wish to use local storage (HTML5) or a server-side database.
  7694. * @type function
  7695. * @member
  7696. * @param {object} oSettings DataTables settings object
  7697. * @return {object} The DataTables state object to be loaded
  7698. * @dtopt Callbacks
  7699. *
  7700. * @example
  7701. * $(document).ready(function() {
  7702. * $('#example').dataTable( {
  7703. * "bStateSave": true,
  7704. * "fnStateLoad": function (oSettings) {
  7705. * var o;
  7706. *
  7707. * // Send an Ajax request to the server to get the data. Note that
  7708. * // this is a synchronous request.
  7709. * $.ajax( {
  7710. * "url": "/state_load",
  7711. * "async": false,
  7712. * "dataType": "json",
  7713. * "success": function (json) {
  7714. * o = json;
  7715. * }
  7716. * } );
  7717. *
  7718. * return o;
  7719. * }
  7720. * } );
  7721. * } );
  7722. */
  7723. "fnStateLoad": function ( oSettings ) {
  7724. var sData = this.oApi._fnReadCookie( oSettings.sCookiePrefix+oSettings.sInstance );
  7725. var oData;
  7726. try {
  7727. oData = (typeof $.parseJSON === 'function') ?
  7728. $.parseJSON(sData) : eval( '('+sData+')' );
  7729. } catch (e) {
  7730. oData = null;
  7731. }
  7732. return oData;
  7733. },
  7734. /**
  7735. * Callback which allows modification of the saved state prior to loading that state.
  7736. * This callback is called when the table is loading state from the stored data, but
  7737. * prior to the settings object being modified by the saved state. Note that for
  7738. * plug-in authors, you should use the 'stateLoadParams' event to load parameters for
  7739. * a plug-in.
  7740. * @type function
  7741. * @param {object} oSettings DataTables settings object
  7742. * @param {object} oData The state object that is to be loaded
  7743. * @dtopt Callbacks
  7744. *
  7745. * @example
  7746. * // Remove a saved filter, so filtering is never loaded
  7747. * $(document).ready(function() {
  7748. * $('#example').dataTable( {
  7749. * "bStateSave": true,
  7750. * "fnStateLoadParams": function (oSettings, oData) {
  7751. * oData.oSearch.sSearch = "";
  7752. * } );
  7753. * } );
  7754. *
  7755. * @example
  7756. * // Disallow state loading by returning false
  7757. * $(document).ready(function() {
  7758. * $('#example').dataTable( {
  7759. * "bStateSave": true,
  7760. * "fnStateLoadParams": function (oSettings, oData) {
  7761. * return false;
  7762. * } );
  7763. * } );
  7764. */
  7765. "fnStateLoadParams": null,
  7766. /**
  7767. * Callback that is called when the state has been loaded from the state saving method
  7768. * and the DataTables settings object has been modified as a result of the loaded state.
  7769. * @type function
  7770. * @param {object} oSettings DataTables settings object
  7771. * @param {object} oData The state object that was loaded
  7772. * @dtopt Callbacks
  7773. *
  7774. * @example
  7775. * // Show an alert with the filtering value that was saved
  7776. * $(document).ready(function() {
  7777. * $('#example').dataTable( {
  7778. * "bStateSave": true,
  7779. * "fnStateLoaded": function (oSettings, oData) {
  7780. * alert( 'Saved filter was: '+oData.oSearch.sSearch );
  7781. * } );
  7782. * } );
  7783. */
  7784. "fnStateLoaded": null,
  7785. /**
  7786. * Save the table state. This function allows you to define where and how the state
  7787. * information for the table is stored - by default it will use a cookie, but you
  7788. * might want to use local storage (HTML5) or a server-side database.
  7789. * @type function
  7790. * @member
  7791. * @param {object} oSettings DataTables settings object
  7792. * @param {object} oData The state object to be saved
  7793. * @dtopt Callbacks
  7794. *
  7795. * @example
  7796. * $(document).ready(function() {
  7797. * $('#example').dataTable( {
  7798. * "bStateSave": true,
  7799. * "fnStateSave": function (oSettings, oData) {
  7800. * // Send an Ajax request to the server with the state object
  7801. * $.ajax( {
  7802. * "url": "/state_save",
  7803. * "data": oData,
  7804. * "dataType": "json",
  7805. * "method": "POST"
  7806. * "success": function () {}
  7807. * } );
  7808. * }
  7809. * } );
  7810. * } );
  7811. */
  7812. "fnStateSave": function ( oSettings, oData ) {
  7813. this.oApi._fnCreateCookie(
  7814. oSettings.sCookiePrefix+oSettings.sInstance,
  7815. this.oApi._fnJsonString(oData),
  7816. oSettings.iCookieDuration,
  7817. oSettings.sCookiePrefix,
  7818. oSettings.fnCookieCallback
  7819. );
  7820. },
  7821. /**
  7822. * Callback which allows modification of the state to be saved. Called when the table
  7823. * has changed state a new state save is required. This method allows modification of
  7824. * the state saving object prior to actually doing the save, including addition or
  7825. * other state properties or modification. Note that for plug-in authors, you should
  7826. * use the 'stateSaveParams' event to save parameters for a plug-in.
  7827. * @type function
  7828. * @param {object} oSettings DataTables settings object
  7829. * @param {object} oData The state object to be saved
  7830. * @dtopt Callbacks
  7831. *
  7832. * @example
  7833. * // Remove a saved filter, so filtering is never saved
  7834. * $(document).ready(function() {
  7835. * $('#example').dataTable( {
  7836. * "bStateSave": true,
  7837. * "fnStateSaveParams": function (oSettings, oData) {
  7838. * oData.oSearch.sSearch = "";
  7839. * } );
  7840. * } );
  7841. */
  7842. "fnStateSaveParams": null,
  7843. /**
  7844. * Duration of the cookie which is used for storing session information. This
  7845. * value is given in seconds.
  7846. * @type int
  7847. * @default 7200 <i>(2 hours)</i>
  7848. * @dtopt Options
  7849. *
  7850. * @example
  7851. * $(document).ready( function() {
  7852. * $('#example').dataTable( {
  7853. * "iCookieDuration": 60*60*24 // 1 day
  7854. * } );
  7855. * } )
  7856. */
  7857. "iCookieDuration": 7200,
  7858. /**
  7859. * When enabled DataTables will not make a request to the server for the first
  7860. * page draw - rather it will use the data already on the page (no sorting etc
  7861. * will be applied to it), thus saving on an XHR at load time. iDeferLoading
  7862. * is used to indicate that deferred loading is required, but it is also used
  7863. * to tell DataTables how many records there are in the full table (allowing
  7864. * the information element and pagination to be displayed correctly). In the case
  7865. * where a filtering is applied to the table on initial load, this can be
  7866. * indicated by giving the parameter as an array, where the first element is
  7867. * the number of records available after filtering and the second element is the
  7868. * number of records without filtering (allowing the table information element
  7869. * to be shown correctly).
  7870. * @type int | array
  7871. * @default null
  7872. * @dtopt Options
  7873. *
  7874. * @example
  7875. * // 57 records available in the table, no filtering applied
  7876. * $(document).ready(function() {
  7877. * $('#example').dataTable( {
  7878. * "bServerSide": true,
  7879. * "sAjaxSource": "scripts/server_processing.php",
  7880. * "iDeferLoading": 57
  7881. * } );
  7882. * } );
  7883. *
  7884. * @example
  7885. * // 57 records after filtering, 100 without filtering (an initial filter applied)
  7886. * $(document).ready(function() {
  7887. * $('#example').dataTable( {
  7888. * "bServerSide": true,
  7889. * "sAjaxSource": "scripts/server_processing.php",
  7890. * "iDeferLoading": [ 57, 100 ],
  7891. * "oSearch": {
  7892. * "sSearch": "my_filter"
  7893. * }
  7894. * } );
  7895. * } );
  7896. */
  7897. "iDeferLoading": null,
  7898. /**
  7899. * Number of rows to display on a single page when using pagination. If
  7900. * feature enabled (bLengthChange) then the end user will be able to override
  7901. * this to a custom setting using a pop-up menu.
  7902. * @type int
  7903. * @default 10
  7904. * @dtopt Options
  7905. *
  7906. * @example
  7907. * $(document).ready( function() {
  7908. * $('#example').dataTable( {
  7909. * "iDisplayLength": 50
  7910. * } );
  7911. * } )
  7912. */
  7913. "iDisplayLength": 10,
  7914. /**
  7915. * Define the starting point for data display when using DataTables with
  7916. * pagination. Note that this parameter is the number of records, rather than
  7917. * the page number, so if you have 10 records per page and want to start on
  7918. * the third page, it should be "20".
  7919. * @type int
  7920. * @default 0
  7921. * @dtopt Options
  7922. *
  7923. * @example
  7924. * $(document).ready( function() {
  7925. * $('#example').dataTable( {
  7926. * "iDisplayStart": 20
  7927. * } );
  7928. * } )
  7929. */
  7930. "iDisplayStart": 0,
  7931. /**
  7932. * The scroll gap is the amount of scrolling that is left to go before
  7933. * DataTables will load the next 'page' of data automatically. You typically
  7934. * want a gap which is big enough that the scrolling will be smooth for the
  7935. * user, while not so large that it will load more data than need.
  7936. * @type int
  7937. * @default 100
  7938. * @dtopt Options
  7939. *
  7940. * @example
  7941. * $(document).ready(function() {
  7942. * $('#example').dataTable( {
  7943. * "bScrollInfinite": true,
  7944. * "bScrollCollapse": true,
  7945. * "sScrollY": "200px",
  7946. * "iScrollLoadGap": 50
  7947. * } );
  7948. * } );
  7949. */
  7950. "iScrollLoadGap": 100,
  7951. /**
  7952. * By default DataTables allows keyboard navigation of the table (sorting, paging,
  7953. * and filtering) by adding a tabindex attribute to the required elements. This
  7954. * allows you to tab through the controls and press the enter key to activate them.
  7955. * The tabindex is default 0, meaning that the tab follows the flow of the document.
  7956. * You can overrule this using this parameter if you wish. Use a value of -1 to
  7957. * disable built-in keyboard navigation.
  7958. * @type int
  7959. * @default 0
  7960. * @dtopt Options
  7961. *
  7962. * @example
  7963. * $(document).ready(function() {
  7964. * $('#example').dataTable( {
  7965. * "iTabIndex": 1
  7966. * } );
  7967. * } );
  7968. */
  7969. "iTabIndex": 0,
  7970. /**
  7971. * All strings that DataTables uses in the user interface that it creates
  7972. * are defined in this object, allowing you to modified them individually or
  7973. * completely replace them all as required.
  7974. * @namespace
  7975. */
  7976. "oLanguage": {
  7977. /**
  7978. * Strings that are used for WAI-ARIA labels and controls only (these are not
  7979. * actually visible on the page, but will be read by screenreaders, and thus
  7980. * must be internationalised as well).
  7981. * @namespace
  7982. */
  7983. "oAria": {
  7984. /**
  7985. * ARIA label that is added to the table headers when the column may be
  7986. * sorted ascending by activing the column (click or return when focused).
  7987. * Note that the column header is prefixed to this string.
  7988. * @type string
  7989. * @default : activate to sort column ascending
  7990. * @dtopt Language
  7991. *
  7992. * @example
  7993. * $(document).ready(function() {
  7994. * $('#example').dataTable( {
  7995. * "oLanguage": {
  7996. * "oAria": {
  7997. * "sSortAscending": " - click/return to sort ascending"
  7998. * }
  7999. * }
  8000. * } );
  8001. * } );
  8002. */
  8003. "sSortAscending": ": activate to sort column ascending",
  8004. /**
  8005. * ARIA label that is added to the table headers when the column may be
  8006. * sorted descending by activing the column (click or return when focused).
  8007. * Note that the column header is prefixed to this string.
  8008. * @type string
  8009. * @default : activate to sort column ascending
  8010. * @dtopt Language
  8011. *
  8012. * @example
  8013. * $(document).ready(function() {
  8014. * $('#example').dataTable( {
  8015. * "oLanguage": {
  8016. * "oAria": {
  8017. * "sSortDescending": " - click/return to sort descending"
  8018. * }
  8019. * }
  8020. * } );
  8021. * } );
  8022. */
  8023. "sSortDescending": ": activate to sort column descending"
  8024. },
  8025. /**
  8026. * Pagination string used by DataTables for the two built-in pagination
  8027. * control types ("two_button" and "full_numbers")
  8028. * @namespace
  8029. */
  8030. "oPaginate": {
  8031. /**
  8032. * Text to use when using the 'full_numbers' type of pagination for the
  8033. * button to take the user to the first page.
  8034. * @type string
  8035. * @default First
  8036. * @dtopt Language
  8037. *
  8038. * @example
  8039. * $(document).ready(function() {
  8040. * $('#example').dataTable( {
  8041. * "oLanguage": {
  8042. * "oPaginate": {
  8043. * "sFirst": "First page"
  8044. * }
  8045. * }
  8046. * } );
  8047. * } );
  8048. */
  8049. "sFirst": "First",
  8050. /**
  8051. * Text to use when using the 'full_numbers' type of pagination for the
  8052. * button to take the user to the last page.
  8053. * @type string
  8054. * @default Last
  8055. * @dtopt Language
  8056. *
  8057. * @example
  8058. * $(document).ready(function() {
  8059. * $('#example').dataTable( {
  8060. * "oLanguage": {
  8061. * "oPaginate": {
  8062. * "sLast": "Last page"
  8063. * }
  8064. * }
  8065. * } );
  8066. * } );
  8067. */
  8068. "sLast": "Last",
  8069. /**
  8070. * Text to use when using the 'full_numbers' type of pagination for the
  8071. * button to take the user to the next page.
  8072. * @type string
  8073. * @default Next
  8074. * @dtopt Language
  8075. *
  8076. * @example
  8077. * $(document).ready(function() {
  8078. * $('#example').dataTable( {
  8079. * "oLanguage": {
  8080. * "oPaginate": {
  8081. * "sNext": "Next page"
  8082. * }
  8083. * }
  8084. * } );
  8085. * } );
  8086. */
  8087. "sNext": "Next",
  8088. /**
  8089. * Text to use when using the 'full_numbers' type of pagination for the
  8090. * button to take the user to the previous page.
  8091. * @type string
  8092. * @default Previous
  8093. * @dtopt Language
  8094. *
  8095. * @example
  8096. * $(document).ready(function() {
  8097. * $('#example').dataTable( {
  8098. * "oLanguage": {
  8099. * "oPaginate": {
  8100. * "sPrevious": "Previous page"
  8101. * }
  8102. * }
  8103. * } );
  8104. * } );
  8105. */
  8106. "sPrevious": "Previous"
  8107. },
  8108. /**
  8109. * This string is shown in preference to sZeroRecords when the table is
  8110. * empty of data (regardless of filtering). Note that this is an optional
  8111. * parameter - if it is not given, the value of sZeroRecords will be used
  8112. * instead (either the default or given value).
  8113. * @type string
  8114. * @default No data available in table
  8115. * @dtopt Language
  8116. *
  8117. * @example
  8118. * $(document).ready(function() {
  8119. * $('#example').dataTable( {
  8120. * "oLanguage": {
  8121. * "sEmptyTable": "No data available in table"
  8122. * }
  8123. * } );
  8124. * } );
  8125. */
  8126. "sEmptyTable": "No data available in table",
  8127. /**
  8128. * This string gives information to the end user about the information that
  8129. * is current on display on the page. The _START_, _END_ and _TOTAL_
  8130. * variables are all dynamically replaced as the table display updates, and
  8131. * can be freely moved or removed as the language requirements change.
  8132. * @type string
  8133. * @default Showing _START_ to _END_ of _TOTAL_ entries
  8134. * @dtopt Language
  8135. *
  8136. * @example
  8137. * $(document).ready(function() {
  8138. * $('#example').dataTable( {
  8139. * "oLanguage": {
  8140. * "sInfo": "Got a total of _TOTAL_ entries to show (_START_ to _END_)"
  8141. * }
  8142. * } );
  8143. * } );
  8144. */
  8145. "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
  8146. /**
  8147. * Display information string for when the table is empty. Typically the
  8148. * format of this string should match sInfo.
  8149. * @type string
  8150. * @default Showing 0 to 0 of 0 entries
  8151. * @dtopt Language
  8152. *
  8153. * @example
  8154. * $(document).ready(function() {
  8155. * $('#example').dataTable( {
  8156. * "oLanguage": {
  8157. * "sInfoEmpty": "No entries to show"
  8158. * }
  8159. * } );
  8160. * } );
  8161. */
  8162. "sInfoEmpty": "Showing 0 to 0 of 0 entries",
  8163. /**
  8164. * When a user filters the information in a table, this string is appended
  8165. * to the information (sInfo) to give an idea of how strong the filtering
  8166. * is. The variable _MAX_ is dynamically updated.
  8167. * @type string
  8168. * @default (filtered from _MAX_ total entries)
  8169. * @dtopt Language
  8170. *
  8171. * @example
  8172. * $(document).ready(function() {
  8173. * $('#example').dataTable( {
  8174. * "oLanguage": {
  8175. * "sInfoFiltered": " - filtering from _MAX_ records"
  8176. * }
  8177. * } );
  8178. * } );
  8179. */
  8180. "sInfoFiltered": "(filtered from _MAX_ total entries)",
  8181. /**
  8182. * If can be useful to append extra information to the info string at times,
  8183. * and this variable does exactly that. This information will be appended to
  8184. * the sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are
  8185. * being used) at all times.
  8186. * @type string
  8187. * @default <i>Empty string</i>
  8188. * @dtopt Language
  8189. *
  8190. * @example
  8191. * $(document).ready(function() {
  8192. * $('#example').dataTable( {
  8193. * "oLanguage": {
  8194. * "sInfoPostFix": "All records shown are derived from real information."
  8195. * }
  8196. * } );
  8197. * } );
  8198. */
  8199. "sInfoPostFix": "",
  8200. /**
  8201. * DataTables has a build in number formatter (fnFormatNumber) which is used
  8202. * to format large numbers that are used in the table information. By
  8203. * default a comma is used, but this can be trivially changed to any
  8204. * character you wish with this parameter.
  8205. * @type string
  8206. * @default ,
  8207. * @dtopt Language
  8208. *
  8209. * @example
  8210. * $(document).ready(function() {
  8211. * $('#example').dataTable( {
  8212. * "oLanguage": {
  8213. * "sInfoThousands": "'"
  8214. * }
  8215. * } );
  8216. * } );
  8217. */
  8218. "sInfoThousands": ",",
  8219. /**
  8220. * Detail the action that will be taken when the drop down menu for the
  8221. * pagination length option is changed. The '_MENU_' variable is replaced
  8222. * with a default select list of 10, 25, 50 and 100, and can be replaced
  8223. * with a custom select box if required.
  8224. * @type string
  8225. * @default Show _MENU_ entries
  8226. * @dtopt Language
  8227. *
  8228. * @example
  8229. * // Language change only
  8230. * $(document).ready(function() {
  8231. * $('#example').dataTable( {
  8232. * "oLanguage": {
  8233. * "sLengthMenu": "Display _MENU_ records"
  8234. * }
  8235. * } );
  8236. * } );
  8237. *
  8238. * @example
  8239. * // Language and options change
  8240. * $(document).ready(function() {
  8241. * $('#example').dataTable( {
  8242. * "oLanguage": {
  8243. * "sLengthMenu": 'Display <select>'+
  8244. * '<option value="10">10</option>'+
  8245. * '<option value="20">20</option>'+
  8246. * '<option value="30">30</option>'+
  8247. * '<option value="40">40</option>'+
  8248. * '<option value="50">50</option>'+
  8249. * '<option value="-1">All</option>'+
  8250. * '</select> records'
  8251. * }
  8252. * } );
  8253. * } );
  8254. */
  8255. "sLengthMenu": "Show _MENU_ entries",
  8256. /**
  8257. * When using Ajax sourced data and during the first draw when DataTables is
  8258. * gathering the data, this message is shown in an empty row in the table to
  8259. * indicate to the end user the the data is being loaded. Note that this
  8260. * parameter is not used when loading data by server-side processing, just
  8261. * Ajax sourced data with client-side processing.
  8262. * @type string
  8263. * @default Loading...
  8264. * @dtopt Language
  8265. *
  8266. * @example
  8267. * $(document).ready( function() {
  8268. * $('#example').dataTable( {
  8269. * "oLanguage": {
  8270. * "sLoadingRecords": "Please wait - loading..."
  8271. * }
  8272. * } );
  8273. * } );
  8274. */
  8275. "sLoadingRecords": "Loading...",
  8276. /**
  8277. * Text which is displayed when the table is processing a user action
  8278. * (usually a sort command or similar).
  8279. * @type string
  8280. * @default Processing...
  8281. * @dtopt Language
  8282. *
  8283. * @example
  8284. * $(document).ready(function() {
  8285. * $('#example').dataTable( {
  8286. * "oLanguage": {
  8287. * "sProcessing": "DataTables is currently busy"
  8288. * }
  8289. * } );
  8290. * } );
  8291. */
  8292. "sProcessing": "Processing...",
  8293. /**
  8294. * Details the actions that will be taken when the user types into the
  8295. * filtering input text box. The variable "_INPUT_", if used in the string,
  8296. * is replaced with the HTML text box for the filtering input allowing
  8297. * control over where it appears in the string. If "_INPUT_" is not given
  8298. * then the input box is appended to the string automatically.
  8299. * @type string
  8300. * @default Search:
  8301. * @dtopt Language
  8302. *
  8303. * @example
  8304. * // Input text box will be appended at the end automatically
  8305. * $(document).ready(function() {
  8306. * $('#example').dataTable( {
  8307. * "oLanguage": {
  8308. * "sSearch": "Filter records:"
  8309. * }
  8310. * } );
  8311. * } );
  8312. *
  8313. * @example
  8314. * // Specify where the filter should appear
  8315. * $(document).ready(function() {
  8316. * $('#example').dataTable( {
  8317. * "oLanguage": {
  8318. * "sSearch": "Apply filter _INPUT_ to table"
  8319. * }
  8320. * } );
  8321. * } );
  8322. */
  8323. "sSearch": "Search:",
  8324. /**
  8325. * All of the language information can be stored in a file on the
  8326. * server-side, which DataTables will look up if this parameter is passed.
  8327. * It must store the URL of the language file, which is in a JSON format,
  8328. * and the object has the same properties as the oLanguage object in the
  8329. * initialiser object (i.e. the above parameters). Please refer to one of
  8330. * the example language files to see how this works in action.
  8331. * @type string
  8332. * @default <i>Empty string - i.e. disabled</i>
  8333. * @dtopt Language
  8334. *
  8335. * @example
  8336. * $(document).ready(function() {
  8337. * $('#example').dataTable( {
  8338. * "oLanguage": {
  8339. * "sUrl": "http://www.sprymedia.co.uk/dataTables/lang.txt"
  8340. * }
  8341. * } );
  8342. * } );
  8343. */
  8344. "sUrl": "",
  8345. /**
  8346. * Text shown inside the table records when the is no information to be
  8347. * displayed after filtering. sEmptyTable is shown when there is simply no
  8348. * information in the table at all (regardless of filtering).
  8349. * @type string
  8350. * @default No matching records found
  8351. * @dtopt Language
  8352. *
  8353. * @example
  8354. * $(document).ready(function() {
  8355. * $('#example').dataTable( {
  8356. * "oLanguage": {
  8357. * "sZeroRecords": "No records to display"
  8358. * }
  8359. * } );
  8360. * } );
  8361. */
  8362. "sZeroRecords": "No matching records found"
  8363. },
  8364. /**
  8365. * This parameter allows you to have define the global filtering state at
  8366. * initialisation time. As an object the "sSearch" parameter must be
  8367. * defined, but all other parameters are optional. When "bRegex" is true,
  8368. * the search string will be treated as a regular expression, when false
  8369. * (default) it will be treated as a straight string. When "bSmart"
  8370. * DataTables will use it's smart filtering methods (to word match at
  8371. * any point in the data), when false this will not be done.
  8372. * @namespace
  8373. * @extends DataTable.models.oSearch
  8374. * @dtopt Options
  8375. *
  8376. * @example
  8377. * $(document).ready( function() {
  8378. * $('#example').dataTable( {
  8379. * "oSearch": {"sSearch": "Initial search"}
  8380. * } );
  8381. * } )
  8382. */
  8383. "oSearch": $.extend( {}, DataTable.models.oSearch ),
  8384. /**
  8385. * By default DataTables will look for the property 'aaData' when obtaining
  8386. * data from an Ajax source or for server-side processing - this parameter
  8387. * allows that property to be changed. You can use Javascript dotted object
  8388. * notation to get a data source for multiple levels of nesting.
  8389. * @type string
  8390. * @default aaData
  8391. * @dtopt Options
  8392. * @dtopt Server-side
  8393. *
  8394. * @example
  8395. * // Get data from { "data": [...] }
  8396. * $(document).ready(function() {
  8397. * var oTable = $('#example').dataTable( {
  8398. * "sAjaxSource": "sources/data.txt",
  8399. * "sAjaxDataProp": "data"
  8400. * } );
  8401. * } );
  8402. *
  8403. * @example
  8404. * // Get data from { "data": { "inner": [...] } }
  8405. * $(document).ready(function() {
  8406. * var oTable = $('#example').dataTable( {
  8407. * "sAjaxSource": "sources/data.txt",
  8408. * "sAjaxDataProp": "data.inner"
  8409. * } );
  8410. * } );
  8411. */
  8412. "sAjaxDataProp": "aaData",
  8413. /**
  8414. * You can instruct DataTables to load data from an external source using this
  8415. * parameter (use aData if you want to pass data in you already have). Simply
  8416. * provide a url a JSON object can be obtained from. This object must include
  8417. * the parameter 'aaData' which is the data source for the table.
  8418. * @type string
  8419. * @default null
  8420. * @dtopt Options
  8421. * @dtopt Server-side
  8422. *
  8423. * @example
  8424. * $(document).ready( function() {
  8425. * $('#example').dataTable( {
  8426. * "sAjaxSource": "http://www.sprymedia.co.uk/dataTables/json.php"
  8427. * } );
  8428. * } )
  8429. */
  8430. "sAjaxSource": null,
  8431. /**
  8432. * This parameter can be used to override the default prefix that DataTables
  8433. * assigns to a cookie when state saving is enabled.
  8434. * @type string
  8435. * @default SpryMedia_DataTables_
  8436. * @dtopt Options
  8437. *
  8438. * @example
  8439. * $(document).ready(function() {
  8440. * $('#example').dataTable( {
  8441. * "sCookiePrefix": "my_datatable_",
  8442. * } );
  8443. * } );
  8444. */
  8445. "sCookiePrefix": "SpryMedia_DataTables_",
  8446. /**
  8447. * This initialisation variable allows you to specify exactly where in the
  8448. * DOM you want DataTables to inject the various controls it adds to the page
  8449. * (for example you might want the pagination controls at the top of the
  8450. * table). DIV elements (with or without a custom class) can also be added to
  8451. * aid styling. The follow syntax is used:
  8452. * <ul>
  8453. * <li>The following options are allowed:
  8454. * <ul>
  8455. * <li>'l' - Length changing</li
  8456. * <li>'f' - Filtering input</li>
  8457. * <li>'t' - The table!</li>
  8458. * <li>'i' - Information</li>
  8459. * <li>'p' - Pagination</li>
  8460. * <li>'r' - pRocessing</li>
  8461. * </ul>
  8462. * </li>
  8463. * <li>The following constants are allowed:
  8464. * <ul>
  8465. * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
  8466. * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
  8467. * </ul>
  8468. * </li>
  8469. * <li>The following syntax is expected:
  8470. * <ul>
  8471. * <li>'&lt;' and '&gt;' - div elements</li>
  8472. * <li>'&lt;"class" and '&gt;' - div with a class</li>
  8473. * <li>'&lt;"#id" and '&gt;' - div with an ID</li>
  8474. * </ul>
  8475. * </li>
  8476. * <li>Examples:
  8477. * <ul>
  8478. * <li>'&lt;"wrapper"flipt&gt;'</li>
  8479. * <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
  8480. * </ul>
  8481. * </li>
  8482. * </ul>
  8483. * @type string
  8484. * @default lfrtip <i>(when bJQueryUI is false)</i> <b>or</b>
  8485. * <"H"lfr>t<"F"ip> <i>(when bJQueryUI is true)</i>
  8486. * @dtopt Options
  8487. *
  8488. * @example
  8489. * $(document).ready(function() {
  8490. * $('#example').dataTable( {
  8491. * "sDom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
  8492. * } );
  8493. * } );
  8494. */
  8495. "sDom": "lfrtip",
  8496. /**
  8497. * DataTables features two different built-in pagination interaction methods
  8498. * ('two_button' or 'full_numbers') which present different page controls to
  8499. * the end user. Further methods can be added using the API (see below).
  8500. * @type string
  8501. * @default two_button
  8502. * @dtopt Options
  8503. *
  8504. * @example
  8505. * $(document).ready( function() {
  8506. * $('#example').dataTable( {
  8507. * "sPaginationType": "full_numbers"
  8508. * } );
  8509. * } )
  8510. */
  8511. "sPaginationType": "two_button",
  8512. /**
  8513. * Enable horizontal scrolling. When a table is too wide to fit into a certain
  8514. * layout, or you have a large number of columns in the table, you can enable
  8515. * x-scrolling to show the table in a viewport, which can be scrolled. This
  8516. * property can be any CSS unit, or a number (in which case it will be treated
  8517. * as a pixel measurement).
  8518. * @type string
  8519. * @default <i>blank string - i.e. disabled</i>
  8520. * @dtopt Features
  8521. *
  8522. * @example
  8523. * $(document).ready(function() {
  8524. * $('#example').dataTable( {
  8525. * "sScrollX": "100%",
  8526. * "bScrollCollapse": true
  8527. * } );
  8528. * } );
  8529. */
  8530. "sScrollX": "",
  8531. /**
  8532. * This property can be used to force a DataTable to use more width than it
  8533. * might otherwise do when x-scrolling is enabled. For example if you have a
  8534. * table which requires to be well spaced, this parameter is useful for
  8535. * "over-sizing" the table, and thus forcing scrolling. This property can by
  8536. * any CSS unit, or a number (in which case it will be treated as a pixel
  8537. * measurement).
  8538. * @type string
  8539. * @default <i>blank string - i.e. disabled</i>
  8540. * @dtopt Options
  8541. *
  8542. * @example
  8543. * $(document).ready(function() {
  8544. * $('#example').dataTable( {
  8545. * "sScrollX": "100%",
  8546. * "sScrollXInner": "110%"
  8547. * } );
  8548. * } );
  8549. */
  8550. "sScrollXInner": "",
  8551. /**
  8552. * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
  8553. * to the given height, and enable scrolling for any data which overflows the
  8554. * current viewport. This can be used as an alternative to paging to display
  8555. * a lot of data in a small area (although paging and scrolling can both be
  8556. * enabled at the same time). This property can be any CSS unit, or a number
  8557. * (in which case it will be treated as a pixel measurement).
  8558. * @type string
  8559. * @default <i>blank string - i.e. disabled</i>
  8560. * @dtopt Features
  8561. *
  8562. * @example
  8563. * $(document).ready(function() {
  8564. * $('#example').dataTable( {
  8565. * "sScrollY": "200px",
  8566. * "bPaginate": false
  8567. * } );
  8568. * } );
  8569. */
  8570. "sScrollY": "",
  8571. /**
  8572. * Set the HTTP method that is used to make the Ajax call for server-side
  8573. * processing or Ajax sourced data.
  8574. * @type string
  8575. * @default GET
  8576. * @dtopt Options
  8577. * @dtopt Server-side
  8578. *
  8579. * @example
  8580. * $(document).ready(function() {
  8581. * $('#example').dataTable( {
  8582. * "bServerSide": true,
  8583. * "sAjaxSource": "scripts/post.php",
  8584. * "sServerMethod": "POST"
  8585. * } );
  8586. * } );
  8587. */
  8588. "sServerMethod": "GET"
  8589. };
  8590. /**
  8591. * Column options that can be given to DataTables at initialisation time.
  8592. * @namespace
  8593. */
  8594. DataTable.defaults.columns = {
  8595. /**
  8596. * Allows a column's sorting to take multiple columns into account when
  8597. * doing a sort. For example first name / last name columns make sense to
  8598. * do a multi-column sort over the two columns.
  8599. * @type array
  8600. * @default null <i>Takes the value of the column index automatically</i>
  8601. * @dtopt Columns
  8602. *
  8603. * @example
  8604. * // Using aoColumnDefs
  8605. * $(document).ready(function() {
  8606. * $('#example').dataTable( {
  8607. * "aoColumnDefs": [
  8608. * { "aDataSort": [ 0, 1 ], "aTargets": [ 0 ] },
  8609. * { "aDataSort": [ 1, 0 ], "aTargets": [ 1 ] },
  8610. * { "aDataSort": [ 2, 3, 4 ], "aTargets": [ 2 ] }
  8611. * ]
  8612. * } );
  8613. * } );
  8614. *
  8615. * @example
  8616. * // Using aoColumns
  8617. * $(document).ready(function() {
  8618. * $('#example').dataTable( {
  8619. * "aoColumns": [
  8620. * { "aDataSort": [ 0, 1 ] },
  8621. * { "aDataSort": [ 1, 0 ] },
  8622. * { "aDataSort": [ 2, 3, 4 ] },
  8623. * null,
  8624. * null
  8625. * ]
  8626. * } );
  8627. * } );
  8628. */
  8629. "aDataSort": null,
  8630. /**
  8631. * You can control the default sorting direction, and even alter the behaviour
  8632. * of the sort handler (i.e. only allow ascending sorting etc) using this
  8633. * parameter.
  8634. * @type array
  8635. * @default [ 'asc', 'desc' ]
  8636. * @dtopt Columns
  8637. *
  8638. * @example
  8639. * // Using aoColumnDefs
  8640. * $(document).ready(function() {
  8641. * $('#example').dataTable( {
  8642. * "aoColumnDefs": [
  8643. * { "asSorting": [ "asc" ], "aTargets": [ 1 ] },
  8644. * { "asSorting": [ "desc", "asc", "asc" ], "aTargets": [ 2 ] },
  8645. * { "asSorting": [ "desc" ], "aTargets": [ 3 ] }
  8646. * ]
  8647. * } );
  8648. * } );
  8649. *
  8650. * @example
  8651. * // Using aoColumns
  8652. * $(document).ready(function() {
  8653. * $('#example').dataTable( {
  8654. * "aoColumns": [
  8655. * null,
  8656. * { "asSorting": [ "asc" ] },
  8657. * { "asSorting": [ "desc", "asc", "asc" ] },
  8658. * { "asSorting": [ "desc" ] },
  8659. * null
  8660. * ]
  8661. * } );
  8662. * } );
  8663. */
  8664. "asSorting": [ 'asc', 'desc' ],
  8665. /**
  8666. * Enable or disable filtering on the data in this column.
  8667. * @type boolean
  8668. * @default true
  8669. * @dtopt Columns
  8670. *
  8671. * @example
  8672. * // Using aoColumnDefs
  8673. * $(document).ready(function() {
  8674. * $('#example').dataTable( {
  8675. * "aoColumnDefs": [
  8676. * { "bSearchable": false, "aTargets": [ 0 ] }
  8677. * ] } );
  8678. * } );
  8679. *
  8680. * @example
  8681. * // Using aoColumns
  8682. * $(document).ready(function() {
  8683. * $('#example').dataTable( {
  8684. * "aoColumns": [
  8685. * { "bSearchable": false },
  8686. * null,
  8687. * null,
  8688. * null,
  8689. * null
  8690. * ] } );
  8691. * } );
  8692. */
  8693. "bSearchable": true,
  8694. /**
  8695. * Enable or disable sorting on this column.
  8696. * @type boolean
  8697. * @default true
  8698. * @dtopt Columns
  8699. *
  8700. * @example
  8701. * // Using aoColumnDefs
  8702. * $(document).ready(function() {
  8703. * $('#example').dataTable( {
  8704. * "aoColumnDefs": [
  8705. * { "bSortable": false, "aTargets": [ 0 ] }
  8706. * ] } );
  8707. * } );
  8708. *
  8709. * @example
  8710. * // Using aoColumns
  8711. * $(document).ready(function() {
  8712. * $('#example').dataTable( {
  8713. * "aoColumns": [
  8714. * { "bSortable": false },
  8715. * null,
  8716. * null,
  8717. * null,
  8718. * null
  8719. * ] } );
  8720. * } );
  8721. */
  8722. "bSortable": true,
  8723. /**
  8724. * When using fnRender() for a column, you may wish to use the original data
  8725. * (before rendering) for sorting and filtering (the default is to used the
  8726. * rendered data that the user can see). This may be useful for dates etc.
  8727. *
  8728. * *NOTE* It is it is advisable now to use mDataProp as a function and make
  8729. * use of the 'type' that it gives, allowing (potentially) different data to
  8730. * be used for sorting, filtering, display and type detection.
  8731. * @type boolean
  8732. * @default true
  8733. * @dtopt Columns
  8734. *
  8735. * @example
  8736. * // Using aoColumnDefs
  8737. * $(document).ready(function() {
  8738. * $('#example').dataTable( {
  8739. * "aoColumnDefs": [
  8740. * {
  8741. * "fnRender": function ( oObj ) {
  8742. * return oObj.aData[0] +' '+ oObj.aData[3];
  8743. * },
  8744. * "bUseRendered": false,
  8745. * "aTargets": [ 0 ]
  8746. * }
  8747. * ]
  8748. * } );
  8749. * } );
  8750. *
  8751. * @example
  8752. * // Using aoColumns
  8753. * $(document).ready(function() {
  8754. * $('#example').dataTable( {
  8755. * "aoColumns": [
  8756. * {
  8757. * "fnRender": function ( oObj ) {
  8758. * return oObj.aData[0] +' '+ oObj.aData[3];
  8759. * },
  8760. * "bUseRendered": false
  8761. * },
  8762. * null,
  8763. * null,
  8764. * null,
  8765. * null
  8766. * ]
  8767. * } );
  8768. * } );
  8769. */
  8770. "bUseRendered": true,
  8771. /**
  8772. * Enable or disable the display of this column.
  8773. * @type boolean
  8774. * @default true
  8775. * @dtopt Columns
  8776. *
  8777. * @example
  8778. * // Using aoColumnDefs
  8779. * $(document).ready(function() {
  8780. * $('#example').dataTable( {
  8781. * "aoColumnDefs": [
  8782. * { "bVisible": false, "aTargets": [ 0 ] }
  8783. * ] } );
  8784. * } );
  8785. *
  8786. * @example
  8787. * // Using aoColumns
  8788. * $(document).ready(function() {
  8789. * $('#example').dataTable( {
  8790. * "aoColumns": [
  8791. * { "bVisible": false },
  8792. * null,
  8793. * null,
  8794. * null,
  8795. * null
  8796. * ] } );
  8797. * } );
  8798. */
  8799. "bVisible": true,
  8800. /**
  8801. * Developer definable function that is called whenever a cell is created (Ajax source,
  8802. * etc) or processed for input (DOM source). This can be used as a compliment to fnRender
  8803. * allowing you to modify the DOM element (add background colour for example) when the
  8804. * element is available (since it is not when fnRender is called).
  8805. * @type function
  8806. * @param {element} nTd The TD node that has been created
  8807. * @param {*} sData The Data for the cell
  8808. * @param {array|object} oData The data for the whole row
  8809. * @param {int} iRow The row index for the aoData data store
  8810. * @param {int} iCol The column index for aoColumns
  8811. * @dtopt Columns
  8812. *
  8813. * @example
  8814. * $(document).ready(function() {
  8815. * $('#example').dataTable( {
  8816. * "aoColumnDefs": [ {
  8817. * "aTargets": [3],
  8818. * "fnCreatedCell": function (nTd, sData, oData, iRow, iCol) {
  8819. * if ( sData == "1.7" ) {
  8820. * $(nTd).css('color', 'blue')
  8821. * }
  8822. * }
  8823. * } ]
  8824. * });
  8825. * } );
  8826. */
  8827. "fnCreatedCell": null,
  8828. /**
  8829. * Custom display function that will be called for the display of each cell in
  8830. * this column.
  8831. * @type function
  8832. * @param {object} o Object with the following parameters:
  8833. * @param {int} o.iDataRow The row in aoData
  8834. * @param {int} o.iDataColumn The column in question
  8835. * @param {array} o.aData The data for the row in question
  8836. * @param {object} o.oSettings The settings object for this DataTables instance
  8837. * @param {object} o.mDataProp The data property used for this column
  8838. * @param {*} val The current cell value
  8839. * @returns {string} The string you which to use in the display
  8840. * @dtopt Columns
  8841. *
  8842. * @example
  8843. * // Using aoColumnDefs
  8844. * $(document).ready(function() {
  8845. * $('#example').dataTable( {
  8846. * "aoColumnDefs": [
  8847. * {
  8848. * "fnRender": function ( o, val ) {
  8849. * return o.aData[0] +' '+ o.aData[3];
  8850. * },
  8851. * "aTargets": [ 0 ]
  8852. * }
  8853. * ]
  8854. * } );
  8855. * } );
  8856. *
  8857. * @example
  8858. * // Using aoColumns
  8859. * $(document).ready(function() {
  8860. * $('#example').dataTable( {
  8861. * "aoColumns": [
  8862. * { "fnRender": function ( o, val ) {
  8863. * return o.aData[0] +' '+ o.aData[3];
  8864. * } },
  8865. * null,
  8866. * null,
  8867. * null,
  8868. * null
  8869. * ]
  8870. * } );
  8871. * } );
  8872. */
  8873. "fnRender": null,
  8874. /**
  8875. * The column index (starting from 0!) that you wish a sort to be performed
  8876. * upon when this column is selected for sorting. This can be used for sorting
  8877. * on hidden columns for example.
  8878. * @type int
  8879. * @default -1 <i>Use automatically calculated column index</i>
  8880. * @dtopt Columns
  8881. *
  8882. * @example
  8883. * // Using aoColumnDefs
  8884. * $(document).ready(function() {
  8885. * $('#example').dataTable( {
  8886. * "aoColumnDefs": [
  8887. * { "iDataSort": 1, "aTargets": [ 0 ] }
  8888. * ]
  8889. * } );
  8890. * } );
  8891. *
  8892. * @example
  8893. * // Using aoColumns
  8894. * $(document).ready(function() {
  8895. * $('#example').dataTable( {
  8896. * "aoColumns": [
  8897. * { "iDataSort": 1 },
  8898. * null,
  8899. * null,
  8900. * null,
  8901. * null
  8902. * ]
  8903. * } );
  8904. * } );
  8905. */
  8906. "iDataSort": -1,
  8907. /**
  8908. * This property can be used to read data from any JSON data source property,
  8909. * including deeply nested objects / properties. mDataProp can be given in a
  8910. * number of different ways which effect its behaviour:
  8911. * <ul>
  8912. * <li>integer - treated as an array index for the data source. This is the
  8913. * default that DataTables uses (incrementally increased for each column).</li>
  8914. * <li>string - read an object property from the data source. Note that you can
  8915. * use Javascript dotted notation to read deep properties/arrays from the
  8916. * data source.</li>
  8917. * <li>null - the sDefaultContent option will be used for the cell (null
  8918. * by default, so you will need to specify the default content you want -
  8919. * typically an empty string). This can be useful on generated columns such
  8920. * as edit / delete action columns.</li>
  8921. * <li>function - the function given will be executed whenever DataTables
  8922. * needs to set or get the data for a cell in the column. The function
  8923. * takes three parameters:
  8924. * <ul>
  8925. * <li>{array|object} The data source for the row</li>
  8926. * <li>{string} The type call data requested - this will be 'set' when
  8927. * setting data or 'filter', 'display', 'type', 'sort' or undefined when
  8928. * gathering data. Note that when <i>undefined</i> is given for the type
  8929. * DataTables expects to get the raw data for the object back</li>
  8930. * <li>{*} Data to set when the second parameter is 'set'.</li>
  8931. * </ul>
  8932. * The return value from the function is not required when 'set' is the type
  8933. * of call, but otherwise the return is what will be used for the data
  8934. * requested.</li>
  8935. * </ul>
  8936. * @type string|int|function|null
  8937. * @default null <i>Use automatically calculated column index</i>
  8938. * @dtopt Columns
  8939. *
  8940. * @example
  8941. * // Read table data from objects
  8942. * $(document).ready(function() {
  8943. * var oTable = $('#example').dataTable( {
  8944. * "sAjaxSource": "sources/deep.txt",
  8945. * "aoColumns": [
  8946. * { "mDataProp": "engine" },
  8947. * { "mDataProp": "browser" },
  8948. * { "mDataProp": "platform.inner" },
  8949. * { "mDataProp": "platform.details.0" },
  8950. * { "mDataProp": "platform.details.1" }
  8951. * ]
  8952. * } );
  8953. * } );
  8954. *
  8955. * @example
  8956. * // Using mDataProp as a function to provide different information for
  8957. * // sorting, filtering and display. In this case, currency (price)
  8958. * $(document).ready(function() {
  8959. * var oTable = $('#example').dataTable( {
  8960. * "aoColumnDefs": [
  8961. * {
  8962. * "aTargets": [ 0 ],
  8963. * "mDataProp": function ( source, type, val ) {
  8964. * if (type === 'set') {
  8965. * source.price = val;
  8966. * // Store the computed dislay and filter values for efficiency
  8967. * source.price_display = val=="" ? "" : "$"+numberFormat(val);
  8968. * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
  8969. * return;
  8970. * }
  8971. * else if (type === 'display') {
  8972. * return source.price_display;
  8973. * }
  8974. * else if (type === 'filter') {
  8975. * return source.price_filter;
  8976. * }
  8977. * // 'sort', 'type' and undefined all just use the integer
  8978. * return source.price;
  8979. * }
  8980. * ]
  8981. * } );
  8982. * } );
  8983. */
  8984. "mDataProp": null,
  8985. /**
  8986. * Change the cell type created for the column - either TD cells or TH cells. This
  8987. * can be useful as TH cells have semantic meaning in the table body, allowing them
  8988. * to act as a header for a row (you may wish to add scope='row' to the TH elements).
  8989. * @type string
  8990. * @default td
  8991. * @dtopt Columns
  8992. *
  8993. * @example
  8994. * // Make the first column use TH cells
  8995. * $(document).ready(function() {
  8996. * var oTable = $('#example').dataTable( {
  8997. * "aoColumnDefs": [
  8998. * {
  8999. * "aTargets": [ 0 ],
  9000. * "sCellType": "th"
  9001. * ]
  9002. * } );
  9003. * } );
  9004. */
  9005. "sCellType": "td",
  9006. /**
  9007. * Class to give to each cell in this column.
  9008. * @type string
  9009. * @default <i>Empty string</i>
  9010. * @dtopt Columns
  9011. *
  9012. * @example
  9013. * // Using aoColumnDefs
  9014. * $(document).ready(function() {
  9015. * $('#example').dataTable( {
  9016. * "aoColumnDefs": [
  9017. * { "sClass": "my_class", "aTargets": [ 0 ] }
  9018. * ]
  9019. * } );
  9020. * } );
  9021. *
  9022. * @example
  9023. * // Using aoColumns
  9024. * $(document).ready(function() {
  9025. * $('#example').dataTable( {
  9026. * "aoColumns": [
  9027. * { "sClass": "my_class" },
  9028. * null,
  9029. * null,
  9030. * null,
  9031. * null
  9032. * ]
  9033. * } );
  9034. * } );
  9035. */
  9036. "sClass": "",
  9037. /**
  9038. * When DataTables calculates the column widths to assign to each column,
  9039. * it finds the longest string in each column and then constructs a
  9040. * temporary table and reads the widths from that. The problem with this
  9041. * is that "mmm" is much wider then "iiii", but the latter is a longer
  9042. * string - thus the calculation can go wrong (doing it properly and putting
  9043. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  9044. * a "work around" we provide this option. It will append its value to the
  9045. * text that is found to be the longest string for the column - i.e. padding.
  9046. * Generally you shouldn't need this, and it is not documented on the
  9047. * general DataTables.net documentation
  9048. * @type string
  9049. * @default <i>Empty string<i>
  9050. * @dtopt Columns
  9051. *
  9052. * @example
  9053. * // Using aoColumns
  9054. * $(document).ready(function() {
  9055. * $('#example').dataTable( {
  9056. * "aoColumns": [
  9057. * null,
  9058. * null,
  9059. * null,
  9060. * {
  9061. * "sContentPadding": "mmm"
  9062. * }
  9063. * ]
  9064. * } );
  9065. * } );
  9066. */
  9067. "sContentPadding": "",
  9068. /**
  9069. * Allows a default value to be given for a column's data, and will be used
  9070. * whenever a null data source is encountered (this can be because mDataProp
  9071. * is set to null, or because the data source itself is null).
  9072. * @type string
  9073. * @default null
  9074. * @dtopt Columns
  9075. *
  9076. * @example
  9077. * // Using aoColumnDefs
  9078. * $(document).ready(function() {
  9079. * $('#example').dataTable( {
  9080. * "aoColumnDefs": [
  9081. * {
  9082. * "mDataProp": null,
  9083. * "sDefaultContent": "Edit",
  9084. * "aTargets": [ -1 ]
  9085. * }
  9086. * ]
  9087. * } );
  9088. * } );
  9089. *
  9090. * @example
  9091. * // Using aoColumns
  9092. * $(document).ready(function() {
  9093. * $('#example').dataTable( {
  9094. * "aoColumns": [
  9095. * null,
  9096. * null,
  9097. * null,
  9098. * {
  9099. * "mDataProp": null,
  9100. * "sDefaultContent": "Edit"
  9101. * }
  9102. * ]
  9103. * } );
  9104. * } );
  9105. */
  9106. "sDefaultContent": null,
  9107. /**
  9108. * This parameter is only used in DataTables' server-side processing. It can
  9109. * be exceptionally useful to know what columns are being displayed on the
  9110. * client side, and to map these to database fields. When defined, the names
  9111. * also allow DataTables to reorder information from the server if it comes
  9112. * back in an unexpected order (i.e. if you switch your columns around on the
  9113. * client-side, your server-side code does not also need updating).
  9114. * @type string
  9115. * @default <i>Empty string</i>
  9116. * @dtopt Columns
  9117. *
  9118. * @example
  9119. * // Using aoColumnDefs
  9120. * $(document).ready(function() {
  9121. * $('#example').dataTable( {
  9122. * "aoColumnDefs": [
  9123. * { "sName": "engine", "aTargets": [ 0 ] },
  9124. * { "sName": "browser", "aTargets": [ 1 ] },
  9125. * { "sName": "platform", "aTargets": [ 2 ] },
  9126. * { "sName": "version", "aTargets": [ 3 ] },
  9127. * { "sName": "grade", "aTargets": [ 4 ] }
  9128. * ]
  9129. * } );
  9130. * } );
  9131. *
  9132. * @example
  9133. * // Using aoColumns
  9134. * $(document).ready(function() {
  9135. * $('#example').dataTable( {
  9136. * "aoColumns": [
  9137. * { "sName": "engine" },
  9138. * { "sName": "browser" },
  9139. * { "sName": "platform" },
  9140. * { "sName": "version" },
  9141. * { "sName": "grade" }
  9142. * ]
  9143. * } );
  9144. * } );
  9145. */
  9146. "sName": "",
  9147. /**
  9148. * Defines a data source type for the sorting which can be used to read
  9149. * realtime information from the table (updating the internally cached
  9150. * version) prior to sorting. This allows sorting to occur on user editable
  9151. * elements such as form inputs.
  9152. * @type string
  9153. * @default std
  9154. * @dtopt Columns
  9155. *
  9156. * @example
  9157. * // Using aoColumnDefs
  9158. * $(document).ready(function() {
  9159. * $('#example').dataTable( {
  9160. * "aoColumnDefs": [
  9161. * { "sSortDataType": "dom-text", "aTargets": [ 2, 3 ] },
  9162. * { "sType": "numeric", "aTargets": [ 3 ] },
  9163. * { "sSortDataType": "dom-select", "aTargets": [ 4 ] },
  9164. * { "sSortDataType": "dom-checkbox", "aTargets": [ 5 ] }
  9165. * ]
  9166. * } );
  9167. * } );
  9168. *
  9169. * @example
  9170. * // Using aoColumns
  9171. * $(document).ready(function() {
  9172. * $('#example').dataTable( {
  9173. * "aoColumns": [
  9174. * null,
  9175. * null,
  9176. * { "sSortDataType": "dom-text" },
  9177. * { "sSortDataType": "dom-text", "sType": "numeric" },
  9178. * { "sSortDataType": "dom-select" },
  9179. * { "sSortDataType": "dom-checkbox" }
  9180. * ]
  9181. * } );
  9182. * } );
  9183. */
  9184. "sSortDataType": "std",
  9185. /**
  9186. * The title of this column.
  9187. * @type string
  9188. * @default null <i>Derived from the 'TH' value for this column in the
  9189. * original HTML table.</i>
  9190. * @dtopt Columns
  9191. *
  9192. * @example
  9193. * // Using aoColumnDefs
  9194. * $(document).ready(function() {
  9195. * $('#example').dataTable( {
  9196. * "aoColumnDefs": [
  9197. * { "sTitle": "My column title", "aTargets": [ 0 ] }
  9198. * ]
  9199. * } );
  9200. * } );
  9201. *
  9202. * @example
  9203. * // Using aoColumns
  9204. * $(document).ready(function() {
  9205. * $('#example').dataTable( {
  9206. * "aoColumns": [
  9207. * { "sTitle": "My column title" },
  9208. * null,
  9209. * null,
  9210. * null,
  9211. * null
  9212. * ]
  9213. * } );
  9214. * } );
  9215. */
  9216. "sTitle": null,
  9217. /**
  9218. * The type allows you to specify how the data for this column will be sorted.
  9219. * Four types (string, numeric, date and html (which will strip HTML tags
  9220. * before sorting)) are currently available. Note that only date formats
  9221. * understood by Javascript's Date() object will be accepted as type date. For
  9222. * example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 'numeric',
  9223. * 'date' or 'html' (by default). Further types can be adding through
  9224. * plug-ins.
  9225. * @type string
  9226. * @default null <i>Auto-detected from raw data</i>
  9227. * @dtopt Columns
  9228. *
  9229. * @example
  9230. * // Using aoColumnDefs
  9231. * $(document).ready(function() {
  9232. * $('#example').dataTable( {
  9233. * "aoColumnDefs": [
  9234. * { "sType": "html", "aTargets": [ 0 ] }
  9235. * ]
  9236. * } );
  9237. * } );
  9238. *
  9239. * @example
  9240. * // Using aoColumns
  9241. * $(document).ready(function() {
  9242. * $('#example').dataTable( {
  9243. * "aoColumns": [
  9244. * { "sType": "html" },
  9245. * null,
  9246. * null,
  9247. * null,
  9248. * null
  9249. * ]
  9250. * } );
  9251. * } );
  9252. */
  9253. "sType": null,
  9254. /**
  9255. * Defining the width of the column, this parameter may take any CSS value
  9256. * (3em, 20px etc). DataTables applys 'smart' widths to columns which have not
  9257. * been given a specific width through this interface ensuring that the table
  9258. * remains readable.
  9259. * @type string
  9260. * @default null <i>Automatic</i>
  9261. * @dtopt Columns
  9262. *
  9263. * @example
  9264. * // Using aoColumnDefs
  9265. * $(document).ready(function() {
  9266. * $('#example').dataTable( {
  9267. * "aoColumnDefs": [
  9268. * { "sWidth": "20%", "aTargets": [ 0 ] }
  9269. * ]
  9270. * } );
  9271. * } );
  9272. *
  9273. * @example
  9274. * // Using aoColumns
  9275. * $(document).ready(function() {
  9276. * $('#example').dataTable( {
  9277. * "aoColumns": [
  9278. * { "sWidth": "20%" },
  9279. * null,
  9280. * null,
  9281. * null,
  9282. * null
  9283. * ]
  9284. * } );
  9285. * } );
  9286. */
  9287. "sWidth": null
  9288. };
  9289. /**
  9290. * DataTables settings object - this holds all the information needed for a
  9291. * given table, including configuration, data and current application of the
  9292. * table options. DataTables does not have a single instance for each DataTable
  9293. * with the settings attached to that instance, but rather instances of the
  9294. * DataTable "class" are created on-the-fly as needed (typically by a
  9295. * $().dataTable() call) and the settings object is then applied to that
  9296. * instance.
  9297. *
  9298. * Note that this object is related to {@link DataTable.defaults} but this
  9299. * one is the internal data store for DataTables's cache of columns. It should
  9300. * NOT be manipulated outside of DataTables. Any configuration should be done
  9301. * through the initialisation options.
  9302. * @namespace
  9303. * @todo Really should attach the settings object to individual instances so we
  9304. * don't need to create new instances on each $().dataTable() call (if the
  9305. * table already exists). It would also save passing oSettings around and
  9306. * into every single function. However, this is a very significant
  9307. * architecture change for DataTables and will almost certainly break
  9308. * backwards compatibility with older installations. This is something that
  9309. * will be done in 2.0.
  9310. */
  9311. DataTable.models.oSettings = {
  9312. /**
  9313. * Primary features of DataTables and their enablement state.
  9314. * @namespace
  9315. */
  9316. "oFeatures": {
  9317. /**
  9318. * Flag to say if DataTables should automatically try to calculate the
  9319. * optimum table and columns widths (true) or not (false).
  9320. * Note that this parameter will be set by the initialisation routine. To
  9321. * set a default use {@link DataTable.defaults}.
  9322. * @type boolean
  9323. */
  9324. "bAutoWidth": null,
  9325. /**
  9326. * Delay the creation of TR and TD elements until they are actually
  9327. * needed by a driven page draw. This can give a significant speed
  9328. * increase for Ajax source and Javascript source data, but makes no
  9329. * difference at all fro DOM and server-side processing tables.
  9330. * Note that this parameter will be set by the initialisation routine. To
  9331. * set a default use {@link DataTable.defaults}.
  9332. * @type boolean
  9333. */
  9334. "bDeferRender": null,
  9335. /**
  9336. * Enable filtering on the table or not. Note that if this is disabled
  9337. * then there is no filtering at all on the table, including fnFilter.
  9338. * To just remove the filtering input use sDom and remove the 'f' option.
  9339. * Note that this parameter will be set by the initialisation routine. To
  9340. * set a default use {@link DataTable.defaults}.
  9341. * @type boolean
  9342. */
  9343. "bFilter": null,
  9344. /**
  9345. * Table information element (the 'Showing x of y records' div) enable
  9346. * flag.
  9347. * Note that this parameter will be set by the initialisation routine. To
  9348. * set a default use {@link DataTable.defaults}.
  9349. * @type boolean
  9350. */
  9351. "bInfo": null,
  9352. /**
  9353. * Present a user control allowing the end user to change the page size
  9354. * when pagination is enabled.
  9355. * Note that this parameter will be set by the initialisation routine. To
  9356. * set a default use {@link DataTable.defaults}.
  9357. * @type boolean
  9358. */
  9359. "bLengthChange": null,
  9360. /**
  9361. * Pagination enabled or not. Note that if this is disabled then length
  9362. * changing must also be disabled.
  9363. * Note that this parameter will be set by the initialisation routine. To
  9364. * set a default use {@link DataTable.defaults}.
  9365. * @type boolean
  9366. */
  9367. "bPaginate": null,
  9368. /**
  9369. * Processing indicator enable flag whenever DataTables is enacting a
  9370. * user request - typically an Ajax request for server-side processing.
  9371. * Note that this parameter will be set by the initialisation routine. To
  9372. * set a default use {@link DataTable.defaults}.
  9373. * @type boolean
  9374. */
  9375. "bProcessing": null,
  9376. /**
  9377. * Server-side processing enabled flag - when enabled DataTables will
  9378. * get all data from the server for every draw - there is no filtering,
  9379. * sorting or paging done on the client-side.
  9380. * Note that this parameter will be set by the initialisation routine. To
  9381. * set a default use {@link DataTable.defaults}.
  9382. * @type boolean
  9383. */
  9384. "bServerSide": null,
  9385. /**
  9386. * Sorting enablement flag.
  9387. * Note that this parameter will be set by the initialisation routine. To
  9388. * set a default use {@link DataTable.defaults}.
  9389. * @type boolean
  9390. */
  9391. "bSort": null,
  9392. /**
  9393. * Apply a class to the columns which are being sorted to provide a
  9394. * visual highlight or not. This can slow things down when enabled since
  9395. * there is a lot of DOM interaction.
  9396. * Note that this parameter will be set by the initialisation routine. To
  9397. * set a default use {@link DataTable.defaults}.
  9398. * @type boolean
  9399. */
  9400. "bSortClasses": null,
  9401. /**
  9402. * State saving enablement flag.
  9403. * Note that this parameter will be set by the initialisation routine. To
  9404. * set a default use {@link DataTable.defaults}.
  9405. * @type boolean
  9406. */
  9407. "bStateSave": null
  9408. },
  9409. /**
  9410. * Scrolling settings for a table.
  9411. * @namespace
  9412. */
  9413. "oScroll": {
  9414. /**
  9415. * Indicate if DataTables should be allowed to set the padding / margin
  9416. * etc for the scrolling header elements or not. Typically you will want
  9417. * this.
  9418. * Note that this parameter will be set by the initialisation routine. To
  9419. * set a default use {@link DataTable.defaults}.
  9420. * @type boolean
  9421. */
  9422. "bAutoCss": null,
  9423. /**
  9424. * When the table is shorter in height than sScrollY, collapse the
  9425. * table container down to the height of the table (when true).
  9426. * Note that this parameter will be set by the initialisation routine. To
  9427. * set a default use {@link DataTable.defaults}.
  9428. * @type boolean
  9429. */
  9430. "bCollapse": null,
  9431. /**
  9432. * Infinite scrolling enablement flag. Now deprecated in favour of
  9433. * using the Scroller plug-in.
  9434. * Note that this parameter will be set by the initialisation routine. To
  9435. * set a default use {@link DataTable.defaults}.
  9436. * @type boolean
  9437. */
  9438. "bInfinite": null,
  9439. /**
  9440. * Width of the scrollbar for the web-browser's platform. Calculated
  9441. * during table initialisation.
  9442. * @type int
  9443. * @default 0
  9444. */
  9445. "iBarWidth": 0,
  9446. /**
  9447. * Space (in pixels) between the bottom of the scrolling container and
  9448. * the bottom of the scrolling viewport before the next page is loaded
  9449. * when using infinite scrolling.
  9450. * Note that this parameter will be set by the initialisation routine. To
  9451. * set a default use {@link DataTable.defaults}.
  9452. * @type int
  9453. */
  9454. "iLoadGap": null,
  9455. /**
  9456. * Viewport width for horizontal scrolling. Horizontal scrolling is
  9457. * disabled if an empty string.
  9458. * Note that this parameter will be set by the initialisation routine. To
  9459. * set a default use {@link DataTable.defaults}.
  9460. * @type string
  9461. */
  9462. "sX": null,
  9463. /**
  9464. * Width to expand the table to when using x-scrolling. Typically you
  9465. * should not need to use this.
  9466. * Note that this parameter will be set by the initialisation routine. To
  9467. * set a default use {@link DataTable.defaults}.
  9468. * @type string
  9469. * @deprecated
  9470. */
  9471. "sXInner": null,
  9472. /**
  9473. * Viewport height for vertical scrolling. Vertical scrolling is disabled
  9474. * if an empty string.
  9475. * Note that this parameter will be set by the initialisation routine. To
  9476. * set a default use {@link DataTable.defaults}.
  9477. * @type string
  9478. */
  9479. "sY": null
  9480. },
  9481. /**
  9482. * Language information for the table.
  9483. * @namespace
  9484. * @extends DataTable.defaults.oLanguage
  9485. */
  9486. "oLanguage": {
  9487. /**
  9488. * Information callback function. See
  9489. * {@link DataTable.defaults.fnInfoCallback}
  9490. * @type function
  9491. * @default
  9492. */
  9493. "fnInfoCallback": null
  9494. },
  9495. /**
  9496. * Array referencing the nodes which are used for the features. The
  9497. * parameters of this object match what is allowed by sDom - i.e.
  9498. * <ul>
  9499. * <li>'l' - Length changing</li>
  9500. * <li>'f' - Filtering input</li>
  9501. * <li>'t' - The table!</li>
  9502. * <li>'i' - Information</li>
  9503. * <li>'p' - Pagination</li>
  9504. * <li>'r' - pRocessing</li>
  9505. * </ul>
  9506. * @type array
  9507. * @default []
  9508. */
  9509. "aanFeatures": [],
  9510. /**
  9511. * Store data information - see {@link DataTable.models.oRow} for detailed
  9512. * information.
  9513. * @type array
  9514. * @default []
  9515. */
  9516. "aoData": [],
  9517. /**
  9518. * Array of indexes which are in the current display (after filtering etc)
  9519. * @type array
  9520. * @default []
  9521. */
  9522. "aiDisplay": [],
  9523. /**
  9524. * Array of indexes for display - no filtering
  9525. * @type array
  9526. * @default []
  9527. */
  9528. "aiDisplayMaster": [],
  9529. /**
  9530. * Store information about each column that is in use
  9531. * @type array
  9532. * @default []
  9533. */
  9534. "aoColumns": [],
  9535. /**
  9536. * Store information about the table's header
  9537. * @type array
  9538. * @default []
  9539. */
  9540. "aoHeader": [],
  9541. /**
  9542. * Store information about the table's footer
  9543. * @type array
  9544. * @default []
  9545. */
  9546. "aoFooter": [],
  9547. /**
  9548. * Search data array for regular expression searching
  9549. * @type array
  9550. * @default []
  9551. */
  9552. "asDataSearch": [],
  9553. /**
  9554. * Store the applied global search information in case we want to force a
  9555. * research or compare the old search to a new one.
  9556. * Note that this parameter will be set by the initialisation routine. To
  9557. * set a default use {@link DataTable.defaults}.
  9558. * @namespace
  9559. * @extends DataTable.models.oSearch
  9560. */
  9561. "oPreviousSearch": {},
  9562. /**
  9563. * Store the applied search for each column - see
  9564. * {@link DataTable.models.oSearch} for the format that is used for the
  9565. * filtering information for each column.
  9566. * @type array
  9567. * @default []
  9568. */
  9569. "aoPreSearchCols": [],
  9570. /**
  9571. * Sorting that is applied to the table. Note that the inner arrays are
  9572. * used in the following manner:
  9573. * <ul>
  9574. * <li>Index 0 - column number</li>
  9575. * <li>Index 1 - current sorting direction</li>
  9576. * <li>Index 2 - index of asSorting for this column</li>
  9577. * </ul>
  9578. * Note that this parameter will be set by the initialisation routine. To
  9579. * set a default use {@link DataTable.defaults}.
  9580. * @type array
  9581. * @todo These inner arrays should really be objects
  9582. */
  9583. "aaSorting": null,
  9584. /**
  9585. * Sorting that is always applied to the table (i.e. prefixed in front of
  9586. * aaSorting).
  9587. * Note that this parameter will be set by the initialisation routine. To
  9588. * set a default use {@link DataTable.defaults}.
  9589. * @type array|null
  9590. * @default null
  9591. */
  9592. "aaSortingFixed": null,
  9593. /**
  9594. * Classes to use for the striping of a table.
  9595. * Note that this parameter will be set by the initialisation routine. To
  9596. * set a default use {@link DataTable.defaults}.
  9597. * @type array
  9598. * @default []
  9599. */
  9600. "asStripeClasses": null,
  9601. /**
  9602. * If restoring a table - we should restore its striping classes as well
  9603. * @type array
  9604. * @default []
  9605. */
  9606. "asDestroyStripes": [],
  9607. /**
  9608. * If restoring a table - we should restore its width
  9609. * @type int
  9610. * @default 0
  9611. */
  9612. "sDestroyWidth": 0,
  9613. /**
  9614. * Callback functions array for every time a row is inserted (i.e. on a draw).
  9615. * @type array
  9616. * @default []
  9617. */
  9618. "aoRowCallback": [],
  9619. /**
  9620. * Callback functions for the header on each draw.
  9621. * @type array
  9622. * @default []
  9623. */
  9624. "aoHeaderCallback": [],
  9625. /**
  9626. * Callback function for the footer on each draw.
  9627. * @type array
  9628. * @default []
  9629. */
  9630. "aoFooterCallback": [],
  9631. /**
  9632. * Array of callback functions for draw callback functions
  9633. * @type array
  9634. * @default []
  9635. */
  9636. "aoDrawCallback": [],
  9637. /**
  9638. * Array of callback functions for row created function
  9639. * @type array
  9640. * @default []
  9641. */
  9642. "aoRowCreatedCallback": [],
  9643. /**
  9644. * Callback functions for just before the table is redrawn. A return of
  9645. * false will be used to cancel the draw.
  9646. * @type array
  9647. * @default []
  9648. */
  9649. "aoPreDrawCallback": [],
  9650. /**
  9651. * Callback functions for when the table has been initialised.
  9652. * @type array
  9653. * @default []
  9654. */
  9655. "aoInitComplete": [],
  9656. /**
  9657. * Callbacks for modifying the settings to be stored for state saving, prior to
  9658. * saving state.
  9659. * @type array
  9660. * @default []
  9661. */
  9662. "aoStateSaveParams": [],
  9663. /**
  9664. * Callbacks for modifying the settings that have been stored for state saving
  9665. * prior to using the stored values to restore the state.
  9666. * @type array
  9667. * @default []
  9668. */
  9669. "aoStateLoadParams": [],
  9670. /**
  9671. * Callbacks for operating on the settings object once the saved state has been
  9672. * loaded
  9673. * @type array
  9674. * @default []
  9675. */
  9676. "aoStateLoaded": [],
  9677. /**
  9678. * Cache the table ID for quick access
  9679. * @type string
  9680. * @default <i>Empty string</i>
  9681. */
  9682. "sTableId": "",
  9683. /**
  9684. * The TABLE node for the main table
  9685. * @type node
  9686. * @default null
  9687. */
  9688. "nTable": null,
  9689. /**
  9690. * Permanent ref to the thead element
  9691. * @type node
  9692. * @default null
  9693. */
  9694. "nTHead": null,
  9695. /**
  9696. * Permanent ref to the tfoot element - if it exists
  9697. * @type node
  9698. * @default null
  9699. */
  9700. "nTFoot": null,
  9701. /**
  9702. * Permanent ref to the tbody element
  9703. * @type node
  9704. * @default null
  9705. */
  9706. "nTBody": null,
  9707. /**
  9708. * Cache the wrapper node (contains all DataTables controlled elements)
  9709. * @type node
  9710. * @default null
  9711. */
  9712. "nTableWrapper": null,
  9713. /**
  9714. * Indicate if when using server-side processing the loading of data
  9715. * should be deferred until the second draw.
  9716. * Note that this parameter will be set by the initialisation routine. To
  9717. * set a default use {@link DataTable.defaults}.
  9718. * @type boolean
  9719. * @default false
  9720. */
  9721. "bDeferLoading": false,
  9722. /**
  9723. * Indicate if all required information has been read in
  9724. * @type boolean
  9725. * @default false
  9726. */
  9727. "bInitialised": false,
  9728. /**
  9729. * Information about open rows. Each object in the array has the parameters
  9730. * 'nTr' and 'nParent'
  9731. * @type array
  9732. * @default []
  9733. */
  9734. "aoOpenRows": [],
  9735. /**
  9736. * Dictate the positioning of DataTables' control elements - see
  9737. * {@link DataTable.model.oInit.sDom}.
  9738. * Note that this parameter will be set by the initialisation routine. To
  9739. * set a default use {@link DataTable.defaults}.
  9740. * @type string
  9741. * @default null
  9742. */
  9743. "sDom": null,
  9744. /**
  9745. * Which type of pagination should be used.
  9746. * Note that this parameter will be set by the initialisation routine. To
  9747. * set a default use {@link DataTable.defaults}.
  9748. * @type string
  9749. * @default two_button
  9750. */
  9751. "sPaginationType": "two_button",
  9752. /**
  9753. * The cookie duration (for bStateSave) in seconds.
  9754. * Note that this parameter will be set by the initialisation routine. To
  9755. * set a default use {@link DataTable.defaults}.
  9756. * @type int
  9757. * @default 0
  9758. */
  9759. "iCookieDuration": 0,
  9760. /**
  9761. * The cookie name prefix.
  9762. * Note that this parameter will be set by the initialisation routine. To
  9763. * set a default use {@link DataTable.defaults}.
  9764. * @type string
  9765. * @default <i>Empty string</i>
  9766. */
  9767. "sCookiePrefix": "",
  9768. /**
  9769. * Callback function for cookie creation.
  9770. * Note that this parameter will be set by the initialisation routine. To
  9771. * set a default use {@link DataTable.defaults}.
  9772. * @type function
  9773. * @default null
  9774. */
  9775. "fnCookieCallback": null,
  9776. /**
  9777. * Array of callback functions for state saving. Each array element is an
  9778. * object with the following parameters:
  9779. * <ul>
  9780. * <li>function:fn - function to call. Takes two parameters, oSettings
  9781. * and the JSON string to save that has been thus far created. Returns
  9782. * a JSON string to be inserted into a json object
  9783. * (i.e. '"param": [ 0, 1, 2]')</li>
  9784. * <li>string:sName - name of callback</li>
  9785. * </ul>
  9786. * @type array
  9787. * @default []
  9788. */
  9789. "aoStateSave": [],
  9790. /**
  9791. * Array of callback functions for state loading. Each array element is an
  9792. * object with the following parameters:
  9793. * <ul>
  9794. * <li>function:fn - function to call. Takes two parameters, oSettings
  9795. * and the object stored. May return false to cancel state loading</li>
  9796. * <li>string:sName - name of callback</li>
  9797. * </ul>
  9798. * @type array
  9799. * @default []
  9800. */
  9801. "aoStateLoad": [],
  9802. /**
  9803. * State that was loaded from the cookie. Useful for back reference
  9804. * @type object
  9805. * @default null
  9806. */
  9807. "oLoadedState": null,
  9808. /**
  9809. * Source url for AJAX data for the table.
  9810. * Note that this parameter will be set by the initialisation routine. To
  9811. * set a default use {@link DataTable.defaults}.
  9812. * @type string
  9813. * @default null
  9814. */
  9815. "sAjaxSource": null,
  9816. /**
  9817. * Property from a given object from which to read the table data from. This
  9818. * can be an empty string (when not server-side processing), in which case
  9819. * it is assumed an an array is given directly.
  9820. * Note that this parameter will be set by the initialisation routine. To
  9821. * set a default use {@link DataTable.defaults}.
  9822. * @type string
  9823. */
  9824. "sAjaxDataProp": null,
  9825. /**
  9826. * Note if draw should be blocked while getting data
  9827. * @type boolean
  9828. * @default true
  9829. */
  9830. "bAjaxDataGet": true,
  9831. /**
  9832. * The last jQuery XHR object that was used for server-side data gathering.
  9833. * This can be used for working with the XHR information in one of the
  9834. * callbacks
  9835. * @type object
  9836. * @default null
  9837. */
  9838. "jqXHR": null,
  9839. /**
  9840. * Function to get the server-side data.
  9841. * Note that this parameter will be set by the initialisation routine. To
  9842. * set a default use {@link DataTable.defaults}.
  9843. * @type function
  9844. */
  9845. "fnServerData": null,
  9846. /**
  9847. * Functions which are called prior to sending an Ajax request so extra
  9848. * parameters can easily be sent to the server
  9849. * @type array
  9850. * @default []
  9851. */
  9852. "aoServerParams": [],
  9853. /**
  9854. * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
  9855. * required).
  9856. * Note that this parameter will be set by the initialisation routine. To
  9857. * set a default use {@link DataTable.defaults}.
  9858. * @type string
  9859. */
  9860. "sServerMethod": null,
  9861. /**
  9862. * Format numbers for display.
  9863. * Note that this parameter will be set by the initialisation routine. To
  9864. * set a default use {@link DataTable.defaults}.
  9865. * @type function
  9866. */
  9867. "fnFormatNumber": null,
  9868. /**
  9869. * List of options that can be used for the user selectable length menu.
  9870. * Note that this parameter will be set by the initialisation routine. To
  9871. * set a default use {@link DataTable.defaults}.
  9872. * @type array
  9873. * @default []
  9874. */
  9875. "aLengthMenu": null,
  9876. /**
  9877. * Counter for the draws that the table does. Also used as a tracker for
  9878. * server-side processing
  9879. * @type int
  9880. * @default 0
  9881. */
  9882. "iDraw": 0,
  9883. /**
  9884. * Indicate if a redraw is being done - useful for Ajax
  9885. * @type boolean
  9886. * @default false
  9887. */
  9888. "bDrawing": false,
  9889. /**
  9890. * Draw index (iDraw) of the last error when parsing the returned data
  9891. * @type int
  9892. * @default -1
  9893. */
  9894. "iDrawError": -1,
  9895. /**
  9896. * Paging display length
  9897. * @type int
  9898. * @default 10
  9899. */
  9900. "_iDisplayLength": 10,
  9901. /**
  9902. * Paging start point - aiDisplay index
  9903. * @type int
  9904. * @default 0
  9905. */
  9906. "_iDisplayStart": 0,
  9907. /**
  9908. * Paging end point - aiDisplay index. Use fnDisplayEnd rather than
  9909. * this property to get the end point
  9910. * @type int
  9911. * @default 10
  9912. * @private
  9913. */
  9914. "_iDisplayEnd": 10,
  9915. /**
  9916. * Server-side processing - number of records in the result set
  9917. * (i.e. before filtering), Use fnRecordsTotal rather than
  9918. * this property to get the value of the number of records, regardless of
  9919. * the server-side processing setting.
  9920. * @type int
  9921. * @default 0
  9922. * @private
  9923. */
  9924. "_iRecordsTotal": 0,
  9925. /**
  9926. * Server-side processing - number of records in the current display set
  9927. * (i.e. after filtering). Use fnRecordsDisplay rather than
  9928. * this property to get the value of the number of records, regardless of
  9929. * the server-side processing setting.
  9930. * @type boolean
  9931. * @default 0
  9932. * @private
  9933. */
  9934. "_iRecordsDisplay": 0,
  9935. /**
  9936. * Flag to indicate if jQuery UI marking and classes should be used.
  9937. * Note that this parameter will be set by the initialisation routine. To
  9938. * set a default use {@link DataTable.defaults}.
  9939. * @type boolean
  9940. */
  9941. "bJUI": null,
  9942. /**
  9943. * The classes to use for the table
  9944. * @type object
  9945. * @default {}
  9946. */
  9947. "oClasses": {},
  9948. /**
  9949. * Flag attached to the settings object so you can check in the draw
  9950. * callback if filtering has been done in the draw. Deprecated in favour of
  9951. * events.
  9952. * @type boolean
  9953. * @default false
  9954. * @deprecated
  9955. */
  9956. "bFiltered": false,
  9957. /**
  9958. * Flag attached to the settings object so you can check in the draw
  9959. * callback if sorting has been done in the draw. Deprecated in favour of
  9960. * events.
  9961. * @type boolean
  9962. * @default false
  9963. * @deprecated
  9964. */
  9965. "bSorted": false,
  9966. /**
  9967. * Indicate that if multiple rows are in the header and there is more than
  9968. * one unique cell per column, if the top one (true) or bottom one (false)
  9969. * should be used for sorting / title by DataTables.
  9970. * Note that this parameter will be set by the initialisation routine. To
  9971. * set a default use {@link DataTable.defaults}.
  9972. * @type boolean
  9973. */
  9974. "bSortCellsTop": null,
  9975. /**
  9976. * Initialisation object that is used for the table
  9977. * @type object
  9978. * @default null
  9979. */
  9980. "oInit": null,
  9981. /**
  9982. * Destroy callback functions - for plug-ins to attach themselves to the
  9983. * destroy so they can clean up markup and events.
  9984. * @type array
  9985. * @default []
  9986. */
  9987. "aoDestroyCallback": [],
  9988. /**
  9989. * Get the number of records in the current record set, before filtering
  9990. * @type function
  9991. */
  9992. "fnRecordsTotal": function ()
  9993. {
  9994. if ( this.oFeatures.bServerSide ) {
  9995. return parseInt(this._iRecordsTotal, 10);
  9996. } else {
  9997. return this.aiDisplayMaster.length;
  9998. }
  9999. },
  10000. /**
  10001. * Get the number of records in the current record set, after filtering
  10002. * @type function
  10003. */
  10004. "fnRecordsDisplay": function ()
  10005. {
  10006. if ( this.oFeatures.bServerSide ) {
  10007. return parseInt(this._iRecordsDisplay, 10);
  10008. } else {
  10009. return this.aiDisplay.length;
  10010. }
  10011. },
  10012. /**
  10013. * Set the display end point - aiDisplay index
  10014. * @type function
  10015. * @todo Should do away with _iDisplayEnd and calculate it on-the-fly here
  10016. */
  10017. "fnDisplayEnd": function ()
  10018. {
  10019. if ( this.oFeatures.bServerSide ) {
  10020. if ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) {
  10021. return this._iDisplayStart+this.aiDisplay.length;
  10022. } else {
  10023. return Math.min( this._iDisplayStart+this._iDisplayLength,
  10024. this._iRecordsDisplay );
  10025. }
  10026. } else {
  10027. return this._iDisplayEnd;
  10028. }
  10029. },
  10030. /**
  10031. * The DataTables object for this table
  10032. * @type object
  10033. * @default null
  10034. */
  10035. "oInstance": null,
  10036. /**
  10037. * Unique identifier for each instance of the DataTables object. If there
  10038. * is an ID on the table node, then it takes that value, otherwise an
  10039. * incrementing internal counter is used.
  10040. * @type string
  10041. * @default null
  10042. */
  10043. "sInstance": null,
  10044. /**
  10045. * tabindex attribute value that is added to DataTables control elements, allowing
  10046. * keyboard navigation of the table and its controls.
  10047. */
  10048. "iTabIndex": 0,
  10049. /**
  10050. * DIV container for the footer scrolling table if scrolling
  10051. */
  10052. "nScrollHead": null,
  10053. /**
  10054. * DIV container for the footer scrolling table if scrolling
  10055. */
  10056. "nScrollFoot": null
  10057. };
  10058. /**
  10059. * Extension object for DataTables that is used to provide all extension options.
  10060. *
  10061. * Note that the <i>DataTable.ext</i> object is available through
  10062. * <i>jQuery.fn.dataTable.ext</i> where it may be accessed and manipulated. It is
  10063. * also aliased to <i>jQuery.fn.dataTableExt</i> for historic reasons.
  10064. * @namespace
  10065. * @extends DataTable.models.ext
  10066. */
  10067. DataTable.ext = $.extend( true, {}, DataTable.models.ext );
  10068. $.extend( DataTable.ext.oStdClasses, {
  10069. "sTable": "dataTable",
  10070. /* Two buttons buttons */
  10071. "sPagePrevEnabled": "paginate_enabled_previous",
  10072. "sPagePrevDisabled": "paginate_disabled_previous",
  10073. "sPageNextEnabled": "paginate_enabled_next",
  10074. "sPageNextDisabled": "paginate_disabled_next",
  10075. "sPageJUINext": "",
  10076. "sPageJUIPrev": "",
  10077. /* Full numbers paging buttons */
  10078. "sPageButton": "paginate_button",
  10079. "sPageButtonActive": "paginate_active",
  10080. "sPageButtonStaticDisabled": "paginate_button paginate_button_disabled",
  10081. "sPageFirst": "first",
  10082. "sPagePrevious": "previous",
  10083. "sPageNext": "next",
  10084. "sPageLast": "last",
  10085. /* Striping classes */
  10086. "sStripeOdd": "odd",
  10087. "sStripeEven": "even",
  10088. /* Empty row */
  10089. "sRowEmpty": "dataTables_empty",
  10090. /* Features */
  10091. "sWrapper": "dataTables_wrapper",
  10092. "sFilter": "dataTables_filter",
  10093. "sInfo": "dataTables_info",
  10094. "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
  10095. "sLength": "dataTables_length",
  10096. "sProcessing": "dataTables_processing",
  10097. /* Sorting */
  10098. "sSortAsc": "sorting_asc",
  10099. "sSortDesc": "sorting_desc",
  10100. "sSortable": "sorting", /* Sortable in both directions */
  10101. "sSortableAsc": "sorting_asc_disabled",
  10102. "sSortableDesc": "sorting_desc_disabled",
  10103. "sSortableNone": "sorting_disabled",
  10104. "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
  10105. "sSortJUIAsc": "",
  10106. "sSortJUIDesc": "",
  10107. "sSortJUI": "",
  10108. "sSortJUIAscAllowed": "",
  10109. "sSortJUIDescAllowed": "",
  10110. "sSortJUIWrapper": "",
  10111. "sSortIcon": "",
  10112. /* Scrolling */
  10113. "sScrollWrapper": "dataTables_scroll",
  10114. "sScrollHead": "dataTables_scrollHead",
  10115. "sScrollHeadInner": "dataTables_scrollHeadInner",
  10116. "sScrollBody": "dataTables_scrollBody",
  10117. "sScrollFoot": "dataTables_scrollFoot",
  10118. "sScrollFootInner": "dataTables_scrollFootInner",
  10119. /* Misc */
  10120. "sFooterTH": "",
  10121. "sJUIHeader": "",
  10122. "sJUIFooter": ""
  10123. } );
  10124. $.extend( DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, {
  10125. /* Two buttons buttons */
  10126. "sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left",
  10127. "sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",
  10128. "sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right",
  10129. "sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",
  10130. "sPageJUINext": "ui-icon ui-icon-circle-arrow-e",
  10131. "sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w",
  10132. /* Full numbers paging buttons */
  10133. "sPageButton": "fg-button ui-button ui-state-default",
  10134. "sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled",
  10135. "sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled",
  10136. "sPageFirst": "first ui-corner-tl ui-corner-bl",
  10137. "sPageLast": "last ui-corner-tr ui-corner-br",
  10138. /* Features */
  10139. "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
  10140. "ui-buttonset-multi paging_", /* Note that the type is postfixed */
  10141. /* Sorting */
  10142. "sSortAsc": "ui-state-default",
  10143. "sSortDesc": "ui-state-default",
  10144. "sSortable": "ui-state-default",
  10145. "sSortableAsc": "ui-state-default",
  10146. "sSortableDesc": "ui-state-default",
  10147. "sSortableNone": "ui-state-default",
  10148. "sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n",
  10149. "sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s",
  10150. "sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s",
  10151. "sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n",
  10152. "sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s",
  10153. "sSortJUIWrapper": "DataTables_sort_wrapper",
  10154. "sSortIcon": "DataTables_sort_icon",
  10155. /* Scrolling */
  10156. "sScrollHead": "dataTables_scrollHead ui-state-default",
  10157. "sScrollFoot": "dataTables_scrollFoot ui-state-default",
  10158. /* Misc */
  10159. "sFooterTH": "ui-state-default",
  10160. "sJUIHeader": "fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix",
  10161. "sJUIFooter": "fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"
  10162. } );
  10163. /*
  10164. * Variable: oPagination
  10165. * Purpose:
  10166. * Scope: jQuery.fn.dataTableExt
  10167. */
  10168. $.extend( DataTable.ext.oPagination, {
  10169. /*
  10170. * Variable: two_button
  10171. * Purpose: Standard two button (forward/back) pagination
  10172. * Scope: jQuery.fn.dataTableExt.oPagination
  10173. */
  10174. "two_button": {
  10175. /*
  10176. * Function: oPagination.two_button.fnInit
  10177. * Purpose: Initialise dom elements required for pagination with forward/back buttons only
  10178. * Returns: -
  10179. * Inputs: object:oSettings - dataTables settings object
  10180. * node:nPaging - the DIV which contains this pagination control
  10181. * function:fnCallbackDraw - draw function which must be called on update
  10182. */
  10183. "fnInit": function ( oSettings, nPaging, fnCallbackDraw )
  10184. {
  10185. var oLang = oSettings.oLanguage.oPaginate;
  10186. var oClasses = oSettings.oClasses;
  10187. var fnClickHandler = function ( e ) {
  10188. if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) )
  10189. {
  10190. fnCallbackDraw( oSettings );
  10191. }
  10192. };
  10193. var sAppend = (!oSettings.bJUI) ?
  10194. '<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sPrevious+'</a>'+
  10195. '<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sNext+'</a>'
  10196. :
  10197. '<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUIPrev+'"></span></a>'+
  10198. '<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUINext+'"></span></a>';
  10199. $(nPaging).append( sAppend );
  10200. var els = $('a', nPaging);
  10201. var nPrevious = els[0],
  10202. nNext = els[1];
  10203. oSettings.oApi._fnBindAction( nPrevious, {action: "previous"}, fnClickHandler );
  10204. oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler );
  10205. /* ID the first elements only */
  10206. if ( !oSettings.aanFeatures.p )
  10207. {
  10208. nPaging.id = oSettings.sTableId+'_paginate';
  10209. nPrevious.id = oSettings.sTableId+'_previous';
  10210. nNext.id = oSettings.sTableId+'_next';
  10211. nPrevious.setAttribute('aria-controls', oSettings.sTableId);
  10212. nNext.setAttribute('aria-controls', oSettings.sTableId);
  10213. }
  10214. },
  10215. /*
  10216. * Function: oPagination.two_button.fnUpdate
  10217. * Purpose: Update the two button pagination at the end of the draw
  10218. * Returns: -
  10219. * Inputs: object:oSettings - dataTables settings object
  10220. * function:fnCallbackDraw - draw function to call on page change
  10221. */
  10222. "fnUpdate": function ( oSettings, fnCallbackDraw )
  10223. {
  10224. if ( !oSettings.aanFeatures.p )
  10225. {
  10226. return;
  10227. }
  10228. var oClasses = oSettings.oClasses;
  10229. var an = oSettings.aanFeatures.p;
  10230. /* Loop over each instance of the pager */
  10231. for ( var i=0, iLen=an.length ; i<iLen ; i++ )
  10232. {
  10233. if ( an[i].childNodes.length !== 0 )
  10234. {
  10235. an[i].childNodes[0].className = ( oSettings._iDisplayStart === 0 ) ?
  10236. oClasses.sPagePrevDisabled : oClasses.sPagePrevEnabled;
  10237. an[i].childNodes[1].className = ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) ?
  10238. oClasses.sPageNextDisabled : oClasses.sPageNextEnabled;
  10239. }
  10240. }
  10241. }
  10242. },
  10243. /*
  10244. * Variable: iFullNumbersShowPages
  10245. * Purpose: Change the number of pages which can be seen
  10246. * Scope: jQuery.fn.dataTableExt.oPagination
  10247. */
  10248. "iFullNumbersShowPages": 5,
  10249. /*
  10250. * Variable: full_numbers
  10251. * Purpose: Full numbers pagination
  10252. * Scope: jQuery.fn.dataTableExt.oPagination
  10253. */
  10254. "full_numbers": {
  10255. /*
  10256. * Function: oPagination.full_numbers.fnInit
  10257. * Purpose: Initialise dom elements required for pagination with a list of the pages
  10258. * Returns: -
  10259. * Inputs: object:oSettings - dataTables settings object
  10260. * node:nPaging - the DIV which contains this pagination control
  10261. * function:fnCallbackDraw - draw function which must be called on update
  10262. */
  10263. "fnInit": function ( oSettings, nPaging, fnCallbackDraw )
  10264. {
  10265. var oLang = oSettings.oLanguage.oPaginate;
  10266. var oClasses = oSettings.oClasses;
  10267. var fnClickHandler = function ( e ) {
  10268. if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) )
  10269. {
  10270. fnCallbackDraw( oSettings );
  10271. }
  10272. };
  10273. $(nPaging).append(
  10274. '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageFirst+'">'+oLang.sFirst+'</a>'+
  10275. '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPagePrevious+'">'+oLang.sPrevious+'</a>'+
  10276. '<span></span>'+
  10277. '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageNext+'">'+oLang.sNext+'</a>'+
  10278. '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageLast+'">'+oLang.sLast+'</a>'
  10279. );
  10280. var els = $('a', nPaging);
  10281. var nFirst = els[0],
  10282. nPrev = els[1],
  10283. nNext = els[2],
  10284. nLast = els[3];
  10285. oSettings.oApi._fnBindAction( nFirst, {action: "first"}, fnClickHandler );
  10286. oSettings.oApi._fnBindAction( nPrev, {action: "previous"}, fnClickHandler );
  10287. oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler );
  10288. oSettings.oApi._fnBindAction( nLast, {action: "last"}, fnClickHandler );
  10289. /* ID the first elements only */
  10290. if ( !oSettings.aanFeatures.p )
  10291. {
  10292. nPaging.id = oSettings.sTableId+'_paginate';
  10293. nFirst.id =oSettings.sTableId+'_first';
  10294. nPrev.id =oSettings.sTableId+'_previous';
  10295. nNext.id =oSettings.sTableId+'_next';
  10296. nLast.id =oSettings.sTableId+'_last';
  10297. }
  10298. },
  10299. /*
  10300. * Function: oPagination.full_numbers.fnUpdate
  10301. * Purpose: Update the list of page buttons shows
  10302. * Returns: -
  10303. * Inputs: object:oSettings - dataTables settings object
  10304. * function:fnCallbackDraw - draw function to call on page change
  10305. */
  10306. "fnUpdate": function ( oSettings, fnCallbackDraw )
  10307. {
  10308. if ( !oSettings.aanFeatures.p )
  10309. {
  10310. return;
  10311. }
  10312. var iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages;
  10313. var iPageCountHalf = Math.floor(iPageCount / 2);
  10314. var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
  10315. var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
  10316. var sList = "";
  10317. var iStartButton, iEndButton, i, iLen;
  10318. var oClasses = oSettings.oClasses;
  10319. var anButtons, anStatic, nPaginateList;
  10320. var an = oSettings.aanFeatures.p;
  10321. var fnBind = function (j) {
  10322. oSettings.oApi._fnBindAction( this, {"page": j+iStartButton-1}, function(e) {
  10323. /* Use the information in the element to jump to the required page */
  10324. oSettings.oApi._fnPageChange( oSettings, e.data.page );
  10325. fnCallbackDraw( oSettings );
  10326. e.preventDefault();
  10327. } );
  10328. };
  10329. /* Pages calculation */
  10330. if ( oSettings._iDisplayLength === -1 )
  10331. {
  10332. iStartButton = 1;
  10333. iEndButton = 1;
  10334. iCurrentPage = 1;
  10335. }
  10336. else if (iPages < iPageCount)
  10337. {
  10338. iStartButton = 1;
  10339. iEndButton = iPages;
  10340. }
  10341. else if (iCurrentPage <= iPageCountHalf)
  10342. {
  10343. iStartButton = 1;
  10344. iEndButton = iPageCount;
  10345. }
  10346. else if (iCurrentPage >= (iPages - iPageCountHalf))
  10347. {
  10348. iStartButton = iPages - iPageCount + 1;
  10349. iEndButton = iPages;
  10350. }
  10351. else
  10352. {
  10353. iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
  10354. iEndButton = iStartButton + iPageCount - 1;
  10355. }
  10356. /* Build the dynamic list */
  10357. for ( i=iStartButton ; i<=iEndButton ; i++ )
  10358. {
  10359. sList += (iCurrentPage !== i) ?
  10360. '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+'">'+oSettings.fnFormatNumber(i)+'</a>' :
  10361. '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButtonActive+'">'+oSettings.fnFormatNumber(i)+'</a>';
  10362. }
  10363. /* Loop over each instance of the pager */
  10364. for ( i=0, iLen=an.length ; i<iLen ; i++ )
  10365. {
  10366. if ( an[i].childNodes.length === 0 )
  10367. {
  10368. continue;
  10369. }
  10370. /* Build up the dynamic list forst - html and listeners */
  10371. $('span:eq(0)', an[i])
  10372. .html( sList )
  10373. .children('a').each( fnBind );
  10374. /* Update the premanent botton's classes */
  10375. anButtons = an[i].getElementsByTagName('a');
  10376. anStatic = [
  10377. anButtons[0], anButtons[1],
  10378. anButtons[anButtons.length-2], anButtons[anButtons.length-1]
  10379. ];
  10380. $(anStatic).removeClass( oClasses.sPageButton+" "+oClasses.sPageButtonActive+" "+oClasses.sPageButtonStaticDisabled );
  10381. $([anStatic[0], anStatic[1]]).addClass(
  10382. (iCurrentPage==1) ?
  10383. oClasses.sPageButtonStaticDisabled :
  10384. oClasses.sPageButton
  10385. );
  10386. $([anStatic[2], anStatic[3]]).addClass(
  10387. (iPages===0 || iCurrentPage===iPages || oSettings._iDisplayLength===-1) ?
  10388. oClasses.sPageButtonStaticDisabled :
  10389. oClasses.sPageButton
  10390. );
  10391. }
  10392. }
  10393. }
  10394. } );
  10395. $.extend( DataTable.ext.oSort, {
  10396. /*
  10397. * text sorting
  10398. */
  10399. "string-pre": function ( a )
  10400. {
  10401. if ( typeof a != 'string' ) {
  10402. a = (a !== null && a.toString) ? a.toString() : '';
  10403. }
  10404. return a.toLowerCase();
  10405. },
  10406. "string-asc": function ( x, y )
  10407. {
  10408. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  10409. },
  10410. "string-desc": function ( x, y )
  10411. {
  10412. return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  10413. },
  10414. /*
  10415. * html sorting (ignore html tags)
  10416. */
  10417. "html-pre": function ( a )
  10418. {
  10419. return a.replace( /<.*?>/g, "" ).toLowerCase();
  10420. },
  10421. "html-asc": function ( x, y )
  10422. {
  10423. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  10424. },
  10425. "html-desc": function ( x, y )
  10426. {
  10427. return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  10428. },
  10429. /*
  10430. * date sorting
  10431. */
  10432. "date-pre": function ( a )
  10433. {
  10434. var x = Date.parse( a );
  10435. if ( isNaN(x) || x==="" )
  10436. {
  10437. x = Date.parse( "01/01/1970 00:00:00" );
  10438. }
  10439. return x;
  10440. },
  10441. "date-asc": function ( x, y )
  10442. {
  10443. return x - y;
  10444. },
  10445. "date-desc": function ( x, y )
  10446. {
  10447. return y - x;
  10448. },
  10449. /*
  10450. * numerical sorting
  10451. */
  10452. "numeric-pre": function ( a )
  10453. {
  10454. return (a=="-" || a==="") ? 0 : a*1;
  10455. },
  10456. "numeric-asc": function ( x, y )
  10457. {
  10458. return x - y;
  10459. },
  10460. "numeric-desc": function ( x, y )
  10461. {
  10462. return y - x;
  10463. }
  10464. } );
  10465. $.extend( DataTable.ext.aTypes, [
  10466. /*
  10467. * Function: -
  10468. * Purpose: Check to see if a string is numeric
  10469. * Returns: string:'numeric' or null
  10470. * Inputs: mixed:sText - string to check
  10471. */
  10472. function ( sData )
  10473. {
  10474. /* Allow zero length strings as a number */
  10475. if ( typeof sData === 'number' )
  10476. {
  10477. return 'numeric';
  10478. }
  10479. else if ( typeof sData !== 'string' )
  10480. {
  10481. return null;
  10482. }
  10483. var sValidFirstChars = "0123456789-";
  10484. var sValidChars = "0123456789.";
  10485. var Char;
  10486. var bDecimal = false;
  10487. /* Check for a valid first char (no period and allow negatives) */
  10488. Char = sData.charAt(0);
  10489. if (sValidFirstChars.indexOf(Char) == -1)
  10490. {
  10491. return null;
  10492. }
  10493. /* Check all the other characters are valid */
  10494. for ( var i=1 ; i<sData.length ; i++ )
  10495. {
  10496. Char = sData.charAt(i);
  10497. if (sValidChars.indexOf(Char) == -1)
  10498. {
  10499. return null;
  10500. }
  10501. /* Only allowed one decimal place... */
  10502. if ( Char == "." )
  10503. {
  10504. if ( bDecimal )
  10505. {
  10506. return null;
  10507. }
  10508. bDecimal = true;
  10509. }
  10510. }
  10511. return 'numeric';
  10512. },
  10513. /*
  10514. * Function: -
  10515. * Purpose: Check to see if a string is actually a formatted date
  10516. * Returns: string:'date' or null
  10517. * Inputs: string:sText - string to check
  10518. */
  10519. function ( sData )
  10520. {
  10521. var iParse = Date.parse(sData);
  10522. if ( (iParse !== null && !isNaN(iParse)) || (typeof sData === 'string' && sData.length === 0) )
  10523. {
  10524. return 'date';
  10525. }
  10526. return null;
  10527. },
  10528. /*
  10529. * Function: -
  10530. * Purpose: Check to see if a string should be treated as an HTML string
  10531. * Returns: string:'html' or null
  10532. * Inputs: string:sText - string to check
  10533. */
  10534. function ( sData )
  10535. {
  10536. if ( typeof sData === 'string' && sData.indexOf('<') != -1 && sData.indexOf('>') != -1 )
  10537. {
  10538. return 'html';
  10539. }
  10540. return null;
  10541. }
  10542. ] );
  10543. // jQuery aliases
  10544. $.fn.DataTable = DataTable;
  10545. $.fn.dataTable = DataTable;
  10546. $.fn.dataTableSettings = DataTable.settings;
  10547. $.fn.dataTableExt = DataTable.ext;
  10548. // Information about events fired by DataTables - for documentation.
  10549. /**
  10550. * Draw event, fired whenever the table is redrawn on the page, at the same point as
  10551. * fnDrawCallback. This may be useful for binding events or performing calculations when
  10552. * the table is altered at all.
  10553. * @name DataTable#draw
  10554. * @event
  10555. * @param {event} e jQuery event object
  10556. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10557. */
  10558. /**
  10559. * Filter event, fired when the filtering applied to the table (using the build in global
  10560. * global filter, or column filters) is altered.
  10561. * @name DataTable#filter
  10562. * @event
  10563. * @param {event} e jQuery event object
  10564. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10565. */
  10566. /**
  10567. * Page change event, fired when the paging of the table is altered.
  10568. * @name DataTable#page
  10569. * @event
  10570. * @param {event} e jQuery event object
  10571. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10572. */
  10573. /**
  10574. * Sort event, fired when the sorting applied to the table is altered.
  10575. * @name DataTable#sort
  10576. * @event
  10577. * @param {event} e jQuery event object
  10578. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10579. */
  10580. /**
  10581. * DataTables initialisation complete event, fired when the table is fully drawn,
  10582. * including Ajax data loaded, if Ajax data is required.
  10583. * @name DataTable#init
  10584. * @event
  10585. * @param {event} e jQuery event object
  10586. * @param {object} oSettings DataTables settings object
  10587. * @param {object} json The JSON object request from the server - only
  10588. * present if client-side Ajax sourced data is used</li></ol>
  10589. */
  10590. /**
  10591. * State save event, fired when the table has changed state a new state save is required.
  10592. * This method allows modification of the state saving object prior to actually doing the
  10593. * save, including addition or other state properties (for plug-ins) or modification
  10594. * of a DataTables core property.
  10595. * @name DataTable#stateSaveParams
  10596. * @event
  10597. * @param {event} e jQuery event object
  10598. * @param {object} oSettings DataTables settings object
  10599. * @param {object} json The state information to be saved
  10600. */
  10601. /**
  10602. * State load event, fired when the table is loading state from the stored data, but
  10603. * prior to the settings object being modified by the saved state - allowing modification
  10604. * of the saved state is required or loading of state for a plug-in.
  10605. * @name DataTable#stateLoadParams
  10606. * @event
  10607. * @param {event} e jQuery event object
  10608. * @param {object} oSettings DataTables settings object
  10609. * @param {object} json The saved state information
  10610. */
  10611. /**
  10612. * State loaded event, fired when state has been loaded from stored data and the settings
  10613. * object has been modified by the loaded data.
  10614. * @name DataTable#stateLoaded
  10615. * @event
  10616. * @param {event} e jQuery event object
  10617. * @param {object} oSettings DataTables settings object
  10618. * @param {object} json The saved state information
  10619. */
  10620. /**
  10621. * Processing event, fired when DataTables is doing some kind of processing (be it,
  10622. * sort, filter or anything else). Can be used to indicate to the end user that
  10623. * there is something happening, or that something has finished.
  10624. * @name DataTable#processing
  10625. * @event
  10626. * @param {event} e jQuery event object
  10627. * @param {object} oSettings DataTables settings object
  10628. * @param {boolean} bShow Flag for if DataTables is doing processing or not
  10629. */
  10630. /**
  10631. * Ajax (XHR) event, fired whenever an Ajax request is completed from a request to
  10632. * made to the server for new data (note that this trigger is called in fnServerData,
  10633. * if you override fnServerData and which to use this event, you need to trigger it in
  10634. * you success function).
  10635. * @name DataTable#xhr
  10636. * @event
  10637. * @param {event} e jQuery event object
  10638. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10639. */
  10640. /**
  10641. * Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing
  10642. * the bDestroy:true parameter in the initialisation object. This can be used to remove
  10643. * bound events, added DOM nodes, etc.
  10644. * @name DataTable#destroy
  10645. * @event
  10646. * @param {event} e jQuery event object
  10647. * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  10648. */
  10649. }(jQuery, window, document, undefined));