var filterObj;
var sortObj;
var row = 0;

/*
* Sortiert eine Tabelle nach der Spalte rowNumber und der Methode method
*/
function sortTable(node, method)
{
	// Sortierreihenfolge wird umgekehrt
	direction = direction * (-1);

	// td wird bestimmt
	while (node.nodeName.toLowerCase() != "td" && node.nodeName.toLowerCase() != "th")
	{
		node = node.parentNode;
	}
	// Tabelle wird bestimmt
	var tab = node.parentNode;
	while (tab.nodeName.toLowerCase() != "table")
	{
		tab = tab.parentNode;
	}
	
	var table = new Table(tab);
	table.evalRow(node);
	table.readRows();
	table.sort(method);
	table.writeTable();
}

/*
* Sortiert eine Tabelle nach der Spalte rowNumber und der Methode method
*/
function sortOtherTable(node, method, tab)
{
	// Sortierreihenfolge wird umgekehrt
	direction = direction * (-1);
	
	var table = new Table(tab);
	table.evalRow(node);
	table.readRows();
	table.sort(method);
	table.writeTable();
}

function Table(node)
{
	this.table = node;
	this.row = 0;
	this.rows = new Array();
	
	/**
	* Spalte wird berechnet
	* Warnung: Dies kann nicht funktionieren wenn die zu sortierende Spalte einen colspan besitzt
	*/
	this.evalRow = function(node)
	{
		if (node.getAttribute("colspan") && node.getAttribute("colspan") > 1)
		{
			this.row += parseInt(node.getAttribute("colspan"))-1;
		}
		var sibling = node.previousSibling;
		while (sibling)
		{
			if (sibling.getAttribute("colspan") && sibling.getAttribute("colspan") > 1)
			{
				this.row += parseInt(sibling.getAttribute("colspan"));
			}
			else
			{
				this.row++;
			}
			sibling = sibling.previousSibling;
		}
	}
	
	/**
	* Alle Elemente des tbody werden in einen Array eingefügt
	* Überschriften für eine Tabelle gehören in ein thead !!
	*/
	this.readRows = function()
	{
		// Rows werden ausgelesen und sortiert
		var tbody =  this.table.getElementsByTagName("tbody")[0];
		var rowCount = tbody.childNodes.length;
	
		while (tbody.childNodes.length > 0)
		{
			this.rows.push(tbody.childNodes[0].cloneNode(true));
			tbody.removeChild(tbody.childNodes[0]);
		}
	}
	
	/**
	* Array der Rows wird sortiert
	*/
	this.sort = function(method)
	{
		row = this.row;
		eval ('this.rows = this.rows.sort('+method+');');
	}
	
	/**
	* Ergebnis wird zurückgeschrieben
	*/
	this.writeTable = function()
	{
		var tbody =  this.table.getElementsByTagName("tbody")[0];
		for (i = 0; i < this.rows.length; i++)
		{
			var node = this.rows[i].firstChild;
			while (node)
			{
				node.setAttribute("class", "")
				node = node.nextSibling;
			}
			getActCell(this.rows[i]).setAttribute("class", "highlight");
			if (i % 2 == 0)
			{
				this.rows[i].setAttribute("class", "uneven");
			}
			else
			{
				this.rows[i].setAttribute("class", "even");
			}
			tbody.appendChild(this.rows[i]);
		}
	}
}

