//
// SimpleTable: Schnelle Tabelle mit fixedlines/fixedcolumns u. Sortierung (keine Filtercombos)
//
// Die festgehaltenen Spalten werden erzeugt sobald sie in die Nähe des sichtbaren Bereichs
// der Tabelle gescrollt werden. Dadurch sind auch größere Tabellen mit fixedcolums/fixedlines
// noch schnell im Aufbau. -pf-
//
// TODO: fixedlines in thead unterbringen damit tbody direkt sortiert werden kann.

var simtViewDelay = 30;	// timer [ms] für das verzögerte Update der fixedcolumns Spalten.


// Liefert die IE Version als positive Zahl, die Mozilla Version als negative Zahl und 0 für den Rest.
var simtBV = null;

function simtCheckBrowserVersion()
{
	var oBV = {}, sUserAgent = navigator.userAgent.toLowerCase();
	oBV.isChrome = sUserAgent.indexOf('chrome') > -1;
	oBV.isOpera = sUserAgent.indexOf("opera") > -1;
	oBV.isKHTML = sUserAgent.indexOf("khtml")>-1 || sUserAgent.indexOf("konqueror")>-1 || sUserAgent.indexOf("applewebkit") > -1;
	oBV.isMoz = sUserAgent.indexOf("gecko")>-1 && !oBV.isKHTML;
	oBV.isIE = sUserAgent.indexOf("compatible")>-1 && sUserAgent.indexOf("msie")>-1 && !oBV.isOpera;

	oBV.browserId = 0;	// IE ver. > 0 ,  Moz. ver. < 0 , Rest 0
	if (oBV.isIE)
	{
		var reIE = new RegExp("msie (\\d+\\.\\d+)");
		reIE.test(sUserAgent);
		oBV.browserId = parseFloat(RegExp["$1"]);
	}
	else if (oBV.isMoz)
	{
		var reMoz = new RegExp("rv:(\\d+\\.\\d+(?:\\.\\d+)?)");
		reMoz.test(sUserAgent);
		oBV.browserId = 0-parseFloat(RegExp["$1"]);
	}
	return oBV;
}


function simtRemoveNode(id)
{
	var obj = simtGet(id);
	if (obj && obj.parentNode)
	   obj.parentNode.removeChild(obj);
}


function simtRuntimeStyle(obj)
{
	if (typeof getComputedStyle == 'function')
	{	// Mozilla, Firefox, ...
		return document.defaultView.getComputedStyle(obj,null);
	}
	else
	{	// IE
		return obj.currentStyle;
	}
}


function simtAddEvent(obj, evt, fn, capture)
{
	simtRemoveEvent(obj, evt, fn, capture);
	
	if (obj.addEventListener) {
    	obj.addEventListener(evt, fn, capture);
  	}
  	else if (obj.attachEvent) {
    	return obj.attachEvent("on" + evt, fn);
  	}
}

function simtRemoveEvent(obj, evt, fn, capture) {
	try
	{
		if (obj.removeEventListener)  {
			obj.removeEventListener(evt, fn, capture);
		}
		else if (obj.detachEvent) {
			return obj.detachEvent("on" + evt, fn);
		}
	}
	catch (e) {
	}
}


function simtGet(_ref)
{
	var ref = _ref || window.event;
	var obj = null;
	
	if (typeof ref == 'object') {
		if (ref.tagName)
			obj = ref;
		else if (ref.target) {
			obj = ref.target.tagName ? ref.target : ref.target.parentNode;
		}
		else if (ref.srcElement) {
			obj = ref.srcElement.tagName ? ref.srcElement : ref.srcElement.parentNode;
		}
	}
	else if (typeof ref == 'string') {
		obj = document.getElementById(ref);
	}
	return obj;
}


function simtWaitElement()
{
	return simtGet("GUI_DISABLE") || simtGet("IsyDisable_CONTAINER");
}

function simtWaitCursor(bShow)
{
	var oWait = simtWaitElement();
	if (!oWait)
		return;

	if (bShow) {
		oWait.style.width = "100%";
		oWait.style.height = "100%";
		oWait.style.cursor = "wait";
		oWait.style.visibility = "visible";
	}
	else {
		oWait.style.visibility = "hidden";
	}
}



