tablefilter.js 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217
  1. /*====================================================
  2. - HTML Table Filter Generator v1.6
  3. - By Max Guglielmi
  4. - mguglielmi.free.fr/scripts/TableFilter/?l=en
  5. - please do not change this comment
  6. - don't forget to give some credit... it's always
  7. good for the author
  8. - Special credit to Cedric Wartel and
  9. cnx.claude@free.fr for contribution and
  10. inspiration
  11. =====================================================*/
  12. // global vars
  13. var TblId, SearchFlt, SlcArgs;
  14. TblId = new Array(), SlcArgs = new Array();
  15. function setFilterGrid(id)
  16. /*====================================================
  17. - Checks if id exists and is a table
  18. - Then looks for additional params
  19. - Calls fn that generates the grid
  20. =====================================================*/
  21. {
  22. var tbl = grabEBI(id);
  23. var ref_row, fObj;
  24. if(tbl != null && tbl.nodeName.toLowerCase() == "table")
  25. {
  26. if(arguments.length>1)
  27. {
  28. for(var i=0; i<arguments.length; i++)
  29. {
  30. var argtype = typeof arguments[i];
  31. switch(argtype.toLowerCase())
  32. {
  33. case "number":
  34. ref_row = arguments[i];
  35. break;
  36. case "object":
  37. fObj = arguments[i];
  38. break;
  39. }//switch
  40. }//for
  41. }//if
  42. ref_row == undefined ? ref_row=2 : ref_row=(ref_row+2);
  43. var ncells = getCellsNb(id,ref_row);
  44. tbl.tf_ncells = ncells;
  45. if(tbl.tf_ref_row==undefined) tbl.tf_ref_row = ref_row;
  46. tbl.tf_Obj = fObj;
  47. if( !hasGrid(id) ) AddGrid(id);
  48. }//if tbl!=null
  49. }
  50. function AddGrid(id)
  51. /*====================================================
  52. - adds a row containing the filtering grid
  53. =====================================================*/
  54. {
  55. TblId.push(id);
  56. var t = grabEBI(id);
  57. var f = t.tf_Obj, n = t.tf_ncells;
  58. var inpclass, fltgrid, displayBtn, btntext, enterkey;
  59. var modfilter_fn, display_allText, on_slcChange;
  60. var displaynrows, totrows_text, btnreset, btnreset_text;
  61. var sort_slc, displayPaging, pagingLength, displayLoader;
  62. var load_text, exactMatch, alternateBgs, colOperation;
  63. var rowVisibility, colWidth, bindScript;
  64. f!=undefined && f["grid"]==false ? fltgrid=false : fltgrid=true;//enables/disables filter grid
  65. f!=undefined && f["btn"]==true ? displayBtn=true : displayBtn=false;//show/hides filter's validation button
  66. f!=undefined && f["btn_text"]!=undefined ? btntext=f["btn_text"] : btntext="go";//defines button text
  67. f!=undefined && f["enter_key"]==false ? enterkey=false : enterkey=true;//enables/disables enter key
  68. f!=undefined && f["mod_filter_fn"] ? modfilter_fn=true : modfilter_fn=false;//defines alternative fn
  69. f!=undefined && f["display_all_text"]!=undefined ? display_allText=f["display_all_text"] : display_allText="";//defines 1st option text
  70. f!=undefined && f["on_change"]==false ? on_slcChange=false : on_slcChange=true;//enables/disables onChange event on combo-box
  71. f!=undefined && f["rows_counter"]==true ? displaynrows=true : displaynrows=false;//show/hides rows counter
  72. f!=undefined && f["rows_counter_text"]!=undefined ? totrows_text=f["rows_counter_text"] : totrows_text="Displayed rows: ";//defines rows counter text
  73. f!=undefined && f["btn_reset"]==true ? btnreset=true : btnreset=false;//show/hides reset link
  74. f!=undefined && f["btn_reset_text"]!=undefined ? btnreset_text=f["btn_reset_text"] : btnreset_text="Reset";//defines reset text
  75. f!=undefined && f["sort_select"]==true ? sort_slc=true : sort_slc=false;//enables/disables select options sorting
  76. f!=undefined && f["paging"]==true ? displayPaging=true : displayPaging=false;//enables/disables table paging
  77. f!=undefined && f["paging_length"]!=undefined ? pagingLength=f["paging_length"] : pagingLength=10;//defines table paging length
  78. f!=undefined && f["loader"]==true ? displayLoader=true : displayLoader=false;//enables/disables loader
  79. f!=undefined && f["loader_text"]!=undefined ? load_text=f["loader_text"] : load_text="Loading...";//defines loader text
  80. f!=undefined && f["exact_match"]==true ? exactMatch=true : exactMatch=false;//enables/disbles exact match for search
  81. f!=undefined && f["alternate_rows"]==true ? alternateBgs=true : alternateBgs=false;//enables/disbles rows alternating bg colors
  82. f!=undefined && f["col_operation"] ? colOperation=true : colOperation=false;//enables/disbles column operation(sum,mean)
  83. f!=undefined && f["rows_always_visible"] ? rowVisibility=true : rowVisibility=false;//makes a row always visible
  84. f!=undefined && f["col_width"] ? colWidth=true : colWidth=false;//defines widths of columns
  85. f!=undefined && f["bind_script"] ? bindScript=true : bindScript=false;
  86. // props are added to table in order to be easily accessible from other fns
  87. t.tf_fltGrid = fltgrid;
  88. t.tf_displayBtn = displayBtn;
  89. t.tf_btnText = btntext;
  90. t.tf_enterKey = enterkey;
  91. t.tf_isModfilter_fn = modfilter_fn;
  92. t.tf_display_allText = display_allText;
  93. t.tf_on_slcChange = on_slcChange;
  94. t.tf_rowsCounter = displaynrows;
  95. t.tf_rowsCounter_text = totrows_text;
  96. t.tf_btnReset = btnreset;
  97. t.tf_btnReset_text = btnreset_text;
  98. t.tf_sortSlc = sort_slc;
  99. t.tf_displayPaging = displayPaging;
  100. t.tf_pagingLength = pagingLength;
  101. t.tf_displayLoader = displayLoader;
  102. t.tf_loadText = load_text;
  103. t.tf_exactMatch = exactMatch;
  104. t.tf_alternateBgs = alternateBgs;
  105. t.tf_startPagingRow = 0;
  106. if(modfilter_fn) t.tf_modfilter_fn = f["mod_filter_fn"];// used by DetectKey fn
  107. if(fltgrid)
  108. {
  109. var fltrow = t.insertRow(0); //adds filter row
  110. fltrow.className = "fltrow";
  111. for(var i=0; i<n; i++)// this loop adds filters
  112. {
  113. var fltcell = fltrow.insertCell(i);
  114. //fltcell.noWrap = true;
  115. i==n-1 && displayBtn==true ? inpclass = "flt_s" : inpclass = "flt";
  116. if(f==undefined || f["col_"+i]==undefined || f["col_"+i]=="none")
  117. {
  118. var inptype;
  119. (f==undefined || f["col_"+i]==undefined) ? inptype="text" : inptype="hidden";//show/hide input
  120. var inp = createElm( "input",["id","flt"+i+"_"+id],["type",inptype],["class",inpclass] );
  121. inp.className = inpclass;// for ie<=6
  122. fltcell.appendChild(inp);
  123. if(enterkey) inp.onkeypress = DetectKey;
  124. }
  125. else if(f["col_"+i]=="select")
  126. {
  127. var slc = createElm( "select",["id","flt"+i+"_"+id],["class",inpclass] );
  128. slc.className = inpclass;// for ie<=6
  129. fltcell.appendChild(slc);
  130. PopulateOptions(id,i);
  131. if(displayPaging)//stores arguments for GroupByPage() fn
  132. {
  133. var args = new Array();
  134. args.push(id); args.push(i); args.push(n);
  135. args.push(display_allText); args.push(sort_slc); args.push(displayPaging);
  136. SlcArgs.push(args);
  137. }
  138. if(enterkey) slc.onkeypress = DetectKey;
  139. if(on_slcChange)
  140. {
  141. (!modfilter_fn) ? slc.onchange = function(){ Filter(id); } : slc.onchange = f["mod_filter_fn"];
  142. }
  143. }
  144. if(i==n-1 && displayBtn==true)// this adds button
  145. {
  146. var btn = createElm(
  147. "input",
  148. ["id","btn"+i+"_"+id],["type","button"],
  149. ["value",btntext],["class","btnflt"]
  150. );
  151. btn.className = "btnflt";
  152. fltcell.appendChild(btn);
  153. (!modfilter_fn) ? btn.onclick = function(){ Filter(id); } : btn.onclick = f["mod_filter_fn"];
  154. }//if
  155. }// for i
  156. }//if fltgrid
  157. if(displaynrows || btnreset || displayPaging || displayLoader)
  158. {
  159. /*** div containing rows # displayer + reset btn ***/
  160. var infdiv = createElm( "div",["id","inf_"+id],["class","inf"] );
  161. infdiv.className = "inf";// setAttribute method for class attribute doesn't seem to work on ie<=6
  162. t.parentNode.insertBefore(infdiv, t);
  163. if(displaynrows)
  164. {
  165. /*** left div containing rows # displayer ***/
  166. var totrows;
  167. var ldiv = createElm( "div",["id","ldiv_"+id] );
  168. displaynrows ? ldiv.className = "ldiv" : ldiv.style.display = "none";
  169. displayPaging ? totrows = pagingLength : totrows = getRowsNb(id);
  170. var totrows_span = createElm( "span",["id","totrows_span_"+id],["class","tot"] ); // tot # of rows displayer
  171. totrows_span.className = "tot";//for ie<=6
  172. totrows_span.appendChild( createText(totrows) );
  173. var totrows_txt = createText(totrows_text);
  174. ldiv.appendChild(totrows_txt);
  175. ldiv.appendChild(totrows_span);
  176. infdiv.appendChild(ldiv);
  177. }
  178. if(displayLoader)
  179. {
  180. /*** div containing loader ***/
  181. var loaddiv = createElm( "div",["id","load_"+id],["class","loader"] );
  182. loaddiv.className = "loader";// for ie<=6
  183. loaddiv.style.display = "none";
  184. loaddiv.appendChild( createText(load_text) );
  185. infdiv.appendChild(loaddiv);
  186. }
  187. if(displayPaging)
  188. {
  189. /*** mid div containing paging displayer ***/
  190. var mdiv = createElm( "div",["id","mdiv_"+id] );
  191. displayPaging ? mdiv.className = "mdiv" : mdiv.style.display = "none";
  192. infdiv.appendChild(mdiv);
  193. var start_row = t.tf_ref_row;
  194. var row = grabTag(t,"tr");
  195. var nrows = row.length;
  196. var npages = Math.ceil( (nrows - start_row)/pagingLength );//calculates page nb
  197. var slcPages = createElm( "select",["id","slcPages_"+id] );
  198. slcPages.onchange = function(){
  199. if(displayLoader) showLoader(id,"");
  200. t.tf_startPagingRow = this.value;
  201. GroupByPage(id);
  202. if(displayLoader) showLoader(id,"none");
  203. }
  204. var pgspan = createElm( "span",["id","pgspan_"+id] );
  205. grabEBI("mdiv_"+id).appendChild( createText(" Page ") );
  206. grabEBI("mdiv_"+id).appendChild(slcPages);
  207. grabEBI("mdiv_"+id).appendChild( createText(" of ") );
  208. pgspan.appendChild( createText(npages+" ") );
  209. grabEBI("mdiv_"+id).appendChild(pgspan);
  210. for(var j=start_row; j<nrows; j++)//this sets rows to validRow=true
  211. {
  212. row[j].setAttribute("validRow","true");
  213. }//for j
  214. setPagingInfo(id);
  215. if(displayLoader) showLoader(id,"none");
  216. }
  217. if(btnreset && fltgrid)
  218. {
  219. /*** right div containing reset button **/
  220. var rdiv = createElm( "div",["id","reset_"+id] );
  221. btnreset ? rdiv.className = "rdiv" : rdiv.style.display = "none";
  222. var fltreset = createElm( "a",
  223. ["href","javascript:clearFilters('"+id+"');Filter('"+id+"');"] );
  224. fltreset.appendChild(createText(btnreset_text));
  225. rdiv.appendChild(fltreset);
  226. infdiv.appendChild(rdiv);
  227. }
  228. }//if displaynrows etc.
  229. if(colWidth)
  230. {
  231. t.tf_colWidth = f["col_width"];
  232. setColWidths(id);
  233. }
  234. if(alternateBgs && !displayPaging)
  235. setAlternateRows(id);
  236. if(colOperation)
  237. {
  238. t.tf_colOperation = f["col_operation"];
  239. setColOperation(id);
  240. }
  241. if(rowVisibility)
  242. {
  243. t.tf_rowVisibility = f["rows_always_visible"];
  244. if(displayPaging) setVisibleRows(id);
  245. }
  246. if(bindScript)
  247. {
  248. t.tf_bindScript = f["bind_script"];
  249. if( t.tf_bindScript!=undefined &&
  250. t.tf_bindScript["target_fn"]!=undefined )
  251. {//calls a fn if defined
  252. t.tf_bindScript["target_fn"].call(null,id);
  253. }
  254. }//if bindScript
  255. }
  256. function PopulateOptions(id,cellIndex)
  257. /*====================================================
  258. - populates select
  259. - adds only 1 occurence of a value
  260. =====================================================*/
  261. {
  262. var t = grabEBI(id);
  263. var ncells = t.tf_ncells, opt0txt = t.tf_display_allText;
  264. var sort_opts = t.tf_sortSlc, paging = t.tf_displayPaging;
  265. var start_row = t.tf_ref_row;
  266. var row = grabTag(t,"tr");
  267. var OptArray = new Array();
  268. var optIndex = 0; // option index
  269. var currOpt = new Option(opt0txt,"",false,false); //1st option
  270. grabEBI("flt"+cellIndex+"_"+id).options[optIndex] = currOpt;
  271. for(var k=start_row; k<row.length; k++)
  272. {
  273. var cell = getChildElms(row[k]).childNodes;
  274. var nchilds = cell.length;
  275. var isPaged = row[k].getAttribute("paging");
  276. if(nchilds == ncells){// checks if row has exact cell #
  277. for(var j=0; j<nchilds; j++)// this loop retrieves cell data
  278. {
  279. if(cellIndex==j)
  280. {
  281. var cell_data = getCellText(cell[j]);
  282. // checks if celldata is already in array
  283. var isMatched = false;
  284. for(w in OptArray)
  285. {
  286. if( cell_data == OptArray[w] ) isMatched = true;
  287. }
  288. if(!isMatched) OptArray.push(cell_data);
  289. }//if cellIndex==j
  290. }//for j
  291. }//if
  292. }//for k
  293. if(sort_opts) OptArray.sort();
  294. for(y in OptArray)
  295. {
  296. optIndex++;
  297. var currOpt = new Option(OptArray[y],OptArray[y],false,false);
  298. grabEBI("flt"+cellIndex+"_"+id).options[optIndex] = currOpt;
  299. }
  300. }
  301. function Filter(id)
  302. /*====================================================
  303. - Filtering fn
  304. - gets search strings from SearchFlt array
  305. - retrieves data from each td in every single tr
  306. and compares to search string for current
  307. column
  308. - tr is hidden if all search strings are not
  309. found
  310. =====================================================*/
  311. {
  312. showLoader(id,"");
  313. SearchFlt = getFilters(id);
  314. var t = grabEBI(id);
  315. t.tf_Obj!=undefined ? fprops = t.tf_Obj : fprops = new Array();
  316. var SearchArgs = new Array();
  317. var ncells = getCellsNb(id);
  318. var totrows = getRowsNb(id), hiddenrows = 0;
  319. var ematch = t.tf_exactMatch;
  320. var showPaging = t.tf_displayPaging;
  321. for(var i=0; i<SearchFlt.length; i++)
  322. SearchArgs.push( (grabEBI(SearchFlt[i]).value).toLowerCase() );
  323. var start_row = t.tf_ref_row;
  324. var row = grabTag(t,"tr");
  325. for(var k=start_row; k<row.length; k++)
  326. {
  327. /*** if table already filtered some rows are not visible ***/
  328. if(row[k].style.display == "none") row[k].style.display = "";
  329. var cell = getChildElms(row[k]).childNodes;
  330. var nchilds = cell.length;
  331. if(nchilds == ncells)// checks if row has exact cell #
  332. {
  333. var cell_value = new Array();
  334. var occurence = new Array();
  335. var isRowValid = true;
  336. for(var j=0; j<nchilds; j++)// this loop retrieves cell data
  337. {
  338. var cell_data = getCellText(cell[j]).toLowerCase();
  339. cell_value.push(cell_data);
  340. if(SearchArgs[j]!="")
  341. {
  342. var num_cell_data = parseFloat(cell_data);
  343. if(/<=/.test(SearchArgs[j]) && !isNaN(num_cell_data)) // first checks if there is an operator (<,>,<=,>=)
  344. {
  345. num_cell_data <= parseFloat(SearchArgs[j].replace(/<=/,"")) ? occurence[j] = true : occurence[j] = false;
  346. }
  347. else if(/>=/.test(SearchArgs[j]) && !isNaN(num_cell_data))
  348. {
  349. num_cell_data >= parseFloat(SearchArgs[j].replace(/>=/,"")) ? occurence[j] = true : occurence[j] = false;
  350. }
  351. else if(/</.test(SearchArgs[j]) && !isNaN(num_cell_data))
  352. {
  353. num_cell_data < parseFloat(SearchArgs[j].replace(/</,"")) ? occurence[j] = true : occurence[j] = false;
  354. }
  355. else if(/>/.test(SearchArgs[j]) && !isNaN(num_cell_data))
  356. {
  357. num_cell_data > parseFloat(SearchArgs[j].replace(/>/,"")) ? occurence[j] = true : occurence[j] = false;
  358. }
  359. else
  360. {
  361. // Improved by Cedric Wartel (cwl)
  362. // automatic exact match for selects and special characters are now filtered
  363. // modif cwl : exact match automatique sur les select
  364. var regexp;
  365. if(ematch || fprops["col_"+j]=="select") regexp = new RegExp('(^)'+regexpEscape(SearchArgs[j])+'($)',"gi");
  366. else regexp = new RegExp(regexpEscape(SearchArgs[j]),"gi");
  367. occurence[j] = regexp.test(cell_data);
  368. }
  369. }//if SearchArgs
  370. }//for j
  371. for(var z=0; z<ncells; z++)
  372. {
  373. if(SearchArgs[z]!="" && !occurence[z]) isRowValid = false;
  374. }//for t
  375. }//if
  376. if(!isRowValid)
  377. {
  378. row[k].style.display = "none"; hiddenrows++;
  379. if( showPaging ) row[k].setAttribute("validRow","false");
  380. } else {
  381. row[k].style.display = "";
  382. if( showPaging ) row[k].setAttribute("validRow","true");
  383. }
  384. }// for k
  385. t.tf_nRows = parseInt( getRowsNb(id) )-hiddenrows;
  386. if( !showPaging ) applyFilterProps(id);//applies filter props after filtering process
  387. if( showPaging ){ t.tf_startPagingRow=0; setPagingInfo(id); }//starts paging process
  388. }
  389. function setPagingInfo(id)
  390. /*====================================================
  391. - Paging fn
  392. - calculates page # according to valid rows
  393. - refreshes paging select according to page #
  394. - Calls GroupByPage fn
  395. =====================================================*/
  396. {
  397. var t = grabEBI(id);
  398. var start_row = parseInt( t.tf_ref_row );//filter start row
  399. var pagelength = t.tf_pagingLength;
  400. var row = grabTag(t,"tr");
  401. var mdiv = grabEBI("mdiv_"+id);
  402. var slcPages = grabEBI("slcPages_"+id);
  403. var pgspan = grabEBI("pgspan_"+id);
  404. var nrows = 0;
  405. for(var j=start_row; j<row.length; j++)//counts rows to be grouped
  406. {
  407. if(row[j].getAttribute("validRow") == "true") nrows++;
  408. }//for j
  409. var npg = Math.ceil( nrows/pagelength );//calculates page nb
  410. pgspan.innerHTML = npg; //refresh page nb span
  411. slcPages.innerHTML = "";//select clearing shortcut
  412. if( npg>0 )
  413. {
  414. mdiv.style.visibility = "visible";
  415. for(var z=0; z<npg; z++)
  416. {
  417. var currOpt = new Option((z+1),z*pagelength,false,false);
  418. slcPages.options[z] = currOpt;
  419. }
  420. } else {/*** if no results paging select is hidden ***/
  421. mdiv.style.visibility = "hidden";
  422. }
  423. GroupByPage(id);
  424. }
  425. function GroupByPage(id)
  426. /*====================================================
  427. - Paging fn
  428. - Displays current page rows
  429. =====================================================*/
  430. {
  431. showLoader(id,"");
  432. var t = grabEBI(id);
  433. var start_row = parseInt( t.tf_ref_row );//filter start row
  434. var pagelength = parseInt( t.tf_pagingLength );
  435. var paging_start_row = parseInt( t.tf_startPagingRow );//paging start row
  436. var paging_end_row = paging_start_row + pagelength;
  437. var row = grabTag(t,"tr");
  438. var nrows = 0;
  439. var validRows = new Array();//stores valid rows index
  440. for(var j=start_row; j<row.length; j++)
  441. //this loop stores valid rows index in validRows Array
  442. {
  443. var isRowValid = row[j].getAttribute("validRow");
  444. if(isRowValid=="true") validRows.push(j);
  445. }//for j
  446. for(h=0; h<validRows.length; h++)
  447. //this loop shows valid rows of current page
  448. {
  449. if( h>=paging_start_row && h<paging_end_row )
  450. {
  451. nrows++;
  452. row[ validRows[h] ].style.display = "";
  453. } else row[ validRows[h] ].style.display = "none";
  454. }//for h
  455. t.tf_nRows = parseInt(nrows);
  456. applyFilterProps(id);//applies filter props after filtering process
  457. }
  458. function applyFilterProps(id)
  459. /*====================================================
  460. - checks fns that should be called
  461. after filtering and/or paging process
  462. =====================================================*/
  463. {
  464. t = grabEBI(id);
  465. var rowsCounter = t.tf_rowsCounter;
  466. var nRows = t.tf_nRows;
  467. var rowVisibility = t.tf_rowVisibility;
  468. var alternateRows = t.tf_alternateBgs;
  469. var colOperation = t.tf_colOperation;
  470. if( rowsCounter ) showRowsCounter( id,parseInt(nRows) );//refreshes rows counter
  471. if( rowVisibility ) setVisibleRows(id);//shows rows always visible
  472. if( alternateRows ) setAlternateRows(id);//alterning row colors
  473. if( colOperation ) setColOperation(id);//makes operation on a col
  474. showLoader(id,"none");
  475. }
  476. function hasGrid(id)
  477. /*====================================================
  478. - checks if table has a filter grid
  479. - returns a boolean
  480. =====================================================*/
  481. {
  482. var r = false, t = grabEBI(id);
  483. if(t != null && t.nodeName.toLowerCase() == "table")
  484. {
  485. for(i in TblId)
  486. {
  487. if(id == TblId[i]) r = true;
  488. }// for i
  489. }//if
  490. return r;
  491. }
  492. function getCellsNb(id,nrow)
  493. /*====================================================
  494. - returns number of cells in a row
  495. - if nrow param is passed returns number of cells
  496. of that specific row
  497. =====================================================*/
  498. {
  499. var t = grabEBI(id);
  500. var tr;
  501. if(nrow == undefined) tr = grabTag(t,"tr")[0];
  502. else tr = grabTag(t,"tr")[nrow];
  503. var n = getChildElms(tr);
  504. return n.childNodes.length;
  505. }
  506. function getRowsNb(id)
  507. /*====================================================
  508. - returns total nb of filterable rows starting
  509. from reference row if defined
  510. =====================================================*/
  511. {
  512. var t = grabEBI(id);
  513. var s = t.tf_ref_row;
  514. var ntrs = grabTag(t,"tr").length;
  515. return parseInt(ntrs-s);
  516. }
  517. function getFilters(id)
  518. /*====================================================
  519. - returns an array containing filters ids
  520. - Note that hidden filters are also returned
  521. =====================================================*/
  522. {
  523. var SearchFltId = new Array();
  524. var t = grabEBI(id);
  525. var tr = grabTag(t,"tr")[0];
  526. var enfants = tr.childNodes;
  527. if(t.tf_fltGrid)
  528. {
  529. for(var i=0; i<enfants.length; i++)
  530. SearchFltId.push(enfants[i].firstChild.getAttribute("id"));
  531. }
  532. return SearchFltId;
  533. }
  534. function clearFilters(id)
  535. /*====================================================
  536. - clears grid filters
  537. =====================================================*/
  538. {
  539. SearchFlt = getFilters(id);
  540. for(i in SearchFlt) grabEBI(SearchFlt[i]).value = "";
  541. }
  542. function showLoader(id,p)
  543. /*====================================================
  544. - displays/hides loader div
  545. =====================================================*/
  546. {
  547. var loader = grabEBI("load_"+id);
  548. if(loader != null && p=="none")
  549. setTimeout("grabEBI('load_"+id+"').style.display = '"+p+"'",150);
  550. else if(loader != null && p!="none") loader.style.display = p;
  551. }
  552. function showRowsCounter(id,p)
  553. /*====================================================
  554. - Shows total number of filtered rows
  555. =====================================================*/
  556. {
  557. var totrows = grabEBI("totrows_span_"+id);
  558. if(totrows != null && totrows.nodeName.toLowerCase() == "span" )
  559. totrows.innerHTML = p;
  560. }
  561. function getChildElms(n)
  562. /*====================================================
  563. - checks passed node is a ELEMENT_NODE nodeType=1
  564. - removes TEXT_NODE nodeType=3
  565. =====================================================*/
  566. {
  567. if(n.nodeType == 1)
  568. {
  569. var enfants = n.childNodes;
  570. for(var i=0; i<enfants.length; i++)
  571. {
  572. var child = enfants[i];
  573. if(child.nodeType == 3) n.removeChild(child);
  574. }
  575. return n;
  576. }
  577. }
  578. function getCellText(n)
  579. /*====================================================
  580. - returns text + text of child nodes of a cell
  581. =====================================================*/
  582. {
  583. var s = "";
  584. var enfants = n.childNodes;
  585. for(var i=0; i<enfants.length; i++)
  586. {
  587. var child = enfants[i];
  588. if(child.nodeType == 3) s+= child.data;
  589. else s+= getCellText(child);
  590. }
  591. return s;
  592. }
  593. function getColValues(id,colindex,num)
  594. /*====================================================
  595. - returns an array containing cell values of
  596. a column
  597. - needs following args:
  598. - filter id (string)
  599. - column index (number)
  600. - a boolean set to true if we want only
  601. numbers to be returned
  602. =====================================================*/
  603. {
  604. var t = grabEBI(id);
  605. var row = grabTag(t,"tr");
  606. var nrows = row.length;
  607. var start_row = parseInt( t.tf_ref_row );//filter start row
  608. var ncells = getCellsNb( id,start_row );
  609. var colValues = new Array();
  610. for(var i=start_row; i<nrows; i++)//iterates rows
  611. {
  612. var cell = getChildElms(row[i]).childNodes;
  613. var nchilds = cell.length;
  614. if(nchilds == ncells)// checks if row has exact cell #
  615. {
  616. for(var j=0; j<nchilds; j++)// this loop retrieves cell data
  617. {
  618. if(j==colindex && row[i].style.display=="" )
  619. {
  620. var cell_data = getCellText( cell[j] ).toLowerCase();
  621. (num) ? colValues.push( parseFloat(cell_data) ) : colValues.push( cell_data );
  622. }//if j==k
  623. }//for j
  624. }//if nchilds == ncells
  625. }//for i
  626. return colValues;
  627. }
  628. function setColWidths(id)
  629. /*====================================================
  630. - sets widths of columns
  631. =====================================================*/
  632. {
  633. if( hasGrid(id) )
  634. {
  635. var t = grabEBI(id);
  636. t.style.tableLayout = "fixed";
  637. var colWidth = t.tf_colWidth;
  638. var start_row = parseInt( t.tf_ref_row );//filter start row
  639. var row = grabTag(t,"tr")[0];
  640. var ncells = getCellsNb(id,start_row);
  641. for(var i=0; i<colWidth.length; i++)
  642. {
  643. for(var k=0; k<ncells; k++)
  644. {
  645. cell = row.childNodes[k];
  646. if(k==i) cell.style.width = colWidth[i];
  647. }//var k
  648. }//for i
  649. }//if hasGrid
  650. }
  651. function setVisibleRows(id)
  652. /*====================================================
  653. - makes a row always visible
  654. =====================================================*/
  655. {
  656. if( hasGrid(id) )
  657. {
  658. var t = grabEBI(id);
  659. var row = grabTag(t,"tr");
  660. var nrows = row.length;
  661. var showPaging = t.tf_displayPaging;
  662. var visibleRows = t.tf_rowVisibility;
  663. for(var i=0; i<visibleRows.length; i++)
  664. {
  665. if(visibleRows[i]<=nrows)//row index cannot be > nrows
  666. {
  667. if(showPaging)
  668. row[ visibleRows[i] ].setAttribute("validRow","true");
  669. row[ visibleRows[i] ].style.display = "";
  670. }//if
  671. }//for i
  672. }//if hasGrid
  673. }
  674. function setAlternateRows(id)
  675. /*====================================================
  676. - alternates row colors for better readability
  677. =====================================================*/
  678. {
  679. if( hasGrid(id) )
  680. {
  681. var t = grabEBI(id);
  682. var row = grabTag(t,"tr");
  683. var nrows = row.length;
  684. var start_row = parseInt( t.tf_ref_row );//filter start row
  685. var visiblerows = new Array();
  686. for(var i=start_row; i<nrows; i++)//visible rows are stored in visiblerows array
  687. if( row[i].style.display=="" ) visiblerows.push(i);
  688. for(var j=0; j<visiblerows.length; j++)//alternates bg color
  689. (j % 2 == 0) ? row[ visiblerows[j] ].className = "even" : row[ visiblerows[j] ].className = "odd";
  690. }//if hasGrid
  691. }
  692. function setColOperation(id)
  693. /*====================================================
  694. - Calculates values of a column
  695. - params are stored in 'colOperation' table's
  696. attribute
  697. - colOperation["id"] contains ids of elements
  698. showing result (array)
  699. - colOperation["col"] contains index of
  700. columns (array)
  701. - colOperation["operation"] contains operation
  702. type (array, values: sum, mean)
  703. - colOperation["write_method"] array defines
  704. which method to use for displaying the
  705. result (innerHTML, setValue, createTextNode).
  706. Note that innerHTML is the default value.
  707. !!! to be optimised
  708. =====================================================*/
  709. {
  710. if( hasGrid(id) )
  711. {
  712. var t = grabEBI(id);
  713. var labelId = t.tf_colOperation["id"];
  714. var colIndex = t.tf_colOperation["col"];
  715. var operation = t.tf_colOperation["operation"];
  716. var outputType = t.tf_colOperation["write_method"];
  717. var precision = 2;//decimal precision
  718. if( (typeof labelId).toLowerCase()=="object"
  719. && (typeof colIndex).toLowerCase()=="object"
  720. && (typeof operation).toLowerCase()=="object" )
  721. {
  722. var row = grabTag(t,"tr");
  723. var nrows = row.length;
  724. var start_row = parseInt( t.tf_ref_row );//filter start row
  725. var ncells = getCellsNb( id,start_row );
  726. var colvalues = new Array();
  727. for(var k=0; k<colIndex.length; k++)//this retrieves col values
  728. {
  729. colvalues.push( getColValues(id,colIndex[k],true) );
  730. }//for k
  731. for(var i=0; i<colvalues.length; i++)
  732. {
  733. var result=0, nbvalues=0;
  734. for(var j=0; j<colvalues[i].length; j++ )
  735. {
  736. var cvalue = colvalues[i][j];
  737. if( !isNaN(cvalue) )
  738. {
  739. switch( operation[i].toLowerCase() )
  740. {
  741. case "sum":
  742. result += parseFloat( cvalue );
  743. break;
  744. case "mean":
  745. nbvalues++;
  746. result += parseFloat( cvalue );
  747. break;
  748. //add cases for other operations
  749. }//switch
  750. }
  751. }//for j
  752. switch( operation[i].toLowerCase() )
  753. {
  754. case "mean":
  755. result = result/nbvalues;
  756. break;
  757. }
  758. if(outputType != undefined && (typeof outputType).toLowerCase()=="object")
  759. //if outputType is defined
  760. {
  761. result = result.toFixed( precision );
  762. if( grabEBI( labelId[i] )!=undefined )
  763. {
  764. switch( outputType[i].toLowerCase() )
  765. {
  766. case "innerhtml":
  767. grabEBI( labelId[i] ).innerHTML = result;
  768. break;
  769. case "setvalue":
  770. grabEBI( labelId[i] ).value = result;
  771. break;
  772. case "createtextnode":
  773. var oldnode = grabEBI( labelId[i] ).firstChild;
  774. var txtnode = createText( result );
  775. grabEBI( labelId[i] ).replaceChild( txtnode,oldnode );
  776. break;
  777. //other cases could be added
  778. }//switch
  779. }
  780. } else {
  781. try
  782. {
  783. grabEBI( labelId[i] ).innerHTML = result.toFixed( precision );
  784. } catch(e){ }//catch
  785. }//else
  786. }//for i
  787. }//if typeof
  788. }//if hasGrid
  789. }
  790. function grabEBI(id)
  791. /*====================================================
  792. - this is just a getElementById shortcut
  793. =====================================================*/
  794. {
  795. return document.getElementById( id );
  796. }
  797. function grabTag(obj,tagname)
  798. /*====================================================
  799. - this is just a getElementsByTagName shortcut
  800. =====================================================*/
  801. {
  802. return obj.getElementsByTagName( tagname );
  803. }
  804. function regexpEscape(s)
  805. /*====================================================
  806. - escapes special characters [\^$.|?*+()
  807. for regexp
  808. - Many thanks to Cedric Wartel for this fn
  809. =====================================================*/
  810. {
  811. // traite les caractères spéciaux [\^$.|?*+()
  812. //remplace le carctère c par \c
  813. function escape(e)
  814. {
  815. a = new RegExp('\\'+e,'g');
  816. s = s.replace(a,'\\'+e);
  817. }
  818. chars = new Array('\\','[','^','$','.','|','?','*','+','(',')');
  819. //chars.each(escape); // no prototype framework here...
  820. for(e in chars) escape(chars[e]);
  821. return s;
  822. }
  823. function createElm(elm)
  824. /*====================================================
  825. - returns an html element with its attributes
  826. - accepts the following params:
  827. - a string defining the html element
  828. to create
  829. - an undetermined # of arrays containing the
  830. couple "attribute name","value" ["id","myId"]
  831. =====================================================*/
  832. {
  833. var el = document.createElement( elm );
  834. if(arguments.length>1)
  835. {
  836. for(var i=0; i<arguments.length; i++)
  837. {
  838. var argtype = typeof arguments[i];
  839. switch( argtype.toLowerCase() )
  840. {
  841. case "object":
  842. if( arguments[i].length==2 )
  843. {
  844. el.setAttribute( arguments[i][0],arguments[i][1] );
  845. }//if array length==2
  846. break;
  847. }//switch
  848. }//for i
  849. }//if args
  850. return el;
  851. }
  852. function createText(node)
  853. /*====================================================
  854. - this is just a document.createTextNode shortcut
  855. =====================================================*/
  856. {
  857. return document.createTextNode( node );
  858. }
  859. function DetectKey(e)
  860. /*====================================================
  861. - common fn that detects return key for a given
  862. element (onkeypress attribute on input)
  863. =====================================================*/
  864. {
  865. var evt=(e)?e:(window.event)?window.event:null;
  866. if(evt)
  867. {
  868. var key=(evt.charCode)?evt.charCode:
  869. ((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));
  870. if(key=="13")
  871. {
  872. var cid, leftstr, tblid, CallFn, Match;
  873. cid = this.getAttribute("id");
  874. leftstr = this.getAttribute("id").split("_")[0];
  875. tblid = cid.substring(leftstr.length+1,cid.length);
  876. t = grabEBI(tblid);
  877. (t.tf_isModfilter_fn) ? t.tf_modfilter_fn.call() : Filter(tblid);
  878. }//if key
  879. }//if evt
  880. }
  881. function importScript(scriptName,scriptPath)
  882. {
  883. var isImported = false;
  884. var scripts = grabTag(document,"script");
  885. for (var i=0; i<scripts.length; i++)
  886. {
  887. if(scripts[i].src.match(scriptPath))
  888. {
  889. isImported = true;
  890. break;
  891. }
  892. }
  893. if( !isImported )//imports script if not available
  894. {
  895. var head = grabTag(document,"head")[0];
  896. var extScript = createElm( "script",
  897. ["id",scriptName],
  898. ["type","text/javascript"],
  899. ["src",scriptPath] );
  900. head.appendChild(extScript);
  901. }
  902. }//fn importScript
  903. /*====================================================
  904. - Below a collection of public functions
  905. for developement purposes
  906. - all public methods start with prefix 'TF_'
  907. - These methods can be removed safely if not
  908. needed
  909. =====================================================*/
  910. function TF_GetFilterIds()
  911. /*====================================================
  912. - returns an array containing filter grids ids
  913. =====================================================*/
  914. {
  915. try{ return TblId }
  916. catch(e){ alert('TF_GetFilterIds() fn: could not retrieve any ids'); }
  917. }
  918. function TF_HasGrid(id)
  919. /*====================================================
  920. - checks if table has a filter grid
  921. - returns a boolean
  922. =====================================================*/
  923. {
  924. return hasGrid(id);
  925. }
  926. function TF_GetFilters(id)
  927. /*====================================================
  928. - returns an array containing filters ids of a
  929. specified grid
  930. =====================================================*/
  931. {
  932. try
  933. {
  934. var flts = getFilters(id);
  935. return flts;
  936. } catch(e) {
  937. alert('TF_GetFilters() fn: table id not found');
  938. }
  939. }
  940. function TF_GetStartRow(id)
  941. /*====================================================
  942. - returns starting row index for filtering
  943. process
  944. =====================================================*/
  945. {
  946. try
  947. {
  948. var t = grabEBI(id);
  949. return t.tf_ref_row;
  950. } catch(e) {
  951. alert('TF_GetStartRow() fn: table id not found');
  952. }
  953. }
  954. function TF_GetColValues(id,colindex,num)
  955. /*====================================================
  956. - returns an array containing cell values of
  957. a column
  958. - needs following args:
  959. - filter id (string)
  960. - column index (number)
  961. - a boolean set to true if we want only
  962. numbers to be returned
  963. =====================================================*/
  964. {
  965. if( hasGrid(id) )
  966. {
  967. return getColValues(id,colindex,num);
  968. }//if TF_HasGrid
  969. else alert('TF_GetColValues() fn: table id not found');
  970. }
  971. function TF_Filter(id)
  972. /*====================================================
  973. - filters a table
  974. =====================================================*/
  975. {
  976. var t = grabEBI(id);
  977. if( TF_HasGrid(id) ) Filter(id);
  978. else alert('TF_Filter() fn: table id not found');
  979. }
  980. function TF_RemoveFilterGrid(id)
  981. /*====================================================
  982. - removes a filter grid
  983. =====================================================*/
  984. {
  985. if( TF_HasGrid(id) )
  986. {
  987. var t = grabEBI(id);
  988. clearFilters(id);
  989. if(grabEBI("inf_"+id)!=null)
  990. {
  991. t.parentNode.removeChild(t.previousSibling);
  992. }
  993. // remove paging here
  994. var row = grabTag(t,"tr");
  995. for(var j=0; j<row.length; j++)
  996. //this loop shows all rows and removes validRow attribute
  997. {
  998. row[j].style.display = "";
  999. try
  1000. {
  1001. if( row[j].hasAttribute("validRow") )
  1002. row[j].removeAttribute("validRow");
  1003. } //ie<=6 doesn't support hasAttribute method
  1004. catch(e){
  1005. for( var x = 0; x < row[j].attributes.length; x++ )
  1006. {
  1007. if( row[j].attributes[x].nodeName.toLowerCase()=="validrow" )
  1008. row[j].removeAttribute("validRow");
  1009. }//for x
  1010. }//catch(e)
  1011. }//for j
  1012. if( t.tf_alternateBgs )//removes alterning row colors
  1013. {
  1014. for(var k=0; k<row.length; k++)
  1015. //this loop removes bg className
  1016. {
  1017. row[k].className = "";
  1018. }
  1019. }
  1020. if(t.tf_fltGrid) t.deleteRow(0);
  1021. for(i in TblId)//removes grid id value from array
  1022. if(id == TblId[i]) TblId.splice(i,1);
  1023. }//if TF_HasGrid
  1024. else alert('TF_RemoveFilterGrid() fn: table id not found');
  1025. }
  1026. function TF_ClearFilters(id)
  1027. /*====================================================
  1028. - clears grid filters only, table is not filtered
  1029. =====================================================*/
  1030. {
  1031. if( TF_HasGrid(id) ) clearFilters(id);
  1032. else alert('TF_ClearFilters() fn: table id not found');
  1033. }
  1034. function TF_SetFilterValue(id,index,searcharg)
  1035. /*====================================================
  1036. - Inserts value in a specified filter
  1037. - Params:
  1038. - id: table id (string)
  1039. - index: filter column index (numeric value)
  1040. - searcharg: search string
  1041. =====================================================*/
  1042. {
  1043. if( TF_HasGrid(id) )
  1044. {
  1045. var flts = getFilters(id);
  1046. for(i in flts)
  1047. {
  1048. if( i==index ) grabEBI(flts[i]).value = searcharg;
  1049. }
  1050. } else {
  1051. alert('TF_SetFilterValue() fn: table id not found');
  1052. }
  1053. }
  1054. /*====================================================
  1055. - bind an external script fns
  1056. - fns below do not belong to filter grid script
  1057. and are used to interface with external
  1058. autocomplete script found at the following URL:
  1059. http://www.codeproject.com/jscript/jsactb.asp
  1060. (credit to zichun)
  1061. - fns used to merge filter grid with external
  1062. scripts
  1063. =====================================================*/
  1064. var colValues = new Array();
  1065. function setAutoComplete(id)
  1066. {
  1067. var t = grabEBI(id);
  1068. var bindScript = t.tf_bindScript;
  1069. var scriptName = bindScript["name"];
  1070. var scriptPath = bindScript["path"];
  1071. initAutoComplete();
  1072. function initAutoComplete()
  1073. {
  1074. var filters = TF_GetFilters(id);
  1075. for(var i=0; i<filters.length; i++)
  1076. {
  1077. if( grabEBI(filters[i]).nodeName.toLowerCase()=="input")
  1078. {
  1079. colValues.push( getColValues(id,i) );
  1080. } else colValues.push( '' );
  1081. }//for i
  1082. try{ actb( grabEBI(filters[0]), colValues[0] ); }
  1083. catch(e){ alert(scriptPath + " script may not be loaded"); }
  1084. }//fn
  1085. }