/*
* Sortierfunktionen für eine Tabelle. Der Funktionsname muss im Aufruf von sortTable() als methode übergeben werden.
*/
this.getActCell = function(aRow)
{
	var i = 0; 			// Index der Spalten incl. colspan
	var n = 0;			// Index der Spalten ohne Colspan
	var aCell = aRow.childNodes[n];
	while (i < row && aCell )
	{
		if (aCell.getAttribute("colspan") && aCell.getAttribute("colspan") > 1)
		{
			i += parseInt(aCell.getAttribute("colspan"));
		}
		else
		{
			i++;
		}
		n++;
		aCell = aRow.childNodes[n];
	}
	return aCell;
}
/**
* Sortiert nach dem ersten String der nicht Teil eines HTML Tags ist
*/
this.sortByName = function(aRow, bRow)
{
	// Die Tabellenzelle von a wird bestimmt
	var aCell = this.getActCell(aRow);

	// Die Tabellenzelle von b wird bestimmt
	var bCell = this.getActCell(bRow);

	// Inhalt wird bestimmt
	var content = /(<.*?>)*(.*)(<\/.*>)?/;
	var result = content.exec(aCell.innerHTML);
	var aValue = RegExp.$2;
	result = content.exec(bCell.innerHTML);
	var bValue = RegExp.$2;

	// Werte werden vergliechen
	if (aValue.toLowerCase() >= bValue.toLowerCase())
	{
		return 1 * direction;
	}
	return -1 * direction;
}
/**
* Sortiert nach dem Datum, erwartet NUR das Datum in der Tabellenzelle
*/
this.sortByDate = function(aRow, bRow)
{
	// Die Tabellenzelle von a wird bestimmt
	aCell = this.getActCell(aRow);

	// Die Tabellenzelle von b wird bestimmt
	bCell = this.getActCell(bRow);

	// Datum wird in Zahlwerte gewandelt und dann verglichen
	var month = new Array(/Jan/, /Feb/, /Mar/, /Apr/, /Mai/, /Jun/, /Jul/, /Aug/, /Sep/, /Oct/, /Nov/, /Dec/);
	var aValue = aCell.innerHTML;
	for (i = 0; i < month.length; i++)
	{
		aValue = aValue.replace(month[i], i+1);
	}
	aValue = aValue.replace(/\./,"");
	aValue = aValue.split(" ");

	var bValue = bCell.innerHTML;
	for (i = 0; i < month.length; i++)
	{
		bValue = bValue.replace(month[i], i+1);
	}
	bValue = bValue.replace(/\./,"");
	bValue = bValue.split(" ");

	if (aValue == "")
	{
		return 1 * direction;
	}
	if (bValue == "")
	{
		return -1 * direction;
	}

	// Jahr wird verglichen
	if ((parseInt(aValue[2]) > parseInt(bValue[2])))
	{
		return 1 * direction;
	}
	else
	{
		if (parseInt(aValue[2]) == parseInt(bValue[2]))
		{
			// Monat wird verglichen, Jahr ist gleich
			if (parseInt(aValue[1]) > parseInt(bValue[1]))
			{
				return 1 * direction;
			}
			else 
			{
				if (parseInt(aValue[1]) == parseInt(bValue[1]))
				{
					// Tag wird verglichen, Monat u. Jahr sind gleich
					if (parseInt(aValue[0]) > parseInt(bValue[0]))
					{
						return 1 * direction;
					}
					else
					{
						if (parseInt(aValue[0]) == parseInt(bValue[0]) && aValue.length > 3 && bValue.length > 3)
						{
							// Uhrzeit wird vergliechen wird verglichen, Monat u. Jahr sind gleich
							if (aValue[3] > bValue[3])
							{
								return 1 * direction;
							}
						}
					}
				}
			}
		}
	}
	return -1 * direction;
}

/*
* Sortiert nach der ersten Nummer, die nicht Teil eines HTML Tags ist
*/
var dummerCounter = 0;
this.sortByNumber = function(aRow, bRow)
{
	try
	{
		dummerCounter++;
		// Die Tabellenzelle von a wird bestimmt
		var aCell = this.getActCell(aRow);
	
		// Die Tabellenzelle von b wird bestimmt
		var bCell = this.getActCell(bRow);
	
		var content = /(<.*?>)*(-?\d+)/;
		var aValue;
		var result = content.exec(aCell.innerHTML);
		if (result)
		{
			aValue = parseFloat(RegExp.$2);
		}
		result = content.exec(bCell.innerHTML);
		var bValue;
		if (result)
		{
			bValue = parseFloat(RegExp.$2);
		}

		if (isNaN(aValue))
		{
			if (isNaN(bValue))
			{
				return 1 * direction;
			}
		}
		else
		{
			if (isNaN(bValue))
			{
				return 1 * direction;
			}
			else
			{
				if ((aValue - bValue) >= 0)
				{
					return 1 * direction;
				}
			}
		}
		return -1 * direction;
	}
	catch(e)
	{
		return 1 * direction;
	}
}



