011-datatables.js 525 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694
  1. /*
  2. * This combined file was created by the DataTables downloader builder:
  3. * https://datatables.net/download
  4. *
  5. * To rebuild or modify this file with the latest versions of the included
  6. * software please visit:
  7. * https://datatables.net/download/#bs5/dt-1.12.0/r-2.3.0/sl-1.4.0
  8. *
  9. * Included libraries:
  10. * DataTables 1.12.0, Responsive 2.3.0, Select 1.4.0
  11. */
  12. /*! DataTables 1.12.0
  13. * ©2008-2022 SpryMedia Ltd - datatables.net/license
  14. */
  15. /**
  16. * @summary DataTables
  17. * @description Paginate, search and order HTML tables
  18. * @version 1.12.0
  19. * @author SpryMedia Ltd
  20. * @contact www.datatables.net
  21. * @copyright SpryMedia Ltd.
  22. *
  23. * This source file is free software, available under the following license:
  24. * MIT license - http://datatables.net/license
  25. *
  26. * This source file is distributed in the hope that it will be useful, but
  27. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  28. * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  29. *
  30. * For details please refer to: http://www.datatables.net
  31. */
  32. /*jslint evil: true, undef: true, browser: true */
  33. /*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
  34. (function( factory ) {
  35. "use strict";
  36. if ( typeof define === 'function' && define.amd ) {
  37. // AMD
  38. define( ['jquery'], function ( $ ) {
  39. return factory( $, window, document );
  40. } );
  41. }
  42. else if ( typeof exports === 'object' ) {
  43. // CommonJS
  44. module.exports = function (root, $) {
  45. if ( ! root ) {
  46. // CommonJS environments without a window global must pass a
  47. // root. This will give an error otherwise
  48. root = window;
  49. }
  50. if ( ! $ ) {
  51. $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
  52. require('jquery') :
  53. require('jquery')( root );
  54. }
  55. return factory( $, root, root.document );
  56. };
  57. }
  58. else {
  59. // Browser
  60. window.DataTable = factory( jQuery, window, document );
  61. }
  62. }
  63. (function( $, window, document, undefined ) {
  64. "use strict";
  65. var DataTable = function ( selector, options )
  66. {
  67. // When creating with `new`, create a new DataTable, returning the API instance
  68. if (this instanceof DataTable) {
  69. return $(selector).DataTable(options);
  70. }
  71. else {
  72. // Argument switching
  73. options = selector;
  74. }
  75. /**
  76. * Perform a jQuery selector action on the table's TR elements (from the tbody) and
  77. * return the resulting jQuery object.
  78. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  79. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  80. * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
  81. * criterion ("applied") or all TR elements (i.e. no filter).
  82. * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
  83. * Can be either 'current', whereby the current sorting of the table is used, or
  84. * 'original' whereby the original order the data was read into the table is used.
  85. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  86. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  87. * 'current' and filter is 'applied', regardless of what they might be given as.
  88. * @returns {object} jQuery object, filtered by the given selector.
  89. * @dtopt API
  90. * @deprecated Since v1.10
  91. *
  92. * @example
  93. * $(document).ready(function() {
  94. * var oTable = $('#example').dataTable();
  95. *
  96. * // Highlight every second row
  97. * oTable.$('tr:odd').css('backgroundColor', 'blue');
  98. * } );
  99. *
  100. * @example
  101. * $(document).ready(function() {
  102. * var oTable = $('#example').dataTable();
  103. *
  104. * // Filter to rows with 'Webkit' in them, add a background colour and then
  105. * // remove the filter, thus highlighting the 'Webkit' rows only.
  106. * oTable.fnFilter('Webkit');
  107. * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
  108. * oTable.fnFilter('');
  109. * } );
  110. */
  111. this.$ = function ( sSelector, oOpts )
  112. {
  113. return this.api(true).$( sSelector, oOpts );
  114. };
  115. /**
  116. * Almost identical to $ in operation, but in this case returns the data for the matched
  117. * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
  118. * rather than any descendants, so the data can be obtained for the row/cell. If matching
  119. * rows are found, the data returned is the original data array/object that was used to
  120. * create the row (or a generated array if from a DOM source).
  121. *
  122. * This method is often useful in-combination with $ where both functions are given the
  123. * same parameters and the array indexes will match identically.
  124. * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  125. * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  126. * @param {string} [oOpts.filter=none] Select elements that meet the current filter
  127. * criterion ("applied") or all elements (i.e. no filter).
  128. * @param {string} [oOpts.order=current] Order of the data in the processed array.
  129. * Can be either 'current', whereby the current sorting of the table is used, or
  130. * 'original' whereby the original order the data was read into the table is used.
  131. * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  132. * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  133. * 'current' and filter is 'applied', regardless of what they might be given as.
  134. * @returns {array} Data for the matched elements. If any elements, as a result of the
  135. * selector, were not TR, TD or TH elements in the DataTable, they will have a null
  136. * entry in the array.
  137. * @dtopt API
  138. * @deprecated Since v1.10
  139. *
  140. * @example
  141. * $(document).ready(function() {
  142. * var oTable = $('#example').dataTable();
  143. *
  144. * // Get the data from the first row in the table
  145. * var data = oTable._('tr:first');
  146. *
  147. * // Do something useful with the data
  148. * alert( "First cell is: "+data[0] );
  149. * } );
  150. *
  151. * @example
  152. * $(document).ready(function() {
  153. * var oTable = $('#example').dataTable();
  154. *
  155. * // Filter to 'Webkit' and get all data for
  156. * oTable.fnFilter('Webkit');
  157. * var data = oTable._('tr', {"search": "applied"});
  158. *
  159. * // Do something with the data
  160. * alert( data.length+" rows matched the search" );
  161. * } );
  162. */
  163. this._ = function ( sSelector, oOpts )
  164. {
  165. return this.api(true).rows( sSelector, oOpts ).data();
  166. };
  167. /**
  168. * Create a DataTables Api instance, with the currently selected tables for
  169. * the Api's context.
  170. * @param {boolean} [traditional=false] Set the API instance's context to be
  171. * only the table referred to by the `DataTable.ext.iApiIndex` option, as was
  172. * used in the API presented by DataTables 1.9- (i.e. the traditional mode),
  173. * or if all tables captured in the jQuery object should be used.
  174. * @return {DataTables.Api}
  175. */
  176. this.api = function ( traditional )
  177. {
  178. return traditional ?
  179. new _Api(
  180. _fnSettingsFromNode( this[ _ext.iApiIndex ] )
  181. ) :
  182. new _Api( this );
  183. };
  184. /**
  185. * Add a single new row or multiple rows of data to the table. Please note
  186. * that this is suitable for client-side processing only - if you are using
  187. * server-side processing (i.e. "bServerSide": true), then to add data, you
  188. * must add it to the data source, i.e. the server-side, through an Ajax call.
  189. * @param {array|object} data The data to be added to the table. This can be:
  190. * <ul>
  191. * <li>1D array of data - add a single row with the data provided</li>
  192. * <li>2D array of arrays - add multiple rows in a single call</li>
  193. * <li>object - data object when using <i>mData</i></li>
  194. * <li>array of objects - multiple data objects when using <i>mData</i></li>
  195. * </ul>
  196. * @param {bool} [redraw=true] redraw the table or not
  197. * @returns {array} An array of integers, representing the list of indexes in
  198. * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
  199. * the table.
  200. * @dtopt API
  201. * @deprecated Since v1.10
  202. *
  203. * @example
  204. * // Global var for counter
  205. * var giCount = 2;
  206. *
  207. * $(document).ready(function() {
  208. * $('#example').dataTable();
  209. * } );
  210. *
  211. * function fnClickAddRow() {
  212. * $('#example').dataTable().fnAddData( [
  213. * giCount+".1",
  214. * giCount+".2",
  215. * giCount+".3",
  216. * giCount+".4" ]
  217. * );
  218. *
  219. * giCount++;
  220. * }
  221. */
  222. this.fnAddData = function( data, redraw )
  223. {
  224. var api = this.api( true );
  225. /* Check if we want to add multiple rows or not */
  226. var rows = Array.isArray(data) && ( Array.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
  227. api.rows.add( data ) :
  228. api.row.add( data );
  229. if ( redraw === undefined || redraw ) {
  230. api.draw();
  231. }
  232. return rows.flatten().toArray();
  233. };
  234. /**
  235. * This function will make DataTables recalculate the column sizes, based on the data
  236. * contained in the table and the sizes applied to the columns (in the DOM, CSS or
  237. * through the sWidth parameter). This can be useful when the width of the table's
  238. * parent element changes (for example a window resize).
  239. * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
  240. * @dtopt API
  241. * @deprecated Since v1.10
  242. *
  243. * @example
  244. * $(document).ready(function() {
  245. * var oTable = $('#example').dataTable( {
  246. * "sScrollY": "200px",
  247. * "bPaginate": false
  248. * } );
  249. *
  250. * $(window).on('resize', function () {
  251. * oTable.fnAdjustColumnSizing();
  252. * } );
  253. * } );
  254. */
  255. this.fnAdjustColumnSizing = function ( bRedraw )
  256. {
  257. var api = this.api( true ).columns.adjust();
  258. var settings = api.settings()[0];
  259. var scroll = settings.oScroll;
  260. if ( bRedraw === undefined || bRedraw ) {
  261. api.draw( false );
  262. }
  263. else if ( scroll.sX !== "" || scroll.sY !== "" ) {
  264. /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
  265. _fnScrollDraw( settings );
  266. }
  267. };
  268. /**
  269. * Quickly and simply clear a table
  270. * @param {bool} [bRedraw=true] redraw the table or not
  271. * @dtopt API
  272. * @deprecated Since v1.10
  273. *
  274. * @example
  275. * $(document).ready(function() {
  276. * var oTable = $('#example').dataTable();
  277. *
  278. * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
  279. * oTable.fnClearTable();
  280. * } );
  281. */
  282. this.fnClearTable = function( bRedraw )
  283. {
  284. var api = this.api( true ).clear();
  285. if ( bRedraw === undefined || bRedraw ) {
  286. api.draw();
  287. }
  288. };
  289. /**
  290. * The exact opposite of 'opening' a row, this function will close any rows which
  291. * are currently 'open'.
  292. * @param {node} nTr the table row to 'close'
  293. * @returns {int} 0 on success, or 1 if failed (can't find the row)
  294. * @dtopt API
  295. * @deprecated Since v1.10
  296. *
  297. * @example
  298. * $(document).ready(function() {
  299. * var oTable;
  300. *
  301. * // 'open' an information row when a row is clicked on
  302. * $('#example tbody tr').click( function () {
  303. * if ( oTable.fnIsOpen(this) ) {
  304. * oTable.fnClose( this );
  305. * } else {
  306. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  307. * }
  308. * } );
  309. *
  310. * oTable = $('#example').dataTable();
  311. * } );
  312. */
  313. this.fnClose = function( nTr )
  314. {
  315. this.api( true ).row( nTr ).child.hide();
  316. };
  317. /**
  318. * Remove a row for the table
  319. * @param {mixed} target The index of the row from aoData to be deleted, or
  320. * the TR element you want to delete
  321. * @param {function|null} [callBack] Callback function
  322. * @param {bool} [redraw=true] Redraw the table or not
  323. * @returns {array} The row that was deleted
  324. * @dtopt API
  325. * @deprecated Since v1.10
  326. *
  327. * @example
  328. * $(document).ready(function() {
  329. * var oTable = $('#example').dataTable();
  330. *
  331. * // Immediately remove the first row
  332. * oTable.fnDeleteRow( 0 );
  333. * } );
  334. */
  335. this.fnDeleteRow = function( target, callback, redraw )
  336. {
  337. var api = this.api( true );
  338. var rows = api.rows( target );
  339. var settings = rows.settings()[0];
  340. var data = settings.aoData[ rows[0][0] ];
  341. rows.remove();
  342. if ( callback ) {
  343. callback.call( this, settings, data );
  344. }
  345. if ( redraw === undefined || redraw ) {
  346. api.draw();
  347. }
  348. return data;
  349. };
  350. /**
  351. * Restore the table to it's original state in the DOM by removing all of DataTables
  352. * enhancements, alterations to the DOM structure of the table and event listeners.
  353. * @param {boolean} [remove=false] Completely remove the table from the DOM
  354. * @dtopt API
  355. * @deprecated Since v1.10
  356. *
  357. * @example
  358. * $(document).ready(function() {
  359. * // This example is fairly pointless in reality, but shows how fnDestroy can be used
  360. * var oTable = $('#example').dataTable();
  361. * oTable.fnDestroy();
  362. * } );
  363. */
  364. this.fnDestroy = function ( remove )
  365. {
  366. this.api( true ).destroy( remove );
  367. };
  368. /**
  369. * Redraw the table
  370. * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
  371. * @dtopt API
  372. * @deprecated Since v1.10
  373. *
  374. * @example
  375. * $(document).ready(function() {
  376. * var oTable = $('#example').dataTable();
  377. *
  378. * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
  379. * oTable.fnDraw();
  380. * } );
  381. */
  382. this.fnDraw = function( complete )
  383. {
  384. // Note that this isn't an exact match to the old call to _fnDraw - it takes
  385. // into account the new data, but can hold position.
  386. this.api( true ).draw( complete );
  387. };
  388. /**
  389. * Filter the input based on data
  390. * @param {string} sInput String to filter the table on
  391. * @param {int|null} [iColumn] Column to limit filtering to
  392. * @param {bool} [bRegex=false] Treat as regular expression or not
  393. * @param {bool} [bSmart=true] Perform smart filtering or not
  394. * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
  395. * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
  396. * @dtopt API
  397. * @deprecated Since v1.10
  398. *
  399. * @example
  400. * $(document).ready(function() {
  401. * var oTable = $('#example').dataTable();
  402. *
  403. * // Sometime later - filter...
  404. * oTable.fnFilter( 'test string' );
  405. * } );
  406. */
  407. this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
  408. {
  409. var api = this.api( true );
  410. if ( iColumn === null || iColumn === undefined ) {
  411. api.search( sInput, bRegex, bSmart, bCaseInsensitive );
  412. }
  413. else {
  414. api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
  415. }
  416. api.draw();
  417. };
  418. /**
  419. * Get the data for the whole table, an individual row or an individual cell based on the
  420. * provided parameters.
  421. * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
  422. * a TR node then the data source for the whole row will be returned. If given as a
  423. * TD/TH cell node then iCol will be automatically calculated and the data for the
  424. * cell returned. If given as an integer, then this is treated as the aoData internal
  425. * data index for the row (see fnGetPosition) and the data for that row used.
  426. * @param {int} [col] Optional column index that you want the data of.
  427. * @returns {array|object|string} If mRow is undefined, then the data for all rows is
  428. * returned. If mRow is defined, just data for that row, and is iCol is
  429. * defined, only data for the designated cell is returned.
  430. * @dtopt API
  431. * @deprecated Since v1.10
  432. *
  433. * @example
  434. * // Row data
  435. * $(document).ready(function() {
  436. * oTable = $('#example').dataTable();
  437. *
  438. * oTable.$('tr').click( function () {
  439. * var data = oTable.fnGetData( this );
  440. * // ... do something with the array / object of data for the row
  441. * } );
  442. * } );
  443. *
  444. * @example
  445. * // Individual cell data
  446. * $(document).ready(function() {
  447. * oTable = $('#example').dataTable();
  448. *
  449. * oTable.$('td').click( function () {
  450. * var sData = oTable.fnGetData( this );
  451. * alert( 'The cell clicked on had the value of '+sData );
  452. * } );
  453. * } );
  454. */
  455. this.fnGetData = function( src, col )
  456. {
  457. var api = this.api( true );
  458. if ( src !== undefined ) {
  459. var type = src.nodeName ? src.nodeName.toLowerCase() : '';
  460. return col !== undefined || type == 'td' || type == 'th' ?
  461. api.cell( src, col ).data() :
  462. api.row( src ).data() || null;
  463. }
  464. return api.data().toArray();
  465. };
  466. /**
  467. * Get an array of the TR nodes that are used in the table's body. Note that you will
  468. * typically want to use the '$' API method in preference to this as it is more
  469. * flexible.
  470. * @param {int} [iRow] Optional row index for the TR element you want
  471. * @returns {array|node} If iRow is undefined, returns an array of all TR elements
  472. * in the table's body, or iRow is defined, just the TR element requested.
  473. * @dtopt API
  474. * @deprecated Since v1.10
  475. *
  476. * @example
  477. * $(document).ready(function() {
  478. * var oTable = $('#example').dataTable();
  479. *
  480. * // Get the nodes from the table
  481. * var nNodes = oTable.fnGetNodes( );
  482. * } );
  483. */
  484. this.fnGetNodes = function( iRow )
  485. {
  486. var api = this.api( true );
  487. return iRow !== undefined ?
  488. api.row( iRow ).node() :
  489. api.rows().nodes().flatten().toArray();
  490. };
  491. /**
  492. * Get the array indexes of a particular cell from it's DOM element
  493. * and column index including hidden columns
  494. * @param {node} node this can either be a TR, TD or TH in the table's body
  495. * @returns {int} If nNode is given as a TR, then a single index is returned, or
  496. * if given as a cell, an array of [row index, column index (visible),
  497. * column index (all)] is given.
  498. * @dtopt API
  499. * @deprecated Since v1.10
  500. *
  501. * @example
  502. * $(document).ready(function() {
  503. * $('#example tbody td').click( function () {
  504. * // Get the position of the current data from the node
  505. * var aPos = oTable.fnGetPosition( this );
  506. *
  507. * // Get the data array for this row
  508. * var aData = oTable.fnGetData( aPos[0] );
  509. *
  510. * // Update the data array and return the value
  511. * aData[ aPos[1] ] = 'clicked';
  512. * this.innerHTML = 'clicked';
  513. * } );
  514. *
  515. * // Init DataTables
  516. * oTable = $('#example').dataTable();
  517. * } );
  518. */
  519. this.fnGetPosition = function( node )
  520. {
  521. var api = this.api( true );
  522. var nodeName = node.nodeName.toUpperCase();
  523. if ( nodeName == 'TR' ) {
  524. return api.row( node ).index();
  525. }
  526. else if ( nodeName == 'TD' || nodeName == 'TH' ) {
  527. var cell = api.cell( node ).index();
  528. return [
  529. cell.row,
  530. cell.columnVisible,
  531. cell.column
  532. ];
  533. }
  534. return null;
  535. };
  536. /**
  537. * Check to see if a row is 'open' or not.
  538. * @param {node} nTr the table row to check
  539. * @returns {boolean} true if the row is currently open, false otherwise
  540. * @dtopt API
  541. * @deprecated Since v1.10
  542. *
  543. * @example
  544. * $(document).ready(function() {
  545. * var oTable;
  546. *
  547. * // 'open' an information row when a row is clicked on
  548. * $('#example tbody tr').click( function () {
  549. * if ( oTable.fnIsOpen(this) ) {
  550. * oTable.fnClose( this );
  551. * } else {
  552. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  553. * }
  554. * } );
  555. *
  556. * oTable = $('#example').dataTable();
  557. * } );
  558. */
  559. this.fnIsOpen = function( nTr )
  560. {
  561. return this.api( true ).row( nTr ).child.isShown();
  562. };
  563. /**
  564. * This function will place a new row directly after a row which is currently
  565. * on display on the page, with the HTML contents that is passed into the
  566. * function. This can be used, for example, to ask for confirmation that a
  567. * particular record should be deleted.
  568. * @param {node} nTr The table row to 'open'
  569. * @param {string|node|jQuery} mHtml The HTML to put into the row
  570. * @param {string} sClass Class to give the new TD cell
  571. * @returns {node} The row opened. Note that if the table row passed in as the
  572. * first parameter, is not found in the table, this method will silently
  573. * return.
  574. * @dtopt API
  575. * @deprecated Since v1.10
  576. *
  577. * @example
  578. * $(document).ready(function() {
  579. * var oTable;
  580. *
  581. * // 'open' an information row when a row is clicked on
  582. * $('#example tbody tr').click( function () {
  583. * if ( oTable.fnIsOpen(this) ) {
  584. * oTable.fnClose( this );
  585. * } else {
  586. * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  587. * }
  588. * } );
  589. *
  590. * oTable = $('#example').dataTable();
  591. * } );
  592. */
  593. this.fnOpen = function( nTr, mHtml, sClass )
  594. {
  595. return this.api( true )
  596. .row( nTr )
  597. .child( mHtml, sClass )
  598. .show()
  599. .child()[0];
  600. };
  601. /**
  602. * Change the pagination - provides the internal logic for pagination in a simple API
  603. * function. With this function you can have a DataTables table go to the next,
  604. * previous, first or last pages.
  605. * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
  606. * or page number to jump to (integer), note that page 0 is the first page.
  607. * @param {bool} [bRedraw=true] Redraw the table or not
  608. * @dtopt API
  609. * @deprecated Since v1.10
  610. *
  611. * @example
  612. * $(document).ready(function() {
  613. * var oTable = $('#example').dataTable();
  614. * oTable.fnPageChange( 'next' );
  615. * } );
  616. */
  617. this.fnPageChange = function ( mAction, bRedraw )
  618. {
  619. var api = this.api( true ).page( mAction );
  620. if ( bRedraw === undefined || bRedraw ) {
  621. api.draw(false);
  622. }
  623. };
  624. /**
  625. * Show a particular column
  626. * @param {int} iCol The column whose display should be changed
  627. * @param {bool} bShow Show (true) or hide (false) the column
  628. * @param {bool} [bRedraw=true] Redraw the table or not
  629. * @dtopt API
  630. * @deprecated Since v1.10
  631. *
  632. * @example
  633. * $(document).ready(function() {
  634. * var oTable = $('#example').dataTable();
  635. *
  636. * // Hide the second column after initialisation
  637. * oTable.fnSetColumnVis( 1, false );
  638. * } );
  639. */
  640. this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
  641. {
  642. var api = this.api( true ).column( iCol ).visible( bShow );
  643. if ( bRedraw === undefined || bRedraw ) {
  644. api.columns.adjust().draw();
  645. }
  646. };
  647. /**
  648. * Get the settings for a particular table for external manipulation
  649. * @returns {object} DataTables settings object. See
  650. * {@link DataTable.models.oSettings}
  651. * @dtopt API
  652. * @deprecated Since v1.10
  653. *
  654. * @example
  655. * $(document).ready(function() {
  656. * var oTable = $('#example').dataTable();
  657. * var oSettings = oTable.fnSettings();
  658. *
  659. * // Show an example parameter from the settings
  660. * alert( oSettings._iDisplayStart );
  661. * } );
  662. */
  663. this.fnSettings = function()
  664. {
  665. return _fnSettingsFromNode( this[_ext.iApiIndex] );
  666. };
  667. /**
  668. * Sort the table by a particular column
  669. * @param {int} iCol the data index to sort on. Note that this will not match the
  670. * 'display index' if you have hidden data entries
  671. * @dtopt API
  672. * @deprecated Since v1.10
  673. *
  674. * @example
  675. * $(document).ready(function() {
  676. * var oTable = $('#example').dataTable();
  677. *
  678. * // Sort immediately with columns 0 and 1
  679. * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
  680. * } );
  681. */
  682. this.fnSort = function( aaSort )
  683. {
  684. this.api( true ).order( aaSort ).draw();
  685. };
  686. /**
  687. * Attach a sort listener to an element for a given column
  688. * @param {node} nNode the element to attach the sort listener to
  689. * @param {int} iColumn the column that a click on this node will sort on
  690. * @param {function} [fnCallback] callback function when sort is run
  691. * @dtopt API
  692. * @deprecated Since v1.10
  693. *
  694. * @example
  695. * $(document).ready(function() {
  696. * var oTable = $('#example').dataTable();
  697. *
  698. * // Sort on column 1, when 'sorter' is clicked on
  699. * oTable.fnSortListener( document.getElementById('sorter'), 1 );
  700. * } );
  701. */
  702. this.fnSortListener = function( nNode, iColumn, fnCallback )
  703. {
  704. this.api( true ).order.listener( nNode, iColumn, fnCallback );
  705. };
  706. /**
  707. * Update a table cell or row - this method will accept either a single value to
  708. * update the cell with, an array of values with one element for each column or
  709. * an object in the same format as the original data source. The function is
  710. * self-referencing in order to make the multi column updates easier.
  711. * @param {object|array|string} mData Data to update the cell/row with
  712. * @param {node|int} mRow TR element you want to update or the aoData index
  713. * @param {int} [iColumn] The column to update, give as null or undefined to
  714. * update a whole row.
  715. * @param {bool} [bRedraw=true] Redraw the table or not
  716. * @param {bool} [bAction=true] Perform pre-draw actions or not
  717. * @returns {int} 0 on success, 1 on error
  718. * @dtopt API
  719. * @deprecated Since v1.10
  720. *
  721. * @example
  722. * $(document).ready(function() {
  723. * var oTable = $('#example').dataTable();
  724. * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
  725. * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
  726. * } );
  727. */
  728. this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
  729. {
  730. var api = this.api( true );
  731. if ( iColumn === undefined || iColumn === null ) {
  732. api.row( mRow ).data( mData );
  733. }
  734. else {
  735. api.cell( mRow, iColumn ).data( mData );
  736. }
  737. if ( bAction === undefined || bAction ) {
  738. api.columns.adjust();
  739. }
  740. if ( bRedraw === undefined || bRedraw ) {
  741. api.draw();
  742. }
  743. return 0;
  744. };
  745. /**
  746. * Provide a common method for plug-ins to check the version of DataTables being used, in order
  747. * to ensure compatibility.
  748. * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
  749. * formats "X" and "X.Y" are also acceptable.
  750. * @returns {boolean} true if this version of DataTables is greater or equal to the required
  751. * version, or false if this version of DataTales is not suitable
  752. * @method
  753. * @dtopt API
  754. * @deprecated Since v1.10
  755. *
  756. * @example
  757. * $(document).ready(function() {
  758. * var oTable = $('#example').dataTable();
  759. * alert( oTable.fnVersionCheck( '1.9.0' ) );
  760. * } );
  761. */
  762. this.fnVersionCheck = _ext.fnVersionCheck;
  763. var _that = this;
  764. var emptyInit = options === undefined;
  765. var len = this.length;
  766. if ( emptyInit ) {
  767. options = {};
  768. }
  769. this.oApi = this.internal = _ext.internal;
  770. // Extend with old style plug-in API methods
  771. for ( var fn in DataTable.ext.internal ) {
  772. if ( fn ) {
  773. this[fn] = _fnExternApiFunc(fn);
  774. }
  775. }
  776. this.each(function() {
  777. // For each initialisation we want to give it a clean initialisation
  778. // object that can be bashed around
  779. var o = {};
  780. var oInit = len > 1 ? // optimisation for single table case
  781. _fnExtend( o, options, true ) :
  782. options;
  783. /*global oInit,_that,emptyInit*/
  784. var i=0, iLen, j, jLen, k, kLen;
  785. var sId = this.getAttribute( 'id' );
  786. var bInitHandedOff = false;
  787. var defaults = DataTable.defaults;
  788. var $this = $(this);
  789. /* Sanity check */
  790. if ( this.nodeName.toLowerCase() != 'table' )
  791. {
  792. _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
  793. return;
  794. }
  795. /* Backwards compatibility for the defaults */
  796. _fnCompatOpts( defaults );
  797. _fnCompatCols( defaults.column );
  798. /* Convert the camel-case defaults to Hungarian */
  799. _fnCamelToHungarian( defaults, defaults, true );
  800. _fnCamelToHungarian( defaults.column, defaults.column, true );
  801. /* Setting up the initialisation object */
  802. _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ), true );
  803. /* Check to see if we are re-initialising a table */
  804. var allSettings = DataTable.settings;
  805. for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
  806. {
  807. var s = allSettings[i];
  808. /* Base check on table node */
  809. if (
  810. s.nTable == this ||
  811. (s.nTHead && s.nTHead.parentNode == this) ||
  812. (s.nTFoot && s.nTFoot.parentNode == this)
  813. ) {
  814. var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
  815. var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
  816. if ( emptyInit || bRetrieve )
  817. {
  818. return s.oInstance;
  819. }
  820. else if ( bDestroy )
  821. {
  822. s.oInstance.fnDestroy();
  823. break;
  824. }
  825. else
  826. {
  827. _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
  828. return;
  829. }
  830. }
  831. /* If the element we are initialising has the same ID as a table which was previously
  832. * initialised, but the table nodes don't match (from before) then we destroy the old
  833. * instance by simply deleting it. This is under the assumption that the table has been
  834. * destroyed by other methods. Anyone using non-id selectors will need to do this manually
  835. */
  836. if ( s.sTableId == this.id )
  837. {
  838. allSettings.splice( i, 1 );
  839. break;
  840. }
  841. }
  842. /* Ensure the table has an ID - required for accessibility */
  843. if ( sId === null || sId === "" )
  844. {
  845. sId = "DataTables_Table_"+(DataTable.ext._unique++);
  846. this.id = sId;
  847. }
  848. /* Create the settings object for this table and set some of the default parameters */
  849. var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
  850. "sDestroyWidth": $this[0].style.width,
  851. "sInstance": sId,
  852. "sTableId": sId
  853. } );
  854. oSettings.nTable = this;
  855. oSettings.oApi = _that.internal;
  856. oSettings.oInit = oInit;
  857. allSettings.push( oSettings );
  858. // Need to add the instance after the instance after the settings object has been added
  859. // to the settings array, so we can self reference the table instance if more than one
  860. oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
  861. // Backwards compatibility, before we apply all the defaults
  862. _fnCompatOpts( oInit );
  863. _fnLanguageCompat( oInit.oLanguage );
  864. // If the length menu is given, but the init display length is not, use the length menu
  865. if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
  866. {
  867. oInit.iDisplayLength = Array.isArray( oInit.aLengthMenu[0] ) ?
  868. oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
  869. }
  870. // Apply the defaults and init options to make a single init object will all
  871. // options defined from defaults and instance options.
  872. oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
  873. // Map the initialisation options onto the settings object
  874. _fnMap( oSettings.oFeatures, oInit, [
  875. "bPaginate",
  876. "bLengthChange",
  877. "bFilter",
  878. "bSort",
  879. "bSortMulti",
  880. "bInfo",
  881. "bProcessing",
  882. "bAutoWidth",
  883. "bSortClasses",
  884. "bServerSide",
  885. "bDeferRender"
  886. ] );
  887. _fnMap( oSettings, oInit, [
  888. "asStripeClasses",
  889. "ajax",
  890. "fnServerData",
  891. "fnFormatNumber",
  892. "sServerMethod",
  893. "aaSorting",
  894. "aaSortingFixed",
  895. "aLengthMenu",
  896. "sPaginationType",
  897. "sAjaxSource",
  898. "sAjaxDataProp",
  899. "iStateDuration",
  900. "sDom",
  901. "bSortCellsTop",
  902. "iTabIndex",
  903. "fnStateLoadCallback",
  904. "fnStateSaveCallback",
  905. "renderer",
  906. "searchDelay",
  907. "rowId",
  908. [ "iCookieDuration", "iStateDuration" ], // backwards compat
  909. [ "oSearch", "oPreviousSearch" ],
  910. [ "aoSearchCols", "aoPreSearchCols" ],
  911. [ "iDisplayLength", "_iDisplayLength" ]
  912. ] );
  913. _fnMap( oSettings.oScroll, oInit, [
  914. [ "sScrollX", "sX" ],
  915. [ "sScrollXInner", "sXInner" ],
  916. [ "sScrollY", "sY" ],
  917. [ "bScrollCollapse", "bCollapse" ]
  918. ] );
  919. _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
  920. /* Callback functions which are array driven */
  921. _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' );
  922. _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' );
  923. _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' );
  924. _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' );
  925. _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' );
  926. _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' );
  927. _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' );
  928. _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' );
  929. _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' );
  930. _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' );
  931. _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' );
  932. oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
  933. /* Browser support detection */
  934. _fnBrowserDetect( oSettings );
  935. var oClasses = oSettings.oClasses;
  936. $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
  937. $this.addClass( oClasses.sTable );
  938. if ( oSettings.iInitDisplayStart === undefined )
  939. {
  940. /* Display start point, taking into account the save saving */
  941. oSettings.iInitDisplayStart = oInit.iDisplayStart;
  942. oSettings._iDisplayStart = oInit.iDisplayStart;
  943. }
  944. if ( oInit.iDeferLoading !== null )
  945. {
  946. oSettings.bDeferLoading = true;
  947. var tmp = Array.isArray( oInit.iDeferLoading );
  948. oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
  949. oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
  950. }
  951. /* Language definitions */
  952. var oLanguage = oSettings.oLanguage;
  953. $.extend( true, oLanguage, oInit.oLanguage );
  954. if ( oLanguage.sUrl )
  955. {
  956. /* Get the language definitions from a file - because this Ajax call makes the language
  957. * get async to the remainder of this function we use bInitHandedOff to indicate that
  958. * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
  959. */
  960. $.ajax( {
  961. dataType: 'json',
  962. url: oLanguage.sUrl,
  963. success: function ( json ) {
  964. _fnCamelToHungarian( defaults.oLanguage, json );
  965. _fnLanguageCompat( json );
  966. $.extend( true, oLanguage, json, oSettings.oInit.oLanguage );
  967. _fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
  968. _fnInitialise( oSettings );
  969. },
  970. error: function () {
  971. // Error occurred loading language file, continue on as best we can
  972. _fnInitialise( oSettings );
  973. }
  974. } );
  975. bInitHandedOff = true;
  976. }
  977. else {
  978. _fnCallbackFire( oSettings, null, 'i18n', [oSettings]);
  979. }
  980. /*
  981. * Stripes
  982. */
  983. if ( oInit.asStripeClasses === null )
  984. {
  985. oSettings.asStripeClasses =[
  986. oClasses.sStripeOdd,
  987. oClasses.sStripeEven
  988. ];
  989. }
  990. /* Remove row stripe classes if they are already on the table row */
  991. var stripeClasses = oSettings.asStripeClasses;
  992. var rowOne = $this.children('tbody').find('tr').eq(0);
  993. if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
  994. return rowOne.hasClass(el);
  995. } ) ) !== -1 ) {
  996. $('tbody tr', this).removeClass( stripeClasses.join(' ') );
  997. oSettings.asDestroyStripes = stripeClasses.slice();
  998. }
  999. /*
  1000. * Columns
  1001. * See if we should load columns automatically or use defined ones
  1002. */
  1003. var anThs = [];
  1004. var aoColumnsInit;
  1005. var nThead = this.getElementsByTagName('thead');
  1006. if ( nThead.length !== 0 )
  1007. {
  1008. _fnDetectHeader( oSettings.aoHeader, nThead[0] );
  1009. anThs = _fnGetUniqueThs( oSettings );
  1010. }
  1011. /* If not given a column array, generate one with nulls */
  1012. if ( oInit.aoColumns === null )
  1013. {
  1014. aoColumnsInit = [];
  1015. for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
  1016. {
  1017. aoColumnsInit.push( null );
  1018. }
  1019. }
  1020. else
  1021. {
  1022. aoColumnsInit = oInit.aoColumns;
  1023. }
  1024. /* Add the columns */
  1025. for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
  1026. {
  1027. _fnAddColumn( oSettings, anThs ? anThs[i] : null );
  1028. }
  1029. /* Apply the column definitions */
  1030. _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
  1031. _fnColumnOptions( oSettings, iCol, oDef );
  1032. } );
  1033. /* HTML5 attribute detection - build an mData object automatically if the
  1034. * attributes are found
  1035. */
  1036. if ( rowOne.length ) {
  1037. var a = function ( cell, name ) {
  1038. return cell.getAttribute( 'data-'+name ) !== null ? name : null;
  1039. };
  1040. $( rowOne[0] ).children('th, td').each( function (i, cell) {
  1041. var col = oSettings.aoColumns[i];
  1042. if ( col.mData === i ) {
  1043. var sort = a( cell, 'sort' ) || a( cell, 'order' );
  1044. var filter = a( cell, 'filter' ) || a( cell, 'search' );
  1045. if ( sort !== null || filter !== null ) {
  1046. col.mData = {
  1047. _: i+'.display',
  1048. sort: sort !== null ? i+'.@data-'+sort : undefined,
  1049. type: sort !== null ? i+'.@data-'+sort : undefined,
  1050. filter: filter !== null ? i+'.@data-'+filter : undefined
  1051. };
  1052. _fnColumnOptions( oSettings, i );
  1053. }
  1054. }
  1055. } );
  1056. }
  1057. var features = oSettings.oFeatures;
  1058. var loadedInit = function () {
  1059. /*
  1060. * Sorting
  1061. * @todo For modularisation (1.11) this needs to do into a sort start up handler
  1062. */
  1063. // If aaSorting is not defined, then we use the first indicator in asSorting
  1064. // in case that has been altered, so the default sort reflects that option
  1065. if ( oInit.aaSorting === undefined ) {
  1066. var sorting = oSettings.aaSorting;
  1067. for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
  1068. sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
  1069. }
  1070. }
  1071. /* Do a first pass on the sorting classes (allows any size changes to be taken into
  1072. * account, and also will apply sorting disabled classes if disabled
  1073. */
  1074. _fnSortingClasses( oSettings );
  1075. if ( features.bSort ) {
  1076. _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
  1077. if ( oSettings.bSorted ) {
  1078. var aSort = _fnSortFlatten( oSettings );
  1079. var sortedColumns = {};
  1080. $.each( aSort, function (i, val) {
  1081. sortedColumns[ val.src ] = val.dir;
  1082. } );
  1083. _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
  1084. _fnSortAria( oSettings );
  1085. }
  1086. } );
  1087. }
  1088. _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
  1089. if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
  1090. _fnSortingClasses( oSettings );
  1091. }
  1092. }, 'sc' );
  1093. /*
  1094. * Final init
  1095. * Cache the header, body and footer as required, creating them if needed
  1096. */
  1097. // Work around for Webkit bug 83867 - store the caption-side before removing from doc
  1098. var captions = $this.children('caption').each( function () {
  1099. this._captionSide = $(this).css('caption-side');
  1100. } );
  1101. var thead = $this.children('thead');
  1102. if ( thead.length === 0 ) {
  1103. thead = $('<thead/>').appendTo($this);
  1104. }
  1105. oSettings.nTHead = thead[0];
  1106. var tbody = $this.children('tbody');
  1107. if ( tbody.length === 0 ) {
  1108. tbody = $('<tbody/>').insertAfter(thead);
  1109. }
  1110. oSettings.nTBody = tbody[0];
  1111. var tfoot = $this.children('tfoot');
  1112. if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
  1113. // If we are a scrolling table, and no footer has been given, then we need to create
  1114. // a tfoot element for the caption element to be appended to
  1115. tfoot = $('<tfoot/>').appendTo($this);
  1116. }
  1117. if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
  1118. $this.addClass( oClasses.sNoFooter );
  1119. }
  1120. else if ( tfoot.length > 0 ) {
  1121. oSettings.nTFoot = tfoot[0];
  1122. _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
  1123. }
  1124. /* Check if there is data passing into the constructor */
  1125. if ( oInit.aaData ) {
  1126. for ( i=0 ; i<oInit.aaData.length ; i++ ) {
  1127. _fnAddData( oSettings, oInit.aaData[ i ] );
  1128. }
  1129. }
  1130. else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
  1131. /* Grab the data from the page - only do this when deferred loading or no Ajax
  1132. * source since there is no point in reading the DOM data if we are then going
  1133. * to replace it with Ajax data
  1134. */
  1135. _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
  1136. }
  1137. /* Copy the data index array */
  1138. oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  1139. /* Initialisation complete - table can be drawn */
  1140. oSettings.bInitialised = true;
  1141. /* Check if we need to initialise the table (it might not have been handed off to the
  1142. * language processor)
  1143. */
  1144. if ( bInitHandedOff === false ) {
  1145. _fnInitialise( oSettings );
  1146. }
  1147. };
  1148. /* Must be done after everything which can be overridden by the state saving! */
  1149. _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
  1150. if ( oInit.bStateSave )
  1151. {
  1152. features.bStateSave = true;
  1153. _fnLoadState( oSettings, oInit, loadedInit );
  1154. }
  1155. else {
  1156. loadedInit();
  1157. }
  1158. } );
  1159. _that = null;
  1160. return this;
  1161. };
  1162. /*
  1163. * It is useful to have variables which are scoped locally so only the
  1164. * DataTables functions can access them and they don't leak into global space.
  1165. * At the same time these functions are often useful over multiple files in the
  1166. * core and API, so we list, or at least document, all variables which are used
  1167. * by DataTables as private variables here. This also ensures that there is no
  1168. * clashing of variable names and that they can easily referenced for reuse.
  1169. */
  1170. // Defined else where
  1171. // _selector_run
  1172. // _selector_opts
  1173. // _selector_first
  1174. // _selector_row_indexes
  1175. var _ext; // DataTable.ext
  1176. var _Api; // DataTable.Api
  1177. var _api_register; // DataTable.Api.register
  1178. var _api_registerPlural; // DataTable.Api.registerPlural
  1179. var _re_dic = {};
  1180. var _re_new_lines = /[\r\n\u2028]/g;
  1181. var _re_html = /<.*?>/g;
  1182. // This is not strict ISO8601 - Date.parse() is quite lax, although
  1183. // implementations differ between browsers.
  1184. var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
  1185. // Escape regular expression special characters
  1186. var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
  1187. // http://en.wikipedia.org/wiki/Foreign_exchange_market
  1188. // - \u20BD - Russian ruble.
  1189. // - \u20a9 - South Korean Won
  1190. // - \u20BA - Turkish Lira
  1191. // - \u20B9 - Indian Rupee
  1192. // - R - Brazil (R$) and South Africa
  1193. // - fr - Swiss Franc
  1194. // - kr - Swedish krona, Norwegian krone and Danish krone
  1195. // - \u2009 is thin space and \u202F is narrow no-break space, both used in many
  1196. // - Ƀ - Bitcoin
  1197. // - Ξ - Ethereum
  1198. // standards as thousands separators.
  1199. var _re_formatted_numeric = /['\u00A0,$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi;
  1200. var _empty = function ( d ) {
  1201. return !d || d === true || d === '-' ? true : false;
  1202. };
  1203. var _intVal = function ( s ) {
  1204. var integer = parseInt( s, 10 );
  1205. return !isNaN(integer) && isFinite(s) ? integer : null;
  1206. };
  1207. // Convert from a formatted number with characters other than `.` as the
  1208. // decimal place, to a Javascript number
  1209. var _numToDecimal = function ( num, decimalPoint ) {
  1210. // Cache created regular expressions for speed as this function is called often
  1211. if ( ! _re_dic[ decimalPoint ] ) {
  1212. _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
  1213. }
  1214. return typeof num === 'string' && decimalPoint !== '.' ?
  1215. num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
  1216. num;
  1217. };
  1218. var _isNumber = function ( d, decimalPoint, formatted ) {
  1219. var strType = typeof d === 'string';
  1220. // If empty return immediately so there must be a number if it is a
  1221. // formatted string (this stops the string "k", or "kr", etc being detected
  1222. // as a formatted number for currency
  1223. if ( _empty( d ) ) {
  1224. return true;
  1225. }
  1226. if ( decimalPoint && strType ) {
  1227. d = _numToDecimal( d, decimalPoint );
  1228. }
  1229. if ( formatted && strType ) {
  1230. d = d.replace( _re_formatted_numeric, '' );
  1231. }
  1232. return !isNaN( parseFloat(d) ) && isFinite( d );
  1233. };
  1234. // A string without HTML in it can be considered to be HTML still
  1235. var _isHtml = function ( d ) {
  1236. return _empty( d ) || typeof d === 'string';
  1237. };
  1238. var _htmlNumeric = function ( d, decimalPoint, formatted ) {
  1239. if ( _empty( d ) ) {
  1240. return true;
  1241. }
  1242. var html = _isHtml( d );
  1243. return ! html ?
  1244. null :
  1245. _isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
  1246. true :
  1247. null;
  1248. };
  1249. var _pluck = function ( a, prop, prop2 ) {
  1250. var out = [];
  1251. var i=0, ien=a.length;
  1252. // Could have the test in the loop for slightly smaller code, but speed
  1253. // is essential here
  1254. if ( prop2 !== undefined ) {
  1255. for ( ; i<ien ; i++ ) {
  1256. if ( a[i] && a[i][ prop ] ) {
  1257. out.push( a[i][ prop ][ prop2 ] );
  1258. }
  1259. }
  1260. }
  1261. else {
  1262. for ( ; i<ien ; i++ ) {
  1263. if ( a[i] ) {
  1264. out.push( a[i][ prop ] );
  1265. }
  1266. }
  1267. }
  1268. return out;
  1269. };
  1270. // Basically the same as _pluck, but rather than looping over `a` we use `order`
  1271. // as the indexes to pick from `a`
  1272. var _pluck_order = function ( a, order, prop, prop2 )
  1273. {
  1274. var out = [];
  1275. var i=0, ien=order.length;
  1276. // Could have the test in the loop for slightly smaller code, but speed
  1277. // is essential here
  1278. if ( prop2 !== undefined ) {
  1279. for ( ; i<ien ; i++ ) {
  1280. if ( a[ order[i] ][ prop ] ) {
  1281. out.push( a[ order[i] ][ prop ][ prop2 ] );
  1282. }
  1283. }
  1284. }
  1285. else {
  1286. for ( ; i<ien ; i++ ) {
  1287. out.push( a[ order[i] ][ prop ] );
  1288. }
  1289. }
  1290. return out;
  1291. };
  1292. var _range = function ( len, start )
  1293. {
  1294. var out = [];
  1295. var end;
  1296. if ( start === undefined ) {
  1297. start = 0;
  1298. end = len;
  1299. }
  1300. else {
  1301. end = start;
  1302. start = len;
  1303. }
  1304. for ( var i=start ; i<end ; i++ ) {
  1305. out.push( i );
  1306. }
  1307. return out;
  1308. };
  1309. var _removeEmpty = function ( a )
  1310. {
  1311. var out = [];
  1312. for ( var i=0, ien=a.length ; i<ien ; i++ ) {
  1313. if ( a[i] ) { // careful - will remove all falsy values!
  1314. out.push( a[i] );
  1315. }
  1316. }
  1317. return out;
  1318. };
  1319. var _stripHtml = function ( d ) {
  1320. return d.replace( _re_html, '' );
  1321. };
  1322. /**
  1323. * Determine if all values in the array are unique. This means we can short
  1324. * cut the _unique method at the cost of a single loop. A sorted array is used
  1325. * to easily check the values.
  1326. *
  1327. * @param {array} src Source array
  1328. * @return {boolean} true if all unique, false otherwise
  1329. * @ignore
  1330. */
  1331. var _areAllUnique = function ( src ) {
  1332. if ( src.length < 2 ) {
  1333. return true;
  1334. }
  1335. var sorted = src.slice().sort();
  1336. var last = sorted[0];
  1337. for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
  1338. if ( sorted[i] === last ) {
  1339. return false;
  1340. }
  1341. last = sorted[i];
  1342. }
  1343. return true;
  1344. };
  1345. /**
  1346. * Find the unique elements in a source array.
  1347. *
  1348. * @param {array} src Source array
  1349. * @return {array} Array of unique items
  1350. * @ignore
  1351. */
  1352. var _unique = function ( src )
  1353. {
  1354. if ( _areAllUnique( src ) ) {
  1355. return src.slice();
  1356. }
  1357. // A faster unique method is to use object keys to identify used values,
  1358. // but this doesn't work with arrays or objects, which we must also
  1359. // consider. See jsperf.com/compare-array-unique-versions/4 for more
  1360. // information.
  1361. var
  1362. out = [],
  1363. val,
  1364. i, ien=src.length,
  1365. j, k=0;
  1366. again: for ( i=0 ; i<ien ; i++ ) {
  1367. val = src[i];
  1368. for ( j=0 ; j<k ; j++ ) {
  1369. if ( out[j] === val ) {
  1370. continue again;
  1371. }
  1372. }
  1373. out.push( val );
  1374. k++;
  1375. }
  1376. return out;
  1377. };
  1378. // Surprisingly this is faster than [].concat.apply
  1379. // https://jsperf.com/flatten-an-array-loop-vs-reduce/2
  1380. var _flatten = function (out, val) {
  1381. if (Array.isArray(val)) {
  1382. for (var i=0 ; i<val.length ; i++) {
  1383. _flatten(out, val[i]);
  1384. }
  1385. }
  1386. else {
  1387. out.push(val);
  1388. }
  1389. return out;
  1390. }
  1391. var _includes = function (search, start) {
  1392. if (start === undefined) {
  1393. start = 0;
  1394. }
  1395. return this.indexOf(search, start) !== -1;
  1396. };
  1397. // Array.isArray polyfill.
  1398. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
  1399. if (! Array.isArray) {
  1400. Array.isArray = function(arg) {
  1401. return Object.prototype.toString.call(arg) === '[object Array]';
  1402. };
  1403. }
  1404. if (! Array.prototype.includes) {
  1405. Array.prototype.includes = _includes;
  1406. }
  1407. // .trim() polyfill
  1408. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
  1409. if (!String.prototype.trim) {
  1410. String.prototype.trim = function () {
  1411. return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  1412. };
  1413. }
  1414. if (! String.prototype.includes) {
  1415. String.prototype.includes = _includes;
  1416. }
  1417. /**
  1418. * DataTables utility methods
  1419. *
  1420. * This namespace provides helper methods that DataTables uses internally to
  1421. * create a DataTable, but which are not exclusively used only for DataTables.
  1422. * These methods can be used by extension authors to save the duplication of
  1423. * code.
  1424. *
  1425. * @namespace
  1426. */
  1427. DataTable.util = {
  1428. /**
  1429. * Throttle the calls to a function. Arguments and context are maintained
  1430. * for the throttled function.
  1431. *
  1432. * @param {function} fn Function to be called
  1433. * @param {integer} freq Call frequency in mS
  1434. * @return {function} Wrapped function
  1435. */
  1436. throttle: function ( fn, freq ) {
  1437. var
  1438. frequency = freq !== undefined ? freq : 200,
  1439. last,
  1440. timer;
  1441. return function () {
  1442. var
  1443. that = this,
  1444. now = +new Date(),
  1445. args = arguments;
  1446. if ( last && now < last + frequency ) {
  1447. clearTimeout( timer );
  1448. timer = setTimeout( function () {
  1449. last = undefined;
  1450. fn.apply( that, args );
  1451. }, frequency );
  1452. }
  1453. else {
  1454. last = now;
  1455. fn.apply( that, args );
  1456. }
  1457. };
  1458. },
  1459. /**
  1460. * Escape a string such that it can be used in a regular expression
  1461. *
  1462. * @param {string} val string to escape
  1463. * @returns {string} escaped string
  1464. */
  1465. escapeRegex: function ( val ) {
  1466. return val.replace( _re_escape_regex, '\\$1' );
  1467. },
  1468. /**
  1469. * Create a function that will write to a nested object or array
  1470. * @param {*} source JSON notation string
  1471. * @returns Write function
  1472. */
  1473. set: function ( source ) {
  1474. if ( $.isPlainObject( source ) ) {
  1475. /* Unlike get, only the underscore (global) option is used for for
  1476. * setting data since we don't know the type here. This is why an object
  1477. * option is not documented for `mData` (which is read/write), but it is
  1478. * for `mRender` which is read only.
  1479. */
  1480. return DataTable.util.set( source._ );
  1481. }
  1482. else if ( source === null ) {
  1483. // Nothing to do when the data source is null
  1484. return function () {};
  1485. }
  1486. else if ( typeof source === 'function' ) {
  1487. return function (data, val, meta) {
  1488. source( data, 'set', val, meta );
  1489. };
  1490. }
  1491. else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
  1492. source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
  1493. {
  1494. // Like the get, we need to get data from a nested object
  1495. var setData = function (data, val, src) {
  1496. var a = _fnSplitObjNotation( src ), b;
  1497. var aLast = a[a.length-1];
  1498. var arrayNotation, funcNotation, o, innerSrc;
  1499. for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) {
  1500. // Protect against prototype pollution
  1501. if (a[i] === '__proto__' || a[i] === 'constructor') {
  1502. throw new Error('Cannot set prototype values');
  1503. }
  1504. // Check if we are dealing with an array notation request
  1505. arrayNotation = a[i].match(__reArray);
  1506. funcNotation = a[i].match(__reFn);
  1507. if ( arrayNotation ) {
  1508. a[i] = a[i].replace(__reArray, '');
  1509. data[ a[i] ] = [];
  1510. // Get the remainder of the nested object to set so we can recurse
  1511. b = a.slice();
  1512. b.splice( 0, i+1 );
  1513. innerSrc = b.join('.');
  1514. // Traverse each entry in the array setting the properties requested
  1515. if ( Array.isArray( val ) ) {
  1516. for ( var j=0, jLen=val.length ; j<jLen ; j++ ) {
  1517. o = {};
  1518. setData( o, val[j], innerSrc );
  1519. data[ a[i] ].push( o );
  1520. }
  1521. }
  1522. else {
  1523. // We've been asked to save data to an array, but it
  1524. // isn't array data to be saved. Best that can be done
  1525. // is to just save the value.
  1526. data[ a[i] ] = val;
  1527. }
  1528. // The inner call to setData has already traversed through the remainder
  1529. // of the source and has set the data, thus we can exit here
  1530. return;
  1531. }
  1532. else if ( funcNotation ) {
  1533. // Function call
  1534. a[i] = a[i].replace(__reFn, '');
  1535. data = data[ a[i] ]( val );
  1536. }
  1537. // If the nested object doesn't currently exist - since we are
  1538. // trying to set the value - create it
  1539. if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) {
  1540. data[ a[i] ] = {};
  1541. }
  1542. data = data[ a[i] ];
  1543. }
  1544. // Last item in the input - i.e, the actual set
  1545. if ( aLast.match(__reFn ) ) {
  1546. // Function call
  1547. data = data[ aLast.replace(__reFn, '') ]( val );
  1548. }
  1549. else {
  1550. // If array notation is used, we just want to strip it and use the property name
  1551. // and assign the value. If it isn't used, then we get the result we want anyway
  1552. data[ aLast.replace(__reArray, '') ] = val;
  1553. }
  1554. };
  1555. return function (data, val) { // meta is also passed in, but not used
  1556. return setData( data, val, source );
  1557. };
  1558. }
  1559. else {
  1560. // Array or flat object mapping
  1561. return function (data, val) { // meta is also passed in, but not used
  1562. data[source] = val;
  1563. };
  1564. }
  1565. },
  1566. /**
  1567. * Create a function that will read nested objects from arrays, based on JSON notation
  1568. * @param {*} source JSON notation string
  1569. * @returns Value read
  1570. */
  1571. get: function ( source ) {
  1572. if ( $.isPlainObject( source ) ) {
  1573. // Build an object of get functions, and wrap them in a single call
  1574. var o = {};
  1575. $.each( source, function (key, val) {
  1576. if ( val ) {
  1577. o[key] = DataTable.util.get( val );
  1578. }
  1579. } );
  1580. return function (data, type, row, meta) {
  1581. var t = o[type] || o._;
  1582. return t !== undefined ?
  1583. t(data, type, row, meta) :
  1584. data;
  1585. };
  1586. }
  1587. else if ( source === null ) {
  1588. // Give an empty string for rendering / sorting etc
  1589. return function (data) { // type, row and meta also passed, but not used
  1590. return data;
  1591. };
  1592. }
  1593. else if ( typeof source === 'function' ) {
  1594. return function (data, type, row, meta) {
  1595. return source( data, type, row, meta );
  1596. };
  1597. }
  1598. else if ( typeof source === 'string' && (source.indexOf('.') !== -1 ||
  1599. source.indexOf('[') !== -1 || source.indexOf('(') !== -1) )
  1600. {
  1601. /* If there is a . in the source string then the data source is in a
  1602. * nested object so we loop over the data for each level to get the next
  1603. * level down. On each loop we test for undefined, and if found immediately
  1604. * return. This allows entire objects to be missing and sDefaultContent to
  1605. * be used if defined, rather than throwing an error
  1606. */
  1607. var fetchData = function (data, type, src) {
  1608. var arrayNotation, funcNotation, out, innerSrc;
  1609. if ( src !== "" ) {
  1610. var a = _fnSplitObjNotation( src );
  1611. for ( var i=0, iLen=a.length ; i<iLen ; i++ ) {
  1612. // Check if we are dealing with special notation
  1613. arrayNotation = a[i].match(__reArray);
  1614. funcNotation = a[i].match(__reFn);
  1615. if ( arrayNotation ) {
  1616. // Array notation
  1617. a[i] = a[i].replace(__reArray, '');
  1618. // Condition allows simply [] to be passed in
  1619. if ( a[i] !== "" ) {
  1620. data = data[ a[i] ];
  1621. }
  1622. out = [];
  1623. // Get the remainder of the nested object to get
  1624. a.splice( 0, i+1 );
  1625. innerSrc = a.join('.');
  1626. // Traverse each entry in the array getting the properties requested
  1627. if ( Array.isArray( data ) ) {
  1628. for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
  1629. out.push( fetchData( data[j], type, innerSrc ) );
  1630. }
  1631. }
  1632. // If a string is given in between the array notation indicators, that
  1633. // is used to join the strings together, otherwise an array is returned
  1634. var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
  1635. data = (join==="") ? out : out.join(join);
  1636. // The inner call to fetchData has already traversed through the remainder
  1637. // of the source requested, so we exit from the loop
  1638. break;
  1639. }
  1640. else if ( funcNotation ) {
  1641. // Function call
  1642. a[i] = a[i].replace(__reFn, '');
  1643. data = data[ a[i] ]();
  1644. continue;
  1645. }
  1646. if ( data === null || data[ a[i] ] === undefined ) {
  1647. return undefined;
  1648. }
  1649. data = data[ a[i] ];
  1650. }
  1651. }
  1652. return data;
  1653. };
  1654. return function (data, type) { // row and meta also passed, but not used
  1655. return fetchData( data, type, source );
  1656. };
  1657. }
  1658. else {
  1659. // Array or flat object mapping
  1660. return function (data, type) { // row and meta also passed, but not used
  1661. return data[source];
  1662. };
  1663. }
  1664. }
  1665. };
  1666. /**
  1667. * Create a mapping object that allows camel case parameters to be looked up
  1668. * for their Hungarian counterparts. The mapping is stored in a private
  1669. * parameter called `_hungarianMap` which can be accessed on the source object.
  1670. * @param {object} o
  1671. * @memberof DataTable#oApi
  1672. */
  1673. function _fnHungarianMap ( o )
  1674. {
  1675. var
  1676. hungarian = 'a aa ai ao as b fn i m o s ',
  1677. match,
  1678. newKey,
  1679. map = {};
  1680. $.each( o, function (key, val) {
  1681. match = key.match(/^([^A-Z]+?)([A-Z])/);
  1682. if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
  1683. {
  1684. newKey = key.replace( match[0], match[2].toLowerCase() );
  1685. map[ newKey ] = key;
  1686. if ( match[1] === 'o' )
  1687. {
  1688. _fnHungarianMap( o[key] );
  1689. }
  1690. }
  1691. } );
  1692. o._hungarianMap = map;
  1693. }
  1694. /**
  1695. * Convert from camel case parameters to Hungarian, based on a Hungarian map
  1696. * created by _fnHungarianMap.
  1697. * @param {object} src The model object which holds all parameters that can be
  1698. * mapped.
  1699. * @param {object} user The object to convert from camel case to Hungarian.
  1700. * @param {boolean} force When set to `true`, properties which already have a
  1701. * Hungarian value in the `user` object will be overwritten. Otherwise they
  1702. * won't be.
  1703. * @memberof DataTable#oApi
  1704. */
  1705. function _fnCamelToHungarian ( src, user, force )
  1706. {
  1707. if ( ! src._hungarianMap ) {
  1708. _fnHungarianMap( src );
  1709. }
  1710. var hungarianKey;
  1711. $.each( user, function (key, val) {
  1712. hungarianKey = src._hungarianMap[ key ];
  1713. if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
  1714. {
  1715. // For objects, we need to buzz down into the object to copy parameters
  1716. if ( hungarianKey.charAt(0) === 'o' )
  1717. {
  1718. // Copy the camelCase options over to the hungarian
  1719. if ( ! user[ hungarianKey ] ) {
  1720. user[ hungarianKey ] = {};
  1721. }
  1722. $.extend( true, user[hungarianKey], user[key] );
  1723. _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
  1724. }
  1725. else {
  1726. user[hungarianKey] = user[ key ];
  1727. }
  1728. }
  1729. } );
  1730. }
  1731. /**
  1732. * Language compatibility - when certain options are given, and others aren't, we
  1733. * need to duplicate the values over, in order to provide backwards compatibility
  1734. * with older language files.
  1735. * @param {object} oSettings dataTables settings object
  1736. * @memberof DataTable#oApi
  1737. */
  1738. function _fnLanguageCompat( lang )
  1739. {
  1740. // Note the use of the Hungarian notation for the parameters in this method as
  1741. // this is called after the mapping of camelCase to Hungarian
  1742. var defaults = DataTable.defaults.oLanguage;
  1743. // Default mapping
  1744. var defaultDecimal = defaults.sDecimal;
  1745. if ( defaultDecimal ) {
  1746. _addNumericSort( defaultDecimal );
  1747. }
  1748. if ( lang ) {
  1749. var zeroRecords = lang.sZeroRecords;
  1750. // Backwards compatibility - if there is no sEmptyTable given, then use the same as
  1751. // sZeroRecords - assuming that is given.
  1752. if ( ! lang.sEmptyTable && zeroRecords &&
  1753. defaults.sEmptyTable === "No data available in table" )
  1754. {
  1755. _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
  1756. }
  1757. // Likewise with loading records
  1758. if ( ! lang.sLoadingRecords && zeroRecords &&
  1759. defaults.sLoadingRecords === "Loading..." )
  1760. {
  1761. _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
  1762. }
  1763. // Old parameter name of the thousands separator mapped onto the new
  1764. if ( lang.sInfoThousands ) {
  1765. lang.sThousands = lang.sInfoThousands;
  1766. }
  1767. var decimal = lang.sDecimal;
  1768. if ( decimal && defaultDecimal !== decimal ) {
  1769. _addNumericSort( decimal );
  1770. }
  1771. }
  1772. }
  1773. /**
  1774. * Map one parameter onto another
  1775. * @param {object} o Object to map
  1776. * @param {*} knew The new parameter name
  1777. * @param {*} old The old parameter name
  1778. */
  1779. var _fnCompatMap = function ( o, knew, old ) {
  1780. if ( o[ knew ] !== undefined ) {
  1781. o[ old ] = o[ knew ];
  1782. }
  1783. };
  1784. /**
  1785. * Provide backwards compatibility for the main DT options. Note that the new
  1786. * options are mapped onto the old parameters, so this is an external interface
  1787. * change only.
  1788. * @param {object} init Object to map
  1789. */
  1790. function _fnCompatOpts ( init )
  1791. {
  1792. _fnCompatMap( init, 'ordering', 'bSort' );
  1793. _fnCompatMap( init, 'orderMulti', 'bSortMulti' );
  1794. _fnCompatMap( init, 'orderClasses', 'bSortClasses' );
  1795. _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
  1796. _fnCompatMap( init, 'order', 'aaSorting' );
  1797. _fnCompatMap( init, 'orderFixed', 'aaSortingFixed' );
  1798. _fnCompatMap( init, 'paging', 'bPaginate' );
  1799. _fnCompatMap( init, 'pagingType', 'sPaginationType' );
  1800. _fnCompatMap( init, 'pageLength', 'iDisplayLength' );
  1801. _fnCompatMap( init, 'searching', 'bFilter' );
  1802. // Boolean initialisation of x-scrolling
  1803. if ( typeof init.sScrollX === 'boolean' ) {
  1804. init.sScrollX = init.sScrollX ? '100%' : '';
  1805. }
  1806. if ( typeof init.scrollX === 'boolean' ) {
  1807. init.scrollX = init.scrollX ? '100%' : '';
  1808. }
  1809. // Column search objects are in an array, so it needs to be converted
  1810. // element by element
  1811. var searchCols = init.aoSearchCols;
  1812. if ( searchCols ) {
  1813. for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
  1814. if ( searchCols[i] ) {
  1815. _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
  1816. }
  1817. }
  1818. }
  1819. }
  1820. /**
  1821. * Provide backwards compatibility for column options. Note that the new options
  1822. * are mapped onto the old parameters, so this is an external interface change
  1823. * only.
  1824. * @param {object} init Object to map
  1825. */
  1826. function _fnCompatCols ( init )
  1827. {
  1828. _fnCompatMap( init, 'orderable', 'bSortable' );
  1829. _fnCompatMap( init, 'orderData', 'aDataSort' );
  1830. _fnCompatMap( init, 'orderSequence', 'asSorting' );
  1831. _fnCompatMap( init, 'orderDataType', 'sortDataType' );
  1832. // orderData can be given as an integer
  1833. var dataSort = init.aDataSort;
  1834. if ( typeof dataSort === 'number' && ! Array.isArray( dataSort ) ) {
  1835. init.aDataSort = [ dataSort ];
  1836. }
  1837. }
  1838. /**
  1839. * Browser feature detection for capabilities, quirks
  1840. * @param {object} settings dataTables settings object
  1841. * @memberof DataTable#oApi
  1842. */
  1843. function _fnBrowserDetect( settings )
  1844. {
  1845. // We don't need to do this every time DataTables is constructed, the values
  1846. // calculated are specific to the browser and OS configuration which we
  1847. // don't expect to change between initialisations
  1848. if ( ! DataTable.__browser ) {
  1849. var browser = {};
  1850. DataTable.__browser = browser;
  1851. // Scrolling feature / quirks detection
  1852. var n = $('<div/>')
  1853. .css( {
  1854. position: 'fixed',
  1855. top: 0,
  1856. left: $(window).scrollLeft()*-1, // allow for scrolling
  1857. height: 1,
  1858. width: 1,
  1859. overflow: 'hidden'
  1860. } )
  1861. .append(
  1862. $('<div/>')
  1863. .css( {
  1864. position: 'absolute',
  1865. top: 1,
  1866. left: 1,
  1867. width: 100,
  1868. overflow: 'scroll'
  1869. } )
  1870. .append(
  1871. $('<div/>')
  1872. .css( {
  1873. width: '100%',
  1874. height: 10
  1875. } )
  1876. )
  1877. )
  1878. .appendTo( 'body' );
  1879. var outer = n.children();
  1880. var inner = outer.children();
  1881. // Numbers below, in order, are:
  1882. // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
  1883. //
  1884. // IE6 XP: 100 100 100 83
  1885. // IE7 Vista: 100 100 100 83
  1886. // IE 8+ Windows: 83 83 100 83
  1887. // Evergreen Windows: 83 83 100 83
  1888. // Evergreen Mac with scrollbars: 85 85 100 85
  1889. // Evergreen Mac without scrollbars: 100 100 100 100
  1890. // Get scrollbar width
  1891. browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
  1892. // IE6/7 will oversize a width 100% element inside a scrolling element, to
  1893. // include the width of the scrollbar, while other browsers ensure the inner
  1894. // element is contained without forcing scrolling
  1895. browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
  1896. // In rtl text layout, some browsers (most, but not all) will place the
  1897. // scrollbar on the left, rather than the right.
  1898. browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
  1899. // IE8- don't provide height and width for getBoundingClientRect
  1900. browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
  1901. n.remove();
  1902. }
  1903. $.extend( settings.oBrowser, DataTable.__browser );
  1904. settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
  1905. }
  1906. /**
  1907. * Array.prototype reduce[Right] method, used for browsers which don't support
  1908. * JS 1.6. Done this way to reduce code size, since we iterate either way
  1909. * @param {object} settings dataTables settings object
  1910. * @memberof DataTable#oApi
  1911. */
  1912. function _fnReduce ( that, fn, init, start, end, inc )
  1913. {
  1914. var
  1915. i = start,
  1916. value,
  1917. isSet = false;
  1918. if ( init !== undefined ) {
  1919. value = init;
  1920. isSet = true;
  1921. }
  1922. while ( i !== end ) {
  1923. if ( ! that.hasOwnProperty(i) ) {
  1924. continue;
  1925. }
  1926. value = isSet ?
  1927. fn( value, that[i], i, that ) :
  1928. that[i];
  1929. isSet = true;
  1930. i += inc;
  1931. }
  1932. return value;
  1933. }
  1934. /**
  1935. * Add a column to the list used for the table with default values
  1936. * @param {object} oSettings dataTables settings object
  1937. * @param {node} nTh The th element for this column
  1938. * @memberof DataTable#oApi
  1939. */
  1940. function _fnAddColumn( oSettings, nTh )
  1941. {
  1942. // Add column to aoColumns array
  1943. var oDefaults = DataTable.defaults.column;
  1944. var iCol = oSettings.aoColumns.length;
  1945. var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
  1946. "nTh": nTh ? nTh : document.createElement('th'),
  1947. "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',
  1948. "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
  1949. "mData": oDefaults.mData ? oDefaults.mData : iCol,
  1950. idx: iCol
  1951. } );
  1952. oSettings.aoColumns.push( oCol );
  1953. // Add search object for column specific search. Note that the `searchCols[ iCol ]`
  1954. // passed into extend can be undefined. This allows the user to give a default
  1955. // with only some of the parameters defined, and also not give a default
  1956. var searchCols = oSettings.aoPreSearchCols;
  1957. searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
  1958. // Use the default column options function to initialise classes etc
  1959. _fnColumnOptions( oSettings, iCol, $(nTh).data() );
  1960. }
  1961. /**
  1962. * Apply options for a column
  1963. * @param {object} oSettings dataTables settings object
  1964. * @param {int} iCol column index to consider
  1965. * @param {object} oOptions object with sType, bVisible and bSearchable etc
  1966. * @memberof DataTable#oApi
  1967. */
  1968. function _fnColumnOptions( oSettings, iCol, oOptions )
  1969. {
  1970. var oCol = oSettings.aoColumns[ iCol ];
  1971. var oClasses = oSettings.oClasses;
  1972. var th = $(oCol.nTh);
  1973. // Try to get width information from the DOM. We can't get it from CSS
  1974. // as we'd need to parse the CSS stylesheet. `width` option can override
  1975. if ( ! oCol.sWidthOrig ) {
  1976. // Width attribute
  1977. oCol.sWidthOrig = th.attr('width') || null;
  1978. // Style attribute
  1979. var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
  1980. if ( t ) {
  1981. oCol.sWidthOrig = t[1];
  1982. }
  1983. }
  1984. /* User specified column options */
  1985. if ( oOptions !== undefined && oOptions !== null )
  1986. {
  1987. // Backwards compatibility
  1988. _fnCompatCols( oOptions );
  1989. // Map camel case parameters to their Hungarian counterparts
  1990. _fnCamelToHungarian( DataTable.defaults.column, oOptions, true );
  1991. /* Backwards compatibility for mDataProp */
  1992. if ( oOptions.mDataProp !== undefined && !oOptions.mData )
  1993. {
  1994. oOptions.mData = oOptions.mDataProp;
  1995. }
  1996. if ( oOptions.sType )
  1997. {
  1998. oCol._sManualType = oOptions.sType;
  1999. }
  2000. // `class` is a reserved word in Javascript, so we need to provide
  2001. // the ability to use a valid name for the camel case input
  2002. if ( oOptions.className && ! oOptions.sClass )
  2003. {
  2004. oOptions.sClass = oOptions.className;
  2005. }
  2006. if ( oOptions.sClass ) {
  2007. th.addClass( oOptions.sClass );
  2008. }
  2009. var origClass = oCol.sClass;
  2010. $.extend( oCol, oOptions );
  2011. _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
  2012. // Merge class from previously defined classes with this one, rather than just
  2013. // overwriting it in the extend above
  2014. if (origClass !== oCol.sClass) {
  2015. oCol.sClass = origClass + ' ' + oCol.sClass;
  2016. }
  2017. /* iDataSort to be applied (backwards compatibility), but aDataSort will take
  2018. * priority if defined
  2019. */
  2020. if ( oOptions.iDataSort !== undefined )
  2021. {
  2022. oCol.aDataSort = [ oOptions.iDataSort ];
  2023. }
  2024. _fnMap( oCol, oOptions, "aDataSort" );
  2025. }
  2026. /* Cache the data get and set functions for speed */
  2027. var mDataSrc = oCol.mData;
  2028. var mData = _fnGetObjectDataFn( mDataSrc );
  2029. var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
  2030. var attrTest = function( src ) {
  2031. return typeof src === 'string' && src.indexOf('@') !== -1;
  2032. };
  2033. oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
  2034. attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
  2035. );
  2036. oCol._setter = null;
  2037. oCol.fnGetData = function (rowData, type, meta) {
  2038. var innerData = mData( rowData, type, undefined, meta );
  2039. return mRender && type ?
  2040. mRender( innerData, type, rowData, meta ) :
  2041. innerData;
  2042. };
  2043. oCol.fnSetData = function ( rowData, val, meta ) {
  2044. return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
  2045. };
  2046. // Indicate if DataTables should read DOM data as an object or array
  2047. // Used in _fnGetRowElements
  2048. if ( typeof mDataSrc !== 'number' ) {
  2049. oSettings._rowReadObject = true;
  2050. }
  2051. /* Feature sorting overrides column specific when off */
  2052. if ( !oSettings.oFeatures.bSort )
  2053. {
  2054. oCol.bSortable = false;
  2055. th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
  2056. }
  2057. /* Check that the class assignment is correct for sorting */
  2058. var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
  2059. var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
  2060. if ( !oCol.bSortable || (!bAsc && !bDesc) )
  2061. {
  2062. oCol.sSortingClass = oClasses.sSortableNone;
  2063. oCol.sSortingClassJUI = "";
  2064. }
  2065. else if ( bAsc && !bDesc )
  2066. {
  2067. oCol.sSortingClass = oClasses.sSortableAsc;
  2068. oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
  2069. }
  2070. else if ( !bAsc && bDesc )
  2071. {
  2072. oCol.sSortingClass = oClasses.sSortableDesc;
  2073. oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
  2074. }
  2075. else
  2076. {
  2077. oCol.sSortingClass = oClasses.sSortable;
  2078. oCol.sSortingClassJUI = oClasses.sSortJUI;
  2079. }
  2080. }
  2081. /**
  2082. * Adjust the table column widths for new data. Note: you would probably want to
  2083. * do a redraw after calling this function!
  2084. * @param {object} settings dataTables settings object
  2085. * @memberof DataTable#oApi
  2086. */
  2087. function _fnAdjustColumnSizing ( settings )
  2088. {
  2089. /* Not interested in doing column width calculation if auto-width is disabled */
  2090. if ( settings.oFeatures.bAutoWidth !== false )
  2091. {
  2092. var columns = settings.aoColumns;
  2093. _fnCalculateColumnWidths( settings );
  2094. for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
  2095. {
  2096. columns[i].nTh.style.width = columns[i].sWidth;
  2097. }
  2098. }
  2099. var scroll = settings.oScroll;
  2100. if ( scroll.sY !== '' || scroll.sX !== '')
  2101. {
  2102. _fnScrollDraw( settings );
  2103. }
  2104. _fnCallbackFire( settings, null, 'column-sizing', [settings] );
  2105. }
  2106. /**
  2107. * Convert the index of a visible column to the index in the data array (take account
  2108. * of hidden columns)
  2109. * @param {object} oSettings dataTables settings object
  2110. * @param {int} iMatch Visible column index to lookup
  2111. * @returns {int} i the data index
  2112. * @memberof DataTable#oApi
  2113. */
  2114. function _fnVisibleToColumnIndex( oSettings, iMatch )
  2115. {
  2116. var aiVis = _fnGetColumns( oSettings, 'bVisible' );
  2117. return typeof aiVis[iMatch] === 'number' ?
  2118. aiVis[iMatch] :
  2119. null;
  2120. }
  2121. /**
  2122. * Convert the index of an index in the data array and convert it to the visible
  2123. * column index (take account of hidden columns)
  2124. * @param {int} iMatch Column index to lookup
  2125. * @param {object} oSettings dataTables settings object
  2126. * @returns {int} i the data index
  2127. * @memberof DataTable#oApi
  2128. */
  2129. function _fnColumnIndexToVisible( oSettings, iMatch )
  2130. {
  2131. var aiVis = _fnGetColumns( oSettings, 'bVisible' );
  2132. var iPos = $.inArray( iMatch, aiVis );
  2133. return iPos !== -1 ? iPos : null;
  2134. }
  2135. /**
  2136. * Get the number of visible columns
  2137. * @param {object} oSettings dataTables settings object
  2138. * @returns {int} i the number of visible columns
  2139. * @memberof DataTable#oApi
  2140. */
  2141. function _fnVisbleColumns( oSettings )
  2142. {
  2143. var vis = 0;
  2144. // No reduce in IE8, use a loop for now
  2145. $.each( oSettings.aoColumns, function ( i, col ) {
  2146. if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
  2147. vis++;
  2148. }
  2149. } );
  2150. return vis;
  2151. }
  2152. /**
  2153. * Get an array of column indexes that match a given property
  2154. * @param {object} oSettings dataTables settings object
  2155. * @param {string} sParam Parameter in aoColumns to look for - typically
  2156. * bVisible or bSearchable
  2157. * @returns {array} Array of indexes with matched properties
  2158. * @memberof DataTable#oApi
  2159. */
  2160. function _fnGetColumns( oSettings, sParam )
  2161. {
  2162. var a = [];
  2163. $.map( oSettings.aoColumns, function(val, i) {
  2164. if ( val[sParam] ) {
  2165. a.push( i );
  2166. }
  2167. } );
  2168. return a;
  2169. }
  2170. /**
  2171. * Calculate the 'type' of a column
  2172. * @param {object} settings dataTables settings object
  2173. * @memberof DataTable#oApi
  2174. */
  2175. function _fnColumnTypes ( settings )
  2176. {
  2177. var columns = settings.aoColumns;
  2178. var data = settings.aoData;
  2179. var types = DataTable.ext.type.detect;
  2180. var i, ien, j, jen, k, ken;
  2181. var col, cell, detectedType, cache;
  2182. // For each column, spin over the
  2183. for ( i=0, ien=columns.length ; i<ien ; i++ ) {
  2184. col = columns[i];
  2185. cache = [];
  2186. if ( ! col.sType && col._sManualType ) {
  2187. col.sType = col._sManualType;
  2188. }
  2189. else if ( ! col.sType ) {
  2190. for ( j=0, jen=types.length ; j<jen ; j++ ) {
  2191. for ( k=0, ken=data.length ; k<ken ; k++ ) {
  2192. // Use a cache array so we only need to get the type data
  2193. // from the formatter once (when using multiple detectors)
  2194. if ( cache[k] === undefined ) {
  2195. cache[k] = _fnGetCellData( settings, k, i, 'type' );
  2196. }
  2197. detectedType = types[j]( cache[k], settings );
  2198. // If null, then this type can't apply to this column, so
  2199. // rather than testing all cells, break out. There is an
  2200. // exception for the last type which is `html`. We need to
  2201. // scan all rows since it is possible to mix string and HTML
  2202. // types
  2203. if ( ! detectedType && j !== types.length-1 ) {
  2204. break;
  2205. }
  2206. // Only a single match is needed for html type since it is
  2207. // bottom of the pile and very similar to string - but it
  2208. // must not be empty
  2209. if ( detectedType === 'html' && ! _empty(cache[k]) ) {
  2210. break;
  2211. }
  2212. }
  2213. // Type is valid for all data points in the column - use this
  2214. // type
  2215. if ( detectedType ) {
  2216. col.sType = detectedType;
  2217. break;
  2218. }
  2219. }
  2220. // Fall back - if no type was detected, always use string
  2221. if ( ! col.sType ) {
  2222. col.sType = 'string';
  2223. }
  2224. }
  2225. }
  2226. }
  2227. /**
  2228. * Take the column definitions and static columns arrays and calculate how
  2229. * they relate to column indexes. The callback function will then apply the
  2230. * definition found for a column to a suitable configuration object.
  2231. * @param {object} oSettings dataTables settings object
  2232. * @param {array} aoColDefs The aoColumnDefs array that is to be applied
  2233. * @param {array} aoCols The aoColumns array that defines columns individually
  2234. * @param {function} fn Callback function - takes two parameters, the calculated
  2235. * column index and the definition for that column.
  2236. * @memberof DataTable#oApi
  2237. */
  2238. function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
  2239. {
  2240. var i, iLen, j, jLen, k, kLen, def;
  2241. var columns = oSettings.aoColumns;
  2242. // Column definitions with aTargets
  2243. if ( aoColDefs )
  2244. {
  2245. /* Loop over the definitions array - loop in reverse so first instance has priority */
  2246. for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
  2247. {
  2248. def = aoColDefs[i];
  2249. /* Each definition can target multiple columns, as it is an array */
  2250. var aTargets = def.target !== undefined
  2251. ? def.target
  2252. : def.targets !== undefined
  2253. ? def.targets
  2254. : def.aTargets;
  2255. if ( ! Array.isArray( aTargets ) )
  2256. {
  2257. aTargets = [ aTargets ];
  2258. }
  2259. for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
  2260. {
  2261. if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
  2262. {
  2263. /* Add columns that we don't yet know about */
  2264. while( columns.length <= aTargets[j] )
  2265. {
  2266. _fnAddColumn( oSettings );
  2267. }
  2268. /* Integer, basic index */
  2269. fn( aTargets[j], def );
  2270. }
  2271. else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
  2272. {
  2273. /* Negative integer, right to left column counting */
  2274. fn( columns.length+aTargets[j], def );
  2275. }
  2276. else if ( typeof aTargets[j] === 'string' )
  2277. {
  2278. /* Class name matching on TH element */
  2279. for ( k=0, kLen=columns.length ; k<kLen ; k++ )
  2280. {
  2281. if ( aTargets[j] == "_all" ||
  2282. $(columns[k].nTh).hasClass( aTargets[j] ) )
  2283. {
  2284. fn( k, def );
  2285. }
  2286. }
  2287. }
  2288. }
  2289. }
  2290. }
  2291. // Statically defined columns array
  2292. if ( aoCols )
  2293. {
  2294. for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
  2295. {
  2296. fn( i, aoCols[i] );
  2297. }
  2298. }
  2299. }
  2300. /**
  2301. * Add a data array to the table, creating DOM node etc. This is the parallel to
  2302. * _fnGatherData, but for adding rows from a Javascript source, rather than a
  2303. * DOM source.
  2304. * @param {object} oSettings dataTables settings object
  2305. * @param {array} aData data array to be added
  2306. * @param {node} [nTr] TR element to add to the table - optional. If not given,
  2307. * DataTables will create a row automatically
  2308. * @param {array} [anTds] Array of TD|TH elements for the row - must be given
  2309. * if nTr is.
  2310. * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
  2311. * @memberof DataTable#oApi
  2312. */
  2313. function _fnAddData ( oSettings, aDataIn, nTr, anTds )
  2314. {
  2315. /* Create the object for storing information about this new row */
  2316. var iRow = oSettings.aoData.length;
  2317. var oData = $.extend( true, {}, DataTable.models.oRow, {
  2318. src: nTr ? 'dom' : 'data',
  2319. idx: iRow
  2320. } );
  2321. oData._aData = aDataIn;
  2322. oSettings.aoData.push( oData );
  2323. /* Create the cells */
  2324. var nTd, sThisType;
  2325. var columns = oSettings.aoColumns;
  2326. // Invalidate the column types as the new data needs to be revalidated
  2327. for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
  2328. {
  2329. columns[i].sType = null;
  2330. }
  2331. /* Add to the display array */
  2332. oSettings.aiDisplayMaster.push( iRow );
  2333. var id = oSettings.rowIdFn( aDataIn );
  2334. if ( id !== undefined ) {
  2335. oSettings.aIds[ id ] = oData;
  2336. }
  2337. /* Create the DOM information, or register it if already present */
  2338. if ( nTr || ! oSettings.oFeatures.bDeferRender )
  2339. {
  2340. _fnCreateTr( oSettings, iRow, nTr, anTds );
  2341. }
  2342. return iRow;
  2343. }
  2344. /**
  2345. * Add one or more TR elements to the table. Generally we'd expect to
  2346. * use this for reading data from a DOM sourced table, but it could be
  2347. * used for an TR element. Note that if a TR is given, it is used (i.e.
  2348. * it is not cloned).
  2349. * @param {object} settings dataTables settings object
  2350. * @param {array|node|jQuery} trs The TR element(s) to add to the table
  2351. * @returns {array} Array of indexes for the added rows
  2352. * @memberof DataTable#oApi
  2353. */
  2354. function _fnAddTr( settings, trs )
  2355. {
  2356. var row;
  2357. // Allow an individual node to be passed in
  2358. if ( ! (trs instanceof $) ) {
  2359. trs = $(trs);
  2360. }
  2361. return trs.map( function (i, el) {
  2362. row = _fnGetRowElements( settings, el );
  2363. return _fnAddData( settings, row.data, el, row.cells );
  2364. } );
  2365. }
  2366. /**
  2367. * Take a TR element and convert it to an index in aoData
  2368. * @param {object} oSettings dataTables settings object
  2369. * @param {node} n the TR element to find
  2370. * @returns {int} index if the node is found, null if not
  2371. * @memberof DataTable#oApi
  2372. */
  2373. function _fnNodeToDataIndex( oSettings, n )
  2374. {
  2375. return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
  2376. }
  2377. /**
  2378. * Take a TD element and convert it into a column data index (not the visible index)
  2379. * @param {object} oSettings dataTables settings object
  2380. * @param {int} iRow The row number the TD/TH can be found in
  2381. * @param {node} n The TD/TH element to find
  2382. * @returns {int} index if the node is found, -1 if not
  2383. * @memberof DataTable#oApi
  2384. */
  2385. function _fnNodeToColumnIndex( oSettings, iRow, n )
  2386. {
  2387. return $.inArray( n, oSettings.aoData[ iRow ].anCells );
  2388. }
  2389. /**
  2390. * Get the data for a given cell from the internal cache, taking into account data mapping
  2391. * @param {object} settings dataTables settings object
  2392. * @param {int} rowIdx aoData row id
  2393. * @param {int} colIdx Column index
  2394. * @param {string} type data get type ('display', 'type' 'filter|search' 'sort|order')
  2395. * @returns {*} Cell data
  2396. * @memberof DataTable#oApi
  2397. */
  2398. function _fnGetCellData( settings, rowIdx, colIdx, type )
  2399. {
  2400. if (type === 'search') {
  2401. type = 'filter';
  2402. }
  2403. else if (type === 'order') {
  2404. type = 'sort';
  2405. }
  2406. var draw = settings.iDraw;
  2407. var col = settings.aoColumns[colIdx];
  2408. var rowData = settings.aoData[rowIdx]._aData;
  2409. var defaultContent = col.sDefaultContent;
  2410. var cellData = col.fnGetData( rowData, type, {
  2411. settings: settings,
  2412. row: rowIdx,
  2413. col: colIdx
  2414. } );
  2415. if ( cellData === undefined ) {
  2416. if ( settings.iDrawError != draw && defaultContent === null ) {
  2417. _fnLog( settings, 0, "Requested unknown parameter "+
  2418. (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
  2419. " for row "+rowIdx+", column "+colIdx, 4 );
  2420. settings.iDrawError = draw;
  2421. }
  2422. return defaultContent;
  2423. }
  2424. // When the data source is null and a specific data type is requested (i.e.
  2425. // not the original data), we can use default column data
  2426. if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
  2427. cellData = defaultContent;
  2428. }
  2429. else if ( typeof cellData === 'function' ) {
  2430. // If the data source is a function, then we run it and use the return,
  2431. // executing in the scope of the data object (for instances)
  2432. return cellData.call( rowData );
  2433. }
  2434. if ( cellData === null && type === 'display' ) {
  2435. return '';
  2436. }
  2437. if ( type === 'filter' ) {
  2438. var fomatters = DataTable.ext.type.search;
  2439. if ( fomatters[ col.sType ] ) {
  2440. cellData = fomatters[ col.sType ]( cellData );
  2441. }
  2442. }
  2443. return cellData;
  2444. }
  2445. /**
  2446. * Set the value for a specific cell, into the internal data cache
  2447. * @param {object} settings dataTables settings object
  2448. * @param {int} rowIdx aoData row id
  2449. * @param {int} colIdx Column index
  2450. * @param {*} val Value to set
  2451. * @memberof DataTable#oApi
  2452. */
  2453. function _fnSetCellData( settings, rowIdx, colIdx, val )
  2454. {
  2455. var col = settings.aoColumns[colIdx];
  2456. var rowData = settings.aoData[rowIdx]._aData;
  2457. col.fnSetData( rowData, val, {
  2458. settings: settings,
  2459. row: rowIdx,
  2460. col: colIdx
  2461. } );
  2462. }
  2463. // Private variable that is used to match action syntax in the data property object
  2464. var __reArray = /\[.*?\]$/;
  2465. var __reFn = /\(\)$/;
  2466. /**
  2467. * Split string on periods, taking into account escaped periods
  2468. * @param {string} str String to split
  2469. * @return {array} Split string
  2470. */
  2471. function _fnSplitObjNotation( str )
  2472. {
  2473. return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
  2474. return s.replace(/\\\./g, '.');
  2475. } );
  2476. }
  2477. /**
  2478. * Return a function that can be used to get data from a source object, taking
  2479. * into account the ability to use nested objects as a source
  2480. * @param {string|int|function} mSource The data source for the object
  2481. * @returns {function} Data get function
  2482. * @memberof DataTable#oApi
  2483. */
  2484. var _fnGetObjectDataFn = DataTable.util.get;
  2485. /**
  2486. * Return a function that can be used to set data from a source object, taking
  2487. * into account the ability to use nested objects as a source
  2488. * @param {string|int|function} mSource The data source for the object
  2489. * @returns {function} Data set function
  2490. * @memberof DataTable#oApi
  2491. */
  2492. var _fnSetObjectDataFn = DataTable.util.set;
  2493. /**
  2494. * Return an array with the full table data
  2495. * @param {object} oSettings dataTables settings object
  2496. * @returns array {array} aData Master data array
  2497. * @memberof DataTable#oApi
  2498. */
  2499. function _fnGetDataMaster ( settings )
  2500. {
  2501. return _pluck( settings.aoData, '_aData' );
  2502. }
  2503. /**
  2504. * Nuke the table
  2505. * @param {object} oSettings dataTables settings object
  2506. * @memberof DataTable#oApi
  2507. */
  2508. function _fnClearTable( settings )
  2509. {
  2510. settings.aoData.length = 0;
  2511. settings.aiDisplayMaster.length = 0;
  2512. settings.aiDisplay.length = 0;
  2513. settings.aIds = {};
  2514. }
  2515. /**
  2516. * Take an array of integers (index array) and remove a target integer (value - not
  2517. * the key!)
  2518. * @param {array} a Index array to target
  2519. * @param {int} iTarget value to find
  2520. * @memberof DataTable#oApi
  2521. */
  2522. function _fnDeleteIndex( a, iTarget, splice )
  2523. {
  2524. var iTargetIndex = -1;
  2525. for ( var i=0, iLen=a.length ; i<iLen ; i++ )
  2526. {
  2527. if ( a[i] == iTarget )
  2528. {
  2529. iTargetIndex = i;
  2530. }
  2531. else if ( a[i] > iTarget )
  2532. {
  2533. a[i]--;
  2534. }
  2535. }
  2536. if ( iTargetIndex != -1 && splice === undefined )
  2537. {
  2538. a.splice( iTargetIndex, 1 );
  2539. }
  2540. }
  2541. /**
  2542. * Mark cached data as invalid such that a re-read of the data will occur when
  2543. * the cached data is next requested. Also update from the data source object.
  2544. *
  2545. * @param {object} settings DataTables settings object
  2546. * @param {int} rowIdx Row index to invalidate
  2547. * @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom'
  2548. * or 'data'
  2549. * @param {int} [colIdx] Column index to invalidate. If undefined the whole
  2550. * row will be invalidated
  2551. * @memberof DataTable#oApi
  2552. *
  2553. * @todo For the modularisation of v1.11 this will need to become a callback, so
  2554. * the sort and filter methods can subscribe to it. That will required
  2555. * initialisation options for sorting, which is why it is not already baked in
  2556. */
  2557. function _fnInvalidate( settings, rowIdx, src, colIdx )
  2558. {
  2559. var row = settings.aoData[ rowIdx ];
  2560. var i, ien;
  2561. var cellWrite = function ( cell, col ) {
  2562. // This is very frustrating, but in IE if you just write directly
  2563. // to innerHTML, and elements that are overwritten are GC'ed,
  2564. // even if there is a reference to them elsewhere
  2565. while ( cell.childNodes.length ) {
  2566. cell.removeChild( cell.firstChild );
  2567. }
  2568. cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
  2569. };
  2570. // Are we reading last data from DOM or the data object?
  2571. if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
  2572. // Read the data from the DOM
  2573. row._aData = _fnGetRowElements(
  2574. settings, row, colIdx, colIdx === undefined ? undefined : row._aData
  2575. )
  2576. .data;
  2577. }
  2578. else {
  2579. // Reading from data object, update the DOM
  2580. var cells = row.anCells;
  2581. if ( cells ) {
  2582. if ( colIdx !== undefined ) {
  2583. cellWrite( cells[colIdx], colIdx );
  2584. }
  2585. else {
  2586. for ( i=0, ien=cells.length ; i<ien ; i++ ) {
  2587. cellWrite( cells[i], i );
  2588. }
  2589. }
  2590. }
  2591. }
  2592. // For both row and cell invalidation, the cached data for sorting and
  2593. // filtering is nulled out
  2594. row._aSortData = null;
  2595. row._aFilterData = null;
  2596. // Invalidate the type for a specific column (if given) or all columns since
  2597. // the data might have changed
  2598. var cols = settings.aoColumns;
  2599. if ( colIdx !== undefined ) {
  2600. cols[ colIdx ].sType = null;
  2601. }
  2602. else {
  2603. for ( i=0, ien=cols.length ; i<ien ; i++ ) {
  2604. cols[i].sType = null;
  2605. }
  2606. // Update DataTables special `DT_*` attributes for the row
  2607. _fnRowAttributes( settings, row );
  2608. }
  2609. }
  2610. /**
  2611. * Build a data source object from an HTML row, reading the contents of the
  2612. * cells that are in the row.
  2613. *
  2614. * @param {object} settings DataTables settings object
  2615. * @param {node|object} TR element from which to read data or existing row
  2616. * object from which to re-read the data from the cells
  2617. * @param {int} [colIdx] Optional column index
  2618. * @param {array|object} [d] Data source object. If `colIdx` is given then this
  2619. * parameter should also be given and will be used to write the data into.
  2620. * Only the column in question will be written
  2621. * @returns {object} Object with two parameters: `data` the data read, in
  2622. * document order, and `cells` and array of nodes (they can be useful to the
  2623. * caller, so rather than needing a second traversal to get them, just return
  2624. * them from here).
  2625. * @memberof DataTable#oApi
  2626. */
  2627. function _fnGetRowElements( settings, row, colIdx, d )
  2628. {
  2629. var
  2630. tds = [],
  2631. td = row.firstChild,
  2632. name, col, o, i=0, contents,
  2633. columns = settings.aoColumns,
  2634. objectRead = settings._rowReadObject;
  2635. // Allow the data object to be passed in, or construct
  2636. d = d !== undefined ?
  2637. d :
  2638. objectRead ?
  2639. {} :
  2640. [];
  2641. var attr = function ( str, td ) {
  2642. if ( typeof str === 'string' ) {
  2643. var idx = str.indexOf('@');
  2644. if ( idx !== -1 ) {
  2645. var attr = str.substring( idx+1 );
  2646. var setter = _fnSetObjectDataFn( str );
  2647. setter( d, td.getAttribute( attr ) );
  2648. }
  2649. }
  2650. };
  2651. // Read data from a cell and store into the data object
  2652. var cellProcess = function ( cell ) {
  2653. if ( colIdx === undefined || colIdx === i ) {
  2654. col = columns[i];
  2655. contents = (cell.innerHTML).trim();
  2656. if ( col && col._bAttrSrc ) {
  2657. var setter = _fnSetObjectDataFn( col.mData._ );
  2658. setter( d, contents );
  2659. attr( col.mData.sort, cell );
  2660. attr( col.mData.type, cell );
  2661. attr( col.mData.filter, cell );
  2662. }
  2663. else {
  2664. // Depending on the `data` option for the columns the data can
  2665. // be read to either an object or an array.
  2666. if ( objectRead ) {
  2667. if ( ! col._setter ) {
  2668. // Cache the setter function
  2669. col._setter = _fnSetObjectDataFn( col.mData );
  2670. }
  2671. col._setter( d, contents );
  2672. }
  2673. else {
  2674. d[i] = contents;
  2675. }
  2676. }
  2677. }
  2678. i++;
  2679. };
  2680. if ( td ) {
  2681. // `tr` element was passed in
  2682. while ( td ) {
  2683. name = td.nodeName.toUpperCase();
  2684. if ( name == "TD" || name == "TH" ) {
  2685. cellProcess( td );
  2686. tds.push( td );
  2687. }
  2688. td = td.nextSibling;
  2689. }
  2690. }
  2691. else {
  2692. // Existing row object passed in
  2693. tds = row.anCells;
  2694. for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
  2695. cellProcess( tds[j] );
  2696. }
  2697. }
  2698. // Read the ID from the DOM if present
  2699. var rowNode = row.firstChild ? row : row.nTr;
  2700. if ( rowNode ) {
  2701. var id = rowNode.getAttribute( 'id' );
  2702. if ( id ) {
  2703. _fnSetObjectDataFn( settings.rowId )( d, id );
  2704. }
  2705. }
  2706. return {
  2707. data: d,
  2708. cells: tds
  2709. };
  2710. }
  2711. /**
  2712. * Create a new TR element (and it's TD children) for a row
  2713. * @param {object} oSettings dataTables settings object
  2714. * @param {int} iRow Row to consider
  2715. * @param {node} [nTrIn] TR element to add to the table - optional. If not given,
  2716. * DataTables will create a row automatically
  2717. * @param {array} [anTds] Array of TD|TH elements for the row - must be given
  2718. * if nTr is.
  2719. * @memberof DataTable#oApi
  2720. */
  2721. function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
  2722. {
  2723. var
  2724. row = oSettings.aoData[iRow],
  2725. rowData = row._aData,
  2726. cells = [],
  2727. nTr, nTd, oCol,
  2728. i, iLen, create;
  2729. if ( row.nTr === null )
  2730. {
  2731. nTr = nTrIn || document.createElement('tr');
  2732. row.nTr = nTr;
  2733. row.anCells = cells;
  2734. /* Use a private property on the node to allow reserve mapping from the node
  2735. * to the aoData array for fast look up
  2736. */
  2737. nTr._DT_RowIndex = iRow;
  2738. /* Special parameters can be given by the data source to be used on the row */
  2739. _fnRowAttributes( oSettings, row );
  2740. /* Process each column */
  2741. for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  2742. {
  2743. oCol = oSettings.aoColumns[i];
  2744. create = nTrIn ? false : true;
  2745. nTd = create ? document.createElement( oCol.sCellType ) : anTds[i];
  2746. nTd._DT_CellIndex = {
  2747. row: iRow,
  2748. column: i
  2749. };
  2750. cells.push( nTd );
  2751. // Need to create the HTML if new, or if a rendering function is defined
  2752. if ( create || ((oCol.mRender || oCol.mData !== i) &&
  2753. (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
  2754. )) {
  2755. nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
  2756. }
  2757. /* Add user defined class */
  2758. if ( oCol.sClass )
  2759. {
  2760. nTd.className += ' '+oCol.sClass;
  2761. }
  2762. // Visibility - add or remove as required
  2763. if ( oCol.bVisible && ! nTrIn )
  2764. {
  2765. nTr.appendChild( nTd );
  2766. }
  2767. else if ( ! oCol.bVisible && nTrIn )
  2768. {
  2769. nTd.parentNode.removeChild( nTd );
  2770. }
  2771. if ( oCol.fnCreatedCell )
  2772. {
  2773. oCol.fnCreatedCell.call( oSettings.oInstance,
  2774. nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
  2775. );
  2776. }
  2777. }
  2778. _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow, cells] );
  2779. }
  2780. }
  2781. /**
  2782. * Add attributes to a row based on the special `DT_*` parameters in a data
  2783. * source object.
  2784. * @param {object} settings DataTables settings object
  2785. * @param {object} DataTables row object for the row to be modified
  2786. * @memberof DataTable#oApi
  2787. */
  2788. function _fnRowAttributes( settings, row )
  2789. {
  2790. var tr = row.nTr;
  2791. var data = row._aData;
  2792. if ( tr ) {
  2793. var id = settings.rowIdFn( data );
  2794. if ( id ) {
  2795. tr.id = id;
  2796. }
  2797. if ( data.DT_RowClass ) {
  2798. // Remove any classes added by DT_RowClass before
  2799. var a = data.DT_RowClass.split(' ');
  2800. row.__rowc = row.__rowc ?
  2801. _unique( row.__rowc.concat( a ) ) :
  2802. a;
  2803. $(tr)
  2804. .removeClass( row.__rowc.join(' ') )
  2805. .addClass( data.DT_RowClass );
  2806. }
  2807. if ( data.DT_RowAttr ) {
  2808. $(tr).attr( data.DT_RowAttr );
  2809. }
  2810. if ( data.DT_RowData ) {
  2811. $(tr).data( data.DT_RowData );
  2812. }
  2813. }
  2814. }
  2815. /**
  2816. * Create the HTML header for the table
  2817. * @param {object} oSettings dataTables settings object
  2818. * @memberof DataTable#oApi
  2819. */
  2820. function _fnBuildHead( oSettings )
  2821. {
  2822. var i, ien, cell, row, column;
  2823. var thead = oSettings.nTHead;
  2824. var tfoot = oSettings.nTFoot;
  2825. var createHeader = $('th, td', thead).length === 0;
  2826. var classes = oSettings.oClasses;
  2827. var columns = oSettings.aoColumns;
  2828. if ( createHeader ) {
  2829. row = $('<tr/>').appendTo( thead );
  2830. }
  2831. for ( i=0, ien=columns.length ; i<ien ; i++ ) {
  2832. column = columns[i];
  2833. cell = $( column.nTh ).addClass( column.sClass );
  2834. if ( createHeader ) {
  2835. cell.appendTo( row );
  2836. }
  2837. // 1.11 move into sorting
  2838. if ( oSettings.oFeatures.bSort ) {
  2839. cell.addClass( column.sSortingClass );
  2840. if ( column.bSortable !== false ) {
  2841. cell
  2842. .attr( 'tabindex', oSettings.iTabIndex )
  2843. .attr( 'aria-controls', oSettings.sTableId );
  2844. _fnSortAttachListener( oSettings, column.nTh, i );
  2845. }
  2846. }
  2847. if ( column.sTitle != cell[0].innerHTML ) {
  2848. cell.html( column.sTitle );
  2849. }
  2850. _fnRenderer( oSettings, 'header' )(
  2851. oSettings, cell, column, classes
  2852. );
  2853. }
  2854. if ( createHeader ) {
  2855. _fnDetectHeader( oSettings.aoHeader, thead );
  2856. }
  2857. /* Deal with the footer - add classes if required */
  2858. $(thead).children('tr').children('th, td').addClass( classes.sHeaderTH );
  2859. $(tfoot).children('tr').children('th, td').addClass( classes.sFooterTH );
  2860. // Cache the footer cells. Note that we only take the cells from the first
  2861. // row in the footer. If there is more than one row the user wants to
  2862. // interact with, they need to use the table().foot() method. Note also this
  2863. // allows cells to be used for multiple columns using colspan
  2864. if ( tfoot !== null ) {
  2865. var cells = oSettings.aoFooter[0];
  2866. for ( i=0, ien=cells.length ; i<ien ; i++ ) {
  2867. column = columns[i];
  2868. column.nTf = cells[i].cell;
  2869. if ( column.sClass ) {
  2870. $(column.nTf).addClass( column.sClass );
  2871. }
  2872. }
  2873. }
  2874. }
  2875. /**
  2876. * Draw the header (or footer) element based on the column visibility states. The
  2877. * methodology here is to use the layout array from _fnDetectHeader, modified for
  2878. * the instantaneous column visibility, to construct the new layout. The grid is
  2879. * traversed over cell at a time in a rows x columns grid fashion, although each
  2880. * cell insert can cover multiple elements in the grid - which is tracks using the
  2881. * aApplied array. Cell inserts in the grid will only occur where there isn't
  2882. * already a cell in that position.
  2883. * @param {object} oSettings dataTables settings object
  2884. * @param array {objects} aoSource Layout array from _fnDetectHeader
  2885. * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
  2886. * @memberof DataTable#oApi
  2887. */
  2888. function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
  2889. {
  2890. var i, iLen, j, jLen, k, kLen, n, nLocalTr;
  2891. var aoLocal = [];
  2892. var aApplied = [];
  2893. var iColumns = oSettings.aoColumns.length;
  2894. var iRowspan, iColspan;
  2895. if ( ! aoSource )
  2896. {
  2897. return;
  2898. }
  2899. if ( bIncludeHidden === undefined )
  2900. {
  2901. bIncludeHidden = false;
  2902. }
  2903. /* Make a copy of the master layout array, but without the visible columns in it */
  2904. for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
  2905. {
  2906. aoLocal[i] = aoSource[i].slice();
  2907. aoLocal[i].nTr = aoSource[i].nTr;
  2908. /* Remove any columns which are currently hidden */
  2909. for ( j=iColumns-1 ; j>=0 ; j-- )
  2910. {
  2911. if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
  2912. {
  2913. aoLocal[i].splice( j, 1 );
  2914. }
  2915. }
  2916. /* Prep the applied array - it needs an element for each row */
  2917. aApplied.push( [] );
  2918. }
  2919. for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
  2920. {
  2921. nLocalTr = aoLocal[i].nTr;
  2922. /* All cells are going to be replaced, so empty out the row */
  2923. if ( nLocalTr )
  2924. {
  2925. while( (n = nLocalTr.firstChild) )
  2926. {
  2927. nLocalTr.removeChild( n );
  2928. }
  2929. }
  2930. for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
  2931. {
  2932. iRowspan = 1;
  2933. iColspan = 1;
  2934. /* Check to see if there is already a cell (row/colspan) covering our target
  2935. * insert point. If there is, then there is nothing to do.
  2936. */
  2937. if ( aApplied[i][j] === undefined )
  2938. {
  2939. nLocalTr.appendChild( aoLocal[i][j].cell );
  2940. aApplied[i][j] = 1;
  2941. /* Expand the cell to cover as many rows as needed */
  2942. while ( aoLocal[i+iRowspan] !== undefined &&
  2943. aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
  2944. {
  2945. aApplied[i+iRowspan][j] = 1;
  2946. iRowspan++;
  2947. }
  2948. /* Expand the cell to cover as many columns as needed */
  2949. while ( aoLocal[i][j+iColspan] !== undefined &&
  2950. aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
  2951. {
  2952. /* Must update the applied array over the rows for the columns */
  2953. for ( k=0 ; k<iRowspan ; k++ )
  2954. {
  2955. aApplied[i+k][j+iColspan] = 1;
  2956. }
  2957. iColspan++;
  2958. }
  2959. /* Do the actual expansion in the DOM */
  2960. $(aoLocal[i][j].cell)
  2961. .attr('rowspan', iRowspan)
  2962. .attr('colspan', iColspan);
  2963. }
  2964. }
  2965. }
  2966. }
  2967. /**
  2968. * Insert the required TR nodes into the table for display
  2969. * @param {object} oSettings dataTables settings object
  2970. * @param ajaxComplete true after ajax call to complete rendering
  2971. * @memberof DataTable#oApi
  2972. */
  2973. function _fnDraw( oSettings, ajaxComplete )
  2974. {
  2975. // Allow for state saving and a custom start position
  2976. _fnStart( oSettings );
  2977. /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
  2978. var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
  2979. if ( $.inArray( false, aPreDraw ) !== -1 )
  2980. {
  2981. _fnProcessingDisplay( oSettings, false );
  2982. return;
  2983. }
  2984. var anRows = [];
  2985. var iRowCount = 0;
  2986. var asStripeClasses = oSettings.asStripeClasses;
  2987. var iStripes = asStripeClasses.length;
  2988. var oLang = oSettings.oLanguage;
  2989. var bServerSide = _fnDataSource( oSettings ) == 'ssp';
  2990. var aiDisplay = oSettings.aiDisplay;
  2991. var iDisplayStart = oSettings._iDisplayStart;
  2992. var iDisplayEnd = oSettings.fnDisplayEnd();
  2993. oSettings.bDrawing = true;
  2994. /* Server-side processing draw intercept */
  2995. if ( oSettings.bDeferLoading )
  2996. {
  2997. oSettings.bDeferLoading = false;
  2998. oSettings.iDraw++;
  2999. _fnProcessingDisplay( oSettings, false );
  3000. }
  3001. else if ( !bServerSide )
  3002. {
  3003. oSettings.iDraw++;
  3004. }
  3005. else if ( !oSettings.bDestroying && !ajaxComplete)
  3006. {
  3007. _fnAjaxUpdate( oSettings );
  3008. return;
  3009. }
  3010. if ( aiDisplay.length !== 0 )
  3011. {
  3012. var iStart = bServerSide ? 0 : iDisplayStart;
  3013. var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
  3014. for ( var j=iStart ; j<iEnd ; j++ )
  3015. {
  3016. var iDataIndex = aiDisplay[j];
  3017. var aoData = oSettings.aoData[ iDataIndex ];
  3018. if ( aoData.nTr === null )
  3019. {
  3020. _fnCreateTr( oSettings, iDataIndex );
  3021. }
  3022. var nRow = aoData.nTr;
  3023. /* Remove the old striping classes and then add the new one */
  3024. if ( iStripes !== 0 )
  3025. {
  3026. var sStripe = asStripeClasses[ iRowCount % iStripes ];
  3027. if ( aoData._sRowStripe != sStripe )
  3028. {
  3029. $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
  3030. aoData._sRowStripe = sStripe;
  3031. }
  3032. }
  3033. // Row callback functions - might want to manipulate the row
  3034. // iRowCount and j are not currently documented. Are they at all
  3035. // useful?
  3036. _fnCallbackFire( oSettings, 'aoRowCallback', null,
  3037. [nRow, aoData._aData, iRowCount, j, iDataIndex] );
  3038. anRows.push( nRow );
  3039. iRowCount++;
  3040. }
  3041. }
  3042. else
  3043. {
  3044. /* Table is empty - create a row with an empty message in it */
  3045. var sZero = oLang.sZeroRecords;
  3046. if ( oSettings.iDraw == 1 && _fnDataSource( oSettings ) == 'ajax' )
  3047. {
  3048. sZero = oLang.sLoadingRecords;
  3049. }
  3050. else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
  3051. {
  3052. sZero = oLang.sEmptyTable;
  3053. }
  3054. anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
  3055. .append( $('<td />', {
  3056. 'valign': 'top',
  3057. 'colSpan': _fnVisbleColumns( oSettings ),
  3058. 'class': oSettings.oClasses.sRowEmpty
  3059. } ).html( sZero ) )[0];
  3060. }
  3061. /* Header and footer callbacks */
  3062. _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
  3063. _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
  3064. _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
  3065. _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
  3066. var body = $(oSettings.nTBody);
  3067. body.children().detach();
  3068. body.append( $(anRows) );
  3069. /* Call all required callback functions for the end of a draw */
  3070. _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
  3071. /* Draw is complete, sorting and filtering must be as well */
  3072. oSettings.bSorted = false;
  3073. oSettings.bFiltered = false;
  3074. oSettings.bDrawing = false;
  3075. }
  3076. /**
  3077. * Redraw the table - taking account of the various features which are enabled
  3078. * @param {object} oSettings dataTables settings object
  3079. * @param {boolean} [holdPosition] Keep the current paging position. By default
  3080. * the paging is reset to the first page
  3081. * @memberof DataTable#oApi
  3082. */
  3083. function _fnReDraw( settings, holdPosition )
  3084. {
  3085. var
  3086. features = settings.oFeatures,
  3087. sort = features.bSort,
  3088. filter = features.bFilter;
  3089. if ( sort ) {
  3090. _fnSort( settings );
  3091. }
  3092. if ( filter ) {
  3093. _fnFilterComplete( settings, settings.oPreviousSearch );
  3094. }
  3095. else {
  3096. // No filtering, so we want to just use the display master
  3097. settings.aiDisplay = settings.aiDisplayMaster.slice();
  3098. }
  3099. if ( holdPosition !== true ) {
  3100. settings._iDisplayStart = 0;
  3101. }
  3102. // Let any modules know about the draw hold position state (used by
  3103. // scrolling internally)
  3104. settings._drawHold = holdPosition;
  3105. _fnDraw( settings );
  3106. settings._drawHold = false;
  3107. }
  3108. /**
  3109. * Add the options to the page HTML for the table
  3110. * @param {object} oSettings dataTables settings object
  3111. * @memberof DataTable#oApi
  3112. */
  3113. function _fnAddOptionsHtml ( oSettings )
  3114. {
  3115. var classes = oSettings.oClasses;
  3116. var table = $(oSettings.nTable);
  3117. var holding = $('<div/>').insertBefore( table ); // Holding element for speed
  3118. var features = oSettings.oFeatures;
  3119. // All DataTables are wrapped in a div
  3120. var insert = $('<div/>', {
  3121. id: oSettings.sTableId+'_wrapper',
  3122. 'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
  3123. } );
  3124. oSettings.nHolding = holding[0];
  3125. oSettings.nTableWrapper = insert[0];
  3126. oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
  3127. /* Loop over the user set positioning and place the elements as needed */
  3128. var aDom = oSettings.sDom.split('');
  3129. var featureNode, cOption, nNewNode, cNext, sAttr, j;
  3130. for ( var i=0 ; i<aDom.length ; i++ )
  3131. {
  3132. featureNode = null;
  3133. cOption = aDom[i];
  3134. if ( cOption == '<' )
  3135. {
  3136. /* New container div */
  3137. nNewNode = $('<div/>')[0];
  3138. /* Check to see if we should append an id and/or a class name to the container */
  3139. cNext = aDom[i+1];
  3140. if ( cNext == "'" || cNext == '"' )
  3141. {
  3142. sAttr = "";
  3143. j = 2;
  3144. while ( aDom[i+j] != cNext )
  3145. {
  3146. sAttr += aDom[i+j];
  3147. j++;
  3148. }
  3149. /* Replace jQuery UI constants @todo depreciated */
  3150. if ( sAttr == "H" )
  3151. {
  3152. sAttr = classes.sJUIHeader;
  3153. }
  3154. else if ( sAttr == "F" )
  3155. {
  3156. sAttr = classes.sJUIFooter;
  3157. }
  3158. /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
  3159. * breaks the string into parts and applies them as needed
  3160. */
  3161. if ( sAttr.indexOf('.') != -1 )
  3162. {
  3163. var aSplit = sAttr.split('.');
  3164. nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
  3165. nNewNode.className = aSplit[1];
  3166. }
  3167. else if ( sAttr.charAt(0) == "#" )
  3168. {
  3169. nNewNode.id = sAttr.substr(1, sAttr.length-1);
  3170. }
  3171. else
  3172. {
  3173. nNewNode.className = sAttr;
  3174. }
  3175. i += j; /* Move along the position array */
  3176. }
  3177. insert.append( nNewNode );
  3178. insert = $(nNewNode);
  3179. }
  3180. else if ( cOption == '>' )
  3181. {
  3182. /* End container div */
  3183. insert = insert.parent();
  3184. }
  3185. // @todo Move options into their own plugins?
  3186. else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
  3187. {
  3188. /* Length */
  3189. featureNode = _fnFeatureHtmlLength( oSettings );
  3190. }
  3191. else if ( cOption == 'f' && features.bFilter )
  3192. {
  3193. /* Filter */
  3194. featureNode = _fnFeatureHtmlFilter( oSettings );
  3195. }
  3196. else if ( cOption == 'r' && features.bProcessing )
  3197. {
  3198. /* pRocessing */
  3199. featureNode = _fnFeatureHtmlProcessing( oSettings );
  3200. }
  3201. else if ( cOption == 't' )
  3202. {
  3203. /* Table */
  3204. featureNode = _fnFeatureHtmlTable( oSettings );
  3205. }
  3206. else if ( cOption == 'i' && features.bInfo )
  3207. {
  3208. /* Info */
  3209. featureNode = _fnFeatureHtmlInfo( oSettings );
  3210. }
  3211. else if ( cOption == 'p' && features.bPaginate )
  3212. {
  3213. /* Pagination */
  3214. featureNode = _fnFeatureHtmlPaginate( oSettings );
  3215. }
  3216. else if ( DataTable.ext.feature.length !== 0 )
  3217. {
  3218. /* Plug-in features */
  3219. var aoFeatures = DataTable.ext.feature;
  3220. for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
  3221. {
  3222. if ( cOption == aoFeatures[k].cFeature )
  3223. {
  3224. featureNode = aoFeatures[k].fnInit( oSettings );
  3225. break;
  3226. }
  3227. }
  3228. }
  3229. /* Add to the 2D features array */
  3230. if ( featureNode )
  3231. {
  3232. var aanFeatures = oSettings.aanFeatures;
  3233. if ( ! aanFeatures[cOption] )
  3234. {
  3235. aanFeatures[cOption] = [];
  3236. }
  3237. aanFeatures[cOption].push( featureNode );
  3238. insert.append( featureNode );
  3239. }
  3240. }
  3241. /* Built our DOM structure - replace the holding div with what we want */
  3242. holding.replaceWith( insert );
  3243. oSettings.nHolding = null;
  3244. }
  3245. /**
  3246. * Use the DOM source to create up an array of header cells. The idea here is to
  3247. * create a layout grid (array) of rows x columns, which contains a reference
  3248. * to the cell that that point in the grid (regardless of col/rowspan), such that
  3249. * any column / row could be removed and the new grid constructed
  3250. * @param array {object} aLayout Array to store the calculated layout in
  3251. * @param {node} nThead The header/footer element for the table
  3252. * @memberof DataTable#oApi
  3253. */
  3254. function _fnDetectHeader ( aLayout, nThead )
  3255. {
  3256. var nTrs = $(nThead).children('tr');
  3257. var nTr, nCell;
  3258. var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
  3259. var bUnique;
  3260. var fnShiftCol = function ( a, i, j ) {
  3261. var k = a[i];
  3262. while ( k[j] ) {
  3263. j++;
  3264. }
  3265. return j;
  3266. };
  3267. aLayout.splice( 0, aLayout.length );
  3268. /* We know how many rows there are in the layout - so prep it */
  3269. for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  3270. {
  3271. aLayout.push( [] );
  3272. }
  3273. /* Calculate a layout array */
  3274. for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  3275. {
  3276. nTr = nTrs[i];
  3277. iColumn = 0;
  3278. /* For every cell in the row... */
  3279. nCell = nTr.firstChild;
  3280. while ( nCell ) {
  3281. if ( nCell.nodeName.toUpperCase() == "TD" ||
  3282. nCell.nodeName.toUpperCase() == "TH" )
  3283. {
  3284. /* Get the col and rowspan attributes from the DOM and sanitise them */
  3285. iColspan = nCell.getAttribute('colspan') * 1;
  3286. iRowspan = nCell.getAttribute('rowspan') * 1;
  3287. iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
  3288. iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
  3289. /* There might be colspan cells already in this row, so shift our target
  3290. * accordingly
  3291. */
  3292. iColShifted = fnShiftCol( aLayout, i, iColumn );
  3293. /* Cache calculation for unique columns */
  3294. bUnique = iColspan === 1 ? true : false;
  3295. /* If there is col / rowspan, copy the information into the layout grid */
  3296. for ( l=0 ; l<iColspan ; l++ )
  3297. {
  3298. for ( k=0 ; k<iRowspan ; k++ )
  3299. {
  3300. aLayout[i+k][iColShifted+l] = {
  3301. "cell": nCell,
  3302. "unique": bUnique
  3303. };
  3304. aLayout[i+k].nTr = nTr;
  3305. }
  3306. }
  3307. }
  3308. nCell = nCell.nextSibling;
  3309. }
  3310. }
  3311. }
  3312. /**
  3313. * Get an array of unique th elements, one for each column
  3314. * @param {object} oSettings dataTables settings object
  3315. * @param {node} nHeader automatically detect the layout from this node - optional
  3316. * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
  3317. * @returns array {node} aReturn list of unique th's
  3318. * @memberof DataTable#oApi
  3319. */
  3320. function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
  3321. {
  3322. var aReturn = [];
  3323. if ( !aLayout )
  3324. {
  3325. aLayout = oSettings.aoHeader;
  3326. if ( nHeader )
  3327. {
  3328. aLayout = [];
  3329. _fnDetectHeader( aLayout, nHeader );
  3330. }
  3331. }
  3332. for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
  3333. {
  3334. for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
  3335. {
  3336. if ( aLayout[i][j].unique &&
  3337. (!aReturn[j] || !oSettings.bSortCellsTop) )
  3338. {
  3339. aReturn[j] = aLayout[i][j].cell;
  3340. }
  3341. }
  3342. }
  3343. return aReturn;
  3344. }
  3345. /**
  3346. * Set the start position for draw
  3347. * @param {object} oSettings dataTables settings object
  3348. */
  3349. function _fnStart( oSettings )
  3350. {
  3351. var bServerSide = _fnDataSource( oSettings ) == 'ssp';
  3352. var iInitDisplayStart = oSettings.iInitDisplayStart;
  3353. // Check and see if we have an initial draw position from state saving
  3354. if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
  3355. {
  3356. oSettings._iDisplayStart = bServerSide ?
  3357. iInitDisplayStart :
  3358. iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
  3359. 0 :
  3360. iInitDisplayStart;
  3361. oSettings.iInitDisplayStart = -1;
  3362. }
  3363. }
  3364. /**
  3365. * Create an Ajax call based on the table's settings, taking into account that
  3366. * parameters can have multiple forms, and backwards compatibility.
  3367. *
  3368. * @param {object} oSettings dataTables settings object
  3369. * @param {array} data Data to send to the server, required by
  3370. * DataTables - may be augmented by developer callbacks
  3371. * @param {function} fn Callback function to run when data is obtained
  3372. */
  3373. function _fnBuildAjax( oSettings, data, fn )
  3374. {
  3375. // Compatibility with 1.9-, allow fnServerData and event to manipulate
  3376. _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
  3377. // Convert to object based for 1.10+ if using the old array scheme which can
  3378. // come from server-side processing or serverParams
  3379. if ( data && Array.isArray(data) ) {
  3380. var tmp = {};
  3381. var rbracket = /(.*?)\[\]$/;
  3382. $.each( data, function (key, val) {
  3383. var match = val.name.match(rbracket);
  3384. if ( match ) {
  3385. // Support for arrays
  3386. var name = match[0];
  3387. if ( ! tmp[ name ] ) {
  3388. tmp[ name ] = [];
  3389. }
  3390. tmp[ name ].push( val.value );
  3391. }
  3392. else {
  3393. tmp[val.name] = val.value;
  3394. }
  3395. } );
  3396. data = tmp;
  3397. }
  3398. var ajaxData;
  3399. var ajax = oSettings.ajax;
  3400. var instance = oSettings.oInstance;
  3401. var callback = function ( json ) {
  3402. var status = oSettings.jqXHR
  3403. ? oSettings.jqXHR.status
  3404. : null;
  3405. if ( json === null || (typeof status === 'number' && status == 204 ) ) {
  3406. json = {};
  3407. _fnAjaxDataSrc( oSettings, json, [] );
  3408. }
  3409. var error = json.error || json.sError;
  3410. if ( error ) {
  3411. _fnLog( oSettings, 0, error );
  3412. }
  3413. oSettings.json = json;
  3414. _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
  3415. fn( json );
  3416. };
  3417. if ( $.isPlainObject( ajax ) && ajax.data )
  3418. {
  3419. ajaxData = ajax.data;
  3420. var newData = typeof ajaxData === 'function' ?
  3421. ajaxData( data, oSettings ) : // fn can manipulate data or return
  3422. ajaxData; // an object object or array to merge
  3423. // If the function returned something, use that alone
  3424. data = typeof ajaxData === 'function' && newData ?
  3425. newData :
  3426. $.extend( true, data, newData );
  3427. // Remove the data property as we've resolved it already and don't want
  3428. // jQuery to do it again (it is restored at the end of the function)
  3429. delete ajax.data;
  3430. }
  3431. var baseAjax = {
  3432. "data": data,
  3433. "success": callback,
  3434. "dataType": "json",
  3435. "cache": false,
  3436. "type": oSettings.sServerMethod,
  3437. "error": function (xhr, error, thrown) {
  3438. var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
  3439. if ( $.inArray( true, ret ) === -1 ) {
  3440. if ( error == "parsererror" ) {
  3441. _fnLog( oSettings, 0, 'Invalid JSON response', 1 );
  3442. }
  3443. else if ( xhr.readyState === 4 ) {
  3444. _fnLog( oSettings, 0, 'Ajax error', 7 );
  3445. }
  3446. }
  3447. _fnProcessingDisplay( oSettings, false );
  3448. }
  3449. };
  3450. // Store the data submitted for the API
  3451. oSettings.oAjaxData = data;
  3452. // Allow plug-ins and external processes to modify the data
  3453. _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
  3454. if ( oSettings.fnServerData )
  3455. {
  3456. // DataTables 1.9- compatibility
  3457. oSettings.fnServerData.call( instance,
  3458. oSettings.sAjaxSource,
  3459. $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
  3460. return { name: key, value: val };
  3461. } ),
  3462. callback,
  3463. oSettings
  3464. );
  3465. }
  3466. else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
  3467. {
  3468. // DataTables 1.9- compatibility
  3469. oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
  3470. url: ajax || oSettings.sAjaxSource
  3471. } ) );
  3472. }
  3473. else if ( typeof ajax === 'function' )
  3474. {
  3475. // Is a function - let the caller define what needs to be done
  3476. oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
  3477. }
  3478. else
  3479. {
  3480. // Object to extend the base settings
  3481. oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
  3482. // Restore for next time around
  3483. ajax.data = ajaxData;
  3484. }
  3485. }
  3486. /**
  3487. * Update the table using an Ajax call
  3488. * @param {object} settings dataTables settings object
  3489. * @returns {boolean} Block the table drawing or not
  3490. * @memberof DataTable#oApi
  3491. */
  3492. function _fnAjaxUpdate( settings )
  3493. {
  3494. settings.iDraw++;
  3495. _fnProcessingDisplay( settings, true );
  3496. _fnBuildAjax(
  3497. settings,
  3498. _fnAjaxParameters( settings ),
  3499. function(json) {
  3500. _fnAjaxUpdateDraw( settings, json );
  3501. }
  3502. );
  3503. }
  3504. /**
  3505. * Build up the parameters in an object needed for a server-side processing
  3506. * request. Note that this is basically done twice, is different ways - a modern
  3507. * method which is used by default in DataTables 1.10 which uses objects and
  3508. * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
  3509. * the sAjaxSource option is used in the initialisation, or the legacyAjax
  3510. * option is set.
  3511. * @param {object} oSettings dataTables settings object
  3512. * @returns {bool} block the table drawing or not
  3513. * @memberof DataTable#oApi
  3514. */
  3515. function _fnAjaxParameters( settings )
  3516. {
  3517. var
  3518. columns = settings.aoColumns,
  3519. columnCount = columns.length,
  3520. features = settings.oFeatures,
  3521. preSearch = settings.oPreviousSearch,
  3522. preColSearch = settings.aoPreSearchCols,
  3523. i, data = [], dataProp, column, columnSearch,
  3524. sort = _fnSortFlatten( settings ),
  3525. displayStart = settings._iDisplayStart,
  3526. displayLength = features.bPaginate !== false ?
  3527. settings._iDisplayLength :
  3528. -1;
  3529. var param = function ( name, value ) {
  3530. data.push( { 'name': name, 'value': value } );
  3531. };
  3532. // DataTables 1.9- compatible method
  3533. param( 'sEcho', settings.iDraw );
  3534. param( 'iColumns', columnCount );
  3535. param( 'sColumns', _pluck( columns, 'sName' ).join(',') );
  3536. param( 'iDisplayStart', displayStart );
  3537. param( 'iDisplayLength', displayLength );
  3538. // DataTables 1.10+ method
  3539. var d = {
  3540. draw: settings.iDraw,
  3541. columns: [],
  3542. order: [],
  3543. start: displayStart,
  3544. length: displayLength,
  3545. search: {
  3546. value: preSearch.sSearch,
  3547. regex: preSearch.bRegex
  3548. }
  3549. };
  3550. for ( i=0 ; i<columnCount ; i++ ) {
  3551. column = columns[i];
  3552. columnSearch = preColSearch[i];
  3553. dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
  3554. d.columns.push( {
  3555. data: dataProp,
  3556. name: column.sName,
  3557. searchable: column.bSearchable,
  3558. orderable: column.bSortable,
  3559. search: {
  3560. value: columnSearch.sSearch,
  3561. regex: columnSearch.bRegex
  3562. }
  3563. } );
  3564. param( "mDataProp_"+i, dataProp );
  3565. if ( features.bFilter ) {
  3566. param( 'sSearch_'+i, columnSearch.sSearch );
  3567. param( 'bRegex_'+i, columnSearch.bRegex );
  3568. param( 'bSearchable_'+i, column.bSearchable );
  3569. }
  3570. if ( features.bSort ) {
  3571. param( 'bSortable_'+i, column.bSortable );
  3572. }
  3573. }
  3574. if ( features.bFilter ) {
  3575. param( 'sSearch', preSearch.sSearch );
  3576. param( 'bRegex', preSearch.bRegex );
  3577. }
  3578. if ( features.bSort ) {
  3579. $.each( sort, function ( i, val ) {
  3580. d.order.push( { column: val.col, dir: val.dir } );
  3581. param( 'iSortCol_'+i, val.col );
  3582. param( 'sSortDir_'+i, val.dir );
  3583. } );
  3584. param( 'iSortingCols', sort.length );
  3585. }
  3586. // If the legacy.ajax parameter is null, then we automatically decide which
  3587. // form to use, based on sAjaxSource
  3588. var legacy = DataTable.ext.legacy.ajax;
  3589. if ( legacy === null ) {
  3590. return settings.sAjaxSource ? data : d;
  3591. }
  3592. // Otherwise, if legacy has been specified then we use that to decide on the
  3593. // form
  3594. return legacy ? data : d;
  3595. }
  3596. /**
  3597. * Data the data from the server (nuking the old) and redraw the table
  3598. * @param {object} oSettings dataTables settings object
  3599. * @param {object} json json data return from the server.
  3600. * @param {string} json.sEcho Tracking flag for DataTables to match requests
  3601. * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
  3602. * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
  3603. * @param {array} json.aaData The data to display on this page
  3604. * @param {string} [json.sColumns] Column ordering (sName, comma separated)
  3605. * @memberof DataTable#oApi
  3606. */
  3607. function _fnAjaxUpdateDraw ( settings, json )
  3608. {
  3609. // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
  3610. // Support both
  3611. var compat = function ( old, modern ) {
  3612. return json[old] !== undefined ? json[old] : json[modern];
  3613. };
  3614. var data = _fnAjaxDataSrc( settings, json );
  3615. var draw = compat( 'sEcho', 'draw' );
  3616. var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' );
  3617. var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
  3618. if ( draw !== undefined ) {
  3619. // Protect against out of sequence returns
  3620. if ( draw*1 < settings.iDraw ) {
  3621. return;
  3622. }
  3623. settings.iDraw = draw * 1;
  3624. }
  3625. // No data in returned object, so rather than an array, we show an empty table
  3626. if ( ! data ) {
  3627. data = [];
  3628. }
  3629. _fnClearTable( settings );
  3630. settings._iRecordsTotal = parseInt(recordsTotal, 10);
  3631. settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
  3632. for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  3633. _fnAddData( settings, data[i] );
  3634. }
  3635. settings.aiDisplay = settings.aiDisplayMaster.slice();
  3636. _fnDraw( settings, true );
  3637. if ( ! settings._bInitComplete ) {
  3638. _fnInitComplete( settings, json );
  3639. }
  3640. _fnProcessingDisplay( settings, false );
  3641. }
  3642. /**
  3643. * Get the data from the JSON data source to use for drawing a table. Using
  3644. * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
  3645. * source object, or from a processing function.
  3646. * @param {object} oSettings dataTables settings object
  3647. * @param {object} json Data source object / array from the server
  3648. * @return {array} Array of data to use
  3649. */
  3650. function _fnAjaxDataSrc ( oSettings, json, write )
  3651. {
  3652. var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
  3653. oSettings.ajax.dataSrc :
  3654. oSettings.sAjaxDataProp; // Compatibility with 1.9-.
  3655. if ( ! write ) {
  3656. if ( dataSrc === 'data' ) {
  3657. // If the default, then we still want to support the old style, and safely ignore
  3658. // it if possible
  3659. return json.aaData || json[dataSrc];
  3660. }
  3661. return dataSrc !== "" ?
  3662. _fnGetObjectDataFn( dataSrc )( json ) :
  3663. json;
  3664. }
  3665. // set
  3666. _fnSetObjectDataFn( dataSrc )( json, write );
  3667. }
  3668. /**
  3669. * Generate the node required for filtering text
  3670. * @returns {node} Filter control element
  3671. * @param {object} oSettings dataTables settings object
  3672. * @memberof DataTable#oApi
  3673. */
  3674. function _fnFeatureHtmlFilter ( settings )
  3675. {
  3676. var classes = settings.oClasses;
  3677. var tableId = settings.sTableId;
  3678. var language = settings.oLanguage;
  3679. var previousSearch = settings.oPreviousSearch;
  3680. var features = settings.aanFeatures;
  3681. var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
  3682. var str = language.sSearch;
  3683. str = str.match(/_INPUT_/) ?
  3684. str.replace('_INPUT_', input) :
  3685. str+input;
  3686. var filter = $('<div/>', {
  3687. 'id': ! features.f ? tableId+'_filter' : null,
  3688. 'class': classes.sFilter
  3689. } )
  3690. .append( $('<label/>' ).append( str ) );
  3691. var searchFn = function(event) {
  3692. /* Update all other filter input elements for the new display */
  3693. var n = features.f;
  3694. var val = !this.value ? "" : this.value; // mental IE8 fix :-(
  3695. if(previousSearch.return && event.key !== "Enter") {
  3696. return;
  3697. }
  3698. /* Now do the filter */
  3699. if ( val != previousSearch.sSearch ) {
  3700. _fnFilterComplete( settings, {
  3701. "sSearch": val,
  3702. "bRegex": previousSearch.bRegex,
  3703. "bSmart": previousSearch.bSmart ,
  3704. "bCaseInsensitive": previousSearch.bCaseInsensitive,
  3705. "return": previousSearch.return
  3706. } );
  3707. // Need to redraw, without resorting
  3708. settings._iDisplayStart = 0;
  3709. _fnDraw( settings );
  3710. }
  3711. };
  3712. var searchDelay = settings.searchDelay !== null ?
  3713. settings.searchDelay :
  3714. _fnDataSource( settings ) === 'ssp' ?
  3715. 400 :
  3716. 0;
  3717. var jqFilter = $('input', filter)
  3718. .val( previousSearch.sSearch )
  3719. .attr( 'placeholder', language.sSearchPlaceholder )
  3720. .on(
  3721. 'keyup.DT search.DT input.DT paste.DT cut.DT',
  3722. searchDelay ?
  3723. _fnThrottle( searchFn, searchDelay ) :
  3724. searchFn
  3725. )
  3726. .on( 'mouseup', function(e) {
  3727. // Edge fix! Edge 17 does not trigger anything other than mouse events when clicking
  3728. // on the clear icon (Edge bug 17584515). This is safe in other browsers as `searchFn`
  3729. // checks the value to see if it has changed. In other browsers it won't have.
  3730. setTimeout( function () {
  3731. searchFn.call(jqFilter[0], e);
  3732. }, 10);
  3733. } )
  3734. .on( 'keypress.DT', function(e) {
  3735. /* Prevent form submission */
  3736. if ( e.keyCode == 13 ) {
  3737. return false;
  3738. }
  3739. } )
  3740. .attr('aria-controls', tableId);
  3741. // Update the input elements whenever the table is filtered
  3742. $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
  3743. if ( settings === s ) {
  3744. // IE9 throws an 'unknown error' if document.activeElement is used
  3745. // inside an iframe or frame...
  3746. try {
  3747. if ( jqFilter[0] !== document.activeElement ) {
  3748. jqFilter.val( previousSearch.sSearch );
  3749. }
  3750. }
  3751. catch ( e ) {}
  3752. }
  3753. } );
  3754. return filter[0];
  3755. }
  3756. /**
  3757. * Filter the table using both the global filter and column based filtering
  3758. * @param {object} oSettings dataTables settings object
  3759. * @param {object} oSearch search information
  3760. * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
  3761. * @memberof DataTable#oApi
  3762. */
  3763. function _fnFilterComplete ( oSettings, oInput, iForce )
  3764. {
  3765. var oPrevSearch = oSettings.oPreviousSearch;
  3766. var aoPrevSearch = oSettings.aoPreSearchCols;
  3767. var fnSaveFilter = function ( oFilter ) {
  3768. /* Save the filtering values */
  3769. oPrevSearch.sSearch = oFilter.sSearch;
  3770. oPrevSearch.bRegex = oFilter.bRegex;
  3771. oPrevSearch.bSmart = oFilter.bSmart;
  3772. oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
  3773. oPrevSearch.return = oFilter.return;
  3774. };
  3775. var fnRegex = function ( o ) {
  3776. // Backwards compatibility with the bEscapeRegex option
  3777. return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
  3778. };
  3779. // Resolve any column types that are unknown due to addition or invalidation
  3780. // @todo As per sort - can this be moved into an event handler?
  3781. _fnColumnTypes( oSettings );
  3782. /* In server-side processing all filtering is done by the server, so no point hanging around here */
  3783. if ( _fnDataSource( oSettings ) != 'ssp' )
  3784. {
  3785. /* Global filter */
  3786. _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive, oInput.return );
  3787. fnSaveFilter( oInput );
  3788. /* Now do the individual column filter */
  3789. for ( var i=0 ; i<aoPrevSearch.length ; i++ )
  3790. {
  3791. _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
  3792. aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
  3793. }
  3794. /* Custom filtering */
  3795. _fnFilterCustom( oSettings );
  3796. }
  3797. else
  3798. {
  3799. fnSaveFilter( oInput );
  3800. }
  3801. /* Tell the draw function we have been filtering */
  3802. oSettings.bFiltered = true;
  3803. _fnCallbackFire( oSettings, null, 'search', [oSettings] );
  3804. }
  3805. /**
  3806. * Apply custom filtering functions
  3807. * @param {object} oSettings dataTables settings object
  3808. * @memberof DataTable#oApi
  3809. */
  3810. function _fnFilterCustom( settings )
  3811. {
  3812. var filters = DataTable.ext.search;
  3813. var displayRows = settings.aiDisplay;
  3814. var row, rowIdx;
  3815. for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
  3816. var rows = [];
  3817. // Loop over each row and see if it should be included
  3818. for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
  3819. rowIdx = displayRows[ j ];
  3820. row = settings.aoData[ rowIdx ];
  3821. if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
  3822. rows.push( rowIdx );
  3823. }
  3824. }
  3825. // So the array reference doesn't break set the results into the
  3826. // existing array
  3827. displayRows.length = 0;
  3828. $.merge( displayRows, rows );
  3829. }
  3830. }
  3831. /**
  3832. * Filter the table on a per-column basis
  3833. * @param {object} oSettings dataTables settings object
  3834. * @param {string} sInput string to filter on
  3835. * @param {int} iColumn column to filter
  3836. * @param {bool} bRegex treat search string as a regular expression or not
  3837. * @param {bool} bSmart use smart filtering or not
  3838. * @param {bool} bCaseInsensitive Do case insensitive matching or not
  3839. * @memberof DataTable#oApi
  3840. */
  3841. function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
  3842. {
  3843. if ( searchStr === '' ) {
  3844. return;
  3845. }
  3846. var data;
  3847. var out = [];
  3848. var display = settings.aiDisplay;
  3849. var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
  3850. for ( var i=0 ; i<display.length ; i++ ) {
  3851. data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
  3852. if ( rpSearch.test( data ) ) {
  3853. out.push( display[i] );
  3854. }
  3855. }
  3856. settings.aiDisplay = out;
  3857. }
  3858. /**
  3859. * Filter the data table based on user input and draw the table
  3860. * @param {object} settings dataTables settings object
  3861. * @param {string} input string to filter on
  3862. * @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
  3863. * @param {bool} regex treat as a regular expression or not
  3864. * @param {bool} smart perform smart filtering or not
  3865. * @param {bool} caseInsensitive Do case insensitive matching or not
  3866. * @memberof DataTable#oApi
  3867. */
  3868. function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
  3869. {
  3870. var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
  3871. var prevSearch = settings.oPreviousSearch.sSearch;
  3872. var displayMaster = settings.aiDisplayMaster;
  3873. var display, invalidated, i;
  3874. var filtered = [];
  3875. // Need to take account of custom filtering functions - always filter
  3876. if ( DataTable.ext.search.length !== 0 ) {
  3877. force = true;
  3878. }
  3879. // Check if any of the rows were invalidated
  3880. invalidated = _fnFilterData( settings );
  3881. // If the input is blank - we just want the full data set
  3882. if ( input.length <= 0 ) {
  3883. settings.aiDisplay = displayMaster.slice();
  3884. }
  3885. else {
  3886. // New search - start from the master array
  3887. if ( invalidated ||
  3888. force ||
  3889. regex ||
  3890. prevSearch.length > input.length ||
  3891. input.indexOf(prevSearch) !== 0 ||
  3892. settings.bSorted // On resort, the display master needs to be
  3893. // re-filtered since indexes will have changed
  3894. ) {
  3895. settings.aiDisplay = displayMaster.slice();
  3896. }
  3897. // Search the display array
  3898. display = settings.aiDisplay;
  3899. for ( i=0 ; i<display.length ; i++ ) {
  3900. if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
  3901. filtered.push( display[i] );
  3902. }
  3903. }
  3904. settings.aiDisplay = filtered;
  3905. }
  3906. }
  3907. /**
  3908. * Build a regular expression object suitable for searching a table
  3909. * @param {string} sSearch string to search for
  3910. * @param {bool} bRegex treat as a regular expression or not
  3911. * @param {bool} bSmart perform smart filtering or not
  3912. * @param {bool} bCaseInsensitive Do case insensitive matching or not
  3913. * @returns {RegExp} constructed object
  3914. * @memberof DataTable#oApi
  3915. */
  3916. function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
  3917. {
  3918. search = regex ?
  3919. search :
  3920. _fnEscapeRegex( search );
  3921. if ( smart ) {
  3922. /* For smart filtering we want to allow the search to work regardless of
  3923. * word order. We also want double quoted text to be preserved, so word
  3924. * order is important - a la google. So this is what we want to
  3925. * generate:
  3926. *
  3927. * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
  3928. */
  3929. var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
  3930. if ( word.charAt(0) === '"' ) {
  3931. var m = word.match( /^"(.*)"$/ );
  3932. word = m ? m[1] : word;
  3933. }
  3934. return word.replace('"', '');
  3935. } );
  3936. search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
  3937. }
  3938. return new RegExp( search, caseInsensitive ? 'i' : '' );
  3939. }
  3940. /**
  3941. * Escape a string such that it can be used in a regular expression
  3942. * @param {string} sVal string to escape
  3943. * @returns {string} escaped string
  3944. * @memberof DataTable#oApi
  3945. */
  3946. var _fnEscapeRegex = DataTable.util.escapeRegex;
  3947. var __filter_div = $('<div>')[0];
  3948. var __filter_div_textContent = __filter_div.textContent !== undefined;
  3949. // Update the filtering data for each row if needed (by invalidation or first run)
  3950. function _fnFilterData ( settings )
  3951. {
  3952. var columns = settings.aoColumns;
  3953. var column;
  3954. var i, j, ien, jen, filterData, cellData, row;
  3955. var wasInvalidated = false;
  3956. for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  3957. row = settings.aoData[i];
  3958. if ( ! row._aFilterData ) {
  3959. filterData = [];
  3960. for ( j=0, jen=columns.length ; j<jen ; j++ ) {
  3961. column = columns[j];
  3962. if ( column.bSearchable ) {
  3963. cellData = _fnGetCellData( settings, i, j, 'filter' );
  3964. // Search in DataTables 1.10 is string based. In 1.11 this
  3965. // should be altered to also allow strict type checking.
  3966. if ( cellData === null ) {
  3967. cellData = '';
  3968. }
  3969. if ( typeof cellData !== 'string' && cellData.toString ) {
  3970. cellData = cellData.toString();
  3971. }
  3972. }
  3973. else {
  3974. cellData = '';
  3975. }
  3976. // If it looks like there is an HTML entity in the string,
  3977. // attempt to decode it so sorting works as expected. Note that
  3978. // we could use a single line of jQuery to do this, but the DOM
  3979. // method used here is much faster http://jsperf.com/html-decode
  3980. if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
  3981. __filter_div.innerHTML = cellData;
  3982. cellData = __filter_div_textContent ?
  3983. __filter_div.textContent :
  3984. __filter_div.innerText;
  3985. }
  3986. if ( cellData.replace ) {
  3987. cellData = cellData.replace(/[\r\n\u2028]/g, '');
  3988. }
  3989. filterData.push( cellData );
  3990. }
  3991. row._aFilterData = filterData;
  3992. row._sFilterRow = filterData.join(' ');
  3993. wasInvalidated = true;
  3994. }
  3995. }
  3996. return wasInvalidated;
  3997. }
  3998. /**
  3999. * Convert from the internal Hungarian notation to camelCase for external
  4000. * interaction
  4001. * @param {object} obj Object to convert
  4002. * @returns {object} Inverted object
  4003. * @memberof DataTable#oApi
  4004. */
  4005. function _fnSearchToCamel ( obj )
  4006. {
  4007. return {
  4008. search: obj.sSearch,
  4009. smart: obj.bSmart,
  4010. regex: obj.bRegex,
  4011. caseInsensitive: obj.bCaseInsensitive
  4012. };
  4013. }
  4014. /**
  4015. * Convert from camelCase notation to the internal Hungarian. We could use the
  4016. * Hungarian convert function here, but this is cleaner
  4017. * @param {object} obj Object to convert
  4018. * @returns {object} Inverted object
  4019. * @memberof DataTable#oApi
  4020. */
  4021. function _fnSearchToHung ( obj )
  4022. {
  4023. return {
  4024. sSearch: obj.search,
  4025. bSmart: obj.smart,
  4026. bRegex: obj.regex,
  4027. bCaseInsensitive: obj.caseInsensitive
  4028. };
  4029. }
  4030. /**
  4031. * Generate the node required for the info display
  4032. * @param {object} oSettings dataTables settings object
  4033. * @returns {node} Information element
  4034. * @memberof DataTable#oApi
  4035. */
  4036. function _fnFeatureHtmlInfo ( settings )
  4037. {
  4038. var
  4039. tid = settings.sTableId,
  4040. nodes = settings.aanFeatures.i,
  4041. n = $('<div/>', {
  4042. 'class': settings.oClasses.sInfo,
  4043. 'id': ! nodes ? tid+'_info' : null
  4044. } );
  4045. if ( ! nodes ) {
  4046. // Update display on each draw
  4047. settings.aoDrawCallback.push( {
  4048. "fn": _fnUpdateInfo,
  4049. "sName": "information"
  4050. } );
  4051. n
  4052. .attr( 'role', 'status' )
  4053. .attr( 'aria-live', 'polite' );
  4054. // Table is described by our info div
  4055. $(settings.nTable).attr( 'aria-describedby', tid+'_info' );
  4056. }
  4057. return n[0];
  4058. }
  4059. /**
  4060. * Update the information elements in the display
  4061. * @param {object} settings dataTables settings object
  4062. * @memberof DataTable#oApi
  4063. */
  4064. function _fnUpdateInfo ( settings )
  4065. {
  4066. /* Show information about the table */
  4067. var nodes = settings.aanFeatures.i;
  4068. if ( nodes.length === 0 ) {
  4069. return;
  4070. }
  4071. var
  4072. lang = settings.oLanguage,
  4073. start = settings._iDisplayStart+1,
  4074. end = settings.fnDisplayEnd(),
  4075. max = settings.fnRecordsTotal(),
  4076. total = settings.fnRecordsDisplay(),
  4077. out = total ?
  4078. lang.sInfo :
  4079. lang.sInfoEmpty;
  4080. if ( total !== max ) {
  4081. /* Record set after filtering */
  4082. out += ' ' + lang.sInfoFiltered;
  4083. }
  4084. // Convert the macros
  4085. out += lang.sInfoPostFix;
  4086. out = _fnInfoMacros( settings, out );
  4087. var callback = lang.fnInfoCallback;
  4088. if ( callback !== null ) {
  4089. out = callback.call( settings.oInstance,
  4090. settings, start, end, max, total, out
  4091. );
  4092. }
  4093. $(nodes).html( out );
  4094. }
  4095. function _fnInfoMacros ( settings, str )
  4096. {
  4097. // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
  4098. // internally
  4099. var
  4100. formatter = settings.fnFormatNumber,
  4101. start = settings._iDisplayStart+1,
  4102. len = settings._iDisplayLength,
  4103. vis = settings.fnRecordsDisplay(),
  4104. all = len === -1;
  4105. return str.
  4106. replace(/_START_/g, formatter.call( settings, start ) ).
  4107. replace(/_END_/g, formatter.call( settings, settings.fnDisplayEnd() ) ).
  4108. replace(/_MAX_/g, formatter.call( settings, settings.fnRecordsTotal() ) ).
  4109. replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
  4110. replace(/_PAGE_/g, formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
  4111. replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
  4112. }
  4113. /**
  4114. * Draw the table for the first time, adding all required features
  4115. * @param {object} settings dataTables settings object
  4116. * @memberof DataTable#oApi
  4117. */
  4118. function _fnInitialise ( settings )
  4119. {
  4120. var i, iLen, iAjaxStart=settings.iInitDisplayStart;
  4121. var columns = settings.aoColumns, column;
  4122. var features = settings.oFeatures;
  4123. var deferLoading = settings.bDeferLoading; // value modified by the draw
  4124. /* Ensure that the table data is fully initialised */
  4125. if ( ! settings.bInitialised ) {
  4126. setTimeout( function(){ _fnInitialise( settings ); }, 200 );
  4127. return;
  4128. }
  4129. /* Show the display HTML options */
  4130. _fnAddOptionsHtml( settings );
  4131. /* Build and draw the header / footer for the table */
  4132. _fnBuildHead( settings );
  4133. _fnDrawHead( settings, settings.aoHeader );
  4134. _fnDrawHead( settings, settings.aoFooter );
  4135. /* Okay to show that something is going on now */
  4136. _fnProcessingDisplay( settings, true );
  4137. /* Calculate sizes for columns */
  4138. if ( features.bAutoWidth ) {
  4139. _fnCalculateColumnWidths( settings );
  4140. }
  4141. for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
  4142. column = columns[i];
  4143. if ( column.sWidth ) {
  4144. column.nTh.style.width = _fnStringToCss( column.sWidth );
  4145. }
  4146. }
  4147. _fnCallbackFire( settings, null, 'preInit', [settings] );
  4148. // If there is default sorting required - let's do it. The sort function
  4149. // will do the drawing for us. Otherwise we draw the table regardless of the
  4150. // Ajax source - this allows the table to look initialised for Ajax sourcing
  4151. // data (show 'loading' message possibly)
  4152. _fnReDraw( settings );
  4153. // Server-side processing init complete is done by _fnAjaxUpdateDraw
  4154. var dataSrc = _fnDataSource( settings );
  4155. if ( dataSrc != 'ssp' || deferLoading ) {
  4156. // if there is an ajax source load the data
  4157. if ( dataSrc == 'ajax' ) {
  4158. _fnBuildAjax( settings, [], function(json) {
  4159. var aData = _fnAjaxDataSrc( settings, json );
  4160. // Got the data - add it to the table
  4161. for ( i=0 ; i<aData.length ; i++ ) {
  4162. _fnAddData( settings, aData[i] );
  4163. }
  4164. // Reset the init display for cookie saving. We've already done
  4165. // a filter, and therefore cleared it before. So we need to make
  4166. // it appear 'fresh'
  4167. settings.iInitDisplayStart = iAjaxStart;
  4168. _fnReDraw( settings );
  4169. _fnProcessingDisplay( settings, false );
  4170. _fnInitComplete( settings, json );
  4171. }, settings );
  4172. }
  4173. else {
  4174. _fnProcessingDisplay( settings, false );
  4175. _fnInitComplete( settings );
  4176. }
  4177. }
  4178. }
  4179. /**
  4180. * Draw the table for the first time, adding all required features
  4181. * @param {object} oSettings dataTables settings object
  4182. * @param {object} [json] JSON from the server that completed the table, if using Ajax source
  4183. * with client-side processing (optional)
  4184. * @memberof DataTable#oApi
  4185. */
  4186. function _fnInitComplete ( settings, json )
  4187. {
  4188. settings._bInitComplete = true;
  4189. // When data was added after the initialisation (data or Ajax) we need to
  4190. // calculate the column sizing
  4191. if ( json || settings.oInit.aaData ) {
  4192. _fnAdjustColumnSizing( settings );
  4193. }
  4194. _fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
  4195. _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
  4196. }
  4197. function _fnLengthChange ( settings, val )
  4198. {
  4199. var len = parseInt( val, 10 );
  4200. settings._iDisplayLength = len;
  4201. _fnLengthOverflow( settings );
  4202. // Fire length change event
  4203. _fnCallbackFire( settings, null, 'length', [settings, len] );
  4204. }
  4205. /**
  4206. * Generate the node required for user display length changing
  4207. * @param {object} settings dataTables settings object
  4208. * @returns {node} Display length feature node
  4209. * @memberof DataTable#oApi
  4210. */
  4211. function _fnFeatureHtmlLength ( settings )
  4212. {
  4213. var
  4214. classes = settings.oClasses,
  4215. tableId = settings.sTableId,
  4216. menu = settings.aLengthMenu,
  4217. d2 = Array.isArray( menu[0] ),
  4218. lengths = d2 ? menu[0] : menu,
  4219. language = d2 ? menu[1] : menu;
  4220. var select = $('<select/>', {
  4221. 'name': tableId+'_length',
  4222. 'aria-controls': tableId,
  4223. 'class': classes.sLengthSelect
  4224. } );
  4225. for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
  4226. select[0][ i ] = new Option(
  4227. typeof language[i] === 'number' ?
  4228. settings.fnFormatNumber( language[i] ) :
  4229. language[i],
  4230. lengths[i]
  4231. );
  4232. }
  4233. var div = $('<div><label/></div>').addClass( classes.sLength );
  4234. if ( ! settings.aanFeatures.l ) {
  4235. div[0].id = tableId+'_length';
  4236. }
  4237. div.children().append(
  4238. settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
  4239. );
  4240. // Can't use `select` variable as user might provide their own and the
  4241. // reference is broken by the use of outerHTML
  4242. $('select', div)
  4243. .val( settings._iDisplayLength )
  4244. .on( 'change.DT', function(e) {
  4245. _fnLengthChange( settings, $(this).val() );
  4246. _fnDraw( settings );
  4247. } );
  4248. // Update node value whenever anything changes the table's length
  4249. $(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
  4250. if ( settings === s ) {
  4251. $('select', div).val( len );
  4252. }
  4253. } );
  4254. return div[0];
  4255. }
  4256. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  4257. * Note that most of the paging logic is done in
  4258. * DataTable.ext.pager
  4259. */
  4260. /**
  4261. * Generate the node required for default pagination
  4262. * @param {object} oSettings dataTables settings object
  4263. * @returns {node} Pagination feature node
  4264. * @memberof DataTable#oApi
  4265. */
  4266. function _fnFeatureHtmlPaginate ( settings )
  4267. {
  4268. var
  4269. type = settings.sPaginationType,
  4270. plugin = DataTable.ext.pager[ type ],
  4271. modern = typeof plugin === 'function',
  4272. redraw = function( settings ) {
  4273. _fnDraw( settings );
  4274. },
  4275. node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
  4276. features = settings.aanFeatures;
  4277. if ( ! modern ) {
  4278. plugin.fnInit( settings, node, redraw );
  4279. }
  4280. /* Add a draw callback for the pagination on first instance, to update the paging display */
  4281. if ( ! features.p )
  4282. {
  4283. node.id = settings.sTableId+'_paginate';
  4284. settings.aoDrawCallback.push( {
  4285. "fn": function( settings ) {
  4286. if ( modern ) {
  4287. var
  4288. start = settings._iDisplayStart,
  4289. len = settings._iDisplayLength,
  4290. visRecords = settings.fnRecordsDisplay(),
  4291. all = len === -1,
  4292. page = all ? 0 : Math.ceil( start / len ),
  4293. pages = all ? 1 : Math.ceil( visRecords / len ),
  4294. buttons = plugin(page, pages),
  4295. i, ien;
  4296. for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
  4297. _fnRenderer( settings, 'pageButton' )(
  4298. settings, features.p[i], i, buttons, page, pages
  4299. );
  4300. }
  4301. }
  4302. else {
  4303. plugin.fnUpdate( settings, redraw );
  4304. }
  4305. },
  4306. "sName": "pagination"
  4307. } );
  4308. }
  4309. return node;
  4310. }
  4311. /**
  4312. * Alter the display settings to change the page
  4313. * @param {object} settings DataTables settings object
  4314. * @param {string|int} action Paging action to take: "first", "previous",
  4315. * "next" or "last" or page number to jump to (integer)
  4316. * @param [bool] redraw Automatically draw the update or not
  4317. * @returns {bool} true page has changed, false - no change
  4318. * @memberof DataTable#oApi
  4319. */
  4320. function _fnPageChange ( settings, action, redraw )
  4321. {
  4322. var
  4323. start = settings._iDisplayStart,
  4324. len = settings._iDisplayLength,
  4325. records = settings.fnRecordsDisplay();
  4326. if ( records === 0 || len === -1 )
  4327. {
  4328. start = 0;
  4329. }
  4330. else if ( typeof action === "number" )
  4331. {
  4332. start = action * len;
  4333. if ( start > records )
  4334. {
  4335. start = 0;
  4336. }
  4337. }
  4338. else if ( action == "first" )
  4339. {
  4340. start = 0;
  4341. }
  4342. else if ( action == "previous" )
  4343. {
  4344. start = len >= 0 ?
  4345. start - len :
  4346. 0;
  4347. if ( start < 0 )
  4348. {
  4349. start = 0;
  4350. }
  4351. }
  4352. else if ( action == "next" )
  4353. {
  4354. if ( start + len < records )
  4355. {
  4356. start += len;
  4357. }
  4358. }
  4359. else if ( action == "last" )
  4360. {
  4361. start = Math.floor( (records-1) / len) * len;
  4362. }
  4363. else
  4364. {
  4365. _fnLog( settings, 0, "Unknown paging action: "+action, 5 );
  4366. }
  4367. var changed = settings._iDisplayStart !== start;
  4368. settings._iDisplayStart = start;
  4369. if ( changed ) {
  4370. _fnCallbackFire( settings, null, 'page', [settings] );
  4371. if ( redraw ) {
  4372. _fnDraw( settings );
  4373. }
  4374. }
  4375. return changed;
  4376. }
  4377. /**
  4378. * Generate the node required for the processing node
  4379. * @param {object} settings dataTables settings object
  4380. * @returns {node} Processing element
  4381. * @memberof DataTable#oApi
  4382. */
  4383. function _fnFeatureHtmlProcessing ( settings )
  4384. {
  4385. return $('<div/>', {
  4386. 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
  4387. 'class': settings.oClasses.sProcessing
  4388. } )
  4389. .html( settings.oLanguage.sProcessing )
  4390. .append('<div><div></div><div></div><div></div><div></div></div>')
  4391. .insertBefore( settings.nTable )[0];
  4392. }
  4393. /**
  4394. * Display or hide the processing indicator
  4395. * @param {object} settings dataTables settings object
  4396. * @param {bool} show Show the processing indicator (true) or not (false)
  4397. * @memberof DataTable#oApi
  4398. */
  4399. function _fnProcessingDisplay ( settings, show )
  4400. {
  4401. if ( settings.oFeatures.bProcessing ) {
  4402. $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
  4403. }
  4404. _fnCallbackFire( settings, null, 'processing', [settings, show] );
  4405. }
  4406. /**
  4407. * Add any control elements for the table - specifically scrolling
  4408. * @param {object} settings dataTables settings object
  4409. * @returns {node} Node to add to the DOM
  4410. * @memberof DataTable#oApi
  4411. */
  4412. function _fnFeatureHtmlTable ( settings )
  4413. {
  4414. var table = $(settings.nTable);
  4415. // Scrolling from here on in
  4416. var scroll = settings.oScroll;
  4417. if ( scroll.sX === '' && scroll.sY === '' ) {
  4418. return settings.nTable;
  4419. }
  4420. var scrollX = scroll.sX;
  4421. var scrollY = scroll.sY;
  4422. var classes = settings.oClasses;
  4423. var caption = table.children('caption');
  4424. var captionSide = caption.length ? caption[0]._captionSide : null;
  4425. var headerClone = $( table[0].cloneNode(false) );
  4426. var footerClone = $( table[0].cloneNode(false) );
  4427. var footer = table.children('tfoot');
  4428. var _div = '<div/>';
  4429. var size = function ( s ) {
  4430. return !s ? null : _fnStringToCss( s );
  4431. };
  4432. if ( ! footer.length ) {
  4433. footer = null;
  4434. }
  4435. /*
  4436. * The HTML structure that we want to generate in this function is:
  4437. * div - scroller
  4438. * div - scroll head
  4439. * div - scroll head inner
  4440. * table - scroll head table
  4441. * thead - thead
  4442. * div - scroll body
  4443. * table - table (master table)
  4444. * thead - thead clone for sizing
  4445. * tbody - tbody
  4446. * div - scroll foot
  4447. * div - scroll foot inner
  4448. * table - scroll foot table
  4449. * tfoot - tfoot
  4450. */
  4451. var scroller = $( _div, { 'class': classes.sScrollWrapper } )
  4452. .append(
  4453. $(_div, { 'class': classes.sScrollHead } )
  4454. .css( {
  4455. overflow: 'hidden',
  4456. position: 'relative',
  4457. border: 0,
  4458. width: scrollX ? size(scrollX) : '100%'
  4459. } )
  4460. .append(
  4461. $(_div, { 'class': classes.sScrollHeadInner } )
  4462. .css( {
  4463. 'box-sizing': 'content-box',
  4464. width: scroll.sXInner || '100%'
  4465. } )
  4466. .append(
  4467. headerClone
  4468. .removeAttr('id')
  4469. .css( 'margin-left', 0 )
  4470. .append( captionSide === 'top' ? caption : null )
  4471. .append(
  4472. table.children('thead')
  4473. )
  4474. )
  4475. )
  4476. )
  4477. .append(
  4478. $(_div, { 'class': classes.sScrollBody } )
  4479. .css( {
  4480. position: 'relative',
  4481. overflow: 'auto',
  4482. width: size( scrollX )
  4483. } )
  4484. .append( table )
  4485. );
  4486. if ( footer ) {
  4487. scroller.append(
  4488. $(_div, { 'class': classes.sScrollFoot } )
  4489. .css( {
  4490. overflow: 'hidden',
  4491. border: 0,
  4492. width: scrollX ? size(scrollX) : '100%'
  4493. } )
  4494. .append(
  4495. $(_div, { 'class': classes.sScrollFootInner } )
  4496. .append(
  4497. footerClone
  4498. .removeAttr('id')
  4499. .css( 'margin-left', 0 )
  4500. .append( captionSide === 'bottom' ? caption : null )
  4501. .append(
  4502. table.children('tfoot')
  4503. )
  4504. )
  4505. )
  4506. );
  4507. }
  4508. var children = scroller.children();
  4509. var scrollHead = children[0];
  4510. var scrollBody = children[1];
  4511. var scrollFoot = footer ? children[2] : null;
  4512. // When the body is scrolled, then we also want to scroll the headers
  4513. if ( scrollX ) {
  4514. $(scrollBody).on( 'scroll.DT', function (e) {
  4515. var scrollLeft = this.scrollLeft;
  4516. scrollHead.scrollLeft = scrollLeft;
  4517. if ( footer ) {
  4518. scrollFoot.scrollLeft = scrollLeft;
  4519. }
  4520. } );
  4521. }
  4522. $(scrollBody).css('max-height', scrollY);
  4523. if (! scroll.bCollapse) {
  4524. $(scrollBody).css('height', scrollY);
  4525. }
  4526. settings.nScrollHead = scrollHead;
  4527. settings.nScrollBody = scrollBody;
  4528. settings.nScrollFoot = scrollFoot;
  4529. // On redraw - align columns
  4530. settings.aoDrawCallback.push( {
  4531. "fn": _fnScrollDraw,
  4532. "sName": "scrolling"
  4533. } );
  4534. return scroller[0];
  4535. }
  4536. /**
  4537. * Update the header, footer and body tables for resizing - i.e. column
  4538. * alignment.
  4539. *
  4540. * Welcome to the most horrible function DataTables. The process that this
  4541. * function follows is basically:
  4542. * 1. Re-create the table inside the scrolling div
  4543. * 2. Take live measurements from the DOM
  4544. * 3. Apply the measurements to align the columns
  4545. * 4. Clean up
  4546. *
  4547. * @param {object} settings dataTables settings object
  4548. * @memberof DataTable#oApi
  4549. */
  4550. function _fnScrollDraw ( settings )
  4551. {
  4552. // Given that this is such a monster function, a lot of variables are use
  4553. // to try and keep the minimised size as small as possible
  4554. var
  4555. scroll = settings.oScroll,
  4556. scrollX = scroll.sX,
  4557. scrollXInner = scroll.sXInner,
  4558. scrollY = scroll.sY,
  4559. barWidth = scroll.iBarWidth,
  4560. divHeader = $(settings.nScrollHead),
  4561. divHeaderStyle = divHeader[0].style,
  4562. divHeaderInner = divHeader.children('div'),
  4563. divHeaderInnerStyle = divHeaderInner[0].style,
  4564. divHeaderTable = divHeaderInner.children('table'),
  4565. divBodyEl = settings.nScrollBody,
  4566. divBody = $(divBodyEl),
  4567. divBodyStyle = divBodyEl.style,
  4568. divFooter = $(settings.nScrollFoot),
  4569. divFooterInner = divFooter.children('div'),
  4570. divFooterTable = divFooterInner.children('table'),
  4571. header = $(settings.nTHead),
  4572. table = $(settings.nTable),
  4573. tableEl = table[0],
  4574. tableStyle = tableEl.style,
  4575. footer = settings.nTFoot ? $(settings.nTFoot) : null,
  4576. browser = settings.oBrowser,
  4577. ie67 = browser.bScrollOversize,
  4578. dtHeaderCells = _pluck( settings.aoColumns, 'nTh' ),
  4579. headerTrgEls, footerTrgEls,
  4580. headerSrcEls, footerSrcEls,
  4581. headerCopy, footerCopy,
  4582. headerWidths=[], footerWidths=[],
  4583. headerContent=[], footerContent=[],
  4584. idx, correction, sanityWidth,
  4585. zeroOut = function(nSizer) {
  4586. var style = nSizer.style;
  4587. style.paddingTop = "0";
  4588. style.paddingBottom = "0";
  4589. style.borderTopWidth = "0";
  4590. style.borderBottomWidth = "0";
  4591. style.height = 0;
  4592. };
  4593. // If the scrollbar visibility has changed from the last draw, we need to
  4594. // adjust the column sizes as the table width will have changed to account
  4595. // for the scrollbar
  4596. var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
  4597. if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
  4598. settings.scrollBarVis = scrollBarVis;
  4599. _fnAdjustColumnSizing( settings );
  4600. return; // adjust column sizing will call this function again
  4601. }
  4602. else {
  4603. settings.scrollBarVis = scrollBarVis;
  4604. }
  4605. /*
  4606. * 1. Re-create the table inside the scrolling div
  4607. */
  4608. // Remove the old minimised thead and tfoot elements in the inner table
  4609. table.children('thead, tfoot').remove();
  4610. if ( footer ) {
  4611. footerCopy = footer.clone().prependTo( table );
  4612. footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
  4613. footerSrcEls = footerCopy.find('tr');
  4614. }
  4615. // Clone the current header and footer elements and then place it into the inner table
  4616. headerCopy = header.clone().prependTo( table );
  4617. headerTrgEls = header.find('tr'); // original header is in its own table
  4618. headerSrcEls = headerCopy.find('tr');
  4619. headerCopy.find('th, td').removeAttr('tabindex');
  4620. /*
  4621. * 2. Take live measurements from the DOM - do not alter the DOM itself!
  4622. */
  4623. // Remove old sizing and apply the calculated column widths
  4624. // Get the unique column headers in the newly created (cloned) header. We want to apply the
  4625. // calculated sizes to this header
  4626. if ( ! scrollX )
  4627. {
  4628. divBodyStyle.width = '100%';
  4629. divHeader[0].style.width = '100%';
  4630. }
  4631. $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
  4632. idx = _fnVisibleToColumnIndex( settings, i );
  4633. el.style.width = settings.aoColumns[idx].sWidth;
  4634. } );
  4635. if ( footer ) {
  4636. _fnApplyToChildren( function(n) {
  4637. n.style.width = "";
  4638. }, footerSrcEls );
  4639. }
  4640. // Size the table as a whole
  4641. sanityWidth = table.outerWidth();
  4642. if ( scrollX === "" ) {
  4643. // No x scrolling
  4644. tableStyle.width = "100%";
  4645. // IE7 will make the width of the table when 100% include the scrollbar
  4646. // - which is shouldn't. When there is a scrollbar we need to take this
  4647. // into account.
  4648. if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
  4649. divBody.css('overflow-y') == "scroll")
  4650. ) {
  4651. tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
  4652. }
  4653. // Recalculate the sanity width
  4654. sanityWidth = table.outerWidth();
  4655. }
  4656. else if ( scrollXInner !== "" ) {
  4657. // legacy x scroll inner has been given - use it
  4658. tableStyle.width = _fnStringToCss(scrollXInner);
  4659. // Recalculate the sanity width
  4660. sanityWidth = table.outerWidth();
  4661. }
  4662. // Hidden header should have zero height, so remove padding and borders. Then
  4663. // set the width based on the real headers
  4664. // Apply all styles in one pass
  4665. _fnApplyToChildren( zeroOut, headerSrcEls );
  4666. // Read all widths in next pass
  4667. _fnApplyToChildren( function(nSizer) {
  4668. var style = window.getComputedStyle ?
  4669. window.getComputedStyle(nSizer).width :
  4670. _fnStringToCss( $(nSizer).width() );
  4671. headerContent.push( nSizer.innerHTML );
  4672. headerWidths.push( style );
  4673. }, headerSrcEls );
  4674. // Apply all widths in final pass
  4675. _fnApplyToChildren( function(nToSize, i) {
  4676. nToSize.style.width = headerWidths[i];
  4677. }, headerTrgEls );
  4678. $(headerSrcEls).css('height', 0);
  4679. /* Same again with the footer if we have one */
  4680. if ( footer )
  4681. {
  4682. _fnApplyToChildren( zeroOut, footerSrcEls );
  4683. _fnApplyToChildren( function(nSizer) {
  4684. footerContent.push( nSizer.innerHTML );
  4685. footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
  4686. }, footerSrcEls );
  4687. _fnApplyToChildren( function(nToSize, i) {
  4688. nToSize.style.width = footerWidths[i];
  4689. }, footerTrgEls );
  4690. $(footerSrcEls).height(0);
  4691. }
  4692. /*
  4693. * 3. Apply the measurements
  4694. */
  4695. // "Hide" the header and footer that we used for the sizing. We need to keep
  4696. // the content of the cell so that the width applied to the header and body
  4697. // both match, but we want to hide it completely. We want to also fix their
  4698. // width to what they currently are
  4699. _fnApplyToChildren( function(nSizer, i) {
  4700. nSizer.innerHTML = '<div class="dataTables_sizing">'+headerContent[i]+'</div>';
  4701. nSizer.childNodes[0].style.height = "0";
  4702. nSizer.childNodes[0].style.overflow = "hidden";
  4703. nSizer.style.width = headerWidths[i];
  4704. }, headerSrcEls );
  4705. if ( footer )
  4706. {
  4707. _fnApplyToChildren( function(nSizer, i) {
  4708. nSizer.innerHTML = '<div class="dataTables_sizing">'+footerContent[i]+'</div>';
  4709. nSizer.childNodes[0].style.height = "0";
  4710. nSizer.childNodes[0].style.overflow = "hidden";
  4711. nSizer.style.width = footerWidths[i];
  4712. }, footerSrcEls );
  4713. }
  4714. // Sanity check that the table is of a sensible width. If not then we are going to get
  4715. // misalignment - try to prevent this by not allowing the table to shrink below its min width
  4716. if ( Math.round(table.outerWidth()) < Math.round(sanityWidth) )
  4717. {
  4718. // The min width depends upon if we have a vertical scrollbar visible or not */
  4719. correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
  4720. divBody.css('overflow-y') == "scroll")) ?
  4721. sanityWidth+barWidth :
  4722. sanityWidth;
  4723. // IE6/7 are a law unto themselves...
  4724. if ( ie67 && (divBodyEl.scrollHeight >
  4725. divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
  4726. ) {
  4727. tableStyle.width = _fnStringToCss( correction-barWidth );
  4728. }
  4729. // And give the user a warning that we've stopped the table getting too small
  4730. if ( scrollX === "" || scrollXInner !== "" ) {
  4731. _fnLog( settings, 1, 'Possible column misalignment', 6 );
  4732. }
  4733. }
  4734. else
  4735. {
  4736. correction = '100%';
  4737. }
  4738. // Apply to the container elements
  4739. divBodyStyle.width = _fnStringToCss( correction );
  4740. divHeaderStyle.width = _fnStringToCss( correction );
  4741. if ( footer ) {
  4742. settings.nScrollFoot.style.width = _fnStringToCss( correction );
  4743. }
  4744. /*
  4745. * 4. Clean up
  4746. */
  4747. if ( ! scrollY ) {
  4748. /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
  4749. * the scrollbar height from the visible display, rather than adding it on. We need to
  4750. * set the height in order to sort this. Don't want to do it in any other browsers.
  4751. */
  4752. if ( ie67 ) {
  4753. divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
  4754. }
  4755. }
  4756. /* Finally set the width's of the header and footer tables */
  4757. var iOuterWidth = table.outerWidth();
  4758. divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
  4759. divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
  4760. // Figure out if there are scrollbar present - if so then we need a the header and footer to
  4761. // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
  4762. var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
  4763. var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
  4764. divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
  4765. if ( footer ) {
  4766. divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
  4767. divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
  4768. divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
  4769. }
  4770. // Correct DOM ordering for colgroup - comes before the thead
  4771. table.children('colgroup').insertBefore( table.children('thead') );
  4772. /* Adjust the position of the header in case we loose the y-scrollbar */
  4773. divBody.trigger('scroll');
  4774. // If sorting or filtering has occurred, jump the scrolling back to the top
  4775. // only if we aren't holding the position
  4776. if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
  4777. divBodyEl.scrollTop = 0;
  4778. }
  4779. }
  4780. /**
  4781. * Apply a given function to the display child nodes of an element array (typically
  4782. * TD children of TR rows
  4783. * @param {function} fn Method to apply to the objects
  4784. * @param array {nodes} an1 List of elements to look through for display children
  4785. * @param array {nodes} an2 Another list (identical structure to the first) - optional
  4786. * @memberof DataTable#oApi
  4787. */
  4788. function _fnApplyToChildren( fn, an1, an2 )
  4789. {
  4790. var index=0, i=0, iLen=an1.length;
  4791. var nNode1, nNode2;
  4792. while ( i < iLen ) {
  4793. nNode1 = an1[i].firstChild;
  4794. nNode2 = an2 ? an2[i].firstChild : null;
  4795. while ( nNode1 ) {
  4796. if ( nNode1.nodeType === 1 ) {
  4797. if ( an2 ) {
  4798. fn( nNode1, nNode2, index );
  4799. }
  4800. else {
  4801. fn( nNode1, index );
  4802. }
  4803. index++;
  4804. }
  4805. nNode1 = nNode1.nextSibling;
  4806. nNode2 = an2 ? nNode2.nextSibling : null;
  4807. }
  4808. i++;
  4809. }
  4810. }
  4811. var __re_html_remove = /<.*?>/g;
  4812. /**
  4813. * Calculate the width of columns for the table
  4814. * @param {object} oSettings dataTables settings object
  4815. * @memberof DataTable#oApi
  4816. */
  4817. function _fnCalculateColumnWidths ( oSettings )
  4818. {
  4819. var
  4820. table = oSettings.nTable,
  4821. columns = oSettings.aoColumns,
  4822. scroll = oSettings.oScroll,
  4823. scrollY = scroll.sY,
  4824. scrollX = scroll.sX,
  4825. scrollXInner = scroll.sXInner,
  4826. columnCount = columns.length,
  4827. visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
  4828. headerCells = $('th', oSettings.nTHead),
  4829. tableWidthAttr = table.getAttribute('width'), // from DOM element
  4830. tableContainer = table.parentNode,
  4831. userInputs = false,
  4832. i, column, columnIdx, width, outerWidth,
  4833. browser = oSettings.oBrowser,
  4834. ie67 = browser.bScrollOversize;
  4835. var styleWidth = table.style.width;
  4836. if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
  4837. tableWidthAttr = styleWidth;
  4838. }
  4839. /* Convert any user input sizes into pixel sizes */
  4840. for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4841. column = columns[ visibleColumns[i] ];
  4842. if ( column.sWidth !== null ) {
  4843. column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
  4844. userInputs = true;
  4845. }
  4846. }
  4847. /* If the number of columns in the DOM equals the number that we have to
  4848. * process in DataTables, then we can use the offsets that are created by
  4849. * the web- browser. No custom sizes can be set in order for this to happen,
  4850. * nor scrolling used
  4851. */
  4852. if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
  4853. columnCount == _fnVisbleColumns( oSettings ) &&
  4854. columnCount == headerCells.length
  4855. ) {
  4856. for ( i=0 ; i<columnCount ; i++ ) {
  4857. var colIdx = _fnVisibleToColumnIndex( oSettings, i );
  4858. if ( colIdx !== null ) {
  4859. columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
  4860. }
  4861. }
  4862. }
  4863. else
  4864. {
  4865. // Otherwise construct a single row, worst case, table with the widest
  4866. // node in the data, assign any user defined widths, then insert it into
  4867. // the DOM and allow the browser to do all the hard work of calculating
  4868. // table widths
  4869. var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
  4870. .css( 'visibility', 'hidden' )
  4871. .removeAttr( 'id' );
  4872. // Clean up the table body
  4873. tmpTable.find('tbody tr').remove();
  4874. var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
  4875. // Clone the table header and footer - we can't use the header / footer
  4876. // from the cloned table, since if scrolling is active, the table's
  4877. // real header and footer are contained in different table tags
  4878. tmpTable.find('thead, tfoot').remove();
  4879. tmpTable
  4880. .append( $(oSettings.nTHead).clone() )
  4881. .append( $(oSettings.nTFoot).clone() );
  4882. // Remove any assigned widths from the footer (from scrolling)
  4883. tmpTable.find('tfoot th, tfoot td').css('width', '');
  4884. // Apply custom sizing to the cloned header
  4885. headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
  4886. for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4887. column = columns[ visibleColumns[i] ];
  4888. headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
  4889. _fnStringToCss( column.sWidthOrig ) :
  4890. '';
  4891. // For scrollX we need to force the column width otherwise the
  4892. // browser will collapse it. If this width is smaller than the
  4893. // width the column requires, then it will have no effect
  4894. if ( column.sWidthOrig && scrollX ) {
  4895. $( headerCells[i] ).append( $('<div/>').css( {
  4896. width: column.sWidthOrig,
  4897. margin: 0,
  4898. padding: 0,
  4899. border: 0,
  4900. height: 1
  4901. } ) );
  4902. }
  4903. }
  4904. // Find the widest cell for each column and put it into the table
  4905. if ( oSettings.aoData.length ) {
  4906. for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4907. columnIdx = visibleColumns[i];
  4908. column = columns[ columnIdx ];
  4909. $( _fnGetWidestNode( oSettings, columnIdx ) )
  4910. .clone( false )
  4911. .append( column.sContentPadding )
  4912. .appendTo( tr );
  4913. }
  4914. }
  4915. // Tidy the temporary table - remove name attributes so there aren't
  4916. // duplicated in the dom (radio elements for example)
  4917. $('[name]', tmpTable).removeAttr('name');
  4918. // Table has been built, attach to the document so we can work with it.
  4919. // A holding element is used, positioned at the top of the container
  4920. // with minimal height, so it has no effect on if the container scrolls
  4921. // or not. Otherwise it might trigger scrolling when it actually isn't
  4922. // needed
  4923. var holder = $('<div/>').css( scrollX || scrollY ?
  4924. {
  4925. position: 'absolute',
  4926. top: 0,
  4927. left: 0,
  4928. height: 1,
  4929. right: 0,
  4930. overflow: 'hidden'
  4931. } :
  4932. {}
  4933. )
  4934. .append( tmpTable )
  4935. .appendTo( tableContainer );
  4936. // When scrolling (X or Y) we want to set the width of the table as
  4937. // appropriate. However, when not scrolling leave the table width as it
  4938. // is. This results in slightly different, but I think correct behaviour
  4939. if ( scrollX && scrollXInner ) {
  4940. tmpTable.width( scrollXInner );
  4941. }
  4942. else if ( scrollX ) {
  4943. tmpTable.css( 'width', 'auto' );
  4944. tmpTable.removeAttr('width');
  4945. // If there is no width attribute or style, then allow the table to
  4946. // collapse
  4947. if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
  4948. tmpTable.width( tableContainer.clientWidth );
  4949. }
  4950. }
  4951. else if ( scrollY ) {
  4952. tmpTable.width( tableContainer.clientWidth );
  4953. }
  4954. else if ( tableWidthAttr ) {
  4955. tmpTable.width( tableWidthAttr );
  4956. }
  4957. // Get the width of each column in the constructed table - we need to
  4958. // know the inner width (so it can be assigned to the other table's
  4959. // cells) and the outer width so we can calculate the full width of the
  4960. // table. This is safe since DataTables requires a unique cell for each
  4961. // column, but if ever a header can span multiple columns, this will
  4962. // need to be modified.
  4963. var total = 0;
  4964. for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4965. var cell = $(headerCells[i]);
  4966. var border = cell.outerWidth() - cell.width();
  4967. // Use getBounding... where possible (not IE8-) because it can give
  4968. // sub-pixel accuracy, which we then want to round up!
  4969. var bounding = browser.bBounding ?
  4970. Math.ceil( headerCells[i].getBoundingClientRect().width ) :
  4971. cell.outerWidth();
  4972. // Total is tracked to remove any sub-pixel errors as the outerWidth
  4973. // of the table might not equal the total given here (IE!).
  4974. total += bounding;
  4975. // Width for each column to use
  4976. columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
  4977. }
  4978. table.style.width = _fnStringToCss( total );
  4979. // Finished with the table - ditch it
  4980. holder.remove();
  4981. }
  4982. // If there is a width attr, we want to attach an event listener which
  4983. // allows the table sizing to automatically adjust when the window is
  4984. // resized. Use the width attr rather than CSS, since we can't know if the
  4985. // CSS is a relative value or absolute - DOM read is always px.
  4986. if ( tableWidthAttr ) {
  4987. table.style.width = _fnStringToCss( tableWidthAttr );
  4988. }
  4989. if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
  4990. var bindResize = function () {
  4991. $(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
  4992. _fnAdjustColumnSizing( oSettings );
  4993. } ) );
  4994. };
  4995. // IE6/7 will crash if we bind a resize event handler on page load.
  4996. // To be removed in 1.11 which drops IE6/7 support
  4997. if ( ie67 ) {
  4998. setTimeout( bindResize, 1000 );
  4999. }
  5000. else {
  5001. bindResize();
  5002. }
  5003. oSettings._reszEvt = true;
  5004. }
  5005. }
  5006. /**
  5007. * Throttle the calls to a function. Arguments and context are maintained for
  5008. * the throttled function
  5009. * @param {function} fn Function to be called
  5010. * @param {int} [freq=200] call frequency in mS
  5011. * @returns {function} wrapped function
  5012. * @memberof DataTable#oApi
  5013. */
  5014. var _fnThrottle = DataTable.util.throttle;
  5015. /**
  5016. * Convert a CSS unit width to pixels (e.g. 2em)
  5017. * @param {string} width width to be converted
  5018. * @param {node} parent parent to get the with for (required for relative widths) - optional
  5019. * @returns {int} width in pixels
  5020. * @memberof DataTable#oApi
  5021. */
  5022. function _fnConvertToWidth ( width, parent )
  5023. {
  5024. if ( ! width ) {
  5025. return 0;
  5026. }
  5027. var n = $('<div/>')
  5028. .css( 'width', _fnStringToCss( width ) )
  5029. .appendTo( parent || document.body );
  5030. var val = n[0].offsetWidth;
  5031. n.remove();
  5032. return val;
  5033. }
  5034. /**
  5035. * Get the widest node
  5036. * @param {object} settings dataTables settings object
  5037. * @param {int} colIdx column of interest
  5038. * @returns {node} widest table node
  5039. * @memberof DataTable#oApi
  5040. */
  5041. function _fnGetWidestNode( settings, colIdx )
  5042. {
  5043. var idx = _fnGetMaxLenString( settings, colIdx );
  5044. if ( idx < 0 ) {
  5045. return null;
  5046. }
  5047. var data = settings.aoData[ idx ];
  5048. return ! data.nTr ? // Might not have been created when deferred rendering
  5049. $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
  5050. data.anCells[ colIdx ];
  5051. }
  5052. /**
  5053. * Get the maximum strlen for each data column
  5054. * @param {object} settings dataTables settings object
  5055. * @param {int} colIdx column of interest
  5056. * @returns {string} max string length for each column
  5057. * @memberof DataTable#oApi
  5058. */
  5059. function _fnGetMaxLenString( settings, colIdx )
  5060. {
  5061. var s, max=-1, maxIdx = -1;
  5062. for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  5063. s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
  5064. s = s.replace( __re_html_remove, '' );
  5065. s = s.replace( /&nbsp;/g, ' ' );
  5066. if ( s.length > max ) {
  5067. max = s.length;
  5068. maxIdx = i;
  5069. }
  5070. }
  5071. return maxIdx;
  5072. }
  5073. /**
  5074. * Append a CSS unit (only if required) to a string
  5075. * @param {string} value to css-ify
  5076. * @returns {string} value with css unit
  5077. * @memberof DataTable#oApi
  5078. */
  5079. function _fnStringToCss( s )
  5080. {
  5081. if ( s === null ) {
  5082. return '0px';
  5083. }
  5084. if ( typeof s == 'number' ) {
  5085. return s < 0 ?
  5086. '0px' :
  5087. s+'px';
  5088. }
  5089. // Check it has a unit character already
  5090. return s.match(/\d$/) ?
  5091. s+'px' :
  5092. s;
  5093. }
  5094. function _fnSortFlatten ( settings )
  5095. {
  5096. var
  5097. i, iLen, k, kLen,
  5098. aSort = [],
  5099. aiOrig = [],
  5100. aoColumns = settings.aoColumns,
  5101. aDataSort, iCol, sType, srcCol,
  5102. fixed = settings.aaSortingFixed,
  5103. fixedObj = $.isPlainObject( fixed ),
  5104. nestedSort = [],
  5105. add = function ( a ) {
  5106. if ( a.length && ! Array.isArray( a[0] ) ) {
  5107. // 1D array
  5108. nestedSort.push( a );
  5109. }
  5110. else {
  5111. // 2D array
  5112. $.merge( nestedSort, a );
  5113. }
  5114. };
  5115. // Build the sort array, with pre-fix and post-fix options if they have been
  5116. // specified
  5117. if ( Array.isArray( fixed ) ) {
  5118. add( fixed );
  5119. }
  5120. if ( fixedObj && fixed.pre ) {
  5121. add( fixed.pre );
  5122. }
  5123. add( settings.aaSorting );
  5124. if (fixedObj && fixed.post ) {
  5125. add( fixed.post );
  5126. }
  5127. for ( i=0 ; i<nestedSort.length ; i++ )
  5128. {
  5129. srcCol = nestedSort[i][0];
  5130. aDataSort = aoColumns[ srcCol ].aDataSort;
  5131. for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
  5132. {
  5133. iCol = aDataSort[k];
  5134. sType = aoColumns[ iCol ].sType || 'string';
  5135. if ( nestedSort[i]._idx === undefined ) {
  5136. nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
  5137. }
  5138. aSort.push( {
  5139. src: srcCol,
  5140. col: iCol,
  5141. dir: nestedSort[i][1],
  5142. index: nestedSort[i]._idx,
  5143. type: sType,
  5144. formatter: DataTable.ext.type.order[ sType+"-pre" ]
  5145. } );
  5146. }
  5147. }
  5148. return aSort;
  5149. }
  5150. /**
  5151. * Change the order of the table
  5152. * @param {object} oSettings dataTables settings object
  5153. * @memberof DataTable#oApi
  5154. * @todo This really needs split up!
  5155. */
  5156. function _fnSort ( oSettings )
  5157. {
  5158. var
  5159. i, ien, iLen, j, jLen, k, kLen,
  5160. sDataType, nTh,
  5161. aiOrig = [],
  5162. oExtSort = DataTable.ext.type.order,
  5163. aoData = oSettings.aoData,
  5164. aoColumns = oSettings.aoColumns,
  5165. aDataSort, data, iCol, sType, oSort,
  5166. formatters = 0,
  5167. sortCol,
  5168. displayMaster = oSettings.aiDisplayMaster,
  5169. aSort;
  5170. // Resolve any column types that are unknown due to addition or invalidation
  5171. // @todo Can this be moved into a 'data-ready' handler which is called when
  5172. // data is going to be used in the table?
  5173. _fnColumnTypes( oSettings );
  5174. aSort = _fnSortFlatten( oSettings );
  5175. for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
  5176. sortCol = aSort[i];
  5177. // Track if we can use the fast sort algorithm
  5178. if ( sortCol.formatter ) {
  5179. formatters++;
  5180. }
  5181. // Load the data needed for the sort, for each cell
  5182. _fnSortData( oSettings, sortCol.col );
  5183. }
  5184. /* No sorting required if server-side or no sorting array */
  5185. if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
  5186. {
  5187. // Create a value - key array of the current row positions such that we can use their
  5188. // current position during the sort, if values match, in order to perform stable sorting
  5189. for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
  5190. aiOrig[ displayMaster[i] ] = i;
  5191. }
  5192. /* Do the sort - here we want multi-column sorting based on a given data source (column)
  5193. * and sorting function (from oSort) in a certain direction. It's reasonably complex to
  5194. * follow on it's own, but this is what we want (example two column sorting):
  5195. * fnLocalSorting = function(a,b){
  5196. * var iTest;
  5197. * iTest = oSort['string-asc']('data11', 'data12');
  5198. * if (iTest !== 0)
  5199. * return iTest;
  5200. * iTest = oSort['numeric-desc']('data21', 'data22');
  5201. * if (iTest !== 0)
  5202. * return iTest;
  5203. * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
  5204. * }
  5205. * Basically we have a test for each sorting column, if the data in that column is equal,
  5206. * test the next column. If all columns match, then we use a numeric sort on the row
  5207. * positions in the original data array to provide a stable sort.
  5208. *
  5209. * Note - I know it seems excessive to have two sorting methods, but the first is around
  5210. * 15% faster, so the second is only maintained for backwards compatibility with sorting
  5211. * methods which do not have a pre-sort formatting function.
  5212. */
  5213. if ( formatters === aSort.length ) {
  5214. // All sort types have formatting functions
  5215. displayMaster.sort( function ( a, b ) {
  5216. var
  5217. x, y, k, test, sort,
  5218. len=aSort.length,
  5219. dataA = aoData[a]._aSortData,
  5220. dataB = aoData[b]._aSortData;
  5221. for ( k=0 ; k<len ; k++ ) {
  5222. sort = aSort[k];
  5223. x = dataA[ sort.col ];
  5224. y = dataB[ sort.col ];
  5225. test = x<y ? -1 : x>y ? 1 : 0;
  5226. if ( test !== 0 ) {
  5227. return sort.dir === 'asc' ? test : -test;
  5228. }
  5229. }
  5230. x = aiOrig[a];
  5231. y = aiOrig[b];
  5232. return x<y ? -1 : x>y ? 1 : 0;
  5233. } );
  5234. }
  5235. else {
  5236. // Depreciated - remove in 1.11 (providing a plug-in option)
  5237. // Not all sort types have formatting methods, so we have to call their sorting
  5238. // methods.
  5239. displayMaster.sort( function ( a, b ) {
  5240. var
  5241. x, y, k, l, test, sort, fn,
  5242. len=aSort.length,
  5243. dataA = aoData[a]._aSortData,
  5244. dataB = aoData[b]._aSortData;
  5245. for ( k=0 ; k<len ; k++ ) {
  5246. sort = aSort[k];
  5247. x = dataA[ sort.col ];
  5248. y = dataB[ sort.col ];
  5249. fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
  5250. test = fn( x, y );
  5251. if ( test !== 0 ) {
  5252. return test;
  5253. }
  5254. }
  5255. x = aiOrig[a];
  5256. y = aiOrig[b];
  5257. return x<y ? -1 : x>y ? 1 : 0;
  5258. } );
  5259. }
  5260. }
  5261. /* Tell the draw function that we have sorted the data */
  5262. oSettings.bSorted = true;
  5263. }
  5264. function _fnSortAria ( settings )
  5265. {
  5266. var label;
  5267. var nextSort;
  5268. var columns = settings.aoColumns;
  5269. var aSort = _fnSortFlatten( settings );
  5270. var oAria = settings.oLanguage.oAria;
  5271. // ARIA attributes - need to loop all columns, to update all (removing old
  5272. // attributes as needed)
  5273. for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
  5274. {
  5275. var col = columns[i];
  5276. var asSorting = col.asSorting;
  5277. var sTitle = col.ariaTitle || col.sTitle.replace( /<.*?>/g, "" );
  5278. var th = col.nTh;
  5279. // IE7 is throwing an error when setting these properties with jQuery's
  5280. // attr() and removeAttr() methods...
  5281. th.removeAttribute('aria-sort');
  5282. /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
  5283. if ( col.bSortable ) {
  5284. if ( aSort.length > 0 && aSort[0].col == i ) {
  5285. th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
  5286. nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
  5287. }
  5288. else {
  5289. nextSort = asSorting[0];
  5290. }
  5291. label = sTitle + ( nextSort === "asc" ?
  5292. oAria.sSortAscending :
  5293. oAria.sSortDescending
  5294. );
  5295. }
  5296. else {
  5297. label = sTitle;
  5298. }
  5299. th.setAttribute('aria-label', label);
  5300. }
  5301. }
  5302. /**
  5303. * Function to run on user sort request
  5304. * @param {object} settings dataTables settings object
  5305. * @param {node} attachTo node to attach the handler to
  5306. * @param {int} colIdx column sorting index
  5307. * @param {boolean} [append=false] Append the requested sort to the existing
  5308. * sort if true (i.e. multi-column sort)
  5309. * @param {function} [callback] callback function
  5310. * @memberof DataTable#oApi
  5311. */
  5312. function _fnSortListener ( settings, colIdx, append, callback )
  5313. {
  5314. var col = settings.aoColumns[ colIdx ];
  5315. var sorting = settings.aaSorting;
  5316. var asSorting = col.asSorting;
  5317. var nextSortIdx;
  5318. var next = function ( a, overflow ) {
  5319. var idx = a._idx;
  5320. if ( idx === undefined ) {
  5321. idx = $.inArray( a[1], asSorting );
  5322. }
  5323. return idx+1 < asSorting.length ?
  5324. idx+1 :
  5325. overflow ?
  5326. null :
  5327. 0;
  5328. };
  5329. // Convert to 2D array if needed
  5330. if ( typeof sorting[0] === 'number' ) {
  5331. sorting = settings.aaSorting = [ sorting ];
  5332. }
  5333. // If appending the sort then we are multi-column sorting
  5334. if ( append && settings.oFeatures.bSortMulti ) {
  5335. // Are we already doing some kind of sort on this column?
  5336. var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
  5337. if ( sortIdx !== -1 ) {
  5338. // Yes, modify the sort
  5339. nextSortIdx = next( sorting[sortIdx], true );
  5340. if ( nextSortIdx === null && sorting.length === 1 ) {
  5341. nextSortIdx = 0; // can't remove sorting completely
  5342. }
  5343. if ( nextSortIdx === null ) {
  5344. sorting.splice( sortIdx, 1 );
  5345. }
  5346. else {
  5347. sorting[sortIdx][1] = asSorting[ nextSortIdx ];
  5348. sorting[sortIdx]._idx = nextSortIdx;
  5349. }
  5350. }
  5351. else {
  5352. // No sort on this column yet
  5353. sorting.push( [ colIdx, asSorting[0], 0 ] );
  5354. sorting[sorting.length-1]._idx = 0;
  5355. }
  5356. }
  5357. else if ( sorting.length && sorting[0][0] == colIdx ) {
  5358. // Single column - already sorting on this column, modify the sort
  5359. nextSortIdx = next( sorting[0] );
  5360. sorting.length = 1;
  5361. sorting[0][1] = asSorting[ nextSortIdx ];
  5362. sorting[0]._idx = nextSortIdx;
  5363. }
  5364. else {
  5365. // Single column - sort only on this column
  5366. sorting.length = 0;
  5367. sorting.push( [ colIdx, asSorting[0] ] );
  5368. sorting[0]._idx = 0;
  5369. }
  5370. // Run the sort by calling a full redraw
  5371. _fnReDraw( settings );
  5372. // callback used for async user interaction
  5373. if ( typeof callback == 'function' ) {
  5374. callback( settings );
  5375. }
  5376. }
  5377. /**
  5378. * Attach a sort handler (click) to a node
  5379. * @param {object} settings dataTables settings object
  5380. * @param {node} attachTo node to attach the handler to
  5381. * @param {int} colIdx column sorting index
  5382. * @param {function} [callback] callback function
  5383. * @memberof DataTable#oApi
  5384. */
  5385. function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
  5386. {
  5387. var col = settings.aoColumns[ colIdx ];
  5388. _fnBindAction( attachTo, {}, function (e) {
  5389. /* If the column is not sortable - don't to anything */
  5390. if ( col.bSortable === false ) {
  5391. return;
  5392. }
  5393. // If processing is enabled use a timeout to allow the processing
  5394. // display to be shown - otherwise to it synchronously
  5395. if ( settings.oFeatures.bProcessing ) {
  5396. _fnProcessingDisplay( settings, true );
  5397. setTimeout( function() {
  5398. _fnSortListener( settings, colIdx, e.shiftKey, callback );
  5399. // In server-side processing, the draw callback will remove the
  5400. // processing display
  5401. if ( _fnDataSource( settings ) !== 'ssp' ) {
  5402. _fnProcessingDisplay( settings, false );
  5403. }
  5404. }, 0 );
  5405. }
  5406. else {
  5407. _fnSortListener( settings, colIdx, e.shiftKey, callback );
  5408. }
  5409. } );
  5410. }
  5411. /**
  5412. * Set the sorting classes on table's body, Note: it is safe to call this function
  5413. * when bSort and bSortClasses are false
  5414. * @param {object} oSettings dataTables settings object
  5415. * @memberof DataTable#oApi
  5416. */
  5417. function _fnSortingClasses( settings )
  5418. {
  5419. var oldSort = settings.aLastSort;
  5420. var sortClass = settings.oClasses.sSortColumn;
  5421. var sort = _fnSortFlatten( settings );
  5422. var features = settings.oFeatures;
  5423. var i, ien, colIdx;
  5424. if ( features.bSort && features.bSortClasses ) {
  5425. // Remove old sorting classes
  5426. for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
  5427. colIdx = oldSort[i].src;
  5428. // Remove column sorting
  5429. $( _pluck( settings.aoData, 'anCells', colIdx ) )
  5430. .removeClass( sortClass + (i<2 ? i+1 : 3) );
  5431. }
  5432. // Add new column sorting
  5433. for ( i=0, ien=sort.length ; i<ien ; i++ ) {
  5434. colIdx = sort[i].src;
  5435. $( _pluck( settings.aoData, 'anCells', colIdx ) )
  5436. .addClass( sortClass + (i<2 ? i+1 : 3) );
  5437. }
  5438. }
  5439. settings.aLastSort = sort;
  5440. }
  5441. // Get the data to sort a column, be it from cache, fresh (populating the
  5442. // cache), or from a sort formatter
  5443. function _fnSortData( settings, idx )
  5444. {
  5445. // Custom sorting function - provided by the sort data type
  5446. var column = settings.aoColumns[ idx ];
  5447. var customSort = DataTable.ext.order[ column.sSortDataType ];
  5448. var customData;
  5449. if ( customSort ) {
  5450. customData = customSort.call( settings.oInstance, settings, idx,
  5451. _fnColumnIndexToVisible( settings, idx )
  5452. );
  5453. }
  5454. // Use / populate cache
  5455. var row, cellData;
  5456. var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
  5457. for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  5458. row = settings.aoData[i];
  5459. if ( ! row._aSortData ) {
  5460. row._aSortData = [];
  5461. }
  5462. if ( ! row._aSortData[idx] || customSort ) {
  5463. cellData = customSort ?
  5464. customData[i] : // If there was a custom sort function, use data from there
  5465. _fnGetCellData( settings, i, idx, 'sort' );
  5466. row._aSortData[ idx ] = formatter ?
  5467. formatter( cellData ) :
  5468. cellData;
  5469. }
  5470. }
  5471. }
  5472. /**
  5473. * Save the state of a table
  5474. * @param {object} oSettings dataTables settings object
  5475. * @memberof DataTable#oApi
  5476. */
  5477. function _fnSaveState ( settings )
  5478. {
  5479. if (settings._bLoadingState) {
  5480. return;
  5481. }
  5482. /* Store the interesting variables */
  5483. var state = {
  5484. time: +new Date(),
  5485. start: settings._iDisplayStart,
  5486. length: settings._iDisplayLength,
  5487. order: $.extend( true, [], settings.aaSorting ),
  5488. search: _fnSearchToCamel( settings.oPreviousSearch ),
  5489. columns: $.map( settings.aoColumns, function ( col, i ) {
  5490. return {
  5491. visible: col.bVisible,
  5492. search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
  5493. };
  5494. } )
  5495. };
  5496. settings.oSavedState = state;
  5497. _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
  5498. if ( settings.oFeatures.bStateSave && !settings.bDestroying )
  5499. {
  5500. settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
  5501. }
  5502. }
  5503. /**
  5504. * Attempt to load a saved table state
  5505. * @param {object} oSettings dataTables settings object
  5506. * @param {object} oInit DataTables init object so we can override settings
  5507. * @param {function} callback Callback to execute when the state has been loaded
  5508. * @memberof DataTable#oApi
  5509. */
  5510. function _fnLoadState ( settings, oInit, callback )
  5511. {
  5512. if ( ! settings.oFeatures.bStateSave ) {
  5513. callback();
  5514. return;
  5515. }
  5516. var loaded = function(state) {
  5517. _fnImplementState(settings, state, callback);
  5518. }
  5519. var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
  5520. if ( state !== undefined ) {
  5521. _fnImplementState( settings, state, callback );
  5522. }
  5523. // otherwise, wait for the loaded callback to be executed
  5524. return true;
  5525. }
  5526. function _fnImplementState ( settings, s, callback) {
  5527. var i, ien;
  5528. var columns = settings.aoColumns;
  5529. settings._bLoadingState = true;
  5530. // When StateRestore was introduced the state could now be implemented at any time
  5531. // Not just initialisation. To do this an api instance is required in some places
  5532. var api = settings._bInitComplete ? new DataTable.Api(settings) : null;
  5533. if ( ! s || ! s.time ) {
  5534. settings._bLoadingState = false;
  5535. callback();
  5536. return;
  5537. }
  5538. // Allow custom and plug-in manipulation functions to alter the saved data set and
  5539. // cancelling of loading by returning false
  5540. var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
  5541. if ( $.inArray( false, abStateLoad ) !== -1 ) {
  5542. settings._bLoadingState = false;
  5543. callback();
  5544. return;
  5545. }
  5546. // Reject old data
  5547. var duration = settings.iStateDuration;
  5548. if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
  5549. settings._bLoadingState = false;
  5550. callback();
  5551. return;
  5552. }
  5553. // Number of columns have changed - all bets are off, no restore of settings
  5554. if ( s.columns && columns.length !== s.columns.length ) {
  5555. settings._bLoadingState = false;
  5556. callback();
  5557. return;
  5558. }
  5559. // Store the saved state so it might be accessed at any time
  5560. settings.oLoadedState = $.extend( true, {}, s );
  5561. // Page Length
  5562. if ( s.length !== undefined ) {
  5563. // If already initialised just set the value directly so that the select element is also updated
  5564. if (api) {
  5565. api.page.len(s.length)
  5566. }
  5567. else {
  5568. settings._iDisplayLength = s.length;
  5569. }
  5570. }
  5571. // Restore key features - todo - for 1.11 this needs to be done by
  5572. // subscribed events
  5573. if ( s.start !== undefined ) {
  5574. if(api === null) {
  5575. settings._iDisplayStart = s.start;
  5576. settings.iInitDisplayStart = s.start;
  5577. }
  5578. else {
  5579. _fnPageChange(settings, s.start/settings._iDisplayLength);
  5580. }
  5581. }
  5582. // Order
  5583. if ( s.order !== undefined ) {
  5584. settings.aaSorting = [];
  5585. $.each( s.order, function ( i, col ) {
  5586. settings.aaSorting.push( col[0] >= columns.length ?
  5587. [ 0, col[1] ] :
  5588. col
  5589. );
  5590. } );
  5591. }
  5592. // Search
  5593. if ( s.search !== undefined ) {
  5594. $.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
  5595. }
  5596. // Columns
  5597. if ( s.columns ) {
  5598. for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
  5599. var col = s.columns[i];
  5600. // Visibility
  5601. if ( col.visible !== undefined ) {
  5602. // If the api is defined, the table has been initialised so we need to use it rather than internal settings
  5603. if (api) {
  5604. // Don't redraw the columns on every iteration of this loop, we will do this at the end instead
  5605. api.column(i).visible(col.visible, false);
  5606. }
  5607. else {
  5608. columns[i].bVisible = col.visible;
  5609. }
  5610. }
  5611. // Search
  5612. if ( col.search !== undefined ) {
  5613. $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
  5614. }
  5615. }
  5616. // If the api is defined then we need to adjust the columns once the visibility has been changed
  5617. if (api) {
  5618. api.columns.adjust();
  5619. }
  5620. }
  5621. settings._bLoadingState = false;
  5622. _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
  5623. callback();
  5624. };
  5625. /**
  5626. * Return the settings object for a particular table
  5627. * @param {node} table table we are using as a dataTable
  5628. * @returns {object} Settings object - or null if not found
  5629. * @memberof DataTable#oApi
  5630. */
  5631. function _fnSettingsFromNode ( table )
  5632. {
  5633. var settings = DataTable.settings;
  5634. var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
  5635. return idx !== -1 ?
  5636. settings[ idx ] :
  5637. null;
  5638. }
  5639. /**
  5640. * Log an error message
  5641. * @param {object} settings dataTables settings object
  5642. * @param {int} level log error messages, or display them to the user
  5643. * @param {string} msg error message
  5644. * @param {int} tn Technical note id to get more information about the error.
  5645. * @memberof DataTable#oApi
  5646. */
  5647. function _fnLog( settings, level, msg, tn )
  5648. {
  5649. msg = 'DataTables warning: '+
  5650. (settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
  5651. if ( tn ) {
  5652. msg += '. For more information about this error, please see '+
  5653. 'http://datatables.net/tn/'+tn;
  5654. }
  5655. if ( ! level ) {
  5656. // Backwards compatibility pre 1.10
  5657. var ext = DataTable.ext;
  5658. var type = ext.sErrMode || ext.errMode;
  5659. if ( settings ) {
  5660. _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
  5661. }
  5662. if ( type == 'alert' ) {
  5663. alert( msg );
  5664. }
  5665. else if ( type == 'throw' ) {
  5666. throw new Error(msg);
  5667. }
  5668. else if ( typeof type == 'function' ) {
  5669. type( settings, tn, msg );
  5670. }
  5671. }
  5672. else if ( window.console && console.log ) {
  5673. console.log( msg );
  5674. }
  5675. }
  5676. /**
  5677. * See if a property is defined on one object, if so assign it to the other object
  5678. * @param {object} ret target object
  5679. * @param {object} src source object
  5680. * @param {string} name property
  5681. * @param {string} [mappedName] name to map too - optional, name used if not given
  5682. * @memberof DataTable#oApi
  5683. */
  5684. function _fnMap( ret, src, name, mappedName )
  5685. {
  5686. if ( Array.isArray( name ) ) {
  5687. $.each( name, function (i, val) {
  5688. if ( Array.isArray( val ) ) {
  5689. _fnMap( ret, src, val[0], val[1] );
  5690. }
  5691. else {
  5692. _fnMap( ret, src, val );
  5693. }
  5694. } );
  5695. return;
  5696. }
  5697. if ( mappedName === undefined ) {
  5698. mappedName = name;
  5699. }
  5700. if ( src[name] !== undefined ) {
  5701. ret[mappedName] = src[name];
  5702. }
  5703. }
  5704. /**
  5705. * Extend objects - very similar to jQuery.extend, but deep copy objects, and
  5706. * shallow copy arrays. The reason we need to do this, is that we don't want to
  5707. * deep copy array init values (such as aaSorting) since the dev wouldn't be
  5708. * able to override them, but we do want to deep copy arrays.
  5709. * @param {object} out Object to extend
  5710. * @param {object} extender Object from which the properties will be applied to
  5711. * out
  5712. * @param {boolean} breakRefs If true, then arrays will be sliced to take an
  5713. * independent copy with the exception of the `data` or `aaData` parameters
  5714. * if they are present. This is so you can pass in a collection to
  5715. * DataTables and have that used as your data source without breaking the
  5716. * references
  5717. * @returns {object} out Reference, just for convenience - out === the return.
  5718. * @memberof DataTable#oApi
  5719. * @todo This doesn't take account of arrays inside the deep copied objects.
  5720. */
  5721. function _fnExtend( out, extender, breakRefs )
  5722. {
  5723. var val;
  5724. for ( var prop in extender ) {
  5725. if ( extender.hasOwnProperty(prop) ) {
  5726. val = extender[prop];
  5727. if ( $.isPlainObject( val ) ) {
  5728. if ( ! $.isPlainObject( out[prop] ) ) {
  5729. out[prop] = {};
  5730. }
  5731. $.extend( true, out[prop], val );
  5732. }
  5733. else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && Array.isArray(val) ) {
  5734. out[prop] = val.slice();
  5735. }
  5736. else {
  5737. out[prop] = val;
  5738. }
  5739. }
  5740. }
  5741. return out;
  5742. }
  5743. /**
  5744. * Bind an event handers to allow a click or return key to activate the callback.
  5745. * This is good for accessibility since a return on the keyboard will have the
  5746. * same effect as a click, if the element has focus.
  5747. * @param {element} n Element to bind the action to
  5748. * @param {object} oData Data object to pass to the triggered function
  5749. * @param {function} fn Callback function for when the event is triggered
  5750. * @memberof DataTable#oApi
  5751. */
  5752. function _fnBindAction( n, oData, fn )
  5753. {
  5754. $(n)
  5755. .on( 'click.DT', oData, function (e) {
  5756. $(n).trigger('blur'); // Remove focus outline for mouse users
  5757. fn(e);
  5758. } )
  5759. .on( 'keypress.DT', oData, function (e){
  5760. if ( e.which === 13 ) {
  5761. e.preventDefault();
  5762. fn(e);
  5763. }
  5764. } )
  5765. .on( 'selectstart.DT', function () {
  5766. /* Take the brutal approach to cancelling text selection */
  5767. return false;
  5768. } );
  5769. }
  5770. /**
  5771. * Register a callback function. Easily allows a callback function to be added to
  5772. * an array store of callback functions that can then all be called together.
  5773. * @param {object} oSettings dataTables settings object
  5774. * @param {string} sStore Name of the array storage for the callbacks in oSettings
  5775. * @param {function} fn Function to be called back
  5776. * @param {string} sName Identifying name for the callback (i.e. a label)
  5777. * @memberof DataTable#oApi
  5778. */
  5779. function _fnCallbackReg( oSettings, sStore, fn, sName )
  5780. {
  5781. if ( fn )
  5782. {
  5783. oSettings[sStore].push( {
  5784. "fn": fn,
  5785. "sName": sName
  5786. } );
  5787. }
  5788. }
  5789. /**
  5790. * Fire callback functions and trigger events. Note that the loop over the
  5791. * callback array store is done backwards! Further note that you do not want to
  5792. * fire off triggers in time sensitive applications (for example cell creation)
  5793. * as its slow.
  5794. * @param {object} settings dataTables settings object
  5795. * @param {string} callbackArr Name of the array storage for the callbacks in
  5796. * oSettings
  5797. * @param {string} eventName Name of the jQuery custom event to trigger. If
  5798. * null no trigger is fired
  5799. * @param {array} args Array of arguments to pass to the callback function /
  5800. * trigger
  5801. * @memberof DataTable#oApi
  5802. */
  5803. function _fnCallbackFire( settings, callbackArr, eventName, args )
  5804. {
  5805. var ret = [];
  5806. if ( callbackArr ) {
  5807. ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
  5808. return val.fn.apply( settings.oInstance, args );
  5809. } );
  5810. }
  5811. if ( eventName !== null ) {
  5812. var e = $.Event( eventName+'.dt' );
  5813. $(settings.nTable).trigger( e, args );
  5814. ret.push( e.result );
  5815. }
  5816. return ret;
  5817. }
  5818. function _fnLengthOverflow ( settings )
  5819. {
  5820. var
  5821. start = settings._iDisplayStart,
  5822. end = settings.fnDisplayEnd(),
  5823. len = settings._iDisplayLength;
  5824. /* If we have space to show extra rows (backing up from the end point - then do so */
  5825. if ( start >= end )
  5826. {
  5827. start = end - len;
  5828. }
  5829. // Keep the start record on the current page
  5830. start -= (start % len);
  5831. if ( len === -1 || start < 0 )
  5832. {
  5833. start = 0;
  5834. }
  5835. settings._iDisplayStart = start;
  5836. }
  5837. function _fnRenderer( settings, type )
  5838. {
  5839. var renderer = settings.renderer;
  5840. var host = DataTable.ext.renderer[type];
  5841. if ( $.isPlainObject( renderer ) && renderer[type] ) {
  5842. // Specific renderer for this type. If available use it, otherwise use
  5843. // the default.
  5844. return host[renderer[type]] || host._;
  5845. }
  5846. else if ( typeof renderer === 'string' ) {
  5847. // Common renderer - if there is one available for this type use it,
  5848. // otherwise use the default
  5849. return host[renderer] || host._;
  5850. }
  5851. // Use the default
  5852. return host._;
  5853. }
  5854. /**
  5855. * Detect the data source being used for the table. Used to simplify the code
  5856. * a little (ajax) and to make it compress a little smaller.
  5857. *
  5858. * @param {object} settings dataTables settings object
  5859. * @returns {string} Data source
  5860. * @memberof DataTable#oApi
  5861. */
  5862. function _fnDataSource ( settings )
  5863. {
  5864. if ( settings.oFeatures.bServerSide ) {
  5865. return 'ssp';
  5866. }
  5867. else if ( settings.ajax || settings.sAjaxSource ) {
  5868. return 'ajax';
  5869. }
  5870. return 'dom';
  5871. }
  5872. /**
  5873. * Computed structure of the DataTables API, defined by the options passed to
  5874. * `DataTable.Api.register()` when building the API.
  5875. *
  5876. * The structure is built in order to speed creation and extension of the Api
  5877. * objects since the extensions are effectively pre-parsed.
  5878. *
  5879. * The array is an array of objects with the following structure, where this
  5880. * base array represents the Api prototype base:
  5881. *
  5882. * [
  5883. * {
  5884. * name: 'data' -- string - Property name
  5885. * val: function () {}, -- function - Api method (or undefined if just an object
  5886. * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
  5887. * propExt: [ ... ] -- array - Array of Api object definitions to extend the property
  5888. * },
  5889. * {
  5890. * name: 'row'
  5891. * val: {},
  5892. * methodExt: [ ... ],
  5893. * propExt: [
  5894. * {
  5895. * name: 'data'
  5896. * val: function () {},
  5897. * methodExt: [ ... ],
  5898. * propExt: [ ... ]
  5899. * },
  5900. * ...
  5901. * ]
  5902. * }
  5903. * ]
  5904. *
  5905. * @type {Array}
  5906. * @ignore
  5907. */
  5908. var __apiStruct = [];
  5909. /**
  5910. * `Array.prototype` reference.
  5911. *
  5912. * @type object
  5913. * @ignore
  5914. */
  5915. var __arrayProto = Array.prototype;
  5916. /**
  5917. * Abstraction for `context` parameter of the `Api` constructor to allow it to
  5918. * take several different forms for ease of use.
  5919. *
  5920. * Each of the input parameter types will be converted to a DataTables settings
  5921. * object where possible.
  5922. *
  5923. * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one
  5924. * of:
  5925. *
  5926. * * `string` - jQuery selector. Any DataTables' matching the given selector
  5927. * with be found and used.
  5928. * * `node` - `TABLE` node which has already been formed into a DataTable.
  5929. * * `jQuery` - A jQuery object of `TABLE` nodes.
  5930. * * `object` - DataTables settings object
  5931. * * `DataTables.Api` - API instance
  5932. * @return {array|null} Matching DataTables settings objects. `null` or
  5933. * `undefined` is returned if no matching DataTable is found.
  5934. * @ignore
  5935. */
  5936. var _toSettings = function ( mixed )
  5937. {
  5938. var idx, jq;
  5939. var settings = DataTable.settings;
  5940. var tables = $.map( settings, function (el, i) {
  5941. return el.nTable;
  5942. } );
  5943. if ( ! mixed ) {
  5944. return [];
  5945. }
  5946. else if ( mixed.nTable && mixed.oApi ) {
  5947. // DataTables settings object
  5948. return [ mixed ];
  5949. }
  5950. else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
  5951. // Table node
  5952. idx = $.inArray( mixed, tables );
  5953. return idx !== -1 ? [ settings[idx] ] : null;
  5954. }
  5955. else if ( mixed && typeof mixed.settings === 'function' ) {
  5956. return mixed.settings().toArray();
  5957. }
  5958. else if ( typeof mixed === 'string' ) {
  5959. // jQuery selector
  5960. jq = $(mixed);
  5961. }
  5962. else if ( mixed instanceof $ ) {
  5963. // jQuery object (also DataTables instance)
  5964. jq = mixed;
  5965. }
  5966. if ( jq ) {
  5967. return jq.map( function(i) {
  5968. idx = $.inArray( this, tables );
  5969. return idx !== -1 ? settings[idx] : null;
  5970. } ).toArray();
  5971. }
  5972. };
  5973. /**
  5974. * DataTables API class - used to control and interface with one or more
  5975. * DataTables enhanced tables.
  5976. *
  5977. * The API class is heavily based on jQuery, presenting a chainable interface
  5978. * that you can use to interact with tables. Each instance of the API class has
  5979. * a "context" - i.e. the tables that it will operate on. This could be a single
  5980. * table, all tables on a page or a sub-set thereof.
  5981. *
  5982. * Additionally the API is designed to allow you to easily work with the data in
  5983. * the tables, retrieving and manipulating it as required. This is done by
  5984. * presenting the API class as an array like interface. The contents of the
  5985. * array depend upon the actions requested by each method (for example
  5986. * `rows().nodes()` will return an array of nodes, while `rows().data()` will
  5987. * return an array of objects or arrays depending upon your table's
  5988. * configuration). The API object has a number of array like methods (`push`,
  5989. * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
  5990. * `unique` etc) to assist your working with the data held in a table.
  5991. *
  5992. * Most methods (those which return an Api instance) are chainable, which means
  5993. * the return from a method call also has all of the methods available that the
  5994. * top level object had. For example, these two calls are equivalent:
  5995. *
  5996. * // Not chained
  5997. * api.row.add( {...} );
  5998. * api.draw();
  5999. *
  6000. * // Chained
  6001. * api.row.add( {...} ).draw();
  6002. *
  6003. * @class DataTable.Api
  6004. * @param {array|object|string|jQuery} context DataTable identifier. This is
  6005. * used to define which DataTables enhanced tables this API will operate on.
  6006. * Can be one of:
  6007. *
  6008. * * `string` - jQuery selector. Any DataTables' matching the given selector
  6009. * with be found and used.
  6010. * * `node` - `TABLE` node which has already been formed into a DataTable.
  6011. * * `jQuery` - A jQuery object of `TABLE` nodes.
  6012. * * `object` - DataTables settings object
  6013. * @param {array} [data] Data to initialise the Api instance with.
  6014. *
  6015. * @example
  6016. * // Direct initialisation during DataTables construction
  6017. * var api = $('#example').DataTable();
  6018. *
  6019. * @example
  6020. * // Initialisation using a DataTables jQuery object
  6021. * var api = $('#example').dataTable().api();
  6022. *
  6023. * @example
  6024. * // Initialisation as a constructor
  6025. * var api = new $.fn.DataTable.Api( 'table.dataTable' );
  6026. */
  6027. _Api = function ( context, data )
  6028. {
  6029. if ( ! (this instanceof _Api) ) {
  6030. return new _Api( context, data );
  6031. }
  6032. var settings = [];
  6033. var ctxSettings = function ( o ) {
  6034. var a = _toSettings( o );
  6035. if ( a ) {
  6036. settings.push.apply( settings, a );
  6037. }
  6038. };
  6039. if ( Array.isArray( context ) ) {
  6040. for ( var i=0, ien=context.length ; i<ien ; i++ ) {
  6041. ctxSettings( context[i] );
  6042. }
  6043. }
  6044. else {
  6045. ctxSettings( context );
  6046. }
  6047. // Remove duplicates
  6048. this.context = _unique( settings );
  6049. // Initial data
  6050. if ( data ) {
  6051. $.merge( this, data );
  6052. }
  6053. // selector
  6054. this.selector = {
  6055. rows: null,
  6056. cols: null,
  6057. opts: null
  6058. };
  6059. _Api.extend( this, this, __apiStruct );
  6060. };
  6061. DataTable.Api = _Api;
  6062. // Don't destroy the existing prototype, just extend it. Required for jQuery 2's
  6063. // isPlainObject.
  6064. $.extend( _Api.prototype, {
  6065. any: function ()
  6066. {
  6067. return this.count() !== 0;
  6068. },
  6069. concat: __arrayProto.concat,
  6070. context: [], // array of table settings objects
  6071. count: function ()
  6072. {
  6073. return this.flatten().length;
  6074. },
  6075. each: function ( fn )
  6076. {
  6077. for ( var i=0, ien=this.length ; i<ien; i++ ) {
  6078. fn.call( this, this[i], i, this );
  6079. }
  6080. return this;
  6081. },
  6082. eq: function ( idx )
  6083. {
  6084. var ctx = this.context;
  6085. return ctx.length > idx ?
  6086. new _Api( ctx[idx], this[idx] ) :
  6087. null;
  6088. },
  6089. filter: function ( fn )
  6090. {
  6091. var a = [];
  6092. if ( __arrayProto.filter ) {
  6093. a = __arrayProto.filter.call( this, fn, this );
  6094. }
  6095. else {
  6096. // Compatibility for browsers without EMCA-252-5 (JS 1.6)
  6097. for ( var i=0, ien=this.length ; i<ien ; i++ ) {
  6098. if ( fn.call( this, this[i], i, this ) ) {
  6099. a.push( this[i] );
  6100. }
  6101. }
  6102. }
  6103. return new _Api( this.context, a );
  6104. },
  6105. flatten: function ()
  6106. {
  6107. var a = [];
  6108. return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
  6109. },
  6110. join: __arrayProto.join,
  6111. indexOf: __arrayProto.indexOf || function (obj, start)
  6112. {
  6113. for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
  6114. if ( this[i] === obj ) {
  6115. return i;
  6116. }
  6117. }
  6118. return -1;
  6119. },
  6120. iterator: function ( flatten, type, fn, alwaysNew ) {
  6121. var
  6122. a = [], ret,
  6123. i, ien, j, jen,
  6124. context = this.context,
  6125. rows, items, item,
  6126. selector = this.selector;
  6127. // Argument shifting
  6128. if ( typeof flatten === 'string' ) {
  6129. alwaysNew = fn;
  6130. fn = type;
  6131. type = flatten;
  6132. flatten = false;
  6133. }
  6134. for ( i=0, ien=context.length ; i<ien ; i++ ) {
  6135. var apiInst = new _Api( context[i] );
  6136. if ( type === 'table' ) {
  6137. ret = fn.call( apiInst, context[i], i );
  6138. if ( ret !== undefined ) {
  6139. a.push( ret );
  6140. }
  6141. }
  6142. else if ( type === 'columns' || type === 'rows' ) {
  6143. // this has same length as context - one entry for each table
  6144. ret = fn.call( apiInst, context[i], this[i], i );
  6145. if ( ret !== undefined ) {
  6146. a.push( ret );
  6147. }
  6148. }
  6149. else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
  6150. // columns and rows share the same structure.
  6151. // 'this' is an array of column indexes for each context
  6152. items = this[i];
  6153. if ( type === 'column-rows' ) {
  6154. rows = _selector_row_indexes( context[i], selector.opts );
  6155. }
  6156. for ( j=0, jen=items.length ; j<jen ; j++ ) {
  6157. item = items[j];
  6158. if ( type === 'cell' ) {
  6159. ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
  6160. }
  6161. else {
  6162. ret = fn.call( apiInst, context[i], item, i, j, rows );
  6163. }
  6164. if ( ret !== undefined ) {
  6165. a.push( ret );
  6166. }
  6167. }
  6168. }
  6169. }
  6170. if ( a.length || alwaysNew ) {
  6171. var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
  6172. var apiSelector = api.selector;
  6173. apiSelector.rows = selector.rows;
  6174. apiSelector.cols = selector.cols;
  6175. apiSelector.opts = selector.opts;
  6176. return api;
  6177. }
  6178. return this;
  6179. },
  6180. lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
  6181. {
  6182. // Bit cheeky...
  6183. return this.indexOf.apply( this.toArray.reverse(), arguments );
  6184. },
  6185. length: 0,
  6186. map: function ( fn )
  6187. {
  6188. var a = [];
  6189. if ( __arrayProto.map ) {
  6190. a = __arrayProto.map.call( this, fn, this );
  6191. }
  6192. else {
  6193. // Compatibility for browsers without EMCA-252-5 (JS 1.6)
  6194. for ( var i=0, ien=this.length ; i<ien ; i++ ) {
  6195. a.push( fn.call( this, this[i], i ) );
  6196. }
  6197. }
  6198. return new _Api( this.context, a );
  6199. },
  6200. pluck: function ( prop )
  6201. {
  6202. let fn = DataTable.util.get(prop);
  6203. return this.map( function ( el ) {
  6204. return fn(el);
  6205. } );
  6206. },
  6207. pop: __arrayProto.pop,
  6208. push: __arrayProto.push,
  6209. // Does not return an API instance
  6210. reduce: __arrayProto.reduce || function ( fn, init )
  6211. {
  6212. return _fnReduce( this, fn, init, 0, this.length, 1 );
  6213. },
  6214. reduceRight: __arrayProto.reduceRight || function ( fn, init )
  6215. {
  6216. return _fnReduce( this, fn, init, this.length-1, -1, -1 );
  6217. },
  6218. reverse: __arrayProto.reverse,
  6219. // Object with rows, columns and opts
  6220. selector: null,
  6221. shift: __arrayProto.shift,
  6222. slice: function () {
  6223. return new _Api( this.context, this );
  6224. },
  6225. sort: __arrayProto.sort, // ? name - order?
  6226. splice: __arrayProto.splice,
  6227. toArray: function ()
  6228. {
  6229. return __arrayProto.slice.call( this );
  6230. },
  6231. to$: function ()
  6232. {
  6233. return $( this );
  6234. },
  6235. toJQuery: function ()
  6236. {
  6237. return $( this );
  6238. },
  6239. unique: function ()
  6240. {
  6241. return new _Api( this.context, _unique(this) );
  6242. },
  6243. unshift: __arrayProto.unshift
  6244. } );
  6245. _Api.extend = function ( scope, obj, ext )
  6246. {
  6247. // Only extend API instances and static properties of the API
  6248. if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
  6249. return;
  6250. }
  6251. var
  6252. i, ien,
  6253. struct,
  6254. methodScoping = function ( scope, fn, struc ) {
  6255. return function () {
  6256. var ret = fn.apply( scope, arguments );
  6257. // Method extension
  6258. _Api.extend( ret, ret, struc.methodExt );
  6259. return ret;
  6260. };
  6261. };
  6262. for ( i=0, ien=ext.length ; i<ien ; i++ ) {
  6263. struct = ext[i];
  6264. // Value
  6265. obj[ struct.name ] = struct.type === 'function' ?
  6266. methodScoping( scope, struct.val, struct ) :
  6267. struct.type === 'object' ?
  6268. {} :
  6269. struct.val;
  6270. obj[ struct.name ].__dt_wrapper = true;
  6271. // Property extension
  6272. _Api.extend( scope, obj[ struct.name ], struct.propExt );
  6273. }
  6274. };
  6275. // @todo - Is there need for an augment function?
  6276. // _Api.augment = function ( inst, name )
  6277. // {
  6278. // // Find src object in the structure from the name
  6279. // var parts = name.split('.');
  6280. // _Api.extend( inst, obj );
  6281. // };
  6282. // [
  6283. // {
  6284. // name: 'data' -- string - Property name
  6285. // val: function () {}, -- function - Api method (or undefined if just an object
  6286. // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
  6287. // propExt: [ ... ] -- array - Array of Api object definitions to extend the property
  6288. // },
  6289. // {
  6290. // name: 'row'
  6291. // val: {},
  6292. // methodExt: [ ... ],
  6293. // propExt: [
  6294. // {
  6295. // name: 'data'
  6296. // val: function () {},
  6297. // methodExt: [ ... ],
  6298. // propExt: [ ... ]
  6299. // },
  6300. // ...
  6301. // ]
  6302. // }
  6303. // ]
  6304. _Api.register = _api_register = function ( name, val )
  6305. {
  6306. if ( Array.isArray( name ) ) {
  6307. for ( var j=0, jen=name.length ; j<jen ; j++ ) {
  6308. _Api.register( name[j], val );
  6309. }
  6310. return;
  6311. }
  6312. var
  6313. i, ien,
  6314. heir = name.split('.'),
  6315. struct = __apiStruct,
  6316. key, method;
  6317. var find = function ( src, name ) {
  6318. for ( var i=0, ien=src.length ; i<ien ; i++ ) {
  6319. if ( src[i].name === name ) {
  6320. return src[i];
  6321. }
  6322. }
  6323. return null;
  6324. };
  6325. for ( i=0, ien=heir.length ; i<ien ; i++ ) {
  6326. method = heir[i].indexOf('()') !== -1;
  6327. key = method ?
  6328. heir[i].replace('()', '') :
  6329. heir[i];
  6330. var src = find( struct, key );
  6331. if ( ! src ) {
  6332. src = {
  6333. name: key,
  6334. val: {},
  6335. methodExt: [],
  6336. propExt: [],
  6337. type: 'object'
  6338. };
  6339. struct.push( src );
  6340. }
  6341. if ( i === ien-1 ) {
  6342. src.val = val;
  6343. src.type = typeof val === 'function' ?
  6344. 'function' :
  6345. $.isPlainObject( val ) ?
  6346. 'object' :
  6347. 'other';
  6348. }
  6349. else {
  6350. struct = method ?
  6351. src.methodExt :
  6352. src.propExt;
  6353. }
  6354. }
  6355. };
  6356. _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
  6357. _Api.register( pluralName, val );
  6358. _Api.register( singularName, function () {
  6359. var ret = val.apply( this, arguments );
  6360. if ( ret === this ) {
  6361. // Returned item is the API instance that was passed in, return it
  6362. return this;
  6363. }
  6364. else if ( ret instanceof _Api ) {
  6365. // New API instance returned, want the value from the first item
  6366. // in the returned array for the singular result.
  6367. return ret.length ?
  6368. Array.isArray( ret[0] ) ?
  6369. new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
  6370. ret[0] :
  6371. undefined;
  6372. }
  6373. // Non-API return - just fire it back
  6374. return ret;
  6375. } );
  6376. };
  6377. /**
  6378. * Selector for HTML tables. Apply the given selector to the give array of
  6379. * DataTables settings objects.
  6380. *
  6381. * @param {string|integer} [selector] jQuery selector string or integer
  6382. * @param {array} Array of DataTables settings objects to be filtered
  6383. * @return {array}
  6384. * @ignore
  6385. */
  6386. var __table_selector = function ( selector, a )
  6387. {
  6388. if ( Array.isArray(selector) ) {
  6389. return $.map( selector, function (item) {
  6390. return __table_selector(item, a);
  6391. } );
  6392. }
  6393. // Integer is used to pick out a table by index
  6394. if ( typeof selector === 'number' ) {
  6395. return [ a[ selector ] ];
  6396. }
  6397. // Perform a jQuery selector on the table nodes
  6398. var nodes = $.map( a, function (el, i) {
  6399. return el.nTable;
  6400. } );
  6401. return $(nodes)
  6402. .filter( selector )
  6403. .map( function (i) {
  6404. // Need to translate back from the table node to the settings
  6405. var idx = $.inArray( this, nodes );
  6406. return a[ idx ];
  6407. } )
  6408. .toArray();
  6409. };
  6410. /**
  6411. * Context selector for the API's context (i.e. the tables the API instance
  6412. * refers to.
  6413. *
  6414. * @name DataTable.Api#tables
  6415. * @param {string|integer} [selector] Selector to pick which tables the iterator
  6416. * should operate on. If not given, all tables in the current context are
  6417. * used. This can be given as a jQuery selector (for example `':gt(0)'`) to
  6418. * select multiple tables or as an integer to select a single table.
  6419. * @returns {DataTable.Api} Returns a new API instance if a selector is given.
  6420. */
  6421. _api_register( 'tables()', function ( selector ) {
  6422. // A new instance is created if there was a selector specified
  6423. return selector !== undefined && selector !== null ?
  6424. new _Api( __table_selector( selector, this.context ) ) :
  6425. this;
  6426. } );
  6427. _api_register( 'table()', function ( selector ) {
  6428. var tables = this.tables( selector );
  6429. var ctx = tables.context;
  6430. // Truncate to the first matched table
  6431. return ctx.length ?
  6432. new _Api( ctx[0] ) :
  6433. tables;
  6434. } );
  6435. _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
  6436. return this.iterator( 'table', function ( ctx ) {
  6437. return ctx.nTable;
  6438. }, 1 );
  6439. } );
  6440. _api_registerPlural( 'tables().body()', 'table().body()' , function () {
  6441. return this.iterator( 'table', function ( ctx ) {
  6442. return ctx.nTBody;
  6443. }, 1 );
  6444. } );
  6445. _api_registerPlural( 'tables().header()', 'table().header()' , function () {
  6446. return this.iterator( 'table', function ( ctx ) {
  6447. return ctx.nTHead;
  6448. }, 1 );
  6449. } );
  6450. _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
  6451. return this.iterator( 'table', function ( ctx ) {
  6452. return ctx.nTFoot;
  6453. }, 1 );
  6454. } );
  6455. _api_registerPlural( 'tables().containers()', 'table().container()' , function () {
  6456. return this.iterator( 'table', function ( ctx ) {
  6457. return ctx.nTableWrapper;
  6458. }, 1 );
  6459. } );
  6460. /**
  6461. * Redraw the tables in the current context.
  6462. */
  6463. _api_register( 'draw()', function ( paging ) {
  6464. return this.iterator( 'table', function ( settings ) {
  6465. if ( paging === 'page' ) {
  6466. _fnDraw( settings );
  6467. }
  6468. else {
  6469. if ( typeof paging === 'string' ) {
  6470. paging = paging === 'full-hold' ?
  6471. false :
  6472. true;
  6473. }
  6474. _fnReDraw( settings, paging===false );
  6475. }
  6476. } );
  6477. } );
  6478. /**
  6479. * Get the current page index.
  6480. *
  6481. * @return {integer} Current page index (zero based)
  6482. *//**
  6483. * Set the current page.
  6484. *
  6485. * Note that if you attempt to show a page which does not exist, DataTables will
  6486. * not throw an error, but rather reset the paging.
  6487. *
  6488. * @param {integer|string} action The paging action to take. This can be one of:
  6489. * * `integer` - The page index to jump to
  6490. * * `string` - An action to take:
  6491. * * `first` - Jump to first page.
  6492. * * `next` - Jump to the next page
  6493. * * `previous` - Jump to previous page
  6494. * * `last` - Jump to the last page.
  6495. * @returns {DataTables.Api} this
  6496. */
  6497. _api_register( 'page()', function ( action ) {
  6498. if ( action === undefined ) {
  6499. return this.page.info().page; // not an expensive call
  6500. }
  6501. // else, have an action to take on all tables
  6502. return this.iterator( 'table', function ( settings ) {
  6503. _fnPageChange( settings, action );
  6504. } );
  6505. } );
  6506. /**
  6507. * Paging information for the first table in the current context.
  6508. *
  6509. * If you require paging information for another table, use the `table()` method
  6510. * with a suitable selector.
  6511. *
  6512. * @return {object} Object with the following properties set:
  6513. * * `page` - Current page index (zero based - i.e. the first page is `0`)
  6514. * * `pages` - Total number of pages
  6515. * * `start` - Display index for the first record shown on the current page
  6516. * * `end` - Display index for the last record shown on the current page
  6517. * * `length` - Display length (number of records). Note that generally `start
  6518. * + length = end`, but this is not always true, for example if there are
  6519. * only 2 records to show on the final page, with a length of 10.
  6520. * * `recordsTotal` - Full data set length
  6521. * * `recordsDisplay` - Data set length once the current filtering criterion
  6522. * are applied.
  6523. */
  6524. _api_register( 'page.info()', function ( action ) {
  6525. if ( this.context.length === 0 ) {
  6526. return undefined;
  6527. }
  6528. var
  6529. settings = this.context[0],
  6530. start = settings._iDisplayStart,
  6531. len = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
  6532. visRecords = settings.fnRecordsDisplay(),
  6533. all = len === -1;
  6534. return {
  6535. "page": all ? 0 : Math.floor( start / len ),
  6536. "pages": all ? 1 : Math.ceil( visRecords / len ),
  6537. "start": start,
  6538. "end": settings.fnDisplayEnd(),
  6539. "length": len,
  6540. "recordsTotal": settings.fnRecordsTotal(),
  6541. "recordsDisplay": visRecords,
  6542. "serverSide": _fnDataSource( settings ) === 'ssp'
  6543. };
  6544. } );
  6545. /**
  6546. * Get the current page length.
  6547. *
  6548. * @return {integer} Current page length. Note `-1` indicates that all records
  6549. * are to be shown.
  6550. *//**
  6551. * Set the current page length.
  6552. *
  6553. * @param {integer} Page length to set. Use `-1` to show all records.
  6554. * @returns {DataTables.Api} this
  6555. */
  6556. _api_register( 'page.len()', function ( len ) {
  6557. // Note that we can't call this function 'length()' because `length`
  6558. // is a Javascript property of functions which defines how many arguments
  6559. // the function expects.
  6560. if ( len === undefined ) {
  6561. return this.context.length !== 0 ?
  6562. this.context[0]._iDisplayLength :
  6563. undefined;
  6564. }
  6565. // else, set the page length
  6566. return this.iterator( 'table', function ( settings ) {
  6567. _fnLengthChange( settings, len );
  6568. } );
  6569. } );
  6570. var __reload = function ( settings, holdPosition, callback ) {
  6571. // Use the draw event to trigger a callback
  6572. if ( callback ) {
  6573. var api = new _Api( settings );
  6574. api.one( 'draw', function () {
  6575. callback( api.ajax.json() );
  6576. } );
  6577. }
  6578. if ( _fnDataSource( settings ) == 'ssp' ) {
  6579. _fnReDraw( settings, holdPosition );
  6580. }
  6581. else {
  6582. _fnProcessingDisplay( settings, true );
  6583. // Cancel an existing request
  6584. var xhr = settings.jqXHR;
  6585. if ( xhr && xhr.readyState !== 4 ) {
  6586. xhr.abort();
  6587. }
  6588. // Trigger xhr
  6589. _fnBuildAjax( settings, [], function( json ) {
  6590. _fnClearTable( settings );
  6591. var data = _fnAjaxDataSrc( settings, json );
  6592. for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  6593. _fnAddData( settings, data[i] );
  6594. }
  6595. _fnReDraw( settings, holdPosition );
  6596. _fnProcessingDisplay( settings, false );
  6597. } );
  6598. }
  6599. };
  6600. /**
  6601. * Get the JSON response from the last Ajax request that DataTables made to the
  6602. * server. Note that this returns the JSON from the first table in the current
  6603. * context.
  6604. *
  6605. * @return {object} JSON received from the server.
  6606. */
  6607. _api_register( 'ajax.json()', function () {
  6608. var ctx = this.context;
  6609. if ( ctx.length > 0 ) {
  6610. return ctx[0].json;
  6611. }
  6612. // else return undefined;
  6613. } );
  6614. /**
  6615. * Get the data submitted in the last Ajax request
  6616. */
  6617. _api_register( 'ajax.params()', function () {
  6618. var ctx = this.context;
  6619. if ( ctx.length > 0 ) {
  6620. return ctx[0].oAjaxData;
  6621. }
  6622. // else return undefined;
  6623. } );
  6624. /**
  6625. * Reload tables from the Ajax data source. Note that this function will
  6626. * automatically re-draw the table when the remote data has been loaded.
  6627. *
  6628. * @param {boolean} [reset=true] Reset (default) or hold the current paging
  6629. * position. A full re-sort and re-filter is performed when this method is
  6630. * called, which is why the pagination reset is the default action.
  6631. * @returns {DataTables.Api} this
  6632. */
  6633. _api_register( 'ajax.reload()', function ( callback, resetPaging ) {
  6634. return this.iterator( 'table', function (settings) {
  6635. __reload( settings, resetPaging===false, callback );
  6636. } );
  6637. } );
  6638. /**
  6639. * Get the current Ajax URL. Note that this returns the URL from the first
  6640. * table in the current context.
  6641. *
  6642. * @return {string} Current Ajax source URL
  6643. *//**
  6644. * Set the Ajax URL. Note that this will set the URL for all tables in the
  6645. * current context.
  6646. *
  6647. * @param {string} url URL to set.
  6648. * @returns {DataTables.Api} this
  6649. */
  6650. _api_register( 'ajax.url()', function ( url ) {
  6651. var ctx = this.context;
  6652. if ( url === undefined ) {
  6653. // get
  6654. if ( ctx.length === 0 ) {
  6655. return undefined;
  6656. }
  6657. ctx = ctx[0];
  6658. return ctx.ajax ?
  6659. $.isPlainObject( ctx.ajax ) ?
  6660. ctx.ajax.url :
  6661. ctx.ajax :
  6662. ctx.sAjaxSource;
  6663. }
  6664. // set
  6665. return this.iterator( 'table', function ( settings ) {
  6666. if ( $.isPlainObject( settings.ajax ) ) {
  6667. settings.ajax.url = url;
  6668. }
  6669. else {
  6670. settings.ajax = url;
  6671. }
  6672. // No need to consider sAjaxSource here since DataTables gives priority
  6673. // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
  6674. // value of `sAjaxSource` redundant.
  6675. } );
  6676. } );
  6677. /**
  6678. * Load data from the newly set Ajax URL. Note that this method is only
  6679. * available when `ajax.url()` is used to set a URL. Additionally, this method
  6680. * has the same effect as calling `ajax.reload()` but is provided for
  6681. * convenience when setting a new URL. Like `ajax.reload()` it will
  6682. * automatically redraw the table once the remote data has been loaded.
  6683. *
  6684. * @returns {DataTables.Api} this
  6685. */
  6686. _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
  6687. // Same as a reload, but makes sense to present it for easy access after a
  6688. // url change
  6689. return this.iterator( 'table', function ( ctx ) {
  6690. __reload( ctx, resetPaging===false, callback );
  6691. } );
  6692. } );
  6693. var _selector_run = function ( type, selector, selectFn, settings, opts )
  6694. {
  6695. var
  6696. out = [], res,
  6697. a, i, ien, j, jen,
  6698. selectorType = typeof selector;
  6699. // Can't just check for isArray here, as an API or jQuery instance might be
  6700. // given with their array like look
  6701. if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
  6702. selector = [ selector ];
  6703. }
  6704. for ( i=0, ien=selector.length ; i<ien ; i++ ) {
  6705. // Only split on simple strings - complex expressions will be jQuery selectors
  6706. a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
  6707. selector[i].split(',') :
  6708. [ selector[i] ];
  6709. for ( j=0, jen=a.length ; j<jen ; j++ ) {
  6710. res = selectFn( typeof a[j] === 'string' ? (a[j]).trim() : a[j] );
  6711. if ( res && res.length ) {
  6712. out = out.concat( res );
  6713. }
  6714. }
  6715. }
  6716. // selector extensions
  6717. var ext = _ext.selector[ type ];
  6718. if ( ext.length ) {
  6719. for ( i=0, ien=ext.length ; i<ien ; i++ ) {
  6720. out = ext[i]( settings, opts, out );
  6721. }
  6722. }
  6723. return _unique( out );
  6724. };
  6725. var _selector_opts = function ( opts )
  6726. {
  6727. if ( ! opts ) {
  6728. opts = {};
  6729. }
  6730. // Backwards compatibility for 1.9- which used the terminology filter rather
  6731. // than search
  6732. if ( opts.filter && opts.search === undefined ) {
  6733. opts.search = opts.filter;
  6734. }
  6735. return $.extend( {
  6736. search: 'none',
  6737. order: 'current',
  6738. page: 'all'
  6739. }, opts );
  6740. };
  6741. var _selector_first = function ( inst )
  6742. {
  6743. // Reduce the API instance to the first item found
  6744. for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
  6745. if ( inst[i].length > 0 ) {
  6746. // Assign the first element to the first item in the instance
  6747. // and truncate the instance and context
  6748. inst[0] = inst[i];
  6749. inst[0].length = 1;
  6750. inst.length = 1;
  6751. inst.context = [ inst.context[i] ];
  6752. return inst;
  6753. }
  6754. }
  6755. // Not found - return an empty instance
  6756. inst.length = 0;
  6757. return inst;
  6758. };
  6759. var _selector_row_indexes = function ( settings, opts )
  6760. {
  6761. var
  6762. i, ien, tmp, a=[],
  6763. displayFiltered = settings.aiDisplay,
  6764. displayMaster = settings.aiDisplayMaster;
  6765. var
  6766. search = opts.search, // none, applied, removed
  6767. order = opts.order, // applied, current, index (original - compatibility with 1.9)
  6768. page = opts.page; // all, current
  6769. if ( _fnDataSource( settings ) == 'ssp' ) {
  6770. // In server-side processing mode, most options are irrelevant since
  6771. // rows not shown don't exist and the index order is the applied order
  6772. // Removed is a special case - for consistency just return an empty
  6773. // array
  6774. return search === 'removed' ?
  6775. [] :
  6776. _range( 0, displayMaster.length );
  6777. }
  6778. else if ( page == 'current' ) {
  6779. // Current page implies that order=current and filter=applied, since it is
  6780. // fairly senseless otherwise, regardless of what order and search actually
  6781. // are
  6782. for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
  6783. a.push( displayFiltered[i] );
  6784. }
  6785. }
  6786. else if ( order == 'current' || order == 'applied' ) {
  6787. if ( search == 'none') {
  6788. a = displayMaster.slice();
  6789. }
  6790. else if ( search == 'applied' ) {
  6791. a = displayFiltered.slice();
  6792. }
  6793. else if ( search == 'removed' ) {
  6794. // O(n+m) solution by creating a hash map
  6795. var displayFilteredMap = {};
  6796. for ( var i=0, ien=displayFiltered.length ; i<ien ; i++ ) {
  6797. displayFilteredMap[displayFiltered[i]] = null;
  6798. }
  6799. a = $.map( displayMaster, function (el) {
  6800. return ! displayFilteredMap.hasOwnProperty(el) ?
  6801. el :
  6802. null;
  6803. } );
  6804. }
  6805. }
  6806. else if ( order == 'index' || order == 'original' ) {
  6807. for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  6808. if ( search == 'none' ) {
  6809. a.push( i );
  6810. }
  6811. else { // applied | removed
  6812. tmp = $.inArray( i, displayFiltered );
  6813. if ((tmp === -1 && search == 'removed') ||
  6814. (tmp >= 0 && search == 'applied') )
  6815. {
  6816. a.push( i );
  6817. }
  6818. }
  6819. }
  6820. }
  6821. return a;
  6822. };
  6823. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  6824. * Rows
  6825. *
  6826. * {} - no selector - use all available rows
  6827. * {integer} - row aoData index
  6828. * {node} - TR node
  6829. * {string} - jQuery selector to apply to the TR elements
  6830. * {array} - jQuery array of nodes, or simply an array of TR nodes
  6831. *
  6832. */
  6833. var __row_selector = function ( settings, selector, opts )
  6834. {
  6835. var rows;
  6836. var run = function ( sel ) {
  6837. var selInt = _intVal( sel );
  6838. var i, ien;
  6839. var aoData = settings.aoData;
  6840. // Short cut - selector is a number and no options provided (default is
  6841. // all records, so no need to check if the index is in there, since it
  6842. // must be - dev error if the index doesn't exist).
  6843. if ( selInt !== null && ! opts ) {
  6844. return [ selInt ];
  6845. }
  6846. if ( ! rows ) {
  6847. rows = _selector_row_indexes( settings, opts );
  6848. }
  6849. if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
  6850. // Selector - integer
  6851. return [ selInt ];
  6852. }
  6853. else if ( sel === null || sel === undefined || sel === '' ) {
  6854. // Selector - none
  6855. return rows;
  6856. }
  6857. // Selector - function
  6858. if ( typeof sel === 'function' ) {
  6859. return $.map( rows, function (idx) {
  6860. var row = aoData[ idx ];
  6861. return sel( idx, row._aData, row.nTr ) ? idx : null;
  6862. } );
  6863. }
  6864. // Selector - node
  6865. if ( sel.nodeName ) {
  6866. var rowIdx = sel._DT_RowIndex; // Property added by DT for fast lookup
  6867. var cellIdx = sel._DT_CellIndex;
  6868. if ( rowIdx !== undefined ) {
  6869. // Make sure that the row is actually still present in the table
  6870. return aoData[ rowIdx ] && aoData[ rowIdx ].nTr === sel ?
  6871. [ rowIdx ] :
  6872. [];
  6873. }
  6874. else if ( cellIdx ) {
  6875. return aoData[ cellIdx.row ] && aoData[ cellIdx.row ].nTr === sel.parentNode ?
  6876. [ cellIdx.row ] :
  6877. [];
  6878. }
  6879. else {
  6880. var host = $(sel).closest('*[data-dt-row]');
  6881. return host.length ?
  6882. [ host.data('dt-row') ] :
  6883. [];
  6884. }
  6885. }
  6886. // ID selector. Want to always be able to select rows by id, regardless
  6887. // of if the tr element has been created or not, so can't rely upon
  6888. // jQuery here - hence a custom implementation. This does not match
  6889. // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
  6890. // but to select it using a CSS selector engine (like Sizzle or
  6891. // querySelect) it would need to need to be escaped for some characters.
  6892. // DataTables simplifies this for row selectors since you can select
  6893. // only a row. A # indicates an id any anything that follows is the id -
  6894. // unescaped.
  6895. if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
  6896. // get row index from id
  6897. var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
  6898. if ( rowObj !== undefined ) {
  6899. return [ rowObj.idx ];
  6900. }
  6901. // need to fall through to jQuery in case there is DOM id that
  6902. // matches
  6903. }
  6904. // Get nodes in the order from the `rows` array with null values removed
  6905. var nodes = _removeEmpty(
  6906. _pluck_order( settings.aoData, rows, 'nTr' )
  6907. );
  6908. // Selector - jQuery selector string, array of nodes or jQuery object/
  6909. // As jQuery's .filter() allows jQuery objects to be passed in filter,
  6910. // it also allows arrays, so this will cope with all three options
  6911. return $(nodes)
  6912. .filter( sel )
  6913. .map( function () {
  6914. return this._DT_RowIndex;
  6915. } )
  6916. .toArray();
  6917. };
  6918. return _selector_run( 'row', selector, run, settings, opts );
  6919. };
  6920. _api_register( 'rows()', function ( selector, opts ) {
  6921. // argument shifting
  6922. if ( selector === undefined ) {
  6923. selector = '';
  6924. }
  6925. else if ( $.isPlainObject( selector ) ) {
  6926. opts = selector;
  6927. selector = '';
  6928. }
  6929. opts = _selector_opts( opts );
  6930. var inst = this.iterator( 'table', function ( settings ) {
  6931. return __row_selector( settings, selector, opts );
  6932. }, 1 );
  6933. // Want argument shifting here and in __row_selector?
  6934. inst.selector.rows = selector;
  6935. inst.selector.opts = opts;
  6936. return inst;
  6937. } );
  6938. _api_register( 'rows().nodes()', function () {
  6939. return this.iterator( 'row', function ( settings, row ) {
  6940. return settings.aoData[ row ].nTr || undefined;
  6941. }, 1 );
  6942. } );
  6943. _api_register( 'rows().data()', function () {
  6944. return this.iterator( true, 'rows', function ( settings, rows ) {
  6945. return _pluck_order( settings.aoData, rows, '_aData' );
  6946. }, 1 );
  6947. } );
  6948. _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
  6949. return this.iterator( 'row', function ( settings, row ) {
  6950. var r = settings.aoData[ row ];
  6951. return type === 'search' ? r._aFilterData : r._aSortData;
  6952. }, 1 );
  6953. } );
  6954. _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
  6955. return this.iterator( 'row', function ( settings, row ) {
  6956. _fnInvalidate( settings, row, src );
  6957. } );
  6958. } );
  6959. _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
  6960. return this.iterator( 'row', function ( settings, row ) {
  6961. return row;
  6962. }, 1 );
  6963. } );
  6964. _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
  6965. var a = [];
  6966. var context = this.context;
  6967. // `iterator` will drop undefined values, but in this case we want them
  6968. for ( var i=0, ien=context.length ; i<ien ; i++ ) {
  6969. for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
  6970. var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
  6971. a.push( (hash === true ? '#' : '' )+ id );
  6972. }
  6973. }
  6974. return new _Api( context, a );
  6975. } );
  6976. _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
  6977. var that = this;
  6978. this.iterator( 'row', function ( settings, row, thatIdx ) {
  6979. var data = settings.aoData;
  6980. var rowData = data[ row ];
  6981. var i, ien, j, jen;
  6982. var loopRow, loopCells;
  6983. data.splice( row, 1 );
  6984. // Update the cached indexes
  6985. for ( i=0, ien=data.length ; i<ien ; i++ ) {
  6986. loopRow = data[i];
  6987. loopCells = loopRow.anCells;
  6988. // Rows
  6989. if ( loopRow.nTr !== null ) {
  6990. loopRow.nTr._DT_RowIndex = i;
  6991. }
  6992. // Cells
  6993. if ( loopCells !== null ) {
  6994. for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
  6995. loopCells[j]._DT_CellIndex.row = i;
  6996. }
  6997. }
  6998. }
  6999. // Delete from the display arrays
  7000. _fnDeleteIndex( settings.aiDisplayMaster, row );
  7001. _fnDeleteIndex( settings.aiDisplay, row );
  7002. _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
  7003. // For server-side processing tables - subtract the deleted row from the count
  7004. if ( settings._iRecordsDisplay > 0 ) {
  7005. settings._iRecordsDisplay--;
  7006. }
  7007. // Check for an 'overflow' they case for displaying the table
  7008. _fnLengthOverflow( settings );
  7009. // Remove the row's ID reference if there is one
  7010. var id = settings.rowIdFn( rowData._aData );
  7011. if ( id !== undefined ) {
  7012. delete settings.aIds[ id ];
  7013. }
  7014. } );
  7015. this.iterator( 'table', function ( settings ) {
  7016. for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  7017. settings.aoData[i].idx = i;
  7018. }
  7019. } );
  7020. return this;
  7021. } );
  7022. _api_register( 'rows.add()', function ( rows ) {
  7023. var newRows = this.iterator( 'table', function ( settings ) {
  7024. var row, i, ien;
  7025. var out = [];
  7026. for ( i=0, ien=rows.length ; i<ien ; i++ ) {
  7027. row = rows[i];
  7028. if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
  7029. out.push( _fnAddTr( settings, row )[0] );
  7030. }
  7031. else {
  7032. out.push( _fnAddData( settings, row ) );
  7033. }
  7034. }
  7035. return out;
  7036. }, 1 );
  7037. // Return an Api.rows() extended instance, so rows().nodes() etc can be used
  7038. var modRows = this.rows( -1 );
  7039. modRows.pop();
  7040. $.merge( modRows, newRows );
  7041. return modRows;
  7042. } );
  7043. /**
  7044. *
  7045. */
  7046. _api_register( 'row()', function ( selector, opts ) {
  7047. return _selector_first( this.rows( selector, opts ) );
  7048. } );
  7049. _api_register( 'row().data()', function ( data ) {
  7050. var ctx = this.context;
  7051. if ( data === undefined ) {
  7052. // Get
  7053. return ctx.length && this.length ?
  7054. ctx[0].aoData[ this[0] ]._aData :
  7055. undefined;
  7056. }
  7057. // Set
  7058. var row = ctx[0].aoData[ this[0] ];
  7059. row._aData = data;
  7060. // If the DOM has an id, and the data source is an array
  7061. if ( Array.isArray( data ) && row.nTr && row.nTr.id ) {
  7062. _fnSetObjectDataFn( ctx[0].rowId )( data, row.nTr.id );
  7063. }
  7064. // Automatically invalidate
  7065. _fnInvalidate( ctx[0], this[0], 'data' );
  7066. return this;
  7067. } );
  7068. _api_register( 'row().node()', function () {
  7069. var ctx = this.context;
  7070. return ctx.length && this.length ?
  7071. ctx[0].aoData[ this[0] ].nTr || null :
  7072. null;
  7073. } );
  7074. _api_register( 'row.add()', function ( row ) {
  7075. // Allow a jQuery object to be passed in - only a single row is added from
  7076. // it though - the first element in the set
  7077. if ( row instanceof $ && row.length ) {
  7078. row = row[0];
  7079. }
  7080. var rows = this.iterator( 'table', function ( settings ) {
  7081. if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
  7082. return _fnAddTr( settings, row )[0];
  7083. }
  7084. return _fnAddData( settings, row );
  7085. } );
  7086. // Return an Api.rows() extended instance, with the newly added row selected
  7087. return this.row( rows[0] );
  7088. } );
  7089. $(document).on('plugin-init.dt', function (e, context) {
  7090. var api = new _Api( context );
  7091. api.on( 'stateSaveParams', function ( e, settings, d ) {
  7092. // This could be more compact with the API, but it is a lot faster as a simple
  7093. // internal loop
  7094. var idFn = settings.rowIdFn;
  7095. var data = settings.aoData;
  7096. var ids = [];
  7097. for (var i=0 ; i<data.length ; i++) {
  7098. if (data[i]._detailsShow) {
  7099. ids.push( '#' + idFn(data[i]._aData) );
  7100. }
  7101. }
  7102. d.childRows = ids;
  7103. })
  7104. var loaded = api.state.loaded();
  7105. if ( loaded && loaded.childRows ) {
  7106. api
  7107. .rows( $.map(loaded.childRows, function (id){
  7108. return id.replace(/:/g, '\\:')
  7109. }) )
  7110. .every( function () {
  7111. _fnCallbackFire( context, null, 'requestChild', [ this ] )
  7112. });
  7113. }
  7114. });
  7115. var __details_add = function ( ctx, row, data, klass )
  7116. {
  7117. // Convert to array of TR elements
  7118. var rows = [];
  7119. var addRow = function ( r, k ) {
  7120. // Recursion to allow for arrays of jQuery objects
  7121. if ( Array.isArray( r ) || r instanceof $ ) {
  7122. for ( var i=0, ien=r.length ; i<ien ; i++ ) {
  7123. addRow( r[i], k );
  7124. }
  7125. return;
  7126. }
  7127. // If we get a TR element, then just add it directly - up to the dev
  7128. // to add the correct number of columns etc
  7129. if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
  7130. rows.push( r );
  7131. }
  7132. else {
  7133. // Otherwise create a row with a wrapper
  7134. var created = $('<tr><td></td></tr>').addClass( k );
  7135. $('td', created)
  7136. .addClass( k )
  7137. .html( r )
  7138. [0].colSpan = _fnVisbleColumns( ctx );
  7139. rows.push( created[0] );
  7140. }
  7141. };
  7142. addRow( data, klass );
  7143. if ( row._details ) {
  7144. row._details.detach();
  7145. }
  7146. row._details = $(rows);
  7147. // If the children were already shown, that state should be retained
  7148. if ( row._detailsShow ) {
  7149. row._details.insertAfter( row.nTr );
  7150. }
  7151. };
  7152. // Make state saving of child row details async to allow them to be batch processed
  7153. var __details_state = DataTable.util.throttle(
  7154. function (ctx) {
  7155. _fnSaveState( ctx[0] )
  7156. },
  7157. 500
  7158. );
  7159. var __details_remove = function ( api, idx )
  7160. {
  7161. var ctx = api.context;
  7162. if ( ctx.length ) {
  7163. var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
  7164. if ( row && row._details ) {
  7165. row._details.remove();
  7166. row._detailsShow = undefined;
  7167. row._details = undefined;
  7168. $( row.nTr ).removeClass( 'dt-hasChild' );
  7169. __details_state( ctx );
  7170. }
  7171. }
  7172. };
  7173. var __details_display = function ( api, show ) {
  7174. var ctx = api.context;
  7175. if ( ctx.length && api.length ) {
  7176. var row = ctx[0].aoData[ api[0] ];
  7177. if ( row._details ) {
  7178. row._detailsShow = show;
  7179. if ( show ) {
  7180. row._details.insertAfter( row.nTr );
  7181. $( row.nTr ).addClass( 'dt-hasChild' );
  7182. }
  7183. else {
  7184. row._details.detach();
  7185. $( row.nTr ).removeClass( 'dt-hasChild' );
  7186. }
  7187. _fnCallbackFire( ctx[0], null, 'childRow', [ show, api.row( api[0] ) ] )
  7188. __details_events( ctx[0] );
  7189. __details_state( ctx );
  7190. }
  7191. }
  7192. };
  7193. var __details_events = function ( settings )
  7194. {
  7195. var api = new _Api( settings );
  7196. var namespace = '.dt.DT_details';
  7197. var drawEvent = 'draw'+namespace;
  7198. var colvisEvent = 'column-sizing'+namespace;
  7199. var destroyEvent = 'destroy'+namespace;
  7200. var data = settings.aoData;
  7201. api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
  7202. if ( _pluck( data, '_details' ).length > 0 ) {
  7203. // On each draw, insert the required elements into the document
  7204. api.on( drawEvent, function ( e, ctx ) {
  7205. if ( settings !== ctx ) {
  7206. return;
  7207. }
  7208. api.rows( {page:'current'} ).eq(0).each( function (idx) {
  7209. // Internal data grab
  7210. var row = data[ idx ];
  7211. if ( row._detailsShow ) {
  7212. row._details.insertAfter( row.nTr );
  7213. }
  7214. } );
  7215. } );
  7216. // Column visibility change - update the colspan
  7217. api.on( colvisEvent, function ( e, ctx, idx, vis ) {
  7218. if ( settings !== ctx ) {
  7219. return;
  7220. }
  7221. // Update the colspan for the details rows (note, only if it already has
  7222. // a colspan)
  7223. var row, visible = _fnVisbleColumns( ctx );
  7224. for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  7225. row = data[i];
  7226. if ( row._details ) {
  7227. row._details.children('td[colspan]').attr('colspan', visible );
  7228. }
  7229. }
  7230. } );
  7231. // Table destroyed - nuke any child rows
  7232. api.on( destroyEvent, function ( e, ctx ) {
  7233. if ( settings !== ctx ) {
  7234. return;
  7235. }
  7236. for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  7237. if ( data[i]._details ) {
  7238. __details_remove( api, i );
  7239. }
  7240. }
  7241. } );
  7242. }
  7243. };
  7244. // Strings for the method names to help minification
  7245. var _emp = '';
  7246. var _child_obj = _emp+'row().child';
  7247. var _child_mth = _child_obj+'()';
  7248. // data can be:
  7249. // tr
  7250. // string
  7251. // jQuery or array of any of the above
  7252. _api_register( _child_mth, function ( data, klass ) {
  7253. var ctx = this.context;
  7254. if ( data === undefined ) {
  7255. // get
  7256. return ctx.length && this.length ?
  7257. ctx[0].aoData[ this[0] ]._details :
  7258. undefined;
  7259. }
  7260. else if ( data === true ) {
  7261. // show
  7262. this.child.show();
  7263. }
  7264. else if ( data === false ) {
  7265. // remove
  7266. __details_remove( this );
  7267. }
  7268. else if ( ctx.length && this.length ) {
  7269. // set
  7270. __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
  7271. }
  7272. return this;
  7273. } );
  7274. _api_register( [
  7275. _child_obj+'.show()',
  7276. _child_mth+'.show()' // only when `child()` was called with parameters (without
  7277. ], function ( show ) { // it returns an object and this method is not executed)
  7278. __details_display( this, true );
  7279. return this;
  7280. } );
  7281. _api_register( [
  7282. _child_obj+'.hide()',
  7283. _child_mth+'.hide()' // only when `child()` was called with parameters (without
  7284. ], function () { // it returns an object and this method is not executed)
  7285. __details_display( this, false );
  7286. return this;
  7287. } );
  7288. _api_register( [
  7289. _child_obj+'.remove()',
  7290. _child_mth+'.remove()' // only when `child()` was called with parameters (without
  7291. ], function () { // it returns an object and this method is not executed)
  7292. __details_remove( this );
  7293. return this;
  7294. } );
  7295. _api_register( _child_obj+'.isShown()', function () {
  7296. var ctx = this.context;
  7297. if ( ctx.length && this.length ) {
  7298. // _detailsShown as false or undefined will fall through to return false
  7299. return ctx[0].aoData[ this[0] ]._detailsShow || false;
  7300. }
  7301. return false;
  7302. } );
  7303. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  7304. * Columns
  7305. *
  7306. * {integer} - column index (>=0 count from left, <0 count from right)
  7307. * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right)
  7308. * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right)
  7309. * "{string}:name" - column name
  7310. * "{string}" - jQuery selector on column header nodes
  7311. *
  7312. */
  7313. // can be an array of these items, comma separated list, or an array of comma
  7314. // separated lists
  7315. var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
  7316. // r1 and r2 are redundant - but it means that the parameters match for the
  7317. // iterator callback in columns().data()
  7318. var __columnData = function ( settings, column, r1, r2, rows ) {
  7319. var a = [];
  7320. for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
  7321. a.push( _fnGetCellData( settings, rows[row], column ) );
  7322. }
  7323. return a;
  7324. };
  7325. var __column_selector = function ( settings, selector, opts )
  7326. {
  7327. var
  7328. columns = settings.aoColumns,
  7329. names = _pluck( columns, 'sName' ),
  7330. nodes = _pluck( columns, 'nTh' );
  7331. var run = function ( s ) {
  7332. var selInt = _intVal( s );
  7333. // Selector - all
  7334. if ( s === '' ) {
  7335. return _range( columns.length );
  7336. }
  7337. // Selector - index
  7338. if ( selInt !== null ) {
  7339. return [ selInt >= 0 ?
  7340. selInt : // Count from left
  7341. columns.length + selInt // Count from right (+ because its a negative value)
  7342. ];
  7343. }
  7344. // Selector = function
  7345. if ( typeof s === 'function' ) {
  7346. var rows = _selector_row_indexes( settings, opts );
  7347. return $.map( columns, function (col, idx) {
  7348. return s(
  7349. idx,
  7350. __columnData( settings, idx, 0, 0, rows ),
  7351. nodes[ idx ]
  7352. ) ? idx : null;
  7353. } );
  7354. }
  7355. // jQuery or string selector
  7356. var match = typeof s === 'string' ?
  7357. s.match( __re_column_selector ) :
  7358. '';
  7359. if ( match ) {
  7360. switch( match[2] ) {
  7361. case 'visIdx':
  7362. case 'visible':
  7363. var idx = parseInt( match[1], 10 );
  7364. // Visible index given, convert to column index
  7365. if ( idx < 0 ) {
  7366. // Counting from the right
  7367. var visColumns = $.map( columns, function (col,i) {
  7368. return col.bVisible ? i : null;
  7369. } );
  7370. return [ visColumns[ visColumns.length + idx ] ];
  7371. }
  7372. // Counting from the left
  7373. return [ _fnVisibleToColumnIndex( settings, idx ) ];
  7374. case 'name':
  7375. // match by name. `names` is column index complete and in order
  7376. return $.map( names, function (name, i) {
  7377. return name === match[1] ? i : null;
  7378. } );
  7379. default:
  7380. return [];
  7381. }
  7382. }
  7383. // Cell in the table body
  7384. if ( s.nodeName && s._DT_CellIndex ) {
  7385. return [ s._DT_CellIndex.column ];
  7386. }
  7387. // jQuery selector on the TH elements for the columns
  7388. var jqResult = $( nodes )
  7389. .filter( s )
  7390. .map( function () {
  7391. return $.inArray( this, nodes ); // `nodes` is column index complete and in order
  7392. } )
  7393. .toArray();
  7394. if ( jqResult.length || ! s.nodeName ) {
  7395. return jqResult;
  7396. }
  7397. // Otherwise a node which might have a `dt-column` data attribute, or be
  7398. // a child or such an element
  7399. var host = $(s).closest('*[data-dt-column]');
  7400. return host.length ?
  7401. [ host.data('dt-column') ] :
  7402. [];
  7403. };
  7404. return _selector_run( 'column', selector, run, settings, opts );
  7405. };
  7406. var __setColumnVis = function ( settings, column, vis ) {
  7407. var
  7408. cols = settings.aoColumns,
  7409. col = cols[ column ],
  7410. data = settings.aoData,
  7411. row, cells, i, ien, tr;
  7412. // Get
  7413. if ( vis === undefined ) {
  7414. return col.bVisible;
  7415. }
  7416. // Set
  7417. // No change
  7418. if ( col.bVisible === vis ) {
  7419. return;
  7420. }
  7421. if ( vis ) {
  7422. // Insert column
  7423. // Need to decide if we should use appendChild or insertBefore
  7424. var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
  7425. for ( i=0, ien=data.length ; i<ien ; i++ ) {
  7426. tr = data[i].nTr;
  7427. cells = data[i].anCells;
  7428. if ( tr ) {
  7429. // insertBefore can act like appendChild if 2nd arg is null
  7430. tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
  7431. }
  7432. }
  7433. }
  7434. else {
  7435. // Remove column
  7436. $( _pluck( settings.aoData, 'anCells', column ) ).detach();
  7437. }
  7438. // Common actions
  7439. col.bVisible = vis;
  7440. };
  7441. _api_register( 'columns()', function ( selector, opts ) {
  7442. // argument shifting
  7443. if ( selector === undefined ) {
  7444. selector = '';
  7445. }
  7446. else if ( $.isPlainObject( selector ) ) {
  7447. opts = selector;
  7448. selector = '';
  7449. }
  7450. opts = _selector_opts( opts );
  7451. var inst = this.iterator( 'table', function ( settings ) {
  7452. return __column_selector( settings, selector, opts );
  7453. }, 1 );
  7454. // Want argument shifting here and in _row_selector?
  7455. inst.selector.cols = selector;
  7456. inst.selector.opts = opts;
  7457. return inst;
  7458. } );
  7459. _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
  7460. return this.iterator( 'column', function ( settings, column ) {
  7461. return settings.aoColumns[column].nTh;
  7462. }, 1 );
  7463. } );
  7464. _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
  7465. return this.iterator( 'column', function ( settings, column ) {
  7466. return settings.aoColumns[column].nTf;
  7467. }, 1 );
  7468. } );
  7469. _api_registerPlural( 'columns().data()', 'column().data()', function () {
  7470. return this.iterator( 'column-rows', __columnData, 1 );
  7471. } );
  7472. _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
  7473. return this.iterator( 'column', function ( settings, column ) {
  7474. return settings.aoColumns[column].mData;
  7475. }, 1 );
  7476. } );
  7477. _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
  7478. return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
  7479. return _pluck_order( settings.aoData, rows,
  7480. type === 'search' ? '_aFilterData' : '_aSortData', column
  7481. );
  7482. }, 1 );
  7483. } );
  7484. _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
  7485. return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
  7486. return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
  7487. }, 1 );
  7488. } );
  7489. _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
  7490. var that = this;
  7491. var ret = this.iterator( 'column', function ( settings, column ) {
  7492. if ( vis === undefined ) {
  7493. return settings.aoColumns[ column ].bVisible;
  7494. } // else
  7495. __setColumnVis( settings, column, vis );
  7496. } );
  7497. // Group the column visibility changes
  7498. if ( vis !== undefined ) {
  7499. this.iterator( 'table', function ( settings ) {
  7500. // Redraw the header after changes
  7501. _fnDrawHead( settings, settings.aoHeader );
  7502. _fnDrawHead( settings, settings.aoFooter );
  7503. // Update colspan for no records display. Child rows and extensions will use their own
  7504. // listeners to do this - only need to update the empty table item here
  7505. if ( ! settings.aiDisplay.length ) {
  7506. $(settings.nTBody).find('td[colspan]').attr('colspan', _fnVisbleColumns(settings));
  7507. }
  7508. _fnSaveState( settings );
  7509. // Second loop once the first is done for events
  7510. that.iterator( 'column', function ( settings, column ) {
  7511. _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
  7512. } );
  7513. if ( calc === undefined || calc ) {
  7514. that.columns.adjust();
  7515. }
  7516. });
  7517. }
  7518. return ret;
  7519. } );
  7520. _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
  7521. return this.iterator( 'column', function ( settings, column ) {
  7522. return type === 'visible' ?
  7523. _fnColumnIndexToVisible( settings, column ) :
  7524. column;
  7525. }, 1 );
  7526. } );
  7527. _api_register( 'columns.adjust()', function () {
  7528. return this.iterator( 'table', function ( settings ) {
  7529. _fnAdjustColumnSizing( settings );
  7530. }, 1 );
  7531. } );
  7532. _api_register( 'column.index()', function ( type, idx ) {
  7533. if ( this.context.length !== 0 ) {
  7534. var ctx = this.context[0];
  7535. if ( type === 'fromVisible' || type === 'toData' ) {
  7536. return _fnVisibleToColumnIndex( ctx, idx );
  7537. }
  7538. else if ( type === 'fromData' || type === 'toVisible' ) {
  7539. return _fnColumnIndexToVisible( ctx, idx );
  7540. }
  7541. }
  7542. } );
  7543. _api_register( 'column()', function ( selector, opts ) {
  7544. return _selector_first( this.columns( selector, opts ) );
  7545. } );
  7546. var __cell_selector = function ( settings, selector, opts )
  7547. {
  7548. var data = settings.aoData;
  7549. var rows = _selector_row_indexes( settings, opts );
  7550. var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
  7551. var allCells = $(_flatten( [], cells ));
  7552. var row;
  7553. var columns = settings.aoColumns.length;
  7554. var a, i, ien, j, o, host;
  7555. var run = function ( s ) {
  7556. var fnSelector = typeof s === 'function';
  7557. if ( s === null || s === undefined || fnSelector ) {
  7558. // All cells and function selectors
  7559. a = [];
  7560. for ( i=0, ien=rows.length ; i<ien ; i++ ) {
  7561. row = rows[i];
  7562. for ( j=0 ; j<columns ; j++ ) {
  7563. o = {
  7564. row: row,
  7565. column: j
  7566. };
  7567. if ( fnSelector ) {
  7568. // Selector - function
  7569. host = data[ row ];
  7570. if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
  7571. a.push( o );
  7572. }
  7573. }
  7574. else {
  7575. // Selector - all
  7576. a.push( o );
  7577. }
  7578. }
  7579. }
  7580. return a;
  7581. }
  7582. // Selector - index
  7583. if ( $.isPlainObject( s ) ) {
  7584. // Valid cell index and its in the array of selectable rows
  7585. return s.column !== undefined && s.row !== undefined && $.inArray( s.row, rows ) !== -1 ?
  7586. [s] :
  7587. [];
  7588. }
  7589. // Selector - jQuery filtered cells
  7590. var jqResult = allCells
  7591. .filter( s )
  7592. .map( function (i, el) {
  7593. return { // use a new object, in case someone changes the values
  7594. row: el._DT_CellIndex.row,
  7595. column: el._DT_CellIndex.column
  7596. };
  7597. } )
  7598. .toArray();
  7599. if ( jqResult.length || ! s.nodeName ) {
  7600. return jqResult;
  7601. }
  7602. // Otherwise the selector is a node, and there is one last option - the
  7603. // element might be a child of an element which has dt-row and dt-column
  7604. // data attributes
  7605. host = $(s).closest('*[data-dt-row]');
  7606. return host.length ?
  7607. [ {
  7608. row: host.data('dt-row'),
  7609. column: host.data('dt-column')
  7610. } ] :
  7611. [];
  7612. };
  7613. return _selector_run( 'cell', selector, run, settings, opts );
  7614. };
  7615. _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
  7616. // Argument shifting
  7617. if ( $.isPlainObject( rowSelector ) ) {
  7618. // Indexes
  7619. if ( rowSelector.row === undefined ) {
  7620. // Selector options in first parameter
  7621. opts = rowSelector;
  7622. rowSelector = null;
  7623. }
  7624. else {
  7625. // Cell index objects in first parameter
  7626. opts = columnSelector;
  7627. columnSelector = null;
  7628. }
  7629. }
  7630. if ( $.isPlainObject( columnSelector ) ) {
  7631. opts = columnSelector;
  7632. columnSelector = null;
  7633. }
  7634. // Cell selector
  7635. if ( columnSelector === null || columnSelector === undefined ) {
  7636. return this.iterator( 'table', function ( settings ) {
  7637. return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
  7638. } );
  7639. }
  7640. // The default built in options need to apply to row and columns
  7641. var internalOpts = opts ? {
  7642. page: opts.page,
  7643. order: opts.order,
  7644. search: opts.search
  7645. } : {};
  7646. // Row + column selector
  7647. var columns = this.columns( columnSelector, internalOpts );
  7648. var rows = this.rows( rowSelector, internalOpts );
  7649. var i, ien, j, jen;
  7650. var cellsNoOpts = this.iterator( 'table', function ( settings, idx ) {
  7651. var a = [];
  7652. for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
  7653. for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
  7654. a.push( {
  7655. row: rows[idx][i],
  7656. column: columns[idx][j]
  7657. } );
  7658. }
  7659. }
  7660. return a;
  7661. }, 1 );
  7662. // There is currently only one extension which uses a cell selector extension
  7663. // It is a _major_ performance drag to run this if it isn't needed, so this is
  7664. // an extension specific check at the moment
  7665. var cells = opts && opts.selected ?
  7666. this.cells( cellsNoOpts, opts ) :
  7667. cellsNoOpts;
  7668. $.extend( cells.selector, {
  7669. cols: columnSelector,
  7670. rows: rowSelector,
  7671. opts: opts
  7672. } );
  7673. return cells;
  7674. } );
  7675. _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
  7676. return this.iterator( 'cell', function ( settings, row, column ) {
  7677. var data = settings.aoData[ row ];
  7678. return data && data.anCells ?
  7679. data.anCells[ column ] :
  7680. undefined;
  7681. }, 1 );
  7682. } );
  7683. _api_register( 'cells().data()', function () {
  7684. return this.iterator( 'cell', function ( settings, row, column ) {
  7685. return _fnGetCellData( settings, row, column );
  7686. }, 1 );
  7687. } );
  7688. _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
  7689. type = type === 'search' ? '_aFilterData' : '_aSortData';
  7690. return this.iterator( 'cell', function ( settings, row, column ) {
  7691. return settings.aoData[ row ][ type ][ column ];
  7692. }, 1 );
  7693. } );
  7694. _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
  7695. return this.iterator( 'cell', function ( settings, row, column ) {
  7696. return _fnGetCellData( settings, row, column, type );
  7697. }, 1 );
  7698. } );
  7699. _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
  7700. return this.iterator( 'cell', function ( settings, row, column ) {
  7701. return {
  7702. row: row,
  7703. column: column,
  7704. columnVisible: _fnColumnIndexToVisible( settings, column )
  7705. };
  7706. }, 1 );
  7707. } );
  7708. _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
  7709. return this.iterator( 'cell', function ( settings, row, column ) {
  7710. _fnInvalidate( settings, row, src, column );
  7711. } );
  7712. } );
  7713. _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
  7714. return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
  7715. } );
  7716. _api_register( 'cell().data()', function ( data ) {
  7717. var ctx = this.context;
  7718. var cell = this[0];
  7719. if ( data === undefined ) {
  7720. // Get
  7721. return ctx.length && cell.length ?
  7722. _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
  7723. undefined;
  7724. }
  7725. // Set
  7726. _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
  7727. _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
  7728. return this;
  7729. } );
  7730. /**
  7731. * Get current ordering (sorting) that has been applied to the table.
  7732. *
  7733. * @returns {array} 2D array containing the sorting information for the first
  7734. * table in the current context. Each element in the parent array represents
  7735. * a column being sorted upon (i.e. multi-sorting with two columns would have
  7736. * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
  7737. * the column index that the sorting condition applies to, the second is the
  7738. * direction of the sort (`desc` or `asc`) and, optionally, the third is the
  7739. * index of the sorting order from the `column.sorting` initialisation array.
  7740. *//**
  7741. * Set the ordering for the table.
  7742. *
  7743. * @param {integer} order Column index to sort upon.
  7744. * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
  7745. * @returns {DataTables.Api} this
  7746. *//**
  7747. * Set the ordering for the table.
  7748. *
  7749. * @param {array} order 1D array of sorting information to be applied.
  7750. * @param {array} [...] Optional additional sorting conditions
  7751. * @returns {DataTables.Api} this
  7752. *//**
  7753. * Set the ordering for the table.
  7754. *
  7755. * @param {array} order 2D array of sorting information to be applied.
  7756. * @returns {DataTables.Api} this
  7757. */
  7758. _api_register( 'order()', function ( order, dir ) {
  7759. var ctx = this.context;
  7760. if ( order === undefined ) {
  7761. // get
  7762. return ctx.length !== 0 ?
  7763. ctx[0].aaSorting :
  7764. undefined;
  7765. }
  7766. // set
  7767. if ( typeof order === 'number' ) {
  7768. // Simple column / direction passed in
  7769. order = [ [ order, dir ] ];
  7770. }
  7771. else if ( order.length && ! Array.isArray( order[0] ) ) {
  7772. // Arguments passed in (list of 1D arrays)
  7773. order = Array.prototype.slice.call( arguments );
  7774. }
  7775. // otherwise a 2D array was passed in
  7776. return this.iterator( 'table', function ( settings ) {
  7777. settings.aaSorting = order.slice();
  7778. } );
  7779. } );
  7780. /**
  7781. * Attach a sort listener to an element for a given column
  7782. *
  7783. * @param {node|jQuery|string} node Identifier for the element(s) to attach the
  7784. * listener to. This can take the form of a single DOM node, a jQuery
  7785. * collection of nodes or a jQuery selector which will identify the node(s).
  7786. * @param {integer} column the column that a click on this node will sort on
  7787. * @param {function} [callback] callback function when sort is run
  7788. * @returns {DataTables.Api} this
  7789. */
  7790. _api_register( 'order.listener()', function ( node, column, callback ) {
  7791. return this.iterator( 'table', function ( settings ) {
  7792. _fnSortAttachListener( settings, node, column, callback );
  7793. } );
  7794. } );
  7795. _api_register( 'order.fixed()', function ( set ) {
  7796. if ( ! set ) {
  7797. var ctx = this.context;
  7798. var fixed = ctx.length ?
  7799. ctx[0].aaSortingFixed :
  7800. undefined;
  7801. return Array.isArray( fixed ) ?
  7802. { pre: fixed } :
  7803. fixed;
  7804. }
  7805. return this.iterator( 'table', function ( settings ) {
  7806. settings.aaSortingFixed = $.extend( true, {}, set );
  7807. } );
  7808. } );
  7809. // Order by the selected column(s)
  7810. _api_register( [
  7811. 'columns().order()',
  7812. 'column().order()'
  7813. ], function ( dir ) {
  7814. var that = this;
  7815. return this.iterator( 'table', function ( settings, i ) {
  7816. var sort = [];
  7817. $.each( that[i], function (j, col) {
  7818. sort.push( [ col, dir ] );
  7819. } );
  7820. settings.aaSorting = sort;
  7821. } );
  7822. } );
  7823. _api_register( 'search()', function ( input, regex, smart, caseInsen ) {
  7824. var ctx = this.context;
  7825. if ( input === undefined ) {
  7826. // get
  7827. return ctx.length !== 0 ?
  7828. ctx[0].oPreviousSearch.sSearch :
  7829. undefined;
  7830. }
  7831. // set
  7832. return this.iterator( 'table', function ( settings ) {
  7833. if ( ! settings.oFeatures.bFilter ) {
  7834. return;
  7835. }
  7836. _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
  7837. "sSearch": input+"",
  7838. "bRegex": regex === null ? false : regex,
  7839. "bSmart": smart === null ? true : smart,
  7840. "bCaseInsensitive": caseInsen === null ? true : caseInsen
  7841. } ), 1 );
  7842. } );
  7843. } );
  7844. _api_registerPlural(
  7845. 'columns().search()',
  7846. 'column().search()',
  7847. function ( input, regex, smart, caseInsen ) {
  7848. return this.iterator( 'column', function ( settings, column ) {
  7849. var preSearch = settings.aoPreSearchCols;
  7850. if ( input === undefined ) {
  7851. // get
  7852. return preSearch[ column ].sSearch;
  7853. }
  7854. // set
  7855. if ( ! settings.oFeatures.bFilter ) {
  7856. return;
  7857. }
  7858. $.extend( preSearch[ column ], {
  7859. "sSearch": input+"",
  7860. "bRegex": regex === null ? false : regex,
  7861. "bSmart": smart === null ? true : smart,
  7862. "bCaseInsensitive": caseInsen === null ? true : caseInsen
  7863. } );
  7864. _fnFilterComplete( settings, settings.oPreviousSearch, 1 );
  7865. } );
  7866. }
  7867. );
  7868. /*
  7869. * State API methods
  7870. */
  7871. _api_register( 'state()', function () {
  7872. return this.context.length ?
  7873. this.context[0].oSavedState :
  7874. null;
  7875. } );
  7876. _api_register( 'state.clear()', function () {
  7877. return this.iterator( 'table', function ( settings ) {
  7878. // Save an empty object
  7879. settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
  7880. } );
  7881. } );
  7882. _api_register( 'state.loaded()', function () {
  7883. return this.context.length ?
  7884. this.context[0].oLoadedState :
  7885. null;
  7886. } );
  7887. _api_register( 'state.save()', function () {
  7888. return this.iterator( 'table', function ( settings ) {
  7889. _fnSaveState( settings );
  7890. } );
  7891. } );
  7892. /**
  7893. * Provide a common method for plug-ins to check the version of DataTables being
  7894. * used, in order to ensure compatibility.
  7895. *
  7896. * @param {string} version Version string to check for, in the format "X.Y.Z".
  7897. * Note that the formats "X" and "X.Y" are also acceptable.
  7898. * @returns {boolean} true if this version of DataTables is greater or equal to
  7899. * the required version, or false if this version of DataTales is not
  7900. * suitable
  7901. * @static
  7902. * @dtopt API-Static
  7903. *
  7904. * @example
  7905. * alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
  7906. */
  7907. DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
  7908. {
  7909. var aThis = DataTable.version.split('.');
  7910. var aThat = version.split('.');
  7911. var iThis, iThat;
  7912. for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
  7913. iThis = parseInt( aThis[i], 10 ) || 0;
  7914. iThat = parseInt( aThat[i], 10 ) || 0;
  7915. // Parts are the same, keep comparing
  7916. if (iThis === iThat) {
  7917. continue;
  7918. }
  7919. // Parts are different, return immediately
  7920. return iThis > iThat;
  7921. }
  7922. return true;
  7923. };
  7924. /**
  7925. * Check if a `<table>` node is a DataTable table already or not.
  7926. *
  7927. * @param {node|jquery|string} table Table node, jQuery object or jQuery
  7928. * selector for the table to test. Note that if more than more than one
  7929. * table is passed on, only the first will be checked
  7930. * @returns {boolean} true the table given is a DataTable, or false otherwise
  7931. * @static
  7932. * @dtopt API-Static
  7933. *
  7934. * @example
  7935. * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
  7936. * $('#example').dataTable();
  7937. * }
  7938. */
  7939. DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
  7940. {
  7941. var t = $(table).get(0);
  7942. var is = false;
  7943. if ( table instanceof DataTable.Api ) {
  7944. return true;
  7945. }
  7946. $.each( DataTable.settings, function (i, o) {
  7947. var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
  7948. var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
  7949. if ( o.nTable === t || head === t || foot === t ) {
  7950. is = true;
  7951. }
  7952. } );
  7953. return is;
  7954. };
  7955. /**
  7956. * Get all DataTable tables that have been initialised - optionally you can
  7957. * select to get only currently visible tables.
  7958. *
  7959. * @param {boolean} [visible=false] Flag to indicate if you want all (default)
  7960. * or visible tables only.
  7961. * @returns {array} Array of `table` nodes (not DataTable instances) which are
  7962. * DataTables
  7963. * @static
  7964. * @dtopt API-Static
  7965. *
  7966. * @example
  7967. * $.each( $.fn.dataTable.tables(true), function () {
  7968. * $(table).DataTable().columns.adjust();
  7969. * } );
  7970. */
  7971. DataTable.tables = DataTable.fnTables = function ( visible )
  7972. {
  7973. var api = false;
  7974. if ( $.isPlainObject( visible ) ) {
  7975. api = visible.api;
  7976. visible = visible.visible;
  7977. }
  7978. var a = $.map( DataTable.settings, function (o) {
  7979. if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
  7980. return o.nTable;
  7981. }
  7982. } );
  7983. return api ?
  7984. new _Api( a ) :
  7985. a;
  7986. };
  7987. /**
  7988. * Convert from camel case parameters to Hungarian notation. This is made public
  7989. * for the extensions to provide the same ability as DataTables core to accept
  7990. * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
  7991. * parameters.
  7992. *
  7993. * @param {object} src The model object which holds all parameters that can be
  7994. * mapped.
  7995. * @param {object} user The object to convert from camel case to Hungarian.
  7996. * @param {boolean} force When set to `true`, properties which already have a
  7997. * Hungarian value in the `user` object will be overwritten. Otherwise they
  7998. * won't be.
  7999. */
  8000. DataTable.camelToHungarian = _fnCamelToHungarian;
  8001. /**
  8002. *
  8003. */
  8004. _api_register( '$()', function ( selector, opts ) {
  8005. var
  8006. rows = this.rows( opts ).nodes(), // Get all rows
  8007. jqRows = $(rows);
  8008. return $( [].concat(
  8009. jqRows.filter( selector ).toArray(),
  8010. jqRows.find( selector ).toArray()
  8011. ) );
  8012. } );
  8013. // jQuery functions to operate on the tables
  8014. $.each( [ 'on', 'one', 'off' ], function (i, key) {
  8015. _api_register( key+'()', function ( /* event, handler */ ) {
  8016. var args = Array.prototype.slice.call(arguments);
  8017. // Add the `dt` namespace automatically if it isn't already present
  8018. args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
  8019. return ! e.match(/\.dt\b/) ?
  8020. e+'.dt' :
  8021. e;
  8022. } ).join( ' ' );
  8023. var inst = $( this.tables().nodes() );
  8024. inst[key].apply( inst, args );
  8025. return this;
  8026. } );
  8027. } );
  8028. _api_register( 'clear()', function () {
  8029. return this.iterator( 'table', function ( settings ) {
  8030. _fnClearTable( settings );
  8031. } );
  8032. } );
  8033. _api_register( 'settings()', function () {
  8034. return new _Api( this.context, this.context );
  8035. } );
  8036. _api_register( 'init()', function () {
  8037. var ctx = this.context;
  8038. return ctx.length ? ctx[0].oInit : null;
  8039. } );
  8040. _api_register( 'data()', function () {
  8041. return this.iterator( 'table', function ( settings ) {
  8042. return _pluck( settings.aoData, '_aData' );
  8043. } ).flatten();
  8044. } );
  8045. _api_register( 'destroy()', function ( remove ) {
  8046. remove = remove || false;
  8047. return this.iterator( 'table', function ( settings ) {
  8048. var classes = settings.oClasses;
  8049. var table = settings.nTable;
  8050. var tbody = settings.nTBody;
  8051. var thead = settings.nTHead;
  8052. var tfoot = settings.nTFoot;
  8053. var jqTable = $(table);
  8054. var jqTbody = $(tbody);
  8055. var jqWrapper = $(settings.nTableWrapper);
  8056. var rows = $.map( settings.aoData, function (r) { return r.nTr; } );
  8057. var i, ien;
  8058. // Flag to note that the table is currently being destroyed - no action
  8059. // should be taken
  8060. settings.bDestroying = true;
  8061. // Fire off the destroy callbacks for plug-ins etc
  8062. _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
  8063. // If not being removed from the document, make all columns visible
  8064. if ( ! remove ) {
  8065. new _Api( settings ).columns().visible( true );
  8066. }
  8067. // Blitz all `DT` namespaced events (these are internal events, the
  8068. // lowercase, `dt` events are user subscribed and they are responsible
  8069. // for removing them
  8070. jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
  8071. $(window).off('.DT-'+settings.sInstance);
  8072. // When scrolling we had to break the table up - restore it
  8073. if ( table != thead.parentNode ) {
  8074. jqTable.children('thead').detach();
  8075. jqTable.append( thead );
  8076. }
  8077. if ( tfoot && table != tfoot.parentNode ) {
  8078. jqTable.children('tfoot').detach();
  8079. jqTable.append( tfoot );
  8080. }
  8081. settings.aaSorting = [];
  8082. settings.aaSortingFixed = [];
  8083. _fnSortingClasses( settings );
  8084. $( rows ).removeClass( settings.asStripeClasses.join(' ') );
  8085. $('th, td', thead).removeClass( classes.sSortable+' '+
  8086. classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
  8087. );
  8088. // Add the TR elements back into the table in their original order
  8089. jqTbody.children().detach();
  8090. jqTbody.append( rows );
  8091. var orig = settings.nTableWrapper.parentNode;
  8092. // Remove the DataTables generated nodes, events and classes
  8093. var removedMethod = remove ? 'remove' : 'detach';
  8094. jqTable[ removedMethod ]();
  8095. jqWrapper[ removedMethod ]();
  8096. // If we need to reattach the table to the document
  8097. if ( ! remove && orig ) {
  8098. // insertBefore acts like appendChild if !arg[1]
  8099. orig.insertBefore( table, settings.nTableReinsertBefore );
  8100. // Restore the width of the original table - was read from the style property,
  8101. // so we can restore directly to that
  8102. jqTable
  8103. .css( 'width', settings.sDestroyWidth )
  8104. .removeClass( classes.sTable );
  8105. // If the were originally stripe classes - then we add them back here.
  8106. // Note this is not fool proof (for example if not all rows had stripe
  8107. // classes - but it's a good effort without getting carried away
  8108. ien = settings.asDestroyStripes.length;
  8109. if ( ien ) {
  8110. jqTbody.children().each( function (i) {
  8111. $(this).addClass( settings.asDestroyStripes[i % ien] );
  8112. } );
  8113. }
  8114. }
  8115. /* Remove the settings object from the settings array */
  8116. var idx = $.inArray( settings, DataTable.settings );
  8117. if ( idx !== -1 ) {
  8118. DataTable.settings.splice( idx, 1 );
  8119. }
  8120. } );
  8121. } );
  8122. // Add the `every()` method for rows, columns and cells in a compact form
  8123. $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
  8124. _api_register( type+'s().every()', function ( fn ) {
  8125. var opts = this.selector.opts;
  8126. var api = this;
  8127. return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
  8128. // Rows and columns:
  8129. // arg1 - index
  8130. // arg2 - table counter
  8131. // arg3 - loop counter
  8132. // arg4 - undefined
  8133. // Cells:
  8134. // arg1 - row index
  8135. // arg2 - column index
  8136. // arg3 - table counter
  8137. // arg4 - loop counter
  8138. fn.call(
  8139. api[ type ](
  8140. arg1,
  8141. type==='cell' ? arg2 : opts,
  8142. type==='cell' ? opts : undefined
  8143. ),
  8144. arg1, arg2, arg3, arg4
  8145. );
  8146. } );
  8147. } );
  8148. } );
  8149. // i18n method for extensions to be able to use the language object from the
  8150. // DataTable
  8151. _api_register( 'i18n()', function ( token, def, plural ) {
  8152. var ctx = this.context[0];
  8153. var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
  8154. if ( resolved === undefined ) {
  8155. resolved = def;
  8156. }
  8157. if ( plural !== undefined && $.isPlainObject( resolved ) ) {
  8158. resolved = resolved[ plural ] !== undefined ?
  8159. resolved[ plural ] :
  8160. resolved._;
  8161. }
  8162. return resolved.replace( '%d', plural ); // nb: plural might be undefined,
  8163. } );
  8164. /**
  8165. * Version string for plug-ins to check compatibility. Allowed format is
  8166. * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
  8167. * only for non-release builds. See http://semver.org/ for more information.
  8168. * @member
  8169. * @type string
  8170. * @default Version number
  8171. */
  8172. DataTable.version = "1.12.0";
  8173. /**
  8174. * Private data store, containing all of the settings objects that are
  8175. * created for the tables on a given page.
  8176. *
  8177. * Note that the `DataTable.settings` object is aliased to
  8178. * `jQuery.fn.dataTableExt` through which it may be accessed and
  8179. * manipulated, or `jQuery.fn.dataTable.settings`.
  8180. * @member
  8181. * @type array
  8182. * @default []
  8183. * @private
  8184. */
  8185. DataTable.settings = [];
  8186. /**
  8187. * Object models container, for the various models that DataTables has
  8188. * available to it. These models define the objects that are used to hold
  8189. * the active state and configuration of the table.
  8190. * @namespace
  8191. */
  8192. DataTable.models = {};
  8193. /**
  8194. * Template object for the way in which DataTables holds information about
  8195. * search information for the global filter and individual column filters.
  8196. * @namespace
  8197. */
  8198. DataTable.models.oSearch = {
  8199. /**
  8200. * Flag to indicate if the filtering should be case insensitive or not
  8201. * @type boolean
  8202. * @default true
  8203. */
  8204. "bCaseInsensitive": true,
  8205. /**
  8206. * Applied search term
  8207. * @type string
  8208. * @default <i>Empty string</i>
  8209. */
  8210. "sSearch": "",
  8211. /**
  8212. * Flag to indicate if the search term should be interpreted as a
  8213. * regular expression (true) or not (false) and therefore and special
  8214. * regex characters escaped.
  8215. * @type boolean
  8216. * @default false
  8217. */
  8218. "bRegex": false,
  8219. /**
  8220. * Flag to indicate if DataTables is to use its smart filtering or not.
  8221. * @type boolean
  8222. * @default true
  8223. */
  8224. "bSmart": true,
  8225. /**
  8226. * Flag to indicate if DataTables should only trigger a search when
  8227. * the return key is pressed.
  8228. * @type boolean
  8229. * @default false
  8230. */
  8231. "return": false
  8232. };
  8233. /**
  8234. * Template object for the way in which DataTables holds information about
  8235. * each individual row. This is the object format used for the settings
  8236. * aoData array.
  8237. * @namespace
  8238. */
  8239. DataTable.models.oRow = {
  8240. /**
  8241. * TR element for the row
  8242. * @type node
  8243. * @default null
  8244. */
  8245. "nTr": null,
  8246. /**
  8247. * Array of TD elements for each row. This is null until the row has been
  8248. * created.
  8249. * @type array nodes
  8250. * @default []
  8251. */
  8252. "anCells": null,
  8253. /**
  8254. * Data object from the original data source for the row. This is either
  8255. * an array if using the traditional form of DataTables, or an object if
  8256. * using mData options. The exact type will depend on the passed in
  8257. * data from the data source, or will be an array if using DOM a data
  8258. * source.
  8259. * @type array|object
  8260. * @default []
  8261. */
  8262. "_aData": [],
  8263. /**
  8264. * Sorting data cache - this array is ostensibly the same length as the
  8265. * number of columns (although each index is generated only as it is
  8266. * needed), and holds the data that is used for sorting each column in the
  8267. * row. We do this cache generation at the start of the sort in order that
  8268. * the formatting of the sort data need be done only once for each cell
  8269. * per sort. This array should not be read from or written to by anything
  8270. * other than the master sorting methods.
  8271. * @type array
  8272. * @default null
  8273. * @private
  8274. */
  8275. "_aSortData": null,
  8276. /**
  8277. * Per cell filtering data cache. As per the sort data cache, used to
  8278. * increase the performance of the filtering in DataTables
  8279. * @type array
  8280. * @default null
  8281. * @private
  8282. */
  8283. "_aFilterData": null,
  8284. /**
  8285. * Filtering data cache. This is the same as the cell filtering cache, but
  8286. * in this case a string rather than an array. This is easily computed with
  8287. * a join on `_aFilterData`, but is provided as a cache so the join isn't
  8288. * needed on every search (memory traded for performance)
  8289. * @type array
  8290. * @default null
  8291. * @private
  8292. */
  8293. "_sFilterRow": null,
  8294. /**
  8295. * Cache of the class name that DataTables has applied to the row, so we
  8296. * can quickly look at this variable rather than needing to do a DOM check
  8297. * on className for the nTr property.
  8298. * @type string
  8299. * @default <i>Empty string</i>
  8300. * @private
  8301. */
  8302. "_sRowStripe": "",
  8303. /**
  8304. * Denote if the original data source was from the DOM, or the data source
  8305. * object. This is used for invalidating data, so DataTables can
  8306. * automatically read data from the original source, unless uninstructed
  8307. * otherwise.
  8308. * @type string
  8309. * @default null
  8310. * @private
  8311. */
  8312. "src": null,
  8313. /**
  8314. * Index in the aoData array. This saves an indexOf lookup when we have the
  8315. * object, but want to know the index
  8316. * @type integer
  8317. * @default -1
  8318. * @private
  8319. */
  8320. "idx": -1
  8321. };
  8322. /**
  8323. * Template object for the column information object in DataTables. This object
  8324. * is held in the settings aoColumns array and contains all the information that
  8325. * DataTables needs about each individual column.
  8326. *
  8327. * Note that this object is related to {@link DataTable.defaults.column}
  8328. * but this one is the internal data store for DataTables's cache of columns.
  8329. * It should NOT be manipulated outside of DataTables. Any configuration should
  8330. * be done through the initialisation options.
  8331. * @namespace
  8332. */
  8333. DataTable.models.oColumn = {
  8334. /**
  8335. * Column index. This could be worked out on-the-fly with $.inArray, but it
  8336. * is faster to just hold it as a variable
  8337. * @type integer
  8338. * @default null
  8339. */
  8340. "idx": null,
  8341. /**
  8342. * A list of the columns that sorting should occur on when this column
  8343. * is sorted. That this property is an array allows multi-column sorting
  8344. * to be defined for a column (for example first name / last name columns
  8345. * would benefit from this). The values are integers pointing to the
  8346. * columns to be sorted on (typically it will be a single integer pointing
  8347. * at itself, but that doesn't need to be the case).
  8348. * @type array
  8349. */
  8350. "aDataSort": null,
  8351. /**
  8352. * Define the sorting directions that are applied to the column, in sequence
  8353. * as the column is repeatedly sorted upon - i.e. the first value is used
  8354. * as the sorting direction when the column if first sorted (clicked on).
  8355. * Sort it again (click again) and it will move on to the next index.
  8356. * Repeat until loop.
  8357. * @type array
  8358. */
  8359. "asSorting": null,
  8360. /**
  8361. * Flag to indicate if the column is searchable, and thus should be included
  8362. * in the filtering or not.
  8363. * @type boolean
  8364. */
  8365. "bSearchable": null,
  8366. /**
  8367. * Flag to indicate if the column is sortable or not.
  8368. * @type boolean
  8369. */
  8370. "bSortable": null,
  8371. /**
  8372. * Flag to indicate if the column is currently visible in the table or not
  8373. * @type boolean
  8374. */
  8375. "bVisible": null,
  8376. /**
  8377. * Store for manual type assignment using the `column.type` option. This
  8378. * is held in store so we can manipulate the column's `sType` property.
  8379. * @type string
  8380. * @default null
  8381. * @private
  8382. */
  8383. "_sManualType": null,
  8384. /**
  8385. * Flag to indicate if HTML5 data attributes should be used as the data
  8386. * source for filtering or sorting. True is either are.
  8387. * @type boolean
  8388. * @default false
  8389. * @private
  8390. */
  8391. "_bAttrSrc": false,
  8392. /**
  8393. * Developer definable function that is called whenever a cell is created (Ajax source,
  8394. * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  8395. * allowing you to modify the DOM element (add background colour for example) when the
  8396. * element is available.
  8397. * @type function
  8398. * @param {element} nTd The TD node that has been created
  8399. * @param {*} sData The Data for the cell
  8400. * @param {array|object} oData The data for the whole row
  8401. * @param {int} iRow The row index for the aoData data store
  8402. * @default null
  8403. */
  8404. "fnCreatedCell": null,
  8405. /**
  8406. * Function to get data from a cell in a column. You should <b>never</b>
  8407. * access data directly through _aData internally in DataTables - always use
  8408. * the method attached to this property. It allows mData to function as
  8409. * required. This function is automatically assigned by the column
  8410. * initialisation method
  8411. * @type function
  8412. * @param {array|object} oData The data array/object for the array
  8413. * (i.e. aoData[]._aData)
  8414. * @param {string} sSpecific The specific data type you want to get -
  8415. * 'display', 'type' 'filter' 'sort'
  8416. * @returns {*} The data for the cell from the given row's data
  8417. * @default null
  8418. */
  8419. "fnGetData": null,
  8420. /**
  8421. * Function to set data for a cell in the column. You should <b>never</b>
  8422. * set the data directly to _aData internally in DataTables - always use
  8423. * this method. It allows mData to function as required. This function
  8424. * is automatically assigned by the column initialisation method
  8425. * @type function
  8426. * @param {array|object} oData The data array/object for the array
  8427. * (i.e. aoData[]._aData)
  8428. * @param {*} sValue Value to set
  8429. * @default null
  8430. */
  8431. "fnSetData": null,
  8432. /**
  8433. * Property to read the value for the cells in the column from the data
  8434. * source array / object. If null, then the default content is used, if a
  8435. * function is given then the return from the function is used.
  8436. * @type function|int|string|null
  8437. * @default null
  8438. */
  8439. "mData": null,
  8440. /**
  8441. * Partner property to mData which is used (only when defined) to get
  8442. * the data - i.e. it is basically the same as mData, but without the
  8443. * 'set' option, and also the data fed to it is the result from mData.
  8444. * This is the rendering method to match the data method of mData.
  8445. * @type function|int|string|null
  8446. * @default null
  8447. */
  8448. "mRender": null,
  8449. /**
  8450. * Unique header TH/TD element for this column - this is what the sorting
  8451. * listener is attached to (if sorting is enabled.)
  8452. * @type node
  8453. * @default null
  8454. */
  8455. "nTh": null,
  8456. /**
  8457. * Unique footer TH/TD element for this column (if there is one). Not used
  8458. * in DataTables as such, but can be used for plug-ins to reference the
  8459. * footer for each column.
  8460. * @type node
  8461. * @default null
  8462. */
  8463. "nTf": null,
  8464. /**
  8465. * The class to apply to all TD elements in the table's TBODY for the column
  8466. * @type string
  8467. * @default null
  8468. */
  8469. "sClass": null,
  8470. /**
  8471. * When DataTables calculates the column widths to assign to each column,
  8472. * it finds the longest string in each column and then constructs a
  8473. * temporary table and reads the widths from that. The problem with this
  8474. * is that "mmm" is much wider then "iiii", but the latter is a longer
  8475. * string - thus the calculation can go wrong (doing it properly and putting
  8476. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  8477. * a "work around" we provide this option. It will append its value to the
  8478. * text that is found to be the longest string for the column - i.e. padding.
  8479. * @type string
  8480. */
  8481. "sContentPadding": null,
  8482. /**
  8483. * Allows a default value to be given for a column's data, and will be used
  8484. * whenever a null data source is encountered (this can be because mData
  8485. * is set to null, or because the data source itself is null).
  8486. * @type string
  8487. * @default null
  8488. */
  8489. "sDefaultContent": null,
  8490. /**
  8491. * Name for the column, allowing reference to the column by name as well as
  8492. * by index (needs a lookup to work by name).
  8493. * @type string
  8494. */
  8495. "sName": null,
  8496. /**
  8497. * Custom sorting data type - defines which of the available plug-ins in
  8498. * afnSortData the custom sorting will use - if any is defined.
  8499. * @type string
  8500. * @default std
  8501. */
  8502. "sSortDataType": 'std',
  8503. /**
  8504. * Class to be applied to the header element when sorting on this column
  8505. * @type string
  8506. * @default null
  8507. */
  8508. "sSortingClass": null,
  8509. /**
  8510. * Class to be applied to the header element when sorting on this column -
  8511. * when jQuery UI theming is used.
  8512. * @type string
  8513. * @default null
  8514. */
  8515. "sSortingClassJUI": null,
  8516. /**
  8517. * Title of the column - what is seen in the TH element (nTh).
  8518. * @type string
  8519. */
  8520. "sTitle": null,
  8521. /**
  8522. * Column sorting and filtering type
  8523. * @type string
  8524. * @default null
  8525. */
  8526. "sType": null,
  8527. /**
  8528. * Width of the column
  8529. * @type string
  8530. * @default null
  8531. */
  8532. "sWidth": null,
  8533. /**
  8534. * Width of the column when it was first "encountered"
  8535. * @type string
  8536. * @default null
  8537. */
  8538. "sWidthOrig": null
  8539. };
  8540. /*
  8541. * Developer note: The properties of the object below are given in Hungarian
  8542. * notation, that was used as the interface for DataTables prior to v1.10, however
  8543. * from v1.10 onwards the primary interface is camel case. In order to avoid
  8544. * breaking backwards compatibility utterly with this change, the Hungarian
  8545. * version is still, internally the primary interface, but is is not documented
  8546. * - hence the @name tags in each doc comment. This allows a Javascript function
  8547. * to create a map from Hungarian notation to camel case (going the other direction
  8548. * would require each property to be listed, which would add around 3K to the size
  8549. * of DataTables, while this method is about a 0.5K hit).
  8550. *
  8551. * Ultimately this does pave the way for Hungarian notation to be dropped
  8552. * completely, but that is a massive amount of work and will break current
  8553. * installs (therefore is on-hold until v2).
  8554. */
  8555. /**
  8556. * Initialisation options that can be given to DataTables at initialisation
  8557. * time.
  8558. * @namespace
  8559. */
  8560. DataTable.defaults = {
  8561. /**
  8562. * An array of data to use for the table, passed in at initialisation which
  8563. * will be used in preference to any data which is already in the DOM. This is
  8564. * particularly useful for constructing tables purely in Javascript, for
  8565. * example with a custom Ajax call.
  8566. * @type array
  8567. * @default null
  8568. *
  8569. * @dtopt Option
  8570. * @name DataTable.defaults.data
  8571. *
  8572. * @example
  8573. * // Using a 2D array data source
  8574. * $(document).ready( function () {
  8575. * $('#example').dataTable( {
  8576. * "data": [
  8577. * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
  8578. * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
  8579. * ],
  8580. * "columns": [
  8581. * { "title": "Engine" },
  8582. * { "title": "Browser" },
  8583. * { "title": "Platform" },
  8584. * { "title": "Version" },
  8585. * { "title": "Grade" }
  8586. * ]
  8587. * } );
  8588. * } );
  8589. *
  8590. * @example
  8591. * // Using an array of objects as a data source (`data`)
  8592. * $(document).ready( function () {
  8593. * $('#example').dataTable( {
  8594. * "data": [
  8595. * {
  8596. * "engine": "Trident",
  8597. * "browser": "Internet Explorer 4.0",
  8598. * "platform": "Win 95+",
  8599. * "version": 4,
  8600. * "grade": "X"
  8601. * },
  8602. * {
  8603. * "engine": "Trident",
  8604. * "browser": "Internet Explorer 5.0",
  8605. * "platform": "Win 95+",
  8606. * "version": 5,
  8607. * "grade": "C"
  8608. * }
  8609. * ],
  8610. * "columns": [
  8611. * { "title": "Engine", "data": "engine" },
  8612. * { "title": "Browser", "data": "browser" },
  8613. * { "title": "Platform", "data": "platform" },
  8614. * { "title": "Version", "data": "version" },
  8615. * { "title": "Grade", "data": "grade" }
  8616. * ]
  8617. * } );
  8618. * } );
  8619. */
  8620. "aaData": null,
  8621. /**
  8622. * If ordering is enabled, then DataTables will perform a first pass sort on
  8623. * initialisation. You can define which column(s) the sort is performed
  8624. * upon, and the sorting direction, with this variable. The `sorting` array
  8625. * should contain an array for each column to be sorted initially containing
  8626. * the column's index and a direction string ('asc' or 'desc').
  8627. * @type array
  8628. * @default [[0,'asc']]
  8629. *
  8630. * @dtopt Option
  8631. * @name DataTable.defaults.order
  8632. *
  8633. * @example
  8634. * // Sort by 3rd column first, and then 4th column
  8635. * $(document).ready( function() {
  8636. * $('#example').dataTable( {
  8637. * "order": [[2,'asc'], [3,'desc']]
  8638. * } );
  8639. * } );
  8640. *
  8641. * // No initial sorting
  8642. * $(document).ready( function() {
  8643. * $('#example').dataTable( {
  8644. * "order": []
  8645. * } );
  8646. * } );
  8647. */
  8648. "aaSorting": [[0,'asc']],
  8649. /**
  8650. * This parameter is basically identical to the `sorting` parameter, but
  8651. * cannot be overridden by user interaction with the table. What this means
  8652. * is that you could have a column (visible or hidden) which the sorting
  8653. * will always be forced on first - any sorting after that (from the user)
  8654. * will then be performed as required. This can be useful for grouping rows
  8655. * together.
  8656. * @type array
  8657. * @default null
  8658. *
  8659. * @dtopt Option
  8660. * @name DataTable.defaults.orderFixed
  8661. *
  8662. * @example
  8663. * $(document).ready( function() {
  8664. * $('#example').dataTable( {
  8665. * "orderFixed": [[0,'asc']]
  8666. * } );
  8667. * } )
  8668. */
  8669. "aaSortingFixed": [],
  8670. /**
  8671. * DataTables can be instructed to load data to display in the table from a
  8672. * Ajax source. This option defines how that Ajax call is made and where to.
  8673. *
  8674. * The `ajax` property has three different modes of operation, depending on
  8675. * how it is defined. These are:
  8676. *
  8677. * * `string` - Set the URL from where the data should be loaded from.
  8678. * * `object` - Define properties for `jQuery.ajax`.
  8679. * * `function` - Custom data get function
  8680. *
  8681. * `string`
  8682. * --------
  8683. *
  8684. * As a string, the `ajax` property simply defines the URL from which
  8685. * DataTables will load data.
  8686. *
  8687. * `object`
  8688. * --------
  8689. *
  8690. * As an object, the parameters in the object are passed to
  8691. * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
  8692. * of the Ajax request. DataTables has a number of default parameters which
  8693. * you can override using this option. Please refer to the jQuery
  8694. * documentation for a full description of the options available, although
  8695. * the following parameters provide additional options in DataTables or
  8696. * require special consideration:
  8697. *
  8698. * * `data` - As with jQuery, `data` can be provided as an object, but it
  8699. * can also be used as a function to manipulate the data DataTables sends
  8700. * to the server. The function takes a single parameter, an object of
  8701. * parameters with the values that DataTables has readied for sending. An
  8702. * object may be returned which will be merged into the DataTables
  8703. * defaults, or you can add the items to the object that was passed in and
  8704. * not return anything from the function. This supersedes `fnServerParams`
  8705. * from DataTables 1.9-.
  8706. *
  8707. * * `dataSrc` - By default DataTables will look for the property `data` (or
  8708. * `aaData` for compatibility with DataTables 1.9-) when obtaining data
  8709. * from an Ajax source or for server-side processing - this parameter
  8710. * allows that property to be changed. You can use Javascript dotted
  8711. * object notation to get a data source for multiple levels of nesting, or
  8712. * it my be used as a function. As a function it takes a single parameter,
  8713. * the JSON returned from the server, which can be manipulated as
  8714. * required, with the returned value being that used by DataTables as the
  8715. * data source for the table. This supersedes `sAjaxDataProp` from
  8716. * DataTables 1.9-.
  8717. *
  8718. * * `success` - Should not be overridden it is used internally in
  8719. * DataTables. To manipulate / transform the data returned by the server
  8720. * use `ajax.dataSrc`, or use `ajax` as a function (see below).
  8721. *
  8722. * `function`
  8723. * ----------
  8724. *
  8725. * As a function, making the Ajax call is left up to yourself allowing
  8726. * complete control of the Ajax request. Indeed, if desired, a method other
  8727. * than Ajax could be used to obtain the required data, such as Web storage
  8728. * or an AIR database.
  8729. *
  8730. * The function is given four parameters and no return is required. The
  8731. * parameters are:
  8732. *
  8733. * 1. _object_ - Data to send to the server
  8734. * 2. _function_ - Callback function that must be executed when the required
  8735. * data has been obtained. That data should be passed into the callback
  8736. * as the only parameter
  8737. * 3. _object_ - DataTables settings object for the table
  8738. *
  8739. * Note that this supersedes `fnServerData` from DataTables 1.9-.
  8740. *
  8741. * @type string|object|function
  8742. * @default null
  8743. *
  8744. * @dtopt Option
  8745. * @name DataTable.defaults.ajax
  8746. * @since 1.10.0
  8747. *
  8748. * @example
  8749. * // Get JSON data from a file via Ajax.
  8750. * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
  8751. * $('#example').dataTable( {
  8752. * "ajax": "data.json"
  8753. * } );
  8754. *
  8755. * @example
  8756. * // Get JSON data from a file via Ajax, using `dataSrc` to change
  8757. * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
  8758. * $('#example').dataTable( {
  8759. * "ajax": {
  8760. * "url": "data.json",
  8761. * "dataSrc": "tableData"
  8762. * }
  8763. * } );
  8764. *
  8765. * @example
  8766. * // Get JSON data from a file via Ajax, using `dataSrc` to read data
  8767. * // from a plain array rather than an array in an object
  8768. * $('#example').dataTable( {
  8769. * "ajax": {
  8770. * "url": "data.json",
  8771. * "dataSrc": ""
  8772. * }
  8773. * } );
  8774. *
  8775. * @example
  8776. * // Manipulate the data returned from the server - add a link to data
  8777. * // (note this can, should, be done using `render` for the column - this
  8778. * // is just a simple example of how the data can be manipulated).
  8779. * $('#example').dataTable( {
  8780. * "ajax": {
  8781. * "url": "data.json",
  8782. * "dataSrc": function ( json ) {
  8783. * for ( var i=0, ien=json.length ; i<ien ; i++ ) {
  8784. * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
  8785. * }
  8786. * return json;
  8787. * }
  8788. * }
  8789. * } );
  8790. *
  8791. * @example
  8792. * // Add data to the request
  8793. * $('#example').dataTable( {
  8794. * "ajax": {
  8795. * "url": "data.json",
  8796. * "data": function ( d ) {
  8797. * return {
  8798. * "extra_search": $('#extra').val()
  8799. * };
  8800. * }
  8801. * }
  8802. * } );
  8803. *
  8804. * @example
  8805. * // Send request as POST
  8806. * $('#example').dataTable( {
  8807. * "ajax": {
  8808. * "url": "data.json",
  8809. * "type": "POST"
  8810. * }
  8811. * } );
  8812. *
  8813. * @example
  8814. * // Get the data from localStorage (could interface with a form for
  8815. * // adding, editing and removing rows).
  8816. * $('#example').dataTable( {
  8817. * "ajax": function (data, callback, settings) {
  8818. * callback(
  8819. * JSON.parse( localStorage.getItem('dataTablesData') )
  8820. * );
  8821. * }
  8822. * } );
  8823. */
  8824. "ajax": null,
  8825. /**
  8826. * This parameter allows you to readily specify the entries in the length drop
  8827. * down menu that DataTables shows when pagination is enabled. It can be
  8828. * either a 1D array of options which will be used for both the displayed
  8829. * option and the value, or a 2D array which will use the array in the first
  8830. * position as the value, and the array in the second position as the
  8831. * displayed options (useful for language strings such as 'All').
  8832. *
  8833. * Note that the `pageLength` property will be automatically set to the
  8834. * first value given in this array, unless `pageLength` is also provided.
  8835. * @type array
  8836. * @default [ 10, 25, 50, 100 ]
  8837. *
  8838. * @dtopt Option
  8839. * @name DataTable.defaults.lengthMenu
  8840. *
  8841. * @example
  8842. * $(document).ready( function() {
  8843. * $('#example').dataTable( {
  8844. * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
  8845. * } );
  8846. * } );
  8847. */
  8848. "aLengthMenu": [ 10, 25, 50, 100 ],
  8849. /**
  8850. * The `columns` option in the initialisation parameter allows you to define
  8851. * details about the way individual columns behave. For a full list of
  8852. * column options that can be set, please see
  8853. * {@link DataTable.defaults.column}. Note that if you use `columns` to
  8854. * define your columns, you must have an entry in the array for every single
  8855. * column that you have in your table (these can be null if you don't which
  8856. * to specify any options).
  8857. * @member
  8858. *
  8859. * @name DataTable.defaults.column
  8860. */
  8861. "aoColumns": null,
  8862. /**
  8863. * Very similar to `columns`, `columnDefs` allows you to target a specific
  8864. * column, multiple columns, or all columns, using the `targets` property of
  8865. * each object in the array. This allows great flexibility when creating
  8866. * tables, as the `columnDefs` arrays can be of any length, targeting the
  8867. * columns you specifically want. `columnDefs` may use any of the column
  8868. * options available: {@link DataTable.defaults.column}, but it _must_
  8869. * have `targets` defined in each object in the array. Values in the `targets`
  8870. * array may be:
  8871. * <ul>
  8872. * <li>a string - class name will be matched on the TH for the column</li>
  8873. * <li>0 or a positive integer - column index counting from the left</li>
  8874. * <li>a negative integer - column index counting from the right</li>
  8875. * <li>the string "_all" - all columns (i.e. assign a default)</li>
  8876. * </ul>
  8877. * @member
  8878. *
  8879. * @name DataTable.defaults.columnDefs
  8880. */
  8881. "aoColumnDefs": null,
  8882. /**
  8883. * Basically the same as `search`, this parameter defines the individual column
  8884. * filtering state at initialisation time. The array must be of the same size
  8885. * as the number of columns, and each element be an object with the parameters
  8886. * `search` and `escapeRegex` (the latter is optional). 'null' is also
  8887. * accepted and the default will be used.
  8888. * @type array
  8889. * @default []
  8890. *
  8891. * @dtopt Option
  8892. * @name DataTable.defaults.searchCols
  8893. *
  8894. * @example
  8895. * $(document).ready( function() {
  8896. * $('#example').dataTable( {
  8897. * "searchCols": [
  8898. * null,
  8899. * { "search": "My filter" },
  8900. * null,
  8901. * { "search": "^[0-9]", "escapeRegex": false }
  8902. * ]
  8903. * } );
  8904. * } )
  8905. */
  8906. "aoSearchCols": [],
  8907. /**
  8908. * An array of CSS classes that should be applied to displayed rows. This
  8909. * array may be of any length, and DataTables will apply each class
  8910. * sequentially, looping when required.
  8911. * @type array
  8912. * @default null <i>Will take the values determined by the `oClasses.stripe*`
  8913. * options</i>
  8914. *
  8915. * @dtopt Option
  8916. * @name DataTable.defaults.stripeClasses
  8917. *
  8918. * @example
  8919. * $(document).ready( function() {
  8920. * $('#example').dataTable( {
  8921. * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
  8922. * } );
  8923. * } )
  8924. */
  8925. "asStripeClasses": null,
  8926. /**
  8927. * Enable or disable automatic column width calculation. This can be disabled
  8928. * as an optimisation (it takes some time to calculate the widths) if the
  8929. * tables widths are passed in using `columns`.
  8930. * @type boolean
  8931. * @default true
  8932. *
  8933. * @dtopt Features
  8934. * @name DataTable.defaults.autoWidth
  8935. *
  8936. * @example
  8937. * $(document).ready( function () {
  8938. * $('#example').dataTable( {
  8939. * "autoWidth": false
  8940. * } );
  8941. * } );
  8942. */
  8943. "bAutoWidth": true,
  8944. /**
  8945. * Deferred rendering can provide DataTables with a huge speed boost when you
  8946. * are using an Ajax or JS data source for the table. This option, when set to
  8947. * true, will cause DataTables to defer the creation of the table elements for
  8948. * each row until they are needed for a draw - saving a significant amount of
  8949. * time.
  8950. * @type boolean
  8951. * @default false
  8952. *
  8953. * @dtopt Features
  8954. * @name DataTable.defaults.deferRender
  8955. *
  8956. * @example
  8957. * $(document).ready( function() {
  8958. * $('#example').dataTable( {
  8959. * "ajax": "sources/arrays.txt",
  8960. * "deferRender": true
  8961. * } );
  8962. * } );
  8963. */
  8964. "bDeferRender": false,
  8965. /**
  8966. * Replace a DataTable which matches the given selector and replace it with
  8967. * one which has the properties of the new initialisation object passed. If no
  8968. * table matches the selector, then the new DataTable will be constructed as
  8969. * per normal.
  8970. * @type boolean
  8971. * @default false
  8972. *
  8973. * @dtopt Options
  8974. * @name DataTable.defaults.destroy
  8975. *
  8976. * @example
  8977. * $(document).ready( function() {
  8978. * $('#example').dataTable( {
  8979. * "srollY": "200px",
  8980. * "paginate": false
  8981. * } );
  8982. *
  8983. * // Some time later....
  8984. * $('#example').dataTable( {
  8985. * "filter": false,
  8986. * "destroy": true
  8987. * } );
  8988. * } );
  8989. */
  8990. "bDestroy": false,
  8991. /**
  8992. * Enable or disable filtering of data. Filtering in DataTables is "smart" in
  8993. * that it allows the end user to input multiple words (space separated) and
  8994. * will match a row containing those words, even if not in the order that was
  8995. * specified (this allow matching across multiple columns). Note that if you
  8996. * wish to use filtering in DataTables this must remain 'true' - to remove the
  8997. * default filtering input box and retain filtering abilities, please use
  8998. * {@link DataTable.defaults.dom}.
  8999. * @type boolean
  9000. * @default true
  9001. *
  9002. * @dtopt Features
  9003. * @name DataTable.defaults.searching
  9004. *
  9005. * @example
  9006. * $(document).ready( function () {
  9007. * $('#example').dataTable( {
  9008. * "searching": false
  9009. * } );
  9010. * } );
  9011. */
  9012. "bFilter": true,
  9013. /**
  9014. * Enable or disable the table information display. This shows information
  9015. * about the data that is currently visible on the page, including information
  9016. * about filtered data if that action is being performed.
  9017. * @type boolean
  9018. * @default true
  9019. *
  9020. * @dtopt Features
  9021. * @name DataTable.defaults.info
  9022. *
  9023. * @example
  9024. * $(document).ready( function () {
  9025. * $('#example').dataTable( {
  9026. * "info": false
  9027. * } );
  9028. * } );
  9029. */
  9030. "bInfo": true,
  9031. /**
  9032. * Allows the end user to select the size of a formatted page from a select
  9033. * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
  9034. * @type boolean
  9035. * @default true
  9036. *
  9037. * @dtopt Features
  9038. * @name DataTable.defaults.lengthChange
  9039. *
  9040. * @example
  9041. * $(document).ready( function () {
  9042. * $('#example').dataTable( {
  9043. * "lengthChange": false
  9044. * } );
  9045. * } );
  9046. */
  9047. "bLengthChange": true,
  9048. /**
  9049. * Enable or disable pagination.
  9050. * @type boolean
  9051. * @default true
  9052. *
  9053. * @dtopt Features
  9054. * @name DataTable.defaults.paging
  9055. *
  9056. * @example
  9057. * $(document).ready( function () {
  9058. * $('#example').dataTable( {
  9059. * "paging": false
  9060. * } );
  9061. * } );
  9062. */
  9063. "bPaginate": true,
  9064. /**
  9065. * Enable or disable the display of a 'processing' indicator when the table is
  9066. * being processed (e.g. a sort). This is particularly useful for tables with
  9067. * large amounts of data where it can take a noticeable amount of time to sort
  9068. * the entries.
  9069. * @type boolean
  9070. * @default false
  9071. *
  9072. * @dtopt Features
  9073. * @name DataTable.defaults.processing
  9074. *
  9075. * @example
  9076. * $(document).ready( function () {
  9077. * $('#example').dataTable( {
  9078. * "processing": true
  9079. * } );
  9080. * } );
  9081. */
  9082. "bProcessing": false,
  9083. /**
  9084. * Retrieve the DataTables object for the given selector. Note that if the
  9085. * table has already been initialised, this parameter will cause DataTables
  9086. * to simply return the object that has already been set up - it will not take
  9087. * account of any changes you might have made to the initialisation object
  9088. * passed to DataTables (setting this parameter to true is an acknowledgement
  9089. * that you understand this). `destroy` can be used to reinitialise a table if
  9090. * you need.
  9091. * @type boolean
  9092. * @default false
  9093. *
  9094. * @dtopt Options
  9095. * @name DataTable.defaults.retrieve
  9096. *
  9097. * @example
  9098. * $(document).ready( function() {
  9099. * initTable();
  9100. * tableActions();
  9101. * } );
  9102. *
  9103. * function initTable ()
  9104. * {
  9105. * return $('#example').dataTable( {
  9106. * "scrollY": "200px",
  9107. * "paginate": false,
  9108. * "retrieve": true
  9109. * } );
  9110. * }
  9111. *
  9112. * function tableActions ()
  9113. * {
  9114. * var table = initTable();
  9115. * // perform API operations with oTable
  9116. * }
  9117. */
  9118. "bRetrieve": false,
  9119. /**
  9120. * When vertical (y) scrolling is enabled, DataTables will force the height of
  9121. * the table's viewport to the given height at all times (useful for layout).
  9122. * However, this can look odd when filtering data down to a small data set,
  9123. * and the footer is left "floating" further down. This parameter (when
  9124. * enabled) will cause DataTables to collapse the table's viewport down when
  9125. * the result set will fit within the given Y height.
  9126. * @type boolean
  9127. * @default false
  9128. *
  9129. * @dtopt Options
  9130. * @name DataTable.defaults.scrollCollapse
  9131. *
  9132. * @example
  9133. * $(document).ready( function() {
  9134. * $('#example').dataTable( {
  9135. * "scrollY": "200",
  9136. * "scrollCollapse": true
  9137. * } );
  9138. * } );
  9139. */
  9140. "bScrollCollapse": false,
  9141. /**
  9142. * Configure DataTables to use server-side processing. Note that the
  9143. * `ajax` parameter must also be given in order to give DataTables a
  9144. * source to obtain the required data for each draw.
  9145. * @type boolean
  9146. * @default false
  9147. *
  9148. * @dtopt Features
  9149. * @dtopt Server-side
  9150. * @name DataTable.defaults.serverSide
  9151. *
  9152. * @example
  9153. * $(document).ready( function () {
  9154. * $('#example').dataTable( {
  9155. * "serverSide": true,
  9156. * "ajax": "xhr.php"
  9157. * } );
  9158. * } );
  9159. */
  9160. "bServerSide": false,
  9161. /**
  9162. * Enable or disable sorting of columns. Sorting of individual columns can be
  9163. * disabled by the `sortable` option for each column.
  9164. * @type boolean
  9165. * @default true
  9166. *
  9167. * @dtopt Features
  9168. * @name DataTable.defaults.ordering
  9169. *
  9170. * @example
  9171. * $(document).ready( function () {
  9172. * $('#example').dataTable( {
  9173. * "ordering": false
  9174. * } );
  9175. * } );
  9176. */
  9177. "bSort": true,
  9178. /**
  9179. * Enable or display DataTables' ability to sort multiple columns at the
  9180. * same time (activated by shift-click by the user).
  9181. * @type boolean
  9182. * @default true
  9183. *
  9184. * @dtopt Options
  9185. * @name DataTable.defaults.orderMulti
  9186. *
  9187. * @example
  9188. * // Disable multiple column sorting ability
  9189. * $(document).ready( function () {
  9190. * $('#example').dataTable( {
  9191. * "orderMulti": false
  9192. * } );
  9193. * } );
  9194. */
  9195. "bSortMulti": true,
  9196. /**
  9197. * Allows control over whether DataTables should use the top (true) unique
  9198. * cell that is found for a single column, or the bottom (false - default).
  9199. * This is useful when using complex headers.
  9200. * @type boolean
  9201. * @default false
  9202. *
  9203. * @dtopt Options
  9204. * @name DataTable.defaults.orderCellsTop
  9205. *
  9206. * @example
  9207. * $(document).ready( function() {
  9208. * $('#example').dataTable( {
  9209. * "orderCellsTop": true
  9210. * } );
  9211. * } );
  9212. */
  9213. "bSortCellsTop": false,
  9214. /**
  9215. * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
  9216. * `sorting\_3` to the columns which are currently being sorted on. This is
  9217. * presented as a feature switch as it can increase processing time (while
  9218. * classes are removed and added) so for large data sets you might want to
  9219. * turn this off.
  9220. * @type boolean
  9221. * @default true
  9222. *
  9223. * @dtopt Features
  9224. * @name DataTable.defaults.orderClasses
  9225. *
  9226. * @example
  9227. * $(document).ready( function () {
  9228. * $('#example').dataTable( {
  9229. * "orderClasses": false
  9230. * } );
  9231. * } );
  9232. */
  9233. "bSortClasses": true,
  9234. /**
  9235. * Enable or disable state saving. When enabled HTML5 `localStorage` will be
  9236. * used to save table display information such as pagination information,
  9237. * display length, filtering and sorting. As such when the end user reloads
  9238. * the page the display display will match what thy had previously set up.
  9239. *
  9240. * Due to the use of `localStorage` the default state saving is not supported
  9241. * in IE6 or 7. If state saving is required in those browsers, use
  9242. * `stateSaveCallback` to provide a storage solution such as cookies.
  9243. * @type boolean
  9244. * @default false
  9245. *
  9246. * @dtopt Features
  9247. * @name DataTable.defaults.stateSave
  9248. *
  9249. * @example
  9250. * $(document).ready( function () {
  9251. * $('#example').dataTable( {
  9252. * "stateSave": true
  9253. * } );
  9254. * } );
  9255. */
  9256. "bStateSave": false,
  9257. /**
  9258. * This function is called when a TR element is created (and all TD child
  9259. * elements have been inserted), or registered if using a DOM source, allowing
  9260. * manipulation of the TR element (adding classes etc).
  9261. * @type function
  9262. * @param {node} row "TR" element for the current row
  9263. * @param {array} data Raw data array for this row
  9264. * @param {int} dataIndex The index of this row in the internal aoData array
  9265. *
  9266. * @dtopt Callbacks
  9267. * @name DataTable.defaults.createdRow
  9268. *
  9269. * @example
  9270. * $(document).ready( function() {
  9271. * $('#example').dataTable( {
  9272. * "createdRow": function( row, data, dataIndex ) {
  9273. * // Bold the grade for all 'A' grade browsers
  9274. * if ( data[4] == "A" )
  9275. * {
  9276. * $('td:eq(4)', row).html( '<b>A</b>' );
  9277. * }
  9278. * }
  9279. * } );
  9280. * } );
  9281. */
  9282. "fnCreatedRow": null,
  9283. /**
  9284. * This function is called on every 'draw' event, and allows you to
  9285. * dynamically modify any aspect you want about the created DOM.
  9286. * @type function
  9287. * @param {object} settings DataTables settings object
  9288. *
  9289. * @dtopt Callbacks
  9290. * @name DataTable.defaults.drawCallback
  9291. *
  9292. * @example
  9293. * $(document).ready( function() {
  9294. * $('#example').dataTable( {
  9295. * "drawCallback": function( settings ) {
  9296. * alert( 'DataTables has redrawn the table' );
  9297. * }
  9298. * } );
  9299. * } );
  9300. */
  9301. "fnDrawCallback": null,
  9302. /**
  9303. * Identical to fnHeaderCallback() but for the table footer this function
  9304. * allows you to modify the table footer on every 'draw' event.
  9305. * @type function
  9306. * @param {node} foot "TR" element for the footer
  9307. * @param {array} data Full table data (as derived from the original HTML)
  9308. * @param {int} start Index for the current display starting point in the
  9309. * display array
  9310. * @param {int} end Index for the current display ending point in the
  9311. * display array
  9312. * @param {array int} display Index array to translate the visual position
  9313. * to the full data array
  9314. *
  9315. * @dtopt Callbacks
  9316. * @name DataTable.defaults.footerCallback
  9317. *
  9318. * @example
  9319. * $(document).ready( function() {
  9320. * $('#example').dataTable( {
  9321. * "footerCallback": function( tfoot, data, start, end, display ) {
  9322. * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
  9323. * }
  9324. * } );
  9325. * } )
  9326. */
  9327. "fnFooterCallback": null,
  9328. /**
  9329. * When rendering large numbers in the information element for the table
  9330. * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
  9331. * to have a comma separator for the 'thousands' units (e.g. 1 million is
  9332. * rendered as "1,000,000") to help readability for the end user. This
  9333. * function will override the default method DataTables uses.
  9334. * @type function
  9335. * @member
  9336. * @param {int} toFormat number to be formatted
  9337. * @returns {string} formatted string for DataTables to show the number
  9338. *
  9339. * @dtopt Callbacks
  9340. * @name DataTable.defaults.formatNumber
  9341. *
  9342. * @example
  9343. * // Format a number using a single quote for the separator (note that
  9344. * // this can also be done with the language.thousands option)
  9345. * $(document).ready( function() {
  9346. * $('#example').dataTable( {
  9347. * "formatNumber": function ( toFormat ) {
  9348. * return toFormat.toString().replace(
  9349. * /\B(?=(\d{3})+(?!\d))/g, "'"
  9350. * );
  9351. * };
  9352. * } );
  9353. * } );
  9354. */
  9355. "fnFormatNumber": function ( toFormat ) {
  9356. return toFormat.toString().replace(
  9357. /\B(?=(\d{3})+(?!\d))/g,
  9358. this.oLanguage.sThousands
  9359. );
  9360. },
  9361. /**
  9362. * This function is called on every 'draw' event, and allows you to
  9363. * dynamically modify the header row. This can be used to calculate and
  9364. * display useful information about the table.
  9365. * @type function
  9366. * @param {node} head "TR" element for the header
  9367. * @param {array} data Full table data (as derived from the original HTML)
  9368. * @param {int} start Index for the current display starting point in the
  9369. * display array
  9370. * @param {int} end Index for the current display ending point in the
  9371. * display array
  9372. * @param {array int} display Index array to translate the visual position
  9373. * to the full data array
  9374. *
  9375. * @dtopt Callbacks
  9376. * @name DataTable.defaults.headerCallback
  9377. *
  9378. * @example
  9379. * $(document).ready( function() {
  9380. * $('#example').dataTable( {
  9381. * "fheaderCallback": function( head, data, start, end, display ) {
  9382. * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
  9383. * }
  9384. * } );
  9385. * } )
  9386. */
  9387. "fnHeaderCallback": null,
  9388. /**
  9389. * The information element can be used to convey information about the current
  9390. * state of the table. Although the internationalisation options presented by
  9391. * DataTables are quite capable of dealing with most customisations, there may
  9392. * be times where you wish to customise the string further. This callback
  9393. * allows you to do exactly that.
  9394. * @type function
  9395. * @param {object} oSettings DataTables settings object
  9396. * @param {int} start Starting position in data for the draw
  9397. * @param {int} end End position in data for the draw
  9398. * @param {int} max Total number of rows in the table (regardless of
  9399. * filtering)
  9400. * @param {int} total Total number of rows in the data set, after filtering
  9401. * @param {string} pre The string that DataTables has formatted using it's
  9402. * own rules
  9403. * @returns {string} The string to be displayed in the information element.
  9404. *
  9405. * @dtopt Callbacks
  9406. * @name DataTable.defaults.infoCallback
  9407. *
  9408. * @example
  9409. * $('#example').dataTable( {
  9410. * "infoCallback": function( settings, start, end, max, total, pre ) {
  9411. * return start +" to "+ end;
  9412. * }
  9413. * } );
  9414. */
  9415. "fnInfoCallback": null,
  9416. /**
  9417. * Called when the table has been initialised. Normally DataTables will
  9418. * initialise sequentially and there will be no need for this function,
  9419. * however, this does not hold true when using external language information
  9420. * since that is obtained using an async XHR call.
  9421. * @type function
  9422. * @param {object} settings DataTables settings object
  9423. * @param {object} json The JSON object request from the server - only
  9424. * present if client-side Ajax sourced data is used
  9425. *
  9426. * @dtopt Callbacks
  9427. * @name DataTable.defaults.initComplete
  9428. *
  9429. * @example
  9430. * $(document).ready( function() {
  9431. * $('#example').dataTable( {
  9432. * "initComplete": function(settings, json) {
  9433. * alert( 'DataTables has finished its initialisation.' );
  9434. * }
  9435. * } );
  9436. * } )
  9437. */
  9438. "fnInitComplete": null,
  9439. /**
  9440. * Called at the very start of each table draw and can be used to cancel the
  9441. * draw by returning false, any other return (including undefined) results in
  9442. * the full draw occurring).
  9443. * @type function
  9444. * @param {object} settings DataTables settings object
  9445. * @returns {boolean} False will cancel the draw, anything else (including no
  9446. * return) will allow it to complete.
  9447. *
  9448. * @dtopt Callbacks
  9449. * @name DataTable.defaults.preDrawCallback
  9450. *
  9451. * @example
  9452. * $(document).ready( function() {
  9453. * $('#example').dataTable( {
  9454. * "preDrawCallback": function( settings ) {
  9455. * if ( $('#test').val() == 1 ) {
  9456. * return false;
  9457. * }
  9458. * }
  9459. * } );
  9460. * } );
  9461. */
  9462. "fnPreDrawCallback": null,
  9463. /**
  9464. * This function allows you to 'post process' each row after it have been
  9465. * generated for each table draw, but before it is rendered on screen. This
  9466. * function might be used for setting the row class name etc.
  9467. * @type function
  9468. * @param {node} row "TR" element for the current row
  9469. * @param {array} data Raw data array for this row
  9470. * @param {int} displayIndex The display index for the current table draw
  9471. * @param {int} displayIndexFull The index of the data in the full list of
  9472. * rows (after filtering)
  9473. *
  9474. * @dtopt Callbacks
  9475. * @name DataTable.defaults.rowCallback
  9476. *
  9477. * @example
  9478. * $(document).ready( function() {
  9479. * $('#example').dataTable( {
  9480. * "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
  9481. * // Bold the grade for all 'A' grade browsers
  9482. * if ( data[4] == "A" ) {
  9483. * $('td:eq(4)', row).html( '<b>A</b>' );
  9484. * }
  9485. * }
  9486. * } );
  9487. * } );
  9488. */
  9489. "fnRowCallback": null,
  9490. /**
  9491. * __Deprecated__ The functionality provided by this parameter has now been
  9492. * superseded by that provided through `ajax`, which should be used instead.
  9493. *
  9494. * This parameter allows you to override the default function which obtains
  9495. * the data from the server so something more suitable for your application.
  9496. * For example you could use POST data, or pull information from a Gears or
  9497. * AIR database.
  9498. * @type function
  9499. * @member
  9500. * @param {string} source HTTP source to obtain the data from (`ajax`)
  9501. * @param {array} data A key/value pair object containing the data to send
  9502. * to the server
  9503. * @param {function} callback to be called on completion of the data get
  9504. * process that will draw the data on the page.
  9505. * @param {object} settings DataTables settings object
  9506. *
  9507. * @dtopt Callbacks
  9508. * @dtopt Server-side
  9509. * @name DataTable.defaults.serverData
  9510. *
  9511. * @deprecated 1.10. Please use `ajax` for this functionality now.
  9512. */
  9513. "fnServerData": null,
  9514. /**
  9515. * __Deprecated__ The functionality provided by this parameter has now been
  9516. * superseded by that provided through `ajax`, which should be used instead.
  9517. *
  9518. * It is often useful to send extra data to the server when making an Ajax
  9519. * request - for example custom filtering information, and this callback
  9520. * function makes it trivial to send extra information to the server. The
  9521. * passed in parameter is the data set that has been constructed by
  9522. * DataTables, and you can add to this or modify it as you require.
  9523. * @type function
  9524. * @param {array} data Data array (array of objects which are name/value
  9525. * pairs) that has been constructed by DataTables and will be sent to the
  9526. * server. In the case of Ajax sourced data with server-side processing
  9527. * this will be an empty array, for server-side processing there will be a
  9528. * significant number of parameters!
  9529. * @returns {undefined} Ensure that you modify the data array passed in,
  9530. * as this is passed by reference.
  9531. *
  9532. * @dtopt Callbacks
  9533. * @dtopt Server-side
  9534. * @name DataTable.defaults.serverParams
  9535. *
  9536. * @deprecated 1.10. Please use `ajax` for this functionality now.
  9537. */
  9538. "fnServerParams": null,
  9539. /**
  9540. * Load the table state. With this function you can define from where, and how, the
  9541. * state of a table is loaded. By default DataTables will load from `localStorage`
  9542. * but you might wish to use a server-side database or cookies.
  9543. * @type function
  9544. * @member
  9545. * @param {object} settings DataTables settings object
  9546. * @param {object} callback Callback that can be executed when done. It
  9547. * should be passed the loaded state object.
  9548. * @return {object} The DataTables state object to be loaded
  9549. *
  9550. * @dtopt Callbacks
  9551. * @name DataTable.defaults.stateLoadCallback
  9552. *
  9553. * @example
  9554. * $(document).ready( function() {
  9555. * $('#example').dataTable( {
  9556. * "stateSave": true,
  9557. * "stateLoadCallback": function (settings, callback) {
  9558. * $.ajax( {
  9559. * "url": "/state_load",
  9560. * "dataType": "json",
  9561. * "success": function (json) {
  9562. * callback( json );
  9563. * }
  9564. * } );
  9565. * }
  9566. * } );
  9567. * } );
  9568. */
  9569. "fnStateLoadCallback": function ( settings ) {
  9570. try {
  9571. return JSON.parse(
  9572. (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
  9573. 'DataTables_'+settings.sInstance+'_'+location.pathname
  9574. )
  9575. );
  9576. } catch (e) {
  9577. return {};
  9578. }
  9579. },
  9580. /**
  9581. * Callback which allows modification of the saved state prior to loading that state.
  9582. * This callback is called when the table is loading state from the stored data, but
  9583. * prior to the settings object being modified by the saved state. Note that for
  9584. * plug-in authors, you should use the `stateLoadParams` event to load parameters for
  9585. * a plug-in.
  9586. * @type function
  9587. * @param {object} settings DataTables settings object
  9588. * @param {object} data The state object that is to be loaded
  9589. *
  9590. * @dtopt Callbacks
  9591. * @name DataTable.defaults.stateLoadParams
  9592. *
  9593. * @example
  9594. * // Remove a saved filter, so filtering is never loaded
  9595. * $(document).ready( function() {
  9596. * $('#example').dataTable( {
  9597. * "stateSave": true,
  9598. * "stateLoadParams": function (settings, data) {
  9599. * data.oSearch.sSearch = "";
  9600. * }
  9601. * } );
  9602. * } );
  9603. *
  9604. * @example
  9605. * // Disallow state loading by returning false
  9606. * $(document).ready( function() {
  9607. * $('#example').dataTable( {
  9608. * "stateSave": true,
  9609. * "stateLoadParams": function (settings, data) {
  9610. * return false;
  9611. * }
  9612. * } );
  9613. * } );
  9614. */
  9615. "fnStateLoadParams": null,
  9616. /**
  9617. * Callback that is called when the state has been loaded from the state saving method
  9618. * and the DataTables settings object has been modified as a result of the loaded state.
  9619. * @type function
  9620. * @param {object} settings DataTables settings object
  9621. * @param {object} data The state object that was loaded
  9622. *
  9623. * @dtopt Callbacks
  9624. * @name DataTable.defaults.stateLoaded
  9625. *
  9626. * @example
  9627. * // Show an alert with the filtering value that was saved
  9628. * $(document).ready( function() {
  9629. * $('#example').dataTable( {
  9630. * "stateSave": true,
  9631. * "stateLoaded": function (settings, data) {
  9632. * alert( 'Saved filter was: '+data.oSearch.sSearch );
  9633. * }
  9634. * } );
  9635. * } );
  9636. */
  9637. "fnStateLoaded": null,
  9638. /**
  9639. * Save the table state. This function allows you to define where and how the state
  9640. * information for the table is stored By default DataTables will use `localStorage`
  9641. * but you might wish to use a server-side database or cookies.
  9642. * @type function
  9643. * @member
  9644. * @param {object} settings DataTables settings object
  9645. * @param {object} data The state object to be saved
  9646. *
  9647. * @dtopt Callbacks
  9648. * @name DataTable.defaults.stateSaveCallback
  9649. *
  9650. * @example
  9651. * $(document).ready( function() {
  9652. * $('#example').dataTable( {
  9653. * "stateSave": true,
  9654. * "stateSaveCallback": function (settings, data) {
  9655. * // Send an Ajax request to the server with the state object
  9656. * $.ajax( {
  9657. * "url": "/state_save",
  9658. * "data": data,
  9659. * "dataType": "json",
  9660. * "method": "POST"
  9661. * "success": function () {}
  9662. * } );
  9663. * }
  9664. * } );
  9665. * } );
  9666. */
  9667. "fnStateSaveCallback": function ( settings, data ) {
  9668. try {
  9669. (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
  9670. 'DataTables_'+settings.sInstance+'_'+location.pathname,
  9671. JSON.stringify( data )
  9672. );
  9673. } catch (e) {}
  9674. },
  9675. /**
  9676. * Callback which allows modification of the state to be saved. Called when the table
  9677. * has changed state a new state save is required. This method allows modification of
  9678. * the state saving object prior to actually doing the save, including addition or
  9679. * other state properties or modification. Note that for plug-in authors, you should
  9680. * use the `stateSaveParams` event to save parameters for a plug-in.
  9681. * @type function
  9682. * @param {object} settings DataTables settings object
  9683. * @param {object} data The state object to be saved
  9684. *
  9685. * @dtopt Callbacks
  9686. * @name DataTable.defaults.stateSaveParams
  9687. *
  9688. * @example
  9689. * // Remove a saved filter, so filtering is never saved
  9690. * $(document).ready( function() {
  9691. * $('#example').dataTable( {
  9692. * "stateSave": true,
  9693. * "stateSaveParams": function (settings, data) {
  9694. * data.oSearch.sSearch = "";
  9695. * }
  9696. * } );
  9697. * } );
  9698. */
  9699. "fnStateSaveParams": null,
  9700. /**
  9701. * Duration for which the saved state information is considered valid. After this period
  9702. * has elapsed the state will be returned to the default.
  9703. * Value is given in seconds.
  9704. * @type int
  9705. * @default 7200 <i>(2 hours)</i>
  9706. *
  9707. * @dtopt Options
  9708. * @name DataTable.defaults.stateDuration
  9709. *
  9710. * @example
  9711. * $(document).ready( function() {
  9712. * $('#example').dataTable( {
  9713. * "stateDuration": 60*60*24; // 1 day
  9714. * } );
  9715. * } )
  9716. */
  9717. "iStateDuration": 7200,
  9718. /**
  9719. * When enabled DataTables will not make a request to the server for the first
  9720. * page draw - rather it will use the data already on the page (no sorting etc
  9721. * will be applied to it), thus saving on an XHR at load time. `deferLoading`
  9722. * is used to indicate that deferred loading is required, but it is also used
  9723. * to tell DataTables how many records there are in the full table (allowing
  9724. * the information element and pagination to be displayed correctly). In the case
  9725. * where a filtering is applied to the table on initial load, this can be
  9726. * indicated by giving the parameter as an array, where the first element is
  9727. * the number of records available after filtering and the second element is the
  9728. * number of records without filtering (allowing the table information element
  9729. * to be shown correctly).
  9730. * @type int | array
  9731. * @default null
  9732. *
  9733. * @dtopt Options
  9734. * @name DataTable.defaults.deferLoading
  9735. *
  9736. * @example
  9737. * // 57 records available in the table, no filtering applied
  9738. * $(document).ready( function() {
  9739. * $('#example').dataTable( {
  9740. * "serverSide": true,
  9741. * "ajax": "scripts/server_processing.php",
  9742. * "deferLoading": 57
  9743. * } );
  9744. * } );
  9745. *
  9746. * @example
  9747. * // 57 records after filtering, 100 without filtering (an initial filter applied)
  9748. * $(document).ready( function() {
  9749. * $('#example').dataTable( {
  9750. * "serverSide": true,
  9751. * "ajax": "scripts/server_processing.php",
  9752. * "deferLoading": [ 57, 100 ],
  9753. * "search": {
  9754. * "search": "my_filter"
  9755. * }
  9756. * } );
  9757. * } );
  9758. */
  9759. "iDeferLoading": null,
  9760. /**
  9761. * Number of rows to display on a single page when using pagination. If
  9762. * feature enabled (`lengthChange`) then the end user will be able to override
  9763. * this to a custom setting using a pop-up menu.
  9764. * @type int
  9765. * @default 10
  9766. *
  9767. * @dtopt Options
  9768. * @name DataTable.defaults.pageLength
  9769. *
  9770. * @example
  9771. * $(document).ready( function() {
  9772. * $('#example').dataTable( {
  9773. * "pageLength": 50
  9774. * } );
  9775. * } )
  9776. */
  9777. "iDisplayLength": 10,
  9778. /**
  9779. * Define the starting point for data display when using DataTables with
  9780. * pagination. Note that this parameter is the number of records, rather than
  9781. * the page number, so if you have 10 records per page and want to start on
  9782. * the third page, it should be "20".
  9783. * @type int
  9784. * @default 0
  9785. *
  9786. * @dtopt Options
  9787. * @name DataTable.defaults.displayStart
  9788. *
  9789. * @example
  9790. * $(document).ready( function() {
  9791. * $('#example').dataTable( {
  9792. * "displayStart": 20
  9793. * } );
  9794. * } )
  9795. */
  9796. "iDisplayStart": 0,
  9797. /**
  9798. * By default DataTables allows keyboard navigation of the table (sorting, paging,
  9799. * and filtering) by adding a `tabindex` attribute to the required elements. This
  9800. * allows you to tab through the controls and press the enter key to activate them.
  9801. * The tabindex is default 0, meaning that the tab follows the flow of the document.
  9802. * You can overrule this using this parameter if you wish. Use a value of -1 to
  9803. * disable built-in keyboard navigation.
  9804. * @type int
  9805. * @default 0
  9806. *
  9807. * @dtopt Options
  9808. * @name DataTable.defaults.tabIndex
  9809. *
  9810. * @example
  9811. * $(document).ready( function() {
  9812. * $('#example').dataTable( {
  9813. * "tabIndex": 1
  9814. * } );
  9815. * } );
  9816. */
  9817. "iTabIndex": 0,
  9818. /**
  9819. * Classes that DataTables assigns to the various components and features
  9820. * that it adds to the HTML table. This allows classes to be configured
  9821. * during initialisation in addition to through the static
  9822. * {@link DataTable.ext.oStdClasses} object).
  9823. * @namespace
  9824. * @name DataTable.defaults.classes
  9825. */
  9826. "oClasses": {},
  9827. /**
  9828. * All strings that DataTables uses in the user interface that it creates
  9829. * are defined in this object, allowing you to modified them individually or
  9830. * completely replace them all as required.
  9831. * @namespace
  9832. * @name DataTable.defaults.language
  9833. */
  9834. "oLanguage": {
  9835. /**
  9836. * Strings that are used for WAI-ARIA labels and controls only (these are not
  9837. * actually visible on the page, but will be read by screenreaders, and thus
  9838. * must be internationalised as well).
  9839. * @namespace
  9840. * @name DataTable.defaults.language.aria
  9841. */
  9842. "oAria": {
  9843. /**
  9844. * ARIA label that is added to the table headers when the column may be
  9845. * sorted ascending by activing the column (click or return when focused).
  9846. * Note that the column header is prefixed to this string.
  9847. * @type string
  9848. * @default : activate to sort column ascending
  9849. *
  9850. * @dtopt Language
  9851. * @name DataTable.defaults.language.aria.sortAscending
  9852. *
  9853. * @example
  9854. * $(document).ready( function() {
  9855. * $('#example').dataTable( {
  9856. * "language": {
  9857. * "aria": {
  9858. * "sortAscending": " - click/return to sort ascending"
  9859. * }
  9860. * }
  9861. * } );
  9862. * } );
  9863. */
  9864. "sSortAscending": ": activate to sort column ascending",
  9865. /**
  9866. * ARIA label that is added to the table headers when the column may be
  9867. * sorted descending by activing the column (click or return when focused).
  9868. * Note that the column header is prefixed to this string.
  9869. * @type string
  9870. * @default : activate to sort column ascending
  9871. *
  9872. * @dtopt Language
  9873. * @name DataTable.defaults.language.aria.sortDescending
  9874. *
  9875. * @example
  9876. * $(document).ready( function() {
  9877. * $('#example').dataTable( {
  9878. * "language": {
  9879. * "aria": {
  9880. * "sortDescending": " - click/return to sort descending"
  9881. * }
  9882. * }
  9883. * } );
  9884. * } );
  9885. */
  9886. "sSortDescending": ": activate to sort column descending"
  9887. },
  9888. /**
  9889. * Pagination string used by DataTables for the built-in pagination
  9890. * control types.
  9891. * @namespace
  9892. * @name DataTable.defaults.language.paginate
  9893. */
  9894. "oPaginate": {
  9895. /**
  9896. * Text to use when using the 'full_numbers' type of pagination for the
  9897. * button to take the user to the first page.
  9898. * @type string
  9899. * @default First
  9900. *
  9901. * @dtopt Language
  9902. * @name DataTable.defaults.language.paginate.first
  9903. *
  9904. * @example
  9905. * $(document).ready( function() {
  9906. * $('#example').dataTable( {
  9907. * "language": {
  9908. * "paginate": {
  9909. * "first": "First page"
  9910. * }
  9911. * }
  9912. * } );
  9913. * } );
  9914. */
  9915. "sFirst": "First",
  9916. /**
  9917. * Text to use when using the 'full_numbers' type of pagination for the
  9918. * button to take the user to the last page.
  9919. * @type string
  9920. * @default Last
  9921. *
  9922. * @dtopt Language
  9923. * @name DataTable.defaults.language.paginate.last
  9924. *
  9925. * @example
  9926. * $(document).ready( function() {
  9927. * $('#example').dataTable( {
  9928. * "language": {
  9929. * "paginate": {
  9930. * "last": "Last page"
  9931. * }
  9932. * }
  9933. * } );
  9934. * } );
  9935. */
  9936. "sLast": "Last",
  9937. /**
  9938. * Text to use for the 'next' pagination button (to take the user to the
  9939. * next page).
  9940. * @type string
  9941. * @default Next
  9942. *
  9943. * @dtopt Language
  9944. * @name DataTable.defaults.language.paginate.next
  9945. *
  9946. * @example
  9947. * $(document).ready( function() {
  9948. * $('#example').dataTable( {
  9949. * "language": {
  9950. * "paginate": {
  9951. * "next": "Next page"
  9952. * }
  9953. * }
  9954. * } );
  9955. * } );
  9956. */
  9957. "sNext": "Next",
  9958. /**
  9959. * Text to use for the 'previous' pagination button (to take the user to
  9960. * the previous page).
  9961. * @type string
  9962. * @default Previous
  9963. *
  9964. * @dtopt Language
  9965. * @name DataTable.defaults.language.paginate.previous
  9966. *
  9967. * @example
  9968. * $(document).ready( function() {
  9969. * $('#example').dataTable( {
  9970. * "language": {
  9971. * "paginate": {
  9972. * "previous": "Previous page"
  9973. * }
  9974. * }
  9975. * } );
  9976. * } );
  9977. */
  9978. "sPrevious": "Previous"
  9979. },
  9980. /**
  9981. * This string is shown in preference to `zeroRecords` when the table is
  9982. * empty of data (regardless of filtering). Note that this is an optional
  9983. * parameter - if it is not given, the value of `zeroRecords` will be used
  9984. * instead (either the default or given value).
  9985. * @type string
  9986. * @default No data available in table
  9987. *
  9988. * @dtopt Language
  9989. * @name DataTable.defaults.language.emptyTable
  9990. *
  9991. * @example
  9992. * $(document).ready( function() {
  9993. * $('#example').dataTable( {
  9994. * "language": {
  9995. * "emptyTable": "No data available in table"
  9996. * }
  9997. * } );
  9998. * } );
  9999. */
  10000. "sEmptyTable": "No data available in table",
  10001. /**
  10002. * This string gives information to the end user about the information
  10003. * that is current on display on the page. The following tokens can be
  10004. * used in the string and will be dynamically replaced as the table
  10005. * display updates. This tokens can be placed anywhere in the string, or
  10006. * removed as needed by the language requires:
  10007. *
  10008. * * `\_START\_` - Display index of the first record on the current page
  10009. * * `\_END\_` - Display index of the last record on the current page
  10010. * * `\_TOTAL\_` - Number of records in the table after filtering
  10011. * * `\_MAX\_` - Number of records in the table without filtering
  10012. * * `\_PAGE\_` - Current page number
  10013. * * `\_PAGES\_` - Total number of pages of data in the table
  10014. *
  10015. * @type string
  10016. * @default Showing _START_ to _END_ of _TOTAL_ entries
  10017. *
  10018. * @dtopt Language
  10019. * @name DataTable.defaults.language.info
  10020. *
  10021. * @example
  10022. * $(document).ready( function() {
  10023. * $('#example').dataTable( {
  10024. * "language": {
  10025. * "info": "Showing page _PAGE_ of _PAGES_"
  10026. * }
  10027. * } );
  10028. * } );
  10029. */
  10030. "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
  10031. /**
  10032. * Display information string for when the table is empty. Typically the
  10033. * format of this string should match `info`.
  10034. * @type string
  10035. * @default Showing 0 to 0 of 0 entries
  10036. *
  10037. * @dtopt Language
  10038. * @name DataTable.defaults.language.infoEmpty
  10039. *
  10040. * @example
  10041. * $(document).ready( function() {
  10042. * $('#example').dataTable( {
  10043. * "language": {
  10044. * "infoEmpty": "No entries to show"
  10045. * }
  10046. * } );
  10047. * } );
  10048. */
  10049. "sInfoEmpty": "Showing 0 to 0 of 0 entries",
  10050. /**
  10051. * When a user filters the information in a table, this string is appended
  10052. * to the information (`info`) to give an idea of how strong the filtering
  10053. * is. The variable _MAX_ is dynamically updated.
  10054. * @type string
  10055. * @default (filtered from _MAX_ total entries)
  10056. *
  10057. * @dtopt Language
  10058. * @name DataTable.defaults.language.infoFiltered
  10059. *
  10060. * @example
  10061. * $(document).ready( function() {
  10062. * $('#example').dataTable( {
  10063. * "language": {
  10064. * "infoFiltered": " - filtering from _MAX_ records"
  10065. * }
  10066. * } );
  10067. * } );
  10068. */
  10069. "sInfoFiltered": "(filtered from _MAX_ total entries)",
  10070. /**
  10071. * If can be useful to append extra information to the info string at times,
  10072. * and this variable does exactly that. This information will be appended to
  10073. * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
  10074. * being used) at all times.
  10075. * @type string
  10076. * @default <i>Empty string</i>
  10077. *
  10078. * @dtopt Language
  10079. * @name DataTable.defaults.language.infoPostFix
  10080. *
  10081. * @example
  10082. * $(document).ready( function() {
  10083. * $('#example').dataTable( {
  10084. * "language": {
  10085. * "infoPostFix": "All records shown are derived from real information."
  10086. * }
  10087. * } );
  10088. * } );
  10089. */
  10090. "sInfoPostFix": "",
  10091. /**
  10092. * This decimal place operator is a little different from the other
  10093. * language options since DataTables doesn't output floating point
  10094. * numbers, so it won't ever use this for display of a number. Rather,
  10095. * what this parameter does is modify the sort methods of the table so
  10096. * that numbers which are in a format which has a character other than
  10097. * a period (`.`) as a decimal place will be sorted numerically.
  10098. *
  10099. * Note that numbers with different decimal places cannot be shown in
  10100. * the same table and still be sortable, the table must be consistent.
  10101. * However, multiple different tables on the page can use different
  10102. * decimal place characters.
  10103. * @type string
  10104. * @default
  10105. *
  10106. * @dtopt Language
  10107. * @name DataTable.defaults.language.decimal
  10108. *
  10109. * @example
  10110. * $(document).ready( function() {
  10111. * $('#example').dataTable( {
  10112. * "language": {
  10113. * "decimal": ","
  10114. * "thousands": "."
  10115. * }
  10116. * } );
  10117. * } );
  10118. */
  10119. "sDecimal": "",
  10120. /**
  10121. * DataTables has a build in number formatter (`formatNumber`) which is
  10122. * used to format large numbers that are used in the table information.
  10123. * By default a comma is used, but this can be trivially changed to any
  10124. * character you wish with this parameter.
  10125. * @type string
  10126. * @default ,
  10127. *
  10128. * @dtopt Language
  10129. * @name DataTable.defaults.language.thousands
  10130. *
  10131. * @example
  10132. * $(document).ready( function() {
  10133. * $('#example').dataTable( {
  10134. * "language": {
  10135. * "thousands": "'"
  10136. * }
  10137. * } );
  10138. * } );
  10139. */
  10140. "sThousands": ",",
  10141. /**
  10142. * Detail the action that will be taken when the drop down menu for the
  10143. * pagination length option is changed. The '_MENU_' variable is replaced
  10144. * with a default select list of 10, 25, 50 and 100, and can be replaced
  10145. * with a custom select box if required.
  10146. * @type string
  10147. * @default Show _MENU_ entries
  10148. *
  10149. * @dtopt Language
  10150. * @name DataTable.defaults.language.lengthMenu
  10151. *
  10152. * @example
  10153. * // Language change only
  10154. * $(document).ready( function() {
  10155. * $('#example').dataTable( {
  10156. * "language": {
  10157. * "lengthMenu": "Display _MENU_ records"
  10158. * }
  10159. * } );
  10160. * } );
  10161. *
  10162. * @example
  10163. * // Language and options change
  10164. * $(document).ready( function() {
  10165. * $('#example').dataTable( {
  10166. * "language": {
  10167. * "lengthMenu": 'Display <select>'+
  10168. * '<option value="10">10</option>'+
  10169. * '<option value="20">20</option>'+
  10170. * '<option value="30">30</option>'+
  10171. * '<option value="40">40</option>'+
  10172. * '<option value="50">50</option>'+
  10173. * '<option value="-1">All</option>'+
  10174. * '</select> records'
  10175. * }
  10176. * } );
  10177. * } );
  10178. */
  10179. "sLengthMenu": "Show _MENU_ entries",
  10180. /**
  10181. * When using Ajax sourced data and during the first draw when DataTables is
  10182. * gathering the data, this message is shown in an empty row in the table to
  10183. * indicate to the end user the the data is being loaded. Note that this
  10184. * parameter is not used when loading data by server-side processing, just
  10185. * Ajax sourced data with client-side processing.
  10186. * @type string
  10187. * @default Loading...
  10188. *
  10189. * @dtopt Language
  10190. * @name DataTable.defaults.language.loadingRecords
  10191. *
  10192. * @example
  10193. * $(document).ready( function() {
  10194. * $('#example').dataTable( {
  10195. * "language": {
  10196. * "loadingRecords": "Please wait - loading..."
  10197. * }
  10198. * } );
  10199. * } );
  10200. */
  10201. "sLoadingRecords": "Loading...",
  10202. /**
  10203. * Text which is displayed when the table is processing a user action
  10204. * (usually a sort command or similar).
  10205. * @type string
  10206. *
  10207. * @dtopt Language
  10208. * @name DataTable.defaults.language.processing
  10209. *
  10210. * @example
  10211. * $(document).ready( function() {
  10212. * $('#example').dataTable( {
  10213. * "language": {
  10214. * "processing": "DataTables is currently busy"
  10215. * }
  10216. * } );
  10217. * } );
  10218. */
  10219. "sProcessing": "",
  10220. /**
  10221. * Details the actions that will be taken when the user types into the
  10222. * filtering input text box. The variable "_INPUT_", if used in the string,
  10223. * is replaced with the HTML text box for the filtering input allowing
  10224. * control over where it appears in the string. If "_INPUT_" is not given
  10225. * then the input box is appended to the string automatically.
  10226. * @type string
  10227. * @default Search:
  10228. *
  10229. * @dtopt Language
  10230. * @name DataTable.defaults.language.search
  10231. *
  10232. * @example
  10233. * // Input text box will be appended at the end automatically
  10234. * $(document).ready( function() {
  10235. * $('#example').dataTable( {
  10236. * "language": {
  10237. * "search": "Filter records:"
  10238. * }
  10239. * } );
  10240. * } );
  10241. *
  10242. * @example
  10243. * // Specify where the filter should appear
  10244. * $(document).ready( function() {
  10245. * $('#example').dataTable( {
  10246. * "language": {
  10247. * "search": "Apply filter _INPUT_ to table"
  10248. * }
  10249. * } );
  10250. * } );
  10251. */
  10252. "sSearch": "Search:",
  10253. /**
  10254. * Assign a `placeholder` attribute to the search `input` element
  10255. * @type string
  10256. * @default
  10257. *
  10258. * @dtopt Language
  10259. * @name DataTable.defaults.language.searchPlaceholder
  10260. */
  10261. "sSearchPlaceholder": "",
  10262. /**
  10263. * All of the language information can be stored in a file on the
  10264. * server-side, which DataTables will look up if this parameter is passed.
  10265. * It must store the URL of the language file, which is in a JSON format,
  10266. * and the object has the same properties as the oLanguage object in the
  10267. * initialiser object (i.e. the above parameters). Please refer to one of
  10268. * the example language files to see how this works in action.
  10269. * @type string
  10270. * @default <i>Empty string - i.e. disabled</i>
  10271. *
  10272. * @dtopt Language
  10273. * @name DataTable.defaults.language.url
  10274. *
  10275. * @example
  10276. * $(document).ready( function() {
  10277. * $('#example').dataTable( {
  10278. * "language": {
  10279. * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
  10280. * }
  10281. * } );
  10282. * } );
  10283. */
  10284. "sUrl": "",
  10285. /**
  10286. * Text shown inside the table records when the is no information to be
  10287. * displayed after filtering. `emptyTable` is shown when there is simply no
  10288. * information in the table at all (regardless of filtering).
  10289. * @type string
  10290. * @default No matching records found
  10291. *
  10292. * @dtopt Language
  10293. * @name DataTable.defaults.language.zeroRecords
  10294. *
  10295. * @example
  10296. * $(document).ready( function() {
  10297. * $('#example').dataTable( {
  10298. * "language": {
  10299. * "zeroRecords": "No records to display"
  10300. * }
  10301. * } );
  10302. * } );
  10303. */
  10304. "sZeroRecords": "No matching records found"
  10305. },
  10306. /**
  10307. * This parameter allows you to have define the global filtering state at
  10308. * initialisation time. As an object the `search` parameter must be
  10309. * defined, but all other parameters are optional. When `regex` is true,
  10310. * the search string will be treated as a regular expression, when false
  10311. * (default) it will be treated as a straight string. When `smart`
  10312. * DataTables will use it's smart filtering methods (to word match at
  10313. * any point in the data), when false this will not be done.
  10314. * @namespace
  10315. * @extends DataTable.models.oSearch
  10316. *
  10317. * @dtopt Options
  10318. * @name DataTable.defaults.search
  10319. *
  10320. * @example
  10321. * $(document).ready( function() {
  10322. * $('#example').dataTable( {
  10323. * "search": {"search": "Initial search"}
  10324. * } );
  10325. * } )
  10326. */
  10327. "oSearch": $.extend( {}, DataTable.models.oSearch ),
  10328. /**
  10329. * __Deprecated__ The functionality provided by this parameter has now been
  10330. * superseded by that provided through `ajax`, which should be used instead.
  10331. *
  10332. * By default DataTables will look for the property `data` (or `aaData` for
  10333. * compatibility with DataTables 1.9-) when obtaining data from an Ajax
  10334. * source or for server-side processing - this parameter allows that
  10335. * property to be changed. You can use Javascript dotted object notation to
  10336. * get a data source for multiple levels of nesting.
  10337. * @type string
  10338. * @default data
  10339. *
  10340. * @dtopt Options
  10341. * @dtopt Server-side
  10342. * @name DataTable.defaults.ajaxDataProp
  10343. *
  10344. * @deprecated 1.10. Please use `ajax` for this functionality now.
  10345. */
  10346. "sAjaxDataProp": "data",
  10347. /**
  10348. * __Deprecated__ The functionality provided by this parameter has now been
  10349. * superseded by that provided through `ajax`, which should be used instead.
  10350. *
  10351. * You can instruct DataTables to load data from an external
  10352. * source using this parameter (use aData if you want to pass data in you
  10353. * already have). Simply provide a url a JSON object can be obtained from.
  10354. * @type string
  10355. * @default null
  10356. *
  10357. * @dtopt Options
  10358. * @dtopt Server-side
  10359. * @name DataTable.defaults.ajaxSource
  10360. *
  10361. * @deprecated 1.10. Please use `ajax` for this functionality now.
  10362. */
  10363. "sAjaxSource": null,
  10364. /**
  10365. * This initialisation variable allows you to specify exactly where in the
  10366. * DOM you want DataTables to inject the various controls it adds to the page
  10367. * (for example you might want the pagination controls at the top of the
  10368. * table). DIV elements (with or without a custom class) can also be added to
  10369. * aid styling. The follow syntax is used:
  10370. * <ul>
  10371. * <li>The following options are allowed:
  10372. * <ul>
  10373. * <li>'l' - Length changing</li>
  10374. * <li>'f' - Filtering input</li>
  10375. * <li>'t' - The table!</li>
  10376. * <li>'i' - Information</li>
  10377. * <li>'p' - Pagination</li>
  10378. * <li>'r' - pRocessing</li>
  10379. * </ul>
  10380. * </li>
  10381. * <li>The following constants are allowed:
  10382. * <ul>
  10383. * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
  10384. * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
  10385. * </ul>
  10386. * </li>
  10387. * <li>The following syntax is expected:
  10388. * <ul>
  10389. * <li>'&lt;' and '&gt;' - div elements</li>
  10390. * <li>'&lt;"class" and '&gt;' - div with a class</li>
  10391. * <li>'&lt;"#id" and '&gt;' - div with an ID</li>
  10392. * </ul>
  10393. * </li>
  10394. * <li>Examples:
  10395. * <ul>
  10396. * <li>'&lt;"wrapper"flipt&gt;'</li>
  10397. * <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
  10398. * </ul>
  10399. * </li>
  10400. * </ul>
  10401. * @type string
  10402. * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
  10403. * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
  10404. *
  10405. * @dtopt Options
  10406. * @name DataTable.defaults.dom
  10407. *
  10408. * @example
  10409. * $(document).ready( function() {
  10410. * $('#example').dataTable( {
  10411. * "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
  10412. * } );
  10413. * } );
  10414. */
  10415. "sDom": "lfrtip",
  10416. /**
  10417. * Search delay option. This will throttle full table searches that use the
  10418. * DataTables provided search input element (it does not effect calls to
  10419. * `dt-api search()`, providing a delay before the search is made.
  10420. * @type integer
  10421. * @default 0
  10422. *
  10423. * @dtopt Options
  10424. * @name DataTable.defaults.searchDelay
  10425. *
  10426. * @example
  10427. * $(document).ready( function() {
  10428. * $('#example').dataTable( {
  10429. * "searchDelay": 200
  10430. * } );
  10431. * } )
  10432. */
  10433. "searchDelay": null,
  10434. /**
  10435. * DataTables features six different built-in options for the buttons to
  10436. * display for pagination control:
  10437. *
  10438. * * `numbers` - Page number buttons only
  10439. * * `simple` - 'Previous' and 'Next' buttons only
  10440. * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
  10441. * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
  10442. * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
  10443. * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
  10444. *
  10445. * Further methods can be added using {@link DataTable.ext.oPagination}.
  10446. * @type string
  10447. * @default simple_numbers
  10448. *
  10449. * @dtopt Options
  10450. * @name DataTable.defaults.pagingType
  10451. *
  10452. * @example
  10453. * $(document).ready( function() {
  10454. * $('#example').dataTable( {
  10455. * "pagingType": "full_numbers"
  10456. * } );
  10457. * } )
  10458. */
  10459. "sPaginationType": "simple_numbers",
  10460. /**
  10461. * Enable horizontal scrolling. When a table is too wide to fit into a
  10462. * certain layout, or you have a large number of columns in the table, you
  10463. * can enable x-scrolling to show the table in a viewport, which can be
  10464. * scrolled. This property can be `true` which will allow the table to
  10465. * scroll horizontally when needed, or any CSS unit, or a number (in which
  10466. * case it will be treated as a pixel measurement). Setting as simply `true`
  10467. * is recommended.
  10468. * @type boolean|string
  10469. * @default <i>blank string - i.e. disabled</i>
  10470. *
  10471. * @dtopt Features
  10472. * @name DataTable.defaults.scrollX
  10473. *
  10474. * @example
  10475. * $(document).ready( function() {
  10476. * $('#example').dataTable( {
  10477. * "scrollX": true,
  10478. * "scrollCollapse": true
  10479. * } );
  10480. * } );
  10481. */
  10482. "sScrollX": "",
  10483. /**
  10484. * This property can be used to force a DataTable to use more width than it
  10485. * might otherwise do when x-scrolling is enabled. For example if you have a
  10486. * table which requires to be well spaced, this parameter is useful for
  10487. * "over-sizing" the table, and thus forcing scrolling. This property can by
  10488. * any CSS unit, or a number (in which case it will be treated as a pixel
  10489. * measurement).
  10490. * @type string
  10491. * @default <i>blank string - i.e. disabled</i>
  10492. *
  10493. * @dtopt Options
  10494. * @name DataTable.defaults.scrollXInner
  10495. *
  10496. * @example
  10497. * $(document).ready( function() {
  10498. * $('#example').dataTable( {
  10499. * "scrollX": "100%",
  10500. * "scrollXInner": "110%"
  10501. * } );
  10502. * } );
  10503. */
  10504. "sScrollXInner": "",
  10505. /**
  10506. * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
  10507. * to the given height, and enable scrolling for any data which overflows the
  10508. * current viewport. This can be used as an alternative to paging to display
  10509. * a lot of data in a small area (although paging and scrolling can both be
  10510. * enabled at the same time). This property can be any CSS unit, or a number
  10511. * (in which case it will be treated as a pixel measurement).
  10512. * @type string
  10513. * @default <i>blank string - i.e. disabled</i>
  10514. *
  10515. * @dtopt Features
  10516. * @name DataTable.defaults.scrollY
  10517. *
  10518. * @example
  10519. * $(document).ready( function() {
  10520. * $('#example').dataTable( {
  10521. * "scrollY": "200px",
  10522. * "paginate": false
  10523. * } );
  10524. * } );
  10525. */
  10526. "sScrollY": "",
  10527. /**
  10528. * __Deprecated__ The functionality provided by this parameter has now been
  10529. * superseded by that provided through `ajax`, which should be used instead.
  10530. *
  10531. * Set the HTTP method that is used to make the Ajax call for server-side
  10532. * processing or Ajax sourced data.
  10533. * @type string
  10534. * @default GET
  10535. *
  10536. * @dtopt Options
  10537. * @dtopt Server-side
  10538. * @name DataTable.defaults.serverMethod
  10539. *
  10540. * @deprecated 1.10. Please use `ajax` for this functionality now.
  10541. */
  10542. "sServerMethod": "GET",
  10543. /**
  10544. * DataTables makes use of renderers when displaying HTML elements for
  10545. * a table. These renderers can be added or modified by plug-ins to
  10546. * generate suitable mark-up for a site. For example the Bootstrap
  10547. * integration plug-in for DataTables uses a paging button renderer to
  10548. * display pagination buttons in the mark-up required by Bootstrap.
  10549. *
  10550. * For further information about the renderers available see
  10551. * DataTable.ext.renderer
  10552. * @type string|object
  10553. * @default null
  10554. *
  10555. * @name DataTable.defaults.renderer
  10556. *
  10557. */
  10558. "renderer": null,
  10559. /**
  10560. * Set the data property name that DataTables should use to get a row's id
  10561. * to set as the `id` property in the node.
  10562. * @type string
  10563. * @default DT_RowId
  10564. *
  10565. * @name DataTable.defaults.rowId
  10566. */
  10567. "rowId": "DT_RowId"
  10568. };
  10569. _fnHungarianMap( DataTable.defaults );
  10570. /*
  10571. * Developer note - See note in model.defaults.js about the use of Hungarian
  10572. * notation and camel case.
  10573. */
  10574. /**
  10575. * Column options that can be given to DataTables at initialisation time.
  10576. * @namespace
  10577. */
  10578. DataTable.defaults.column = {
  10579. /**
  10580. * Define which column(s) an order will occur on for this column. This
  10581. * allows a column's ordering to take multiple columns into account when
  10582. * doing a sort or use the data from a different column. For example first
  10583. * name / last name columns make sense to do a multi-column sort over the
  10584. * two columns.
  10585. * @type array|int
  10586. * @default null <i>Takes the value of the column index automatically</i>
  10587. *
  10588. * @name DataTable.defaults.column.orderData
  10589. * @dtopt Columns
  10590. *
  10591. * @example
  10592. * // Using `columnDefs`
  10593. * $(document).ready( function() {
  10594. * $('#example').dataTable( {
  10595. * "columnDefs": [
  10596. * { "orderData": [ 0, 1 ], "targets": [ 0 ] },
  10597. * { "orderData": [ 1, 0 ], "targets": [ 1 ] },
  10598. * { "orderData": 2, "targets": [ 2 ] }
  10599. * ]
  10600. * } );
  10601. * } );
  10602. *
  10603. * @example
  10604. * // Using `columns`
  10605. * $(document).ready( function() {
  10606. * $('#example').dataTable( {
  10607. * "columns": [
  10608. * { "orderData": [ 0, 1 ] },
  10609. * { "orderData": [ 1, 0 ] },
  10610. * { "orderData": 2 },
  10611. * null,
  10612. * null
  10613. * ]
  10614. * } );
  10615. * } );
  10616. */
  10617. "aDataSort": null,
  10618. "iDataSort": -1,
  10619. /**
  10620. * You can control the default ordering direction, and even alter the
  10621. * behaviour of the sort handler (i.e. only allow ascending ordering etc)
  10622. * using this parameter.
  10623. * @type array
  10624. * @default [ 'asc', 'desc' ]
  10625. *
  10626. * @name DataTable.defaults.column.orderSequence
  10627. * @dtopt Columns
  10628. *
  10629. * @example
  10630. * // Using `columnDefs`
  10631. * $(document).ready( function() {
  10632. * $('#example').dataTable( {
  10633. * "columnDefs": [
  10634. * { "orderSequence": [ "asc" ], "targets": [ 1 ] },
  10635. * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
  10636. * { "orderSequence": [ "desc" ], "targets": [ 3 ] }
  10637. * ]
  10638. * } );
  10639. * } );
  10640. *
  10641. * @example
  10642. * // Using `columns`
  10643. * $(document).ready( function() {
  10644. * $('#example').dataTable( {
  10645. * "columns": [
  10646. * null,
  10647. * { "orderSequence": [ "asc" ] },
  10648. * { "orderSequence": [ "desc", "asc", "asc" ] },
  10649. * { "orderSequence": [ "desc" ] },
  10650. * null
  10651. * ]
  10652. * } );
  10653. * } );
  10654. */
  10655. "asSorting": [ 'asc', 'desc' ],
  10656. /**
  10657. * Enable or disable filtering on the data in this column.
  10658. * @type boolean
  10659. * @default true
  10660. *
  10661. * @name DataTable.defaults.column.searchable
  10662. * @dtopt Columns
  10663. *
  10664. * @example
  10665. * // Using `columnDefs`
  10666. * $(document).ready( function() {
  10667. * $('#example').dataTable( {
  10668. * "columnDefs": [
  10669. * { "searchable": false, "targets": [ 0 ] }
  10670. * ] } );
  10671. * } );
  10672. *
  10673. * @example
  10674. * // Using `columns`
  10675. * $(document).ready( function() {
  10676. * $('#example').dataTable( {
  10677. * "columns": [
  10678. * { "searchable": false },
  10679. * null,
  10680. * null,
  10681. * null,
  10682. * null
  10683. * ] } );
  10684. * } );
  10685. */
  10686. "bSearchable": true,
  10687. /**
  10688. * Enable or disable ordering on this column.
  10689. * @type boolean
  10690. * @default true
  10691. *
  10692. * @name DataTable.defaults.column.orderable
  10693. * @dtopt Columns
  10694. *
  10695. * @example
  10696. * // Using `columnDefs`
  10697. * $(document).ready( function() {
  10698. * $('#example').dataTable( {
  10699. * "columnDefs": [
  10700. * { "orderable": false, "targets": [ 0 ] }
  10701. * ] } );
  10702. * } );
  10703. *
  10704. * @example
  10705. * // Using `columns`
  10706. * $(document).ready( function() {
  10707. * $('#example').dataTable( {
  10708. * "columns": [
  10709. * { "orderable": false },
  10710. * null,
  10711. * null,
  10712. * null,
  10713. * null
  10714. * ] } );
  10715. * } );
  10716. */
  10717. "bSortable": true,
  10718. /**
  10719. * Enable or disable the display of this column.
  10720. * @type boolean
  10721. * @default true
  10722. *
  10723. * @name DataTable.defaults.column.visible
  10724. * @dtopt Columns
  10725. *
  10726. * @example
  10727. * // Using `columnDefs`
  10728. * $(document).ready( function() {
  10729. * $('#example').dataTable( {
  10730. * "columnDefs": [
  10731. * { "visible": false, "targets": [ 0 ] }
  10732. * ] } );
  10733. * } );
  10734. *
  10735. * @example
  10736. * // Using `columns`
  10737. * $(document).ready( function() {
  10738. * $('#example').dataTable( {
  10739. * "columns": [
  10740. * { "visible": false },
  10741. * null,
  10742. * null,
  10743. * null,
  10744. * null
  10745. * ] } );
  10746. * } );
  10747. */
  10748. "bVisible": true,
  10749. /**
  10750. * Developer definable function that is called whenever a cell is created (Ajax source,
  10751. * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  10752. * allowing you to modify the DOM element (add background colour for example) when the
  10753. * element is available.
  10754. * @type function
  10755. * @param {element} td The TD node that has been created
  10756. * @param {*} cellData The Data for the cell
  10757. * @param {array|object} rowData The data for the whole row
  10758. * @param {int} row The row index for the aoData data store
  10759. * @param {int} col The column index for aoColumns
  10760. *
  10761. * @name DataTable.defaults.column.createdCell
  10762. * @dtopt Columns
  10763. *
  10764. * @example
  10765. * $(document).ready( function() {
  10766. * $('#example').dataTable( {
  10767. * "columnDefs": [ {
  10768. * "targets": [3],
  10769. * "createdCell": function (td, cellData, rowData, row, col) {
  10770. * if ( cellData == "1.7" ) {
  10771. * $(td).css('color', 'blue')
  10772. * }
  10773. * }
  10774. * } ]
  10775. * });
  10776. * } );
  10777. */
  10778. "fnCreatedCell": null,
  10779. /**
  10780. * This parameter has been replaced by `data` in DataTables to ensure naming
  10781. * consistency. `dataProp` can still be used, as there is backwards
  10782. * compatibility in DataTables for this option, but it is strongly
  10783. * recommended that you use `data` in preference to `dataProp`.
  10784. * @name DataTable.defaults.column.dataProp
  10785. */
  10786. /**
  10787. * This property can be used to read data from any data source property,
  10788. * including deeply nested objects / properties. `data` can be given in a
  10789. * number of different ways which effect its behaviour:
  10790. *
  10791. * * `integer` - treated as an array index for the data source. This is the
  10792. * default that DataTables uses (incrementally increased for each column).
  10793. * * `string` - read an object property from the data source. There are
  10794. * three 'special' options that can be used in the string to alter how
  10795. * DataTables reads the data from the source object:
  10796. * * `.` - Dotted Javascript notation. Just as you use a `.` in
  10797. * Javascript to read from nested objects, so to can the options
  10798. * specified in `data`. For example: `browser.version` or
  10799. * `browser.name`. If your object parameter name contains a period, use
  10800. * `\\` to escape it - i.e. `first\\.name`.
  10801. * * `[]` - Array notation. DataTables can automatically combine data
  10802. * from and array source, joining the data with the characters provided
  10803. * between the two brackets. For example: `name[, ]` would provide a
  10804. * comma-space separated list from the source array. If no characters
  10805. * are provided between the brackets, the original array source is
  10806. * returned.
  10807. * * `()` - Function notation. Adding `()` to the end of a parameter will
  10808. * execute a function of the name given. For example: `browser()` for a
  10809. * simple function on the data source, `browser.version()` for a
  10810. * function in a nested property or even `browser().version` to get an
  10811. * object property if the function called returns an object. Note that
  10812. * function notation is recommended for use in `render` rather than
  10813. * `data` as it is much simpler to use as a renderer.
  10814. * * `null` - use the original data source for the row rather than plucking
  10815. * data directly from it. This action has effects on two other
  10816. * initialisation options:
  10817. * * `defaultContent` - When null is given as the `data` option and
  10818. * `defaultContent` is specified for the column, the value defined by
  10819. * `defaultContent` will be used for the cell.
  10820. * * `render` - When null is used for the `data` option and the `render`
  10821. * option is specified for the column, the whole data source for the
  10822. * row is used for the renderer.
  10823. * * `function` - the function given will be executed whenever DataTables
  10824. * needs to set or get the data for a cell in the column. The function
  10825. * takes three parameters:
  10826. * * Parameters:
  10827. * * `{array|object}` The data source for the row
  10828. * * `{string}` The type call data requested - this will be 'set' when
  10829. * setting data or 'filter', 'display', 'type', 'sort' or undefined
  10830. * when gathering data. Note that when `undefined` is given for the
  10831. * type DataTables expects to get the raw data for the object back<
  10832. * * `{*}` Data to set when the second parameter is 'set'.
  10833. * * Return:
  10834. * * The return value from the function is not required when 'set' is
  10835. * the type of call, but otherwise the return is what will be used
  10836. * for the data requested.
  10837. *
  10838. * Note that `data` is a getter and setter option. If you just require
  10839. * formatting of data for output, you will likely want to use `render` which
  10840. * is simply a getter and thus simpler to use.
  10841. *
  10842. * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
  10843. * name change reflects the flexibility of this property and is consistent
  10844. * with the naming of mRender. If 'mDataProp' is given, then it will still
  10845. * be used by DataTables, as it automatically maps the old name to the new
  10846. * if required.
  10847. *
  10848. * @type string|int|function|null
  10849. * @default null <i>Use automatically calculated column index</i>
  10850. *
  10851. * @name DataTable.defaults.column.data
  10852. * @dtopt Columns
  10853. *
  10854. * @example
  10855. * // Read table data from objects
  10856. * // JSON structure for each row:
  10857. * // {
  10858. * // "engine": {value},
  10859. * // "browser": {value},
  10860. * // "platform": {value},
  10861. * // "version": {value},
  10862. * // "grade": {value}
  10863. * // }
  10864. * $(document).ready( function() {
  10865. * $('#example').dataTable( {
  10866. * "ajaxSource": "sources/objects.txt",
  10867. * "columns": [
  10868. * { "data": "engine" },
  10869. * { "data": "browser" },
  10870. * { "data": "platform" },
  10871. * { "data": "version" },
  10872. * { "data": "grade" }
  10873. * ]
  10874. * } );
  10875. * } );
  10876. *
  10877. * @example
  10878. * // Read information from deeply nested objects
  10879. * // JSON structure for each row:
  10880. * // {
  10881. * // "engine": {value},
  10882. * // "browser": {value},
  10883. * // "platform": {
  10884. * // "inner": {value}
  10885. * // },
  10886. * // "details": [
  10887. * // {value}, {value}
  10888. * // ]
  10889. * // }
  10890. * $(document).ready( function() {
  10891. * $('#example').dataTable( {
  10892. * "ajaxSource": "sources/deep.txt",
  10893. * "columns": [
  10894. * { "data": "engine" },
  10895. * { "data": "browser" },
  10896. * { "data": "platform.inner" },
  10897. * { "data": "details.0" },
  10898. * { "data": "details.1" }
  10899. * ]
  10900. * } );
  10901. * } );
  10902. *
  10903. * @example
  10904. * // Using `data` as a function to provide different information for
  10905. * // sorting, filtering and display. In this case, currency (price)
  10906. * $(document).ready( function() {
  10907. * $('#example').dataTable( {
  10908. * "columnDefs": [ {
  10909. * "targets": [ 0 ],
  10910. * "data": function ( source, type, val ) {
  10911. * if (type === 'set') {
  10912. * source.price = val;
  10913. * // Store the computed display and filter values for efficiency
  10914. * source.price_display = val=="" ? "" : "$"+numberFormat(val);
  10915. * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
  10916. * return;
  10917. * }
  10918. * else if (type === 'display') {
  10919. * return source.price_display;
  10920. * }
  10921. * else if (type === 'filter') {
  10922. * return source.price_filter;
  10923. * }
  10924. * // 'sort', 'type' and undefined all just use the integer
  10925. * return source.price;
  10926. * }
  10927. * } ]
  10928. * } );
  10929. * } );
  10930. *
  10931. * @example
  10932. * // Using default content
  10933. * $(document).ready( function() {
  10934. * $('#example').dataTable( {
  10935. * "columnDefs": [ {
  10936. * "targets": [ 0 ],
  10937. * "data": null,
  10938. * "defaultContent": "Click to edit"
  10939. * } ]
  10940. * } );
  10941. * } );
  10942. *
  10943. * @example
  10944. * // Using array notation - outputting a list from an array
  10945. * $(document).ready( function() {
  10946. * $('#example').dataTable( {
  10947. * "columnDefs": [ {
  10948. * "targets": [ 0 ],
  10949. * "data": "name[, ]"
  10950. * } ]
  10951. * } );
  10952. * } );
  10953. *
  10954. */
  10955. "mData": null,
  10956. /**
  10957. * This property is the rendering partner to `data` and it is suggested that
  10958. * when you want to manipulate data for display (including filtering,
  10959. * sorting etc) without altering the underlying data for the table, use this
  10960. * property. `render` can be considered to be the the read only companion to
  10961. * `data` which is read / write (then as such more complex). Like `data`
  10962. * this option can be given in a number of different ways to effect its
  10963. * behaviour:
  10964. *
  10965. * * `integer` - treated as an array index for the data source. This is the
  10966. * default that DataTables uses (incrementally increased for each column).
  10967. * * `string` - read an object property from the data source. There are
  10968. * three 'special' options that can be used in the string to alter how
  10969. * DataTables reads the data from the source object:
  10970. * * `.` - Dotted Javascript notation. Just as you use a `.` in
  10971. * Javascript to read from nested objects, so to can the options
  10972. * specified in `data`. For example: `browser.version` or
  10973. * `browser.name`. If your object parameter name contains a period, use
  10974. * `\\` to escape it - i.e. `first\\.name`.
  10975. * * `[]` - Array notation. DataTables can automatically combine data
  10976. * from and array source, joining the data with the characters provided
  10977. * between the two brackets. For example: `name[, ]` would provide a
  10978. * comma-space separated list from the source array. If no characters
  10979. * are provided between the brackets, the original array source is
  10980. * returned.
  10981. * * `()` - Function notation. Adding `()` to the end of a parameter will
  10982. * execute a function of the name given. For example: `browser()` for a
  10983. * simple function on the data source, `browser.version()` for a
  10984. * function in a nested property or even `browser().version` to get an
  10985. * object property if the function called returns an object.
  10986. * * `object` - use different data for the different data types requested by
  10987. * DataTables ('filter', 'display', 'type' or 'sort'). The property names
  10988. * of the object is the data type the property refers to and the value can
  10989. * defined using an integer, string or function using the same rules as
  10990. * `render` normally does. Note that an `_` option _must_ be specified.
  10991. * This is the default value to use if you haven't specified a value for
  10992. * the data type requested by DataTables.
  10993. * * `function` - the function given will be executed whenever DataTables
  10994. * needs to set or get the data for a cell in the column. The function
  10995. * takes three parameters:
  10996. * * Parameters:
  10997. * * {array|object} The data source for the row (based on `data`)
  10998. * * {string} The type call data requested - this will be 'filter',
  10999. * 'display', 'type' or 'sort'.
  11000. * * {array|object} The full data source for the row (not based on
  11001. * `data`)
  11002. * * Return:
  11003. * * The return value from the function is what will be used for the
  11004. * data requested.
  11005. *
  11006. * @type string|int|function|object|null
  11007. * @default null Use the data source value.
  11008. *
  11009. * @name DataTable.defaults.column.render
  11010. * @dtopt Columns
  11011. *
  11012. * @example
  11013. * // Create a comma separated list from an array of objects
  11014. * $(document).ready( function() {
  11015. * $('#example').dataTable( {
  11016. * "ajaxSource": "sources/deep.txt",
  11017. * "columns": [
  11018. * { "data": "engine" },
  11019. * { "data": "browser" },
  11020. * {
  11021. * "data": "platform",
  11022. * "render": "[, ].name"
  11023. * }
  11024. * ]
  11025. * } );
  11026. * } );
  11027. *
  11028. * @example
  11029. * // Execute a function to obtain data
  11030. * $(document).ready( function() {
  11031. * $('#example').dataTable( {
  11032. * "columnDefs": [ {
  11033. * "targets": [ 0 ],
  11034. * "data": null, // Use the full data source object for the renderer's source
  11035. * "render": "browserName()"
  11036. * } ]
  11037. * } );
  11038. * } );
  11039. *
  11040. * @example
  11041. * // As an object, extracting different data for the different types
  11042. * // This would be used with a data source such as:
  11043. * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
  11044. * // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
  11045. * // (which has both forms) is used for filtering for if a user inputs either format, while
  11046. * // the formatted phone number is the one that is shown in the table.
  11047. * $(document).ready( function() {
  11048. * $('#example').dataTable( {
  11049. * "columnDefs": [ {
  11050. * "targets": [ 0 ],
  11051. * "data": null, // Use the full data source object for the renderer's source
  11052. * "render": {
  11053. * "_": "phone",
  11054. * "filter": "phone_filter",
  11055. * "display": "phone_display"
  11056. * }
  11057. * } ]
  11058. * } );
  11059. * } );
  11060. *
  11061. * @example
  11062. * // Use as a function to create a link from the data source
  11063. * $(document).ready( function() {
  11064. * $('#example').dataTable( {
  11065. * "columnDefs": [ {
  11066. * "targets": [ 0 ],
  11067. * "data": "download_link",
  11068. * "render": function ( data, type, full ) {
  11069. * return '<a href="'+data+'">Download</a>';
  11070. * }
  11071. * } ]
  11072. * } );
  11073. * } );
  11074. */
  11075. "mRender": null,
  11076. /**
  11077. * Change the cell type created for the column - either TD cells or TH cells. This
  11078. * can be useful as TH cells have semantic meaning in the table body, allowing them
  11079. * to act as a header for a row (you may wish to add scope='row' to the TH elements).
  11080. * @type string
  11081. * @default td
  11082. *
  11083. * @name DataTable.defaults.column.cellType
  11084. * @dtopt Columns
  11085. *
  11086. * @example
  11087. * // Make the first column use TH cells
  11088. * $(document).ready( function() {
  11089. * $('#example').dataTable( {
  11090. * "columnDefs": [ {
  11091. * "targets": [ 0 ],
  11092. * "cellType": "th"
  11093. * } ]
  11094. * } );
  11095. * } );
  11096. */
  11097. "sCellType": "td",
  11098. /**
  11099. * Class to give to each cell in this column.
  11100. * @type string
  11101. * @default <i>Empty string</i>
  11102. *
  11103. * @name DataTable.defaults.column.class
  11104. * @dtopt Columns
  11105. *
  11106. * @example
  11107. * // Using `columnDefs`
  11108. * $(document).ready( function() {
  11109. * $('#example').dataTable( {
  11110. * "columnDefs": [
  11111. * { "class": "my_class", "targets": [ 0 ] }
  11112. * ]
  11113. * } );
  11114. * } );
  11115. *
  11116. * @example
  11117. * // Using `columns`
  11118. * $(document).ready( function() {
  11119. * $('#example').dataTable( {
  11120. * "columns": [
  11121. * { "class": "my_class" },
  11122. * null,
  11123. * null,
  11124. * null,
  11125. * null
  11126. * ]
  11127. * } );
  11128. * } );
  11129. */
  11130. "sClass": "",
  11131. /**
  11132. * When DataTables calculates the column widths to assign to each column,
  11133. * it finds the longest string in each column and then constructs a
  11134. * temporary table and reads the widths from that. The problem with this
  11135. * is that "mmm" is much wider then "iiii", but the latter is a longer
  11136. * string - thus the calculation can go wrong (doing it properly and putting
  11137. * it into an DOM object and measuring that is horribly(!) slow). Thus as
  11138. * a "work around" we provide this option. It will append its value to the
  11139. * text that is found to be the longest string for the column - i.e. padding.
  11140. * Generally you shouldn't need this!
  11141. * @type string
  11142. * @default <i>Empty string<i>
  11143. *
  11144. * @name DataTable.defaults.column.contentPadding
  11145. * @dtopt Columns
  11146. *
  11147. * @example
  11148. * // Using `columns`
  11149. * $(document).ready( function() {
  11150. * $('#example').dataTable( {
  11151. * "columns": [
  11152. * null,
  11153. * null,
  11154. * null,
  11155. * {
  11156. * "contentPadding": "mmm"
  11157. * }
  11158. * ]
  11159. * } );
  11160. * } );
  11161. */
  11162. "sContentPadding": "",
  11163. /**
  11164. * Allows a default value to be given for a column's data, and will be used
  11165. * whenever a null data source is encountered (this can be because `data`
  11166. * is set to null, or because the data source itself is null).
  11167. * @type string
  11168. * @default null
  11169. *
  11170. * @name DataTable.defaults.column.defaultContent
  11171. * @dtopt Columns
  11172. *
  11173. * @example
  11174. * // Using `columnDefs`
  11175. * $(document).ready( function() {
  11176. * $('#example').dataTable( {
  11177. * "columnDefs": [
  11178. * {
  11179. * "data": null,
  11180. * "defaultContent": "Edit",
  11181. * "targets": [ -1 ]
  11182. * }
  11183. * ]
  11184. * } );
  11185. * } );
  11186. *
  11187. * @example
  11188. * // Using `columns`
  11189. * $(document).ready( function() {
  11190. * $('#example').dataTable( {
  11191. * "columns": [
  11192. * null,
  11193. * null,
  11194. * null,
  11195. * {
  11196. * "data": null,
  11197. * "defaultContent": "Edit"
  11198. * }
  11199. * ]
  11200. * } );
  11201. * } );
  11202. */
  11203. "sDefaultContent": null,
  11204. /**
  11205. * This parameter is only used in DataTables' server-side processing. It can
  11206. * be exceptionally useful to know what columns are being displayed on the
  11207. * client side, and to map these to database fields. When defined, the names
  11208. * also allow DataTables to reorder information from the server if it comes
  11209. * back in an unexpected order (i.e. if you switch your columns around on the
  11210. * client-side, your server-side code does not also need updating).
  11211. * @type string
  11212. * @default <i>Empty string</i>
  11213. *
  11214. * @name DataTable.defaults.column.name
  11215. * @dtopt Columns
  11216. *
  11217. * @example
  11218. * // Using `columnDefs`
  11219. * $(document).ready( function() {
  11220. * $('#example').dataTable( {
  11221. * "columnDefs": [
  11222. * { "name": "engine", "targets": [ 0 ] },
  11223. * { "name": "browser", "targets": [ 1 ] },
  11224. * { "name": "platform", "targets": [ 2 ] },
  11225. * { "name": "version", "targets": [ 3 ] },
  11226. * { "name": "grade", "targets": [ 4 ] }
  11227. * ]
  11228. * } );
  11229. * } );
  11230. *
  11231. * @example
  11232. * // Using `columns`
  11233. * $(document).ready( function() {
  11234. * $('#example').dataTable( {
  11235. * "columns": [
  11236. * { "name": "engine" },
  11237. * { "name": "browser" },
  11238. * { "name": "platform" },
  11239. * { "name": "version" },
  11240. * { "name": "grade" }
  11241. * ]
  11242. * } );
  11243. * } );
  11244. */
  11245. "sName": "",
  11246. /**
  11247. * Defines a data source type for the ordering which can be used to read
  11248. * real-time information from the table (updating the internally cached
  11249. * version) prior to ordering. This allows ordering to occur on user
  11250. * editable elements such as form inputs.
  11251. * @type string
  11252. * @default std
  11253. *
  11254. * @name DataTable.defaults.column.orderDataType
  11255. * @dtopt Columns
  11256. *
  11257. * @example
  11258. * // Using `columnDefs`
  11259. * $(document).ready( function() {
  11260. * $('#example').dataTable( {
  11261. * "columnDefs": [
  11262. * { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
  11263. * { "type": "numeric", "targets": [ 3 ] },
  11264. * { "orderDataType": "dom-select", "targets": [ 4 ] },
  11265. * { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
  11266. * ]
  11267. * } );
  11268. * } );
  11269. *
  11270. * @example
  11271. * // Using `columns`
  11272. * $(document).ready( function() {
  11273. * $('#example').dataTable( {
  11274. * "columns": [
  11275. * null,
  11276. * null,
  11277. * { "orderDataType": "dom-text" },
  11278. * { "orderDataType": "dom-text", "type": "numeric" },
  11279. * { "orderDataType": "dom-select" },
  11280. * { "orderDataType": "dom-checkbox" }
  11281. * ]
  11282. * } );
  11283. * } );
  11284. */
  11285. "sSortDataType": "std",
  11286. /**
  11287. * The title of this column.
  11288. * @type string
  11289. * @default null <i>Derived from the 'TH' value for this column in the
  11290. * original HTML table.</i>
  11291. *
  11292. * @name DataTable.defaults.column.title
  11293. * @dtopt Columns
  11294. *
  11295. * @example
  11296. * // Using `columnDefs`
  11297. * $(document).ready( function() {
  11298. * $('#example').dataTable( {
  11299. * "columnDefs": [
  11300. * { "title": "My column title", "targets": [ 0 ] }
  11301. * ]
  11302. * } );
  11303. * } );
  11304. *
  11305. * @example
  11306. * // Using `columns`
  11307. * $(document).ready( function() {
  11308. * $('#example').dataTable( {
  11309. * "columns": [
  11310. * { "title": "My column title" },
  11311. * null,
  11312. * null,
  11313. * null,
  11314. * null
  11315. * ]
  11316. * } );
  11317. * } );
  11318. */
  11319. "sTitle": null,
  11320. /**
  11321. * The type allows you to specify how the data for this column will be
  11322. * ordered. Four types (string, numeric, date and html (which will strip
  11323. * HTML tags before ordering)) are currently available. Note that only date
  11324. * formats understood by Javascript's Date() object will be accepted as type
  11325. * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
  11326. * 'numeric', 'date' or 'html' (by default). Further types can be adding
  11327. * through plug-ins.
  11328. * @type string
  11329. * @default null <i>Auto-detected from raw data</i>
  11330. *
  11331. * @name DataTable.defaults.column.type
  11332. * @dtopt Columns
  11333. *
  11334. * @example
  11335. * // Using `columnDefs`
  11336. * $(document).ready( function() {
  11337. * $('#example').dataTable( {
  11338. * "columnDefs": [
  11339. * { "type": "html", "targets": [ 0 ] }
  11340. * ]
  11341. * } );
  11342. * } );
  11343. *
  11344. * @example
  11345. * // Using `columns`
  11346. * $(document).ready( function() {
  11347. * $('#example').dataTable( {
  11348. * "columns": [
  11349. * { "type": "html" },
  11350. * null,
  11351. * null,
  11352. * null,
  11353. * null
  11354. * ]
  11355. * } );
  11356. * } );
  11357. */
  11358. "sType": null,
  11359. /**
  11360. * Defining the width of the column, this parameter may take any CSS value
  11361. * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
  11362. * been given a specific width through this interface ensuring that the table
  11363. * remains readable.
  11364. * @type string
  11365. * @default null <i>Automatic</i>
  11366. *
  11367. * @name DataTable.defaults.column.width
  11368. * @dtopt Columns
  11369. *
  11370. * @example
  11371. * // Using `columnDefs`
  11372. * $(document).ready( function() {
  11373. * $('#example').dataTable( {
  11374. * "columnDefs": [
  11375. * { "width": "20%", "targets": [ 0 ] }
  11376. * ]
  11377. * } );
  11378. * } );
  11379. *
  11380. * @example
  11381. * // Using `columns`
  11382. * $(document).ready( function() {
  11383. * $('#example').dataTable( {
  11384. * "columns": [
  11385. * { "width": "20%" },
  11386. * null,
  11387. * null,
  11388. * null,
  11389. * null
  11390. * ]
  11391. * } );
  11392. * } );
  11393. */
  11394. "sWidth": null
  11395. };
  11396. _fnHungarianMap( DataTable.defaults.column );
  11397. /**
  11398. * DataTables settings object - this holds all the information needed for a
  11399. * given table, including configuration, data and current application of the
  11400. * table options. DataTables does not have a single instance for each DataTable
  11401. * with the settings attached to that instance, but rather instances of the
  11402. * DataTable "class" are created on-the-fly as needed (typically by a
  11403. * $().dataTable() call) and the settings object is then applied to that
  11404. * instance.
  11405. *
  11406. * Note that this object is related to {@link DataTable.defaults} but this
  11407. * one is the internal data store for DataTables's cache of columns. It should
  11408. * NOT be manipulated outside of DataTables. Any configuration should be done
  11409. * through the initialisation options.
  11410. * @namespace
  11411. * @todo Really should attach the settings object to individual instances so we
  11412. * don't need to create new instances on each $().dataTable() call (if the
  11413. * table already exists). It would also save passing oSettings around and
  11414. * into every single function. However, this is a very significant
  11415. * architecture change for DataTables and will almost certainly break
  11416. * backwards compatibility with older installations. This is something that
  11417. * will be done in 2.0.
  11418. */
  11419. DataTable.models.oSettings = {
  11420. /**
  11421. * Primary features of DataTables and their enablement state.
  11422. * @namespace
  11423. */
  11424. "oFeatures": {
  11425. /**
  11426. * Flag to say if DataTables should automatically try to calculate the
  11427. * optimum table and columns widths (true) or not (false).
  11428. * Note that this parameter will be set by the initialisation routine. To
  11429. * set a default use {@link DataTable.defaults}.
  11430. * @type boolean
  11431. */
  11432. "bAutoWidth": null,
  11433. /**
  11434. * Delay the creation of TR and TD elements until they are actually
  11435. * needed by a driven page draw. This can give a significant speed
  11436. * increase for Ajax source and Javascript source data, but makes no
  11437. * difference at all for DOM and server-side processing tables.
  11438. * Note that this parameter will be set by the initialisation routine. To
  11439. * set a default use {@link DataTable.defaults}.
  11440. * @type boolean
  11441. */
  11442. "bDeferRender": null,
  11443. /**
  11444. * Enable filtering on the table or not. Note that if this is disabled
  11445. * then there is no filtering at all on the table, including fnFilter.
  11446. * To just remove the filtering input use sDom and remove the 'f' option.
  11447. * Note that this parameter will be set by the initialisation routine. To
  11448. * set a default use {@link DataTable.defaults}.
  11449. * @type boolean
  11450. */
  11451. "bFilter": null,
  11452. /**
  11453. * Table information element (the 'Showing x of y records' div) enable
  11454. * flag.
  11455. * Note that this parameter will be set by the initialisation routine. To
  11456. * set a default use {@link DataTable.defaults}.
  11457. * @type boolean
  11458. */
  11459. "bInfo": null,
  11460. /**
  11461. * Present a user control allowing the end user to change the page size
  11462. * when pagination is enabled.
  11463. * Note that this parameter will be set by the initialisation routine. To
  11464. * set a default use {@link DataTable.defaults}.
  11465. * @type boolean
  11466. */
  11467. "bLengthChange": null,
  11468. /**
  11469. * Pagination enabled or not. Note that if this is disabled then length
  11470. * changing must also be disabled.
  11471. * Note that this parameter will be set by the initialisation routine. To
  11472. * set a default use {@link DataTable.defaults}.
  11473. * @type boolean
  11474. */
  11475. "bPaginate": null,
  11476. /**
  11477. * Processing indicator enable flag whenever DataTables is enacting a
  11478. * user request - typically an Ajax request for server-side processing.
  11479. * Note that this parameter will be set by the initialisation routine. To
  11480. * set a default use {@link DataTable.defaults}.
  11481. * @type boolean
  11482. */
  11483. "bProcessing": null,
  11484. /**
  11485. * Server-side processing enabled flag - when enabled DataTables will
  11486. * get all data from the server for every draw - there is no filtering,
  11487. * sorting or paging done on the client-side.
  11488. * Note that this parameter will be set by the initialisation routine. To
  11489. * set a default use {@link DataTable.defaults}.
  11490. * @type boolean
  11491. */
  11492. "bServerSide": null,
  11493. /**
  11494. * Sorting enablement flag.
  11495. * Note that this parameter will be set by the initialisation routine. To
  11496. * set a default use {@link DataTable.defaults}.
  11497. * @type boolean
  11498. */
  11499. "bSort": null,
  11500. /**
  11501. * Multi-column sorting
  11502. * Note that this parameter will be set by the initialisation routine. To
  11503. * set a default use {@link DataTable.defaults}.
  11504. * @type boolean
  11505. */
  11506. "bSortMulti": null,
  11507. /**
  11508. * Apply a class to the columns which are being sorted to provide a
  11509. * visual highlight or not. This can slow things down when enabled since
  11510. * there is a lot of DOM interaction.
  11511. * Note that this parameter will be set by the initialisation routine. To
  11512. * set a default use {@link DataTable.defaults}.
  11513. * @type boolean
  11514. */
  11515. "bSortClasses": null,
  11516. /**
  11517. * State saving enablement flag.
  11518. * Note that this parameter will be set by the initialisation routine. To
  11519. * set a default use {@link DataTable.defaults}.
  11520. * @type boolean
  11521. */
  11522. "bStateSave": null
  11523. },
  11524. /**
  11525. * Scrolling settings for a table.
  11526. * @namespace
  11527. */
  11528. "oScroll": {
  11529. /**
  11530. * When the table is shorter in height than sScrollY, collapse the
  11531. * table container down to the height of the table (when true).
  11532. * Note that this parameter will be set by the initialisation routine. To
  11533. * set a default use {@link DataTable.defaults}.
  11534. * @type boolean
  11535. */
  11536. "bCollapse": null,
  11537. /**
  11538. * Width of the scrollbar for the web-browser's platform. Calculated
  11539. * during table initialisation.
  11540. * @type int
  11541. * @default 0
  11542. */
  11543. "iBarWidth": 0,
  11544. /**
  11545. * Viewport width for horizontal scrolling. Horizontal scrolling is
  11546. * disabled if an empty string.
  11547. * Note that this parameter will be set by the initialisation routine. To
  11548. * set a default use {@link DataTable.defaults}.
  11549. * @type string
  11550. */
  11551. "sX": null,
  11552. /**
  11553. * Width to expand the table to when using x-scrolling. Typically you
  11554. * should not need to use this.
  11555. * Note that this parameter will be set by the initialisation routine. To
  11556. * set a default use {@link DataTable.defaults}.
  11557. * @type string
  11558. * @deprecated
  11559. */
  11560. "sXInner": null,
  11561. /**
  11562. * Viewport height for vertical scrolling. Vertical scrolling is disabled
  11563. * if an empty string.
  11564. * Note that this parameter will be set by the initialisation routine. To
  11565. * set a default use {@link DataTable.defaults}.
  11566. * @type string
  11567. */
  11568. "sY": null
  11569. },
  11570. /**
  11571. * Language information for the table.
  11572. * @namespace
  11573. * @extends DataTable.defaults.oLanguage
  11574. */
  11575. "oLanguage": {
  11576. /**
  11577. * Information callback function. See
  11578. * {@link DataTable.defaults.fnInfoCallback}
  11579. * @type function
  11580. * @default null
  11581. */
  11582. "fnInfoCallback": null
  11583. },
  11584. /**
  11585. * Browser support parameters
  11586. * @namespace
  11587. */
  11588. "oBrowser": {
  11589. /**
  11590. * Indicate if the browser incorrectly calculates width:100% inside a
  11591. * scrolling element (IE6/7)
  11592. * @type boolean
  11593. * @default false
  11594. */
  11595. "bScrollOversize": false,
  11596. /**
  11597. * Determine if the vertical scrollbar is on the right or left of the
  11598. * scrolling container - needed for rtl language layout, although not
  11599. * all browsers move the scrollbar (Safari).
  11600. * @type boolean
  11601. * @default false
  11602. */
  11603. "bScrollbarLeft": false,
  11604. /**
  11605. * Flag for if `getBoundingClientRect` is fully supported or not
  11606. * @type boolean
  11607. * @default false
  11608. */
  11609. "bBounding": false,
  11610. /**
  11611. * Browser scrollbar width
  11612. * @type integer
  11613. * @default 0
  11614. */
  11615. "barWidth": 0
  11616. },
  11617. "ajax": null,
  11618. /**
  11619. * Array referencing the nodes which are used for the features. The
  11620. * parameters of this object match what is allowed by sDom - i.e.
  11621. * <ul>
  11622. * <li>'l' - Length changing</li>
  11623. * <li>'f' - Filtering input</li>
  11624. * <li>'t' - The table!</li>
  11625. * <li>'i' - Information</li>
  11626. * <li>'p' - Pagination</li>
  11627. * <li>'r' - pRocessing</li>
  11628. * </ul>
  11629. * @type array
  11630. * @default []
  11631. */
  11632. "aanFeatures": [],
  11633. /**
  11634. * Store data information - see {@link DataTable.models.oRow} for detailed
  11635. * information.
  11636. * @type array
  11637. * @default []
  11638. */
  11639. "aoData": [],
  11640. /**
  11641. * Array of indexes which are in the current display (after filtering etc)
  11642. * @type array
  11643. * @default []
  11644. */
  11645. "aiDisplay": [],
  11646. /**
  11647. * Array of indexes for display - no filtering
  11648. * @type array
  11649. * @default []
  11650. */
  11651. "aiDisplayMaster": [],
  11652. /**
  11653. * Map of row ids to data indexes
  11654. * @type object
  11655. * @default {}
  11656. */
  11657. "aIds": {},
  11658. /**
  11659. * Store information about each column that is in use
  11660. * @type array
  11661. * @default []
  11662. */
  11663. "aoColumns": [],
  11664. /**
  11665. * Store information about the table's header
  11666. * @type array
  11667. * @default []
  11668. */
  11669. "aoHeader": [],
  11670. /**
  11671. * Store information about the table's footer
  11672. * @type array
  11673. * @default []
  11674. */
  11675. "aoFooter": [],
  11676. /**
  11677. * Store the applied global search information in case we want to force a
  11678. * research or compare the old search to a new one.
  11679. * Note that this parameter will be set by the initialisation routine. To
  11680. * set a default use {@link DataTable.defaults}.
  11681. * @namespace
  11682. * @extends DataTable.models.oSearch
  11683. */
  11684. "oPreviousSearch": {},
  11685. /**
  11686. * Store the applied search for each column - see
  11687. * {@link DataTable.models.oSearch} for the format that is used for the
  11688. * filtering information for each column.
  11689. * @type array
  11690. * @default []
  11691. */
  11692. "aoPreSearchCols": [],
  11693. /**
  11694. * Sorting that is applied to the table. Note that the inner arrays are
  11695. * used in the following manner:
  11696. * <ul>
  11697. * <li>Index 0 - column number</li>
  11698. * <li>Index 1 - current sorting direction</li>
  11699. * </ul>
  11700. * Note that this parameter will be set by the initialisation routine. To
  11701. * set a default use {@link DataTable.defaults}.
  11702. * @type array
  11703. * @todo These inner arrays should really be objects
  11704. */
  11705. "aaSorting": null,
  11706. /**
  11707. * Sorting that is always applied to the table (i.e. prefixed in front of
  11708. * aaSorting).
  11709. * Note that this parameter will be set by the initialisation routine. To
  11710. * set a default use {@link DataTable.defaults}.
  11711. * @type array
  11712. * @default []
  11713. */
  11714. "aaSortingFixed": [],
  11715. /**
  11716. * Classes to use for the striping of a table.
  11717. * Note that this parameter will be set by the initialisation routine. To
  11718. * set a default use {@link DataTable.defaults}.
  11719. * @type array
  11720. * @default []
  11721. */
  11722. "asStripeClasses": null,
  11723. /**
  11724. * If restoring a table - we should restore its striping classes as well
  11725. * @type array
  11726. * @default []
  11727. */
  11728. "asDestroyStripes": [],
  11729. /**
  11730. * If restoring a table - we should restore its width
  11731. * @type int
  11732. * @default 0
  11733. */
  11734. "sDestroyWidth": 0,
  11735. /**
  11736. * Callback functions array for every time a row is inserted (i.e. on a draw).
  11737. * @type array
  11738. * @default []
  11739. */
  11740. "aoRowCallback": [],
  11741. /**
  11742. * Callback functions for the header on each draw.
  11743. * @type array
  11744. * @default []
  11745. */
  11746. "aoHeaderCallback": [],
  11747. /**
  11748. * Callback function for the footer on each draw.
  11749. * @type array
  11750. * @default []
  11751. */
  11752. "aoFooterCallback": [],
  11753. /**
  11754. * Array of callback functions for draw callback functions
  11755. * @type array
  11756. * @default []
  11757. */
  11758. "aoDrawCallback": [],
  11759. /**
  11760. * Array of callback functions for row created function
  11761. * @type array
  11762. * @default []
  11763. */
  11764. "aoRowCreatedCallback": [],
  11765. /**
  11766. * Callback functions for just before the table is redrawn. A return of
  11767. * false will be used to cancel the draw.
  11768. * @type array
  11769. * @default []
  11770. */
  11771. "aoPreDrawCallback": [],
  11772. /**
  11773. * Callback functions for when the table has been initialised.
  11774. * @type array
  11775. * @default []
  11776. */
  11777. "aoInitComplete": [],
  11778. /**
  11779. * Callbacks for modifying the settings to be stored for state saving, prior to
  11780. * saving state.
  11781. * @type array
  11782. * @default []
  11783. */
  11784. "aoStateSaveParams": [],
  11785. /**
  11786. * Callbacks for modifying the settings that have been stored for state saving
  11787. * prior to using the stored values to restore the state.
  11788. * @type array
  11789. * @default []
  11790. */
  11791. "aoStateLoadParams": [],
  11792. /**
  11793. * Callbacks for operating on the settings object once the saved state has been
  11794. * loaded
  11795. * @type array
  11796. * @default []
  11797. */
  11798. "aoStateLoaded": [],
  11799. /**
  11800. * Cache the table ID for quick access
  11801. * @type string
  11802. * @default <i>Empty string</i>
  11803. */
  11804. "sTableId": "",
  11805. /**
  11806. * The TABLE node for the main table
  11807. * @type node
  11808. * @default null
  11809. */
  11810. "nTable": null,
  11811. /**
  11812. * Permanent ref to the thead element
  11813. * @type node
  11814. * @default null
  11815. */
  11816. "nTHead": null,
  11817. /**
  11818. * Permanent ref to the tfoot element - if it exists
  11819. * @type node
  11820. * @default null
  11821. */
  11822. "nTFoot": null,
  11823. /**
  11824. * Permanent ref to the tbody element
  11825. * @type node
  11826. * @default null
  11827. */
  11828. "nTBody": null,
  11829. /**
  11830. * Cache the wrapper node (contains all DataTables controlled elements)
  11831. * @type node
  11832. * @default null
  11833. */
  11834. "nTableWrapper": null,
  11835. /**
  11836. * Indicate if when using server-side processing the loading of data
  11837. * should be deferred until the second draw.
  11838. * Note that this parameter will be set by the initialisation routine. To
  11839. * set a default use {@link DataTable.defaults}.
  11840. * @type boolean
  11841. * @default false
  11842. */
  11843. "bDeferLoading": false,
  11844. /**
  11845. * Indicate if all required information has been read in
  11846. * @type boolean
  11847. * @default false
  11848. */
  11849. "bInitialised": false,
  11850. /**
  11851. * Information about open rows. Each object in the array has the parameters
  11852. * 'nTr' and 'nParent'
  11853. * @type array
  11854. * @default []
  11855. */
  11856. "aoOpenRows": [],
  11857. /**
  11858. * Dictate the positioning of DataTables' control elements - see
  11859. * {@link DataTable.model.oInit.sDom}.
  11860. * Note that this parameter will be set by the initialisation routine. To
  11861. * set a default use {@link DataTable.defaults}.
  11862. * @type string
  11863. * @default null
  11864. */
  11865. "sDom": null,
  11866. /**
  11867. * Search delay (in mS)
  11868. * @type integer
  11869. * @default null
  11870. */
  11871. "searchDelay": null,
  11872. /**
  11873. * Which type of pagination should be used.
  11874. * Note that this parameter will be set by the initialisation routine. To
  11875. * set a default use {@link DataTable.defaults}.
  11876. * @type string
  11877. * @default two_button
  11878. */
  11879. "sPaginationType": "two_button",
  11880. /**
  11881. * The state duration (for `stateSave`) in seconds.
  11882. * Note that this parameter will be set by the initialisation routine. To
  11883. * set a default use {@link DataTable.defaults}.
  11884. * @type int
  11885. * @default 0
  11886. */
  11887. "iStateDuration": 0,
  11888. /**
  11889. * Array of callback functions for state saving. Each array element is an
  11890. * object with the following parameters:
  11891. * <ul>
  11892. * <li>function:fn - function to call. Takes two parameters, oSettings
  11893. * and the JSON string to save that has been thus far created. Returns
  11894. * a JSON string to be inserted into a json object
  11895. * (i.e. '"param": [ 0, 1, 2]')</li>
  11896. * <li>string:sName - name of callback</li>
  11897. * </ul>
  11898. * @type array
  11899. * @default []
  11900. */
  11901. "aoStateSave": [],
  11902. /**
  11903. * Array of callback functions for state loading. Each array element is an
  11904. * object with the following parameters:
  11905. * <ul>
  11906. * <li>function:fn - function to call. Takes two parameters, oSettings
  11907. * and the object stored. May return false to cancel state loading</li>
  11908. * <li>string:sName - name of callback</li>
  11909. * </ul>
  11910. * @type array
  11911. * @default []
  11912. */
  11913. "aoStateLoad": [],
  11914. /**
  11915. * State that was saved. Useful for back reference
  11916. * @type object
  11917. * @default null
  11918. */
  11919. "oSavedState": null,
  11920. /**
  11921. * State that was loaded. Useful for back reference
  11922. * @type object
  11923. * @default null
  11924. */
  11925. "oLoadedState": null,
  11926. /**
  11927. * Source url for AJAX data for the table.
  11928. * Note that this parameter will be set by the initialisation routine. To
  11929. * set a default use {@link DataTable.defaults}.
  11930. * @type string
  11931. * @default null
  11932. */
  11933. "sAjaxSource": null,
  11934. /**
  11935. * Property from a given object from which to read the table data from. This
  11936. * can be an empty string (when not server-side processing), in which case
  11937. * it is assumed an an array is given directly.
  11938. * Note that this parameter will be set by the initialisation routine. To
  11939. * set a default use {@link DataTable.defaults}.
  11940. * @type string
  11941. */
  11942. "sAjaxDataProp": null,
  11943. /**
  11944. * The last jQuery XHR object that was used for server-side data gathering.
  11945. * This can be used for working with the XHR information in one of the
  11946. * callbacks
  11947. * @type object
  11948. * @default null
  11949. */
  11950. "jqXHR": null,
  11951. /**
  11952. * JSON returned from the server in the last Ajax request
  11953. * @type object
  11954. * @default undefined
  11955. */
  11956. "json": undefined,
  11957. /**
  11958. * Data submitted as part of the last Ajax request
  11959. * @type object
  11960. * @default undefined
  11961. */
  11962. "oAjaxData": undefined,
  11963. /**
  11964. * Function to get the server-side data.
  11965. * Note that this parameter will be set by the initialisation routine. To
  11966. * set a default use {@link DataTable.defaults}.
  11967. * @type function
  11968. */
  11969. "fnServerData": null,
  11970. /**
  11971. * Functions which are called prior to sending an Ajax request so extra
  11972. * parameters can easily be sent to the server
  11973. * @type array
  11974. * @default []
  11975. */
  11976. "aoServerParams": [],
  11977. /**
  11978. * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
  11979. * required).
  11980. * Note that this parameter will be set by the initialisation routine. To
  11981. * set a default use {@link DataTable.defaults}.
  11982. * @type string
  11983. */
  11984. "sServerMethod": null,
  11985. /**
  11986. * Format numbers for display.
  11987. * Note that this parameter will be set by the initialisation routine. To
  11988. * set a default use {@link DataTable.defaults}.
  11989. * @type function
  11990. */
  11991. "fnFormatNumber": null,
  11992. /**
  11993. * List of options that can be used for the user selectable length menu.
  11994. * Note that this parameter will be set by the initialisation routine. To
  11995. * set a default use {@link DataTable.defaults}.
  11996. * @type array
  11997. * @default []
  11998. */
  11999. "aLengthMenu": null,
  12000. /**
  12001. * Counter for the draws that the table does. Also used as a tracker for
  12002. * server-side processing
  12003. * @type int
  12004. * @default 0
  12005. */
  12006. "iDraw": 0,
  12007. /**
  12008. * Indicate if a redraw is being done - useful for Ajax
  12009. * @type boolean
  12010. * @default false
  12011. */
  12012. "bDrawing": false,
  12013. /**
  12014. * Draw index (iDraw) of the last error when parsing the returned data
  12015. * @type int
  12016. * @default -1
  12017. */
  12018. "iDrawError": -1,
  12019. /**
  12020. * Paging display length
  12021. * @type int
  12022. * @default 10
  12023. */
  12024. "_iDisplayLength": 10,
  12025. /**
  12026. * Paging start point - aiDisplay index
  12027. * @type int
  12028. * @default 0
  12029. */
  12030. "_iDisplayStart": 0,
  12031. /**
  12032. * Server-side processing - number of records in the result set
  12033. * (i.e. before filtering), Use fnRecordsTotal rather than
  12034. * this property to get the value of the number of records, regardless of
  12035. * the server-side processing setting.
  12036. * @type int
  12037. * @default 0
  12038. * @private
  12039. */
  12040. "_iRecordsTotal": 0,
  12041. /**
  12042. * Server-side processing - number of records in the current display set
  12043. * (i.e. after filtering). Use fnRecordsDisplay rather than
  12044. * this property to get the value of the number of records, regardless of
  12045. * the server-side processing setting.
  12046. * @type boolean
  12047. * @default 0
  12048. * @private
  12049. */
  12050. "_iRecordsDisplay": 0,
  12051. /**
  12052. * The classes to use for the table
  12053. * @type object
  12054. * @default {}
  12055. */
  12056. "oClasses": {},
  12057. /**
  12058. * Flag attached to the settings object so you can check in the draw
  12059. * callback if filtering has been done in the draw. Deprecated in favour of
  12060. * events.
  12061. * @type boolean
  12062. * @default false
  12063. * @deprecated
  12064. */
  12065. "bFiltered": false,
  12066. /**
  12067. * Flag attached to the settings object so you can check in the draw
  12068. * callback if sorting has been done in the draw. Deprecated in favour of
  12069. * events.
  12070. * @type boolean
  12071. * @default false
  12072. * @deprecated
  12073. */
  12074. "bSorted": false,
  12075. /**
  12076. * Indicate that if multiple rows are in the header and there is more than
  12077. * one unique cell per column, if the top one (true) or bottom one (false)
  12078. * should be used for sorting / title by DataTables.
  12079. * Note that this parameter will be set by the initialisation routine. To
  12080. * set a default use {@link DataTable.defaults}.
  12081. * @type boolean
  12082. */
  12083. "bSortCellsTop": null,
  12084. /**
  12085. * Initialisation object that is used for the table
  12086. * @type object
  12087. * @default null
  12088. */
  12089. "oInit": null,
  12090. /**
  12091. * Destroy callback functions - for plug-ins to attach themselves to the
  12092. * destroy so they can clean up markup and events.
  12093. * @type array
  12094. * @default []
  12095. */
  12096. "aoDestroyCallback": [],
  12097. /**
  12098. * Get the number of records in the current record set, before filtering
  12099. * @type function
  12100. */
  12101. "fnRecordsTotal": function ()
  12102. {
  12103. return _fnDataSource( this ) == 'ssp' ?
  12104. this._iRecordsTotal * 1 :
  12105. this.aiDisplayMaster.length;
  12106. },
  12107. /**
  12108. * Get the number of records in the current record set, after filtering
  12109. * @type function
  12110. */
  12111. "fnRecordsDisplay": function ()
  12112. {
  12113. return _fnDataSource( this ) == 'ssp' ?
  12114. this._iRecordsDisplay * 1 :
  12115. this.aiDisplay.length;
  12116. },
  12117. /**
  12118. * Get the display end point - aiDisplay index
  12119. * @type function
  12120. */
  12121. "fnDisplayEnd": function ()
  12122. {
  12123. var
  12124. len = this._iDisplayLength,
  12125. start = this._iDisplayStart,
  12126. calc = start + len,
  12127. records = this.aiDisplay.length,
  12128. features = this.oFeatures,
  12129. paginate = features.bPaginate;
  12130. if ( features.bServerSide ) {
  12131. return paginate === false || len === -1 ?
  12132. start + records :
  12133. Math.min( start+len, this._iRecordsDisplay );
  12134. }
  12135. else {
  12136. return ! paginate || calc>records || len===-1 ?
  12137. records :
  12138. calc;
  12139. }
  12140. },
  12141. /**
  12142. * The DataTables object for this table
  12143. * @type object
  12144. * @default null
  12145. */
  12146. "oInstance": null,
  12147. /**
  12148. * Unique identifier for each instance of the DataTables object. If there
  12149. * is an ID on the table node, then it takes that value, otherwise an
  12150. * incrementing internal counter is used.
  12151. * @type string
  12152. * @default null
  12153. */
  12154. "sInstance": null,
  12155. /**
  12156. * tabindex attribute value that is added to DataTables control elements, allowing
  12157. * keyboard navigation of the table and its controls.
  12158. */
  12159. "iTabIndex": 0,
  12160. /**
  12161. * DIV container for the footer scrolling table if scrolling
  12162. */
  12163. "nScrollHead": null,
  12164. /**
  12165. * DIV container for the footer scrolling table if scrolling
  12166. */
  12167. "nScrollFoot": null,
  12168. /**
  12169. * Last applied sort
  12170. * @type array
  12171. * @default []
  12172. */
  12173. "aLastSort": [],
  12174. /**
  12175. * Stored plug-in instances
  12176. * @type object
  12177. * @default {}
  12178. */
  12179. "oPlugins": {},
  12180. /**
  12181. * Function used to get a row's id from the row's data
  12182. * @type function
  12183. * @default null
  12184. */
  12185. "rowIdFn": null,
  12186. /**
  12187. * Data location where to store a row's id
  12188. * @type string
  12189. * @default null
  12190. */
  12191. "rowId": null
  12192. };
  12193. /**
  12194. * Extension object for DataTables that is used to provide all extension
  12195. * options.
  12196. *
  12197. * Note that the `DataTable.ext` object is available through
  12198. * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
  12199. * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
  12200. * @namespace
  12201. * @extends DataTable.models.ext
  12202. */
  12203. /**
  12204. * DataTables extensions
  12205. *
  12206. * This namespace acts as a collection area for plug-ins that can be used to
  12207. * extend DataTables capabilities. Indeed many of the build in methods
  12208. * use this method to provide their own capabilities (sorting methods for
  12209. * example).
  12210. *
  12211. * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
  12212. * reasons
  12213. *
  12214. * @namespace
  12215. */
  12216. DataTable.ext = _ext = {
  12217. /**
  12218. * Buttons. For use with the Buttons extension for DataTables. This is
  12219. * defined here so other extensions can define buttons regardless of load
  12220. * order. It is _not_ used by DataTables core.
  12221. *
  12222. * @type object
  12223. * @default {}
  12224. */
  12225. buttons: {},
  12226. /**
  12227. * Element class names
  12228. *
  12229. * @type object
  12230. * @default {}
  12231. */
  12232. classes: {},
  12233. /**
  12234. * DataTables build type (expanded by the download builder)
  12235. *
  12236. * @type string
  12237. */
  12238. build:"bs5/dt-1.12.0/r-2.3.0/sl-1.4.0",
  12239. /**
  12240. * Error reporting.
  12241. *
  12242. * How should DataTables report an error. Can take the value 'alert',
  12243. * 'throw', 'none' or a function.
  12244. *
  12245. * @type string|function
  12246. * @default alert
  12247. */
  12248. errMode: "alert",
  12249. /**
  12250. * Feature plug-ins.
  12251. *
  12252. * This is an array of objects which describe the feature plug-ins that are
  12253. * available to DataTables. These feature plug-ins are then available for
  12254. * use through the `dom` initialisation option.
  12255. *
  12256. * Each feature plug-in is described by an object which must have the
  12257. * following properties:
  12258. *
  12259. * * `fnInit` - function that is used to initialise the plug-in,
  12260. * * `cFeature` - a character so the feature can be enabled by the `dom`
  12261. * instillation option. This is case sensitive.
  12262. *
  12263. * The `fnInit` function has the following input parameters:
  12264. *
  12265. * 1. `{object}` DataTables settings object: see
  12266. * {@link DataTable.models.oSettings}
  12267. *
  12268. * And the following return is expected:
  12269. *
  12270. * * {node|null} The element which contains your feature. Note that the
  12271. * return may also be void if your plug-in does not require to inject any
  12272. * DOM elements into DataTables control (`dom`) - for example this might
  12273. * be useful when developing a plug-in which allows table control via
  12274. * keyboard entry
  12275. *
  12276. * @type array
  12277. *
  12278. * @example
  12279. * $.fn.dataTable.ext.features.push( {
  12280. * "fnInit": function( oSettings ) {
  12281. * return new TableTools( { "oDTSettings": oSettings } );
  12282. * },
  12283. * "cFeature": "T"
  12284. * } );
  12285. */
  12286. feature: [],
  12287. /**
  12288. * Row searching.
  12289. *
  12290. * This method of searching is complimentary to the default type based
  12291. * searching, and a lot more comprehensive as it allows you complete control
  12292. * over the searching logic. Each element in this array is a function
  12293. * (parameters described below) that is called for every row in the table,
  12294. * and your logic decides if it should be included in the searching data set
  12295. * or not.
  12296. *
  12297. * Searching functions have the following input parameters:
  12298. *
  12299. * 1. `{object}` DataTables settings object: see
  12300. * {@link DataTable.models.oSettings}
  12301. * 2. `{array|object}` Data for the row to be processed (same as the
  12302. * original format that was passed in as the data source, or an array
  12303. * from a DOM data source
  12304. * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
  12305. * can be useful to retrieve the `TR` element if you need DOM interaction.
  12306. *
  12307. * And the following return is expected:
  12308. *
  12309. * * {boolean} Include the row in the searched result set (true) or not
  12310. * (false)
  12311. *
  12312. * Note that as with the main search ability in DataTables, technically this
  12313. * is "filtering", since it is subtractive. However, for consistency in
  12314. * naming we call it searching here.
  12315. *
  12316. * @type array
  12317. * @default []
  12318. *
  12319. * @example
  12320. * // The following example shows custom search being applied to the
  12321. * // fourth column (i.e. the data[3] index) based on two input values
  12322. * // from the end-user, matching the data in a certain range.
  12323. * $.fn.dataTable.ext.search.push(
  12324. * function( settings, data, dataIndex ) {
  12325. * var min = document.getElementById('min').value * 1;
  12326. * var max = document.getElementById('max').value * 1;
  12327. * var version = data[3] == "-" ? 0 : data[3]*1;
  12328. *
  12329. * if ( min == "" && max == "" ) {
  12330. * return true;
  12331. * }
  12332. * else if ( min == "" && version < max ) {
  12333. * return true;
  12334. * }
  12335. * else if ( min < version && "" == max ) {
  12336. * return true;
  12337. * }
  12338. * else if ( min < version && version < max ) {
  12339. * return true;
  12340. * }
  12341. * return false;
  12342. * }
  12343. * );
  12344. */
  12345. search: [],
  12346. /**
  12347. * Selector extensions
  12348. *
  12349. * The `selector` option can be used to extend the options available for the
  12350. * selector modifier options (`selector-modifier` object data type) that
  12351. * each of the three built in selector types offer (row, column and cell +
  12352. * their plural counterparts). For example the Select extension uses this
  12353. * mechanism to provide an option to select only rows, columns and cells
  12354. * that have been marked as selected by the end user (`{selected: true}`),
  12355. * which can be used in conjunction with the existing built in selector
  12356. * options.
  12357. *
  12358. * Each property is an array to which functions can be pushed. The functions
  12359. * take three attributes:
  12360. *
  12361. * * Settings object for the host table
  12362. * * Options object (`selector-modifier` object type)
  12363. * * Array of selected item indexes
  12364. *
  12365. * The return is an array of the resulting item indexes after the custom
  12366. * selector has been applied.
  12367. *
  12368. * @type object
  12369. */
  12370. selector: {
  12371. cell: [],
  12372. column: [],
  12373. row: []
  12374. },
  12375. /**
  12376. * Internal functions, exposed for used in plug-ins.
  12377. *
  12378. * Please note that you should not need to use the internal methods for
  12379. * anything other than a plug-in (and even then, try to avoid if possible).
  12380. * The internal function may change between releases.
  12381. *
  12382. * @type object
  12383. * @default {}
  12384. */
  12385. internal: {},
  12386. /**
  12387. * Legacy configuration options. Enable and disable legacy options that
  12388. * are available in DataTables.
  12389. *
  12390. * @type object
  12391. */
  12392. legacy: {
  12393. /**
  12394. * Enable / disable DataTables 1.9 compatible server-side processing
  12395. * requests
  12396. *
  12397. * @type boolean
  12398. * @default null
  12399. */
  12400. ajax: null
  12401. },
  12402. /**
  12403. * Pagination plug-in methods.
  12404. *
  12405. * Each entry in this object is a function and defines which buttons should
  12406. * be shown by the pagination rendering method that is used for the table:
  12407. * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
  12408. * buttons are displayed in the document, while the functions here tell it
  12409. * what buttons to display. This is done by returning an array of button
  12410. * descriptions (what each button will do).
  12411. *
  12412. * Pagination types (the four built in options and any additional plug-in
  12413. * options defined here) can be used through the `paginationType`
  12414. * initialisation parameter.
  12415. *
  12416. * The functions defined take two parameters:
  12417. *
  12418. * 1. `{int} page` The current page index
  12419. * 2. `{int} pages` The number of pages in the table
  12420. *
  12421. * Each function is expected to return an array where each element of the
  12422. * array can be one of:
  12423. *
  12424. * * `first` - Jump to first page when activated
  12425. * * `last` - Jump to last page when activated
  12426. * * `previous` - Show previous page when activated
  12427. * * `next` - Show next page when activated
  12428. * * `{int}` - Show page of the index given
  12429. * * `{array}` - A nested array containing the above elements to add a
  12430. * containing 'DIV' element (might be useful for styling).
  12431. *
  12432. * Note that DataTables v1.9- used this object slightly differently whereby
  12433. * an object with two functions would be defined for each plug-in. That
  12434. * ability is still supported by DataTables 1.10+ to provide backwards
  12435. * compatibility, but this option of use is now decremented and no longer
  12436. * documented in DataTables 1.10+.
  12437. *
  12438. * @type object
  12439. * @default {}
  12440. *
  12441. * @example
  12442. * // Show previous, next and current page buttons only
  12443. * $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
  12444. * return [ 'previous', page, 'next' ];
  12445. * };
  12446. */
  12447. pager: {},
  12448. renderer: {
  12449. pageButton: {},
  12450. header: {}
  12451. },
  12452. /**
  12453. * Ordering plug-ins - custom data source
  12454. *
  12455. * The extension options for ordering of data available here is complimentary
  12456. * to the default type based ordering that DataTables typically uses. It
  12457. * allows much greater control over the the data that is being used to
  12458. * order a column, but is necessarily therefore more complex.
  12459. *
  12460. * This type of ordering is useful if you want to do ordering based on data
  12461. * live from the DOM (for example the contents of an 'input' element) rather
  12462. * than just the static string that DataTables knows of.
  12463. *
  12464. * The way these plug-ins work is that you create an array of the values you
  12465. * wish to be ordering for the column in question and then return that
  12466. * array. The data in the array much be in the index order of the rows in
  12467. * the table (not the currently ordering order!). Which order data gathering
  12468. * function is run here depends on the `dt-init columns.orderDataType`
  12469. * parameter that is used for the column (if any).
  12470. *
  12471. * The functions defined take two parameters:
  12472. *
  12473. * 1. `{object}` DataTables settings object: see
  12474. * {@link DataTable.models.oSettings}
  12475. * 2. `{int}` Target column index
  12476. *
  12477. * Each function is expected to return an array:
  12478. *
  12479. * * `{array}` Data for the column to be ordering upon
  12480. *
  12481. * @type array
  12482. *
  12483. * @example
  12484. * // Ordering using `input` node values
  12485. * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col )
  12486. * {
  12487. * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
  12488. * return $('input', td).val();
  12489. * } );
  12490. * }
  12491. */
  12492. order: {},
  12493. /**
  12494. * Type based plug-ins.
  12495. *
  12496. * Each column in DataTables has a type assigned to it, either by automatic
  12497. * detection or by direct assignment using the `type` option for the column.
  12498. * The type of a column will effect how it is ordering and search (plug-ins
  12499. * can also make use of the column type if required).
  12500. *
  12501. * @namespace
  12502. */
  12503. type: {
  12504. /**
  12505. * Type detection functions.
  12506. *
  12507. * The functions defined in this object are used to automatically detect
  12508. * a column's type, making initialisation of DataTables super easy, even
  12509. * when complex data is in the table.
  12510. *
  12511. * The functions defined take two parameters:
  12512. *
  12513. * 1. `{*}` Data from the column cell to be analysed
  12514. * 2. `{settings}` DataTables settings object. This can be used to
  12515. * perform context specific type detection - for example detection
  12516. * based on language settings such as using a comma for a decimal
  12517. * place. Generally speaking the options from the settings will not
  12518. * be required
  12519. *
  12520. * Each function is expected to return:
  12521. *
  12522. * * `{string|null}` Data type detected, or null if unknown (and thus
  12523. * pass it on to the other type detection functions.
  12524. *
  12525. * @type array
  12526. *
  12527. * @example
  12528. * // Currency type detection plug-in:
  12529. * $.fn.dataTable.ext.type.detect.push(
  12530. * function ( data, settings ) {
  12531. * // Check the numeric part
  12532. * if ( ! data.substring(1).match(/[0-9]/) ) {
  12533. * return null;
  12534. * }
  12535. *
  12536. * // Check prefixed by currency
  12537. * if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
  12538. * return 'currency';
  12539. * }
  12540. * return null;
  12541. * }
  12542. * );
  12543. */
  12544. detect: [],
  12545. /**
  12546. * Type based search formatting.
  12547. *
  12548. * The type based searching functions can be used to pre-format the
  12549. * data to be search on. For example, it can be used to strip HTML
  12550. * tags or to de-format telephone numbers for numeric only searching.
  12551. *
  12552. * Note that is a search is not defined for a column of a given type,
  12553. * no search formatting will be performed.
  12554. *
  12555. * Pre-processing of searching data plug-ins - When you assign the sType
  12556. * for a column (or have it automatically detected for you by DataTables
  12557. * or a type detection plug-in), you will typically be using this for
  12558. * custom sorting, but it can also be used to provide custom searching
  12559. * by allowing you to pre-processing the data and returning the data in
  12560. * the format that should be searched upon. This is done by adding
  12561. * functions this object with a parameter name which matches the sType
  12562. * for that target column. This is the corollary of <i>afnSortData</i>
  12563. * for searching data.
  12564. *
  12565. * The functions defined take a single parameter:
  12566. *
  12567. * 1. `{*}` Data from the column cell to be prepared for searching
  12568. *
  12569. * Each function is expected to return:
  12570. *
  12571. * * `{string|null}` Formatted string that will be used for the searching.
  12572. *
  12573. * @type object
  12574. * @default {}
  12575. *
  12576. * @example
  12577. * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
  12578. * return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
  12579. * }
  12580. */
  12581. search: {},
  12582. /**
  12583. * Type based ordering.
  12584. *
  12585. * The column type tells DataTables what ordering to apply to the table
  12586. * when a column is sorted upon. The order for each type that is defined,
  12587. * is defined by the functions available in this object.
  12588. *
  12589. * Each ordering option can be described by three properties added to
  12590. * this object:
  12591. *
  12592. * * `{type}-pre` - Pre-formatting function
  12593. * * `{type}-asc` - Ascending order function
  12594. * * `{type}-desc` - Descending order function
  12595. *
  12596. * All three can be used together, only `{type}-pre` or only
  12597. * `{type}-asc` and `{type}-desc` together. It is generally recommended
  12598. * that only `{type}-pre` is used, as this provides the optimal
  12599. * implementation in terms of speed, although the others are provided
  12600. * for compatibility with existing Javascript sort functions.
  12601. *
  12602. * `{type}-pre`: Functions defined take a single parameter:
  12603. *
  12604. * 1. `{*}` Data from the column cell to be prepared for ordering
  12605. *
  12606. * And return:
  12607. *
  12608. * * `{*}` Data to be sorted upon
  12609. *
  12610. * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
  12611. * functions, taking two parameters:
  12612. *
  12613. * 1. `{*}` Data to compare to the second parameter
  12614. * 2. `{*}` Data to compare to the first parameter
  12615. *
  12616. * And returning:
  12617. *
  12618. * * `{*}` Ordering match: <0 if first parameter should be sorted lower
  12619. * than the second parameter, ===0 if the two parameters are equal and
  12620. * >0 if the first parameter should be sorted height than the second
  12621. * parameter.
  12622. *
  12623. * @type object
  12624. * @default {}
  12625. *
  12626. * @example
  12627. * // Numeric ordering of formatted numbers with a pre-formatter
  12628. * $.extend( $.fn.dataTable.ext.type.order, {
  12629. * "string-pre": function(x) {
  12630. * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
  12631. * return parseFloat( a );
  12632. * }
  12633. * } );
  12634. *
  12635. * @example
  12636. * // Case-sensitive string ordering, with no pre-formatting method
  12637. * $.extend( $.fn.dataTable.ext.order, {
  12638. * "string-case-asc": function(x,y) {
  12639. * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  12640. * },
  12641. * "string-case-desc": function(x,y) {
  12642. * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  12643. * }
  12644. * } );
  12645. */
  12646. order: {}
  12647. },
  12648. /**
  12649. * Unique DataTables instance counter
  12650. *
  12651. * @type int
  12652. * @private
  12653. */
  12654. _unique: 0,
  12655. //
  12656. // Depreciated
  12657. // The following properties are retained for backwards compatibility only.
  12658. // The should not be used in new projects and will be removed in a future
  12659. // version
  12660. //
  12661. /**
  12662. * Version check function.
  12663. * @type function
  12664. * @depreciated Since 1.10
  12665. */
  12666. fnVersionCheck: DataTable.fnVersionCheck,
  12667. /**
  12668. * Index for what 'this' index API functions should use
  12669. * @type int
  12670. * @deprecated Since v1.10
  12671. */
  12672. iApiIndex: 0,
  12673. /**
  12674. * jQuery UI class container
  12675. * @type object
  12676. * @deprecated Since v1.10
  12677. */
  12678. oJUIClasses: {},
  12679. /**
  12680. * Software version
  12681. * @type string
  12682. * @deprecated Since v1.10
  12683. */
  12684. sVersion: DataTable.version
  12685. };
  12686. //
  12687. // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
  12688. //
  12689. $.extend( _ext, {
  12690. afnFiltering: _ext.search,
  12691. aTypes: _ext.type.detect,
  12692. ofnSearch: _ext.type.search,
  12693. oSort: _ext.type.order,
  12694. afnSortData: _ext.order,
  12695. aoFeatures: _ext.feature,
  12696. oApi: _ext.internal,
  12697. oStdClasses: _ext.classes,
  12698. oPagination: _ext.pager
  12699. } );
  12700. $.extend( DataTable.ext.classes, {
  12701. "sTable": "dataTable",
  12702. "sNoFooter": "no-footer",
  12703. /* Paging buttons */
  12704. "sPageButton": "paginate_button",
  12705. "sPageButtonActive": "current",
  12706. "sPageButtonDisabled": "disabled",
  12707. /* Striping classes */
  12708. "sStripeOdd": "odd",
  12709. "sStripeEven": "even",
  12710. /* Empty row */
  12711. "sRowEmpty": "dataTables_empty",
  12712. /* Features */
  12713. "sWrapper": "dataTables_wrapper",
  12714. "sFilter": "dataTables_filter",
  12715. "sInfo": "dataTables_info",
  12716. "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
  12717. "sLength": "dataTables_length",
  12718. "sProcessing": "dataTables_processing",
  12719. /* Sorting */
  12720. "sSortAsc": "sorting_asc",
  12721. "sSortDesc": "sorting_desc",
  12722. "sSortable": "sorting", /* Sortable in both directions */
  12723. "sSortableAsc": "sorting_desc_disabled",
  12724. "sSortableDesc": "sorting_asc_disabled",
  12725. "sSortableNone": "sorting_disabled",
  12726. "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
  12727. /* Filtering */
  12728. "sFilterInput": "",
  12729. /* Page length */
  12730. "sLengthSelect": "",
  12731. /* Scrolling */
  12732. "sScrollWrapper": "dataTables_scroll",
  12733. "sScrollHead": "dataTables_scrollHead",
  12734. "sScrollHeadInner": "dataTables_scrollHeadInner",
  12735. "sScrollBody": "dataTables_scrollBody",
  12736. "sScrollFoot": "dataTables_scrollFoot",
  12737. "sScrollFootInner": "dataTables_scrollFootInner",
  12738. /* Misc */
  12739. "sHeaderTH": "",
  12740. "sFooterTH": "",
  12741. // Deprecated
  12742. "sSortJUIAsc": "",
  12743. "sSortJUIDesc": "",
  12744. "sSortJUI": "",
  12745. "sSortJUIAscAllowed": "",
  12746. "sSortJUIDescAllowed": "",
  12747. "sSortJUIWrapper": "",
  12748. "sSortIcon": "",
  12749. "sJUIHeader": "",
  12750. "sJUIFooter": ""
  12751. } );
  12752. var extPagination = DataTable.ext.pager;
  12753. function _numbers ( page, pages ) {
  12754. var
  12755. numbers = [],
  12756. buttons = extPagination.numbers_length,
  12757. half = Math.floor( buttons / 2 ),
  12758. i = 1;
  12759. if ( pages <= buttons ) {
  12760. numbers = _range( 0, pages );
  12761. }
  12762. else if ( page <= half ) {
  12763. numbers = _range( 0, buttons-2 );
  12764. numbers.push( 'ellipsis' );
  12765. numbers.push( pages-1 );
  12766. }
  12767. else if ( page >= pages - 1 - half ) {
  12768. numbers = _range( pages-(buttons-2), pages );
  12769. numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
  12770. numbers.splice( 0, 0, 0 );
  12771. }
  12772. else {
  12773. numbers = _range( page-half+2, page+half-1 );
  12774. numbers.push( 'ellipsis' );
  12775. numbers.push( pages-1 );
  12776. numbers.splice( 0, 0, 'ellipsis' );
  12777. numbers.splice( 0, 0, 0 );
  12778. }
  12779. numbers.DT_el = 'span';
  12780. return numbers;
  12781. }
  12782. $.extend( extPagination, {
  12783. simple: function ( page, pages ) {
  12784. return [ 'previous', 'next' ];
  12785. },
  12786. full: function ( page, pages ) {
  12787. return [ 'first', 'previous', 'next', 'last' ];
  12788. },
  12789. numbers: function ( page, pages ) {
  12790. return [ _numbers(page, pages) ];
  12791. },
  12792. simple_numbers: function ( page, pages ) {
  12793. return [ 'previous', _numbers(page, pages), 'next' ];
  12794. },
  12795. full_numbers: function ( page, pages ) {
  12796. return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
  12797. },
  12798. first_last_numbers: function (page, pages) {
  12799. return ['first', _numbers(page, pages), 'last'];
  12800. },
  12801. // For testing and plug-ins to use
  12802. _numbers: _numbers,
  12803. // Number of number buttons (including ellipsis) to show. _Must be odd!_
  12804. numbers_length: 7
  12805. } );
  12806. $.extend( true, DataTable.ext.renderer, {
  12807. pageButton: {
  12808. _: function ( settings, host, idx, buttons, page, pages ) {
  12809. var classes = settings.oClasses;
  12810. var lang = settings.oLanguage.oPaginate;
  12811. var aria = settings.oLanguage.oAria.paginate || {};
  12812. var btnDisplay, btnClass, counter=0;
  12813. var attach = function( container, buttons ) {
  12814. var i, ien, node, button, tabIndex;
  12815. var disabledClass = classes.sPageButtonDisabled;
  12816. var clickHandler = function ( e ) {
  12817. _fnPageChange( settings, e.data.action, true );
  12818. };
  12819. for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
  12820. button = buttons[i];
  12821. if ( Array.isArray( button ) ) {
  12822. var inner = $( '<'+(button.DT_el || 'div')+'/>' )
  12823. .appendTo( container );
  12824. attach( inner, button );
  12825. }
  12826. else {
  12827. btnDisplay = null;
  12828. btnClass = button;
  12829. tabIndex = settings.iTabIndex;
  12830. switch ( button ) {
  12831. case 'ellipsis':
  12832. container.append('<span class="ellipsis">&#x2026;</span>');
  12833. break;
  12834. case 'first':
  12835. btnDisplay = lang.sFirst;
  12836. if ( page === 0 ) {
  12837. tabIndex = -1;
  12838. btnClass += ' ' + disabledClass;
  12839. }
  12840. break;
  12841. case 'previous':
  12842. btnDisplay = lang.sPrevious;
  12843. if ( page === 0 ) {
  12844. tabIndex = -1;
  12845. btnClass += ' ' + disabledClass;
  12846. }
  12847. break;
  12848. case 'next':
  12849. btnDisplay = lang.sNext;
  12850. if ( pages === 0 || page === pages-1 ) {
  12851. tabIndex = -1;
  12852. btnClass += ' ' + disabledClass;
  12853. }
  12854. break;
  12855. case 'last':
  12856. btnDisplay = lang.sLast;
  12857. if ( pages === 0 || page === pages-1 ) {
  12858. tabIndex = -1;
  12859. btnClass += ' ' + disabledClass;
  12860. }
  12861. break;
  12862. default:
  12863. btnDisplay = settings.fnFormatNumber( button + 1 );
  12864. btnClass = page === button ?
  12865. classes.sPageButtonActive : '';
  12866. break;
  12867. }
  12868. if ( btnDisplay !== null ) {
  12869. node = $('<a>', {
  12870. 'class': classes.sPageButton+' '+btnClass,
  12871. 'aria-controls': settings.sTableId,
  12872. 'aria-label': aria[ button ],
  12873. 'data-dt-idx': counter,
  12874. 'tabindex': tabIndex,
  12875. 'id': idx === 0 && typeof button === 'string' ?
  12876. settings.sTableId +'_'+ button :
  12877. null
  12878. } )
  12879. .html( btnDisplay )
  12880. .appendTo( container );
  12881. _fnBindAction(
  12882. node, {action: button}, clickHandler
  12883. );
  12884. counter++;
  12885. }
  12886. }
  12887. }
  12888. };
  12889. // IE9 throws an 'unknown error' if document.activeElement is used
  12890. // inside an iframe or frame. Try / catch the error. Not good for
  12891. // accessibility, but neither are frames.
  12892. var activeEl;
  12893. try {
  12894. // Because this approach is destroying and recreating the paging
  12895. // elements, focus is lost on the select button which is bad for
  12896. // accessibility. So we want to restore focus once the draw has
  12897. // completed
  12898. activeEl = $(host).find(document.activeElement).data('dt-idx');
  12899. }
  12900. catch (e) {}
  12901. attach( $(host).empty(), buttons );
  12902. if ( activeEl !== undefined ) {
  12903. $(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');
  12904. }
  12905. }
  12906. }
  12907. } );
  12908. // Built in type detection. See model.ext.aTypes for information about
  12909. // what is required from this methods.
  12910. $.extend( DataTable.ext.type.detect, [
  12911. // Plain numbers - first since V8 detects some plain numbers as dates
  12912. // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
  12913. function ( d, settings )
  12914. {
  12915. var decimal = settings.oLanguage.sDecimal;
  12916. return _isNumber( d, decimal ) ? 'num'+decimal : null;
  12917. },
  12918. // Dates (only those recognised by the browser's Date.parse)
  12919. function ( d, settings )
  12920. {
  12921. // V8 tries _very_ hard to make a string passed into `Date.parse()`
  12922. // valid, so we need to use a regex to restrict date formats. Use a
  12923. // plug-in for anything other than ISO8601 style strings
  12924. if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
  12925. return null;
  12926. }
  12927. var parsed = Date.parse(d);
  12928. return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
  12929. },
  12930. // Formatted numbers
  12931. function ( d, settings )
  12932. {
  12933. var decimal = settings.oLanguage.sDecimal;
  12934. return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
  12935. },
  12936. // HTML numeric
  12937. function ( d, settings )
  12938. {
  12939. var decimal = settings.oLanguage.sDecimal;
  12940. return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
  12941. },
  12942. // HTML numeric, formatted
  12943. function ( d, settings )
  12944. {
  12945. var decimal = settings.oLanguage.sDecimal;
  12946. return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
  12947. },
  12948. // HTML (this is strict checking - there must be html)
  12949. function ( d, settings )
  12950. {
  12951. return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
  12952. 'html' : null;
  12953. }
  12954. ] );
  12955. // Filter formatting functions. See model.ext.ofnSearch for information about
  12956. // what is required from these methods.
  12957. //
  12958. // Note that additional search methods are added for the html numbers and
  12959. // html formatted numbers by `_addNumericSort()` when we know what the decimal
  12960. // place is
  12961. $.extend( DataTable.ext.type.search, {
  12962. html: function ( data ) {
  12963. return _empty(data) ?
  12964. data :
  12965. typeof data === 'string' ?
  12966. data
  12967. .replace( _re_new_lines, " " )
  12968. .replace( _re_html, "" ) :
  12969. '';
  12970. },
  12971. string: function ( data ) {
  12972. return _empty(data) ?
  12973. data :
  12974. typeof data === 'string' ?
  12975. data.replace( _re_new_lines, " " ) :
  12976. data;
  12977. }
  12978. } );
  12979. var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
  12980. if ( d !== 0 && (!d || d === '-') ) {
  12981. return -Infinity;
  12982. }
  12983. // If a decimal place other than `.` is used, it needs to be given to the
  12984. // function so we can detect it and replace with a `.` which is the only
  12985. // decimal place Javascript recognises - it is not locale aware.
  12986. if ( decimalPlace ) {
  12987. d = _numToDecimal( d, decimalPlace );
  12988. }
  12989. if ( d.replace ) {
  12990. if ( re1 ) {
  12991. d = d.replace( re1, '' );
  12992. }
  12993. if ( re2 ) {
  12994. d = d.replace( re2, '' );
  12995. }
  12996. }
  12997. return d * 1;
  12998. };
  12999. // Add the numeric 'deformatting' functions for sorting and search. This is done
  13000. // in a function to provide an easy ability for the language options to add
  13001. // additional methods if a non-period decimal place is used.
  13002. function _addNumericSort ( decimalPlace ) {
  13003. $.each(
  13004. {
  13005. // Plain numbers
  13006. "num": function ( d ) {
  13007. return __numericReplace( d, decimalPlace );
  13008. },
  13009. // Formatted numbers
  13010. "num-fmt": function ( d ) {
  13011. return __numericReplace( d, decimalPlace, _re_formatted_numeric );
  13012. },
  13013. // HTML numeric
  13014. "html-num": function ( d ) {
  13015. return __numericReplace( d, decimalPlace, _re_html );
  13016. },
  13017. // HTML numeric, formatted
  13018. "html-num-fmt": function ( d ) {
  13019. return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
  13020. }
  13021. },
  13022. function ( key, fn ) {
  13023. // Add the ordering method
  13024. _ext.type.order[ key+decimalPlace+'-pre' ] = fn;
  13025. // For HTML types add a search formatter that will strip the HTML
  13026. if ( key.match(/^html\-/) ) {
  13027. _ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
  13028. }
  13029. }
  13030. );
  13031. }
  13032. // Default sort methods
  13033. $.extend( _ext.type.order, {
  13034. // Dates
  13035. "date-pre": function ( d ) {
  13036. var ts = Date.parse( d );
  13037. return isNaN(ts) ? -Infinity : ts;
  13038. },
  13039. // html
  13040. "html-pre": function ( a ) {
  13041. return _empty(a) ?
  13042. '' :
  13043. a.replace ?
  13044. a.replace( /<.*?>/g, "" ).toLowerCase() :
  13045. a+'';
  13046. },
  13047. // string
  13048. "string-pre": function ( a ) {
  13049. // This is a little complex, but faster than always calling toString,
  13050. // http://jsperf.com/tostring-v-check
  13051. return _empty(a) ?
  13052. '' :
  13053. typeof a === 'string' ?
  13054. a.toLowerCase() :
  13055. ! a.toString ?
  13056. '' :
  13057. a.toString();
  13058. },
  13059. // string-asc and -desc are retained only for compatibility with the old
  13060. // sort methods
  13061. "string-asc": function ( x, y ) {
  13062. return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  13063. },
  13064. "string-desc": function ( x, y ) {
  13065. return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  13066. }
  13067. } );
  13068. // Numeric sorting types - order doesn't matter here
  13069. _addNumericSort( '' );
  13070. $.extend( true, DataTable.ext.renderer, {
  13071. header: {
  13072. _: function ( settings, cell, column, classes ) {
  13073. // No additional mark-up required
  13074. // Attach a sort listener to update on sort - note that using the
  13075. // `DT` namespace will allow the event to be removed automatically
  13076. // on destroy, while the `dt` namespaced event is the one we are
  13077. // listening for
  13078. $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
  13079. if ( settings !== ctx ) { // need to check this this is the host
  13080. return; // table, not a nested one
  13081. }
  13082. var colIdx = column.idx;
  13083. cell
  13084. .removeClass(
  13085. classes.sSortAsc +' '+
  13086. classes.sSortDesc
  13087. )
  13088. .addClass( columns[ colIdx ] == 'asc' ?
  13089. classes.sSortAsc : columns[ colIdx ] == 'desc' ?
  13090. classes.sSortDesc :
  13091. column.sSortingClass
  13092. );
  13093. } );
  13094. },
  13095. jqueryui: function ( settings, cell, column, classes ) {
  13096. $('<div/>')
  13097. .addClass( classes.sSortJUIWrapper )
  13098. .append( cell.contents() )
  13099. .append( $('<span/>')
  13100. .addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
  13101. )
  13102. .appendTo( cell );
  13103. // Attach a sort listener to update on sort
  13104. $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
  13105. if ( settings !== ctx ) {
  13106. return;
  13107. }
  13108. var colIdx = column.idx;
  13109. cell
  13110. .removeClass( classes.sSortAsc +" "+classes.sSortDesc )
  13111. .addClass( columns[ colIdx ] == 'asc' ?
  13112. classes.sSortAsc : columns[ colIdx ] == 'desc' ?
  13113. classes.sSortDesc :
  13114. column.sSortingClass
  13115. );
  13116. cell
  13117. .find( 'span.'+classes.sSortIcon )
  13118. .removeClass(
  13119. classes.sSortJUIAsc +" "+
  13120. classes.sSortJUIDesc +" "+
  13121. classes.sSortJUI +" "+
  13122. classes.sSortJUIAscAllowed +" "+
  13123. classes.sSortJUIDescAllowed
  13124. )
  13125. .addClass( columns[ colIdx ] == 'asc' ?
  13126. classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
  13127. classes.sSortJUIDesc :
  13128. column.sSortingClassJUI
  13129. );
  13130. } );
  13131. }
  13132. }
  13133. } );
  13134. /*
  13135. * Public helper functions. These aren't used internally by DataTables, or
  13136. * called by any of the options passed into DataTables, but they can be used
  13137. * externally by developers working with DataTables. They are helper functions
  13138. * to make working with DataTables a little bit easier.
  13139. */
  13140. var __htmlEscapeEntities = function ( d ) {
  13141. if (Array.isArray(d)) {
  13142. d = d.join(',');
  13143. }
  13144. return typeof d === 'string' ?
  13145. d
  13146. .replace(/&/g, '&amp;')
  13147. .replace(/</g, '&lt;')
  13148. .replace(/>/g, '&gt;')
  13149. .replace(/"/g, '&quot;') :
  13150. d;
  13151. };
  13152. // Common logic for moment, luxon or a date action
  13153. function __mld( dt, momentFn, luxonFn, dateFn, arg1 ) {
  13154. if (window.moment) {
  13155. return dt[momentFn]( arg1 );
  13156. }
  13157. else if (window.luxon) {
  13158. return dt[luxonFn]( arg1 );
  13159. }
  13160. return dateFn ? dt[dateFn]( arg1 ) : dt;
  13161. }
  13162. var __mlWarning = false;
  13163. function __mldObj (d, format, locale) {
  13164. var dt;
  13165. if (window.moment) {
  13166. dt = window.moment.utc( d, format, locale, true );
  13167. if (! dt.isValid()) {
  13168. return null;
  13169. }
  13170. }
  13171. else if (window.luxon) {
  13172. dt = format
  13173. ? window.luxon.DateTime.fromFormat( d, format )
  13174. : window.luxon.DateTime.fromISO( d );
  13175. if (! dt.isValid) {
  13176. return null;
  13177. }
  13178. dt.setLocale(locale);
  13179. }
  13180. else if (! format) {
  13181. // No format given, must be ISO
  13182. dt = new Date(d);
  13183. }
  13184. else {
  13185. if (! __mlWarning) {
  13186. alert('DataTables warning: Formatted date without Moment.js or Luxon - https://datatables.net/tn/17');
  13187. }
  13188. __mlWarning = true;
  13189. }
  13190. return dt;
  13191. }
  13192. // Wrapper for date, datetime and time which all operate the same way with the exception of
  13193. // the output string for auto locale support
  13194. function __mlHelper (localeString) {
  13195. return function ( from, to, locale, def ) {
  13196. // Luxon and Moment support
  13197. // Argument shifting
  13198. if ( arguments.length === 0 ) {
  13199. locale = 'en';
  13200. to = null; // means toLocaleString
  13201. from = null; // means iso8601
  13202. }
  13203. else if ( arguments.length === 1 ) {
  13204. locale = 'en';
  13205. to = from;
  13206. from = null;
  13207. }
  13208. else if ( arguments.length === 2 ) {
  13209. locale = to;
  13210. to = from;
  13211. from = null;
  13212. }
  13213. var typeName = 'datetime-' + to;
  13214. // Add type detection and sorting specific to this date format - we need to be able to identify
  13215. // date type columns as such, rather than as numbers in extensions. Hence the need for this.
  13216. if (! DataTable.ext.type.order[typeName]) {
  13217. // The renderer will give the value to type detect as the type!
  13218. DataTable.ext.type.detect.unshift(function (d) {
  13219. return d === typeName ? typeName : false;
  13220. });
  13221. // The renderer gives us Moment, Luxon or Date obects for the sorting, all of which have a
  13222. // `valueOf` which gives milliseconds epoch
  13223. DataTable.ext.type.order[typeName + '-asc'] = function (a, b) {
  13224. var x = a.valueOf();
  13225. var y = b.valueOf();
  13226. return x === y
  13227. ? 0
  13228. : x < y
  13229. ? -1
  13230. : 1;
  13231. }
  13232. DataTable.ext.type.order[typeName + '-desc'] = function (a, b) {
  13233. var x = a.valueOf();
  13234. var y = b.valueOf();
  13235. return x === y
  13236. ? 0
  13237. : x > y
  13238. ? -1
  13239. : 1;
  13240. }
  13241. }
  13242. return function ( d, type ) {
  13243. // Allow for a default value
  13244. if (d === null || d === undefined) {
  13245. if (def === '--now') {
  13246. // We treat everything as UTC further down, so no changes are
  13247. // made, as such need to get the local date / time as if it were
  13248. // UTC
  13249. var local = new Date();
  13250. d = new Date( Date.UTC(
  13251. local.getFullYear(), local.getMonth(), local.getDate(),
  13252. local.getHours(), local.getMinutes(), local.getSeconds()
  13253. ) );
  13254. }
  13255. else {
  13256. d = '';
  13257. }
  13258. }
  13259. if (type === 'type') {
  13260. // Typing uses the type name for fast matching
  13261. return typeName;
  13262. }
  13263. if (d === '') {
  13264. return type !== 'sort'
  13265. ? ''
  13266. : __mldObj('0000-01-01 00:00:00', null, locale);
  13267. }
  13268. // Shortcut. If `from` and `to` are the same, we are using the renderer to
  13269. // format for ordering, not display - its already in the display format.
  13270. if ( to !== null && from === to && type !== 'sort' && type !== 'type' && ! (d instanceof Date) ) {
  13271. return d;
  13272. }
  13273. var dt = __mldObj(d, from, locale);
  13274. if (dt === null) {
  13275. return d;
  13276. }
  13277. if (type === 'sort') {
  13278. return dt;
  13279. }
  13280. var formatted = to === null
  13281. ? __mld(dt, 'toDate', 'toJSDate', '')[localeString]()
  13282. : __mld(dt, 'format', 'toFormat', 'toISOString', to);
  13283. // XSS protection
  13284. return type === 'display' ?
  13285. __htmlEscapeEntities( formatted ) :
  13286. formatted;
  13287. };
  13288. }
  13289. }
  13290. // Based on locale, determine standard number formatting
  13291. var __thousands = '';
  13292. var __decimal = '';
  13293. if (Intl) {
  13294. var num = new Intl.NumberFormat().formatToParts(1000.1);
  13295. __thousands = num[1].value;
  13296. __decimal = num[3].value;
  13297. }
  13298. // Formatted date time detection - use by declaring the formats you are going to use
  13299. DataTable.datetime = function ( format, locale ) {
  13300. var typeName = 'datetime-detect-' + format;
  13301. if (! locale) {
  13302. locale = 'en';
  13303. }
  13304. if (! DataTable.ext.type.order[typeName]) {
  13305. DataTable.ext.type.detect.unshift(function (d) {
  13306. var dt = __mldObj(d, format, locale);
  13307. return d === '' || dt ? typeName : false;
  13308. });
  13309. DataTable.ext.type.order[typeName + '-pre'] = function (d) {
  13310. return __mldObj(d, format, locale) || 0;
  13311. }
  13312. }
  13313. }
  13314. /**
  13315. * Helpers for `columns.render`.
  13316. *
  13317. * The options defined here can be used with the `columns.render` initialisation
  13318. * option to provide a display renderer. The following functions are defined:
  13319. *
  13320. * * `number` - Will format numeric data (defined by `columns.data`) for
  13321. * display, retaining the original unformatted data for sorting and filtering.
  13322. * It takes 5 parameters:
  13323. * * `string` - Thousands grouping separator
  13324. * * `string` - Decimal point indicator
  13325. * * `integer` - Number of decimal points to show
  13326. * * `string` (optional) - Prefix.
  13327. * * `string` (optional) - Postfix (/suffix).
  13328. * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
  13329. * parameters.
  13330. *
  13331. * @example
  13332. * // Column definition using the number renderer
  13333. * {
  13334. * data: "salary",
  13335. * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
  13336. * }
  13337. *
  13338. * @namespace
  13339. */
  13340. DataTable.render = {
  13341. date: __mlHelper('toLocaleDateString'),
  13342. datetime: __mlHelper('toLocaleString'),
  13343. time: __mlHelper('toLocaleTimeString'),
  13344. number: function ( thousands, decimal, precision, prefix, postfix ) {
  13345. // Auto locale detection
  13346. if (thousands === null || thousands === undefined) {
  13347. thousands = __thousands;
  13348. }
  13349. if (decimal === null || decimal === undefined) {
  13350. decimal = __decimal;
  13351. }
  13352. return {
  13353. display: function ( d ) {
  13354. if ( typeof d !== 'number' && typeof d !== 'string' ) {
  13355. return d;
  13356. }
  13357. var negative = d < 0 ? '-' : '';
  13358. var flo = parseFloat( d );
  13359. // If NaN then there isn't much formatting that we can do - just
  13360. // return immediately, escaping any HTML (this was supposed to
  13361. // be a number after all)
  13362. if ( isNaN( flo ) ) {
  13363. return __htmlEscapeEntities( d );
  13364. }
  13365. flo = flo.toFixed( precision );
  13366. d = Math.abs( flo );
  13367. var intPart = parseInt( d, 10 );
  13368. var floatPart = precision ?
  13369. decimal+(d - intPart).toFixed( precision ).substring( 2 ):
  13370. '';
  13371. // If zero, then can't have a negative prefix
  13372. if (intPart === 0 && parseFloat(floatPart) === 0) {
  13373. negative = '';
  13374. }
  13375. return negative + (prefix||'') +
  13376. intPart.toString().replace(
  13377. /\B(?=(\d{3})+(?!\d))/g, thousands
  13378. ) +
  13379. floatPart +
  13380. (postfix||'');
  13381. }
  13382. };
  13383. },
  13384. text: function () {
  13385. return {
  13386. display: __htmlEscapeEntities,
  13387. filter: __htmlEscapeEntities
  13388. };
  13389. }
  13390. };
  13391. /*
  13392. * This is really a good bit rubbish this method of exposing the internal methods
  13393. * publicly... - To be fixed in 2.0 using methods on the prototype
  13394. */
  13395. /**
  13396. * Create a wrapper function for exporting an internal functions to an external API.
  13397. * @param {string} fn API function name
  13398. * @returns {function} wrapped function
  13399. * @memberof DataTable#internal
  13400. */
  13401. function _fnExternApiFunc (fn)
  13402. {
  13403. return function() {
  13404. var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
  13405. Array.prototype.slice.call(arguments)
  13406. );
  13407. return DataTable.ext.internal[fn].apply( this, args );
  13408. };
  13409. }
  13410. /**
  13411. * Reference to internal functions for use by plug-in developers. Note that
  13412. * these methods are references to internal functions and are considered to be
  13413. * private. If you use these methods, be aware that they are liable to change
  13414. * between versions.
  13415. * @namespace
  13416. */
  13417. $.extend( DataTable.ext.internal, {
  13418. _fnExternApiFunc: _fnExternApiFunc,
  13419. _fnBuildAjax: _fnBuildAjax,
  13420. _fnAjaxUpdate: _fnAjaxUpdate,
  13421. _fnAjaxParameters: _fnAjaxParameters,
  13422. _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
  13423. _fnAjaxDataSrc: _fnAjaxDataSrc,
  13424. _fnAddColumn: _fnAddColumn,
  13425. _fnColumnOptions: _fnColumnOptions,
  13426. _fnAdjustColumnSizing: _fnAdjustColumnSizing,
  13427. _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
  13428. _fnColumnIndexToVisible: _fnColumnIndexToVisible,
  13429. _fnVisbleColumns: _fnVisbleColumns,
  13430. _fnGetColumns: _fnGetColumns,
  13431. _fnColumnTypes: _fnColumnTypes,
  13432. _fnApplyColumnDefs: _fnApplyColumnDefs,
  13433. _fnHungarianMap: _fnHungarianMap,
  13434. _fnCamelToHungarian: _fnCamelToHungarian,
  13435. _fnLanguageCompat: _fnLanguageCompat,
  13436. _fnBrowserDetect: _fnBrowserDetect,
  13437. _fnAddData: _fnAddData,
  13438. _fnAddTr: _fnAddTr,
  13439. _fnNodeToDataIndex: _fnNodeToDataIndex,
  13440. _fnNodeToColumnIndex: _fnNodeToColumnIndex,
  13441. _fnGetCellData: _fnGetCellData,
  13442. _fnSetCellData: _fnSetCellData,
  13443. _fnSplitObjNotation: _fnSplitObjNotation,
  13444. _fnGetObjectDataFn: _fnGetObjectDataFn,
  13445. _fnSetObjectDataFn: _fnSetObjectDataFn,
  13446. _fnGetDataMaster: _fnGetDataMaster,
  13447. _fnClearTable: _fnClearTable,
  13448. _fnDeleteIndex: _fnDeleteIndex,
  13449. _fnInvalidate: _fnInvalidate,
  13450. _fnGetRowElements: _fnGetRowElements,
  13451. _fnCreateTr: _fnCreateTr,
  13452. _fnBuildHead: _fnBuildHead,
  13453. _fnDrawHead: _fnDrawHead,
  13454. _fnDraw: _fnDraw,
  13455. _fnReDraw: _fnReDraw,
  13456. _fnAddOptionsHtml: _fnAddOptionsHtml,
  13457. _fnDetectHeader: _fnDetectHeader,
  13458. _fnGetUniqueThs: _fnGetUniqueThs,
  13459. _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
  13460. _fnFilterComplete: _fnFilterComplete,
  13461. _fnFilterCustom: _fnFilterCustom,
  13462. _fnFilterColumn: _fnFilterColumn,
  13463. _fnFilter: _fnFilter,
  13464. _fnFilterCreateSearch: _fnFilterCreateSearch,
  13465. _fnEscapeRegex: _fnEscapeRegex,
  13466. _fnFilterData: _fnFilterData,
  13467. _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
  13468. _fnUpdateInfo: _fnUpdateInfo,
  13469. _fnInfoMacros: _fnInfoMacros,
  13470. _fnInitialise: _fnInitialise,
  13471. _fnInitComplete: _fnInitComplete,
  13472. _fnLengthChange: _fnLengthChange,
  13473. _fnFeatureHtmlLength: _fnFeatureHtmlLength,
  13474. _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
  13475. _fnPageChange: _fnPageChange,
  13476. _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
  13477. _fnProcessingDisplay: _fnProcessingDisplay,
  13478. _fnFeatureHtmlTable: _fnFeatureHtmlTable,
  13479. _fnScrollDraw: _fnScrollDraw,
  13480. _fnApplyToChildren: _fnApplyToChildren,
  13481. _fnCalculateColumnWidths: _fnCalculateColumnWidths,
  13482. _fnThrottle: _fnThrottle,
  13483. _fnConvertToWidth: _fnConvertToWidth,
  13484. _fnGetWidestNode: _fnGetWidestNode,
  13485. _fnGetMaxLenString: _fnGetMaxLenString,
  13486. _fnStringToCss: _fnStringToCss,
  13487. _fnSortFlatten: _fnSortFlatten,
  13488. _fnSort: _fnSort,
  13489. _fnSortAria: _fnSortAria,
  13490. _fnSortListener: _fnSortListener,
  13491. _fnSortAttachListener: _fnSortAttachListener,
  13492. _fnSortingClasses: _fnSortingClasses,
  13493. _fnSortData: _fnSortData,
  13494. _fnSaveState: _fnSaveState,
  13495. _fnLoadState: _fnLoadState,
  13496. _fnImplementState: _fnImplementState,
  13497. _fnSettingsFromNode: _fnSettingsFromNode,
  13498. _fnLog: _fnLog,
  13499. _fnMap: _fnMap,
  13500. _fnBindAction: _fnBindAction,
  13501. _fnCallbackReg: _fnCallbackReg,
  13502. _fnCallbackFire: _fnCallbackFire,
  13503. _fnLengthOverflow: _fnLengthOverflow,
  13504. _fnRenderer: _fnRenderer,
  13505. _fnDataSource: _fnDataSource,
  13506. _fnRowAttributes: _fnRowAttributes,
  13507. _fnExtend: _fnExtend,
  13508. _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
  13509. // in 1.10, so this dead-end function is
  13510. // added to prevent errors
  13511. } );
  13512. // jQuery access
  13513. $.fn.dataTable = DataTable;
  13514. // Provide access to the host jQuery object (circular reference)
  13515. DataTable.$ = $;
  13516. // Legacy aliases
  13517. $.fn.dataTableSettings = DataTable.settings;
  13518. $.fn.dataTableExt = DataTable.ext;
  13519. // With a capital `D` we return a DataTables API instance rather than a
  13520. // jQuery object
  13521. $.fn.DataTable = function ( opts ) {
  13522. return $(this).dataTable( opts ).api();
  13523. };
  13524. // All properties that are available to $.fn.dataTable should also be
  13525. // available on $.fn.DataTable
  13526. $.each( DataTable, function ( prop, val ) {
  13527. $.fn.DataTable[ prop ] = val;
  13528. } );
  13529. return DataTable;
  13530. }));
  13531. /*! DataTables Bootstrap 5 integration
  13532. * 2020 SpryMedia Ltd - datatables.net/license
  13533. */
  13534. /**
  13535. * DataTables integration for Bootstrap 4. This requires Bootstrap 5 and
  13536. * DataTables 1.10 or newer.
  13537. *
  13538. * This file sets the defaults and adds options to DataTables to style its
  13539. * controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
  13540. * for further information.
  13541. */
  13542. (function( factory ){
  13543. if ( typeof define === 'function' && define.amd ) {
  13544. // AMD
  13545. define( ['jquery', 'datatables.net'], function ( $ ) {
  13546. return factory( $, window, document );
  13547. } );
  13548. }
  13549. else if ( typeof exports === 'object' ) {
  13550. // CommonJS
  13551. module.exports = function (root, $) {
  13552. if ( ! root ) {
  13553. root = window;
  13554. }
  13555. if ( ! $ || ! $.fn.dataTable ) {
  13556. // Require DataTables, which attaches to jQuery, including
  13557. // jQuery if needed and have a $ property so we can access the
  13558. // jQuery object that is used
  13559. $ = require('datatables.net')(root, $).$;
  13560. }
  13561. return factory( $, root, root.document );
  13562. };
  13563. }
  13564. else {
  13565. // Browser
  13566. factory( jQuery, window, document );
  13567. }
  13568. }(function( $, window, document, undefined ) {
  13569. 'use strict';
  13570. var DataTable = $.fn.dataTable;
  13571. /* Set the defaults for DataTables initialisation */
  13572. $.extend( true, DataTable.defaults, {
  13573. dom:
  13574. "<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>>" +
  13575. "<'row'<'col-sm-12'tr>>" +
  13576. "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
  13577. renderer: 'bootstrap'
  13578. } );
  13579. /* Default class modification */
  13580. $.extend( DataTable.ext.classes, {
  13581. sWrapper: "dataTables_wrapper dt-bootstrap5",
  13582. sFilterInput: "form-control form-control-sm",
  13583. sLengthSelect: "form-select form-select-sm",
  13584. sProcessing: "dataTables_processing card",
  13585. sPageButton: "paginate_button page-item"
  13586. } );
  13587. /* Bootstrap paging button renderer */
  13588. DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
  13589. var api = new DataTable.Api( settings );
  13590. var classes = settings.oClasses;
  13591. var lang = settings.oLanguage.oPaginate;
  13592. var aria = settings.oLanguage.oAria.paginate || {};
  13593. var btnDisplay, btnClass, counter=0;
  13594. var attach = function( container, buttons ) {
  13595. var i, ien, node, button;
  13596. var clickHandler = function ( e ) {
  13597. e.preventDefault();
  13598. if ( !$(e.currentTarget).hasClass('disabled') && api.page() != e.data.action ) {
  13599. api.page( e.data.action ).draw( 'page' );
  13600. }
  13601. };
  13602. for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
  13603. button = buttons[i];
  13604. if ( Array.isArray( button ) ) {
  13605. attach( container, button );
  13606. }
  13607. else {
  13608. btnDisplay = '';
  13609. btnClass = '';
  13610. switch ( button ) {
  13611. case 'ellipsis':
  13612. btnDisplay = '&#x2026;';
  13613. btnClass = 'disabled';
  13614. break;
  13615. case 'first':
  13616. btnDisplay = lang.sFirst;
  13617. btnClass = button + (page > 0 ?
  13618. '' : ' disabled');
  13619. break;
  13620. case 'previous':
  13621. btnDisplay = lang.sPrevious;
  13622. btnClass = button + (page > 0 ?
  13623. '' : ' disabled');
  13624. break;
  13625. case 'next':
  13626. btnDisplay = lang.sNext;
  13627. btnClass = button + (page < pages-1 ?
  13628. '' : ' disabled');
  13629. break;
  13630. case 'last':
  13631. btnDisplay = lang.sLast;
  13632. btnClass = button + (page < pages-1 ?
  13633. '' : ' disabled');
  13634. break;
  13635. default:
  13636. btnDisplay = button + 1;
  13637. btnClass = page === button ?
  13638. 'active' : '';
  13639. break;
  13640. }
  13641. if ( btnDisplay ) {
  13642. node = $('<li>', {
  13643. 'class': classes.sPageButton+' '+btnClass,
  13644. 'id': idx === 0 && typeof button === 'string' ?
  13645. settings.sTableId +'_'+ button :
  13646. null
  13647. } )
  13648. .append( $('<a>', {
  13649. 'href': '#',
  13650. 'aria-controls': settings.sTableId,
  13651. 'aria-label': aria[ button ],
  13652. 'data-dt-idx': counter,
  13653. 'tabindex': settings.iTabIndex,
  13654. 'class': 'page-link'
  13655. } )
  13656. .html( btnDisplay )
  13657. )
  13658. .appendTo( container );
  13659. settings.oApi._fnBindAction(
  13660. node, {action: button}, clickHandler
  13661. );
  13662. counter++;
  13663. }
  13664. }
  13665. }
  13666. };
  13667. // IE9 throws an 'unknown error' if document.activeElement is used
  13668. // inside an iframe or frame.
  13669. var activeEl;
  13670. try {
  13671. // Because this approach is destroying and recreating the paging
  13672. // elements, focus is lost on the select button which is bad for
  13673. // accessibility. So we want to restore focus once the draw has
  13674. // completed
  13675. activeEl = $(host).find(document.activeElement).data('dt-idx');
  13676. }
  13677. catch (e) {}
  13678. attach(
  13679. $(host).empty().html('<ul class="pagination"/>').children('ul'),
  13680. buttons
  13681. );
  13682. if ( activeEl !== undefined ) {
  13683. $(host).find( '[data-dt-idx='+activeEl+']' ).trigger('focus');
  13684. }
  13685. };
  13686. return DataTable;
  13687. }));
  13688. /*! Responsive 2.3.0
  13689. * 2014-2022 SpryMedia Ltd - datatables.net/license
  13690. */
  13691. /**
  13692. * @summary Responsive
  13693. * @description Responsive tables plug-in for DataTables
  13694. * @version 2.3.0
  13695. * @author SpryMedia Ltd (www.sprymedia.co.uk)
  13696. * @contact www.sprymedia.co.uk/contact
  13697. * @copyright SpryMedia Ltd.
  13698. *
  13699. * This source file is free software, available under the following license:
  13700. * MIT license - http://datatables.net/license/mit
  13701. *
  13702. * This source file is distributed in the hope that it will be useful, but
  13703. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  13704. * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  13705. *
  13706. * For details please refer to: http://www.datatables.net
  13707. */
  13708. (function( factory ){
  13709. if ( typeof define === 'function' && define.amd ) {
  13710. // AMD
  13711. define( ['jquery', 'datatables.net'], function ( $ ) {
  13712. return factory( $, window, document );
  13713. } );
  13714. }
  13715. else if ( typeof exports === 'object' ) {
  13716. // CommonJS
  13717. module.exports = function (root, $) {
  13718. if ( ! root ) {
  13719. root = window;
  13720. }
  13721. if ( ! $ || ! $.fn.dataTable ) {
  13722. $ = require('datatables.net')(root, $).$;
  13723. }
  13724. return factory( $, root, root.document );
  13725. };
  13726. }
  13727. else {
  13728. // Browser
  13729. factory( jQuery, window, document );
  13730. }
  13731. }(function( $, window, document, undefined ) {
  13732. 'use strict';
  13733. var DataTable = $.fn.dataTable;
  13734. /**
  13735. * Responsive is a plug-in for the DataTables library that makes use of
  13736. * DataTables' ability to change the visibility of columns, changing the
  13737. * visibility of columns so the displayed columns fit into the table container.
  13738. * The end result is that complex tables will be dynamically adjusted to fit
  13739. * into the viewport, be it on a desktop, tablet or mobile browser.
  13740. *
  13741. * Responsive for DataTables has two modes of operation, which can used
  13742. * individually or combined:
  13743. *
  13744. * * Class name based control - columns assigned class names that match the
  13745. * breakpoint logic can be shown / hidden as required for each breakpoint.
  13746. * * Automatic control - columns are automatically hidden when there is no
  13747. * room left to display them. Columns removed from the right.
  13748. *
  13749. * In additional to column visibility control, Responsive also has built into
  13750. * options to use DataTables' child row display to show / hide the information
  13751. * from the table that has been hidden. There are also two modes of operation
  13752. * for this child row display:
  13753. *
  13754. * * Inline - when the control element that the user can use to show / hide
  13755. * child rows is displayed inside the first column of the table.
  13756. * * Column - where a whole column is dedicated to be the show / hide control.
  13757. *
  13758. * Initialisation of Responsive is performed by:
  13759. *
  13760. * * Adding the class `responsive` or `dt-responsive` to the table. In this case
  13761. * Responsive will automatically be initialised with the default configuration
  13762. * options when the DataTable is created.
  13763. * * Using the `responsive` option in the DataTables configuration options. This
  13764. * can also be used to specify the configuration options, or simply set to
  13765. * `true` to use the defaults.
  13766. *
  13767. * @class
  13768. * @param {object} settings DataTables settings object for the host table
  13769. * @param {object} [opts] Configuration options
  13770. * @requires jQuery 1.7+
  13771. * @requires DataTables 1.10.3+
  13772. *
  13773. * @example
  13774. * $('#example').DataTable( {
  13775. * responsive: true
  13776. * } );
  13777. * } );
  13778. */
  13779. var Responsive = function ( settings, opts ) {
  13780. // Sanity check that we are using DataTables 1.10 or newer
  13781. if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.10' ) ) {
  13782. throw 'DataTables Responsive requires DataTables 1.10.10 or newer';
  13783. }
  13784. this.s = {
  13785. dt: new DataTable.Api( settings ),
  13786. columns: [],
  13787. current: []
  13788. };
  13789. // Check if responsive has already been initialised on this table
  13790. if ( this.s.dt.settings()[0].responsive ) {
  13791. return;
  13792. }
  13793. // details is an object, but for simplicity the user can give it as a string
  13794. // or a boolean
  13795. if ( opts && typeof opts.details === 'string' ) {
  13796. opts.details = { type: opts.details };
  13797. }
  13798. else if ( opts && opts.details === false ) {
  13799. opts.details = { type: false };
  13800. }
  13801. else if ( opts && opts.details === true ) {
  13802. opts.details = { type: 'inline' };
  13803. }
  13804. this.c = $.extend( true, {}, Responsive.defaults, DataTable.defaults.responsive, opts );
  13805. settings.responsive = this;
  13806. this._constructor();
  13807. };
  13808. $.extend( Responsive.prototype, {
  13809. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  13810. * Constructor
  13811. */
  13812. /**
  13813. * Initialise the Responsive instance
  13814. *
  13815. * @private
  13816. */
  13817. _constructor: function ()
  13818. {
  13819. var that = this;
  13820. var dt = this.s.dt;
  13821. var dtPrivateSettings = dt.settings()[0];
  13822. var oldWindowWidth = $(window).innerWidth();
  13823. dt.settings()[0]._responsive = this;
  13824. // Use DataTables' throttle function to avoid processor thrashing on
  13825. // resize
  13826. $(window).on( 'resize.dtr orientationchange.dtr', DataTable.util.throttle( function () {
  13827. // iOS has a bug whereby resize can fire when only scrolling
  13828. // See: http://stackoverflow.com/questions/8898412
  13829. var width = $(window).innerWidth();
  13830. if ( width !== oldWindowWidth ) {
  13831. that._resize();
  13832. oldWindowWidth = width;
  13833. }
  13834. } ) );
  13835. // DataTables doesn't currently trigger an event when a row is added, so
  13836. // we need to hook into its private API to enforce the hidden rows when
  13837. // new data is added
  13838. dtPrivateSettings.oApi._fnCallbackReg( dtPrivateSettings, 'aoRowCreatedCallback', function (tr, data, idx) {
  13839. if ( $.inArray( false, that.s.current ) !== -1 ) {
  13840. $('>td, >th', tr).each( function ( i ) {
  13841. var idx = dt.column.index( 'toData', i );
  13842. if ( that.s.current[idx] === false ) {
  13843. $(this).css('display', 'none');
  13844. }
  13845. } );
  13846. }
  13847. } );
  13848. // Destroy event handler
  13849. dt.on( 'destroy.dtr', function () {
  13850. dt.off( '.dtr' );
  13851. $( dt.table().body() ).off( '.dtr' );
  13852. $(window).off( 'resize.dtr orientationchange.dtr' );
  13853. dt.cells('.dtr-control').nodes().to$().removeClass('dtr-control');
  13854. // Restore the columns that we've hidden
  13855. $.each( that.s.current, function ( i, val ) {
  13856. if ( val === false ) {
  13857. that._setColumnVis( i, true );
  13858. }
  13859. } );
  13860. } );
  13861. // Reorder the breakpoints array here in case they have been added out
  13862. // of order
  13863. this.c.breakpoints.sort( function (a, b) {
  13864. return a.width < b.width ? 1 :
  13865. a.width > b.width ? -1 : 0;
  13866. } );
  13867. this._classLogic();
  13868. this._resizeAuto();
  13869. // Details handler
  13870. var details = this.c.details;
  13871. if ( details.type !== false ) {
  13872. that._detailsInit();
  13873. // DataTables will trigger this event on every column it shows and
  13874. // hides individually
  13875. dt.on( 'column-visibility.dtr', function () {
  13876. // Use a small debounce to allow multiple columns to be set together
  13877. if ( that._timer ) {
  13878. clearTimeout( that._timer );
  13879. }
  13880. that._timer = setTimeout( function () {
  13881. that._timer = null;
  13882. that._classLogic();
  13883. that._resizeAuto();
  13884. that._resize(true);
  13885. that._redrawChildren();
  13886. }, 100 );
  13887. } );
  13888. // Redraw the details box on each draw which will happen if the data
  13889. // has changed. This is used until DataTables implements a native
  13890. // `updated` event for rows
  13891. dt.on( 'draw.dtr', function () {
  13892. that._redrawChildren();
  13893. } );
  13894. $(dt.table().node()).addClass( 'dtr-'+details.type );
  13895. }
  13896. dt.on( 'column-reorder.dtr', function (e, settings, details) {
  13897. that._classLogic();
  13898. that._resizeAuto();
  13899. that._resize(true);
  13900. } );
  13901. // Change in column sizes means we need to calc
  13902. dt.on( 'column-sizing.dtr', function () {
  13903. that._resizeAuto();
  13904. that._resize();
  13905. });
  13906. // DT2 let's us tell it if we are hiding columns
  13907. dt.on( 'column-calc.dt', function (e, d) {
  13908. var curr = that.s.current;
  13909. for (var i=0 ; i<curr.length ; i++) {
  13910. var idx = d.visible.indexOf(i);
  13911. if (curr[i] === false && idx >= 0) {
  13912. d.visible.splice(idx, 1);
  13913. }
  13914. }
  13915. } );
  13916. // On Ajax reload we want to reopen any child rows which are displayed
  13917. // by responsive
  13918. dt.on( 'preXhr.dtr', function () {
  13919. var rowIds = [];
  13920. dt.rows().every( function () {
  13921. if ( this.child.isShown() ) {
  13922. rowIds.push( this.id(true) );
  13923. }
  13924. } );
  13925. dt.one( 'draw.dtr', function () {
  13926. that._resizeAuto();
  13927. that._resize();
  13928. dt.rows( rowIds ).every( function () {
  13929. that._detailsDisplay( this, false );
  13930. } );
  13931. } );
  13932. });
  13933. dt
  13934. .on( 'draw.dtr', function () {
  13935. that._controlClass();
  13936. })
  13937. .on( 'init.dtr', function (e, settings, details) {
  13938. if ( e.namespace !== 'dt' ) {
  13939. return;
  13940. }
  13941. that._resizeAuto();
  13942. that._resize();
  13943. // If columns were hidden, then DataTables needs to adjust the
  13944. // column sizing
  13945. if ( $.inArray( false, that.s.current ) ) {
  13946. dt.columns.adjust();
  13947. }
  13948. } );
  13949. // First pass - draw the table for the current viewport size
  13950. this._resize();
  13951. },
  13952. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  13953. * Private methods
  13954. */
  13955. /**
  13956. * Calculate the visibility for the columns in a table for a given
  13957. * breakpoint. The result is pre-determined based on the class logic if
  13958. * class names are used to control all columns, but the width of the table
  13959. * is also used if there are columns which are to be automatically shown
  13960. * and hidden.
  13961. *
  13962. * @param {string} breakpoint Breakpoint name to use for the calculation
  13963. * @return {array} Array of boolean values initiating the visibility of each
  13964. * column.
  13965. * @private
  13966. */
  13967. _columnsVisiblity: function ( breakpoint )
  13968. {
  13969. var dt = this.s.dt;
  13970. var columns = this.s.columns;
  13971. var i, ien;
  13972. // Create an array that defines the column ordering based first on the
  13973. // column's priority, and secondly the column index. This allows the
  13974. // columns to be removed from the right if the priority matches
  13975. var order = columns
  13976. .map( function ( col, idx ) {
  13977. return {
  13978. columnIdx: idx,
  13979. priority: col.priority
  13980. };
  13981. } )
  13982. .sort( function ( a, b ) {
  13983. if ( a.priority !== b.priority ) {
  13984. return a.priority - b.priority;
  13985. }
  13986. return a.columnIdx - b.columnIdx;
  13987. } );
  13988. // Class logic - determine which columns are in this breakpoint based
  13989. // on the classes. If no class control (i.e. `auto`) then `-` is used
  13990. // to indicate this to the rest of the function
  13991. var display = $.map( columns, function ( col, i ) {
  13992. if ( dt.column(i).visible() === false ) {
  13993. return 'not-visible';
  13994. }
  13995. return col.auto && col.minWidth === null ?
  13996. false :
  13997. col.auto === true ?
  13998. '-' :
  13999. $.inArray( breakpoint, col.includeIn ) !== -1;
  14000. } );
  14001. // Auto column control - first pass: how much width is taken by the
  14002. // ones that must be included from the non-auto columns
  14003. var requiredWidth = 0;
  14004. for ( i=0, ien=display.length ; i<ien ; i++ ) {
  14005. if ( display[i] === true ) {
  14006. requiredWidth += columns[i].minWidth;
  14007. }
  14008. }
  14009. // Second pass, use up any remaining width for other columns. For
  14010. // scrolling tables we need to subtract the width of the scrollbar. It
  14011. // may not be requires which makes this sub-optimal, but it would
  14012. // require another full redraw to make complete use of those extra few
  14013. // pixels
  14014. var scrolling = dt.settings()[0].oScroll;
  14015. var bar = scrolling.sY || scrolling.sX ? scrolling.iBarWidth : 0;
  14016. var widthAvailable = dt.table().container().offsetWidth - bar;
  14017. var usedWidth = widthAvailable - requiredWidth;
  14018. // Control column needs to always be included. This makes it sub-
  14019. // optimal in terms of using the available with, but to stop layout
  14020. // thrashing or overflow. Also we need to account for the control column
  14021. // width first so we know how much width is available for the other
  14022. // columns, since the control column might not be the first one shown
  14023. for ( i=0, ien=display.length ; i<ien ; i++ ) {
  14024. if ( columns[i].control ) {
  14025. usedWidth -= columns[i].minWidth;
  14026. }
  14027. }
  14028. // Allow columns to be shown (counting by priority and then right to
  14029. // left) until we run out of room
  14030. var empty = false;
  14031. for ( i=0, ien=order.length ; i<ien ; i++ ) {
  14032. var colIdx = order[i].columnIdx;
  14033. if ( display[colIdx] === '-' && ! columns[colIdx].control && columns[colIdx].minWidth ) {
  14034. // Once we've found a column that won't fit we don't let any
  14035. // others display either, or columns might disappear in the
  14036. // middle of the table
  14037. if ( empty || usedWidth - columns[colIdx].minWidth < 0 ) {
  14038. empty = true;
  14039. display[colIdx] = false;
  14040. }
  14041. else {
  14042. display[colIdx] = true;
  14043. }
  14044. usedWidth -= columns[colIdx].minWidth;
  14045. }
  14046. }
  14047. // Determine if the 'control' column should be shown (if there is one).
  14048. // This is the case when there is a hidden column (that is not the
  14049. // control column). The two loops look inefficient here, but they are
  14050. // trivial and will fly through. We need to know the outcome from the
  14051. // first , before the action in the second can be taken
  14052. var showControl = false;
  14053. for ( i=0, ien=columns.length ; i<ien ; i++ ) {
  14054. if ( ! columns[i].control && ! columns[i].never && display[i] === false ) {
  14055. showControl = true;
  14056. break;
  14057. }
  14058. }
  14059. for ( i=0, ien=columns.length ; i<ien ; i++ ) {
  14060. if ( columns[i].control ) {
  14061. display[i] = showControl;
  14062. }
  14063. // Replace not visible string with false from the control column detection above
  14064. if ( display[i] === 'not-visible' ) {
  14065. display[i] = false;
  14066. }
  14067. }
  14068. // Finally we need to make sure that there is at least one column that
  14069. // is visible
  14070. if ( $.inArray( true, display ) === -1 ) {
  14071. display[0] = true;
  14072. }
  14073. return display;
  14074. },
  14075. /**
  14076. * Create the internal `columns` array with information about the columns
  14077. * for the table. This includes determining which breakpoints the column
  14078. * will appear in, based upon class names in the column, which makes up the
  14079. * vast majority of this method.
  14080. *
  14081. * @private
  14082. */
  14083. _classLogic: function ()
  14084. {
  14085. var that = this;
  14086. var calc = {};
  14087. var breakpoints = this.c.breakpoints;
  14088. var dt = this.s.dt;
  14089. var columns = dt.columns().eq(0).map( function (i) {
  14090. var column = this.column(i);
  14091. var className = column.header().className;
  14092. var priority = dt.settings()[0].aoColumns[i].responsivePriority;
  14093. var dataPriority = column.header().getAttribute('data-priority');
  14094. if ( priority === undefined ) {
  14095. priority = dataPriority === undefined || dataPriority === null?
  14096. 10000 :
  14097. dataPriority * 1;
  14098. }
  14099. return {
  14100. className: className,
  14101. includeIn: [],
  14102. auto: false,
  14103. control: false,
  14104. never: className.match(/\b(dtr\-)?never\b/) ? true : false,
  14105. priority: priority
  14106. };
  14107. } );
  14108. // Simply add a breakpoint to `includeIn` array, ensuring that there are
  14109. // no duplicates
  14110. var add = function ( colIdx, name ) {
  14111. var includeIn = columns[ colIdx ].includeIn;
  14112. if ( $.inArray( name, includeIn ) === -1 ) {
  14113. includeIn.push( name );
  14114. }
  14115. };
  14116. var column = function ( colIdx, name, operator, matched ) {
  14117. var size, i, ien;
  14118. if ( ! operator ) {
  14119. columns[ colIdx ].includeIn.push( name );
  14120. }
  14121. else if ( operator === 'max-' ) {
  14122. // Add this breakpoint and all smaller
  14123. size = that._find( name ).width;
  14124. for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
  14125. if ( breakpoints[i].width <= size ) {
  14126. add( colIdx, breakpoints[i].name );
  14127. }
  14128. }
  14129. }
  14130. else if ( operator === 'min-' ) {
  14131. // Add this breakpoint and all larger
  14132. size = that._find( name ).width;
  14133. for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
  14134. if ( breakpoints[i].width >= size ) {
  14135. add( colIdx, breakpoints[i].name );
  14136. }
  14137. }
  14138. }
  14139. else if ( operator === 'not-' ) {
  14140. // Add all but this breakpoint
  14141. for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
  14142. if ( breakpoints[i].name.indexOf( matched ) === -1 ) {
  14143. add( colIdx, breakpoints[i].name );
  14144. }
  14145. }
  14146. }
  14147. };
  14148. // Loop over each column and determine if it has a responsive control
  14149. // class
  14150. columns.each( function ( col, i ) {
  14151. var classNames = col.className.split(' ');
  14152. var hasClass = false;
  14153. // Split the class name up so multiple rules can be applied if needed
  14154. for ( var k=0, ken=classNames.length ; k<ken ; k++ ) {
  14155. var className = classNames[k].trim();
  14156. if ( className === 'all' || className === 'dtr-all' ) {
  14157. // Include in all
  14158. hasClass = true;
  14159. col.includeIn = $.map( breakpoints, function (a) {
  14160. return a.name;
  14161. } );
  14162. return;
  14163. }
  14164. else if ( className === 'none' || className === 'dtr-none' || col.never ) {
  14165. // Include in none (default) and no auto
  14166. hasClass = true;
  14167. return;
  14168. }
  14169. else if ( className === 'control' || className === 'dtr-control' ) {
  14170. // Special column that is only visible, when one of the other
  14171. // columns is hidden. This is used for the details control
  14172. hasClass = true;
  14173. col.control = true;
  14174. return;
  14175. }
  14176. $.each( breakpoints, function ( j, breakpoint ) {
  14177. // Does this column have a class that matches this breakpoint?
  14178. var brokenPoint = breakpoint.name.split('-');
  14179. var re = new RegExp( '(min\\-|max\\-|not\\-)?('+brokenPoint[0]+')(\\-[_a-zA-Z0-9])?' );
  14180. var match = className.match( re );
  14181. if ( match ) {
  14182. hasClass = true;
  14183. if ( match[2] === brokenPoint[0] && match[3] === '-'+brokenPoint[1] ) {
  14184. // Class name matches breakpoint name fully
  14185. column( i, breakpoint.name, match[1], match[2]+match[3] );
  14186. }
  14187. else if ( match[2] === brokenPoint[0] && ! match[3] ) {
  14188. // Class name matched primary breakpoint name with no qualifier
  14189. column( i, breakpoint.name, match[1], match[2] );
  14190. }
  14191. }
  14192. } );
  14193. }
  14194. // If there was no control class, then automatic sizing is used
  14195. if ( ! hasClass ) {
  14196. col.auto = true;
  14197. }
  14198. } );
  14199. this.s.columns = columns;
  14200. },
  14201. /**
  14202. * Update the cells to show the correct control class / button
  14203. * @private
  14204. */
  14205. _controlClass: function ()
  14206. {
  14207. if ( this.c.details.type === 'inline' ) {
  14208. var dt = this.s.dt;
  14209. var columnsVis = this.s.current;
  14210. var firstVisible = $.inArray(true, columnsVis);
  14211. // Remove from any cells which shouldn't have it
  14212. dt.cells(
  14213. null,
  14214. function(idx) {
  14215. return idx !== firstVisible;
  14216. },
  14217. {page: 'current'}
  14218. )
  14219. .nodes()
  14220. .to$()
  14221. .filter('.dtr-control')
  14222. .removeClass('dtr-control');
  14223. dt.cells(null, firstVisible, {page: 'current'})
  14224. .nodes()
  14225. .to$()
  14226. .addClass('dtr-control');
  14227. }
  14228. },
  14229. /**
  14230. * Show the details for the child row
  14231. *
  14232. * @param {DataTables.Api} row API instance for the row
  14233. * @param {boolean} update Update flag
  14234. * @private
  14235. */
  14236. _detailsDisplay: function ( row, update )
  14237. {
  14238. var that = this;
  14239. var dt = this.s.dt;
  14240. var details = this.c.details;
  14241. if ( details && details.type !== false ) {
  14242. var renderer = typeof details.renderer === 'string'
  14243. ? Responsive.renderer[details.renderer]()
  14244. : details.renderer;
  14245. var res = details.display( row, update, function () {
  14246. return renderer(
  14247. dt, row[0], that._detailsObj(row[0])
  14248. );
  14249. } );
  14250. if ( res === true || res === false ) {
  14251. $(dt.table().node()).triggerHandler( 'responsive-display.dt', [dt, row, res, update] );
  14252. }
  14253. }
  14254. },
  14255. /**
  14256. * Initialisation for the details handler
  14257. *
  14258. * @private
  14259. */
  14260. _detailsInit: function ()
  14261. {
  14262. var that = this;
  14263. var dt = this.s.dt;
  14264. var details = this.c.details;
  14265. // The inline type always uses the first child as the target
  14266. if ( details.type === 'inline' ) {
  14267. details.target = 'td.dtr-control, th.dtr-control';
  14268. }
  14269. // Keyboard accessibility
  14270. dt.on( 'draw.dtr', function () {
  14271. that._tabIndexes();
  14272. } );
  14273. that._tabIndexes(); // Initial draw has already happened
  14274. $( dt.table().body() ).on( 'keyup.dtr', 'td, th', function (e) {
  14275. if ( e.keyCode === 13 && $(this).data('dtr-keyboard') ) {
  14276. $(this).click();
  14277. }
  14278. } );
  14279. // type.target can be a string jQuery selector or a column index
  14280. var target = details.target;
  14281. var selector = typeof target === 'string' ? target : 'td, th';
  14282. if ( target !== undefined || target !== null ) {
  14283. // Click handler to show / hide the details rows when they are available
  14284. $( dt.table().body() )
  14285. .on( 'click.dtr mousedown.dtr mouseup.dtr', selector, function (e) {
  14286. // If the table is not collapsed (i.e. there is no hidden columns)
  14287. // then take no action
  14288. if ( ! $(dt.table().node()).hasClass('collapsed' ) ) {
  14289. return;
  14290. }
  14291. // Check that the row is actually a DataTable's controlled node
  14292. if ( $.inArray( $(this).closest('tr').get(0), dt.rows().nodes().toArray() ) === -1 ) {
  14293. return;
  14294. }
  14295. // For column index, we determine if we should act or not in the
  14296. // handler - otherwise it is already okay
  14297. if ( typeof target === 'number' ) {
  14298. var targetIdx = target < 0 ?
  14299. dt.columns().eq(0).length + target :
  14300. target;
  14301. if ( dt.cell( this ).index().column !== targetIdx ) {
  14302. return;
  14303. }
  14304. }
  14305. // $().closest() includes itself in its check
  14306. var row = dt.row( $(this).closest('tr') );
  14307. // Check event type to do an action
  14308. if ( e.type === 'click' ) {
  14309. // The renderer is given as a function so the caller can execute it
  14310. // only when they need (i.e. if hiding there is no point is running
  14311. // the renderer)
  14312. that._detailsDisplay( row, false );
  14313. }
  14314. else if ( e.type === 'mousedown' ) {
  14315. // For mouse users, prevent the focus ring from showing
  14316. $(this).css('outline', 'none');
  14317. }
  14318. else if ( e.type === 'mouseup' ) {
  14319. // And then re-allow at the end of the click
  14320. $(this).trigger('blur').css('outline', '');
  14321. }
  14322. } );
  14323. }
  14324. },
  14325. /**
  14326. * Get the details to pass to a renderer for a row
  14327. * @param {int} rowIdx Row index
  14328. * @private
  14329. */
  14330. _detailsObj: function ( rowIdx )
  14331. {
  14332. var that = this;
  14333. var dt = this.s.dt;
  14334. return $.map( this.s.columns, function( col, i ) {
  14335. // Never and control columns should not be passed to the renderer
  14336. if ( col.never || col.control ) {
  14337. return;
  14338. }
  14339. var dtCol = dt.settings()[0].aoColumns[ i ];
  14340. return {
  14341. className: dtCol.sClass,
  14342. columnIndex: i,
  14343. data: dt.cell( rowIdx, i ).render( that.c.orthogonal ),
  14344. hidden: dt.column( i ).visible() && !that.s.current[ i ],
  14345. rowIndex: rowIdx,
  14346. title: dtCol.sTitle !== null ?
  14347. dtCol.sTitle :
  14348. $(dt.column(i).header()).text()
  14349. };
  14350. } );
  14351. },
  14352. /**
  14353. * Find a breakpoint object from a name
  14354. *
  14355. * @param {string} name Breakpoint name to find
  14356. * @return {object} Breakpoint description object
  14357. * @private
  14358. */
  14359. _find: function ( name )
  14360. {
  14361. var breakpoints = this.c.breakpoints;
  14362. for ( var i=0, ien=breakpoints.length ; i<ien ; i++ ) {
  14363. if ( breakpoints[i].name === name ) {
  14364. return breakpoints[i];
  14365. }
  14366. }
  14367. },
  14368. /**
  14369. * Re-create the contents of the child rows as the display has changed in
  14370. * some way.
  14371. *
  14372. * @private
  14373. */
  14374. _redrawChildren: function ()
  14375. {
  14376. var that = this;
  14377. var dt = this.s.dt;
  14378. dt.rows( {page: 'current'} ).iterator( 'row', function ( settings, idx ) {
  14379. var row = dt.row( idx );
  14380. that._detailsDisplay( dt.row( idx ), true );
  14381. } );
  14382. },
  14383. /**
  14384. * Alter the table display for a resized viewport. This involves first
  14385. * determining what breakpoint the window currently is in, getting the
  14386. * column visibilities to apply and then setting them.
  14387. *
  14388. * @param {boolean} forceRedraw Force a redraw
  14389. * @private
  14390. */
  14391. _resize: function (forceRedraw)
  14392. {
  14393. var that = this;
  14394. var dt = this.s.dt;
  14395. var width = $(window).innerWidth();
  14396. var breakpoints = this.c.breakpoints;
  14397. var breakpoint = breakpoints[0].name;
  14398. var columns = this.s.columns;
  14399. var i, ien;
  14400. var oldVis = this.s.current.slice();
  14401. // Determine what breakpoint we are currently at
  14402. for ( i=breakpoints.length-1 ; i>=0 ; i-- ) {
  14403. if ( width <= breakpoints[i].width ) {
  14404. breakpoint = breakpoints[i].name;
  14405. break;
  14406. }
  14407. }
  14408. // Show the columns for that break point
  14409. var columnsVis = this._columnsVisiblity( breakpoint );
  14410. this.s.current = columnsVis;
  14411. // Set the class before the column visibility is changed so event
  14412. // listeners know what the state is. Need to determine if there are
  14413. // any columns that are not visible but can be shown
  14414. var collapsedClass = false;
  14415. for ( i=0, ien=columns.length ; i<ien ; i++ ) {
  14416. if ( columnsVis[i] === false && ! columns[i].never && ! columns[i].control && ! dt.column(i).visible() === false ) {
  14417. collapsedClass = true;
  14418. break;
  14419. }
  14420. }
  14421. $( dt.table().node() ).toggleClass( 'collapsed', collapsedClass );
  14422. var changed = false;
  14423. var visible = 0;
  14424. dt.columns().eq(0).each( function ( colIdx, i ) {
  14425. if ( columnsVis[i] === true ) {
  14426. visible++;
  14427. }
  14428. if ( forceRedraw || columnsVis[i] !== oldVis[i] ) {
  14429. changed = true;
  14430. that._setColumnVis( colIdx, columnsVis[i] );
  14431. }
  14432. } );
  14433. if ( changed ) {
  14434. this._redrawChildren();
  14435. // Inform listeners of the change
  14436. $(dt.table().node()).trigger( 'responsive-resize.dt', [dt, this.s.current] );
  14437. // If no records, update the "No records" display element
  14438. if ( dt.page.info().recordsDisplay === 0 ) {
  14439. $('td', dt.table().body()).eq(0).attr('colspan', visible);
  14440. }
  14441. }
  14442. that._controlClass();
  14443. },
  14444. /**
  14445. * Determine the width of each column in the table so the auto column hiding
  14446. * has that information to work with. This method is never going to be 100%
  14447. * perfect since column widths can change slightly per page, but without
  14448. * seriously compromising performance this is quite effective.
  14449. *
  14450. * @private
  14451. */
  14452. _resizeAuto: function ()
  14453. {
  14454. var dt = this.s.dt;
  14455. var columns = this.s.columns;
  14456. // Are we allowed to do auto sizing?
  14457. if ( ! this.c.auto ) {
  14458. return;
  14459. }
  14460. // Are there any columns that actually need auto-sizing, or do they all
  14461. // have classes defined
  14462. if ( $.inArray( true, $.map( columns, function (c) { return c.auto; } ) ) === -1 ) {
  14463. return;
  14464. }
  14465. // Need to restore all children. They will be reinstated by a re-render
  14466. if ( ! $.isEmptyObject( _childNodeStore ) ) {
  14467. $.each( _childNodeStore, function ( key ) {
  14468. var idx = key.split('-');
  14469. _childNodesRestore( dt, idx[0]*1, idx[1]*1 );
  14470. } );
  14471. }
  14472. // Clone the table with the current data in it
  14473. var tableWidth = dt.table().node().offsetWidth;
  14474. var columnWidths = dt.columns;
  14475. var clonedTable = dt.table().node().cloneNode( false );
  14476. var clonedHeader = $( dt.table().header().cloneNode( false ) ).appendTo( clonedTable );
  14477. var clonedBody = $( dt.table().body() ).clone( false, false ).empty().appendTo( clonedTable ); // use jQuery because of IE8
  14478. clonedTable.style.width = 'auto';
  14479. // Header
  14480. var headerCells = dt.columns()
  14481. .header()
  14482. .filter( function (idx) {
  14483. return dt.column(idx).visible();
  14484. } )
  14485. .to$()
  14486. .clone( false )
  14487. .css( 'display', 'table-cell' )
  14488. .css( 'width', 'auto' )
  14489. .css( 'min-width', 0 );
  14490. // Body rows - we don't need to take account of DataTables' column
  14491. // visibility since we implement our own here (hence the `display` set)
  14492. $(clonedBody)
  14493. .append( $(dt.rows( { page: 'current' } ).nodes()).clone( false ) )
  14494. .find( 'th, td' ).css( 'display', '' );
  14495. // Footer
  14496. var footer = dt.table().footer();
  14497. if ( footer ) {
  14498. var clonedFooter = $( footer.cloneNode( false ) ).appendTo( clonedTable );
  14499. var footerCells = dt.columns()
  14500. .footer()
  14501. .filter( function (idx) {
  14502. return dt.column(idx).visible();
  14503. } )
  14504. .to$()
  14505. .clone( false )
  14506. .css( 'display', 'table-cell' );
  14507. $('<tr/>')
  14508. .append( footerCells )
  14509. .appendTo( clonedFooter );
  14510. }
  14511. $('<tr/>')
  14512. .append( headerCells )
  14513. .appendTo( clonedHeader );
  14514. // In the inline case extra padding is applied to the first column to
  14515. // give space for the show / hide icon. We need to use this in the
  14516. // calculation
  14517. if ( this.c.details.type === 'inline' ) {
  14518. $(clonedTable).addClass( 'dtr-inline collapsed' );
  14519. }
  14520. // It is unsafe to insert elements with the same name into the DOM
  14521. // multiple times. For example, cloning and inserting a checked radio
  14522. // clears the chcecked state of the original radio.
  14523. $( clonedTable ).find( '[name]' ).removeAttr( 'name' );
  14524. // A position absolute table would take the table out of the flow of
  14525. // our container element, bypassing the height and width (Scroller)
  14526. $( clonedTable ).css( 'position', 'relative' )
  14527. var inserted = $('<div/>')
  14528. .css( {
  14529. width: 1,
  14530. height: 1,
  14531. overflow: 'hidden',
  14532. clear: 'both'
  14533. } )
  14534. .append( clonedTable );
  14535. inserted.insertBefore( dt.table().node() );
  14536. // The cloned header now contains the smallest that each column can be
  14537. headerCells.each( function (i) {
  14538. var idx = dt.column.index( 'fromVisible', i );
  14539. columns[ idx ].minWidth = this.offsetWidth || 0;
  14540. } );
  14541. inserted.remove();
  14542. },
  14543. /**
  14544. * Get the state of the current hidden columns - controlled by Responsive only
  14545. */
  14546. _responsiveOnlyHidden: function ()
  14547. {
  14548. var dt = this.s.dt;
  14549. return $.map( this.s.current, function (v, i) {
  14550. // If the column is hidden by DataTables then it can't be hidden by
  14551. // Responsive!
  14552. if ( dt.column(i).visible() === false ) {
  14553. return true;
  14554. }
  14555. return v;
  14556. } );
  14557. },
  14558. /**
  14559. * Set a column's visibility.
  14560. *
  14561. * We don't use DataTables' column visibility controls in order to ensure
  14562. * that column visibility can Responsive can no-exist. Since only IE8+ is
  14563. * supported (and all evergreen browsers of course) the control of the
  14564. * display attribute works well.
  14565. *
  14566. * @param {integer} col Column index
  14567. * @param {boolean} showHide Show or hide (true or false)
  14568. * @private
  14569. */
  14570. _setColumnVis: function ( col, showHide )
  14571. {
  14572. var dt = this.s.dt;
  14573. var display = showHide ? '' : 'none'; // empty string will remove the attr
  14574. $( dt.column( col ).header() )
  14575. .css( 'display', display )
  14576. .toggleClass('dtr-hidden', !showHide);
  14577. $( dt.column( col ).footer() )
  14578. .css( 'display', display )
  14579. .toggleClass('dtr-hidden', !showHide);
  14580. dt.column( col ).nodes().to$()
  14581. .css( 'display', display )
  14582. .toggleClass('dtr-hidden', !showHide);
  14583. // If the are child nodes stored, we might need to reinsert them
  14584. if ( ! $.isEmptyObject( _childNodeStore ) ) {
  14585. dt.cells( null, col ).indexes().each( function (idx) {
  14586. _childNodesRestore( dt, idx.row, idx.column );
  14587. } );
  14588. }
  14589. },
  14590. /**
  14591. * Update the cell tab indexes for keyboard accessibility. This is called on
  14592. * every table draw - that is potentially inefficient, but also the least
  14593. * complex option given that column visibility can change on the fly. Its a
  14594. * shame user-focus was removed from CSS 3 UI, as it would have solved this
  14595. * issue with a single CSS statement.
  14596. *
  14597. * @private
  14598. */
  14599. _tabIndexes: function ()
  14600. {
  14601. var dt = this.s.dt;
  14602. var cells = dt.cells( { page: 'current' } ).nodes().to$();
  14603. var ctx = dt.settings()[0];
  14604. var target = this.c.details.target;
  14605. cells.filter( '[data-dtr-keyboard]' ).removeData( '[data-dtr-keyboard]' );
  14606. if ( typeof target === 'number' ) {
  14607. dt.cells( null, target, { page: 'current' } ).nodes().to$()
  14608. .attr( 'tabIndex', ctx.iTabIndex )
  14609. .data( 'dtr-keyboard', 1 );
  14610. }
  14611. else {
  14612. // This is a bit of a hack - we need to limit the selected nodes to just
  14613. // those of this table
  14614. if ( target === 'td:first-child, th:first-child' ) {
  14615. target = '>td:first-child, >th:first-child';
  14616. }
  14617. $( target, dt.rows( { page: 'current' } ).nodes() )
  14618. .attr( 'tabIndex', ctx.iTabIndex )
  14619. .data( 'dtr-keyboard', 1 );
  14620. }
  14621. }
  14622. } );
  14623. /**
  14624. * List of default breakpoints. Each item in the array is an object with two
  14625. * properties:
  14626. *
  14627. * * `name` - the breakpoint name.
  14628. * * `width` - the breakpoint width
  14629. *
  14630. * @name Responsive.breakpoints
  14631. * @static
  14632. */
  14633. Responsive.breakpoints = [
  14634. { name: 'desktop', width: Infinity },
  14635. { name: 'tablet-l', width: 1024 },
  14636. { name: 'tablet-p', width: 768 },
  14637. { name: 'mobile-l', width: 480 },
  14638. { name: 'mobile-p', width: 320 }
  14639. ];
  14640. /**
  14641. * Display methods - functions which define how the hidden data should be shown
  14642. * in the table.
  14643. *
  14644. * @namespace
  14645. * @name Responsive.defaults
  14646. * @static
  14647. */
  14648. Responsive.display = {
  14649. childRow: function ( row, update, render ) {
  14650. if ( update ) {
  14651. if ( $(row.node()).hasClass('parent') ) {
  14652. row.child( render(), 'child' ).show();
  14653. return true;
  14654. }
  14655. }
  14656. else {
  14657. if ( ! row.child.isShown() ) {
  14658. row.child( render(), 'child' ).show();
  14659. $( row.node() ).addClass( 'parent' );
  14660. return true;
  14661. }
  14662. else {
  14663. row.child( false );
  14664. $( row.node() ).removeClass( 'parent' );
  14665. return false;
  14666. }
  14667. }
  14668. },
  14669. childRowImmediate: function ( row, update, render ) {
  14670. if ( (! update && row.child.isShown()) || ! row.responsive.hasHidden() ) {
  14671. // User interaction and the row is show, or nothing to show
  14672. row.child( false );
  14673. $( row.node() ).removeClass( 'parent' );
  14674. return false;
  14675. }
  14676. else {
  14677. // Display
  14678. row.child( render(), 'child' ).show();
  14679. $( row.node() ).addClass( 'parent' );
  14680. return true;
  14681. }
  14682. },
  14683. // This is a wrapper so the modal options for Bootstrap and jQuery UI can
  14684. // have options passed into them. This specific one doesn't need to be a
  14685. // function but it is for consistency in the `modal` name
  14686. modal: function ( options ) {
  14687. return function ( row, update, render ) {
  14688. if ( ! update ) {
  14689. // Show a modal
  14690. var close = function () {
  14691. modal.remove(); // will tidy events for us
  14692. $(document).off( 'keypress.dtr' );
  14693. };
  14694. var modal = $('<div class="dtr-modal"/>')
  14695. .append( $('<div class="dtr-modal-display"/>')
  14696. .append( $('<div class="dtr-modal-content"/>')
  14697. .append( render() )
  14698. )
  14699. .append( $('<div class="dtr-modal-close">&times;</div>' )
  14700. .click( function () {
  14701. close();
  14702. } )
  14703. )
  14704. )
  14705. .append( $('<div class="dtr-modal-background"/>')
  14706. .click( function () {
  14707. close();
  14708. } )
  14709. )
  14710. .appendTo( 'body' );
  14711. $(document).on( 'keyup.dtr', function (e) {
  14712. if ( e.keyCode === 27 ) {
  14713. e.stopPropagation();
  14714. close();
  14715. }
  14716. } );
  14717. }
  14718. else {
  14719. $('div.dtr-modal-content')
  14720. .empty()
  14721. .append( render() );
  14722. }
  14723. if ( options && options.header ) {
  14724. $('div.dtr-modal-content').prepend(
  14725. '<h2>'+options.header( row )+'</h2>'
  14726. );
  14727. }
  14728. };
  14729. }
  14730. };
  14731. var _childNodeStore = {};
  14732. function _childNodes( dt, row, col ) {
  14733. var name = row+'-'+col;
  14734. if ( _childNodeStore[ name ] ) {
  14735. return _childNodeStore[ name ];
  14736. }
  14737. // https://jsperf.com/childnodes-array-slice-vs-loop
  14738. var nodes = [];
  14739. var children = dt.cell( row, col ).node().childNodes;
  14740. for ( var i=0, ien=children.length ; i<ien ; i++ ) {
  14741. nodes.push( children[i] );
  14742. }
  14743. _childNodeStore[ name ] = nodes;
  14744. return nodes;
  14745. }
  14746. function _childNodesRestore( dt, row, col ) {
  14747. var name = row+'-'+col;
  14748. if ( ! _childNodeStore[ name ] ) {
  14749. return;
  14750. }
  14751. var node = dt.cell( row, col ).node();
  14752. var store = _childNodeStore[ name ];
  14753. var parent = store[0].parentNode;
  14754. var parentChildren = parent.childNodes;
  14755. var a = [];
  14756. for ( var i=0, ien=parentChildren.length ; i<ien ; i++ ) {
  14757. a.push( parentChildren[i] );
  14758. }
  14759. for ( var j=0, jen=a.length ; j<jen ; j++ ) {
  14760. node.appendChild( a[j] );
  14761. }
  14762. _childNodeStore[ name ] = undefined;
  14763. }
  14764. /**
  14765. * Display methods - functions which define how the hidden data should be shown
  14766. * in the table.
  14767. *
  14768. * @namespace
  14769. * @name Responsive.defaults
  14770. * @static
  14771. */
  14772. Responsive.renderer = {
  14773. listHiddenNodes: function () {
  14774. return function ( api, rowIdx, columns ) {
  14775. var ul = $('<ul data-dtr-index="'+rowIdx+'" class="dtr-details"/>');
  14776. var found = false;
  14777. var data = $.each( columns, function ( i, col ) {
  14778. if ( col.hidden ) {
  14779. var klass = col.className ?
  14780. 'class="'+ col.className +'"' :
  14781. '';
  14782. $(
  14783. '<li '+klass+' data-dtr-index="'+col.columnIndex+'" data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
  14784. '<span class="dtr-title">'+
  14785. col.title+
  14786. '</span> '+
  14787. '</li>'
  14788. )
  14789. .append( $('<span class="dtr-data"/>').append( _childNodes( api, col.rowIndex, col.columnIndex ) ) )// api.cell( col.rowIndex, col.columnIndex ).node().childNodes ) )
  14790. .appendTo( ul );
  14791. found = true;
  14792. }
  14793. } );
  14794. return found ?
  14795. ul :
  14796. false;
  14797. };
  14798. },
  14799. listHidden: function () {
  14800. return function ( api, rowIdx, columns ) {
  14801. var data = $.map( columns, function ( col ) {
  14802. var klass = col.className ?
  14803. 'class="'+ col.className +'"' :
  14804. '';
  14805. return col.hidden ?
  14806. '<li '+klass+' data-dtr-index="'+col.columnIndex+'" data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
  14807. '<span class="dtr-title">'+
  14808. col.title+
  14809. '</span> '+
  14810. '<span class="dtr-data">'+
  14811. col.data+
  14812. '</span>'+
  14813. '</li>' :
  14814. '';
  14815. } ).join('');
  14816. return data ?
  14817. $('<ul data-dtr-index="'+rowIdx+'" class="dtr-details"/>').append( data ) :
  14818. false;
  14819. }
  14820. },
  14821. tableAll: function ( options ) {
  14822. options = $.extend( {
  14823. tableClass: ''
  14824. }, options );
  14825. return function ( api, rowIdx, columns ) {
  14826. var data = $.map( columns, function ( col ) {
  14827. var klass = col.className ?
  14828. 'class="'+ col.className +'"' :
  14829. '';
  14830. return '<tr '+klass+' data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
  14831. '<td>'+col.title+':'+'</td> '+
  14832. '<td>'+col.data+'</td>'+
  14833. '</tr>';
  14834. } ).join('');
  14835. return $('<table class="'+options.tableClass+' dtr-details" width="100%"/>').append( data );
  14836. }
  14837. }
  14838. };
  14839. /**
  14840. * Responsive default settings for initialisation
  14841. *
  14842. * @namespace
  14843. * @name Responsive.defaults
  14844. * @static
  14845. */
  14846. Responsive.defaults = {
  14847. /**
  14848. * List of breakpoints for the instance. Note that this means that each
  14849. * instance can have its own breakpoints. Additionally, the breakpoints
  14850. * cannot be changed once an instance has been creased.
  14851. *
  14852. * @type {Array}
  14853. * @default Takes the value of `Responsive.breakpoints`
  14854. */
  14855. breakpoints: Responsive.breakpoints,
  14856. /**
  14857. * Enable / disable auto hiding calculations. It can help to increase
  14858. * performance slightly if you disable this option, but all columns would
  14859. * need to have breakpoint classes assigned to them
  14860. *
  14861. * @type {Boolean}
  14862. * @default `true`
  14863. */
  14864. auto: true,
  14865. /**
  14866. * Details control. If given as a string value, the `type` property of the
  14867. * default object is set to that value, and the defaults used for the rest
  14868. * of the object - this is for ease of implementation.
  14869. *
  14870. * The object consists of the following properties:
  14871. *
  14872. * * `display` - A function that is used to show and hide the hidden details
  14873. * * `renderer` - function that is called for display of the child row data.
  14874. * The default function will show the data from the hidden columns
  14875. * * `target` - Used as the selector for what objects to attach the child
  14876. * open / close to
  14877. * * `type` - `false` to disable the details display, `inline` or `column`
  14878. * for the two control types
  14879. *
  14880. * @type {Object|string}
  14881. */
  14882. details: {
  14883. display: Responsive.display.childRow,
  14884. renderer: Responsive.renderer.listHidden(),
  14885. target: 0,
  14886. type: 'inline'
  14887. },
  14888. /**
  14889. * Orthogonal data request option. This is used to define the data type
  14890. * requested when Responsive gets the data to show in the child row.
  14891. *
  14892. * @type {String}
  14893. */
  14894. orthogonal: 'display'
  14895. };
  14896. /*
  14897. * API
  14898. */
  14899. var Api = $.fn.dataTable.Api;
  14900. // Doesn't do anything - work around for a bug in DT... Not documented
  14901. Api.register( 'responsive()', function () {
  14902. return this;
  14903. } );
  14904. Api.register( 'responsive.index()', function ( li ) {
  14905. li = $(li);
  14906. return {
  14907. column: li.data('dtr-index'),
  14908. row: li.parent().data('dtr-index')
  14909. };
  14910. } );
  14911. Api.register( 'responsive.rebuild()', function () {
  14912. return this.iterator( 'table', function ( ctx ) {
  14913. if ( ctx._responsive ) {
  14914. ctx._responsive._classLogic();
  14915. }
  14916. } );
  14917. } );
  14918. Api.register( 'responsive.recalc()', function () {
  14919. return this.iterator( 'table', function ( ctx ) {
  14920. if ( ctx._responsive ) {
  14921. ctx._responsive._resizeAuto();
  14922. ctx._responsive._resize();
  14923. }
  14924. } );
  14925. } );
  14926. Api.register( 'responsive.hasHidden()', function () {
  14927. var ctx = this.context[0];
  14928. return ctx._responsive ?
  14929. $.inArray( false, ctx._responsive._responsiveOnlyHidden() ) !== -1 :
  14930. false;
  14931. } );
  14932. Api.registerPlural( 'columns().responsiveHidden()', 'column().responsiveHidden()', function () {
  14933. return this.iterator( 'column', function ( settings, column ) {
  14934. return settings._responsive ?
  14935. settings._responsive._responsiveOnlyHidden()[ column ] :
  14936. false;
  14937. }, 1 );
  14938. } );
  14939. /**
  14940. * Version information
  14941. *
  14942. * @name Responsive.version
  14943. * @static
  14944. */
  14945. Responsive.version = '2.3.0';
  14946. $.fn.dataTable.Responsive = Responsive;
  14947. $.fn.DataTable.Responsive = Responsive;
  14948. // Attach a listener to the document which listens for DataTables initialisation
  14949. // events so we can automatically initialise
  14950. $(document).on( 'preInit.dt.dtr', function (e, settings, json) {
  14951. if ( e.namespace !== 'dt' ) {
  14952. return;
  14953. }
  14954. if ( $(settings.nTable).hasClass( 'responsive' ) ||
  14955. $(settings.nTable).hasClass( 'dt-responsive' ) ||
  14956. settings.oInit.responsive ||
  14957. DataTable.defaults.responsive
  14958. ) {
  14959. var init = settings.oInit.responsive;
  14960. if ( init !== false ) {
  14961. new Responsive( settings, $.isPlainObject( init ) ? init : {} );
  14962. }
  14963. }
  14964. } );
  14965. return Responsive;
  14966. }));
  14967. /*! Bootstrap 5 integration for DataTables' Responsive
  14968. * ©2021 SpryMedia Ltd - datatables.net/license
  14969. */
  14970. (function( factory ){
  14971. if ( typeof define === 'function' && define.amd ) {
  14972. // AMD
  14973. define( ['jquery', 'datatables.net-bs5', 'datatables.net-responsive'], function ( $ ) {
  14974. return factory( $, window, document );
  14975. } );
  14976. }
  14977. else if ( typeof exports === 'object' ) {
  14978. // CommonJS
  14979. module.exports = function (root, $) {
  14980. if ( ! root ) {
  14981. root = window;
  14982. }
  14983. if ( ! $ || ! $.fn.dataTable ) {
  14984. $ = require('datatables.net-bs5')(root, $).$;
  14985. }
  14986. if ( ! $.fn.dataTable.Responsive ) {
  14987. require('datatables.net-responsive')(root, $);
  14988. }
  14989. return factory( $, root, root.document );
  14990. };
  14991. }
  14992. else {
  14993. // Browser
  14994. factory( jQuery, window, document );
  14995. }
  14996. }(function( $, window, document, undefined ) {
  14997. 'use strict';
  14998. var DataTable = $.fn.dataTable;
  14999. var _display = DataTable.Responsive.display;
  15000. var _original = _display.modal;
  15001. var _modal = $(
  15002. '<div class="modal fade dtr-bs-modal" role="dialog">'+
  15003. '<div class="modal-dialog" role="document">'+
  15004. '<div class="modal-content">'+
  15005. '<div class="modal-header">'+
  15006. '<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>'+
  15007. '</div>'+
  15008. '<div class="modal-body"/>'+
  15009. '</div>'+
  15010. '</div>'+
  15011. '</div>'
  15012. );
  15013. var modal;
  15014. // Note this could be undefined at the time of initialisation - the
  15015. // DataTable.Responsive.bootstrap function can be used to set a different
  15016. // bootstrap object
  15017. var _bs = window.bootstrap;
  15018. DataTable.Responsive.bootstrap = function (bs) {
  15019. _bs = bs;
  15020. }
  15021. _display.modal = function ( options ) {
  15022. if (! modal) {
  15023. modal = new _bs.Modal(_modal[0]);
  15024. }
  15025. return function ( row, update, render ) {
  15026. if ( ! $.fn.modal ) {
  15027. _original( row, update, render );
  15028. }
  15029. else {
  15030. if ( ! update ) {
  15031. if ( options && options.header ) {
  15032. var header = _modal.find('div.modal-header');
  15033. var button = header.find('button').detach();
  15034. header
  15035. .empty()
  15036. .append( '<h4 class="modal-title">'+options.header( row )+'</h4>' )
  15037. .append( button );
  15038. }
  15039. _modal.find( 'div.modal-body' )
  15040. .empty()
  15041. .append( render() );
  15042. _modal
  15043. .appendTo( 'body' )
  15044. .modal();
  15045. modal.show();
  15046. }
  15047. }
  15048. };
  15049. };
  15050. return DataTable.Responsive;
  15051. }));
  15052. /*! Select for DataTables 1.4.0
  15053. * 2015-2021 SpryMedia Ltd - datatables.net/license/mit
  15054. */
  15055. /**
  15056. * @summary Select for DataTables
  15057. * @description A collection of API methods, events and buttons for DataTables
  15058. * that provides selection options of the items in a DataTable
  15059. * @version 1.4.0
  15060. * @file dataTables.select.js
  15061. * @author SpryMedia Ltd (www.sprymedia.co.uk)
  15062. * @contact datatables.net/forums
  15063. * @copyright Copyright 2015-2021 SpryMedia Ltd.
  15064. *
  15065. * This source file is free software, available under the following license:
  15066. * MIT license - http://datatables.net/license/mit
  15067. *
  15068. * This source file is distributed in the hope that it will be useful, but
  15069. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  15070. * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  15071. *
  15072. * For details please refer to: http://www.datatables.net/extensions/select
  15073. */
  15074. (function( factory ){
  15075. if ( typeof define === 'function' && define.amd ) {
  15076. // AMD
  15077. define( ['jquery', 'datatables.net'], function ( $ ) {
  15078. return factory( $, window, document );
  15079. } );
  15080. }
  15081. else if ( typeof exports === 'object' ) {
  15082. // CommonJS
  15083. module.exports = function (root, $) {
  15084. if ( ! root ) {
  15085. root = window;
  15086. }
  15087. if ( ! $ || ! $.fn.dataTable ) {
  15088. $ = require('datatables.net')(root, $).$;
  15089. }
  15090. return factory( $, root, root.document );
  15091. };
  15092. }
  15093. else {
  15094. // Browser
  15095. factory( jQuery, window, document );
  15096. }
  15097. }(function( $, window, document, undefined ) {
  15098. 'use strict';
  15099. var DataTable = $.fn.dataTable;
  15100. // Version information for debugger
  15101. DataTable.select = {};
  15102. DataTable.select.version = '1.4.0';
  15103. DataTable.select.init = function ( dt ) {
  15104. var ctx = dt.settings()[0];
  15105. if (ctx._select) {
  15106. return;
  15107. }
  15108. var savedSelected = dt.state.loaded();
  15109. var selectAndSave = function(e, settings, data) {
  15110. if(data === null || data.select === undefined) {
  15111. return;
  15112. }
  15113. // Clear any currently selected rows, before restoring state
  15114. // None will be selected on first initialisation
  15115. if (dt.rows({selected: true}).any()) {
  15116. dt.rows().deselect();
  15117. }
  15118. if (data.select.rows !== undefined) {
  15119. dt.rows(data.select.rows).select();
  15120. }
  15121. if (dt.columns({selected: true}).any()) {
  15122. dt.columns().deselect();
  15123. }
  15124. if (data.select.columns !== undefined) {
  15125. dt.columns(data.select.columns).select();
  15126. }
  15127. if (dt.cells({selected: true}).any()) {
  15128. dt.cells().deselect();
  15129. }
  15130. if (data.select.cells !== undefined) {
  15131. for(var i = 0; i < data.select.cells.length; i++) {
  15132. dt.cell(data.select.cells[i].row, data.select.cells[i].column).select();
  15133. }
  15134. }
  15135. dt.state.save();
  15136. }
  15137. dt.one('init', function() {
  15138. dt.on('stateSaveParams', function(e, settings, data) {
  15139. data.select = {};
  15140. data.select.rows = dt.rows({selected:true}).ids(true).toArray();
  15141. data.select.columns = dt.columns({selected:true})[0];
  15142. data.select.cells = dt.cells({selected:true})[0].map(function(coords) {
  15143. return {row: dt.row(coords.row).id(true), column: coords.column}
  15144. });
  15145. })
  15146. selectAndSave(undefined, undefined, savedSelected)
  15147. dt.on('stateLoaded stateLoadParams', selectAndSave)
  15148. })
  15149. var init = ctx.oInit.select;
  15150. var defaults = DataTable.defaults.select;
  15151. var opts = init === undefined ?
  15152. defaults :
  15153. init;
  15154. // Set defaults
  15155. var items = 'row';
  15156. var style = 'api';
  15157. var blurable = false;
  15158. var toggleable = true;
  15159. var info = true;
  15160. var selector = 'td, th';
  15161. var className = 'selected';
  15162. var setStyle = false;
  15163. ctx._select = {};
  15164. // Initialisation customisations
  15165. if ( opts === true ) {
  15166. style = 'os';
  15167. setStyle = true;
  15168. }
  15169. else if ( typeof opts === 'string' ) {
  15170. style = opts;
  15171. setStyle = true;
  15172. }
  15173. else if ( $.isPlainObject( opts ) ) {
  15174. if ( opts.blurable !== undefined ) {
  15175. blurable = opts.blurable;
  15176. }
  15177. if ( opts.toggleable !== undefined ) {
  15178. toggleable = opts.toggleable;
  15179. }
  15180. if ( opts.info !== undefined ) {
  15181. info = opts.info;
  15182. }
  15183. if ( opts.items !== undefined ) {
  15184. items = opts.items;
  15185. }
  15186. if ( opts.style !== undefined ) {
  15187. style = opts.style;
  15188. setStyle = true;
  15189. }
  15190. else {
  15191. style = 'os';
  15192. setStyle = true;
  15193. }
  15194. if ( opts.selector !== undefined ) {
  15195. selector = opts.selector;
  15196. }
  15197. if ( opts.className !== undefined ) {
  15198. className = opts.className;
  15199. }
  15200. }
  15201. dt.select.selector( selector );
  15202. dt.select.items( items );
  15203. dt.select.style( style );
  15204. dt.select.blurable( blurable );
  15205. dt.select.toggleable( toggleable );
  15206. dt.select.info( info );
  15207. ctx._select.className = className;
  15208. // Sort table based on selected rows. Requires Select Datatables extension
  15209. $.fn.dataTable.ext.order['select-checkbox'] = function ( settings, col ) {
  15210. return this.api().column( col, {order: 'index'} ).nodes().map( function ( td ) {
  15211. if ( settings._select.items === 'row' ) {
  15212. return $( td ).parent().hasClass( settings._select.className );
  15213. } else if ( settings._select.items === 'cell' ) {
  15214. return $( td ).hasClass( settings._select.className );
  15215. }
  15216. return false;
  15217. });
  15218. };
  15219. // If the init options haven't enabled select, but there is a selectable
  15220. // class name, then enable
  15221. if ( ! setStyle && $( dt.table().node() ).hasClass( 'selectable' ) ) {
  15222. dt.select.style( 'os' );
  15223. }
  15224. };
  15225. /*
  15226. Select is a collection of API methods, event handlers, event emitters and
  15227. buttons (for the `Buttons` extension) for DataTables. It provides the following
  15228. features, with an overview of how they are implemented:
  15229. ## Selection of rows, columns and cells. Whether an item is selected or not is
  15230. stored in:
  15231. * rows: a `_select_selected` property which contains a boolean value of the
  15232. DataTables' `aoData` object for each row
  15233. * columns: a `_select_selected` property which contains a boolean value of the
  15234. DataTables' `aoColumns` object for each column
  15235. * cells: a `_selected_cells` property which contains an array of boolean values
  15236. of the `aoData` object for each row. The array is the same length as the
  15237. columns array, with each element of it representing a cell.
  15238. This method of using boolean flags allows Select to operate when nodes have not
  15239. been created for rows / cells (DataTables' defer rendering feature).
  15240. ## API methods
  15241. A range of API methods are available for triggering selection and de-selection
  15242. of rows. Methods are also available to configure the selection events that can
  15243. be triggered by an end user (such as which items are to be selected). To a large
  15244. extent, these of API methods *is* Select. It is basically a collection of helper
  15245. functions that can be used to select items in a DataTable.
  15246. Configuration of select is held in the object `_select` which is attached to the
  15247. DataTables settings object on initialisation. Select being available on a table
  15248. is not optional when Select is loaded, but its default is for selection only to
  15249. be available via the API - so the end user wouldn't be able to select rows
  15250. without additional configuration.
  15251. The `_select` object contains the following properties:
  15252. ```
  15253. {
  15254. items:string - Can be `rows`, `columns` or `cells`. Defines what item
  15255. will be selected if the user is allowed to activate row
  15256. selection using the mouse.
  15257. style:string - Can be `none`, `single`, `multi` or `os`. Defines the
  15258. interaction style when selecting items
  15259. blurable:boolean - If row selection can be cleared by clicking outside of
  15260. the table
  15261. toggleable:boolean - If row selection can be cancelled by repeated clicking
  15262. on the row
  15263. info:boolean - If the selection summary should be shown in the table
  15264. information elements
  15265. }
  15266. ```
  15267. In addition to the API methods, Select also extends the DataTables selector
  15268. options for rows, columns and cells adding a `selected` option to the selector
  15269. options object, allowing the developer to select only selected items or
  15270. unselected items.
  15271. ## Mouse selection of items
  15272. Clicking on items can be used to select items. This is done by a simple event
  15273. handler that will select the items using the API methods.
  15274. */
  15275. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  15276. * Local functions
  15277. */
  15278. /**
  15279. * Add one or more cells to the selection when shift clicking in OS selection
  15280. * style cell selection.
  15281. *
  15282. * Cell range is more complicated than row and column as we want to select
  15283. * in the visible grid rather than by index in sequence. For example, if you
  15284. * click first in cell 1-1 and then shift click in 2-2 - cells 1-2 and 2-1
  15285. * should also be selected (and not 1-3, 1-4. etc)
  15286. *
  15287. * @param {DataTable.Api} dt DataTable
  15288. * @param {object} idx Cell index to select to
  15289. * @param {object} last Cell index to select from
  15290. * @private
  15291. */
  15292. function cellRange( dt, idx, last )
  15293. {
  15294. var indexes;
  15295. var columnIndexes;
  15296. var rowIndexes;
  15297. var selectColumns = function ( start, end ) {
  15298. if ( start > end ) {
  15299. var tmp = end;
  15300. end = start;
  15301. start = tmp;
  15302. }
  15303. var record = false;
  15304. return dt.columns( ':visible' ).indexes().filter( function (i) {
  15305. if ( i === start ) {
  15306. record = true;
  15307. }
  15308. if ( i === end ) { // not else if, as start might === end
  15309. record = false;
  15310. return true;
  15311. }
  15312. return record;
  15313. } );
  15314. };
  15315. var selectRows = function ( start, end ) {
  15316. var indexes = dt.rows( { search: 'applied' } ).indexes();
  15317. // Which comes first - might need to swap
  15318. if ( indexes.indexOf( start ) > indexes.indexOf( end ) ) {
  15319. var tmp = end;
  15320. end = start;
  15321. start = tmp;
  15322. }
  15323. var record = false;
  15324. return indexes.filter( function (i) {
  15325. if ( i === start ) {
  15326. record = true;
  15327. }
  15328. if ( i === end ) {
  15329. record = false;
  15330. return true;
  15331. }
  15332. return record;
  15333. } );
  15334. };
  15335. if ( ! dt.cells( { selected: true } ).any() && ! last ) {
  15336. // select from the top left cell to this one
  15337. columnIndexes = selectColumns( 0, idx.column );
  15338. rowIndexes = selectRows( 0 , idx.row );
  15339. }
  15340. else {
  15341. // Get column indexes between old and new
  15342. columnIndexes = selectColumns( last.column, idx.column );
  15343. rowIndexes = selectRows( last.row , idx.row );
  15344. }
  15345. indexes = dt.cells( rowIndexes, columnIndexes ).flatten();
  15346. if ( ! dt.cells( idx, { selected: true } ).any() ) {
  15347. // Select range
  15348. dt.cells( indexes ).select();
  15349. }
  15350. else {
  15351. // Deselect range
  15352. dt.cells( indexes ).deselect();
  15353. }
  15354. }
  15355. /**
  15356. * Disable mouse selection by removing the selectors
  15357. *
  15358. * @param {DataTable.Api} dt DataTable to remove events from
  15359. * @private
  15360. */
  15361. function disableMouseSelection( dt )
  15362. {
  15363. var ctx = dt.settings()[0];
  15364. var selector = ctx._select.selector;
  15365. $( dt.table().container() )
  15366. .off( 'mousedown.dtSelect', selector )
  15367. .off( 'mouseup.dtSelect', selector )
  15368. .off( 'click.dtSelect', selector );
  15369. $('body').off( 'click.dtSelect' + _safeId(dt.table().node()) );
  15370. }
  15371. /**
  15372. * Attach mouse listeners to the table to allow mouse selection of items
  15373. *
  15374. * @param {DataTable.Api} dt DataTable to remove events from
  15375. * @private
  15376. */
  15377. function enableMouseSelection ( dt )
  15378. {
  15379. var container = $( dt.table().container() );
  15380. var ctx = dt.settings()[0];
  15381. var selector = ctx._select.selector;
  15382. var matchSelection;
  15383. container
  15384. .on( 'mousedown.dtSelect', selector, function(e) {
  15385. // Disallow text selection for shift clicking on the table so multi
  15386. // element selection doesn't look terrible!
  15387. if ( e.shiftKey || e.metaKey || e.ctrlKey ) {
  15388. container
  15389. .css( '-moz-user-select', 'none' )
  15390. .one('selectstart.dtSelect', selector, function () {
  15391. return false;
  15392. } );
  15393. }
  15394. if ( window.getSelection ) {
  15395. matchSelection = window.getSelection();
  15396. }
  15397. } )
  15398. .on( 'mouseup.dtSelect', selector, function() {
  15399. // Allow text selection to occur again, Mozilla style (tested in FF
  15400. // 35.0.1 - still required)
  15401. container.css( '-moz-user-select', '' );
  15402. } )
  15403. .on( 'click.dtSelect', selector, function ( e ) {
  15404. var items = dt.select.items();
  15405. var idx;
  15406. // If text was selected (click and drag), then we shouldn't change
  15407. // the row's selected state
  15408. if ( matchSelection ) {
  15409. var selection = window.getSelection();
  15410. // If the element that contains the selection is not in the table, we can ignore it
  15411. // This can happen if the developer selects text from the click event
  15412. if ( ! selection.anchorNode || $(selection.anchorNode).closest('table')[0] === dt.table().node() ) {
  15413. if ( selection !== matchSelection ) {
  15414. return;
  15415. }
  15416. }
  15417. }
  15418. var ctx = dt.settings()[0];
  15419. var wrapperClass = dt.settings()[0].oClasses.sWrapper.trim().replace(/ +/g, '.');
  15420. // Ignore clicks inside a sub-table
  15421. if ( $(e.target).closest('div.'+wrapperClass)[0] != dt.table().container() ) {
  15422. return;
  15423. }
  15424. var cell = dt.cell( $(e.target).closest('td, th') );
  15425. // Check the cell actually belongs to the host DataTable (so child
  15426. // rows, etc, are ignored)
  15427. if ( ! cell.any() ) {
  15428. return;
  15429. }
  15430. var event = $.Event('user-select.dt');
  15431. eventTrigger( dt, event, [ items, cell, e ] );
  15432. if ( event.isDefaultPrevented() ) {
  15433. return;
  15434. }
  15435. var cellIndex = cell.index();
  15436. if ( items === 'row' ) {
  15437. idx = cellIndex.row;
  15438. typeSelect( e, dt, ctx, 'row', idx );
  15439. }
  15440. else if ( items === 'column' ) {
  15441. idx = cell.index().column;
  15442. typeSelect( e, dt, ctx, 'column', idx );
  15443. }
  15444. else if ( items === 'cell' ) {
  15445. idx = cell.index();
  15446. typeSelect( e, dt, ctx, 'cell', idx );
  15447. }
  15448. ctx._select_lastCell = cellIndex;
  15449. } );
  15450. // Blurable
  15451. $('body').on( 'click.dtSelect' + _safeId(dt.table().node()), function ( e ) {
  15452. if ( ctx._select.blurable ) {
  15453. // If the click was inside the DataTables container, don't blur
  15454. if ( $(e.target).parents().filter( dt.table().container() ).length ) {
  15455. return;
  15456. }
  15457. // Ignore elements which have been removed from the DOM (i.e. paging
  15458. // buttons)
  15459. if ( $(e.target).parents('html').length === 0 ) {
  15460. return;
  15461. }
  15462. // Don't blur in Editor form
  15463. if ( $(e.target).parents('div.DTE').length ) {
  15464. return;
  15465. }
  15466. var event = $.Event('select-blur.dt');
  15467. eventTrigger( dt, event, [ e.target, e ] );
  15468. if ( event.isDefaultPrevented() ) {
  15469. return;
  15470. }
  15471. clear( ctx, true );
  15472. }
  15473. } );
  15474. }
  15475. /**
  15476. * Trigger an event on a DataTable
  15477. *
  15478. * @param {DataTable.Api} api DataTable to trigger events on
  15479. * @param {boolean} selected true if selected, false if deselected
  15480. * @param {string} type Item type acting on
  15481. * @param {boolean} any Require that there are values before
  15482. * triggering
  15483. * @private
  15484. */
  15485. function eventTrigger ( api, type, args, any )
  15486. {
  15487. if ( any && ! api.flatten().length ) {
  15488. return;
  15489. }
  15490. if ( typeof type === 'string' ) {
  15491. type = type +'.dt';
  15492. }
  15493. args.unshift( api );
  15494. $(api.table().node()).trigger( type, args );
  15495. }
  15496. /**
  15497. * Update the information element of the DataTable showing information about the
  15498. * items selected. This is done by adding tags to the existing text
  15499. *
  15500. * @param {DataTable.Api} api DataTable to update
  15501. * @private
  15502. */
  15503. function info ( api )
  15504. {
  15505. var ctx = api.settings()[0];
  15506. if ( ! ctx._select.info || ! ctx.aanFeatures.i ) {
  15507. return;
  15508. }
  15509. if ( api.select.style() === 'api' ) {
  15510. return;
  15511. }
  15512. var rows = api.rows( { selected: true } ).flatten().length;
  15513. var columns = api.columns( { selected: true } ).flatten().length;
  15514. var cells = api.cells( { selected: true } ).flatten().length;
  15515. var add = function ( el, name, num ) {
  15516. el.append( $('<span class="select-item"/>').append( api.i18n(
  15517. 'select.'+name+'s',
  15518. { _: '%d '+name+'s selected', 0: '', 1: '1 '+name+' selected' },
  15519. num
  15520. ) ) );
  15521. };
  15522. // Internal knowledge of DataTables to loop over all information elements
  15523. $.each( ctx.aanFeatures.i, function ( i, el ) {
  15524. el = $(el);
  15525. var output = $('<span class="select-info"/>');
  15526. add( output, 'row', rows );
  15527. add( output, 'column', columns );
  15528. add( output, 'cell', cells );
  15529. var exisiting = el.children('span.select-info');
  15530. if ( exisiting.length ) {
  15531. exisiting.remove();
  15532. }
  15533. if ( output.text() !== '' ) {
  15534. el.append( output );
  15535. }
  15536. } );
  15537. }
  15538. /**
  15539. * Initialisation of a new table. Attach event handlers and callbacks to allow
  15540. * Select to operate correctly.
  15541. *
  15542. * This will occur _after_ the initial DataTables initialisation, although
  15543. * before Ajax data is rendered, if there is ajax data
  15544. *
  15545. * @param {DataTable.settings} ctx Settings object to operate on
  15546. * @private
  15547. */
  15548. function init ( ctx ) {
  15549. var api = new DataTable.Api( ctx );
  15550. ctx._select_init = true;
  15551. // Row callback so that classes can be added to rows and cells if the item
  15552. // was selected before the element was created. This will happen with the
  15553. // `deferRender` option enabled.
  15554. //
  15555. // This method of attaching to `aoRowCreatedCallback` is a hack until
  15556. // DataTables has proper events for row manipulation If you are reviewing
  15557. // this code to create your own plug-ins, please do not do this!
  15558. ctx.aoRowCreatedCallback.push( {
  15559. fn: function ( row, data, index ) {
  15560. var i, ien;
  15561. var d = ctx.aoData[ index ];
  15562. // Row
  15563. if ( d._select_selected ) {
  15564. $( row ).addClass( ctx._select.className );
  15565. }
  15566. // Cells and columns - if separated out, we would need to do two
  15567. // loops, so it makes sense to combine them into a single one
  15568. for ( i=0, ien=ctx.aoColumns.length ; i<ien ; i++ ) {
  15569. if ( ctx.aoColumns[i]._select_selected || (d._selected_cells && d._selected_cells[i]) ) {
  15570. $(d.anCells[i]).addClass( ctx._select.className );
  15571. }
  15572. }
  15573. },
  15574. sName: 'select-deferRender'
  15575. } );
  15576. // On Ajax reload we want to reselect all rows which are currently selected,
  15577. // if there is an rowId (i.e. a unique value to identify each row with)
  15578. api.on( 'preXhr.dt.dtSelect', function (e, settings) {
  15579. if (settings !== api.settings()[0]) {
  15580. // Not triggered by our DataTable!
  15581. return;
  15582. }
  15583. // note that column selection doesn't need to be cached and then
  15584. // reselected, as they are already selected
  15585. var rows = api.rows( { selected: true } ).ids( true ).filter( function ( d ) {
  15586. return d !== undefined;
  15587. } );
  15588. var cells = api.cells( { selected: true } ).eq(0).map( function ( cellIdx ) {
  15589. var id = api.row( cellIdx.row ).id( true );
  15590. return id ?
  15591. { row: id, column: cellIdx.column } :
  15592. undefined;
  15593. } ).filter( function ( d ) {
  15594. return d !== undefined;
  15595. } );
  15596. // On the next draw, reselect the currently selected items
  15597. api.one( 'draw.dt.dtSelect', function () {
  15598. api.rows( rows ).select();
  15599. // `cells` is not a cell index selector, so it needs a loop
  15600. if ( cells.any() ) {
  15601. cells.each( function ( id ) {
  15602. api.cells( id.row, id.column ).select();
  15603. } );
  15604. }
  15605. } );
  15606. } );
  15607. // Update the table information element with selected item summary
  15608. api.on( 'draw.dtSelect.dt select.dtSelect.dt deselect.dtSelect.dt info.dt', function () {
  15609. info( api );
  15610. api.state.save();
  15611. } );
  15612. // Clean up and release
  15613. api.on( 'destroy.dtSelect', function () {
  15614. api.rows({selected: true}).deselect();
  15615. disableMouseSelection( api );
  15616. api.off( '.dtSelect' );
  15617. $('body').off('.dtSelect' + _safeId(api.table().node()));
  15618. } );
  15619. }
  15620. /**
  15621. * Add one or more items (rows or columns) to the selection when shift clicking
  15622. * in OS selection style
  15623. *
  15624. * @param {DataTable.Api} dt DataTable
  15625. * @param {string} type Row or column range selector
  15626. * @param {object} idx Item index to select to
  15627. * @param {object} last Item index to select from
  15628. * @private
  15629. */
  15630. function rowColumnRange( dt, type, idx, last )
  15631. {
  15632. // Add a range of rows from the last selected row to this one
  15633. var indexes = dt[type+'s']( { search: 'applied' } ).indexes();
  15634. var idx1 = $.inArray( last, indexes );
  15635. var idx2 = $.inArray( idx, indexes );
  15636. if ( ! dt[type+'s']( { selected: true } ).any() && idx1 === -1 ) {
  15637. // select from top to here - slightly odd, but both Windows and Mac OS
  15638. // do this
  15639. indexes.splice( $.inArray( idx, indexes )+1, indexes.length );
  15640. }
  15641. else {
  15642. // reverse so we can shift click 'up' as well as down
  15643. if ( idx1 > idx2 ) {
  15644. var tmp = idx2;
  15645. idx2 = idx1;
  15646. idx1 = tmp;
  15647. }
  15648. indexes.splice( idx2+1, indexes.length );
  15649. indexes.splice( 0, idx1 );
  15650. }
  15651. if ( ! dt[type]( idx, { selected: true } ).any() ) {
  15652. // Select range
  15653. dt[type+'s']( indexes ).select();
  15654. }
  15655. else {
  15656. // Deselect range - need to keep the clicked on row selected
  15657. indexes.splice( $.inArray( idx, indexes ), 1 );
  15658. dt[type+'s']( indexes ).deselect();
  15659. }
  15660. }
  15661. /**
  15662. * Clear all selected items
  15663. *
  15664. * @param {DataTable.settings} ctx Settings object of the host DataTable
  15665. * @param {boolean} [force=false] Force the de-selection to happen, regardless
  15666. * of selection style
  15667. * @private
  15668. */
  15669. function clear( ctx, force )
  15670. {
  15671. if ( force || ctx._select.style === 'single' ) {
  15672. var api = new DataTable.Api( ctx );
  15673. api.rows( { selected: true } ).deselect();
  15674. api.columns( { selected: true } ).deselect();
  15675. api.cells( { selected: true } ).deselect();
  15676. }
  15677. }
  15678. /**
  15679. * Select items based on the current configuration for style and items.
  15680. *
  15681. * @param {object} e Mouse event object
  15682. * @param {DataTables.Api} dt DataTable
  15683. * @param {DataTable.settings} ctx Settings object of the host DataTable
  15684. * @param {string} type Items to select
  15685. * @param {int|object} idx Index of the item to select
  15686. * @private
  15687. */
  15688. function typeSelect ( e, dt, ctx, type, idx )
  15689. {
  15690. var style = dt.select.style();
  15691. var toggleable = dt.select.toggleable();
  15692. var isSelected = dt[type]( idx, { selected: true } ).any();
  15693. if ( isSelected && ! toggleable ) {
  15694. return;
  15695. }
  15696. if ( style === 'os' ) {
  15697. if ( e.ctrlKey || e.metaKey ) {
  15698. // Add or remove from the selection
  15699. dt[type]( idx ).select( ! isSelected );
  15700. }
  15701. else if ( e.shiftKey ) {
  15702. if ( type === 'cell' ) {
  15703. cellRange( dt, idx, ctx._select_lastCell || null );
  15704. }
  15705. else {
  15706. rowColumnRange( dt, type, idx, ctx._select_lastCell ?
  15707. ctx._select_lastCell[type] :
  15708. null
  15709. );
  15710. }
  15711. }
  15712. else {
  15713. // No cmd or shift click - deselect if selected, or select
  15714. // this row only
  15715. var selected = dt[type+'s']( { selected: true } );
  15716. if ( isSelected && selected.flatten().length === 1 ) {
  15717. dt[type]( idx ).deselect();
  15718. }
  15719. else {
  15720. selected.deselect();
  15721. dt[type]( idx ).select();
  15722. }
  15723. }
  15724. } else if ( style == 'multi+shift' ) {
  15725. if ( e.shiftKey ) {
  15726. if ( type === 'cell' ) {
  15727. cellRange( dt, idx, ctx._select_lastCell || null );
  15728. }
  15729. else {
  15730. rowColumnRange( dt, type, idx, ctx._select_lastCell ?
  15731. ctx._select_lastCell[type] :
  15732. null
  15733. );
  15734. }
  15735. }
  15736. else {
  15737. dt[ type ]( idx ).select( ! isSelected );
  15738. }
  15739. }
  15740. else {
  15741. dt[ type ]( idx ).select( ! isSelected );
  15742. }
  15743. }
  15744. function _safeId( node ) {
  15745. return node.id.replace(/[^a-zA-Z0-9\-\_]/g, '-');
  15746. }
  15747. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  15748. * DataTables selectors
  15749. */
  15750. // row and column are basically identical just assigned to different properties
  15751. // and checking a different array, so we can dynamically create the functions to
  15752. // reduce the code size
  15753. $.each( [
  15754. { type: 'row', prop: 'aoData' },
  15755. { type: 'column', prop: 'aoColumns' }
  15756. ], function ( i, o ) {
  15757. DataTable.ext.selector[ o.type ].push( function ( settings, opts, indexes ) {
  15758. var selected = opts.selected;
  15759. var data;
  15760. var out = [];
  15761. if ( selected !== true && selected !== false ) {
  15762. return indexes;
  15763. }
  15764. for ( var i=0, ien=indexes.length ; i<ien ; i++ ) {
  15765. data = settings[ o.prop ][ indexes[i] ];
  15766. if ( (selected === true && data._select_selected === true) ||
  15767. (selected === false && ! data._select_selected )
  15768. ) {
  15769. out.push( indexes[i] );
  15770. }
  15771. }
  15772. return out;
  15773. } );
  15774. } );
  15775. DataTable.ext.selector.cell.push( function ( settings, opts, cells ) {
  15776. var selected = opts.selected;
  15777. var rowData;
  15778. var out = [];
  15779. if ( selected === undefined ) {
  15780. return cells;
  15781. }
  15782. for ( var i=0, ien=cells.length ; i<ien ; i++ ) {
  15783. rowData = settings.aoData[ cells[i].row ];
  15784. if ( (selected === true && rowData._selected_cells && rowData._selected_cells[ cells[i].column ] === true) ||
  15785. (selected === false && ( ! rowData._selected_cells || ! rowData._selected_cells[ cells[i].column ] ) )
  15786. ) {
  15787. out.push( cells[i] );
  15788. }
  15789. }
  15790. return out;
  15791. } );
  15792. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  15793. * DataTables API
  15794. *
  15795. * For complete documentation, please refer to the docs/api directory or the
  15796. * DataTables site
  15797. */
  15798. // Local variables to improve compression
  15799. var apiRegister = DataTable.Api.register;
  15800. var apiRegisterPlural = DataTable.Api.registerPlural;
  15801. apiRegister( 'select()', function () {
  15802. return this.iterator( 'table', function ( ctx ) {
  15803. DataTable.select.init( new DataTable.Api( ctx ) );
  15804. } );
  15805. } );
  15806. apiRegister( 'select.blurable()', function ( flag ) {
  15807. if ( flag === undefined ) {
  15808. return this.context[0]._select.blurable;
  15809. }
  15810. return this.iterator( 'table', function ( ctx ) {
  15811. ctx._select.blurable = flag;
  15812. } );
  15813. } );
  15814. apiRegister( 'select.toggleable()', function ( flag ) {
  15815. if ( flag === undefined ) {
  15816. return this.context[0]._select.toggleable;
  15817. }
  15818. return this.iterator( 'table', function ( ctx ) {
  15819. ctx._select.toggleable = flag;
  15820. } );
  15821. } );
  15822. apiRegister( 'select.info()', function ( flag ) {
  15823. if ( flag === undefined ) {
  15824. return this.context[0]._select.info;
  15825. }
  15826. return this.iterator( 'table', function ( ctx ) {
  15827. ctx._select.info = flag;
  15828. } );
  15829. } );
  15830. apiRegister( 'select.items()', function ( items ) {
  15831. if ( items === undefined ) {
  15832. return this.context[0]._select.items;
  15833. }
  15834. return this.iterator( 'table', function ( ctx ) {
  15835. ctx._select.items = items;
  15836. eventTrigger( new DataTable.Api( ctx ), 'selectItems', [ items ] );
  15837. } );
  15838. } );
  15839. // Takes effect from the _next_ selection. None disables future selection, but
  15840. // does not clear the current selection. Use the `deselect` methods for that
  15841. apiRegister( 'select.style()', function ( style ) {
  15842. if ( style === undefined ) {
  15843. return this.context[0]._select.style;
  15844. }
  15845. return this.iterator( 'table', function ( ctx ) {
  15846. if ( ! ctx._select ) {
  15847. DataTable.select.init( new DataTable.Api(ctx) );
  15848. }
  15849. if ( ! ctx._select_init ) {
  15850. init(ctx);
  15851. }
  15852. ctx._select.style = style;
  15853. // Add / remove mouse event handlers. They aren't required when only
  15854. // API selection is available
  15855. var dt = new DataTable.Api( ctx );
  15856. disableMouseSelection( dt );
  15857. if ( style !== 'api' ) {
  15858. enableMouseSelection( dt );
  15859. }
  15860. eventTrigger( new DataTable.Api( ctx ), 'selectStyle', [ style ] );
  15861. } );
  15862. } );
  15863. apiRegister( 'select.selector()', function ( selector ) {
  15864. if ( selector === undefined ) {
  15865. return this.context[0]._select.selector;
  15866. }
  15867. return this.iterator( 'table', function ( ctx ) {
  15868. disableMouseSelection( new DataTable.Api( ctx ) );
  15869. ctx._select.selector = selector;
  15870. if ( ctx._select.style !== 'api' ) {
  15871. enableMouseSelection( new DataTable.Api( ctx ) );
  15872. }
  15873. } );
  15874. } );
  15875. apiRegisterPlural( 'rows().select()', 'row().select()', function ( select ) {
  15876. var api = this;
  15877. if ( select === false ) {
  15878. return this.deselect();
  15879. }
  15880. this.iterator( 'row', function ( ctx, idx ) {
  15881. clear( ctx );
  15882. ctx.aoData[ idx ]._select_selected = true;
  15883. $( ctx.aoData[ idx ].nTr ).addClass( ctx._select.className );
  15884. } );
  15885. this.iterator( 'table', function ( ctx, i ) {
  15886. eventTrigger( api, 'select', [ 'row', api[i] ], true );
  15887. } );
  15888. return this;
  15889. } );
  15890. apiRegister( 'row().selected()', function () {
  15891. var ctx = this.context[0];
  15892. if (
  15893. ctx &&
  15894. this.length &&
  15895. ctx.aoData[this[0]] &&
  15896. ctx.aoData[this[0]]._select_selected
  15897. ) {
  15898. return true;
  15899. }
  15900. return false;
  15901. } );
  15902. apiRegisterPlural( 'columns().select()', 'column().select()', function ( select ) {
  15903. var api = this;
  15904. if ( select === false ) {
  15905. return this.deselect();
  15906. }
  15907. this.iterator( 'column', function ( ctx, idx ) {
  15908. clear( ctx );
  15909. ctx.aoColumns[ idx ]._select_selected = true;
  15910. var column = new DataTable.Api( ctx ).column( idx );
  15911. $( column.header() ).addClass( ctx._select.className );
  15912. $( column.footer() ).addClass( ctx._select.className );
  15913. column.nodes().to$().addClass( ctx._select.className );
  15914. } );
  15915. this.iterator( 'table', function ( ctx, i ) {
  15916. eventTrigger( api, 'select', [ 'column', api[i] ], true );
  15917. } );
  15918. return this;
  15919. } );
  15920. apiRegister( 'column().selected()', function () {
  15921. var ctx = this.context[0];
  15922. if (
  15923. ctx &&
  15924. this.length &&
  15925. ctx.aoColumns[this[0]] &&
  15926. ctx.aoColumns[this[0]]._select_selected
  15927. ) {
  15928. return true;
  15929. }
  15930. return false;
  15931. } );
  15932. apiRegisterPlural( 'cells().select()', 'cell().select()', function ( select ) {
  15933. var api = this;
  15934. if ( select === false ) {
  15935. return this.deselect();
  15936. }
  15937. this.iterator( 'cell', function ( ctx, rowIdx, colIdx ) {
  15938. clear( ctx );
  15939. var data = ctx.aoData[ rowIdx ];
  15940. if ( data._selected_cells === undefined ) {
  15941. data._selected_cells = [];
  15942. }
  15943. data._selected_cells[ colIdx ] = true;
  15944. if ( data.anCells ) {
  15945. $( data.anCells[ colIdx ] ).addClass( ctx._select.className );
  15946. }
  15947. } );
  15948. this.iterator( 'table', function ( ctx, i ) {
  15949. eventTrigger( api, 'select', [ 'cell', api.cells(api[i]).indexes().toArray() ], true );
  15950. } );
  15951. return this;
  15952. } );
  15953. apiRegister( 'cell().selected()', function () {
  15954. var ctx = this.context[0];
  15955. if (ctx && this.length) {
  15956. var row = ctx.aoData[this[0][0].row];
  15957. if (row && row._selected_cells && row._selected_cells[this[0][0].column]) {
  15958. return true;
  15959. }
  15960. }
  15961. return false;
  15962. } );
  15963. apiRegisterPlural( 'rows().deselect()', 'row().deselect()', function () {
  15964. var api = this;
  15965. this.iterator( 'row', function ( ctx, idx ) {
  15966. ctx.aoData[ idx ]._select_selected = false;
  15967. ctx._select_lastCell = null;
  15968. $( ctx.aoData[ idx ].nTr ).removeClass( ctx._select.className );
  15969. } );
  15970. this.iterator( 'table', function ( ctx, i ) {
  15971. eventTrigger( api, 'deselect', [ 'row', api[i] ], true );
  15972. } );
  15973. return this;
  15974. } );
  15975. apiRegisterPlural( 'columns().deselect()', 'column().deselect()', function () {
  15976. var api = this;
  15977. this.iterator( 'column', function ( ctx, idx ) {
  15978. ctx.aoColumns[ idx ]._select_selected = false;
  15979. var api = new DataTable.Api( ctx );
  15980. var column = api.column( idx );
  15981. $( column.header() ).removeClass( ctx._select.className );
  15982. $( column.footer() ).removeClass( ctx._select.className );
  15983. // Need to loop over each cell, rather than just using
  15984. // `column().nodes()` as cells which are individually selected should
  15985. // not have the `selected` class removed from them
  15986. api.cells( null, idx ).indexes().each( function (cellIdx) {
  15987. var data = ctx.aoData[ cellIdx.row ];
  15988. var cellSelected = data._selected_cells;
  15989. if ( data.anCells && (! cellSelected || ! cellSelected[ cellIdx.column ]) ) {
  15990. $( data.anCells[ cellIdx.column ] ).removeClass( ctx._select.className );
  15991. }
  15992. } );
  15993. } );
  15994. this.iterator( 'table', function ( ctx, i ) {
  15995. eventTrigger( api, 'deselect', [ 'column', api[i] ], true );
  15996. } );
  15997. return this;
  15998. } );
  15999. apiRegisterPlural( 'cells().deselect()', 'cell().deselect()', function () {
  16000. var api = this;
  16001. this.iterator( 'cell', function ( ctx, rowIdx, colIdx ) {
  16002. var data = ctx.aoData[ rowIdx ];
  16003. if(data._selected_cells !== undefined) {
  16004. data._selected_cells[ colIdx ] = false;
  16005. }
  16006. // Remove class only if the cells exist, and the cell is not column
  16007. // selected, in which case the class should remain (since it is selected
  16008. // in the column)
  16009. if ( data.anCells && ! ctx.aoColumns[ colIdx ]._select_selected ) {
  16010. $( data.anCells[ colIdx ] ).removeClass( ctx._select.className );
  16011. }
  16012. } );
  16013. this.iterator( 'table', function ( ctx, i ) {
  16014. eventTrigger( api, 'deselect', [ 'cell', api[i] ], true );
  16015. } );
  16016. return this;
  16017. } );
  16018. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  16019. * Buttons
  16020. */
  16021. function i18n( label, def ) {
  16022. return function (dt) {
  16023. return dt.i18n( 'buttons.'+label, def );
  16024. };
  16025. }
  16026. // Common events with suitable namespaces
  16027. function namespacedEvents ( config ) {
  16028. var unique = config._eventNamespace;
  16029. return 'draw.dt.DT'+unique+' select.dt.DT'+unique+' deselect.dt.DT'+unique;
  16030. }
  16031. function enabled ( dt, config ) {
  16032. if ( $.inArray( 'rows', config.limitTo ) !== -1 && dt.rows( { selected: true } ).any() ) {
  16033. return true;
  16034. }
  16035. if ( $.inArray( 'columns', config.limitTo ) !== -1 && dt.columns( { selected: true } ).any() ) {
  16036. return true;
  16037. }
  16038. if ( $.inArray( 'cells', config.limitTo ) !== -1 && dt.cells( { selected: true } ).any() ) {
  16039. return true;
  16040. }
  16041. return false;
  16042. }
  16043. var _buttonNamespace = 0;
  16044. $.extend( DataTable.ext.buttons, {
  16045. selected: {
  16046. text: i18n( 'selected', 'Selected' ),
  16047. className: 'buttons-selected',
  16048. limitTo: [ 'rows', 'columns', 'cells' ],
  16049. init: function ( dt, node, config ) {
  16050. var that = this;
  16051. config._eventNamespace = '.select'+(_buttonNamespace++);
  16052. // .DT namespace listeners are removed by DataTables automatically
  16053. // on table destroy
  16054. dt.on( namespacedEvents(config), function () {
  16055. that.enable( enabled(dt, config) );
  16056. } );
  16057. this.disable();
  16058. },
  16059. destroy: function ( dt, node, config ) {
  16060. dt.off( config._eventNamespace );
  16061. }
  16062. },
  16063. selectedSingle: {
  16064. text: i18n( 'selectedSingle', 'Selected single' ),
  16065. className: 'buttons-selected-single',
  16066. init: function ( dt, node, config ) {
  16067. var that = this;
  16068. config._eventNamespace = '.select'+(_buttonNamespace++);
  16069. dt.on( namespacedEvents(config), function () {
  16070. var count = dt.rows( { selected: true } ).flatten().length +
  16071. dt.columns( { selected: true } ).flatten().length +
  16072. dt.cells( { selected: true } ).flatten().length;
  16073. that.enable( count === 1 );
  16074. } );
  16075. this.disable();
  16076. },
  16077. destroy: function ( dt, node, config ) {
  16078. dt.off( config._eventNamespace );
  16079. }
  16080. },
  16081. selectAll: {
  16082. text: i18n( 'selectAll', 'Select all' ),
  16083. className: 'buttons-select-all',
  16084. action: function () {
  16085. var items = this.select.items();
  16086. this[ items+'s' ]().select();
  16087. }
  16088. },
  16089. selectNone: {
  16090. text: i18n( 'selectNone', 'Deselect all' ),
  16091. className: 'buttons-select-none',
  16092. action: function () {
  16093. clear( this.settings()[0], true );
  16094. },
  16095. init: function ( dt, node, config ) {
  16096. var that = this;
  16097. config._eventNamespace = '.select'+(_buttonNamespace++);
  16098. dt.on( namespacedEvents(config), function () {
  16099. var count = dt.rows( { selected: true } ).flatten().length +
  16100. dt.columns( { selected: true } ).flatten().length +
  16101. dt.cells( { selected: true } ).flatten().length;
  16102. that.enable( count > 0 );
  16103. } );
  16104. this.disable();
  16105. },
  16106. destroy: function ( dt, node, config ) {
  16107. dt.off( config._eventNamespace );
  16108. }
  16109. }
  16110. } );
  16111. $.each( [ 'Row', 'Column', 'Cell' ], function ( i, item ) {
  16112. var lc = item.toLowerCase();
  16113. DataTable.ext.buttons[ 'select'+item+'s' ] = {
  16114. text: i18n( 'select'+item+'s', 'Select '+lc+'s' ),
  16115. className: 'buttons-select-'+lc+'s',
  16116. action: function () {
  16117. this.select.items( lc );
  16118. },
  16119. init: function ( dt ) {
  16120. var that = this;
  16121. dt.on( 'selectItems.dt.DT', function ( e, ctx, items ) {
  16122. that.active( items === lc );
  16123. } );
  16124. }
  16125. };
  16126. } );
  16127. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  16128. * Initialisation
  16129. */
  16130. // DataTables creation - check if select has been defined in the options. Note
  16131. // this required that the table be in the document! If it isn't then something
  16132. // needs to trigger this method unfortunately. The next major release of
  16133. // DataTables will rework the events and address this.
  16134. $(document).on( 'preInit.dt.dtSelect', function (e, ctx) {
  16135. if ( e.namespace !== 'dt' ) {
  16136. return;
  16137. }
  16138. DataTable.select.init( new DataTable.Api( ctx ) );
  16139. } );
  16140. return DataTable.select;
  16141. }));