function simtRemoveSortArrow(id)
{
	simtRemoveNode(id + "_SORT_ARROW");
}


function simtScrollToTableElement(rowId)
{
	if (typeof(rowId) != 'string') 
		return false;
	var oRow = simtGet(rowId);
	if (!oRow)
		return false;

	oRow.scrollIntoView(false);
	return true;
}

	
function simtAddSortArrow(id, oArrow, asc)
{
	var oT = simtGet(id);
	var oDiv = document.createElement("div");
	var oImg = document.createElement("img");
	var w = oArrow.offsetWidth, h = oArrow.offsetHeight;
	var l = parseInt(w) - 12 + oArrow.offsetLeft, t = 3;
	
	oDiv.appendChild(oImg);
	oImg.setAttribute("src", asc ?
		oT.getAttribute('sortarrowup_img') :
		oT.getAttribute('sortarrowdown_img'));
	
	oDiv.id = id + "_SORT_ARROW";
	oDiv.style.position = "absolute";
	oDiv.style.left = String(l)+"px";
	oDiv.style.top = String(t)+"px";
		
	var divId = id + "_" + oArrow.id.substring(0, 3) + "DIV";
	var oArrowDiv = simtGet(divId);
	if (oArrowDiv) {
		oArrowDiv.appendChild(oDiv);
	}
}


function simtGetTableFrom(obj) {
	try
	{
		while(obj.nodeName != "DIV")
			obj = obj.parentNode;
		return simtGet((obj.id).replace("_FC", ""));
	}
	catch (e) {
		return null;
	}
}

function simtGetRowNum(obj) {
	try	{
		var oT = simtGetTableFrom(obj);
		
		while (obj.nodeName != "DIV")
		{
			var p = obj.id.indexOf(oT.id + "_");
			if (p > -1) {
				var rowNum = obj.id.substring(p + oT.id.length + 1);
				return parseFloat(rowNum);
			}
			obj = obj.parentNode;
		}
	}
	catch (e) {
		return null;
	}
}

function simtGetRowFrom(obj) {
	try
	{
		while(obj.nodeName != "TR")
			obj = obj.parentNode;
		return obj;
	}
	catch (e) {
		return null;
	}
}


// unveränderte Compare Funktion
function simtCompareValues(a,b)
{
	var a_tmp = parseFloat(a.replace(',', '.'));
	var b_tmp = parseFloat(b.replace(',', '.'));

	if (!isNaN(a_tmp) && !isNaN(b_tmp))
	{	// Zahlenvergleich
		return a_tmp - b_tmp;
	}
	else if (a != null && b != null)
	{	// Textvergleich
		a_tmp = String(a); //.toUpperCase();
		b_tmp = String(b); //.toUpperCase();
		return a_tmp.localeCompare(b_tmp);
	}
}


function simtScrollHandler(id)
{
	simtAddEvent(simtGet(id), "scroll", simtSetScrollPos, false);
}

function simtRemoveScrollHandler(id)
{
	simtRemoveEvent(simtGet(id), "scroll", simtSetScrollPos, false)
}


function simtSetScrollPos(evt)
{
	//var el = typeof getElementFrom=='function' ? getElementFrom(evt) : simtGetElement(evt);
	var el = simtGet(evt);
	if (typeof el != 'object')
		return;
	
	// horizontales scrollen (inkl. fixedlines)
	var oTFL = simtGet(el.id + "_FL_DIV");
	if (oTFL && el.scrollLeft!=el.lastScrollLeft ) {
   		oTFL.scrollLeft = el.scrollLeft;
   		el.lastScrollLeft=el.scrollLeft;
   	}
  
  	//Comboboxen im fixedlines Bereich ausblenden (IE6 Bug)
  	if (simtBV.browserId > 0 && simtBV.browserId < 7 && el.hideComboLock != true
  		&& oTFL && el.scrollTop != el.hideComboScrollTop)
   	{
   		el.hideComboLock = true;
   		el.hideComboScrollTop = el.scrollTop;
   		setTimeout("simtHideFixedLineCombos('"+el.id+"')",simtViewDelay);
	}
   		
	// vertikales scrollen (inkl. fixedcolumns)
	var oTFC = simtGet(el.id + "_FC");
	if (oTFC && oTFC.getAttribute("_rows_complete"))
	{	// fixedcolumns komplett
		oTFC.scrollTop = el.scrollTop;
	}
	else if (oTFC && el.lockScroll != true && el.scrollTop != el.lastScrollTop)
	{	// fixedcolumns für den sichbaren Bereich erzeugen.
		if (el.scrollLeft == 0)
			oTFC.style.visibility = 'hidden';
		el.lastScrollTop = el.scrollTop;
		el.lockScroll = true;
		setTimeout("simtShowFixedCols('"+el.id+"')",simtViewDelay); 
	}
}



