// mehrere onLoadactions verarbeiten, vgl Ajax in Action S. 110
// Testweise, inkompatible mit bestehendem Code
/*
window.onloadListeners = new Array();
window.addOnloadListener(listener) {
	window.onloadListeners[window.onloadListeners.length] = listener
}
window.onload = function() {
	for(var i=0;i<window.onloadListeners.length;i++) {
	var func = windows.onloadListeners[i]
	func.call()
	}checkbrowser

}
*/
var is_ie
var is_ie7
var is_ie8
var is_ie9
var is_ieAfter8
var is_mac
var is_safari
var is_mac_ie
var is_gecko
var is_mac_moz
var browser

initContains(window);



// Cachen von Hintergundbildern im IE6
if (document.all) {
	try {
	  document.execCommand("BackgroundImageCache", false, true);
	} catch(err) {}
}

function imgPreloader(arr) {
	// report(arr.length)
	for (i=0;i<arr.length;i++) {var img = new Image(); img.src = arr[i]}
}

function getTime(str,br,outputMode) {
	if (window.timer) {
		if (!outputMode) 	report(timer.getTime(str,br));
		else 				alert( timer.getTime(str,br));			
	}
}


function in_array(arr,item) {
	//alert("----> in_array " + Arr.join(",") + " search str " + str)
	l = arr.length
	for (var i=0;i<l;i++) {if (arr[i]==item) return item}
}

function replaceIEFlashObjects() {
	// wird nicht mehr benoetigt!
	return;
	agt = navigator.userAgent.toLowerCase();
	if (document.all) {
		o = document.getElementsByTagName("object");  
		for(i=0; i<o.length; i++) { 
			o[i].outerHTML = o[i].outerHTML.replace('wait=1','wait=0');  // triggert Ladebalken
		}
	}
}

function initContains(windowObj) {
	// ergaenzt die contains Funktion fuer geckeo
	// alert("initContains " + windowObj)
	if (!document.all) {
		windowObj.HTMLElement.prototype.contains = function(node) {
			// alert("contains "+node.nodeName)
			if (node == null)
				return false;
			if (node == this)
				return true;
			else
				return this.contains(node.parentNode);
		}
	}
}


function getWindowWidth(win) { 
	if (win==undefined) win = window; 
	if (win.innerWidth) { 
		return win.innerWidth
	} else { 
		if (win.document.documentElement && win.document.documentElement.clientWidth) {
			return win.document.documentElement.clientWidth
		} 
		return win.document.body.offsetWidth
	}
} 
	
function getWindowHeight(win) {
	if (win == undefined) win = window; 
	if (win.innerHeight) { 
		return win.innerHeight
	} else { 
		if (win.document.documentElement && win.document.documentElement.clientHeight) {
			return win.document.documentElement.clientHeight
		}
		return win.document.body.offsetHeight
	}
} 



function source(str) {
	// asl sourcecode lesbar ausgeben, z. B. fuer report
	if (str) {
		//alert("source: " + str)
		str = str.replace(/</g,'&lt;')
		str = str.replace(/>/g,'&gt;')
	}
	return '<i>' + str + '</i>'
}

function stopEvent(e) {
	if (document.all) {
		e.cancelBubble = true
		e.returnValue = false;
	} else {
		e.stopPropagation() // ?
		e.preventDefault()
	}
}

