/*------------------------------------------------------------------- 
Author's Statement:
This script is based on ideas of the author.
You may copy, modify and use it for any purpose. The only condition is that if you publish web pages that use this script you point to its author at a suitable place and don't remove this Statement from it.
It's your responsibility to handle possible bugs even if you didn't modify anything. I cannot promise any support.
Dieter Bungers
GMD (www.gmd.de) and infovation (www.infovation.de)
--------------------------------------------------------------------*/

var rowsToDisplay = 10;		// Table rows to be displayed at once. The value 
							// is updated by the user's input the in bottom 
							// line of the Filter Window 
iFirst = 0;					// Index of the first table row to be displayed 
iLast = rowsToDisplay;		// Index of the last table row to be displayed
kSort = new Array(0, 1);	// Sort instructions: Number of the sort column, 
							// initialized with 0 (i.e. first column) and
							// sort direction initialized with 1 (i.e. "up";
							// we then use -1 for "down")
theColumn = new Array();	// Container for sorting of filtered rows: The
							// first element is reserved for the row value 
							// to be sorted, the second element contains the 
							// row index as defined originally in the array 
							// "theRows". By this, we have only to sort and
							// filter this container and can continue 
							// accessing the original values of the array
							// "theRows" in order to display them in the 
							// table.
for (var i=0; i < theRows.length; i++) { // Initializing the Container
     theColumn[i] = new Array(0,i);
}

var tableWidth = 0;			// Determining the width of the Table
for (j=0; j<theCols.length; j++) {
	tableWidth += theCols[j][2];
}
tableWidth += 2*(theCols.length-1)

function initFilter() {	// This initializes the table rows of the Filter Window. 
						// Each row corresponds with a column of the table 
						// to be displayed and represents a filter corresponding 
						// to the data type of this column. The function is 
						// called from the Filter Window only once when it is 
						// loaded.
	for(i=0; i<theCols.length; i++) {
		filterWindow.document.writeln("<tr class=dark><th>" + theCols[i][0] + "</th><td align=right>");
		var dataType = theCols[i][1];
		if (dataType == 0) filterWindow.document.write("Check:</td><td><input name=filterI_" + i + " type=checkbox>");
		else if (dataType == 3) filterWindow.document.write("Select:</td><td><select name=filterS_" + i + "><option>&nbsp;" + theCols[i][3] + "</select>");
		else if (dataType == 4) filterWindow.document.write("<select name=filterS_" + i + "><option>&nbsp;<option>Starts with<option>Includes<option>Equals</select></td><td><input name=filterI_" + i + " type=text size=10>");
		else filterWindow.document.write("<select name=filterS_" + i + "><option>&nbsp;<option>&lt;<option>&lt;=<option>==<option>&gt;=<option>&gt;</select></td><td><input name=filterI_" + i + " type=text size=10>");
		filterWindow.document.write("</tr>");
	}
}

function showFilter() {	// This shows the Filter Window again 
	if(!filterWindow.closed) filterWindow.focus();
	else filterWindow = window.open('filter.htm', 'filter', 'toolbar=no,status=no,scrollbars=no,resizable=yes,width=400,height=524');
}

/* Building the HTML code of the static parts of the table only once */ 

var tabStart = "<html> \n<head> \n<title>" + theTitle + "</title> \n<link rel=stylesheet type=\"text/css\" href=\"tabstyle.css\"> \n</head> \n<body> \n<table border=0 cellspacing=2 cellpadding=2 width=" + tableWidth + "> \n<tr> \n";

var tabMiddle = "<table border=0 cellspacing=0 cellpadding=4> \n<form> \n<tr> \n<th rowspan=2 align=right> \n<input type=button value=\"&nbsp;|<&nbsp;\" onclick=\"parent.scrollTable(-2)\">&nbsp;&nbsp; \n<input type=button value=\"&nbsp;<&nbsp;\" onclick=\"parent.scrollTable(-1)\"> \n</th> \n<th>";

var tabEnd = "</th> \n<th rowspan=2 align=left> \n<input type=button value=\"&nbsp;>&nbsp;\" onclick=\"parent.scrollTable(1)\">&nbsp;&nbsp; \n<input type=button value=\"&nbsp;>|&nbsp;\" onclick=\"parent.scrollTable(2)\"> \n</th> \n</tr><tr> \n<th> \n<input type=button value=\"Show Filter\" onclick=\"parent.showFilter()\"> \n</th> \n</tr> \n</form> \n</table> \n</tr> \n</table> \n</body> \n</html>"