function simtMouseWheelFC(ev)
{
    var evt = ev || window.event;
    var delta = evt.detail ? evt.detail * (-120) : evt.wheelDelta;
	var oT = simtGetTableFrom(simtGet(evt));

	if (delta != 0 && oT) {
		oT.scrollTop -= (delta / 3);
	}
}

function simtSelectRowFC(evt) {
	var obj = simtGet(evt);
	
	if (typeof obj == "object") {
		var rowId = obj.parentNode.id.replace("_FC", "");
		simtSelectRow(rowId);
	}
}



function simtMouseOverOut(ev, out, suf)
{
	var obj = simtGet(ev || window.event);
	var oT = simtGetTableFrom(obj);
	var rowNum = simtGetRowNum(obj);
	var rowId = oT.id + "_" + rowNum;
	
	var fl = oT.getAttribute('fixedlines') || 0;
	if (rowNum < fl)
		return;

	var oRow = simtGet(rowId + suf);
	if (!oRow || oRow.nodeName != "TR")
		return;

	if (oRow) {
		if (!out)
			oRow.style.backgroundColor = oT.getAttribute('hover_bgcolor');
		else
			oRow.style.backgroundColor = "";
	}
}

function simtMouseOverFC(ev)	{ simtMouseOverOut(ev, false, ""); }
function simtMouseOutFC(ev)		{ simtMouseOverOut(ev, true, ""); }

function simtMouseOver(ev)		{ simtMouseOverOut(ev, false, "_FC"); }
function simtMouseOut(ev)		{ simtMouseOverOut(ev, true, "_FC"); }




function simtHideFixedLineCombos(id)
{
	return false; // IE6 ignorieren
	// Comboboxen im Bereich der fixedlines ausblenden und 
	// umgekehrt wieder einblenden. Ab IE7 sollte das Problem
	// erledigt sein.
	
	var oT = simtGet(id);
	var oTFL = simtGet(id + "_FL_DIV");
	if (!oTFL) {
		oT.hideComboLock = false;
		return false;
	}
	if (oT.scrollTop != oT.hideComboScrollTop) {
   		oT.hideComboScrollTop=oT.scrollTop;
   		return setTimeout("simtHideFixedLineCombos('"+id+"')",simtViewDelay);
	}
		
	var cbArray=oT.getElementsByTagName("select");
	var limitTop=parseInt(oT.scrollTop);
	var limitBottom=limitTop+parseInt(oTFL.offsetHeight);

   	for(var i = 0; i < cbArray.length; i++)
   	{
		if (oT.scrollTop != oT.hideComboScrollTop) {
	   		oT.hideComboScrollTop=oT.scrollTop;
	   		return setTimeout("simtHideFixedLineCombos('"+id+"')",simtViewDelay);
		}
   		
   		var cb=cbArray[i];
		if (parseInt(cb.offsetTop+cb.offsetHeight)>=limitTop && parseInt(cb.offsetTop)<=limitBottom)
		{
			if (!cb.getAttribute('hiddenCombo'))
				cb.setAttribute('hiddenCombo','true');
			cb.style.visibility='hidden';
		}
		else if (parseInt(cb.offsetTop)>limitBottom && cb.getAttribute('hiddenCombo'))
		{
			cb.style.visibility='visible';
			cb.removeAttribute('hiddenCombo');
		}
	}
	oT.hideComboLock=false;
	return true;
}



function simtClickHandler(id)
{
	var oT = simtGet(id);
	
	simtAddEvent(oT, "click", simtSelectRow, false);
	
	if ((userFunction = oT.getAttribute('userfunction')) && userFunction!="")
		simtAddEvent(oT, "click", eval(userFunction), false);
		
	if ((dblclickhandler = oT.getAttribute('dblclickhandler')) && dblclickhandler!="")
		simtAddEvent(oT, "dblclick", eval(dblclickhandler), false);
}


