PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /home2/samarhoy/public_html/admin/plugins/datatables-select/js
Viewing File: /home2/samarhoy/public_html/admin/plugins/datatables-select/js/dataTables.select.js
/*! Select for DataTables 1.3.4-dev * 2015-2021 SpryMedia Ltd - datatables.net/license/mit */ /** * @summary Select for DataTables * @description A collection of API methods, events and buttons for DataTables * that provides selection options of the items in a DataTable * @version 1.3.4-dev * @file dataTables.select.js * @author SpryMedia Ltd (www.sprymedia.co.uk) * @contact datatables.net/forums * @copyright Copyright 2015-2021 SpryMedia Ltd. * * This source file is free software, available under the following license: * MIT license - http://datatables.net/license/mit * * This source file is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. * * For details please refer to: http://www.datatables.net/extensions/select */ (function( factory ){ if ( typeof define === 'function' && define.amd ) { // AMD define( ['jquery', 'datatables.net'], function ( $ ) { return factory( $, window, document ); } ); } else if ( typeof exports === 'object' ) { // CommonJS module.exports = function (root, $) { if ( ! root ) { root = window; } if ( ! $ || ! $.fn.dataTable ) { $ = require('datatables.net')(root, $).$; } return factory( $, root, root.document ); }; } else { // Browser factory( jQuery, window, document ); } }(function( $, window, document, undefined ) { 'use strict'; var DataTable = $.fn.dataTable; // Version information for debugger DataTable.select = {}; DataTable.select.version = '1.3.4-dev'; DataTable.select.init = function ( dt ) { var ctx = dt.settings()[0]; if (ctx._select) { return; } var savedSelected = dt.state.loaded(); var selectAndSave = function(e, settings, data) { if(data === null || data.select === undefined) { return; } dt.rows().deselect(); dt.columns().deselect(); dt.cells().deselect(); if (data.select.rows !== undefined) { dt.rows(data.select.rows).select(); } if (data.select.columns !== undefined) { dt.columns(data.select.columns).select(); } if (data.select.cells !== undefined) { for(var i = 0; i < data.select.cells.length; i++) { dt.cell(data.select.cells[i].row, data.select.cells[i].column).select(); } } dt.state.save(); } dt.one('init', function() { dt.on('stateSaveParams', function(e, settings, data) { data.select = {}; data.select.rows = dt.rows({selected:true}).ids(true).toArray(); data.select.columns = dt.columns({selected:true})[0]; data.select.cells = dt.cells({selected:true})[0].map(function(coords) { return {row: dt.row(coords.row).id(true), column: coords.column} }); }) selectAndSave(undefined, undefined, savedSelected) dt.on('stateLoaded stateLoadParams', selectAndSave) }) var init = ctx.oInit.select; var defaults = DataTable.defaults.select; var opts = init === undefined ? defaults : init; // Set defaults var items = 'row'; var style = 'api'; var blurable = false; var toggleable = true; var info = true; var selector = 'td, th'; var className = 'selected'; var setStyle = false; ctx._select = {}; // Initialisation customisations if ( opts === true ) { style = 'os'; setStyle = true; } else if ( typeof opts === 'string' ) { style = opts; setStyle = true; } else if ( $.isPlainObject( opts ) ) { if ( opts.blurable !== undefined ) { blurable = opts.blurable; } if ( opts.toggleable !== undefined ) { toggleable = opts.toggleable; } if ( opts.info !== undefined ) { info = opts.info; } if ( opts.items !== undefined ) { items = opts.items; } if ( opts.style !== undefined ) { style = opts.style; setStyle = true; } else { style = 'os'; setStyle = true; } if ( opts.selector !== undefined ) { selector = opts.selector; } if ( opts.className !== undefined ) { className = opts.className; } } dt.select.selector( selector ); dt.select.items( items ); dt.select.style( style ); dt.select.blurable( blurable ); dt.select.toggleable( toggleable ); dt.select.info( info ); ctx._select.className = className; // Sort table based on selected rows. Requires Select Datatables extension $.fn.dataTable.ext.order['select-checkbox'] = function ( settings, col ) { return this.api().column( col, {order: 'index'} ).nodes().map( function ( td ) { if ( settings._select.items === 'row' ) { return $( td ).parent().hasClass( settings._select.className ); } else if ( settings._select.items === 'cell' ) { return $( td ).hasClass( settings._select.className ); } return false; }); }; // If the init options haven't enabled select, but there is a selectable // class name, then enable if ( ! setStyle && $( dt.table().node() ).hasClass( 'selectable' ) ) { dt.select.style( 'os' ); } }; /* Select is a collection of API methods, event handlers, event emitters and buttons (for the `Buttons` extension) for DataTables. It provides the following features, with an overview of how they are implemented: ## Selection of rows, columns and cells. Whether an item is selected or not is stored in: * rows: a `_select_selected` property which contains a boolean value of the DataTables' `aoData` object for each row * columns: a `_select_selected` property which contains a boolean value of the DataTables' `aoColumns` object for each column * cells: a `_selected_cells` property which contains an array of boolean values of the `aoData` object for each row. The array is the same length as the columns array, with each element of it representing a cell. This method of using boolean flags allows Select to operate when nodes have not been created for rows / cells (DataTables' defer rendering feature). ## API methods A range of API methods are available for triggering selection and de-selection of rows. Methods are also available to configure the selection events that can be triggered by an end user (such as which items are to be selected). To a large extent, these of API methods *is* Select. It is basically a collection of helper functions that can be used to select items in a DataTable. Configuration of select is held in the object `_select` which is attached to the DataTables settings object on initialisation. Select being available on a table is not optional when Select is loaded, but its default is for selection only to be available via the API - so the end user wouldn't be able to select rows without additional configuration. The `_select` object contains the following properties: ``` { items:string - Can be `rows`, `columns` or `cells`. Defines what item will be selected if the user is allowed to activate row selection using the mouse. style:string - Can be `none`, `single`, `multi` or `os`. Defines the interaction style when selecting items blurable:boolean - If row selection can be cleared by clicking outside of the table toggleable:boolean - If row selection can be cancelled by repeated clicking on the row info:boolean - If the selection summary should be shown in the table information elements } ``` In addition to the API methods, Select also extends the DataTables selector options for rows, columns and cells adding a `selected` option to the selector options object, allowing the developer to select only selected items or unselected items. ## Mouse selection of items Clicking on items can be used to select items. This is done by a simple event handler that will select the items using the API methods. */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Local functions */ /** * Add one or more cells to the selection when shift clicking in OS selection * style cell selection. * * Cell range is more complicated than row and column as we want to select * in the visible grid rather than by index in sequence. For example, if you * click first in cell 1-1 and then shift click in 2-2 - cells 1-2 and 2-1 * should also be selected (and not 1-3, 1-4. etc) * * @param {DataTable.Api} dt DataTable * @param {object} idx Cell index to select to * @param {object} last Cell index to select from * @private */ function cellRange( dt, idx, last ) { var indexes; var columnIndexes; var rowIndexes; var selectColumns = function ( start, end ) { if ( start > end ) { var tmp = end; end = start; start = tmp; } var record = false; return dt.columns( ':visible' ).indexes().filter( function (i) { if ( i === start ) { record = true; } if ( i === end ) { // not else if, as start might === end record = false; return true; } return record; } ); }; var selectRows = function ( start, end ) { var indexes = dt.rows( { search: 'applied' } ).indexes(); // Which comes first - might need to swap if ( indexes.indexOf( start ) > indexes.indexOf( end ) ) { var tmp = end; end = start; start = tmp; } var record = false; return indexes.filter( function (i) { if ( i === start ) { record = true; } if ( i === end ) { record = false; return true; } return record; } ); }; if ( ! dt.cells( { selected: true } ).any() && ! last ) { // select from the top left cell to this one columnIndexes = selectColumns( 0, idx.column ); rowIndexes = selectRows( 0 , idx.row ); } else { // Get column indexes between old and new columnIndexes = selectColumns( last.column, idx.column ); rowIndexes = selectRows( last.row , idx.row ); } indexes = dt.cells( rowIndexes, columnIndexes ).flatten(); if ( ! dt.cells( idx, { selected: true } ).any() ) { // Select range dt.cells( indexes ).select(); } else { // Deselect range dt.cells( indexes ).deselect(); } } /** * Disable mouse selection by removing the selectors * * @param {DataTable.Api} dt DataTable to remove events from * @private */ function disableMouseSelection( dt ) { var ctx = dt.settings()[0]; var selector = ctx._select.selector; $( dt.table().container() ) .off( 'mousedown.dtSelect', selector ) .off( 'mouseup.dtSelect', selector ) .off( 'click.dtSelect', selector ); $('body').off( 'click.dtSelect' + _safeId(dt.table().node()) ); } /** * Attach mouse listeners to the table to allow mouse selection of items * * @param {DataTable.Api} dt DataTable to remove events from * @private */ function enableMouseSelection ( dt ) { var container = $( dt.table().container() ); var ctx = dt.settings()[0]; var selector = ctx._select.selector; var matchSelection; container .on( 'mousedown.dtSelect', selector, function(e) { // Disallow text selection for shift clicking on the table so multi // element selection doesn't look terrible! if ( e.shiftKey || e.metaKey || e.ctrlKey ) { container .css( '-moz-user-select', 'none' ) .one('selectstart.dtSelect', selector, function () { return false; } ); } if ( window.getSelection ) { matchSelection = window.getSelection(); } } ) .on( 'mouseup.dtSelect', selector, function() { // Allow text selection to occur again, Mozilla style (tested in FF // 35.0.1 - still required) container.css( '-moz-user-select', '' ); } ) .on( 'click.dtSelect', selector, function ( e ) { var items = dt.select.items(); var idx; // If text was selected (click and drag), then we shouldn't change // the row's selected state if ( matchSelection ) { var selection = window.getSelection(); // If the element that contains the selection is not in the table, we can ignore it // This can happen if the developer selects text from the click event if ( ! selection.anchorNode || $(selection.anchorNode).closest('table')[0] === dt.table().node() ) { if ( selection !== matchSelection ) { return; } } } var ctx = dt.settings()[0]; var wrapperClass = dt.settings()[0].oClasses.sWrapper.trim().replace(/ +/g, '.'); // Ignore clicks inside a sub-table if ( $(e.target).closest('div.'+wrapperClass)[0] != dt.table().container() ) { return; } var cell = dt.cell( $(e.target).closest('td, th') ); // Check the cell actually belongs to the host DataTable (so child // rows, etc, are ignored) if ( ! cell.any() ) { return; } var event = $.Event('user-select.dt'); eventTrigger( dt, event, [ items, cell, e ] ); if ( event.isDefaultPrevented() ) { return; } var cellIndex = cell.index(); if ( items === 'row' ) { idx = cellIndex.row; typeSelect( e, dt, ctx, 'row', idx ); } else if ( items === 'column' ) { idx = cell.index().column; typeSelect( e, dt, ctx, 'column', idx ); } else if ( items === 'cell' ) { idx = cell.index(); typeSelect( e, dt, ctx, 'cell', idx ); } ctx._select_lastCell = cellIndex; } ); // Blurable $('body').on( 'click.dtSelect' + _safeId(dt.table().node()), function ( e ) { if ( ctx._select.blurable ) { // If the click was inside the DataTables container, don't blur if ( $(e.target).parents().filter( dt.table().container() ).length ) { return; } // Ignore elements which have been removed from the DOM (i.e. paging // buttons) if ( $(e.target).parents('html').length === 0 ) { return; } // Don't blur in Editor form if ( $(e.target).parents('div.DTE').length ) { return; } clear( ctx, true ); } } ); } /** * Trigger an event on a DataTable * * @param {DataTable.Api} api DataTable to trigger events on * @param {boolean} selected true if selected, false if deselected * @param {string} type Item type acting on * @param {boolean} any Require that there are values before * triggering * @private */ function eventTrigger ( api, type, args, any ) { if ( any && ! api.flatten().length ) { return; } if ( typeof type === 'string' ) { type = type +'.dt'; } args.unshift( api ); $(api.table().node()).trigger( type, args ); } /** * Update the information element of the DataTable showing information about the * items selected. This is done by adding tags to the existing text * * @param {DataTable.Api} api DataTable to update * @private */ function info ( api ) { var ctx = api.settings()[0]; if ( ! ctx._select.info || ! ctx.aanFeatures.i ) { return; } if ( api.select.style() === 'api' ) { return; } var rows = api.rows( { selected: true } ).flatten().length; var columns = api.columns( { selected: true } ).flatten().length; var cells = api.cells( { selected: true } ).flatten().length; var add = function ( el, name, num ) { el.append( $('<span class="select-item"/>').append( api.i18n( 'select.'+name+'s', { _: '%d '+name+'s selected', 0: '', 1: '1 '+name+' selected' }, num ) ) ); }; // Internal knowledge of DataTables to loop over all information elements $.each( ctx.aanFeatures.i, function ( i, el ) { el = $(el); var output = $('<span class="select-info"/>'); add( output, 'row', rows ); add( output, 'column', columns ); add( output, 'cell', cells ); var exisiting = el.children('span.select-info'); if ( exisiting.length ) { exisiting.remove(); } if ( output.text() !== '' ) { el.append( output ); } } ); } /** * Initialisation of a new table. Attach event handlers and callbacks to allow * Select to operate correctly. * * This will occur _after_ the initial DataTables initialisation, although * before Ajax data is rendered, if there is ajax data * * @param {DataTable.settings} ctx Settings object to operate on * @private */ function init ( ctx ) { var api = new DataTable.Api( ctx ); ctx._select_init = true; // Row callback so that classes can be added to rows and cells if the item // was selected before the element was created. This will happen with the // `deferRender` option enabled. // // This method of attaching to `aoRowCreatedCallback` is a hack until // DataTables has proper events for row manipulation If you are reviewing // this code to create your own plug-ins, please do not do this! ctx.aoRowCreatedCallback.push( { fn: function ( row, data, index ) { var i, ien; var d = ctx.aoData[ index ]; // Row if ( d._select_selected ) { $( row ).addClass( ctx._select.className ); } // Cells and columns - if separated out, we would need to do two // loops, so it makes sense to combine them into a single one for ( i=0, ien=ctx.aoColumns.length ; i<ien ; i++ ) { if ( ctx.aoColumns[i]._select_selected || (d._selected_cells && d._selected_cells[i]) ) { $(d.anCells[i]).addClass( ctx._select.className ); } } }, sName: 'select-deferRender' } ); // On Ajax reload we want to reselect all rows which are currently selected, // if there is an rowId (i.e. a unique value to identify each row with) api.on( 'preXhr.dt.dtSelect', function (e, settings) { if (settings !== api.settings()[0]) { // Not triggered by our DataTable! return; } // note that column selection doesn't need to be cached and then // reselected, as they are already selected var rows = api.rows( { selected: true } ).ids( true ).filter( function ( d ) { return d !== undefined; } ); var cells = api.cells( { selected: true } ).eq(0).map( function ( cellIdx ) { var id = api.row( cellIdx.row ).id( true ); return id ? { row: id, column: cellIdx.column } : undefined; } ).filter( function ( d ) { return d !== undefined; } ); // On the next draw, reselect the currently selected items api.one( 'draw.dt.dtSelect', function () { api.rows( rows ).select(); // `cells` is not a cell index selector, so it needs a loop if ( cells.any() ) { cells.each( function ( id ) { api.cells( id.row, id.column ).select(); } ); } } ); } ); // Update the table information element with selected item summary api.on( 'draw.dtSelect.dt select.dtSelect.dt deselect.dtSelect.dt info.dt', function () { info( api ); api.state.save(); } ); // Clean up and release api.on( 'destroy.dtSelect', function () { api.rows({selected: true}).deselect(); disableMouseSelection( api ); api.off( '.dtSelect' ); $('body').off('.dtSelect' + _safeId(api.table().node())); } ); } /** * Add one or more items (rows or columns) to the selection when shift clicking * in OS selection style * * @param {DataTable.Api} dt DataTable * @param {string} type Row or column range selector * @param {object} idx Item index to select to * @param {object} last Item index to select from * @private */ function rowColumnRange( dt, type, idx, last ) { // Add a range of rows from the last selected row to this one var indexes = dt[type+'s']( { search: 'applied' } ).indexes(); var idx1 = $.inArray( last, indexes ); var idx2 = $.inArray( idx, indexes ); if ( ! dt[type+'s']( { selected: true } ).any() && idx1 === -1 ) { // select from top to here - slightly odd, but both Windows and Mac OS // do this indexes.splice( $.inArray( idx, indexes )+1, indexes.length ); } else { // reverse so we can shift click 'up' as well as down if ( idx1 > idx2 ) { var tmp = idx2; idx2 = idx1; idx1 = tmp; } indexes.splice( idx2+1, indexes.length ); indexes.splice( 0, idx1 ); } if ( ! dt[type]( idx, { selected: true } ).any() ) { // Select range dt[type+'s']( indexes ).select(); } else { // Deselect range - need to keep the clicked on row selected indexes.splice( $.inArray( idx, indexes ), 1 ); dt[type+'s']( indexes ).deselect(); } } /** * Clear all selected items * * @param {DataTable.settings} ctx Settings object of the host DataTable * @param {boolean} [force=false] Force the de-selection to happen, regardless * of selection style * @private */ function clear( ctx, force ) { if ( force || ctx._select.style === 'single' ) { var api = new DataTable.Api( ctx ); api.rows( { selected: true } ).deselect(); api.columns( { selected: true } ).deselect(); api.cells( { selected: true } ).deselect(); } } /** * Select items based on the current configuration for style and items. * * @param {object} e Mouse event object * @param {DataTables.Api} dt DataTable * @param {DataTable.settings} ctx Settings object of the host DataTable * @param {string} type Items to select * @param {int|object} idx Index of the item to select * @private */ function typeSelect ( e, dt, ctx, type, idx ) { var style = dt.select.style(); var toggleable = dt.select.toggleable(); var isSelected = dt[type]( idx, { selected: true } ).any(); if ( isSelected && ! toggleable ) { return; } if ( style === 'os' ) { if ( e.ctrlKey || e.metaKey ) { // Add or remove from the selection dt[type]( idx ).select( ! isSelected ); } else if ( e.shiftKey ) { if ( type === 'cell' ) { cellRange( dt, idx, ctx._select_lastCell || null ); } else { rowColumnRange( dt, type, idx, ctx._select_lastCell ? ctx._select_lastCell[type] : null ); } } else { // No cmd or shift click - deselect if selected, or select // this row only var selected = dt[type+'s']( { selected: true } ); if ( isSelected && selected.flatten().length === 1 ) { dt[type]( idx ).deselect(); } else { selected.deselect(); dt[type]( idx ).select(); } } } else if ( style == 'multi+shift' ) { if ( e.shiftKey ) { if ( type === 'cell' ) { cellRange( dt, idx, ctx._select_lastCell || null ); } else { rowColumnRange( dt, type, idx, ctx._select_lastCell ? ctx._select_lastCell[type] : null ); } } else { dt[ type ]( idx ).select( ! isSelected ); } } else { dt[ type ]( idx ).select( ! isSelected ); } } function _safeId( node ) { return node.id.replace(/[^a-zA-Z0-9\-\_]/g, '-'); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DataTables selectors */ // row and column are basically identical just assigned to different properties // and checking a different array, so we can dynamically create the functions to // reduce the code size $.each( [ { type: 'row', prop: 'aoData' }, { type: 'column', prop: 'aoColumns' } ], function ( i, o ) { DataTable.ext.selector[ o.type ].push( function ( settings, opts, indexes ) { var selected = opts.selected; var data; var out = []; if ( selected !== true && selected !== false ) { return indexes; } for ( var i=0, ien=indexes.length ; i<ien ; i++ ) { data = settings[ o.prop ][ indexes[i] ]; if ( (selected === true && data._select_selected === true) || (selected === false && ! data._select_selected ) ) { out.push( indexes[i] ); } } return out; } ); } ); DataTable.ext.selector.cell.push( function ( settings, opts, cells ) { var selected = opts.selected; var rowData; var out = []; if ( selected === undefined ) { return cells; } for ( var i=0, ien=cells.length ; i<ien ; i++ ) { rowData = settings.aoData[ cells[i].row ]; if ( (selected === true && rowData._selected_cells && rowData._selected_cells[ cells[i].column ] === true) || (selected === false && ( ! rowData._selected_cells || ! rowData._selected_cells[ cells[i].column ] ) ) ) { out.push( cells[i] ); } } return out; } ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DataTables API * * For complete documentation, please refer to the docs/api directory or the * DataTables site */ // Local variables to improve compression var apiRegister = DataTable.Api.register; var apiRegisterPlural = DataTable.Api.registerPlural; apiRegister( 'select()', function () { return this.iterator( 'table', function ( ctx ) { DataTable.select.init( new DataTable.Api( ctx ) ); } ); } ); apiRegister( 'select.blurable()', function ( flag ) { if ( flag === undefined ) { return this.context[0]._select.blurable; } return this.iterator( 'table', function ( ctx ) { ctx._select.blurable = flag; } ); } ); apiRegister( 'select.toggleable()', function ( flag ) { if ( flag === undefined ) { return this.context[0]._select.toggleable; } return this.iterator( 'table', function ( ctx ) { ctx._select.toggleable = flag; } ); } ); apiRegister( 'select.info()', function ( flag ) { if ( flag === undefined ) { return this.context[0]._select.info; } return this.iterator( 'table', function ( ctx ) { ctx._select.info = flag; } ); } ); apiRegister( 'select.items()', function ( items ) { if ( items === undefined ) { return this.context[0]._select.items; } return this.iterator( 'table', function ( ctx ) { ctx._select.items = items; eventTrigger( new DataTable.Api( ctx ), 'selectItems', [ items ] ); } ); } ); // Takes effect from the _next_ selection. None disables future selection, but // does not clear the current selection. Use the `deselect` methods for that apiRegister( 'select.style()', function ( style ) { if ( style === undefined ) { return this.context[0]._select.style; } return this.iterator( 'table', function ( ctx ) { if ( ! ctx._select ) { DataTable.select.init( new DataTable.Api(ctx) ); } if ( ! ctx._select_init ) { init(ctx); } ctx._select.style = style; // Add / remove mouse event handlers. They aren't required when only // API selection is available var dt = new DataTable.Api( ctx ); disableMouseSelection( dt ); if ( style !== 'api' ) { enableMouseSelection( dt ); } eventTrigger( new DataTable.Api( ctx ), 'selectStyle', [ style ] ); } ); } ); apiRegister( 'select.selector()', function ( selector ) { if ( selector === undefined ) { return this.context[0]._select.selector; } return this.iterator( 'table', function ( ctx ) { disableMouseSelection( new DataTable.Api( ctx ) ); ctx._select.selector = selector; if ( ctx._select.style !== 'api' ) { enableMouseSelection( new DataTable.Api( ctx ) ); } } ); } ); apiRegisterPlural( 'rows().select()', 'row().select()', function ( select ) { var api = this; if ( select === false ) { return this.deselect(); } this.iterator( 'row', function ( ctx, idx ) { clear( ctx ); ctx.aoData[ idx ]._select_selected = true; $( ctx.aoData[ idx ].nTr ).addClass( ctx._select.className ); } ); this.iterator( 'table', function ( ctx, i ) { eventTrigger( api, 'select', [ 'row', api[i] ], true ); } ); return this; } ); apiRegisterPlural( 'columns().select()', 'column().select()', function ( select ) { var api = this; if ( select === false ) { return this.deselect(); } this.iterator( 'column', function ( ctx, idx ) { clear( ctx ); ctx.aoColumns[ idx ]._select_selected = true; var column = new DataTable.Api( ctx ).column( idx ); $( column.header() ).addClass( ctx._select.className ); $( column.footer() ).addClass( ctx._select.className ); column.nodes().to$().addClass( ctx._select.className ); } ); this.iterator( 'table', function ( ctx, i ) { eventTrigger( api, 'select', [ 'column', api[i] ], true ); } ); return this; } ); apiRegisterPlural( 'cells().select()', 'cell().select()', function ( select ) { var api = this; if ( select === false ) { return this.deselect(); } this.iterator( 'cell', function ( ctx, rowIdx, colIdx ) { clear( ctx ); var data = ctx.aoData[ rowIdx ]; if ( data._selected_cells === undefined ) { data._selected_cells = []; } data._selected_cells[ colIdx ] = true; if ( data.anCells ) { $( data.anCells[ colIdx ] ).addClass( ctx._select.className ); } } ); this.iterator( 'table', function ( ctx, i ) { eventTrigger( api, 'select', [ 'cell', api.cells(api[i]).indexes().toArray() ], true ); } ); return this; } ); apiRegisterPlural( 'rows().deselect()', 'row().deselect()', function () { var api = this; this.iterator( 'row', function ( ctx, idx ) { ctx.aoData[ idx ]._select_selected = false; ctx._select_lastCell = null; $( ctx.aoData[ idx ].nTr ).removeClass( ctx._select.className ); } ); this.iterator( 'table', function ( ctx, i ) { eventTrigger( api, 'deselect', [ 'row', api[i] ], true ); } ); return this; } ); apiRegisterPlural( 'columns().deselect()', 'column().deselect()', function () { var api = this; this.iterator( 'column', function ( ctx, idx ) { ctx.aoColumns[ idx ]._select_selected = false; var api = new DataTable.Api( ctx ); var column = api.column( idx ); $( column.header() ).removeClass( ctx._select.className ); $( column.footer() ).removeClass( ctx._select.className ); // Need to loop over each cell, rather than just using // `column().nodes()` as cells which are individually selected should // not have the `selected` class removed from them api.cells( null, idx ).indexes().each( function (cellIdx) { var data = ctx.aoData[ cellIdx.row ]; var cellSelected = data._selected_cells; if ( data.anCells && (! cellSelected || ! cellSelected[ cellIdx.column ]) ) { $( data.anCells[ cellIdx.column ] ).removeClass( ctx._select.className ); } } ); } ); this.iterator( 'table', function ( ctx, i ) { eventTrigger( api, 'deselect', [ 'column', api[i] ], true ); } ); return this; } ); apiRegisterPlural( 'cells().deselect()', 'cell().deselect()', function () { var api = this; this.iterator( 'cell', function ( ctx, rowIdx, colIdx ) { var data = ctx.aoData[ rowIdx ]; if(data._selected_cells !== undefined) { data._selected_cells[ colIdx ] = false; } // Remove class only if the cells exist, and the cell is not column // selected, in which case the class should remain (since it is selected // in the column) if ( data.anCells && ! ctx.aoColumns[ colIdx ]._select_selected ) { $( data.anCells[ colIdx ] ).removeClass( ctx._select.className ); } } ); this.iterator( 'table', function ( ctx, i ) { eventTrigger( api, 'deselect', [ 'cell', api[i] ], true ); } ); return this; } ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Buttons */ function i18n( label, def ) { return function (dt) { return dt.i18n( 'buttons.'+label, def ); }; } // Common events with suitable namespaces function namespacedEvents ( config ) { var unique = config._eventNamespace; return 'draw.dt.DT'+unique+' select.dt.DT'+unique+' deselect.dt.DT'+unique; } function enabled ( dt, config ) { if ( $.inArray( 'rows', config.limitTo ) !== -1 && dt.rows( { selected: true } ).any() ) { return true; } if ( $.inArray( 'columns', config.limitTo ) !== -1 && dt.columns( { selected: true } ).any() ) { return true; } if ( $.inArray( 'cells', config.limitTo ) !== -1 && dt.cells( { selected: true } ).any() ) { return true; } return false; } var _buttonNamespace = 0; $.extend( DataTable.ext.buttons, { selected: { text: i18n( 'selected', 'Selected' ), className: 'buttons-selected', limitTo: [ 'rows', 'columns', 'cells' ], init: function ( dt, node, config ) { var that = this; config._eventNamespace = '.select'+(_buttonNamespace++); // .DT namespace listeners are removed by DataTables automatically // on table destroy dt.on( namespacedEvents(config), function () { that.enable( enabled(dt, config) ); } ); this.disable(); }, destroy: function ( dt, node, config ) { dt.off( config._eventNamespace ); } }, selectedSingle: { text: i18n( 'selectedSingle', 'Selected single' ), className: 'buttons-selected-single', init: function ( dt, node, config ) { var that = this; config._eventNamespace = '.select'+(_buttonNamespace++); dt.on( namespacedEvents(config), function () { var count = dt.rows( { selected: true } ).flatten().length + dt.columns( { selected: true } ).flatten().length + dt.cells( { selected: true } ).flatten().length; that.enable( count === 1 ); } ); this.disable(); }, destroy: function ( dt, node, config ) { dt.off( config._eventNamespace ); } }, selectAll: { text: i18n( 'selectAll', 'Select all' ), className: 'buttons-select-all', action: function () { var items = this.select.items(); this[ items+'s' ]().select(); } }, selectNone: { text: i18n( 'selectNone', 'Deselect all' ), className: 'buttons-select-none', action: function () { clear( this.settings()[0], true ); }, init: function ( dt, node, config ) { var that = this; config._eventNamespace = '.select'+(_buttonNamespace++); dt.on( namespacedEvents(config), function () { var count = dt.rows( { selected: true } ).flatten().length + dt.columns( { selected: true } ).flatten().length + dt.cells( { selected: true } ).flatten().length; that.enable( count > 0 ); } ); this.disable(); }, destroy: function ( dt, node, config ) { dt.off( config._eventNamespace ); } } } ); $.each( [ 'Row', 'Column', 'Cell' ], function ( i, item ) { var lc = item.toLowerCase(); DataTable.ext.buttons[ 'select'+item+'s' ] = { text: i18n( 'select'+item+'s', 'Select '+lc+'s' ), className: 'buttons-select-'+lc+'s', action: function () { this.select.items( lc ); }, init: function ( dt ) { var that = this; dt.on( 'selectItems.dt.DT', function ( e, ctx, items ) { that.active( items === lc ); } ); } }; } ); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Initialisation */ // DataTables creation - check if select has been defined in the options. Note // this required that the table be in the document! If it isn't then something // needs to trigger this method unfortunately. The next major release of // DataTables will rework the events and address this. $(document).on( 'preInit.dt.dtSelect', function (e, ctx) { if ( e.namespace !== 'dt' ) { return; } DataTable.select.init( new DataTable.Api( ctx ) ); } ); return DataTable.select; }));