// http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_stripslashes/
function stripslashes(str) {
	// http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Ates Goral (http://magnetiq.com)
    // +   fixed by: Mick@el
    // +   improved by: marrtins
    // +   bugfixed by: Onno Marsman
    // +   improved by: rezna
    // *   example 1: stripslashes('Kevin\'s code');
    // *   returns 1: "Kevin's code"
    // *   example 2: stripslashes('Kevin\\\'s code');
    // *   returns 2: "Kevin\'s code"
	return (str+'').replace(/\0/g, '0').replace(/\\([\\'"])/g, '$1');
}


function addslashes(str) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Ates Goral (http://magnetiq.com)
    // +   improved by: marrtins
    // +   improved by: Nate
    // +   improved by: Onno Marsman
    // *     example 1: addslashes("kevin's birthday");
    // *     returns 1: 'kevin\'s birthday'
 	return (str+'').replace(/([\\"'])/g, "\\$1").replace(/\0/g, "\\0");
}
/*
//http://javascript.about.com/library/bladdslash.htm
function addslashes(str) {
	str=str.replace(/\'/g,'\\\'');
	str=str.replace(/\"/g,'\\"');
	str=str.replace(/\\/g,'\\\\');
	str=str.replace(/\0/g,'\\0');
	return str;
}
function stripslashes(str) {
	str=str.replace(/\\'/g,'\'');
	str=str.replace(/\\"/g,'"');
	str=str.replace(/\\\\/g,'\\');
	str=str.replace(/\\0/g,'\0');
	return str;
}
*/


function printFromInside() {
	// alert("printFromInside")
	this.focus()
	self.print();
	return false
}


function showLoadingTime() {
		//alert("showLoadingTime")
		//alert("has parent " + parent)
		//alert("has opener " + opener)
		if (parent && parent.writeLoadingTime) {
			//alert("writeLoadingTime")
			parent.writeLoadingTime(document.location.href)
		} else {
		// es soll auch eine Moeglichkeit geben, die Ladezeiten so auszulesen
			// alert(t.getTime();
		}
}

function openDialog(DialogData) {
		url = DialogData.url
		//alert(url)
		if (!DialogData.h)        h       = 100;        else h = DialogData.h;
		if (!DialogData.w)        w       = 100;        else w = DialogData.w;
		if (!DialogData.t)        t       = 100;        else t = DialogData.t;
		if (!DialogData.left)     left    = 100;        else left = DialogData.left;
		if (!DialogData.resize)   resize  = 0;          else resize = DialogData.resize;
		if (!DialogData.status)   status  = 0;          else status = DialogData.status;
		if (!DialogData.scrollen) scrollen= 0;          else scrollen = DialogData.scrollen;
		if (!DialogData.edge)     edge    = "raised";   else edge = DialogData.edge;
		if (!DialogData.loc)      loc     = 0;    		else loc = DialogData.loc;
		myDialogArguments = DialogData.args // wird von Mozilla abgerufen, wenn ein Fenster geoeffnet wurde
		//alert("DialogData.windowmode: " + DialogData.windowmode) 
		if (DialogData.windowmode == 'inline') 	window['cargowindow_'+window.cwCounter] = new cargowindowObj({url:url, width:w, height:h, left:l, top:t, cwCounter:window.cwCounter})
		else 									aktueldialogEditor 						= window.open(url, "", 'menuebar = 0, width='+(w-6)+', height='+(h-26)+', left='+left+', top='+t+',status='+status+', toolbar=0, scrollbars='+scrollen+', resizable='+resize+', location='+loc+',fullscreen = 0');
}

function clapWindow(elname,height,mozdiff) { 
		// macht ein Element sichtbar und vergoessert das Fenster
		// height = heoehe des fensters ie
		if(!window.fensterhoehe_start) {
			if (document.all) 	fensterhoehe_start = document.body.clientHeight + 29 // Fenster mit Titelleiste
			else 	  		 	fensterhoehe_start = window.outerHeight
		}
		// alert(fensterhoehe_start)
		mozdiff = 90;
		if (!document.getElementById(elname)) return;
		klappbereich = document.getElementById(elname)
		if (document.all) 	fensterbreite = document.body.clientWidth + 8 // fuer Border
		else 	   			fensterbreite = window.outerWidth
		//alert(fensterbreite)
		if (klappbereich.style.display == "none")  {
			klappbereich.style.display = "inline";
			document.getElementById("img_"+elname).src = "/cms/images/icon_klapppfeildown.gif";
			if (document.all) 	window.resizeTo(fensterbreite,height);
			else 	  		 	window.outerHeight = height + mozdiff;
		} else {
			klappbereich.style.display = "none";
			document.getElementById("img_"+elname).src = "/cms/images/icon_klapppfeilup.gif";
			if (document.all) 	window.resizeTo(fensterbreite,fensterhoehe_start);
			else 				window.outerHeight = fensterhoehe_start;
		}
	}
	
	
function getAsQuerystring(formname) {
	inputArr 	= document[formname].getElementsByTagName('input');
	selectArr 	= document[formname].getElementsByTagName('select');
	textareaArr = document[formname].getElementsByTagName('textarea');
	str = '';
	for(i=0;i<inputArr.length;i++) {
		input = inputArr[i]
		if (input.type=='checkbox') {
			if (input.checked) str += '&' + input.name + '=' + input.value
		} else if (input.type=='radio') {
			if (input.checked) str += '&' + input.name + '=' + input.value
		} else {
			str += '&' + input.name + '=' + input.value
		}
	}
	for(i=0;i<selectArr.length;i++) {
		str += '&' + selectArr[i].name + '=' + selectArr[i].value
	}
	
	for(i=0;i<textareaArr.length;i++) {
		val = textareaArr[i].value
		val = val.replace("'","\'"); 				// Da ich mit einfachen Anfuehrungszeichen arbeite, diese escapen!
		str += '&' + textareaArr[i].name + '=' + val
	}
	// alert(str);
	return str;
}



function report(info,clr,top) {
	// alert(info)
	// top = '800px'
	var css
	info += "\n"
	info  = info.replace(/\n+/g, "<br/>")
	info  = info.replace(/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;")
	if (document.getElementById("infodiv")) {
		document.getElementById("infodiv").style.display 	= 'block'
		document.getElementById("infodiv").style.textAlign 	= 'left'
	} else {
		// alert("create div")
		div = document.createElement('div');
		div.id = "infodiv"
		css  = 'z-index:1000000; background:#FFFF00; position:absolute; font-family:verdana; font-size:9px;'
		css += 'width:600px;'
		// css += 'height:100%;'
		css += 'overflow:auto;' 
		css += 'white-space: nowrap;' 
		// css += 'margin-right:-600px;'
		css += 'left:0px;' // 800
		css += 'top:0px;'
		div.style.cssText = css;
		document.body.insertBefore(div,document.body.firstChild)
		// Clapbutton
		document.getElementById("infodiv").innerHTML += '<input type="button" value="h" onclick="var h=this.parentNode.style.height; if(h==\'100%\') {this.parentNode.style.height=\'30px\'} else {this.parentNode.style.height=\'100%\'};">';
		// show range Button
		document.getElementById("infodiv").innerHTML += '<input type="button" value="range" onclick="editor.analyseRange()">';
		document.getElementById("infodiv").innerHTML += '<input type="button" value="clear" onclick="report(\'\',1)">';
		document.getElementById("infodiv").innerHTML += '<input type="button" value="cleanNode()" onclick="editor.cleanNodeTest(editor.editableRootElement,\'\',0)">';
		document.getElementById("infodiv").innerHTML += '<div id="infodivInner"></div>';
		//document.body.appendChild(div)
	}
	if (clr) document.getElementById("infodivInner").innerHTML = '';
	document.getElementById("infodivInner").innerHTML += (" " +info)
}

function posinfo(el) {
	var str = 	"position: " 		+ el.style.position 	+ "\n" + 
				"offsetWidth: " 	+ el.offsetWidth 		+ "\n" + 
				"offsetHeight: " 	+ el.offsetHeight 		+ "\n" + 
				"style.width : " 	+ el.style.width 		+ "\n" + 
				"style.height: " 	+ el.style.height 		+ "\n" + 
				"absLeft: " 		+ absLeft(el) 			+ "\n" + 
				"absTop: "  		+ absTop(el) 			+ "\n" + 
				"display: "  		+ el.style.display  	+ "\n" + 
				"parentNode: "  	+ el.parentNode.nodeName + ' id: ' +el.parentNode.id + ' class: ' +el.parentNode.className 	+ "\n" + 
	""
	return str
}

function elementinfo(el) {
	var name
	if(!el) return;
	if (el.getAttribute) name = el.getAttribute('name'); // geht nicht direct... el.name
	var str = 	"\nelementinfo:" + el.nodeName 	+ "\n" + 
				(el.innerHTML 	? "\t<i>" + source(el.innerHTML)		+ "</i>\n" 	: "") + 
				(el.nodeValue 	? "\t<i>{" + el.nodeValue 			+ "}</i>\n" 	: "") +
				(el.id 			? "\tid:"	+ el.id +"\n" 						: "") +
				(el.className 	? "\tclass:" + el.className 		+ "\n" 		: "") +
				(name 			? "\tname:" + name 				+ "\n" 		: "") +
				(el.style && el.style.cssText ? '\tcss:' + el.style.cssText	+ "\n" 		: "") +
			""
	return str
}

var changedFieldsObj = {}
function listChanges(fieldname) {
	// alert("listChanges " + fieldname)
	changedFieldsObj.fieldname = 1;
}


// alert("jbasics")
// Window class
function windowInfo() {
	this.getOuterWidth = function() {
		if (is_ie) 	return document.body.clientWidth // provisorisch: IE aeussere Fenstergoesse?
		else 		return window.outerWidth
	}
	this.getOuterHeigth = function() {
		if (is_ie) 	return document.body.clientHeight
		else 		return window.outerHeight
	}
	/*
	if (is_ie) {
		 	mouseX = window.event.clientX;
		   	mouseY = window.event.clientY;
			windowWidth = document.body.clientWidth
			windowHeight= document.body.clientHeight
	} else {
			mouseX = e.clientX;
		   	mouseY = e.clientY;
			windowWidth = window.innerWidth
			windowHeight= window.innerHeight
	}
	*/
}


function getBorderWidth(el) {
// Problem: Border ist mit getComputedStyle nicht erreichbar in FF, Moz
// allerdings kann man es aus der Differenz berechne, aus offsetWidt (mit Border), padding und width.
// Die margin hat keine Einfluss auf offsetWidth
// Einschraenkung: Das Verfahren setzt voraus, dass die Border auf allen Seiten gleich breit ist...
// http://forum.de.selfhtml.org/archiv/2008/1/t165198/#m1077100
	if (document.all) {
		var borderWidth = parseInt(el.currentStyle['borderWidth']);
	} else {
		/*
		report(
				"getComputedStyle width: " 			+ window.getComputedStyle(el,"").getPropertyValue('width')		 	+ "\n" + 
				"offsetWidth: " 					+ el.offsetWidth														+ "\n" + 
				"getComputedStyle padding-left: " 	+ window.getComputedStyle(el,"").getPropertyValue('padding-left')	+ "\n" + 
				"getComputedStyle padding-right: " 	+ window.getComputedStyle(el,"").getPropertyValue('padding-right')
		)
		*/
		var w 				= parseInt(window.getComputedStyle(el,"").getPropertyValue('width'))
		var offW			= el.offsetWidth													
		var paddingLeft 	= parseInt(window.getComputedStyle(el,"").getPropertyValue('padding-left'))
		var paddingRight 	= parseInt(window.getComputedStyle(el,"").getPropertyValue('padding-right'))
		var borderWidth 	= (offW - w - paddingLeft - paddingRight) / 2
	}
	// alert("borderWidth: " + borderWidth)
	return borderWidth
}


function getCSSStyle(el,attribut) {   
	// alert ("el " + el.nodeName + " getCSSStyle " + attribut)
	// INPUT: attribut = "background-color", nicht Javascript Schreibweise "backgroundColor"
	if (window.getComputedStyle) { // Moz
		 attributVal = window.getComputedStyle(el,"").getPropertyValue(attribut);
	  } else if (el.currentStyle) { // IE
		 attributVal= el.currentStyle[attribut];
	}
	// Moz borderWidth Bug!
	if 	 	(attribut.indexOf('borderWidth')!=-1)  attributVal = getBorderWidth(el) // Anm) das kann man irgendwann verveinern, um auch unterschediliceh borderWidht zu erhalten
	else if (attribut.indexOf('border-width')!=-1) attributVal = getBorderWidth(el) // Anm) das kann man irgendwann verveinern, um auch unterschediliceh borderWidht zu erhalten
	// alert(attributVal)
	return attributVal;
}

function cargoWindow(type,vars,url,pars) {
	// alert("type: "+type + " vars: "+ vars + " url: " + url + " pars: " + pars);
	if (type=="importcsv") 			{F2 = window.open('/cms/popups/uploadcsv.php?'           +vars,'','toolbar=no,location=no,menubar=no,scrollbars=yes,resizable=yes,width=1000,height=500,left=10,top=10');}
	else 							{F2 = window.open(url+vars,'',pars)}
}


function selectAll(idStr, onOff, formname) {
	// onOff: 1 | 0
	// alert("idStr " + idStr + " onOff " + onOff + " formname " + formname);
	if (!formname) formname = 'edit';
	flength = document[formname].elements.length
	//alert("document[formname].elements.length " + document[formname].elements.length)
	for (i=0;i<flength;i++){
		// alert(document[formname].elements[i].id)
		if(document[formname].elements[i].name && document[formname].elements[i].name.indexOf(idStr)!= -1) {
			document[formname].elements[i].checked = onOff;
		}
	}
	moreCheckboxAction(idStr,onOff,'selectAll') // eine viewbezogen Funktion aufrufen, wenn sie vorhanden ist
}
function moreCheckboxAction(idStr,onOff,mode) {
	idstrArr = idStr.split('__');
	viewname = idstrArr[1];
	// alert("moreCheckboxAction " + idStr + " onOff " + onOff + " mode " + mode + " viewname " + viewname);
	// alert(window[viewname+"_checkboxaction")
	functionName = viewname+"_"+ mode+ "_checkBoxAction"
	// alert("functionName: " + functionName + " " + window[functionName])
	if (window[functionName]) eval(functionName+"("+onOff+")");
}

function btn_Set(obj,className) 		{obj.className=className}
function btn_hover(obj) 	{obj.className="btn_hover"}
function btn_out(obj) 		{obj.className="btn"}
function btn_down(obj) 		{obj.className="btn_active"}
function btn_up(obj) 		{obj.className="btn"}
function btntop_hover(obj) 	{obj.className="btntop_hover"}
function btntop_out(obj) 	{obj.className="btntop"}
function btntop_down(obj) 	{obj.className="btntop_active"}
function btntop_up(obj) 	{obj.className="btntop"}
function btnhell_hover(obj) {obj.className="btnhell_hover"}
function btnhell_out(obj) 	{obj.className="btnhell"}
function btnhell_down(obj) 	{obj.className="btnhell_active"}
function btnhell_up(obj) 	{obj.className="btnhell"}


function activateHighlightRowOnClick(el,colOver,colClick) {
	var trArr = getElementsByClassNameM(el,'tr','row')
	var L = trArr.length
	for (var i=0; i<L; i++) {
		tr = trArr[i]
		prevCol = getCSSStyle(tr,"background-color")
		if (!prevCol) prevCol = 'transparent';
		registerEventListeners(tr,'click',		function(){highlightRow('click',this,colClick,prevCol);},		false) 
		registerEventListeners(tr,'mouseover',	function(){highlightRow('over',this,colOver,prevCol,colClick);},false) 
		registerEventListeners(tr,'mouseout', 	function(){highlightRow('out',this,prevCol,colOver,colClick);},false) 
	}
}
function highlightRow(mode,tr,col,prevCol,colClick) {  // Evtl. muss ein Hover style deactivert werden
	// keine per Click aktivierten Rows ueberschreiben
	if (tr.style && tr.style.backgroundColor == colClick) return
	if (tr.style && tr.style.backgroundColor != col) {
		tr.style.backgroundColor  = col
	} else {
		if (mode != 'out') tr.style.backgroundColor = prevCol
	}
}




// BROWSERCHECKS
function checkbrowser() {
	var sq  = '';
	var agt = navigator.userAgent.toLowerCase();
	// alert("checkbrowser" +agt)
	// 360se meldet sich im Hauptfenster als msie 7, im Popup als msie 8
	/*
	mozilla/4-0 (compatible; msie 8.0; windows nt 6.1;wow64; trident/5.0;slcc2; 
	.net clr 2.0.50727; .net clr 3.5.30729; .net clr 3.0.30729; 
	media center pc 6.0; -net4.0c
	
	*/
	is_ie	  = ((agt.indexOf("msie")  != -1) && (agt.indexOf("opera") == -1));
	is_ie7	  = (agt.indexOf("msie 7") != -1);
	is_ie6	  = (agt.indexOf("msie 6") != -1);
	is_ie8	  = (agt.indexOf("msie 8") != -1);
	is_ie9	  = (agt.indexOf("msie 9") != -1); // +++Achtung: > IE9
	is_ie10	  = (agt.indexOf("msie 10")!= -1);
	is_opera  = (agt.indexOf("opera")  != -1);
	is_mac	  = (agt.indexOf("mac")    != -1);
	is_safari = (agt.indexOf("safari") != -1); // Safari
	is_mac_ie = (is_ie && is_mac);
	is_win_ie = (is_ie && !is_mac);
	is_gecko  = (navigator.product == "Gecko");
	is_mac_not_moz = (!is_gecko && is_mac);
	is_mac_moz= (is_gecko && is_mac);
	if (is_ie10 || is_ie9) is_ieAfter8 = 1; // nodeType: 3, es hat sich etwas an der Erfassung von Whitespace geaendert ab iE 9
	if (sq) alert("userAgent: " 	+ agt + "\n" + 
			"is_ie: " 		+ is_ie + "\n" + 
			"is_ie6: " 		+ is_ie6 + "\n" + 
			"is_ie7: " 		+ is_ie7 + "\n" + 
			"is_ie8: " 		+ is_ie8 + "\n" + 
			"is_opera: " 	+ is_opera + "\n" + 
			"is_gecko: " 	+ is_gecko + "\n" + 
			"is_mac: " 		+ is_mac
	)
}


// E V E N T S 
function openNewWindow(theURL,winName,features) {
	//toolbar=no,location=no,menubar=no,scrollbars=no,resizable=yes,width=520,height=280,left=0,top=0
	// alert(features)
	window.open(theURL,winName,features);
}
function addevent(el, evname, func) {
	// alert("is_ie " + is_ie + " el: " + el + "   evname: " + evname + " func: " + func);
	if(el) {
		if (is_ie) el.attachEvent("on" + evname, func);
		else       el.addEventListener(evname, func, true);
	} else {
		if (is_ie) attachEvent("on" + evname, func); 			// geht nicht mit document.body
		else       addEventListener(evname, func, true);
	}
}
// E V E N T S  F U E R    O B J E K T E , vgl:registerEventListenersObj(document, 	"mousedown",	this, false, 'startdrag');

// registerEventListenersObj(this.lis[i], "mousedown", this, false, 'show');
function registerEventListenersObj(element,eventtype,listener,captures,f,pars) {
	// listener ist das object
	// pars kommen bei der Listener[f] (function) als 3. Parameter an , vgl.: {listener[f](event,element,pars)}
	// registerEventListenersObj.caller + 
	// report("\nelement: " + element + "\neventtype: "+ eventtype + "\nlistener " + listener + "\ncaptures: " +captures + "\nf: " + f + "\npars:" + pars)
	if (document.addEventListener) element.addEventListener(eventtype,  function(event) 		{listener[f](event,element,pars)}, captures)
	else 						   element.attachEvent("on" +eventtype, function() 				{listener[f](event,element,pars)})
}
function registerEventListeners(element,eventtype,listenerfunction,captures) {
	// alert("element: "+ listenerfunction + ", eventtype: "+ eventtype + ", listenerfunction: "+listenerfunction)	
	// report("listenerfunction:" + listenerfunction)
	if (document.addEventListener)  element.addEventListener(eventtype,  listenerfunction, captures)
	else 							element.attachEvent("on" +eventtype, listenerfunction)
}
function registerEventListenersWithPars(element,eventtype,listener,captures,pars) {
	if (document.addEventListener) element.addEventListener(eventtype,  function(){eval(listener)},true)
	else 						   element.attachEvent("on" +eventtype, function(){eval(listener)})
}
function addClassName(el,clssName) {
	if (!el) return;
	// report("clssName: "+ clssName)
	// report("el: "+ el)
	if (!el.className.match(new RegExp("(^|\\s)" + clssName + "(\\s|$)"))) el.className += ' '+clssName
}
function removeClassName(el,clssName) {
	el.className = el.className.replace(new RegExp(" ?" + clssName),'')
}
function replaceClassName(el,clssName1,clssName2) {
	// clssName1 wird druch clssName2 ersetzt
	// ist der zu ersetztende ClassName (clssName1) nicht vorhanden, wird der neue angeheangt (clssName2), ansonsten einfach ersetzt.
	if (!el.className.match(new RegExp("(^|\\s)" + clssName1 + "(\\s|$)"))) {
		el.className += ' ' + clssName2
		// report("replaceClassName: classname not there, append to " + el.className + " + " + clssName2)
	} else {
		el.className = el.className.replace(clssName1,clssName2)
		// report("replaceClassName: classname is there, replace: " + clssName1 + "->" +clssName2)
	}
	// report("el.className: " + el.className)
}
function hasClassName(el,thisClassName) {
	// report(el.nodeName)
	if (!el.className) return false;
	if (el.className == thisClassName || el.className.match(new RegExp("(^|\\s)" + thisClassName + "(\\s|$)"))) return true
}
// vgl: http://www.dcljs.de/faq/antwort.php?Antwort=dhtml_koordinaten
function absLeft(el) {
	// report(el.nodeName + " " + el.offsetLeft)
	return (el.offsetParent) ? el.offsetLeft + absLeft(el.offsetParent) : el.offsetLeft;
}
function absTop(el) {
	// if (el.offsetParent) report(el.offsetParent.nodeName + " offsetTop: " + el.offsetParent.offsetTop+"\n")
	return (el.offsetParent)? el.offsetTop+absTop(el.offsetParent) : el.offsetTop;
}
function absHeight(el) {
	// alert(el.nodeName + " " + el.offsetLeft)
	return (el.offsetParent) ? el.offsetHeight + absHeight(el.offsetParent) : el.offsetHeight;
}
function getSize(el) {
	return {left:absLeft(el), top:absTop(el), width:el.offsetWidth, height:el.offsetHeight}
}

function findeNodeIndex(el,nodeType) {
	// gibt den Index eine Chilnodes zurueck, z.B. -> 3. Sibling
	// erweitert 07.12.09, nodeType, wenn 1, dann nur Elemente zaehlen
	// report("findeNodeIndex el:" + el.nodeName + " el.parentNode: " + el.parentNode.nodeName +"\n")
	if (!el || !el.parentNode) return;
	var k = 0;
	for (i=0;i<el.parentNode.childNodes.length;i++) {
		var child = el.parentNode.childNodes[i]
		if (nodeType)   {if (child.nodeType != nodeType) k++;}
		else 			{k = i;}
		if (el.parentNode.childNodes[i] == el) return k
	}
}

function getElementsByClassNameM(el,tag,className) {
// el:			startelement oder body
// tag:			welche elemente?, <div>, <span></span> oder alle '*'
	if (!tag) tag = '*';
	// report("tag: " + tag)
	// report("className: " + className)
	var elArr = (el || document.body).getElementsByTagName(tag);
	//var elArr = el.getElementsByTagName(tag);
	//var elArr = document.body.getElementsByTagName(tag);
	var elements = [], child; // array
	// alert("elArr.length: " + elArr.length)
	// return;
	if (elArr) {
		l = elArr.length
		for (var i=0; i<l; i++) {
	      	child = elArr[i]
	     	var r = new RegExp("( "+className+"$)|(^"+className+" )|( "+className+" )")
			// report("regExp: " + r +"<br>")
			// report("child.className: " + child.className)
			// if (child.className.match(new RegExp("\b" + className + "\b"))) 		elements.push(child)
			// if (child.className.match(r)) elements.push(child) // *
			if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) elements.push(child)
		}
	}
	return elements;
}

function findParentWidthClassName(el,thisClassName) {
	// alert(el.nodeName)
	if (el.nodeName.toLowerCase() != 'html') return (hasClassName(el,thisClassName)) ? el : findParentWidthClassName(el.parentNode,thisClassName);
}

function findParentElementByNodeName(el,tragetNodeName) {
	// report("findParentElementByNodeName tragetNodeName: " + tragetNodeName+ ", nodename: " + el.nodeName + " id:" + el.id + " class: " + el.className)
	// such ein bestimmte parentelement, z. B. ein <form>
	// Input: erwartet ein Element!
	// alert("findParentElementByNodeName el " + el + " tragetNodeName " + tragetNodeName)
	if (el.nodeName.toLowerCase() != 'html') return (el.nodeName.toLowerCase() == tragetNodeName.toLowerCase()) ? el :  findParentElementByNodeName(el.parentNode,tragetNodeName);
}

function getQueryStr() {
	queryStr 		= window.location.search
	queryStr 		= queryStr.replace(/\?/,"");
	return queryStr
}

function parseQueryStr(qs,withoutFullQueryStr) {
	// gibt den Querystring als Object/Assoc Array zurueck
	// enthält als erste Property den kompellten queryString, dann die einzelene Variablen
	// Bsp: ?test=nase&pageID=99  -> {querystring:'?test=nase&pageID=99',test:'nase',pageID:99}
 	queryVarObj = {}
	//if (window.location.search) {
	if (!qs) {	// nur wenn qs nicht gegeben ist, den queryString des Fensters nehmen
		qs = window.location.search
		qs = qs.replace(/\?/,"");
	}
	if(qs) {
		// alert("parseQueryStr qs:" + qs)
		if (qs.indexOf('?') != -1) { // evtl ? entfernen
			qsArr 	= qs.split('?')
			qs 		= qsArr[1]
		}
		// alert("qs after: "+ qs);
		qsParts = qs.split("&");
		if (!withoutFullQueryStr) queryVarObj.querystring = qs		// kompletten QS mit ins Object packen?
		for (i=0;i<qsParts.length;i++) {
			varArr = qsParts[i].split("=");
			// alert("varArr[0]" + varArr[0] + "\n" + " varArr[1] " + varArr[1])
			if (varArr[0]) {
				queryVarObj[varArr[0]] = varArr[1]
			}
		}
	}
	return queryVarObj;
}



function str2Obj(str) {
	// alert("str2Obj: " + str)
	if (str == '') 	obj = {} 						// leeres Object zureuckgeben
	else 			eval("var obj = "+str)
	return obj 
}
// Konvertieren von Objecten in Strings, zum Speichern in DB oder Textfeldern
// mit eval() wieder in Objecte zurueckwandelbar
// Anm: Hier gibt es Probleme mti typeof Array zu erkennen typof([]) -> liefert 'object' zurueck, ich verwende jetzt 'instanceof'
// vgl: http://javascript.crockford.com/remedial.html
function obj2Str(object,indent) {
	// +++ Achtung: Json muss alles in doppelten Anfuehrungszeichen verwalten
	var str = ''
	var attribute
	if (indent==1) 		indent = "\t"
	else if (indent) 	indent += "\t"
	for (attribute in object) {
		var to = typeof(object[attribute])
		// alert("object[attribute]: "+ object[attribute] + " " + to)
		if 			(object[attribute] instanceof Array) 	{if (str) str += ",\n" + indent; str += ('"' + attribute + '": ' 		+ array2Str(object[attribute],indent))}	// Array
		else if 	(to == 'string') 						{if (str) str += ",\n" + indent; str += ('"' + attribute + '": "' 		+ object[attribute]+'"')} 			// string
		else if 	(to == 'number') 						{if (str) str += ",\n" + indent; str += ('"' + attribute + '": ' 		+ object[attribute])}				// Number
		else if 	(to == 'boolean') 						{if (str) str += ",\n" + indent; str += ('"' + attribute + '": ' 		+ object[attribute])}				// Boolean
		else if 	(to == 'object') 						{if (str) str += ",\n" + indent; str += ('"' + attribute + '": '+"\n" 	+ obj2Str(object[attribute],indent))} 		// Object
		
	}
	return  "\n" + indent + '{'+str +'}';
}


function array2Str(arr,indent) {
	var str = ''
	var L = arr.length
	if (indent) indent += "\t"
	for (var i=0; i<L; i++) {
		var val = arr[i]
		var to  = typeof(val)
		// alert("val: "+ val + " " + to)
		if 	(val instanceof Array) 						{if (str) str += ",\n" + indent; str += array2Str(val,indent)}			
		else if 	(to == 'object') 					{if (str) str += ",\n" + indent; str += (obj2Str(val,indent))}
		else if 	(to == 'string') 					{if (str) str += ",\n" + indent; str += indent + ('"' + val + '"')} 
		else if 	(to == 'number') 					{if (str) str += ",\n" + indent; str += indent + val}
		else if 	(to == 'boolean') 					{if (str) str += ",\n" + indent; str += indent + val}
	}
	str =  '[' + str + ']';
	return str
}




function sO(object, rec, withElements) {return showObject(object, rec, withElements)} // Kurzform
function showObject(object, rec, withElements) {
	// wenn 1 rec, keine recursion!
  	var attribute, result = ''
	// report("showObject " + typeof(object));
	for (attribute in object) {
		// alert("attribute: " + attribute)
  		if (rec) {
			if (withElements && typeof(object[attribute])=='object') 						result += (attribute + ": \n" + showObject(object[attribute])) // elemente werden voll ausgegeben (viel Code...)
			else if (typeof(object[attribute])=='object' && !object[attribute].nodeName) 	result += (attribute + ": \n" + showObject(object[attribute]))
    		else 																			result += (attribute + ': '+ object[attribute]+"\n")
		} else {
			result += (attribute + ': '+ object[attribute]+"\n")
		}
	}
	return result;
}





function getOuterHTML(thisnode) {
	// verschiebt den Inhalt in ein uebergeoardnetes Element, und gibt dessen innerHTML zurueck
	divtemp = document.createElement("div")
	divtemp.appendChild(thisnode.cloneNode(true))
	return divtemp.innerHTML
}
function findNextSibling(el,nodeName) {
	while(el.nextSibling) {
		el = el.nextSibling
		if (el.nodeName.toLowerCase() == nodeName) return el
	}
}
function findPreviousSibling(el,nodeName) {
	while(el.previousSibling) {
		el = el.nextSibling
		if (el.nodeName.toLowerCase() == nodeName) return el
	}
}


function modifyQueryStr(queryStr) {
	// vereinfachte Function, analog zu PHP 'modifyQueryStr'
	// gibt es eine url?
 	var sq = '';
	if (sq) report("modifyQueryStr in: " + queryStr);
	if (queryStr.indexOf('?') != -1) var tmpArr = queryStr.split('?');
	if (tmpArr && tmpArr[0]) {
		var url 		= tmpArr[0]; // url von Querystr trennen
		var queryStr	= tmpArr[1];
	}
	qsArrInput 	= {}
	tmpArr = queryStr.split('&');
	var L = tmpArr.length
	for (i=0; i<L; i++) {
		keyValStr = tmpArr[i]
		if (keyValStr) {
			keyValArr = keyValStr.split('=')		
			qsArrInput[keyValArr[0]] = keyValArr[1];
		}
	}
	newQueryStr = '';
	for (key in qsArrInput) {	
		if (key) {
			var val = qsArrInput[key]
			if (val) 	newQueryStr ? newQueryStr += ('&'+ key + '=' + val) : newQueryStr += (key + '=' + val); 
			else 		newQueryStr ? newQueryStr += ('&'+ key)             : newQueryStr += (key);
		}
	}
	if (url) 	resStr = url+'?'+newQueryStr;
	else 		resStr = newQueryStr;
	if(sq) report("modifyQueryStr out: " + newQueryStr);
	return resStr
}
 

// changeQueryPars
function modifyQueryString(qs,useWindwowQs,varNameOrArray,varValue) {
	// alert("modifyQueryString")
	sq = '';
	if (sq) {
		report(	"\nmodifyQueryString Input: " + "\n" + 
				"qs: " 				+ qs 				+ "\n" + 
				"useWindwowQs: " 	+ useWindwowQs 		+ "\n" + 
				"varNameOrArray: " 	+ varNameOrArray 	+ "\n" + 
				"varValue: " 		+ varValue 			+ "\n" 
		)
	}
	// Bsp: var1=x&var2=y&...
	/*
	+++ Achtung: 	newUrl = modifyQueryString('',1,'',window.queryStr)	geht, 
	aber nicht 		newUrl = modifyQueryString('',1,window.queryStr,'') !			der 4. Parameter kann var=value enthöten, der 3. nur einen varname
	
	
	Input:   	qs: ein Querystring, 
				useWindwowQs: Es wird derQuerystring des Fenster ermittel und als Basis verwendet
				varNameOrArray, varvalue										2 Werte		 Bsp: varNameOrArray: "test", varValue: "nase"							
				oder Object {varname: 'value', varname2:'none', ...				1 Array/Object Assoc
				varValue: QueryString Teilstring:								&test=nase&test2=gurke
				
	Regeln:		wenn !useWindwowQs && !varNameOrArray				-> return qs
				
	nimmt einen optionalen QueryString und ersetzt dessen Parameter
	Wenn kein Querystring gegeben ist, dann wird der aktuelle QueryString ermittelt (Ausnahme: 'none')
	Werte die 'none' sind, werden entfern
	löscht doppelte und gibt den Querystr oder dei kompßlette url zurueck
	
	varNameOrArray : String oder Object  {varname: 'varvalue', ...}	
	
	Aufrufvarianten:
	// mit qs als queryString der Seite
	// modifyQueryString('',1,'testname','testvalue')							// normal: 			varname, varvalue		
	// modifyQueryString('',1,'&testname','testvalue')							// mit 				&varname
	// modifyQueryString('',1,'','varname=varvalue')							// mit varvalue  	varname=varvalue
	// modifyQueryString('',1,'','&varname=varvalue')							// mit varvalue  	&varname=varvalue
	// modifyQueryString('',1,'','varname=varvalue&nase=test')					// mit varvalue 	varname=varvalue&nase=test
	// modifyQueryString('',1,'','&varname=varvalue&nase=test')					// mit varvalue  	&varname=varvalue&nase=test
	// modifyQueryString('',1,'varname','&varname=varvalue&nase=test')			// gemischt: 		varname +  &varname=varvalue&nase=test
	
	// mit qs als Object
	// modifyQueryString('',1, {varname:'varvalue', nase:'test'},'')								// mit object {varname:'varvalue', nase:'test'}
	// modifyQueryString('',1, {varname:'varvalue', nase:'test'},'&varname=varvalue&nase=test')		// mit object gemsischt {varname:'varvalue', nase:'test'}
	
	// mit qs als Parameter
	// modifyQueryString('?varname=varvaluexxx&nase=testxxx',0,'varname','varvalue')							// mit '?'
	// modifyQueryString('varname=varvaluexxx&nase=testxxx',0,'varname','varvalue')							// ohne '?'
	// modifyQueryString('www.spiegel.de?varname=varvaluexxx&nase=testxxx',0,'varname','varvalue')							// ohne '?'
	// modifyQueryString('www.spiegel.de?varname=varvaluexxx&nase=testxxx',0,{varname:'varvalue', nase:'test'},'varname=varvalue2&nase=test2')							// ohne '?'
	
	
	*/
	//alert("typeof: " + typeof(varNameOrArray))
	var qsOutput 	= ''
	var output 		= ''
	var url 	 	= ''
	var hasQuestionmark = 0;
	
	if (qs.indexOf('?') !=-1) {				// komplette url?   dann splitten in url + querystr
		qsArr = qs.split('?'); 
		url = qsArr[0]; 
		qs = qsArr[1];
		hasQuestionmark = 1;
	}
	// kein qs als Parameter und useWindwowQs?
	if 		( useWindwowQs) qs = getQueryStr()					// +++ Achtung: wenn kein qs gegeben ist, dann aktuellen Query String nehmen, kann mit 'none' explizit ausgeschaltet werden
	else if (!useWindwowQs && !varNameOrArray) return qs;		// qs wird direkt zurueckgegeben
	qs = qs.replace(' ','')
	if (qs == '&' || qs == '?' || qs == '?&' ) qs = ''
	if (sq) report("qs nach getQueryStr: " + qs)
	qsArr2 		= qs.split("&");	// Querystr in Array 
	len 		= qsArr2.length
	qsArrInput 	= {}
	qsArrtemp 	= {}	
	// Aus dem Basis-Input qs wird eine Object gebildet
	for (i=0; i<len; i++) {						 		// Array/Object bilden  {varname: 'varvalue', ...}	
		keyValStr = qsArr2[i]
		if (keyValStr) {
			keyValArr = keyValStr.split('=')		
			qsArrInput[keyValArr[0]] = keyValArr[1];
		}
	}
	if(sq) report("qsArrInput: " + showObject(qsArrInput));
	// Umwandeln: string in Arrays/Oject
	// Aus dem mdyfy Input wird ein 2. Array gebildet
	if (typeof(varNameOrArray) == 'string')	qsArrtemp[varNameOrArray.replace('&','')] = varValue			// normaler string
	else 									qsArrtemp  = varNameOrArray;
	// wenn der varValue ein queryTeilstring ist: &test=1&test2=2...
	// dann wird der varValue geparst
	if(sq) report("varValue: " + varValue)
	if (varValue && (varValue.indexOf('=') != -1 || varValue.indexOf('&') != -1)) {
		qsArrtemp = parseQueryStr(varValue,'withoutFullQueryStr')
		if(sq) report("qsArrtemp: " + showObject(qsArrtemp));
	} 
	// if(sq)  report(showObject(qsArrtemp));
	// mergen der Arrays/Ojecte
	for (var key in qsArrtemp) {qsArrInput[key] = qsArrtemp[key]} // es werden bestehende key in qsArrInput ersetz oder neu hinzugefuegt
	if (sq) report("qsArrInput: " + showObject(qsArrInput));
	// report("hier")
	for (key in qsArrInput) {	
		if (key) {							// +++ Achtung: es kann auch leere keys geben!
			val = qsArrInput[key]
			if (val == 'none') continue;	// werte die 'none' sind werden entfernt"
			if (val) 	qsOutput ? qsOutput += ('&'+ key + '=' + val) : qsOutput += (key + '=' + val);  	//  Standard: 		"&key=value"
			else 		qsOutput ? qsOutput += ('&'+ key)             : qsOutput += (key);					// leerer Value: 	"&key"
		}
	}
	if (url || useWindwowQs || hasQuestionmark) {					// es gibt eine Url...
		output = url
		if (qsOutput) output += ('?' + qsOutput)
	} else {
		if (qsOutput) output += '&' + qsOutput; 
	}
	if(sq) report("modifyQueryString output " + output)
	// report("modifyQueryString output " + output)
	return output
}



// ______________________________________________________________________________
function findFirstElementChildNode(el) { // findet den 1. Childnode, der keine Text ist
	for (var i=0;i<el.childNodes.length;i++) {
		if (el.childNodes[i].nodeType != 3) return el.childNodes[i]
	}
}

function switchViewEditMode(el,mode) {
	if(mode=='row') {
		tr = findParentElementByNodeName(el,'tr')
		L = tr.childNodes.length
		//alert(L)
		for(var i=0;i<L;i++) {
			if (tr.childNodes[i].nodeName.toLowerCase() == 'td') {
				td = tr.childNodes[i]
				// report(td.className+"\n")
				if (td.className.indexOf('view_b_')  !=-1) continue // der Buttobs sollen nicht umgewandelt werden
				if (td.className.indexOf('t_spacer') !=-1) continue // der Buttobs sollen nicht umgewandelt werden
				if (td.childNodes[0]) {
					var wrappingEl = td.childNodes[0]
					//report(wrappingEl.childNodes.length+"\n")
					//report(wrappingEl.innerHTML+"\n")
					if (wrappingEl.childNodes[0]) {
						var contentEl  	= findFirstElementChildNode(wrappingEl)
							if (contentEl) {
							var nN   		= contentEl.nodeName.toLowerCase()
							//report("nN: " + nN + "\n")
							var name 		= contentEl.getAttribute('name')
							report("nN: " + nN + " name: " + name + "\n")
							if (!name) 											continue // keine Elemente ohne Name!
							if (nN=='textarea' || nN=='input' || nN=='select') 	continue // keine Forms umwandeln!
							/* I N F O
							Das Switch Dilemma:
							Wenn ich den Inhalt eines Divs in eine Textarea packe, treten Probleme mit Umbruechen auf.
							Beim Div wird nicht umbrochen(wrap), aber linbreaks "\n" werden dargestellt, wenn white-space:pre.
							Ohne white-space:pre ist es genau umgekerht: Es wird umbrochen, aber "\n" werden ignoriert.
							Bei der Textarea werden "\n" ebenfall dargestellt und ausserdem umbrochen, d.h. die Textarea wird tendenziell hoeher.
							Trick:
							Um das Problem beim Switchen aufzufangen, wird der Inhalt testweise in einen Dummycontainer gepackt, 
							die "\n" in <br> umgewandelt, die entstandene Hoehe gemessen und dann auf die Zieltextarea angewendet. 
							Also nur zum Messen.
							*/
							// report(contentEl.innerHTML +"\n");
							var newEl = document.createElement('textarea')
							lbd = document.getElementById('linebreakDummy')
							if (!lbd) {
								var lbd = document.createElement('div')
								document.body.appendChild(lbd)
								lbd.id 				= 'linebreakDummy'
							}
							lbd.style.width 	= contentEl.offsetWidth
							lbd.className 		= contentEl.className
							lbd.style.position 	= 'absolute'
							lbd.style.whiteSpace = 'normal'
							lbd.style.border 	= '1px solid green'
							lbd.style.padding 	= '3px'
							lbd.style.left 		= '-100000px'				// Ausblenden
							// end Switch Dilemma
							contentEl.parentNode.appendChild(lbd)
							var iHTML 			= contentEl.innerHTML
							iHTML = iHTML.replace(/\n/gi,'xxx<br/>')
							lbd.innerHTML   = iHTML
							lbdOffsetHeight = lbd.offsetHeight
							lbd.innerHTML 		= ''						// leeren nach dem Auslesen der Hoehe
							newEl.value = contentEl.innerHTML
							newEl.style.border = '1px solid red'
							newEl.style.padding = '2px'
							// Die Hoehenapssung kann noch optimiert werden, indem ich auf white-Space nowrap pruefe
							// if (contentEl.offsetHeight > 20) newEl.style.height = contentEl.offsetHeight +6+ 'px' // soll gleiche Hoehe annehmen, wenn sie nicht einzeilig sind
							newEl.style.height = lbdOffsetHeight + 'px'
							// newEl.style.height = contentEl.offsetHeight +2+ 'px' // soll gleiche Hoehe annehmen
							newEl.name = name
							wrappingEl.removeChild(contentEl)
							wrappingEl.appendChild(newEl)
						}
					}
				}
			}
		}
	}
}


function thisMovie(movieName) {
	if (navigator.appName.indexOf("Microsoft") != -1) {
		// alert("document.getElementById(movieName).id: " + document.getElementById(movieName).id)
		// alert("window[movieName]:" +document.getElementById(movieName).id)
		return document.getElementById(movieName)
		// alert("window[movieName]:" +window[movieName])
		// return window[movieName];
	} else {
		return document[movieName];
	}
}


function radioVal(rObj) {
	// alert(rObj.name)
	// alert(rObj.length)
	for (var i=0; i<rObj.length; i++) {
		// alert("radio value: " + rObj[i].value)
		if (rObj[i].checked) return rObj[i].value;
	}
    return false;
}

function menuVal(rObj) {
	// alert(rObj.name)
	// alert(rObj.length)
	var arr = new Array();
	var c = 0;
	for (var i=0; i<rObj.options.length; i++){
		if (rObj.options[i].selected){
			
			arr[c] = (rObj.options[i].value)
			c++;
		}
	} 
	return arr;
}