function simtClickHandlerFC(id)
{
	var oT = simtGet(id);
	var oTFC = simtGet(id + "_FC");

	//simtAddEvent(oTFC, "click", simtSelectRowFC, false);
	
	if ((userFunction = oT.getAttribute('userfunction')) && userFunction!="")
		simtAddEvent(oTFC, "click", eval(userFunction), false);
		
	if ((dblclickhandler = oT.getAttribute('dblclickhandler')) && dblclickhandler!="")
		simtAddEvent(oTFC, "dblclick", eval(dblclickhandler), false);
}


function simtNoSelectedRow(id)
{
	var oT = simtGet(id);
	var lastSelRow = oT.getAttribute('lastselectedrow') ?
		simtGet(oT.getAttribute('lastselectedrow')) : null;
		
	if (lastSelRow)
	{
		lastSelRow.className = lastSelRow.className.replace("selected", "");
	
		var fc = oT.getAttribute('fixedcolumns_hidden') || 0;
		if (fc > 0)
		{
			var lastSelRowFC = simtGet(lastSelRow.id + "_FC");
			if (lastSelRowFC) {
				lastSelRowFC.className = lastSelRowFC.className.replace("selected", "");
			}
		}
	}
	
	oT.removeAttribute('lastselectedrow');
	
	if (document.isycat && document.isycat[oT.id])
		document.isycat[oT.id].value = "";
}


function simtSelectRow(evt)
{
	var el = simtGet(evt);
	if (el == null || el.nodeName == "DIV" || el.id == "" || el==false)
		return;

	var oT = simtGetTableFrom(el);
	var oRow = simtGetRowFrom(el);
	var fl = oT.getAttribute('fixedlines') || 0;
	var oTBody = oRow.parentNode;

	for (var i = 0; i < fl; i++)
		if (oTBody.childNodes[i] == oRow)
			return false;	// fixedlines nie selektieren

	simtNoSelectedRow(oT.id);
	
	oRow.className += " selected";

	var fc = oT.getAttribute('fixedcolumns_hidden');
	if (fc > 0)
	{
		var oRowFC = simtGet(oRow.id + "_FC");
		if (oRowFC) {
			oRowFC.className += " selected";
		}
	}
	
	// Zur Sicherheit doppelt speichern (Siehe: simtNoSelectedRow)
	oT.setAttribute('lastselectedrow', oRow.id);
	oT.setAttribute('selected', oRow.id);
	
	if (document.isycat && document.isycat[oT.id])
		document.isycat[oT.id].value = oRow.id;
}


function simtGetSelectedRow(id)
{
	var oT = simtGet(id);
	var selectedRowId = !oT ? "" : oT.getAttribute('selected');
	return selectedRowId || "";
}



function simtSetDisabled(id, bDisable)
{
	var oT = simtGet(id);
	if (oT) {
		oT.disabled = bDisable;
		
		var oTFC = simtGet(id + "_FC");
		if (oTFC) oTFC.disabled = bDisable;
		
		var oFC_DIV = simtGet(id + "_FC_DIV");
		if (oFC_DIV) oFC_DIV.disabled = bDisable;
		
		var oFL_DIV = simtGet(id + "_FL_DIV");
		if (oFL_DIV) oFL_DIV.disabled = bDisable;
	}
}

function simtGetDisabled(id)
{
	var oT = simtGet(id);
	return !oT ? false : (oT.disabled == true);
}



function simtGenerateCompareTRs(iCol)
{
	// Neben Text auch Editfelder und Comboboxen sortierbar.
    return function compareTRs(oTR1, oTR2)
	{
		var val1 = oTR1.cells[iCol].firstChild.nodeValue;
		var val2 = oTR2.cells[iCol].firstChild.nodeValue;
		
		for(var oVal1=oTR1.cells[iCol].firstChild ; oVal1.nextSibling!=null ; oVal1=oVal1.nextSibling)
		{
			if (oVal1.nodeName=="INPUT")  { val1=oVal1.value; break; }
			if (oVal1.nodeName=="SELECT") { val1=oVal1.selectedIndex>=0 ? oVal1[oVal1.selectedIndex].text : "" ; break; }
		}

		for(var oVal2=oTR2.cells[iCol].firstChild ; oVal2.nextSibling!=null ; oVal2=oVal2.nextSibling)
		{
			if (oVal2.nodeName=="INPUT") { val2=oVal2.value; break; }
			if (oVal2.nodeName=="SELECT") { val2=oVal2.selectedIndex>=0 ? oVal2[oVal2.selectedIndex].text : "" ; break; }
		}
		
		return simtCompareValues(val1,val2);
	};
}


