MediaWiki:Common.js

/* Any JavaScript here will be loaded for all users on every page load. */

/** Collapsible tables ********************************************************* * * Description: Allows tables to be collapsed, showing only the header. See *                        http://www.mediawiki.org/wiki/Manual:Collapsible_tables. * Maintainers: en:User:R. Koot */ var autoCollapse = 2; var collapseCaption = 'hide'; var expandCaption = 'show'; function collapseTable( tableIndex ) { var Button = document.getElementById( 'collapseButton' + tableIndex ); var Table = document.getElementById( 'collapsibleTable' + tableIndex ); if ( !Table || !Button ) { return false; }       var Rows = Table.rows; if ( Button.firstChild.data == collapseCaption ) { for ( var i = 1; i < Rows.length; i++ ) { Rows[i].style.display = 'none'; }               Button.firstChild.data = expandCaption; } else { for ( var i = 1; i < Rows.length; i++ ) { Rows[i].style.display = Rows[0].style.display; }               Button.firstChild.data = collapseCaption; } } function createCollapseButtons { var tableIndex = 0; var NavigationBoxes = new Object; var Tables = document.getElementsByTagName( 'table' ); for ( var i = 0; i < Tables.length; i++ ) { if ( hasClass( Tables[i], 'collapsible' ) ) { /* only add button and increment count if there is a header row to work with */ var HeaderRow = Tables[i].getElementsByTagName( 'tr' )[0]; if ( !HeaderRow ) { continue; }                       var Header = HeaderRow.getElementsByTagName( 'th' )[0]; if ( !Header ) { continue; }                       NavigationBoxes[tableIndex] = Tables[i]; Tables[i].setAttribute( 'id', 'collapsibleTable' + tableIndex ); var Button = document.createElement( 'span' ); var ButtonLink = document.createElement( 'a' ); var ButtonText = document.createTextNode( collapseCaption ); Button.className = 'collapseButton'; // Styles are declared in MediaWiki:Common.css ButtonLink.style.color = Header.style.color; ButtonLink.setAttribute( 'id', 'collapseButton' + tableIndex ); ButtonLink.setAttribute( 'href', "javascript:collapseTable(" + tableIndex + ");" ); ButtonLink.appendChild( ButtonText ); Button.appendChild( document.createTextNode( '[' ) ); Button.appendChild( ButtonLink ); Button.appendChild( document.createTextNode( ']' ) ); Header.insertBefore( Button, Header.childNodes[0] ); tableIndex++; }       }        for ( var i = 0;  i < tableIndex; i++ ) { if ( hasClass( NavigationBoxes[i], 'collapsed' ) || ( tableIndex >= autoCollapse && hasClass( NavigationBoxes[i], 'autocollapse' ) ) ) { collapseTable( i ); } else if ( hasClass( NavigationBoxes[i], 'innercollapse' ) ) { var element = NavigationBoxes[i]; while ( element = element.parentNode ) { if ( hasClass( element, 'outercollapse' ) ) { collapseTable( i ); break; }                       }                }        } } addOnloadHook( createCollapseButtons ); /** Test if an element has a certain class ************************************** * * Description: Uses regular expressions and caching for better performance. * Maintainers: User:Mike Dillon, User:R. Koot, User:SG */ var hasClass = ( function {       var reCache = {};        return function( element, className ) {                return ( reCache[className] ? reCache[className] : ( reCache[className] = new RegExp( "(?:\\s|^)" + className + "(?:\\s|$)" ) ) ).test( element.className );       }; });

/*====================================================	- HTML Table Filter Generator v1.6 - By Max Guglielmi - mguglielmi.free.fr/scripts/TableFilter/?l=en - please do not change this comment - don't forget to give some credit... it's always good for the author - Special credit to Cedric Wartel and cnx.claude@free.fr for contribution and inspiration

=
========================================*/

// global vars var TblId, SearchFlt, SlcArgs; TblId = new Array, SlcArgs = new Array;

function setFilterGrid(id) /*====================================================	- Checks if id exists and is a table - Then looks for additional params - Calls fn that generates the grid

=
========================================*/ {		var tbl = grabEBI(id); var ref_row, fObj; if(tbl != null && tbl.nodeName.toLowerCase == "table") {								if(arguments.length>1) {			for(var i=0; i<arguments.length; i++) {				var argtype = typeof arguments[i]; switch(argtype.toLowerCase) {					case "number": ref_row = arguments[i]; break; case "object": fObj = arguments[i]; break; }//switch }//for }//if ref_row == undefined ? ref_row=2 : ref_row=(ref_row+2); var ncells = getCellsNb(id,ref_row); tbl.tf_ncells = ncells; if(tbl.tf_ref_row==undefined) tbl.tf_ref_row = ref_row; tbl.tf_Obj = fObj; if( !hasGrid(id) ) AddGrid(id); }//if tbl!=null }

function AddGrid(id) /*====================================================	- adds a row containing the filtering grid

=
========================================*/ {		TblId.push(id); var t = grabEBI(id); var f = t.tf_Obj, n = t.tf_ncells; var inpclass, fltgrid, displayBtn, btntext, enterkey; var modfilter_fn, display_allText, on_slcChange; var displaynrows, totrows_text, btnreset, btnreset_text; var sort_slc, displayPaging, pagingLength, displayLoader; var load_text, exactMatch, alternateBgs, colOperation; var rowVisibility, colWidth, bindScript; f!=undefined && f["grid"]==false ? fltgrid=false : fltgrid=true;//enables/disables filter grid f!=undefined && f["btn"]==true ? displayBtn=true : displayBtn=false;//show/hides filter's validation button f!=undefined && f["btn_text"]!=undefined ? btntext=f["btn_text"] : btntext="go";//defines button text f!=undefined && f["enter_key"]==false ? enterkey=false : enterkey=true;//enables/disables enter key f!=undefined && f["mod_filter_fn"] ? modfilter_fn=true : modfilter_fn=false;//defines alternative fn f!=undefined && f["display_all_text"]!=undefined ? display_allText=f["display_all_text"] : display_allText="";//defines 1st option text f!=undefined && f["on_change"]==false ? on_slcChange=false : on_slcChange=true;//enables/disables onChange event on combo-box f!=undefined && f["rows_counter"]==true ? displaynrows=true : displaynrows=false;//show/hides rows counter f!=undefined && f["rows_counter_text"]!=undefined ? totrows_text=f["rows_counter_text"] : totrows_text="Displayed rows: ";//defines rows counter text f!=undefined && f["btn_reset"]==true ? btnreset=true : btnreset=false;//show/hides reset link f!=undefined && f["btn_reset_text"]!=undefined ? btnreset_text=f["btn_reset_text"] : btnreset_text="Reset";//defines reset text f!=undefined && f["sort_select"]==true ? sort_slc=true : sort_slc=false;//enables/disables select options sorting f!=undefined && f["paging"]==true ? displayPaging=true : displayPaging=false;//enables/disables table paging f!=undefined && f["paging_length"]!=undefined ? pagingLength=f["paging_length"] : pagingLength=10;//defines table paging length f!=undefined && f["loader"]==true ? displayLoader=true : displayLoader=false;//enables/disables loader f!=undefined && f["loader_text"]!=undefined ? load_text=f["loader_text"] : load_text="Loading...";//defines loader text f!=undefined && f["exact_match"]==true ? exactMatch=true : exactMatch=false;//enables/disbles exact match for search f!=undefined && f["alternate_rows"]==true ? alternateBgs=true : alternateBgs=false;//enables/disbles rows alternating bg colors f!=undefined && f["col_operation"] ? colOperation=true : colOperation=false;//enables/disbles column operation(sum,mean) f!=undefined && f["rows_always_visible"] ? rowVisibility=true : rowVisibility=false;//makes a row always visible f!=undefined && f["col_width"] ? colWidth=true : colWidth=false;//defines widths of columns f!=undefined && f["bind_script"] ? bindScript=true : bindScript=false; // props are added to table in order to be easily accessible from other fns t.tf_fltGrid			=	fltgrid; t.tf_displayBtn			= 	displayBtn; t.tf_btnText			=	btntext; t.tf_enterKey			= 	enterkey; t.tf_isModfilter_fn		= 	modfilter_fn; t.tf_display_allText 	= 	display_allText; t.tf_on_slcChange 		= 	on_slcChange; t.tf_rowsCounter 		= 	displaynrows; t.tf_rowsCounter_text	= 	totrows_text; t.tf_btnReset 			= 	btnreset; t.tf_btnReset_text 		= 	btnreset_text; t.tf_sortSlc 			=	sort_slc; t.tf_displayPaging 		= 	displayPaging; t.tf_pagingLength 		= 	pagingLength; t.tf_displayLoader		= 	displayLoader; t.tf_loadText			= 	load_text; t.tf_exactMatch 		= 	exactMatch; t.tf_alternateBgs		=	alternateBgs; t.tf_startPagingRow		= 	0; if(modfilter_fn) t.tf_modfilter_fn = f["mod_filter_fn"];// used by DetectKey fn

if(fltgrid) {		var fltrow = t.insertRow(0); //adds filter row fltrow.className = "fltrow"; for(var i=0; i<n; i++)// this loop adds filters {			var fltcell = fltrow.insertCell(i); //fltcell.noWrap = true; i==n-1 && displayBtn==true ? inpclass = "flt_s" : inpclass = "flt"; if(f==undefined || f["col_"+i]==undefined || f["col_"+i]=="none") {				var inptype; (f==undefined || f["col_"+i]==undefined) ? inptype="text" : inptype="hidden";//show/hide input var inp = createElm( "input",["id","flt"+i+"_"+id],["type",inptype],["class",inpclass] ); inp.className = inpclass;// for ie<=6 fltcell.appendChild(inp); if(enterkey) inp.onkeypress = DetectKey; }			else if(f["col_"+i]=="select") {				var slc = createElm( "select",["id","flt"+i+"_"+id],["class",inpclass] ); slc.className = inpclass;// for ie<=6 fltcell.appendChild(slc); PopulateOptions(id,i); if(displayPaging)//stores arguments for GroupByPage fn				{ var args = new Array; args.push(id); args.push(i); args.push(n); args.push(display_allText); args.push(sort_slc); args.push(displayPaging); SlcArgs.push(args); }				if(enterkey) slc.onkeypress = DetectKey; if(on_slcChange) {					(!modfilter_fn) ? slc.onchange = function{ Filter(id); } : slc.onchange = f["mod_filter_fn"]; } 			}			if(i==n-1 && displayBtn==true)// this adds button {				var btn = createElm(										"input",										["id","btn"+i+"_"+id],["type","button"],										["value",btntext],["class","btnflt"] 									); btn.className = "btnflt"; fltcell.appendChild(btn); (!modfilter_fn) ? btn.onclick = function{ Filter(id); } : btn.onclick = f["mod_filter_fn"]; }//if }// for i }//if fltgrid

if(displaynrows || btnreset || displayPaging || displayLoader) {		/*** div containing rows # displayer + reset btn ***/ var infdiv = createElm( "div",["id","inf_"+id],["class","inf"] ); infdiv.className = "inf";// setAttribute method for class attribute doesn't seem to work on ie<=6 t.parentNode.insertBefore(infdiv, t); if(displaynrows) {			/*** left div containing rows # displayer ***/ var totrows; var ldiv = createElm( "div",["id","ldiv_"+id] ); displaynrows ? ldiv.className = "ldiv" : ldiv.style.display = "none"; displayPaging ? totrows = pagingLength : totrows = getRowsNb(id); var totrows_span = createElm( "span",["id","totrows_span_"+id],["class","tot"] ); // tot # of rows displayer totrows_span.className = "tot";//for ie<=6 totrows_span.appendChild( createText(totrows) ); var totrows_txt = createText(totrows_text); ldiv.appendChild(totrows_txt); ldiv.appendChild(totrows_span); infdiv.appendChild(ldiv); }		if(displayLoader) {			/*** div containing loader ***/ var loaddiv = createElm( "div",["id","load_"+id],["class","loader"] ); loaddiv.className = "loader";// for ie<=6 loaddiv.style.display = "none"; loaddiv.appendChild( createText(load_text) ); infdiv.appendChild(loaddiv); }		if(displayPaging) {			/*** mid div containing paging displayer ***/ var mdiv = createElm( "div",["id","mdiv_"+id] ); displayPaging ? mdiv.className = "mdiv" : mdiv.style.display = "none"; infdiv.appendChild(mdiv); var start_row = t.tf_ref_row; var row = grabTag(t,"tr"); var nrows = row.length; var npages = Math.ceil( (nrows - start_row)/pagingLength );//calculates page nb			var slcPages = createElm( "select",["id","slcPages_"+id] ); slcPages.onchange = function{ if(displayLoader) showLoader(id,""); t.tf_startPagingRow = this.value; GroupByPage(id); if(displayLoader) showLoader(id,"none"); }			var pgspan = createElm( "span",["id","pgspan_"+id] ); grabEBI("mdiv_"+id).appendChild( createText(" Page ") ); grabEBI("mdiv_"+id).appendChild(slcPages); grabEBI("mdiv_"+id).appendChild( createText(" of ") ); pgspan.appendChild( createText(npages+" ") ); grabEBI("mdiv_"+id).appendChild(pgspan); for(var j=start_row; j<nrows; j++)//this sets rows to validRow=true {				row[j].setAttribute("validRow","true"); }//for j			setPagingInfo(id); if(displayLoader) showLoader(id,"none"); }		if(btnreset && fltgrid) {			/*** right div containing reset button **/ var rdiv = createElm( "div",["id","reset_"+id] ); btnreset ? rdiv.className = "rdiv" : rdiv.style.display = "none"; var fltreset = createElm( 	"a",										["href","javascript:clearFilters('"+id+"');Filter('"+id+"');"] ); fltreset.appendChild(createText(btnreset_text)); rdiv.appendChild(fltreset); infdiv.appendChild(rdiv); }	}//if displaynrows etc.	if(colWidth) {		t.tf_colWidth = f["col_width"]; setColWidths(id); }	if(alternateBgs && !displayPaging) setAlternateRows(id); if(colOperation) {		t.tf_colOperation = f["col_operation"]; setColOperation(id); }	if(rowVisibility) {		t.tf_rowVisibility = f["rows_always_visible"]; if(displayPaging) setVisibleRows(id); }	if(bindScript) {		t.tf_bindScript = f["bind_script"]; if(	t.tf_bindScript!=undefined &&			t.tf_bindScript["target_fn"]!=undefined ) {//calls a fn if defined t.tf_bindScript["target_fn"].call(null,id); }	}//if bindScript }

function PopulateOptions(id,cellIndex) /*====================================================	- populates select - adds only 1 occurence of a value

=
========================================*/ {	var t = grabEBI(id); var ncells = t.tf_ncells, opt0txt = t.tf_display_allText; var sort_opts = t.tf_sortSlc, paging = t.tf_displayPaging; var start_row = t.tf_ref_row; var row = grabTag(t,"tr"); var OptArray = new Array; var optIndex = 0; // option index var currOpt = new Option(opt0txt,"",false,false); //1st option grabEBI("flt"+cellIndex+"_"+id).options[optIndex] = currOpt; for(var k=start_row; k<row.length; k++) {		var cell = getChildElms(row[k]).childNodes; var nchilds = cell.length; var isPaged = row[k].getAttribute("paging"); if(nchilds == ncells){// checks if row has exact cell # for(var j=0; j<nchilds; j++)// this loop retrieves cell data {				if(cellIndex==j) {					var cell_data = getCellText(cell[j]); // checks if celldata is already in array var isMatched = false; for(w in OptArray) {						if( cell_data == OptArray[w] ) isMatched = true; }					if(!isMatched) OptArray.push(cell_data); }//if cellIndex==j }//for j		}//if }//for k	if(sort_opts) OptArray.sort; for(y in OptArray) {		optIndex++; var currOpt = new Option(OptArray[y],OptArray[y],false,false); grabEBI("flt"+cellIndex+"_"+id).options[optIndex] = currOpt; } }

function Filter(id) /*====================================================	- Filtering fn	- gets search strings from SearchFlt array - retrieves data from each td in every single tr	and compares to search string for current column - tr is hidden if all search strings are not found

=
========================================*/ {		showLoader(id,""); SearchFlt = getFilters(id); var t = grabEBI(id); t.tf_Obj!=undefined ? fprops = t.tf_Obj : fprops = new Array; var SearchArgs = new Array; var ncells = getCellsNb(id); var totrows = getRowsNb(id), hiddenrows = 0; var ematch = t.tf_exactMatch; var showPaging = t.tf_displayPaging; for(var i=0; i<SearchFlt.length; i++) SearchArgs.push( (grabEBI(SearchFlt[i]).value).toLowerCase ); var start_row = t.tf_ref_row; var row = grabTag(t,"tr"); for(var k=start_row; k<row.length; k++) {		/*** if table already filtered some rows are not visible ***/ if(row[k].style.display == "none") row[k].style.display = ""; var cell = getChildElms(row[k]).childNodes; var nchilds = cell.length;

if(nchilds == ncells)// checks if row has exact cell # {			var cell_value = new Array; var occurence = new Array; var isRowValid = true; for(var j=0; j,<=,>=) {						num_cell_data <= parseFloat(SearchArgs[j].replace(/<=/,"")) ? occurence[j] = true : occurence[j] = false; }					else if(/>=/.test(SearchArgs[j]) && !isNaN(num_cell_data)) {						num_cell_data >= parseFloat(SearchArgs[j].replace(/>=/,"")) ? occurence[j] = true : occurence[j] = false; }					else if(//.test(SearchArgs[j]) && !isNaN(num_cell_data)) {						num_cell_data > parseFloat(SearchArgs[j].replace(/>/,"")) ? occurence[j] = true : occurence[j] = false; }										else {												// Improved by Cedric Wartel (cwl) // automatic exact match for selects and special characters are now filtered // modif cwl : exact match automatique sur les select var regexp; if(ematch || fprops["col_"+j]=="select") regexp = new RegExp('(^)'+regexpEscape(SearchArgs[j])+'($)',"gi"); else regexp = new RegExp(regexpEscape(SearchArgs[j]),"gi"); occurence[j] = regexp.test(cell_data); }				}//if SearchArgs }//for j			for(var z=0; z<ncells; z++) {				if(SearchArgs[z]!="" && !occurence[z]) isRowValid = false; }//for t		}//if if(!isRowValid) { 			row[k].style.display = "none"; hiddenrows++; if( showPaging ) row[k].setAttribute("validRow","false"); } else { row[k].style.display = ""; if( showPaging ) row[k].setAttribute("validRow","true"); }	}// for k	t.tf_nRows = parseInt( getRowsNb(id) )-hiddenrows; if( !showPaging ) applyFilterProps(id);//applies filter props after filtering process if( showPaging ){ t.tf_startPagingRow=0; setPagingInfo(id); }//starts paging process }

function setPagingInfo(id) /*====================================================	- Paging fn	- calculates page # according to valid rows - refreshes paging select according to page # - Calls GroupByPage fn

=
========================================*/ {		var t = grabEBI(id); var start_row = parseInt( t.tf_ref_row );//filter start row var pagelength = t.tf_pagingLength; var row = grabTag(t,"tr"); var mdiv = grabEBI("mdiv_"+id); var slcPages = grabEBI("slcPages_"+id); var pgspan = grabEBI("pgspan_"+id); var nrows = 0; for(var j=start_row; j0 ) {		mdiv.style.visibility = "visible"; for(var z=0; z<npg; z++) {			var currOpt = new Option((z+1),z*pagelength,false,false); slcPages.options[z] = currOpt; }	} else {/*** if no results paging select is hidden ***/ mdiv.style.visibility = "hidden"; }	GroupByPage(id); }

function GroupByPage(id) /*====================================================	- Paging fn	- Displays current page rows

=
========================================*/ {	showLoader(id,""); var t = grabEBI(id); var start_row = parseInt( t.tf_ref_row );//filter start row var pagelength = parseInt( t.tf_pagingLength ); var paging_start_row = parseInt( t.tf_startPagingRow );//paging start row var paging_end_row = paging_start_row + pagelength; var row = grabTag(t,"tr"); var nrows = 0; var validRows = new Array;//stores valid rows index for(var j=start_row; j=paging_start_row && h<paging_end_row ) {			nrows++; row[ validRows[h] ].style.display = ""; } else row[ validRows[h] ].style.display = "none"; }//for h	t.tf_nRows = parseInt(nrows); applyFilterProps(id);//applies filter props after filtering process }

function applyFilterProps(id) /*====================================================	- checks fns that should be called after filtering and/or paging process

=
========================================*/ {	t = grabEBI(id); var rowsCounter = t.tf_rowsCounter; var nRows = t.tf_nRows; var rowVisibility = t.tf_rowVisibility; var alternateRows = t.tf_alternateBgs; var colOperation = t.tf_colOperation; if( rowsCounter ) showRowsCounter( id,parseInt(nRows) );//refreshes rows counter if( rowVisibility ) setVisibleRows(id);//shows rows always visible if( alternateRows ) setAlternateRows(id);//alterning row colors if( colOperation ) setColOperation(id);//makes operation on a col showLoader(id,"none"); }

function hasGrid(id) /*====================================================	- checks if table has a filter grid - returns a boolean

=
========================================*/ {	var r = false, t = grabEBI(id); if(t != null && t.nodeName.toLowerCase == "table") {		for(i in TblId) {			if(id == TblId[i]) r = true; }// for i	}//if return r; }

function getCellsNb(id,nrow) /*====================================================	- returns number of cells in a row - if nrow param is passed returns number of cells of that specific row

=
========================================*/ { 	var t = grabEBI(id); var tr; if(nrow == undefined) tr = grabTag(t,"tr")[0]; else tr = grabTag(t,"tr")[nrow]; var n = getChildElms(tr); return n.childNodes.length; }

function getRowsNb(id) /*====================================================	- returns total nb of filterable rows starting from reference row if defined

=
========================================*/ {	var t = grabEBI(id); var s = t.tf_ref_row; var ntrs = grabTag(t,"tr").length; return parseInt(ntrs-s); }

function getFilters(id) /*====================================================	- returns an array containing filters ids - Note that hidden filters are also returned

=
========================================*/ {	var SearchFltId = new Array; var t = grabEBI(id); var tr = grabTag(t,"tr")[0]; var enfants = tr.childNodes; if(t.tf_fltGrid) {		for(var i=0; i<enfants.length; i++) SearchFltId.push(enfants[i].firstChild.getAttribute("id")); }	return SearchFltId; }

function clearFilters(id) /*====================================================	- clears grid filters

=
========================================*/ {	SearchFlt = getFilters(id); for(i in SearchFlt) grabEBI(SearchFlt[i]).value = ""; }

function showLoader(id,p) /*====================================================	- displays/hides loader div

=
========================================*/ {	var loader = grabEBI("load_"+id); if(loader != null && p=="none") setTimeout("grabEBI('load_"+id+"').style.display = '"+p+"'",150); else if(loader != null && p!="none") loader.style.display = p; }

function showRowsCounter(id,p) /*====================================================	- Shows total number of filtered rows

=
========================================*/ {	var totrows = grabEBI("totrows_span_"+id); if(totrows != null && totrows.nodeName.toLowerCase == "span" ) totrows.innerHTML = p; }

function getChildElms(n) /*====================================================	- checks passed node is a ELEMENT_NODE nodeType=1 - removes TEXT_NODE nodeType=3

=
========================================*/ {	if(n.nodeType == 1) {		var enfants = n.childNodes; for(var i=0; i<enfants.length; i++) {			var child = enfants[i]; if(child.nodeType == 3) n.removeChild(child); }		return n; } }

function getCellText(n) /*====================================================	- returns text + text of child nodes of a cell

=
========================================*/ {	var s = ""; var enfants = n.childNodes; for(var i=0; i<enfants.length; i++) {		var child = enfants[i]; if(child.nodeType == 3) s+= child.data; else s+= getCellText(child); }	return s; }

function getColValues(id,colindex,num) /*====================================================	- returns an array containing cell values of	a column - needs following args: - filter id (string) - column index (number) - a boolean set to true if we want only numbers to be returned

=
========================================*/ {	var t = grabEBI(id); var row = grabTag(t,"tr"); var nrows = row.length; var start_row = parseInt( t.tf_ref_row );//filter start row var ncells = getCellsNb( id,start_row ); var colValues = new Array; for(var i=start_row; i<nrows; i++)//iterates rows {		var cell = getChildElms(row[i]).childNodes; var nchilds = cell.length; if(nchilds == ncells)// checks if row has exact cell # {			for(var j=0; j<nchilds; j++)// this loop retrieves cell data {				if(j==colindex && row[i].style.display=="" ) {					var cell_data = getCellText( cell[j] ).toLowerCase; (num) ? colValues.push( parseFloat(cell_data) ) : colValues.push( cell_data ); }//if j==k }//for j		}//if nchilds == ncells }//for i	return colValues; }

function setColWidths(id) /*====================================================	- sets widths of columns

=
========================================*/ {	if( hasGrid(id) ) {		var t = grabEBI(id); t.style.tableLayout = "fixed"; var colWidth = t.tf_colWidth; var start_row = parseInt( t.tf_ref_row );//filter start row var row = grabTag(t,"tr")[0]; var ncells = getCellsNb(id,start_row); for(var i=0; i<colWidth.length; i++) {			for(var k=0; k<ncells; k++) {				cell = row.childNodes[k]; if(k==i) cell.style.width = colWidth[i]; }//var k		}//for i	}//if hasGrid }

function setVisibleRows(id) /*====================================================	- makes a row always visible

=
========================================*/ {	if( hasGrid(id) ) {		var t = grabEBI(id); var row = grabTag(t,"tr"); var nrows = row.length; var showPaging = t.tf_displayPaging; var visibleRows = t.tf_rowVisibility; for(var i=0; i nrows {				if(showPaging) row[ visibleRows[i] ].setAttribute("validRow","true"); row[ visibleRows[i] ].style.display = ""; }//if }//for i	}//if hasGrid }

function setAlternateRows(id) /*====================================================	- alternates row colors for better readability

=
========================================*/ {	if( hasGrid(id) ) {		var t = grabEBI(id); var row = grabTag(t,"tr"); var nrows = row.length; var start_row = parseInt( t.tf_ref_row );//filter start row var visiblerows = new Array; for(var i=start_row; i<nrows; i++)//visible rows are stored in visiblerows array if( row[i].style.display=="" ) visiblerows.push(i); for(var j=0; j<visiblerows.length; j++)//alternates bg color (j % 2 == 0) ? row[ visiblerows[j] ].className = "even" : row[ visiblerows[j] ].className = "odd"; }//if hasGrid }

function setColOperation(id) /*====================================================	- Calculates values of a column - params are stored in 'colOperation' table's	attribute - colOperation["id"] contains ids of elements showing result (array) - colOperation["col"] contains index of 		columns (array) - colOperation["operation"] contains operation type (array, values: sum, mean) - colOperation["write_method"] array defines which method to use for displaying the result (innerHTML, setValue, createTextNode). Note that innerHTML is the default value. !!! to be optimised

=
========================================*/ {	if( hasGrid(id) ) {		var t = grabEBI(id); var labelId = t.tf_colOperation["id"]; var colIndex = t.tf_colOperation["col"]; var operation = t.tf_colOperation["operation"]; var outputType = t.tf_colOperation["write_method"]; var precision = 2;//decimal precision if( (typeof labelId).toLowerCase=="object" 			&& (typeof colIndex).toLowerCase=="object" 			&& (typeof operation).toLowerCase=="object" ) {			var row = grabTag(t,"tr"); var nrows = row.length; var start_row = parseInt( t.tf_ref_row );//filter start row var ncells = getCellsNb( id,start_row ); var colvalues = new Array; for(var k=0; k<colIndex.length; k++)//this retrieves col values {				colvalues.push( getColValues(id,colIndex[k],true) ); }//for k			for(var i=0; i<colvalues.length; i++) {				var result=0, nbvalues=0; for(var j=0; j<colvalues[i].length; j++ ) {					var cvalue = colvalues[i][j]; if( !isNaN(cvalue) ) {						switch( operation[i].toLowerCase ) {							case "sum": result += parseFloat( cvalue ); break; case "mean": nbvalues++; result += parseFloat( cvalue ); break; //add cases for other operations }//switch }				}//for j				switch( operation[i].toLowerCase ) {					case "mean": result = result/nbvalues; break; }				if(outputType != undefined && (typeof outputType).toLowerCase=="object") //if outputType is defined {					result = result.toFixed( precision ); if( grabEBI( labelId[i] )!=undefined ) {						switch( outputType[i].toLowerCase ) {							case "innerhtml": grabEBI( labelId[i] ).innerHTML = result; break; case "setvalue": grabEBI( labelId[i] ).value = result; break; case "createtextnode": var oldnode = grabEBI( labelId[i] ).firstChild; var txtnode = createText( result ); grabEBI( labelId[i] ).replaceChild( txtnode,oldnode ); break; //other cases could be added }//switch }				} else { try {						grabEBI( labelId[i] ).innerHTML = result.toFixed( precision ); } catch(e){ }//catch }//else }//for i

}//if typeof }//if hasGrid }

function grabEBI(id) /*====================================================	- this is just a getElementById shortcut

=
========================================*/ {	return document.getElementById( id ); }

function grabTag(obj,tagname) /*====================================================	- this is just a getElementsByTagName shortcut

=
========================================*/ {	return obj.getElementsByTagName( tagname ); }

function regexpEscape(s) /*====================================================	- escapes special characters [\^$.|?*+ for regexp - Many thanks to Cedric Wartel for this fn

=
========================================*/ {	// traite les caractères spéciaux [\^$.|?*+ //remplace le carctère c par \c function escape(e) {		a = new RegExp('\\'+e,'g'); s = s.replace(a,'\\'+e); }

chars = new Array('\\','[','^','$','.','|','?','*','+','(',')'); //chars.each(escape); // no prototype framework here... for(e in chars) escape(chars[e]); return s; }

function createElm(elm) /*====================================================	- returns an html element with its attributes - accepts the following params: - a string defining the html element to create - an undetermined # of arrays containing the couple "attribute name","value" ["id","myId"]

=
========================================*/ {	var el = document.createElement( elm ); if(arguments.length>1) {		for(var i=0; i<arguments.length; i++) {			var argtype = typeof arguments[i]; switch( argtype.toLowerCase ) {				case "object": if( arguments[i].length==2 ) {													el.setAttribute( arguments[i][0],arguments[i][1] ); }//if array length==2 break; }//switch }//for i	}//if args return el; }

function createText(node) /*====================================================	- this is just a document.createTextNode shortcut

=
========================================*/ {	return document.createTextNode( node ); }

function DetectKey(e) /*====================================================	- common fn that detects return key for a given element (onkeypress attribute on input)

=
========================================*/ {	var evt=(e)?e:(window.event)?window.event:null; if(evt) {		var key=(evt.charCode)?evt.charCode: ((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0)); if(key=="13") {			var cid, leftstr, tblid, CallFn, Match; cid = this.getAttribute("id"); leftstr = this.getAttribute("id").split("_")[0]; tblid = cid.substring(leftstr.length+1,cid.length); t = grabEBI(tblid); (t.tf_isModfilter_fn) ? t.tf_modfilter_fn.call : Filter(tblid); }//if key }//if evt }

function importScript(scriptName,scriptPath) {	var isImported = false; var scripts = grabTag(document,"script");

for (var i=0; i<scripts.length; i++) {		if(scripts[i].src.match(scriptPath)) { 			isImported = true; break; }	}

if( !isImported )//imports script if not available {		var head = grabTag(document,"head")[0]; var extScript = createElm(	"script",									["id",scriptName],									["type","text/javascript"],									["src",scriptPath]	); head.appendChild(extScript); } }//fn importScript

/*====================================================	- Below a collection of public functions for developement purposes - all public methods start with prefix 'TF_' - These methods can be removed safely if not needed

=
========================================*/

function TF_GetFilterIds /*====================================================	- returns an array containing filter grids ids

=
========================================*/ {	try{ return TblId } catch(e){ alert('TF_GetFilterIds fn: could not retrieve any ids'); } }

function TF_HasGrid(id) /*====================================================	- checks if table has a filter grid - returns a boolean

=
========================================*/ {	return hasGrid(id); }

function TF_GetFilters(id) /*====================================================	- returns an array containing filters ids of a	specified grid

=
========================================*/ {	try {		var flts = getFilters(id); return flts; } catch(e) { alert('TF_GetFilters fn: table id not found'); } }

function TF_GetStartRow(id) /*====================================================	- returns starting row index for filtering process

=
========================================*/ {	try {		var t = grabEBI(id); return t.tf_ref_row; } catch(e) { alert('TF_GetStartRow fn: table id not found'); } }

function TF_GetColValues(id,colindex,num) /*====================================================	- returns an array containing cell values of	a column - needs following args: - filter id (string) - column index (number) - a boolean set to true if we want only numbers to be returned

=
========================================*/ {	if( hasGrid(id) ) {		return getColValues(id,colindex,num); }//if TF_HasGrid else alert('TF_GetColValues fn: table id not found'); }

function TF_Filter(id) /*====================================================	- filters a table

=
========================================*/ {	var t = grabEBI(id); if( TF_HasGrid(id) ) Filter(id); else alert('TF_Filter fn: table id not found'); }

function TF_RemoveFilterGrid(id) /*====================================================	- removes a filter grid

=
========================================*/ {	if( TF_HasGrid(id) ) {		var t = grabEBI(id); clearFilters(id); if(grabEBI("inf_"+id)!=null) {			t.parentNode.removeChild(t.previousSibling); }		// remove paging here var row = grabTag(t,"tr"); for(var j=0; j<row.length; j++) //this loop shows all rows and removes validRow attribute {						row[j].style.display = ""; try { 				if( row[j].hasAttribute("validRow") ) row[j].removeAttribute("validRow"); } //ie<=6 doesn't support hasAttribute method catch(e){ for( var x = 0; x < row[j].attributes.length; x++ ) {					if( row[j].attributes[x].nodeName.toLowerCase=="validrow" ) row[j].removeAttribute("validRow"); }//for x			}//catch(e) }//for j if( t.tf_alternateBgs )//removes alterning row colors {			for(var k=0; k<row.length; k++) //this loop removes bg className {				row[k].className = ""; }		}		if(t.tf_fltGrid) t.deleteRow(0); for(i in TblId)//removes grid id value from array if(id == TblId[i]) TblId.splice(i,1); }//if TF_HasGrid else alert('TF_RemoveFilterGrid fn: table id not found'); }

function TF_ClearFilters(id) /*====================================================	- clears grid filters only, table is not filtered

=
========================================*/ {	if( TF_HasGrid(id) ) clearFilters(id); else alert('TF_ClearFilters fn: table id not found'); }

function TF_SetFilterValue(id,index,searcharg) /*====================================================	- Inserts value in a specified filter - Params: - id: table id (string) - index: filter column index (numeric value) - searcharg: search string

=
========================================*/ {	if( TF_HasGrid(id) ) {		var flts = getFilters(id); for(i in flts) {			if( i==index ) grabEBI(flts[i]).value = searcharg; }	} else { alert('TF_SetFilterValue fn: table id not found'); } }

/*====================================================	- bind an external script fns - fns below do not belong to filter grid script and are used to interface with external autocomplete script found at the following URL: http://www.codeproject.com/jscript/jsactb.asp (credit to zichun) - fns used to merge filter grid with external scripts

=
========================================*/ var colValues = new Array;

function setAutoComplete(id) {	var t = grabEBI(id); var bindScript = t.tf_bindScript; var scriptName = bindScript["name"]; var scriptPath = bindScript["path"]; initAutoComplete; function initAutoComplete {		var filters = TF_GetFilters(id); for(var i=0; i<filters.length; i++) {			if( grabEBI(filters[i]).nodeName.toLowerCase=="input") {				colValues.push( getColValues(id,i) ); } else colValues.push( '' ); }//for i

try{ actb( grabEBI(filters[0]), colValues[0] ); } catch(e){ alert(scriptPath + " script may not be loaded"); }

}//fn }