			
	var domok=document.all||document.getElementById
if (domok) {
//*****************************************************************************
// Description: This javascript file can be applied to convert record tables
// in a HTML file to be client-side sortable by associating title columns with
// sort events. 
//
// COPYRIGHT (C) extensions   :  2007 PANTA-RHEI-SYSTEMS-GMBH
// COPYRIGHT (C) basic script :  2001 HAN J. YU, LIPING DAI 
// THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY IT 
// UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY THE FREE 
// SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR (AT YOUR OPTION) 
// ANY LATER VERSION. THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE 
// USEFUL, BUT WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF 
// MERCHANTABILITY OF FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU GENERAL 
// PUBLIC LICENSE FOR MORE DETAILS. 
//
//*****************************************************************************

//*****************************************************************************
// sortTable.js
//
// This script contains useful functions that can be used to convert ordinary
// tables into sortable tables by modifying the HTML sources.
// 
// Here is how one can do that. The following assumptions are required
// for the tables to be sorted.
//
// 1. All the record columns must be the same lengh. Otherwise (i.e. the ones
//    that contain colspan) the rows will be ignored. 
//
// 2. Row spans can not happen in the record rows though column spans
//    can be one of the record rows.
//
// 3. Row-spanned single column will be considered as title.
//
// To enable the sorting, simply include this javascript source file and
// add an onLoad event to the <body> like below:
//
// <body onLoad='initTable("table1");initTable("table2");' ...>
//
// To choose a alternative searchorder you can put a input hidden field at 
// the end of the <td> tag. like:
//
// <input type="hidden" name="sort" value=" ** SEARCHORDERVALUE ** "> </td>
//
// Note that all the tables that need to be sorted MUST contain ID tag. 
// So, if they do not exist, you must create one for each table that
// needs to be sorted.
//*****************************************************************************

// Global variables
var table;				// Table object
var rowElemArray = new Array();
var rowArray = new Array();		// Data row array
var titleRowArray = new Array();	// Contains title texts
var titleRowCellArray = new Array();	// Dynamically constructed title cells
var titleSpanCellArray = new Array();	// Title elelments from row-spanned
var colSpanArray = new Array();		// Rows col-spanned
var colTitleFilled = new Array();	// Indicates whether title is filled
var sortIndex;				// Selected index for sort
var descending = false;			// Descending order
var nRow, actualNRow, maxNCol;		// Various table stats
var isIE;				// True if IE
var linkEventString =			// What's insider <a> tag
	'onMouseOver=\'setCursor(this);' + '\' '  + 'onClick=\'sortTable(';
//'onMouseOver=\'setCursor(this);' + 'setColor(this,"selected");\' ' + 'onMouseOut=\'setColor(this,"default");\' ' + 'onClick=\'sortTable(';
// Configurable constants
var ascChr = "9650";			// int value from Symbol for ascending sort
var desChr = "9660";			// int value from Symbol for descending sort
var recDelimiter = '|';			// Char used as a record separator
var titleFace = 'span';			// Specifies the HTML tag for titles
var updownColor = 'gray';		// Specified the color for up/downs 

//*****************************************************************************
// Main function. This is to be associated with onLoad event in <BODY>. 
//
// IMPORTANT: This is the only function that needs to be included in the pages
// to be sorted. The rest of the functions are simply called by this
// function.
//*****************************************************************************
function initTable(obj){
	// Check whether it's viewed by IE 5.0 or greater
	if (! checkBrowser()) return;

	// Local variables
	var countCol;
	var nChildNodes;
	var innerMostNode;
	var nColSpan, nRowSpannedTitleCol, colPos;
	var cell, cellText;
	var titleFound = false;
	var rNRowSpan, rNColSpan;

	// Initializing global table object variable
	try{
	if (obj.tagName == "TABLE"){
		// Assumes that the obj is THE OBJECT
		table = obj;
	}else{
		// Assumes that the obj is the id of the object
		table = document.getElementById(obj);
	}
  }
  catch (e) {
  
  }
	// Check whether it's an object
	if (table == null) return;

	// Check whether it's a table
	if (table.tagName != "TABLE") return;

	// Initializing the max col number with the size of last data row
	maxNCol = table.rows[table.rows.length-1].cells.length;

	// Initializing arrays
	rowArray = new Array();
	colSpanArray = new Array();
	colTitleFilled = new Array();
	titleRowArray = new Array();
	titleRowCellArray = new Array();
	rowElemArray = new Array();
	
	for (var i=0; i<maxNCol; i++)
		colTitleFilled[i] = false;

	// Setting the number of rows
	nRow = table.rows.length;	

	// Should have at least 1 row
	if (nRow < 1) return;

	// Initialization of local variables
	actualNRow = 0;			// Number of actual data rows
	rNRowSpan = 0;			// Remaining rows in the row span
	rNColSpan = 0;			// Remaining cols in the col span
	nRowSpannedTitleCol = 0;	// Number of title cols from row span
		
	// Loop through rows
	for (var i=0; i<nRow; i++){
		nColSpan = 1, colPos = 0;
		// Loop through columns
		// Initializing
		for (var j=0; j<table.rows[i].cells.length; j++){
			// Do this iff title has not been found
			if (titleFound == false){
				if (table.rows[i].cells[j].rowSpan > 1){
					if (table.rows[i].cells[j].colSpan < 2){
						titleSpanCellArray[colPos] = table.rows[i].cells[j];
						colTitleFilled[colPos] = true;
						nRowSpannedTitleCol++;
					}
					if (table.rows[i].cells[j].rowSpan - 1> rNRowSpan){
						rNRowSpan = table.rows[i].cells[j].rowSpan - 1;
						if (table.rows[i].cells[j].colSpan > 1)
							rNColSpan = rNRowSpan + 1;
					}
				}
			}
			if (table.rows[i].cells[j].colSpan > 1 &&	rNColSpan == 0){ 
				nColSpan = table.rows[i].cells[j].colSpan;
				colPos += nColSpan;
			}else{
				colPos++;
			}		
		}
					
		// Setting up the title cells
		if (titleFound == false && nColSpan == 1 && rNRowSpan == 0 && rNColSpan == 0 && titleFound == false){
			colSpanArray[i] = true;
			titleFound = true;

			// Using indivisual cell as an array element
			countCol = 0;
			for (var j=0;j<table.rows[i].cells.length + nRowSpannedTitleCol; j++){
				if (colTitleFilled[j] != true){
					titleRowCellArray[j] = table.rows[i].cells[countCol];
					countCol++;
				}else{
					titleRowCellArray[j] = 
						titleSpanCellArray[j];
				}
			}
		}
		// Setting up the data rows
		else if (titleFound == true && nColSpan == 1 && rNRowSpan == 0){
			for (var j=0; j<table.rows[i].cells.length; j++){
				// Can't have row span in record rows ...
				if (table.rows[i].cells[j].rowSpan > 1) return;
				nChildNodes = table.rows[i].cells[j].firstChild.childNodes.length;
				innerMostNode = table.rows[i]. cells[j].firstChild;
				//check browser because the IE don't accept to write innerHTML to a table
				if(isIE){
					if(j==0){ 
						rowElemArray[actualNRow] = table.rows[i].cells[j].innerHTML; 
					}else{
						rowElemArray[actualNRow] += recDelimiter + table.rows[i].cells[j].innerHTML; 
					}
				}else{
					if((j % table.rows[i].cells.length) == 0) { 
						rowElemArray[actualNRow] = table.rows[i].innerHTML; 
					} 
				}
				// Searchtext from Cell
			  var searchText = null;
			  var activCell = table.rows[i].cells[j];
			  for(var pr=0; pr < activCell.childNodes.length; pr++){
			  	// look for a alternativ saerchorderfield
			  	if ( activCell.childNodes[pr].tagName == "INPUT" && activCell.childNodes[pr].type == "hidden" ){
			  		searchText = activCell.childNodes[pr].defaultValue;
					}
				}
			  if( searchText == null){
				  while ( nChildNodes != 0){
						innerMostNode = innerMostNode.firstChild;
						nChildNodes = innerMostNode.childNodes.length;
					}
				  //get the searchable text from the cell
				  // wenn Tabellenspalte leer ist
				  if(innerMostNode.data == null){
				 	   searchText = ' ';
				  }else {
				     searchText = innerMostNode.data.replace(/^\s*(\S*)/, '$1').toLowerCase();
					}
				  if( searchText != null){
				  	if(searchText == ''){
				   		searchText = table.rows[i].cells[j].textContent.replace(/^\s*(\S*)/, '$1').toLowerCase();
				   		if( searchText != null && searchText == ''){
				   			searchText = ' ';
				   		}
				  	}else if(searchText.charCodeAt(0) == 160){
				  		searchText = ' ';
				  	}	
				  }
				}
				if (j == 0){
					rowArray[actualNRow] = searchText;
				}else{
					rowArray[actualNRow] += recDelimiter + searchText;
				}
			}
			// Inconsistent col lengh for data rows
			if (table.rows[i].cells.length > maxNCol)
				return;
			actualNRow++;
			colSpanArray[i] = false;
		}
		else if (nColSpan == 1 && rNRowSpan == 0 && 
			rNColSpan == 0 && titleFound == false)
		{
			colSpanArray[i] = false;
		}else{
			colSpanArray[i] = true;
		}
		
		// Counters for row/column spans
		if (rNRowSpan > 0) rNRowSpan--;
		if (rNColSpan > 0) rNColSpan--;
	}

	// If the row number is < 1, no need to do anything ...
	if (actualNRow < 1) return;
	// Re-drawing the title row
	for (var j=0; j<maxNCol; j++){
		// If for some reason, the rows do NOT have any child, then
		// simply return ...
		if (titleRowCellArray[j].childNodes.length == 0) return;
		if (titleRowCellArray[j].firstChild != null){
			// delete HTML-Tags in cellText without <br>
			cellText = titleRowCellArray[j].innerHTML.replace(/<\s*?br\s*?\/?>/gi,'§br§').replace(/<.[^>]*>/gi, '').replace(/§br§/gi,'<br />');
			//delete ascChr or desChr in cellText
			cellText = cellText.replace(new RegExp(String.fromCharCode(ascChr),"g"),"");
			cellText = cellText.replace(new RegExp(String.fromCharCode(desChr),"g"),"");	
		}else{
			cellText = "column(" + j + ")";
		}
		titleRowArray[j] = cellText;
		titleRowCellArray[j].innerHTML = '<a ' + linkEventString + j + ',' + '"' + table.id + '"' + ');\'>' +  '<' + titleFace + '>' + cellText + '</' + titleFace +'></a>';
	}
		table.rules = table.rules;
}

//*****************************************************************************
// re-draw table for browsers other IE
//*****************************************************************************
function redrawTableOTHER(){
	for (var i=0; i < rowArray.length; i++){
		PR_IndexArray = rowArray[i].split(recDelimiter);
		PR_IndexArrayLenght = PR_IndexArray.length - 1;	
		PR_Index = PR_IndexArray[PR_IndexArrayLenght];
		table.rows[i+1].innerHTML = rowElemArray[PR_Index];
	}
}

//*****************************************************************************
// re-draw table for IE
//*****************************************************************************
function redrawTableIE(){
	rowCount = 0;
	for (var i=0; i<nRow; i++){
		if (! colSpanArray[i]){
			for (var j=0; j<maxNCol; j++){
				PR_IndexArray = rowArray[rowCount].split(recDelimiter);
				PR_IndexArrayLenght = PR_IndexArray.length - 1;	
				PR_Index = PR_IndexArray[PR_IndexArrayLenght];
				rowContent = rowElemArray[PR_Index].split(recDelimiter);
				table.rows[i].cells[j].innerHTML = rowContent[j];
			}
			rowCount++;
		}
	}
}

//*****************************************************************************
// Function called when user clicks on a title to sort
//*****************************************************************************
function sortTable(index,obj){
	// Re-inializing the table object
	initTable(obj);

	// Local variables
	var nChildNodes;
	var innerMostNode;
	var rowContent;
	var rowCount;
	var cell, cellText;
	var newTitle;
	
	var PR_Index;
	var PR_IndexArray;
	var PR_IndexArrayLenght;
	
	// Can't sort past the max allowed column size
	if (index < 0 || index >= maxNCol) return;
	
	// create index column
	for (var i=0; i<rowArray.length; i++){
		rowArray[i] += recDelimiter + i;		
	}
	
	// Assignment of sort index
	sortIndex = index;
	// Doing the sort using JavaScript generic function for an Array
	rowArray.sort(compare);

	// Re-drawing the title row
	for (var j=0; j<maxNCol; j++)
	{
		cellText = titleRowArray[j];
		cellText = '<' + titleFace +'>' + cellText + '</' + titleFace + '>';
		newTitle = '<a ' + linkEventString + j + ',' + '"' + table.id + '"' + ');\'>' + cellText + '</a>';
		if (j == sortIndex)
		{		
			var fontstyle;
			//Fontstyle HACK
			if(isIE){
				fontstyle = ' <font style=\"font-size:100%; color:'+ updownColor+ '\">';
			}else{
				fontstyle = ' <font style=\"font-size:75%; color:'+ updownColor+ '\">';
			}
			
			var tab = newTitle.search(/<br \/><br \/>/gi);
			//HACK for CSS
			if(tab!= -1){
				var breaks = newTitle.substring(tab,tab+12);
				newTitle = newTitle.substring(0,tab) + newTitle.substring(tab+12, newTitle.length);
			}
							
			newTitle += fontstyle;
			if (descending)
				newTitle += "&#" + desChr + ";";
			else
				newTitle += "&#" + ascChr + ";";
			newTitle += '</font>';
			
			//HACK for CSS
			if(tab!= -1){
				newTitle += breaks ;
			}
		}
		titleRowCellArray[j].innerHTML = newTitle;
	}

	//check browser because the IE don't accept to write innerHTML to a table
	if(isIE){
		redrawTableIE();
	}else{
		redrawTableOTHER();
	}
	// Switching btw descending/ascending sort
	if (descending)
		descending = false;
	else
		descending = true;
}

//*****************************************************************************
// Function to be used for Array sorting
//*****************************************************************************
function compare(a, b){
	// Getting the element array for inputs (a,b)
	var aRowContent = a.split(recDelimiter);
	var bRowContent = b.split(recDelimiter);
	
	// Needed in case the data conversion is necessary
	var aToBeCompared, bToBeCompared;

	if (aRowContent[sortIndex] != ' ' && !isNaN(aRowContent[sortIndex]))
		aToBeCompared = parseInt(aRowContent[sortIndex], 10);
		else
		aToBeCompared = aRowContent[sortIndex];
	if (bRowContent[sortIndex] != ' ' && ! isNaN(bRowContent[sortIndex]))
		bToBeCompared = parseInt(bRowContent[sortIndex], 10);
		else
		bToBeCompared = bRowContent[sortIndex];

	if (aToBeCompared < bToBeCompared)
		if (!descending){
			return -1;
		}else{
			return 1;
		}	
	if (aToBeCompared > bToBeCompared)
		if (!descending){
			return 1;
		}else{
			return -1;
		}
	return 0;
}

//*****************************************************************************
// Function to set the cursor
//*****************************************************************************
function setCursor(obj){
	// Show hint text at the browser status bar
	window.status = "Sort by " + obj.firstChild.innerHTML;
	// Change the mouse cursor to hand or pointer
	if (isIE)
		obj.firstChild.style.cursor = "hand";
	else
		obj.firstChild.style.cursor = "pointer";
}

//*****************************************************************************
// Function to check browser type/version
//*****************************************************************************
function checkBrowser(){
	if (navigator.appName == "Microsoft Internet Explorer" && navigator.appVersion.indexOf("5.") >= 0){
		isIE = true;
		return true;
	}
	// For some reason, appVersion returns 5 for Netscape 6.2 ...
	else if (navigator.appName == "Netscape" && navigator.appVersion.indexOf("5.") >= 0){
		isIE = false;
		return true;
	}
	else
		return false;
}
}		