function simtSortTable(sTableId, iCol, tdObj)
{
	var oT = simtGet(sTableId);
	var oTable = simtGet(sTableId+"_TABLE");
	var oTBody = oTable.tBodies[0];
	var colDataRows = oTBody.rows;
	var nRows=colDataRows.length;
	var aTRs = new Array;
	var aFixTRs = new Array;
	var fl = oT.getAttribute('fixedlines') || 0;
	var fc = oT.getAttribute('fixedcolumns_hidden') || 0;
	var sUserSortFn = oT.getAttribute('usersortfunction') || "";

	fl = parseInt(fl); fc = parseInt(fc);
	
	// eigene Sortierfunktion?
	if (oTable.sortCol != iCol && sUserSortFn != "")
	{
		var sortFn = eval(sUserSortFn);
		if (typeof(sortFn)=="function")
			return sortFn(sTableId,iCol,true);
		else
		{
			alert("usersortfunction error: "+sUserSortFn+" "+typeof(sortFn)); 
			return false;
		}
	}
	
	simtWaitCursor(true);
	
	// fixedlines retten
	for (var i = 0; i < nRows; i++)
	{
		if (i < fl)
			aFixTRs[i] = colDataRows[i];
		else
			aTRs[i-fl] = colDataRows[i];
	}
	
	// Zeilen sortieren.
	if (oTable.sortCol == iCol)
		aTRs.reverse(); // Bereits sortierte Tabelle nur umdrehen
	else
		aTRs.sort(simtGenerateCompareTRs(iCol));

	// geänderte Zeilen wieder ins Dokument
	var oFragment = document.createDocumentFragment();
	for (var i = 0; i < nRows; i++)
	{
		if (i < fl)
			oFragment.appendChild(aFixTRs[i]);
		else
			oFragment.appendChild(aTRs[i-fl]);
	}
	
	oTBody.appendChild(oFragment);
	
	if (oTable.sortCol != iCol)
		oTable.sortAscending = true;
	else
		oTable.sortAscending = !oTable.sortAscending;

	var headerDiv = tdObj.parentNode;
	while (!headerDiv.id)
		headerDiv = headerDiv.parentNode;

	if (oT.getAttribute('sortarrows') != "false") {
		simtRemoveSortArrow(sTableId);
		simtAddSortArrow(sTableId, tdObj, oTable.sortAscending);
	}
	
	oTable.sortCol = iCol;
	
	simtWaitCursor(false);
}


function simtSortColumn(sTableId, colIdx, tdObj)
{
	// nach onclick auf Überschrift die Tabelle sortieren und
	// eventuell die Zeilenfarben neu setzen.
	
	var oT = simtGet(sTableId);
	
	simtSortTable(sTableId, colIdx, tdObj);
	
	if (oT.getAttribute("preparerowcolors")!=null)
	{
		eval(oT.getAttribute("preparerowcolors")+"('"+sTableId+"')");
	}
	else if (typeof setRowStyles=='function')
	{
		setRowStyles(sTableId);
	}

	var fc = oT.getAttribute('fixedcolumns_hidden') || 0;
	if (fc > 0) {
		simtRemoveNode(sTableId + "_FC"); 	// fixedcolumns div leeren
		simtShowFixedCols(sTableId);		// und neu erzeugen 
	}
}