/*
* Filtern einer Tabelle
*/
function FilterTable()
{
	// Spalte auf die gefiltert werden soll
	this.row = 0;
	// Filtermöglichkeiten
	this.options = new Array();
	this.specialOption = "<div><a href='#' onclick='filterObj.unFilterTable();'>Alle Filter l&ouml;schen</a></div>";

	/*
	* Ermittelt die Tabelle die zu der Zelle gehört
	* Erwartet die Tabellenzelle als Parameter
	*/
	this.getTable = function(node)
	{
		while (node.nodeName.toLowerCase() != "table")
		{
			node = node.parent;
		}
	}

	/*
	* Ermittelt die Reihe der Tabellenzelle
	* Erwartet die Tabellenzelle als Parameter
	*/
	this.getRow = function(node)
	{

		for (var i = 0; i < node.parent.childNodes.length; i++)
		{
			if (node.parent.childNodes[i] === node)
			{
				this.row++;
				break;
			}
			else
			{
				// Es wird überprüft ob die Zelle mehrere Spalten umspannt
				if (node.parent.childNodes[i].colSpan > 0)
				{
					this.row += node.parent.childNodes[i].colSpan;
				}
				else
				{
					this.row++;
				}
			}
		}
	}

	/*
	* Tabelle wird gefiltert
	*/
	this.filterTable = function()
	{
		var checkedOptions = new Array();
		// Options werden ermittelt
		for (i = 0; i < document.filter.elements.length; i++)
		{
			if (document.filter.elements[i].checked)
			{
				checkedOptions.push(this.options[i]);
			}
		}

		if (checkedOptions.length == 0)
		{
			// Falls keine Option gewählt wurde, wird die gesammt Tabelle angezeigt
			this.unFilterTable();
		}
		else
		{
			// Tabelle wird entsprechend den Option gefiltert
			var even = true;
			for (var i = this.startRow; i < this.tableBody.childNodes.length; i++)
			{
				if (this.tableBody.childNodes[i].nodeName.toLowerCase() == "tr")
				{
					try
					{
						// Es wird überprüft ob die tr auf die Filterbedingungen zutrifft
						if (this.checkOption(this.tableBody.childNodes[i], checkedOptions))
						{
							
							this.showRow(i, even);
							even = even == false;
						}
						else
						{
							// Tabellereihe wird ausgeblendet
							this.hideRow(i);
						}
					}
					catch(e)
					{
						// Tabellereihe wird ausgeblendet
						this.hideRow(i);
					}
				}
			}
		}
	}
	
	/*
	* Zeigt eine Tabelenzeile angezeigt
	* i = Zeile der Tabelle
	* even gibt Farbangaben an
	*/
	this.showRow = function(i, even)
	{
		// Tabellereihe wird angezeigt
		try
		{
			this.tableBody.childNodes[i].style.display = "table-row";
		}
		catch(e)
		{
			this.tableBody.childNodes[i].style.display = "block";
		}
	}
	
	this.hideRow = function(i)
	{
		this.tableBody.childNodes[i].style.display = "none";
	}

	/*
	* Filtern einer Tabelle aufheben
	* Alle Spalten werden durchlaufen und sichtbar gemacht
	* XXX Die Spaltenhintergrundfarbe wird aktualisiert
	*/
	this.unFilterTable = function()
	{
		// Filteroptionen werden zurückgesetzt, es wird das Formular "Filter" angesprochen
		for (i = 0; i < document.filter.elements.length; i++)
		{
			document.filter.elements[i].checked = false;
		}
		for (var i = 1; i < this.tableBody.childNodes.length; i++)
		{
			if (this.tableBody.childNodes[i].nodeName.toLowerCase() == "tr")
			{
				// Tabellereihe wird angezeigt
				try
				{
					this.tableBody.childNodes[i].style.display = "table-row";
				}
				catch(e)
				{
					this.tableBody.childNodes[i].style.display = "block";
				}
			}
		}

	}

	/*
	* Generiert und zeigt die Filteroptionen für eine Tabelle an
	* event ist das auslösende Event (wird für die Positionierung verwendet)
	*/
	this.displayFilterOptions = function(event)
	{
		// DIV das die Filteroptionen enthält
		this.filter = document.getElementById("filter");
		// Inhaltsbereich für die Filteroptionen
		this.filterContent = document.getElementById("filterContent");

		// Optionen werden hinzugefügt
		this.filterContent.innerHTML = "";
		for (var i = 0; i < this.options.length; i++)
		{
			var inputNode = document.createElement("input");

			var typeAttr = document.createAttribute("type");
			typeAttr.nodeValue = "checkbox";
			inputNode.setAttributeNode(typeAttr);

			var onclickAttr = document.createAttribute("onclick");
			onclickAttr.nodeValue = "filterObj.filterTable();";

			//onclickAttr.nodeValue = "filterTable('0');";
			inputNode.setAttributeNode(onclickAttr);

			var nameAttr = document.createAttribute("name");
			nameAttr.nodeValue = "filterOption";
			inputNode.setAttributeNode(nameAttr);

			var valueAttr = document.createAttribute("value");
			valueAttr.nodeValue = this.options[i].value;
			inputNode.setAttributeNode(valueAttr);

			this.filterContent.appendChild(inputNode);

			this.filterContent.appendChild(document.createTextNode(this.options[i].title));
			this.filterContent.appendChild(document.createElement("br"));
		}

		this.filterContent.innerHTML += this.specialOption;

		// filter wird angezeigt
		this.filter.style.display = "block";

		positionElement(event, this.filter, this.row);
	}


	/*
	* Erstellt einen Array mit Filteroptionen.
	* Durchläuft die Tabelle und sucht Filteroptionen
	*/
	this.getFilterOptions = function ()
	{
		for (var i = 3; i < this.table.firstChild.childNodes.length; i++)
		{
			if (this.table.firstChild.childNodes[i].nodeName.toLowerCase() == "tr")
			{
				try
				{
					var option = this.getFilterOption(this.table.firstChild.childNodes[i].childNodes[this.row]);
					if (!this.options.inArray(option))
					{
						this.options.push(option);
					}
				}
				catch(e)
				{
				}
			}
		}
	}
}