/* The following functions the name of which starts with "refresh..." return the HTML code of those parts of the table that vary because of the user's sort, filter or scroll requests */ 

function refreshHeader() {		// Table head with current position and shape 
								// of the sort symbol ("up.gif" or "down.gif")
								// that depend on the values of kSort 
	var str = "";
	for(k=0; k<theCols.length; k++) {
		str += ("<th width=" + theCols[k][2] + " align=center><a class=head href=\"javaScript:parent.mySort(" + k + ")\">" + theCols[k][0] + ((kSort[0]==k)?((kSort[1]==1)?"<br><img src=\"up.gif\" border=0>":"<br><img src=\"down.gif\" border=0>"):"&nbsp;") + "</a></th>");
	}
	return str;
}

function refreshTabRows() {		// Table rows depending on the result of
								// filtering and sorting. The indexes of them 
								// are stored in theColumn[k][1], k=1,2,...
								// (Remember that  theColumn[k][0] is used for 
								// the row values to be sorted). 
	var currentRows = "";
	for (var k=iFirst; k < iLast; k++) {
		theRec = theRows[theColumn[k][1]];
		currentRows += ("\n<tr class=" + ((k%2==0)?"light":"dark") + ">");
		for(l=0; l<theCols.length; l++) {
			var currentValue = (theRec[l] == "") ? "&nbsp;" : theRec[l]
			var theCell = "<td";
			if (theCols[l][1]==0) theCell += (" align=center>"+((theRec[l])?"<img src='check.gif'>":"&nbsp;"));
			else if (theCols[l][1]<=2) theCell += (" align=right>"+currentValue); 
			else if (theCols[l][1]==3) theCell += (" align=center>"+theCols[l][3].split("<option>")[currentValue]); 
			else theCell += (">"+currentValue);
			currentRows += (theCell + "</td>");
		}
		currentRows += "</tr>";
	}
	return currentRows + ("\n<tr><th colspan=" + theCols.length + ">");
}

function refreshTabCount() {	// This actualizes the row counter in the table's
								// bottom line when the user scrolls forth and back
	var N = theColumn.length;
	return (N > 0) ? ("Showing No. " + (iFirst+1) + " to " + iLast + " of " + N) : "No Matches";
}

function refreshTable() {		// This brings the static and variable parts 
								// of the table together and displayes them.
								// (The open() and close() commands ensure the 
								// old tabe to be overwritten.)
	table.document.clear();
	table.document.write(tabStart + refreshHeader() + refreshTabRows() + tabMiddle + refreshTabCount() + tabEnd);
	table.document.close();
}

function newTable() {			//

/* Building the filters for selecting the records to be displayed in the table. This is a string of JavaScript code, named "theFilter". It's only "true" if the user didn't define any filter. Otherwise it consists of some comparision expressions corresponding to the user's input in the Filter Window. The data type of a column decides the way the user's input has to be transfomed into a comparision expression. The comparision expressions are concatenated by the AND-Operation "&&" */

	theFilter = "true ";
	for(j=0; j<theCols.length; j++) {
		var dataType = theCols[j][1];
		var thisVal = "thisRow[" + j + "]";
		with (filterWindow.document.inputs) {
			if (dataType == 0 && eval("filterI_" + j + ".checked")) {
				theFilter += "&&"+thisVal;
			} 
			else if (dataType == 1 && (eval("filterS_"+j+".selectedIndex") != 0)) {
				var theOp = eval("filterS_"+j+".options[filterS_"+j+".selectedIndex].text");
				theFilter += "&&(" + thisVal + theOp + eval("filterI_" + j +".value") + ")";
			}
			else if (dataType == 2 && (eval("filterS_"+j+".selectedIndex") != 0)) {
				var theOp = eval("filterS_"+j+".options[filterS_"+j+".selectedIndex].text");
				var rightTerm = dateToNum(eval("filterI_"+j+".value"));
				var leftTerm = "dateToNum(" + thisVal + ")";
				theFilter += ("&&(" + leftTerm + theOp + rightTerm + ")");
			}
			else if (dataType == 3 && (eval("filterS_"+j+".selectedIndex") != 0)) {
				var theValue = eval("filterS_"+j+".selectedIndex");
				theFilter += ("&&(" + thisVal + "==" + theValue + ")");
			}
			else if (dataType == 4 && (eval("filterS_"+j+".selectedIndex") != 0)) {
				var opIndex = eval("filterS_"+j+".selectedIndex");
				var theValue = eval("filterI_"+j+".value.toUpperCase()");
				if (opIndex < 3) theFilter += "&&(innerText(" + thisVal + ").toUpperCase().indexOf(\"" + theValue + "\"" + ((opIndex==1)?")==0)":")!=-1)");
				else  theFilter += ("&&(innerText(" + thisVal + ").toUpperCase() == \"" + theValue + "\")");
			}
		}
	}

/* Now using the filter to obtain the indexes of the table rows (i.e. of the array theRow) that have to be displayed. This results in an update of the container "theColumn", the second subelement of the elements of which are the selected indexes. */
	
	myColumn = new Array();
	j = 0;
    for (var i=0; i < theRows.length; i++) {
		var thisRow = theRows[i];
        if (eval(theFilter)) {
			myColumn[j] = new Array(0,i);
			j++;
		}
	}
	theColumn = myColumn;

/* Sorting and redisplaying the table by means of the mySort and scrollTable functions */

	kSort[1] = -kSort[1];
	mySort(kSort[0]);	
	scrollTable(-2);
}