function simtShowFixedCols(id)
{
	// Nur die sichtbaren fixen Spalten erzeugen. Beim vertikalen Scrollen müssen 
	// die fehlenden Elemente für den "Sichtbereich" erzeugt werden. Dadurch fallen
	// die langen Wartezeiten beim init weg.
		
	var oT=simtGet(id);
	var oTable = simtGet(id + "_TABLE");
	var fl = oT.getAttribute('fixedlines') || 0;
	var fc = oT.getAttribute('fixedcolumns_hidden') || 0;
	var oTBody = simtGet(id + "_TABLE").tBodies[0];
	var n = oTBody.rows.length;
	if (fc <= 0 || n == 0) {
		oT.lockScroll = false;
		return false;
	}
	else if (oT.scrollTop != oT.lastScrollTop) {
		oT.lastScrollTop = oT.scrollTop;
		setTimeout("simtShowFixedCols('"+id+"')",simtViewDelay);
	}
		
	var tableClass = oTable.className || "";
	var oDummyTR = document.createElement("TR");
	var oTStyle = simtRuntimeStyle(oT);
	var defHeight = parseInt(oT.scrollHeight) / n;
	var limitTop = parseInt(oT.scrollTop) - parseInt( defHeight );
	var limitBottom = limitTop + parseInt(oT.offsetHeight) + parseInt(defHeight);
	var divHtml = "", colGroupHtml = "", addHtml = "", elemHtml = "";
	var l = 0, t = 0, h = 0, w = 0, count = 0;
	
	var aTD = oTBody.rows[0].cells;
	var lrObj = (aTD.length >= fc) ? aTD[fc - 1] : null;
	if (!lrObj) {
		oT.lockScroll = false;
		return false;
	} else {
		for (var i = 0; i <= fc; i++)
			colGroupHtml += "<col width=" + aTD[i].offsetWidth + ">";
	}
	
	w = parseInt(lrObj.offsetLeft + lrObj.offsetWidth);
	h = parseInt(oT.offsetHeight);

	if ((parseInt(oT.scrollWidth) + 16) > parseInt(oT.offsetWidth))
		h = parseInt(oT.offsetHeight) - 16; // Scrollbalken
	
	
	var oTFC = simtGet(id + "_FC");
	if (!oTFC)
	{
		divHtml = "<div id='"+id+"_FC' style='position:absolute; overflow:hidden; z-index:10; ";
		divHtml+= "left:"+oTStyle.left+"; top:"+oTStyle.top+"; width:"+w+"px; height:"+h+"px;' ";
		divHtml+= "onclick='simtSelectRowFC()' onmousewheel='simtMouseWheelFC()' ";
		divHtml+= "onmouseover='simtMouseOverFC()' onmouseout='simtMouseOutFC()' ";
		divHtml+= ">";

		oT.insertAdjacentHTML("beforeBegin", divHtml + "</div>");
		oTFC = simtGet(id + "_FC");
		
		if (simtBV.isMoz) {
			simtAddEvent(oTFC, "click", simtSelectRowFC, false);
			simtAddEvent(oTFC, "DOMMouseScroll", simtMouseWheelFC, false);
			simtAddEvent(oTFC, "mouseover", simtMouseOverFC, false);
			simtAddEvent(oTFC, "mouseout", simtMouseOutFC, false);
		}
		
		simtAddEvent(oT, "mouseover", simtMouseOver, false);
		simtAddEvent(oT, "mouseout", simtMouseOut, false);
		simtClickHandlerFC(id);
	}
	

	var wExtended = aTD[fc].offsetLeft + aTD[fc].offsetWidth - aTD[0].offsetLeft;

	for (var i = fl; i < n; i++)
	{
		var oTR = oTBody.rows[i], aTD = oTR.cells;
		var trId = oTR.id + "_FC";
		var rowTop = parseInt(oTR.offsetTop);

		if (rowTop > limitBottom)
			break;
			
		if (rowTop < limitTop || simtGet(trId))
			continue;

		// Kein outerHTML in Mozilla, deshalb Umweg über cloneNode, appendChild, u. innerHTML
		var elemHtml = '', srchId = '';
		
		if (oTR.innerHTML.indexOf(' id="') > -1)
			srchId = ' id="';
		else if (oTR.innerHTML.indexOf(' id=\'') > -1)
			srchId = ' id=\'';
		else
			srchId = ' id=';
		
		for (var j = 0; j <= fc; j++) {
			oDummyTR.appendChild(aTD[j].cloneNode(true));
			elemHtml += oDummyTR.innerHTML.replace(srchId, srchId + "FC_");
			oDummyTR.removeChild(oDummyTR.firstChild);
		}
		
		addHtml += "<table class='"+tableClass+"' style='position:absolute; ";
		addHtml += "left:"+oTR.offsetLeft+"px; top:"+(oTR.offsetTop-1)+"px; ";
		addHtml += "width:"+wExtended+"px; height:"+oTR.offsetHeight+"px;'>";
		addHtml += "<colgroup>"+colGroupHtml+"</colgroup><tbody>";
		addHtml += "<tr id='"+trId+"'>"+elemHtml+"</tr></tbody></table>";
	}

	if (addHtml != "")
		oTFC.insertAdjacentHTML("beforeEnd", addHtml);
	
	if (oTFC.childNodes.length == (n - fl))
		oTFC.setAttribute("_rows_complete","true"); // fixedcolumns vollständig
	
	oTFC.style.visibility='visible';
	oTFC.scrollTop = oT.scrollTop;
	oT.lockScroll=false;
	return true;
}


