	// Contains all record for table beign sorted ( except title )
	lines = new Array();

	/**
	 * Used so save table lines into array of records
	 */
	function saveTable(tableId){

		var table = document.getElementById(tableId);

		if (!tableId){
			alert('Error handling ' + tableId);
			return false;
		} // if

		var tbody = table.getElementsByTagName('tbody')[0];
		var trs = table.getElementsByTagName('tr');
	
		lines.length = 0;

		// Do not touch title
		for (var i = 1; i < trs.length; i++){
			lines[lines.length] = trs[i].cloneNode(true);

		} // for

		return true;

	} // function 

	/**
	 * Removes records from table.
	 */
	function clearTable(tableId){

		var table = document.getElementById(tableId);

		if (!tableId){
			alert('Error handling ' + tableId);
			return false;
		} // if

		var tbody = table.getElementsByTagName('tbody')[0];
		var trs = table.getElementsByTagName('tr');
	
		// Do not toch title
		// Removing values
		while (trs.length > 1){
			tbody.removeChild(trs[trs.length - 1]);
		} // for

		return true;

	} // function 

	function restoreTableFromLines(tableId){
		
		var table = document.getElementById(tableId);

		if (!tableId){
			alert('Error handling ' + tableId);
			return false;
		} // if

		var tbody = table.getElementsByTagName('tbody')[0];
		var trs = table.getElementsByTagName('tr');

		for (var i = 0; i < lines.length; i++)
			tbody.appendChild(lines[i]);

		return true;

	} // function

	function sortLines(columnNum, order, withDescriptions){

		if (!withDescriptions)
			withDescriptions = false;

		// We don't need first line

		if (!withDescriptions)
		for (var i = lines.length - 1; i > 0; i--)
			for (var j = 0; j < i; j++){
				if (firstTrIsGreater(lines[j], lines[j + 1], columnNum, order)){
					var temp = lines[j];
					lines[j] = lines[j + 1];
					lines[j + 1] = temp;

				} // if
			} // for
		else {
			// If we use descriptions, every line consists of two lines
			// the first is for regular columns and the second is for description.
			// So we sort the according to that.
			var doubleLinesCount = lines.length;

			if ((doubleLinesCount % 2) == 1) {
				// The table is probably contains no records.
				// Just return in this case.
				return false;
			} // if

			var meanLinesCount = parseInt( doubleLinesCount / 2 );
			for (var i = meanLinesCount - 1; i > 0; i--) {
				for (var j = 0; j < i; j++){
				    var index_j = 2 * j;
					if ( firstTrIsGreater(lines[ index_j ], lines[ index_j + 2 ], columnNum, order) ){

						// swap both of the columns.
						var temp = lines[index_j];
						lines[index_j] = lines[index_j + 2];
						lines[index_j + 2] = temp;

						// swap both of the columns.
						temp = lines[index_j + 1];
						lines[index_j + 1] = lines[index_j + 3];
						lines[index_j + 3] = temp;

					} // if

				} // for
			} // for

		} // else (the table with descriptions)

		return true;

	} // function

	function sortTable(tableId, columnNum, order, withDescriptions){

		if ( !withDescriptions )
			withDescriptions = false;

		if ( tableId.indexOf('table_') < 0 )
			tableRealId = 'table_' + tableId;
		else tableRealId = tableId;

		// save table to lines array.
		saveTable( tableRealId );

		// sort lines in dedicated array.
		sortLines( columnNum, order, withDescriptions );

		// restore odd lines
		restoreOddLines( withDescriptions );

		// remove lines from original table.
		clearTable( tableRealId );

		// restore new (sorded) lines.
		restoreTableFromLines( tableRealId );

		// fix table values.
		fixTableSortingView( tableId, columnNum, order, withDescriptions );
	
		return true;

	} // function

	/**
	 * Used to compare table lines. 
	 */
	function firstTrIsGreater(first, second, columnNum, order){

		if (!first || !second){
			alert('Lines are not valid.');
			return false;

		} // if

		var firstColumn = first.getElementsByTagName('td')[columnNum];

		var secondColumn = second.getElementsByTagName('td')[columnNum];

		firstColumnValue = firstColumn.getAttribute("sort_value");
		secondColumnValue = secondColumn.getAttribute("sort_value");

		var intRe = new RegExp('^[0-9]+$');

		if (firstColumnValue.match(intRe))
			firstColumnValue = parseInt(firstColumnValue);

		if (secondColumnValue.match(intRe))
			secondColumnValue = parseInt(secondColumnValue);

		if (order == 'asc'){

			if (firstColumnValue > secondColumnValue){
				return true;
			} // if
			else {
				return false;
			} // else

		} // if
		else {

			if (firstColumnValue < secondColumnValue){
				return true;
			} // if
			else {
				return false;
			} // else

		} // else
	
	} // fucntion 

	/**
	 * Shows description id for table id and line number.
	 */
	function showFileDescription( tableId, lineNumber ) {

		var elemName = 'description_' + tableId + '_' + lineNumber;
		var tdElementName = 'td_container_' + tableId + '_' + lineNumber;
		var tableElemName = 'table_' + tableId;
		var trElementName = 'tr_container_' + tableId + '_' + lineNumber;

		var elem = document.getElementById( elemName );

		// if already displayed
		if (elem.style.zIndex > 0)
			return false;

		var tdElem = document.getElementById( tdElementName );
		var tableElem = document.getElementById( tableElemName );
		var trElem = document.getElementById( trElementName );

		trInfo = elementInfo( trElem );

		// [curleft , curtop, oheight, owidth]
		var trElemTop = trInfo[1];
		var trElemLeft = trInfo[0];
		var trElemWidth = trInfo[3];

		// [curleft , curtop, oheight, owidth]
		var containerInfo = elementInfo( elem );
		var tableInfo = elementInfo( tableElem );
		var newLeft = containerInfo[0];
		var newTop = parseInt( containerInfo[1] ) + parseInt( containerInfo[2] );
		var newWidth = tableInfo[3];

		// Set positions for our element.
//		elem.style.position = "absolute";
		elem.style.zIndex = 100;

//		elem.style.width = parseInt( trElemWidth - 50 ) + 'px';

		elem.style.padding = '10px';
		elem.style.marginLeft = '30px';
		elem.style.backgroundColor = 'white';
		elem.style.borderRightWidth = '1px';
		elem.style.borderRightStyle = 'dotted';
		elem.style.borderRightColor = '#999';
		elem.style.borderLeftWidth = '1px';
		elem.style.borderLeftStyle = 'dotted';
		elem.style.borderLeftColor = '#999';

		appear( elem );

		var displayedElemInfo = elementInfo( elem );
		var displayedElemHeight = displayedElemInfo[2];

//		trElem.style.height = ( parseInt( trElem.offsetHeight ) + parseInt( displayedElemHeight )) + "px";

		elem.style.top = ( parseInt( trElemTop ) + parseInt( trElem.offsetHeight ) - parseInt( displayedElemHeight ) ) + "px";
		elem.style.left = parseInt( trElemLeft + 25 ) + "px";

		return;

	} // function

	
	function fixAllDescriptions(){

		if (!window.allSortedTables)
			return;

		var fixedCount = 0;

		for (var tableIndex = window.allSortedTables.length - 1; tableIndex >= 0; tableIndex--){
			var tableElem = document.getElementById( "table_" + window.allSortedTables[ tableIndex ] );
			if (!tableElem) {
				alert("Error handling " + "table_" + window.allSortedTables[ tableIndex ]);
				continue;
			} // if

			var tableId = tableElem.getAttribute( "id" );
			if (tableId.length == 0){
				alert( "Empty id for " + window.allSortedTables[ tableIndex ] );
				continue;
			}

			setTimeout( "fixAllDescriptionPositionsFor( '"+ tableId +"' )", (1 * tableIndex + 1) );

		} // for

		return true;

	} // function
	
	function fixAllDescriptionPositionsFor( tableId ){

		if (tableId.indexOf("table_") == 0){
			tableId = tableId.substr( "table_".length );
		} // if

		var tableElemName = "table_" + tableId;

		var tableElem = document.getElementById( tableElemName );

		var allTrs = tableElem.getElementsByTagName("tr");

		for (var lineNumber = 0; lineNumber < allTrs.length; lineNumber++){

			var elemName = 'description_' + tableId + '_' + lineNumber;
			var tdElementName = 'td_container_' + tableId + '_' + lineNumber;
			var trElementName = 'tr_container_' + tableId + '_' + lineNumber;

			var elem = document.getElementById( elemName );

			if ( !elem )
				continue;

			// if already displayed 
			if (elem.style.zIndex > 0){

				var tdElem = document.getElementById( tdElementName );
				var trElem = document.getElementById( trElementName );

				trInfo = elementInfo( trElem );

				var trElemTop = trInfo[1];

				// [curleft , curtop, oheight, owidth]
				var containerInfo = elementInfo( elem );
				var tableInfo = elementInfo( tableElem );
				var newLeft = containerInfo[0];
				var newTop = parseInt( containerInfo[1] ) + parseInt( containerInfo[2] );
				var newWidth = tableInfo[3];

				var displayedElemInfo = elementInfo( elem );
				var displayedElemHeight = displayedElemInfo[2];

				elem.style.top = ( parseInt( trElemTop ) + parseInt( trElem.offsetHeight ) - parseInt( displayedElemHeight ) ) + "px";

			} // if it is displayed element

		} // for

		return true;

	} // function

	/**
	 * Hide description.
	 */
	function hideFileDescription( tableId, lineNumber ) {

		var elemName = 'description_' + tableId + '_' + lineNumber;
		var elem = document.getElementById( elemName );

		var elemInfo = elementInfo( elem );
		var elemHeight = elemInfo[ 2 ];

		// If already hidden do nothing
		if ( elem.style.zIndex == 0 )
			return false;

		elem.style.zIndex = 0;
	
		disappear( elem );

		// fix the original size of the tr.
		var trElemName = 'tr_container_' + tableId + '_' + lineNumber;
		trElem = document.getElementById( trElemName );
//		trElem.style.height = ( parseInt( trElem.offsetHeight ) - elemHeight ) + "px";

		return;

	} // function

	/**
	 * Fix table attributes.
	 */
	function fixTableSortingView(tableId, column, order, withDescriptions){

		// First fix the links target
		var AlinkElem = document.getElementById( tableId + "_sortLink_" + column );
		if (!AlinkElem) {
			alert("Error handling " + tableId + "_sortLink_" + column );
			return false;
		} // if

		var revOrder = order == 'desc' ? 'asc' : 'desc';
		var withDescriptionsStr = withDescriptions ? 'true' : 'false';

		AlinkElem.href = "javascript:sortTable(\'" + tableId + "\', " + column + ", \'" + revOrder + "\', " + withDescriptionsStr + "); fixAllDescriptionPositionsFor( \'" + tableId + "\' ); void 0;";

		// clear the previous sort image
		// set the current image.
		var done = false;
		colIndex = 0;
		while ( !done ) {
			var elemToProcess = document.getElementById( "table_sort_icon_" + tableId + "_" + colIndex);

			if (!elemToProcess)
				break;

			else if ( colIndex == column ){

				if (order == "desc")
					elemToProcess.innerHTML = "<img src=\"fileadmin/stuff/images/tools/down.gif\">";
				else elemToProcess.innerHTML = "<img src=\"fileadmin/stuff/images/tools/up.gif\">";

			} // if it is current image
			else elemToProcess.innerHTML = "";

			colIndex++;

		} // while

		return true;

	} // function

	/**
	 * After sorting the oddness is broken. Have to fix.
	 */
	function restoreOddLines( withDescriptions ){

		if (!window.lines)
			return false;

		if (!withDescriptions)
			withDescriptions = false;
			 	
		var i = 1;
		for (; i <= window.lines.length; i++){

			if (!withDescriptions)

				if ( i % 2 ){
					window.lines[i - 1].className = 'odd';
				}
				else {
					window.lines[i - 1].className = '';
				} // else

			else 

				if ( (i % 4) == 1){
					window.lines[i - 1].className = 'odd';
				}
				else {
					window.lines[i - 1].className = '';
				} // else

		} // for

		return true;

	} // function

	function plusToMinus(obj, tableId, rowNum){

		obj.setAttribute("currentState", "minus");
		obj.innerHTML = '<img alt="-" src="/fileadmin/stuff/images/tools/minus_blue.gif" width="9px" heigth="9px">';
		obj.href = 'javascript: hideFileDescription("' + tableId + '" , "' + rowNum + '" ); fixAllDescriptions(); revPlusMinus("' + tableId + '", '+ rowNum +'); void 0;';

	} // function

	function minusToPlus(obj, tableId, rowNum){

		obj.setAttribute("currentState", "plus");
		obj.innerHTML = '<img alt="+" src="/fileadmin/stuff/images/tools/plus_blue.gif" width="9px" heigth="9px">';
		obj.href = 'javascript: showFileDescription("' + tableId + '" , "' + rowNum + '" ); fixAllDescriptions(); revPlusMinus("' + tableId + '", '+ rowNum +'); void 0;';
          
	} // function

	function revPlusMinus( tableId, rowNum ){

		var obj = document.getElementById("href_for_" + tableId + "_" + rowNum);

		if (!obj){
			alert("Error handling element " + "href_for_" + tableId + "_" + rowNum);
			return false;

		} // if

		var currentState = obj.getAttribute("currentState");

		if ( !currentState || currentState == "plus" )
			return plusToMinus( obj, tableId, rowNum );
		else return minusToPlus( obj, tableId, rowNum );

	} // function