function dateToNum(dateString) {
	var dateArray = dateString.split("/");
	return dateArray[2]*10000 + dateArray[0]*100 + eval(dateArray[1]);
}

function innerText(str) {	// Eliminating HTML-tags from text to 
							// be filtered or sorted
	while (str.indexOf("<") != -1) {
		a = str.indexOf("<");
		b = str.indexOf(">");
		str = str.substring(0,a) + str.substring(b+1,str.length);
	}
	return(str);
}

function compare(a, b) {	// Needed for javaScript's sort method
							// that is used by the following function 
							// "mySort" (see last statement). The sort
							// direction is defined by kSort[1] that toggles
							// between -1 and +1.  
     if (a[0] < b[0]) return -kSort[1];
     if (a[0] > b[0]) return kSort[1];
     return 0;
}

function mySort(k) {		// This sorts the indexes of the filtered table rows
							// (stored in theColumn[j][1], j=1,2,....) by applying
							// javaScript's sort method to the row values 
							// (stored in theColumn[j][0], j=1,2,....). The above 
							// compare function ensures the right values are sorted. 
	if (kSort[0] == k) {	// Same row to be sorted so the sort direcrion toggles.
		kSort[1] = -kSort[1];
	}
	else {
		kSort[0] = k;		// New row to be sorted so kSort[0] is updated and 
		kSort[1] = 1;		// the sort direcrion is set to "up".
	}
/* Determining the sort value depending on the sort column's data type and storing it to theColumn[j][0], j=1,2,...: */
	var dataType = theCols[k][1]; 
	for (var j=0; j < theColumn.length; j++) { 
		var x = theRows[theColumn[j][1]][k];
		if (dataType == 0) {
			theColumn[j][0] = (x) ? 1 : 0;
		}
		else if (dataType == 1 || dataType == 3) {
			theColumn[j][0] = eval(x);
		}
		else if (dataType == 2) {
			if (x != "") theColumn[j][0] = dateToNum(x);
			else theColumn[j][0] = 0;
		}
		else {
			theColumn[j][0] = innerText(x).toUpperCase();
		}
	}
	theColumn = theColumn.sort(compare); // This performes the sort
	scrollTable(-2);
}

function scrollTable(x) {	// This determines the segment of the array "theColumn" 
							// the elements of which point to the table rows 
							// that currently have to be displayed. Then the 
							// function redisplays the table ba calling 
							// "refreshTable()". - Meaning of the parameter x:
							// -2 : show first rows 
							// -1 : show previous rows
							//  1 : show next rows
							//  2 : show last rows
							// The function is called from the onclick events of
							// the scroll buttons in the bottom line of the table
							// (see the global variables tabMiddle and tabEnd)
							// and from the function mySort. 
	if(!filterWindow.closed) rowsToDisplay = eval(filterWindow.document.inputs.numberOfLines.value);
	if (x==-2) iFirst = 0;
	else {
		if (x==2) iFirst = Math.min(Math.max(0,theColumn.length-1),theColumn.length-theColumn.length%rowsToDisplay);
		else iFirst = Math.min(Math.max(0,iFirst += x * rowsToDisplay), theColumn.length-theColumn.length%rowsToDisplay);
	}
	iLast = Math.min(iFirst+rowsToDisplay,theColumn.length);
	refreshTable();
	table.focus();
}

document.write("<title>" + theTitle + "</title>");
var filterWindow = window.open("filter.htm", "filter",
"toolbar=no,status=no,scrollbars=no,resizable=yes,width=400,height="+(92 + theCols.length*26));
window.focus();