/*
* Es werden von den Images die Title-Attributs ausgelesen
* Erwartet eine Tabellenzelle im Konstructor
*/
function FilterByImg()
{
	//Membervariablen werden gesetzt
	this.table = this.getTable(cell);
	this.row = this.getRow(cell);

	this.getFilterOption = function()
	{
		return new Option(node.firstChild.title, node.firstChild.title);
	}
}
FilterByImg.prototype = new FilterTable();

/*
* Es wird nach den Lektionen gefiltert
*/
function FilterLection(table)
{
	/*
	* Membervariablen werden gesetzt
	*/
	// Tabelle die gefiltert wird
	this.table = table;
	this.tableBody = this.table.getElementsByTagName("tbody")[0];

	
	// Aktiviert die Sonderfilteroption
	this.nonSorted = false;
	this.startRow = 0;

	this.specialOption = "<div><a href='#' onclick='filterObj.filterUnSorted();'>Nicht eingeteilte Vokabeln</a></div>" + this.specialOption;

	/*
	* Zeigt nur noch nicht eingeteilte Vokabeln an
	*/
	this.filterUnSorted = function()
	{
		for (var i = this.startRow; i < this.tableBody.childNodes.length; i++)
		{
			if (this.tableBody.childNodes[i].nodeName.toLowerCase() == "tr")
			{
				try
				{
					if (this.isUnSorted(this.tableBody.childNodes[i]))
					{
						// Tabellenreihe wird angezeigt
						this.showRow(i, true);
					}
					else
					{
						// Tabellenreihe wird ausgeblendet
						this.hideRow(i);
					}
				}
				catch(e)
				{
					// Tabellenreihe wird ausgeblendet
						this.hideRow(i);
				}
			}
		}
	}
	
	/*
	* Überprüft ob in einer Zeile keine CHeckboxen gesetzt sind
	*/
	this.isUnSorted = function(tableRow)
	{
		for (var n = 0; n < tableRow.childNodes.length; n++)
		{
			try
			{
				var cell = tableRow.childNodes[n];
				if ( cell.firstChild.nodeName.toLowerCase() == "input" && cell.firstChild.checked)
				{
					return false;
				}
			}
			catch(e)
			{
			}
		}
		return true;
	}
			
	/*
	* Erstellt einen Array mit Filteroptionen.
	* Overload für die Methode in FilterTable
	*/
	this.getFilterOptions = function()
	{
		var tableBody = document.getElementById("arrangeTableHeader").getElementsByTagName("tbody")[0];
		for (i = 3; i < tableBody.childNodes[0].childNodes.length-1; i++)
		{
			try
			{
				this.options.push(new Option(tableBody.childNodes[0].childNodes[i].innerHTML, i+2));
			}
			catch(e)
			{
			}
		}
	}

	/*
	* Überprüft ob auf diese Reihe die Filteroptionen zutreffen
	* Erwartet als Parameter die Tabellereihe und die gewählten Optionen
	*/
	this.checkOption = function(tableRow, checkedOptions)
	{
		for (var n = 0; n < checkedOptions.length; n++)
		{
			var cell = tableRow.childNodes[checkedOptions[n].value];
			if ( cell.firstChild.nodeName.toLowerCase() == "input" && cell.firstChild.checked)
			{
				return true;
			}
		}
		return false;
	}

	this.getFilterOptions();
}
FilterLection.prototype = new FilterTable();

/*
* Es wird nach dem Inhalt der Tabellenzelle gefiltert
* Erwartet eine Tabellenzelle im Konstructor
*/
function FilterName(cell)
{
	table.firstChild.childNodes.length >= 5

	//Membervariablen werden gesetzt
	this.table = this.getTable(cell);
	this.row = this.getRow(cell);

	this.getFilterOption = function(cell)
	{
		return new Option(cell.innerHTML, cell.innerHTML);
	}
}
FilterByImg.prototype = new FilterTable();

