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