function simtPreLoadImage(imgSrc, imgId)
{
	if (simtGet(imgId))
		return;
	oImg = document.createElement('img');
	oImg.setAttribute('id', imgId);
	oImg.setAttribute('src', imgSrc);
	oImg.style.visibility = 'hidden';
	document.body.appendChild(oImg);
}



function simtInitTable(id)
{
	simtBV = simtCheckBrowserVersion();
	
	var oT = simtGet(id);
	var oTable = simtGet(id + "_TABLE");
	var fl = oT.getAttribute('fixedlines') || 0;
	var fc = oT.getAttribute('fixedcolumns') || 0;
	
	if (fc > 0) { // Den Wert verstecken (warum nochmal?!?)
		oT.setAttribute('fixedcolumns_hidden',fc);
		oT.setAttribute('fixedcolumns', 0);
	}

	// Die fixen Überschriften erzeugen. Bei der Kombination fixedlines und
	// fixedcolumns sind 2 Div Blöcke notwendig.
	var totalHeight = 0, htmlFL = "", htmlFC = "";
	var oTBody = oTable.tBodies[0];
	var aTR = (fl > 0) ? oTBody.rows : null;
	var oTStyle = simtRuntimeStyle(oT);
	if (oTStyle.backgroundColor == 'transparent' && oT.getAttribute("rowbackgroundcolor"))
		oT.style.backgroundColor=oT.getAttribute("rowbackgroundcolor");
	var bgcolor = (oTStyle.backgroundColor != 'transparent') ? oTStyle.backgroundColor : 'white';
	var tableClass = oTable.className || "";
	
	if (oTBody.rows.length > 0) { // hover_bgcolor: tr.hover { "background-color" }
		var oRow = oTBody.rows[0];
		oRow.className += " hover";
		oT.setAttribute('hover_bgcolor', simtRuntimeStyle(oRow).backgroundColor);
		oRow.className = oRow.className.replace("hover", "");
	}
	
	if (fl > 0)
	{	// preload sort arrows
		simtPreLoadImage(oT.getAttribute('sortarrowup_img'), 'simt_arrowup');
		simtPreLoadImage(oT.getAttribute('sortarrowdown_img'), 'simt_arrowdown');
	}
		
	for(var row = 0; row < fl; row++)
	{
		var oDummyTable = document.createElement("TABLE");
		var oTR = aTR[row], aTD = oTR.cells;
		totalHeight += oTR.offsetHeight;
		
		var colGroup = "<colgroup>";
		for (var i = 0; i < aTD.length; i++)
			colGroup += "<col width="+aTD[i].offsetWidth+">";
		colGroup += "</colgroup>";
		
		var srchId, htmlTR = "<table class='"+tableClass+"' style='";
		htmlTR += "left:" + oTable.offsetLeft + "px; top:" + oTable.offsetTop + "px;";
		htmlTR += "width:" + oTable.offsetWidth + "px; height:" + oTR.offsetHeight + "px;'>";
		htmlTR += colGroup + "<tbody>";

		oDummyTable.appendChild(oTR.cloneNode(true));
		htmlTR += oDummyTable.innerHTML.replace("\t", " ");
		oDummyTable.removeChild(oDummyTable.firstChild);

		htmlTR += "</tbody></table>";
		htmlFL += htmlTR; htmlFC += htmlTR;
		
		if (htmlTR.indexOf(' id="') > -1)
			srchId = ' id="';
		else if (htmlTR.indexOf(' id=\'') > -1)
			srchId = ' id=\'';
		else
			srchId = ' id=';
		
		for (var i = 0; i < aTD.length; i++) {
			var srch = srchId + aTD[i].id;
			var evtHtml = " onclick=\"simtSortColumn('"+id+"',"+i+",this)\" ";
			var replFL = evtHtml + srchId + "FL_" + aTD[i].id;
			var replFC = evtHtml + srchId + "FC_" + aTD[i].id;
			
			htmlFL = htmlFL.replace(srch, replFL);
			htmlFC = htmlFC.replace(srch, replFC);
		}
	}
	
	var l = parseInt(oT.offsetLeft),		t = parseInt(oT.offsetTop);
	var w = parseInt(oT.offsetWidth - 17),	h = totalHeight;
	
	//alert("position fixed header div: l="+l+" t="+t+" w="+w+" h="+h);
	
	if (htmlFC != "" && fc > 0)
	{
		// Schnittmenge zw. fixedlines und fixedcolumns, d.h. horizontal u. vertikal fix.
		var aTD = aTR[0].cells, wFC = aTD[fc].offsetLeft - aTD[0].offsetLeft;
		
		var htmlFC_DIV = "<div style='left:"+l+"px; top:"+t+"px; width:"+wFC+"px;height:"+h+"px; ";
		htmlFC_DIV+= "position:absolute; overflow:hidden; z-index:11' id='"+id+"_FC_DIV'>";
		htmlFC_DIV+= htmlFC + "</div>";
		oT.insertAdjacentHTML("afterEnd", htmlFC_DIV);
	}

	if (htmlFL != "")
	{
		// fixedlines, d.h. vertikal fix
		var htmlFL_DIV = "<div style='left:"+l+"px; top:"+t+"px; width:"+w+"px;height:"+h+"px; ";
		htmlFL_DIV+="position:absolute; overflow:hidden; z-index:10' id='"+id+"_FL_DIV'>";
		htmlFL_DIV+= htmlFL + "</div>";
		oT.insertAdjacentHTML("afterEnd", htmlFL_DIV);
	}

	simtScrollHandler(id);
	simtClickHandler(id);
	
	if (oT.getAttribute("preparerowcolors") != null)
	{	// Userfunction zum setzen der Hintergrundfarben
		// (z.B. bei 2 möglichen Farben für die selected row)
		eval(oT.getAttribute("preparerowcolors")+"('"+id+"')");
	}
	else if (typeof setRowStyles == 'function')
	{	// Falls vorhanden die Standardfunktion für die Farben ausführen.
		setRowStyles(id);
	}
	
	if (oT.getAttribute('selected') && oT.getAttribute('selected') != "")
	{	// selected row markieren und anscrollen
		var selectedRowId = oT.getAttribute('selected');
		if (selectedRowId != "" && simtGet(selectedRowId)) {
			simtSelectRow(selectedRowId);
			simtScrollToTableElement(selectedRowId);
		}
	}
	
	if (fc > 0)
		simtShowFixedCols(id);	// festgehaltene Spalten erzeugen
}




// Simulating inserAdjacentHTML on NS6
// Code by thor@jscript.dk
// ******************************************

if (typeof HTMLElement!="undefined" && !HTMLElement.prototype.insertAdjacentElement){
	HTMLElement.prototype.insertAdjacentElement = function (where,parsedNode)
	{
		switch (where){
		case 'beforeBegin':
			this.parentNode.insertBefore(parsedNode,this)
			break;
		case 'afterBegin':
			this.insertBefore(parsedNode,this.firstChild);
			break;
		case 'beforeEnd':
			this.appendChild(parsedNode);
			break;
		case 'afterEnd':
			if (this.nextSibling) 
				this.parentNode.insertBefore(parsedNode,this.nextSibling);
			else this.parentNode.appendChild(parsedNode);
			break;
		}
	}

	HTMLElement.prototype.insertAdjacentHTML = function(where,htmlStr)
	{
		var r = this.ownerDocument.createRange();
		r.setStartBefore(this);
		var parsedHTML = r.createContextualFragment(htmlStr);
		this.insertAdjacentElement(where,parsedHTML)
	}
}