/*
* Es wird nach der Domain gefiltert
* Erwartet eine Tabellenzelle im Konstructor
*/
function FilterDomain(cell)
{
	//Membervariablen werden gesetzt
	//this.table = this.getTable(cell);
	//this.row = this.getRow(cell);

	this.getFilterOption = function(node)
	{
		return new Option( node.innerHTML.match(/\[(\<\w+\>)?\w*\.?(<\/\w+\>)?\]/)[0].replace(/(\<\w+\>)|(<\/\w+\>)/g,""),node.innerHTML.match(/\[(\<\w+\>)?\w*\.?(<\/\w+\>)?\]/)[0].replace(/(\<\w+\>)|(<\/\w+\>)/g,""));
	}
	
	/*
	* Überprüft ob auf diese Reihe die Filteroptionen zutreffen
	* Erwartet als Parameter die Tabellereihe und die gewählten Optionen
	*/
	this.checkOption = function(tableRow, checkedOptions)
	{
		var option = this.getFilterOption(tableRow.childNodes[this.row]);
		return checkedOptions.inArray(option);
	}
}
FilterDomain.prototype = new FilterTable();

/*
* Eine Filteroption
*/
function Option(title, value)
{
	this.title = title;
	this.value = value;
	
	this.isEqual = function(obj)
	{
		if (typeof this == typeof obj && this.title == obj.title && this.value == obj.value)
		{
			return true;
		}
		return false;
	}
}




function positionElement(event, div, direction)
{
	var y;
	if (self.pageYOffset) // all except Explorer
	{
		y = self.pageYOffset;
	}
	else if (document.documentElement && document.documentElement.scrollTop)
	// Explorer 6 Strict
	{
		y = document.documentElement.scrollTop;
	}
	else if (document.body) // all other Explorers
	{
		y = document.body.scrollTop;
	}

	if (event.pageX)

	{
		var pageX = event.pageX;
		var pageY = event.pageY;
	}
	else
	{
		var pageX = event.clientX;
		var pageY = event.clientY + y;
	}

	div.style.right = "";
	if (direction > 0)
	{
		div.style.left = (pageX - 10)+ "px";
	}
	else
	{
		div.style.left = "";

		var innerWidth, offSetY, pageX, pageY;

		/**
		* Die X/Y-Position "pageX, pageY" des Events wird bestimmt
		* Fuer den IE muss dazu der Scroll-Offset "offSetY"  bestimmt werden
		*/
		if (self.pageYOffset) // all except Explorer
		{
			offSetY = self.pageYOffset;
		}
		else if (document.documentElement && document.documentElement.scrollTop)
		// Explorer 6 Strict
		{
			offSetY = document.documentElement.scrollTop;
		}
		else if (document.body) // all other Explorers
		{
			offSetY = document.body.scrollTop;
		}
		if (event.pageX)
		{
			pageX = event.pageX;
		}
		else
		{
			pageX = event.clientX;
		}

		/**
		* Fensterbreite "innerWidth" wird bestimmt.
		*/
		if (self.innerHeight)
		{
			// alle Browser auser IE
			innerWidth = self.innerWidth;
		}
		else if (document.documentElement && document.documentElement.clientHeight)
		{
			// IE 6 Strict Mode
			innerWidth = document.documentElement.clientWidth;
		}
		else if (document.body)
		{
			// andere IEs
			innerWidth = document.body.clientWidth;
		}
		if ((!is_opera) || is_opera9up)
		{
			div.style.right = (innerWidth - pageX - 30)+ "px";
		}
		else
		{
			div.style.left = (pageX - 10)+ "px";
		}
	}
	div.style.top = (pageY - 10) + "px";
}


/*
* Zeigt die Filteroptionen für eine Tabelle an
* alte noch im dict Verwendete Funktion
*/
function displayFilterOptionsTable(event, idTable, rowNumber, method)
{
	if (!(filterObj && filterObj instanceof FilterDomain && rowNumber == filterObj.row))
	{
		if (filterObj && filterObj instanceof FilterDomain)
		{
			filterObj.unFilterTable();
		}
		
		filterObj = new FilterDomain();
		filterObj.table = document.getElementById(idTable);
		filterObj.row = rowNumber;
		filterObj.getFilterOptions();
		filterObj.tableBody = filterObj.table.firstChild;
		filterObj.startRow = 3;
		filterObj.displayFilterOptions(event);
	}
	else
	{
		filterObj.filter.style.display = "block";
	}
}