/* A E N D E R U N G E N 


17.03.09		ScrollbarObj: Umsellung der Berechnungsreihenfolge nach Textfeldverkleinerung
10.03.09		messageObj, cargowindowObj von /cargo/js/widgets.php hinzugefuegt

*/



// von cargo
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________


// M E S S A G E 
// Einblenden von Informationen
function messageObj(P) {
	// Call:
	// var m = new messageObj({message:'0Cargo editor startet and it is very nice to <b> see</b> this message poping up!', style:'right:20px; top:190px; width:250px;'})
	// Mit Fading:
	// new messageObj({message:ajaxSyncResult,refEl:P.el, mode:'all', livetime:1500, offsettop:-40, offsetleft:0})
	
	// Noch ergaenzen: modal, nicht modal
	var sq = 0
	P.mode 				?  this.mode 		= P.mode  			: this.mode 		= 'all' //   all |  errors  || success
	P.message 			?  this.message 	= P.message  		: this.message 		= ''
	P.closable 			?  this.closable 	= P.closable  		: this.closable 	= 'yes'	// no
	P.fade 				?  this.fade 		= P.fade  			: this.fade 		= ''
	P.className 		?  this.className 	= P.className  		: this.className 	= 'cargomessage'
	P.style 			?  this.style 		= P.style  			: this.style 		= ''
	P.refEl 			?  this.refEl 		= P.refEl  			: this.refEl 		= '' // Ein Elemente, an dessen linker Oberkannte positioniert wird
	P.offsetleft 		?  this.offsetleft 	= P.offsetleft  	: this.offsetleft 	= 0
	P.offsettop 		?  this.offsettop 	= P.offsettop  		: this.offsettop 	= 0
	P.offsettop 		?  this.livetime 	= P.livetime  		: this.livetime 	= ''
	P.draggable 		?  this.draggable 	= P.draggable  		: this.draggable 	= '1'
	P.cssText 			=  this.cssText
	if (!this.cssText) this.cssText = 'position:absolute; display:block; z-index:100000;' + this.style
	// report("this.cssText: " 	+ this.cssText)
	// report("this.style: " 	+ this.style)
	if (this.message) {
		this.text 		= this.message.substr(1,this.message.length)
		this.iconNmb 	= this.message[0]
	}
	if (this.mode=='errors'  && iconNmb != 0) return; // beenden, wenn der mode nicht passt
	if (this.mode=='success' && iconNmb != 1) return;
	// report("this.text: " 	+ this.text)
	// report("this.iconNmb: " + this.iconNmb)
	this.messageEl 					= document.createElement('div')
	this.messageEl.className		= this.className;
	// this.messageEl.onclick 			= "alert('close'); this.style.display = 'none';"
	this.messageEl.style.cssText	= this.cssText;
	// this.messageEl.setAttribute('onclick',"this.style.display='none';")
	if (this.refEl) {
		this.messageEl.style.left		= absLeft(this.refEl) + this.offsetleft + 'px'
		this.messageEl.style.top		= absTop(this.refEl)  + this.offsettop + 'px'
	}
	this.messageEl.innerHTML		= '<div class="icon" style="background: url(/cargo/images/icon_ok'+this.iconNmb+'.gif) center center no-repeat;"></div><div class="text">'+this.text+'</div>'
	// alert(this.refEl)
	// Closer icon
	document.body.appendChild(this.messageEl,document.body.firstChild)
	if (this.closable) {
		var closer = document.createElement('div')
		closer.className 	= 'closer'
		closer.setAttribute('onclick', "this.parentNode.parentNode.removeChild(this.parentNode);") // this.parentNode.style.display='none';
		closer.innerHTML 	= "&nbsp;" 
		this.messageEl.appendChild(closer)
	}
	this.show()
	// fade out
	if (this.livetime) {
		var fader = new faderObj({el:this.messageEl, mode:'out', properties:['opacity'], faderStep:1, limit:100, clearAfterFade:1, delay:this.livetime})
	}
	if (this.draggable) {
		var d = new dragObj({dragEl: this.messageEl})
	}
	// fade(fader,'out',100000)
}

messageObj.prototype.show = function() {
	this.messageEl.style.display = 'block'
	// alert("bin da" + this.messageEl.innerHTML)
}






// C A R G O W I N D O W
// lastchange:17.01.09
function cargowindowObj(P) {
	if (!P.url && !P.sourceEl) 	alert("cargowindowObj: url or sourceEl not given. Cant' go on.s")
	if (!window.cwCounter) window.cwCounter = 0; 	// zaehlt die Fenster
	if (!P.cwCounter) 			{window.cwCounter++; this.cwCounter = window.cwCounter} 
	else 						{this.cwCounter 	= P.cwCounter}
	this.url 		= P.url
	P.type 		?  	this.type  		= P.type  		: this.type  		= ''; // 'context' ...
	P.event 	?  	this.event 		= P.event 		: this.event 		= ''; // das ausloesende event fuer die Positionierung eines Contextmenus
	P.className ?  	this.className 	= P.className 	: this.className 	= 'cw'; // das ausloesende event fuer die Positionierung eines Contextmenus
	P.width		?	this.width		= P.width		: this.width		= '400px';
	P.height	?	this.height		= P.height		: this.height		= '700px';
	P.left		?	this.left		= P.left		: this.left			= '100px';
	P.top		?	this.top		= P.top			: this.top			= '100px';
	P.sourceEl	?	this.sourceID	= P.sourceID	: this.sourceID		= '';
	if (typeof(P.sourceEl)=='string') this.sourceEl = document.getElementById(P.sourceEl)
	// alert("sourceEl: " + sourceEl)
	// report("width height " + this.height + " " + this.width)
	
	this.rootID = 'cw_' + this.cwCounter // daran erkennen die Fenster das cargowindowObj im opener
	this.rootEl = this.opencargowindow(); // gibt das table Element zurueck
	// danach steht
}

cargowindowObj.prototype.closeWindow = function() {
	// alert("close")
	//if (editor) editor.openInterfaceElements.pop(); 				// interface wieder frei machen
	var iframe = document.getElementById('iframe'+this.cwCounter) 	// es muss erst die iframeSrc geloescht werden, sonst gibt es in IE seltame Verhaltensweisen (keien Textselection mehr moeglich)
	if (iframe) iframe.parentNode.removeChild(iframe);
	this.rootEl.parentNode.removeChild(this.rootEl);
	window['cargowindow_'+window.cwCounter] = ''  					 // delete(this) // geht nicht im IE
	if (editor.fastEditWindow) editor.fastEditWindow = null	// fasteedit: wrid im editorObject gespeichert!
}

cargowindowObj.prototype.resize = function() {
	i = new windowInfo()
	// wurde das Fenster bereits scaliert?
	border = 0
	if (i.bodyWidth()-border != this.rootEl.offsetWidth || i.bodyHeight()-border != this.rootEl.offsetHeight) 	mode = 'maximize';
	else 																										mode = 'reset';
	/*
	alert(		"this.rootEl "  	+ this.rootEl.nodeName  + "\n" + 
				"i.outerWidth "  	+ i.bodyWidth()  + "\n" + 
				"i.outerHeight " 	+ i.bodyHeight() + "\n" + 
				"width "  			+ parseInt(this.rootEl.offsetWidth) + "\n" +
				"height " 			+ parseInt(this.rootEl.offsetHeight) + "\n" +
				"this.width "  		+ this.width + "\n" +
				"this.height " 		+ this.height + "\n" +
				"mode " 			+ mode
	)
	*/
	if (mode == 'maximize') {
		this.rootEl.style.left   = 0
		this.rootEl.style.top  	 = 0
		this.rootEl.style.width  = (i.bodyWidth()  - border) + 'px'
		this.rootEl.style.height = (i.bodyHeight() - border) + 'px'
	} else {
		this.rootEl.style.left   = this.left   + 'px'
		this.rootEl.style.top  	 = this.top    + 'px'
		this.rootEl.style.width  = this.width  + 'px'
		this.rootEl.style.height = this.height + 'px'
	}
}

cargowindowObj.prototype.opencargowindow = function() {
	// alert("url: "+url +"\n" + w +" " + h)
	// alert("this.height: " + this.height)
	// alert ("this.rootID: " + this.rootID);
	html  = '<table class="cwtable" id="' + this.rootID + '_table" cellpadding="0" cellspacing="0" border="0" width="100%" height="100%">'
	html += '<tr>'
	html += ' 	<td class="cwlt">&nbsp;</td>'
	html += '	<td class="cwct" id="' + this.rootID + '_cw_griff">&nbsp;</td>'
	html += '	<td class="cwrt">&nbsp;</td>'
	html += '</tr>'
	html += '<tr>'
	html += '	<td class="cwlm">&nbsp;</td>'
	html += '	<td class="cwmm '+ (this.type == 'fastedit' ? 'cw_body':'')+'" valign="top">'
	// alert(this.type)
	if (this.type == 'fastedit')	{
	// headerleiste
	// actuell
		var closer 	= "editor.fastEditWindow.closeWindow()"
		var resizer = "editor.fastEditWindow.resize()"
		var saver 	= 'editor.fastEditWindow.sourceEl.'+ (this.sourceEl.value ? 'value' : 'innerHTML')+'= document.getElementById(\'fastEditTextArea\').value; '
		// alert("closer: "+closer)
		html += '<table class="cw_header" cellpadding="0" cellspacing="0" border="0" width="100%" height:22px;><tr>'
		html += '<td class="cw_header_left"><img src="/cargo/images/icon_write.gif"></td>' // icon
		html += '<td class="cw_header_leftline"></td>'
		html += '<td class="cw_header_text"><div style="overflow:hidden; height:14px; padding:1px 0 0 0;"><? echo $wheadertext ?></div></td>'
		html += '<td class="cw_header_divider"><img src="/cargo/images/cw_header_divider.gif"></td>'
		html += '<td class="cw_header_maximize" onclick="'+resizer+'"><img src="/cargo/images/cw_icon_maximize.gif"></td>'
		html += '<td class="cw_header_close"    onclick="'+closer+'"><img src="/cargo/images/cw_icon_close.gif"></td>'
		html += '</tr></table>'
		// Message
		// html += '<div id="cw_message" class="cw_message">'
		// html += '<div class="cw_divider"></div>'
		// html += '<p></p>'// message
		// html += '</div>'
		html += '<div class="cw_divider"></div>'
		// Textarea
		html += '<div style="padding:10px;"><textarea name="fastEditTextArea" id="fastEditTextArea" class="cargofields2" style="width:100%; height: 100px;" id="text" name="text">'
		html += (this.sourceEl.value ? this.sourceEl.value: this.sourceEl.innerHTML)
		html += '</textarea>'
		// Buttonleiste
		html += '<table width="1%" cellpadding="0" cellspacing="0" style="margin-top:10px;"><tr>'
		html += '<td><input class="cargobuttons" type="button" value="Cancel" onclick="'+closer+'"></td>' // html += '<td><input class="cargobuttons" type="reset" value="Reset"></td>'
		html += '<td class="border1"><input class="cargobuttons" type="button" onclick="'+saver+closer+'" name="" value="Insert"></td>'
        html += '</tr></table></div>'
	} else {
		this.url.indexOf('?') != -1 ? qp = '':qp = '?';
		// html += '<div style="height:'+(this.height)+'px; background:red;"></div>'
		// +++ Achtung: margin-bottom:-3px Verstehe ich nicht, es entsteht sonst unter dem Iframe ein 2px spalt
		// wenn man den iframe gegen ein div aistausche, dann geht es... Darstellungs-Bug mit iframes?
		html += '<iframe id="iframe'+this.cwCounter+'" src="' + this.url + qp + '&cwCounter=' + this.cwCounter + '" style="width:100%; height:'+(this.height)+'px; margin-bottom:-3px; padding:0" frameborder="0"></iframe>'
	}
	html += '</td>'
	html += '<td class="cwrm">&nbsp;</td>'
	html += '</tr>'
	html += '<tr>'
	html += '	<td class="cwlb">&nbsp;</td>'
	html += '	<td class="cwcb">&nbsp;</td>'
	html += '	<td class="cwrb">&nbsp;</td>'
	html += '</tr>'
	html += '</table>'
	// Testen
	//var html = '<div style="padding:2px; background:orange; position:absolute; top:0px; left:600px; width:350px; height:150px;">'
	// var html = '<iframe id="iframe'+this.cwCounter+'" src="' + this.url + qp + '&cwCounter=' + this.cwCounter + '" style="width:100%; height:'+(this.height)+'px; margin-bottom:-3px; padding:0" frameborder="0"></iframe>'
	//html += '<iframe id="iframe'+this.cwCounter+'" src="/iframe_drag_inside_test.htm" style="width:100%; height:'+(this.height)+'px; margin-bottom:-3px; padding:0" frameborder="0"></iframe>'
	//html += '</div>'
	cw = document.createElement('div')
	cw.innerHTML 	 = html
	//cw.style.cssText = 'padding:2px; background:orange; border:2px solid orange; position:absolute; top:0px; left:200px; width:350px; height:150px;'
	document.body.appendChild(cw) // cw.id = 'cw'
	cw.setAttribute('id',this.rootID)
	cw.setAttribute('class','cw')
	//cw.setAttribute('style','width:'+this.width+'; height:'+this.height+'; left:'+this.left+'; top:'+this.top+';')
	cw.setAttribute('style','')
	cw.style.cssText = 'border:0px solid orange; position:absolute; width:'+this.width+'px; height:'+this.height+'px; left:'+this.left+'px; top:'+this.top+'px; z-Index:10000;'
	// cw.setAttribute('style','border:5px solid red;')
	// alert(document.getElementById('cw').id)
	this.iframe = document.getElementById('iframe'+this.cwCounter)
	// alert(this.iframe.id)
	this.drag = new dragObj({dragEl: this.rootID, controlEl: this.rootID + '_cw_griff'}) // geht nicht mit cw!
	return cw // gibt das umfassende Div zurueck, das das gesamte Fenster enthaelt, wird dann this.rootEl zugewiesen
}


// von cargo end
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________
// _______________________________________________________________________________________________________























// S E L E C T
// ein Custom select, dass sich wie ein formelemnt verhaelt, wird mit document.write() in die Seite geschreiben
function selectObj(P) {
	/* I N F O 
	
	Aenderungen:
	07.04.09	scrollbars einbauen
	
	Anm value) aus irgendeinem grund gibt der IE value=1 zurueck, wenn value eigentlich '' ist!
	z-index in IE ist noch ungeloest...
	
	*/
	if (!window.selectCounter) window.selectCounter = 0
	window.selectCounter++
	var sq 				= 1
	this.name 			= P.name;			if (!this.name) 	alert("selectObj: name not given");
	this.rootID 		= P.rootID;			if (!this.rootID) 	this.rootID = this.name + '_' + window.selectCounter // Name als rootID verwenden, wenn nicht gegeben
	if (document.all) 	this.mouseUpCounter = 1; // fuer die  mouseup-Steuerung: Das select  soll sich erst beim 2. Klick wieder schliessen, wenn gerade aufgeklappt wurde
	else 				this.mouseUpCounter = 0;
	P.className			?  this.className 			= P.className 			: this.className 		= 'select'
	P.style				?  this.style 				= P.style 				: this.style 			= ''
	P.optionsObj		?  this.optionsObj 			= P.optionsObj 			: this.optionsObj 		= {}
	P.onchange			?  this.onchange 			= P.onchange 			: this.onchange 		= ''
	P.openerstyle		?  this.openerstyle 		= P.openerstyle 		: this.openerstyle 		= ''
	P.layerstyle		?  this.layerstyle 			= P.layerstyle 			: this.layerstyle 		= ''
	P.optionstyle		?  this.optionstyle 		= P.optionstyle 		: this.optionstyle 		= ''
	P.scrollbarabspos	?  this.scrollbarabspos 	= P.scrollbarabspos 	: this.scrollbarabspos 	= ''
	P.maxHeight			?  this.maxHeight 			= P.maxHeight 			: this.maxHeight 		= '300' // wenn groesser, dan scrollbar
	// alert(P.selected != undefined)
	P.selected != undefined	?  this.selected 		= P.selected 			: this.selected 		= null
	this.selectedOption = '&nbsp;'						// den 1. Nehmen
	this.selectedValue  = ''
			for (option in this.optionsObj) {
		if (this.selected==null) {
			this.selectedOption = option						// den 1. Nehmen
			this.selectedValue  = this.optionsObj[option]
			break
		} else {
			if (this.optionsObj[option] == this.selected) {
				this.selectedOption = option
				this.selectedValue  = this.optionsObj[option]
				break
			}
		}
	} // end for
	
	// alert(firstOption)
	// alert(showObject(this.optionsObj));
	// alert(window.selectCounter)
	// report(this.className)
	// report(window.selectCounter)
	var html = '<div 	id="'+this.rootID+'" 				class="'+this.className+'" unselectable="on" style="'+this.style+'">'
	html 	+= '<div 	id="'+this.rootID+'_opener" 		style="'+this.openerstyle+'" unselectable="on" class="opener"><div unselectable="on" style="border:0px solid green; overflow:hidden">'+this.selectedOption+'</div></div>'+"\n"	// select Element, sichtbar
	html 	+= '<div 										style="position:relative; z-index:'+window.selectCounter+'; height:0px; width:0px; left:0; top:0; border:0px solid red; float:left;" unselectable="on">'+"\n"		
	html 	+= '<ul  	id="'+this.rootID+'_layer"			style="'+this.layerstyle+'" class="layer" unselectable="on">'+"\n"																									// Ausklappbarer Layer
	var i = 0
	for (option in this.optionsObj) {
		// html 	+= "\t"+'<li class="option" id="" style="'+this.optionstyle+'" onmouseup="javascript:'+this.rootID+'.selectValue(\''+option+'\',\''+this.optionsObj[option]+'\')">'+option+'</li>'+"\n";
		// mit Listener, wird weiter unten hinzugefuegt
		// report(this.optionsObj[option])
		html 	+= "\t"+'<li class="option" id="'+this.rootID+'_option_'+i+'" style="'+this.optionstyle+'" value="'+this.optionsObj[option]+'" unselectable="on">'+option+'</li>'+"\n";
		i++
	}
	html 	+= '</ul>'+"\n";
	html 	+= '</div>'+"\n";
	html 	+= '<input id="'+this.rootID+'_hiddenfield" type="hidden" name="'+this.name+'" value="'+this.selectedValue+'">'	
	html 	+= '</div>'+"\n";
	document.write(html)
	
	// report(source(html))
	this.layerEl 	= document.getElementById(this.rootID+'_layer')
	this.rootEl  	= document.getElementById(this.rootID)
	this.openerEl  	= document.getElementById(this.rootID+'_opener')
	if (document.all) 	registerEventListenersObj(document, "mouseup", this, true, 'hide',''); // geht nur mit document im IE!
	else 				registerEventListenersObj(window,   "mouseup", this, true, 'hide','');
	registerEventListenersObj(document.getElementById(this.rootID+'_opener'), "mousedown", this, true, 'show', '');
	var i=0 
	// ich verwende einen Listener, weil ich das Objekt, wenn es nicht in einer Variable gespeichert wurde, sonst nicht identifizieren kann.
	// ich mache das hier, weil weiter oben die Elemente noch nicht exisiteren, wg. document.write
	for (option in this.optionsObj) {
		registerEventListenersObj(document.getElementById(this.rootID+'_option_'+i), "mouseup",  this, true, 'selectValue', '')
		i++
	}
	// Breite auslesen und anpassen des opener-Elements, wenn zu schmal fuer die laengste option
	// Display none hat offsetWidth:0, deshalb der "left:-10000" Trick
	var layerWidth = this.layerEl.offsetWidth
	// Fall 1) opener ist Kleiner als breiteste Option? -> Opener anpassen
	if (!this.openerEl.style.width) {
		//report("layerWidth: " + layerWidth)
		//report("this.openerEl.style.width: " + this.openerEl.style.width)
		if (layerWidth > this.openerEl.style.width) {
			this.openerEl.style.width = layerWidth - 11 + 'px'
		}
	}
	// Fall 2) options sind kuerzer als opener? Options anpassen
	if (!this.layerEl.style.width) {
		// alert(this.rootID + " layerWidth: " + layerWidth + " this.openerEl.style.width: " + this.openerEl.style.width)
		if (layerWidth < parseInt(this.openerEl.style.width)) this.layerEl.style.width = parseInt(this.openerEl.style.width) + 11 -2 + 'px'
	}
	// P.maxHeight
	// report("layerEl.offsetHeight: " + this.layerEl.offsetHeight)
	// report("this.maxHeight: " + this.maxHeight)
	// report("absLeft: " + absLeft(this.layerEl))
	// report("absLeft: " + absLeft(this.layerEl))
	
	// Variante mit Systemcrollbar
	/*
	if (this.layerEl.offsetHeight > this.maxHeight) {
		this.layerEl.style.height 		= this.maxHeight + 'px'
		this.layerEl.style.overflow 	= 'auto'
	}
	*/
	
	// Variante mit Karcher-Systemcrollbar, hier schonmal den overflow einstellen, damit im unsichtbareb Bereich keine sehr langen hidden Elemente
	// entstehen, die einen Fenster-Scrollbar erzeugen koennen
	if (this.layerEl.offsetHeight > this.maxHeight) {
		this.layerEl.style.height 	 = this.maxHeight + 'px'
		this.layerEl.className 		+= ' scrollable abspos'
	}
	
}


selectObj.prototype.selectValue = function(e, el) {
	var option 	= el.innerHTML
	var val 	= el.getAttribute('value')
	// alert("val: " +val)
	// alert(typeof(val))
	// alert(el.outerHTML)
	document.getElementById(this.rootID + '_hiddenfield').value = val			// hiddenfield setzen
	document.getElementById(this.rootID+'_opener').firstChild.innerHTML 	= option		// text im select setzten
	this.layerEl.style.left = -10000 + 'px'
	if (this.scrollBar) {this.scrollBar.scrollbarEl.style.left = -100000 + 'px'}
	this.mouseUpCounter = 0;
	// alert(this.onchange)
	if (this.onchange) {
		// Anm value
		if (document.all && val==1) return;
		else eval(this.onchange)
	}
}

selectObj.prototype.setValue = function(val) {
	document.getElementById(this.rootID + '_hiddenfield').value = val	
	// anhand des values wir die option ermittelt
	for (var opt in this.optionsObj) {
		if (this.optionsObj[opt] == val) {
			var option = opt
			break;
		}
	}
	document.getElementById(this.rootID+'_opener').firstChild.innerHTML = opt
}


selectObj.prototype.show = function() {
	this.layerEl.style.left = 0
	// Variante mit Karcher-Systemcrollbar, erstellen
	if (this.maxHeight && this.layerEl.offsetHeight > this.maxHeight && !this.scrollBar) {
		this.layerEl.style.height 	 = this.maxHeight + 'px'
		this.layerEl.className 		+= ' scrollable'
		var P = {refEl:this.layerEl, barwidth:15, buttonheight:15, slideroverlap:1, abspos:this.scrollbarabspos, scrollbarLeftoverlap:1, xxxbarOutside:1} // var P = {refEl:document.getElementById(''), barwidth:15, buttonheight:15, slideroverlap:1}
		this.scrollBar = new scrollbarObj(P)
	}
	if (this.scrollBar) {
		// report(this.layerEl.offsetWidth)
		// report(absLeft(this.layerEl))
		// var zInd = (document.all ? getCSSStyle(this.layerEl,'z-index') : getCSSStyle(this.layerEl,'zIndex'));
		// var zInd = getCSSStyle('z-index')
		// report("zInd: " + zInd)
		this.scrollBar.scrollbarEl.style.left = absLeft(this.layerEl) + this.layerEl.offsetWidth +  - 1 + 'px'
		// report("this.scrollBar.scrollbarEl.style.zIndex: "+this.scrollBar.scrollbarEl.style.zIndex)
		this.scrollBar.scrollbarEl.style.zIndex = 1000
	}
	// report(this.scrollBar.scrollbarEl.style)
}

selectObj.prototype.hide = function(e,el) {
	e = e ? e : event
	//if (document.all) 	report("nodeName: " + e.srcElement.nodeName.toLowerCase())
	//else  				report("nodeName: " + e.target.nodeName.toLowerCase())
	
	//if (document.all) 	report("nodeName: " + e.toElement.nodeName.toLowerCase())
	//else  				report("nodeName: " + e.relatedTarget.nodeName.toLowerCase())
	
	// if (document.all)	{if (e.srcElement.nodeName.toLowerCase() == 'html') {this.layerEl.style.display = 'none'; return}}
	// else 				{if (e.target.nodeName.toLowerCase()     == 'html') {this.layerEl.style.display = 'none'; return}}
	// el = (e.target) ? e.target : e.srcElement;
	// report("hide " + e.target + " " + this.rootEl.className + " contains")
	if (!document.all) this.mouseUpCounter++
	// report("this.mouseUpCounter: " + this.mouseUpCounter + " this.rootEl.contains? " + this.rootEl.contains)
	// Wenn ich 
	if (this.rootEl.contains) {
		var stop = 0
		
		// Scrollbars: Es muss verhindert werden, dass sich das Select bei Click auf den Scrollbar schliesst
		// report("test: " + (e.target || e.srcElement).id)
		if (this.scrollBar && ((e.target || e.srcElement).id.indexOf('scrollbar') != -1)) {
			stop = 1
		}
		// report("stop: " + stop)
		// Click auf opener
		// report("modulo: "+this.mouseUpCounter % 2)
		if (!stop && this.mouseUpCounter % 2==0) {
			if (e.target || e.srcElement == this.openerEl) {
				this.layerEl.style.left = -10000 + 'px'
				this.mouseUpCounter = 0
				if (this.scrollBar) {this.scrollBar.scrollbarEl.style.left = -100000 + 'px'}
				// report("ok")
			}
		}
		// Click auf etwas ausserhalb
		if (!stop && !this.rootEl.contains(e.target || e.srcElement)) {
			// report("hier")
			this.layerEl.style.left = -10000 + 'px'
			this.mouseUpCounter = 0
			if (this.scrollBar) {this.scrollBar.scrollbarEl.style.left = -100000 + 'px'}
		}
	}
	if (document.all) this.mouseUpCounter++
}






















// S C R O L L B A R
// initialisieren aller Scrollbars auf der Seite, class="scrollable"
function activateScrollBars(P) {
	// alert("activateScrollBars")
	if (!window.cargoScrollbarsObjArr)  window.cargoScrollbarsObjArr = {} 
	if (!window.cargoScrollbarElArr) 	window.cargoScrollbarElArr 	 = []
	// alle Scrollbars, deren Elemente eine ID haben, werden heir im Object verwaltet.
	// damit kann man spater auf die Methoden zugrefien
	// alert("activateScrollBars")
	var Pbasic = {barwidth:15, buttonheight:15, slideroverlap:1, scrollbarLeftoverlap:1} // var P = {refEl:document.getElementById(''), barwidth:15, buttonheight:15, slideroverlap:1}
	if (P) { // parameter von draussen uebernehmen
		for(a in P) {Pbasic[a] = P[a]}
	}
	
	var scrollElArr = getElementsByClassNameM(document.body,'','scrollable')
	for (var i=0;i<scrollElArr.length;i++) {
		Pbasic.refEl = scrollElArr[i]
		// report(Pbasic.refEl)
		if (in_array(window.cargoScrollbarElArr,Pbasic.refEl)) continue // verhindern doppelter Scrollbars durch mehrfachen Aufruf von activateScrollBars
		// report("Activate Scrollbar for: "+P.refEl.id)
		if (Pbasic.refEl.id) cargoScrollbarsObjArr[Pbasic.refEl.id] = new scrollbarObj(Pbasic)
		else 														  new scrollbarObj(Pbasic)
	}
	// report(showObject(cargoScrollbarsObjArr,1))
}

function scrollbarObj(P) {
	// return;
	/* I N F O 
	
	P.abspos = 1 oder class="scrollable abspos"
						Scollbar wird dem mit body.appendChild eingesetzt
	!abspos:			Scollbar wird dem mit refEl.parentNode.appendChild eingesetzt		
	class="baroutside":	Scrollbar liegt rechst neben dem Div, das div wird mit megrin verkleinert um die Breite des Scrollbars (Default)
	class="barinside":	Scrollbar liegt inside, das div bleibt gelic hgross, der Bar ueberdeck die hinteren Pixel
	
	
	Erweitert am 24.02.09:	refEl.width kann in '%' angegeben werden
	IE/:	this.refEl.scrollHeight = 0, wenn innerhalb einer Tabelle!
	
	noch ergaenzen:
	-	Mindestgroesse des Slider: Bei sehr viel Inhalt kann der Slider sehr klein werden
	-	ScrollWheel: ist die mouse schon vor dem Laden der Seite ueber dem Scrollbereich? e.clientX abfragen? von welchem event?
	Wenn ein zusaetzliches div mit class="outerscroll" verwednet wird, dann kann man den Sctollbalken dynamisch scalierbar machen, 
	d.h. es gibt kein Geruckel bei window.resize.
	outerscroll wird selbstaendig erkannt.
	Ansonsten wird der Scrollbar mit window.resize an Groessenaenderungen angepasst.
	
	Das zu scrollende Div sollte keine border haben
	
	scrollbarslidertop: Das ist ein Div, dass oben im Slider liegt, und nur eine Moeglichkeit bieten soll, eine Border zu bilden
	Es sollte vermieden werden, in das dragabble Element noch weiter Elemente einzubauen...
	
	Hat der Slider ein Hintergundbild, das unten links auserichte ist, dann fehlt bei der  dynamischen Skalierungen des Scrollsliders die obere Kante...
	Die Kante selbst ist allerdings nicht draggable. Es wird fuer IE/ ein t.gif verwendet mti 1ps height, sonst entsteht eine Mindeshoehe von 10 px...
	
	Um Platz fuer den Scrollbar zu schaffen, wird das zu scrollende Element mit einem padding-right versehen
	
	
	
	
	
	
	*/
	
	var sq 				= 1
	var l 				= 0 // nur zum checken, schiebt Buttons und Slider nach rects
	this.refEl 			= P.refEl
	if (typeof(this.refEl) == 'string') this.refEl = document.getElementById(this.refEl)
	if (!this.refEl) alert('scrollbarObj: refEl not given')
	if (!window.cargoScrollbarElArr) 	window.cargoScrollbarElArr 		= []	// listet die Elemente, die bereits eine Scrollbar haben, um doppelte zu vermeiden
	if (!window.cargoScrollbarsObjArr) 	window.cargoScrollbarsObjArr 	= {} 	// enthelt die Scrollbarobjecte, mit ID abrufbar
	if (!window.cargoScrollbarCounter)  window.cargoScrollbarCounter  	= 0   	// zaehlt die Scrollbars, um Elementen ohen ID einen Identifier zu geben
	// Gibt es den schon?
	// report("bis hier")
	if (!this.refEl.id) {
		// keine ID? dann scrollBarID generieren aus counter
		this.scrollBarID = 'cargoScrollbar_'+window.cargoScrollbarCounter
		window.cargoScrollbarCounter++;
	} else {
		this.scrollBarID = 'cargoScrollbar_' + this.refEl.id
	}
	// report(this.scrollBarID)
	// registrieren in einem globalen Object/Array
	window.cargoScrollbarElArr.push(this.refEl) 										// es wird das Element in den Array aufgenommen, damit man auch Elemente ohne ID mit Scrollbars versehen kann
	if (!cargoScrollbarsObjArr[this.scrollBarID]) cargoScrollbarsObjArr[this.scrollBarID] = this  // Referenz in globalem Object sichern, passiert auch bei activateScrollBars
	
	// report(showObject(P))
	// alert("scrollbar for: " + this.refEl.id + " scrollBarID: " + this.scrollBarID)
	// alert("make scrollbar")
	// Slider benoetigt?
	// alert("this.refEl.id: " + this.refEl.id + " this.refEl.offsetHeight: " + this.refEl.offsetHeight);
	// this.applied			= 0
	this.useOuterScroll 	= 0;
	if (hasClassName(this.refEl.parentNode,'outerscroll')) 	{
		this.useOuterScroll = 1
		var p = getCSSStyle(this.refEl.parentNode,'position'); if (!p) this.refEl.parentNode.style.position = 'relative'
	}
	
	// return;
	// Pars
	P.barwidth					?  	this.barwidth 				= P.barwidth 			: this.barwidth 			= 20	// Die Balkenbreite, horizontal oder vertikal
	P.buttonheight				?  	this.buttonheight 			= P.buttonheight 		: this.buttonheight 		= 20	
	P.borderwidth				?  	this.borderwidth 			= P.borderwidth 		: this.borderwidth 			= 0	
	P.slideroverlap				?  	this.slideroverlap 			= P.slideroverlap 		: this.slideroverlap		= 0		
	P.displace					?  	this.displace 				= P.displace 			: this.displace				= 0		
	P.scrollbarLeftoverlap		?  	this.scrollbarLeftoverlap	= P.scrollbarLeftoverlap: this.scrollbarLeftoverlap	= 0	
	P.barOutside != undefined 	?	this.barOutside				= P.barOutside			: this.barOutside			= 1
	P.abspos 					?	this.abspos					= P.abspos				: this.abspos				= 0
	P.refElWidth				?  	this.refElWidth				= P.refElWidth			: this.refElWidth			= null	// eine feste Width, fuer Elemente, auf die mehrfach ein Scrollbar angewendet wird
	// this.abspos = 1
	// alert("this.refElWidth: " + this.refElWidth)
	if (document.all) 	this.firstMarginRight = parseInt(getCSSStyle(this.refEl,'margin-right'));
	else 				this.firstMarginRight = parseInt(getCSSStyle(this.refEl,'marginRight'));
	if (!this.firstMarginRight) 	this.firstMarginRight = 0;
	if (document.all) 	this.firstBorderWidth = parseInt(getCSSStyle(this.refEl,'borderWidth'));
	else 				this.firstBorderWidth = parseInt(getCSSStyle(this.refEl,'border-width'));
	if (!this.firstBorderWidth) 	this.firstBorderWidth = 0;
	
	// report(getCSSStyle(this.refEl,'margin-left'))
	// report(getCSSStyle(this.refEl,'margin-right'))
	// report("Start: this.refElWidth: " + this.refElWidth)
	// report("Start: this.refEl.offsetWidth: " + this.refEl.offsetWidth)
	// report("Start: this.firstMarginRight: " + this.firstMarginRight)
	// report("Start: this.firstBorderWidth: " + this.firstBorderWidth)
	// report("P.barOutside == undefined: " + (P.barOutside == undefined))
	// P.SliderTextDist		? 	this.SliderTextDist		= P.SliderTextDist		: this.SliderTextDist		= 0
	// Breite der vertikalen Ueberlappung, z. B. wenn die Buttons eine graueLine haben, der Slider ebenfalls, dann mussen sie sich 1 px ueberlappen, sonst entsteht eine Doppellini...
	
	if (P.overflow=='hidden') this.refEl.style.overflow = 'hidden' // 24.06.2010 entfernt, wegen FF Printproblem
	
	// baroutside kann durch die class barinside wieder deaktivert werden
	if (hasClassName(this.refEl,'barinside')) 	this.barOutside = 0
	if (hasClassName(this.refEl,'abspos')) 		this.abspos 	= 1;
	if (this.useOuterScroll) 					var pos			= 'relative'
	else 					 					var pos 		= 'absolute'
	// report("abspos: " + this.abspos)
	
	
	
	// S C R O L L B A R    E R S T E L L E N 
	this.scrollbarEl 				= document.createElement('div')
	this.scrollbarEl.className 		= 'scrollbar'
	this.scrollbarEl.style.cssText 	= 'position:absolute; border:0px solid red;width:'+this.barwidth+'px; display:block; display:none;' // +++ Achtung:top:0 ist wichtig, sont wird unten appended, es entsteht ein Scrollbar und bei % weidht ergibt sich eine kleinee Breite!
	var html 	 = '<div class="scrollbartop" 		id="scrollbarbuttontop_'		+this.scrollBarID+'" style="top:0; left:'+l+'px; position:absolute; width:'+this.barwidth+'px; height:'+this.buttonheight+'px"></div>'
	html 		+= '<div class="scrollbarslider" 	id="scrollbarslider_'		+this.scrollBarID+'" style="top:'+(this.buttonheight - this.slideroverlap)+'px; left:'+l+'px; position:relative; width:'+this.barwidth+'px;"><div class="scrollbarslidertop" style="height:1px"><img src="/cms/images/t.gif" height="1px"></div></div>'
	html 		+= '<div class="scrollbarbottom" 	id="scrollbarbuttonbottom_'	+this.scrollBarID+'" style="left:'+l+'px; bottom:0; position:absolute; width:'+this.barwidth+'px; height:'+this.buttonheight+'px"></div>'
	this.scrollbarEl.innerHTML = html;
	// alert("1this.refEl.offsetWidth: " + this.refEl.offsetWidth)
	// alert(this.refEl.parentNode.className)
	// report("this.refEl: " + this.refEl.id + "this.refEl.offsetLeft: "+ this.refEl.offsetLeft)
	// report("this.refEl.parentNode: " + this.refEl.parentNode.id + "this.refEl.parentNode.offsetLeft: "+ this.refEl.parentNode.offsetLeft)
	if 		(this.useOuterScroll) 	this.refEl.parentNode.appendChild(this.scrollbarEl)
	else if (this.abspos) 			document.body.appendChild(this.scrollbarEl)
	else 							this.refEl.parentNode.appendChild(this.scrollbarEl)
	// alert("this.refEl.style.width: " + this.refEl.style.width)
	// alert("2this.refEl.offsetWidth: " + this.refEl.offsetWidth)
	// this.applied = 1
	this.sliderEl 				= document.getElementById('scrollbarslider_' 		+ this.scrollBarID)
	this.scrollbarbuttontop 	= document.getElementById('scrollbarbuttontop_' 		+ this.scrollBarID)
	this.scrollbarbuttonbottom	= document.getElementById('scrollbarbuttonbottom_' 	+ this.scrollBarID)
	var obj = this
	this.dragObj = new dragObj({dragEl:this.sliderEl,	maxTop: this.maxTop, maxBottom: this.maxBottom, constrainH:0, constrainV:1, call_drag: function(){obj.scroll()}})
	this.positionScrollBar();
	registerEventListenersObj(window, 						'resize', this, true, 'positionScrollBar');
	registerEventListenersObj(this.scrollbarbuttontop, 		'click',  this, true, 'scrollStep', 'top');
	registerEventListenersObj(this.scrollbarbuttonbottom, 	'click',  this, true, 'scrollStep', 'bottom');
	// Scrollrad
	// document.onmousewheel = function() {report("scroll")};
	// report("this.scrollBarID: " + this.scrollBarID)
	// report(showObject(cargoScrollbarsObjArr[this.scrollBarID],0));
	// report("scroll")
	// S C R O L L W H E E L
	var obj = this
	if (document.all) this.refEl.onmousewheel = function(){cargoScrollbarsObjArr[obj.scrollBarID].scrollWheel(event); stopEvent(event)}; // registrieren von "onmousewheel" klappte nicht!
	else registerEventListenersObj(this.refEl, 'DOMMouseScroll', this, true, 'scrollWheel','');
	registerEventListenersObj(this.refEl, 'mouseover',  this, true, 'getFocus','');
	registerEventListenersObj(this.refEl, 'mousemove',  this, true, 'getFocus','');
	registerEventListenersObj(this.refEl, 'mouseout',  	this, true, 'leaveFocus','');
}


scrollbarObj.prototype.getFocus = function(e,el) {				// report("enter: "+el.nodeType)
	this.hasFocus = 1
}
scrollbarObj.prototype.leaveFocus = function(e,el) {			// report("leave: "+el.nodeType)
	this.hasFocus = 0
}

scrollbarObj.prototype.scrollStep = function(e,el,pars,mode) {	// report(pars)
	var sPos = parseInt(this.sliderEl.style.top)				// report('this.scrollStepDist: ' + this.scrollStepDist  + " sPos: "+sPos + ' this.maxBottom: '+ this.maxBottom + ' maxTop:' + this.maxTop)
	if (mode=='wheel') 	var scrollStepDist = this.scrollStepDistWheel
	else 				var scrollStepDist = this.scrollStepDist
	if (pars=='bottom') {
		var newPos = parseInt(sPos + scrollStepDist)			// report('sPos: ' + sPos + ' newPos: ' + newPos)
		if (newPos > this.maxBottom)	this.sliderEl.style.top = this.maxBottom + 'px'
		else 							this.sliderEl.style.top = parseInt(newPos) + 'px'
	}
	if (pars=='top') {
		var newPos = sPos - scrollStepDist						// report('sPos: ' + sPos + ' newPos: ' + newPos)
		if (newPos < this.maxTop)	this.sliderEl.style.top = this.maxTop + 'px'
		else 						this.sliderEl.style.top = parseInt(newPos) + 'px'
	}
	this.scroll()
}

scrollbarObj.prototype.positionScrollBar = function() {
	var sq = 0
	// report("this.refEl.scrollHeight vor Breitenanpassung: " + this.refEl.scrollHeight + " this.refEl.offsetHeight: " + this.refEl.offsetHeight)
	// A N P A S S E N
	// Verkleinern des Elements umd die Scrollbar-width + Margin-right um Platz fuer Scrollbar zu schaffen
	// Im Modus "barOutside" wird das Element um dei Breite des Scrollbars verkleinert. Um den Abstabd zu halten, wird die margin erhoeht
	// if (1==1) report("this.refElWidth: " + this.refElWidth + " barOutside: " + this.barOutside) 
	if (!this.refElWidth) {
		// Problem: Firefox liefert bei % Werten float + px Wert zurueck -> 249.8px, ausserdem ist der Wert 3 Pixel zu klein...
		// var test = getCSSStyle(this.refEl,'width') 
		if (document.all) {
			var paddingL = parseInt(getCSSStyle(this.refEl,'paddingLeft'));
			var paddingR = parseInt(getCSSStyle(this.refEl,'paddingRight'));
		} else {
			var paddingL = parseInt(getCSSStyle(this.refEl,'padding-left'));
			var paddingR = parseInt(getCSSStyle(this.refEl,'padding-right'));
		}
		if (!paddingL) paddingL = 0
		if (!paddingR) paddingR = 0
		// report("this.firstBorderWidth: " + this.firstBorderWidth)
		// report("paddingL: " +paddingL)
		// report("paddingR: " + paddingR)
		this.refElWidth = this.refEl.offsetWidth - this.firstBorderWidth*2 - paddingL - paddingR
		// report("this.refElWidth:" + this.refElWidth)
	}
	
	if (this.barOutside) {
		if (!this.displace) this.displace = this.barwidth - this.scrollbarLeftoverlap
	}
	// report("this.barOutside: " + this.barOutside + ", this.displace: " + this.displace + ", this.barwidth: " + this.barwidth)
	var s = "\n"
	if (1==2) report(
				
				" this.applied: " 					+ this.applied + s +
				" this.barOutside: " 				+ this.barOutside + s +
				" this.refElWidth: " 				+ this.refElWidth + s +
				" this.refEl.style.width: " 		+ this.refEl.style.width + s +
				" marginR: " 						+ marginR + s +
				" paddingR: " 						+ paddingR + s +
				" paddingL: " 						+ paddingL + s +
				" borderL: " 						+ borderL + s +
				" borderR: " 						+ borderR + s +
				" this.displace: " 					+ this.displace + s +
				" this.refEl.style.marginRight: " 	+ this.refEl.style.marginRight 
	) // in IE7 undefined
	
	// kein Scrollbar noetig? Dann raus!
	// alert("this.refEl.id: " + this.refEl.id)
	// report("this.refEl.scrollHeight: " + this.refEl.scrollHeight + " this.refEl.offsetHeight: " + this.refEl.offsetHeight)
	if (this.refEl.scrollHeight <= this.refEl.offsetHeight) {
		// report(this.refEl.id + "dont need scrollbar")
		this.scrollbarEl.style.display = 'none'
		// report("vor none this.refEl.id: " + this.refEl.id + " this.refEl.style.marginRight: " + this.refEl.style.marginRight)
		if (this.barOutside && this.isActivated && !this.useOuterScroll) {
			this.refEl.style.width 			= parseInt(this.refEl.style.width)  	  + this.displace + 'px'
			this.refEl.style.marginRight 	= parseInt(this.refEl.style.marginRight)  - this.displace +'px'
		}
		// report("none this.refEl.id: " + this.refEl.id + " this.refEl.style.marginRight: " + this.refEl.style.marginRight)
		this.isActivated = 0
	} else {
		this.scrollbarEl.style.display = 'block'
		if (this.barOutside && !this.useOuterScroll) {
			this.refEl.style.width 			= this.refElWidth - this.displace  + 'px' // ++ Achtung: wenn useOuterScroll verwendet wird, keine Grossenzuweisung! Sonst geht dei automatisceh Anpassung nicht mehr
			this.refEl.style.marginRight 	= this.firstMarginRight + this.displace + 'px'
		}
		this.isActivated = 1
	}
	// report("this.refEl.style.width" + this.refEl.style.width)
	// report("this.refEl.scrollHeight nach Breitenanpassung: " + this.refEl.scrollHeight + " this.refEl.offsetHeight: " + this.refEl.offsetHeight)
	
	//this.width 							= this.refEl.offsetWidth
	this.height = this.refEl.offsetHeight
	// alert(this.refEl.scrollTop) 
	// report("this.height: " + this.height)
	if (!this.height) return; // +++ Achtung: Im Zusammenahng mit dem Popup wird der onresize.listener aufgerufen. In IE 7 hat thei.ehight dann kinen Wert und erzeugt eine Fehler beim Schliessen des Popups
	if (this.isActivated == 0) return;
	// if (!this.applied) this.refEl.style.width = this.width - this.barwidth + 'px' // verkleinern des Elements, um den Scrollbar rechts danebenzustellen, nur beim 1. Mal
	// alert("scrollbarObj")
	this.scrollHeight					= this.refEl.scrollHeight
	this.scrollFactor 					= this.height/this.scrollHeight					// sichtbarer Bereich in %
	this.scrollSliderHeight 			= (this.refEl.offsetHeight - this.buttonheight*2 +this.slideroverlap*2) * this.scrollFactor
	// report("this.refEl.offsetHeight: " + this.refEl.offsetHeight+  " this.scrollSliderHeight" + this.scrollSliderHeight);
	// report("this.scrollFactor " + this.scrollFactor)
	// report("this.refEl.offsetHeight - this.buttonheight*2 " + this.refEl.offsetHeight - this.buttonheight*2)
	// report("this.scrollSliderHeight: " + this.scrollSliderHeight)
	this.scrollDist 					= parseInt(this.refEl.offsetHeight - this.scrollSliderHeight - this.buttonheight*2 + this.slideroverlap*2) // maximale Anzahl an px, die der Slider bewegt werden kann
	// alert("scrollDist:" +this.scrollDist + " scrollTop: " + this.refEl.scrollTop)
	this.scrollStepDist 				= this.scrollDist /10 // Distanz in px, bei Klick auf die Buttons
	this.scrollStepDistWheel 			= this.scrollDist /20 
	// alert(this.scrollbarEl)
	
	// ???
	// if (this.scrollbarEl.offsetParent && this.scrollbarEl.offsetParent.style && this.scrollbarEl.offsetParent.style.position) this.scrollbarEl.style.height = '100%' // passt sich selbt an
	// else this.scrollbarEl.style.height = this.refEl.offsetHeight + 'px'
	this.scrollbarEl.style.height = this.refEl.offsetHeight + 'px'
	
	var tTop = 0 // nur zum testen, um Scrollbar runterzuschieben
	// alert("this.useOuterScroll: " + this.useOuterScroll)
	if (this.useOuterScroll) {
		this.scrollbarEl.style.height  		= '100%'
		this.scrollbarEl.style.top  		= tTop
		this.scrollbarEl.style.left 		= '100%'
		this.scrollbarEl.style.marginLeft 	= -this.barwidth + 'px'
		this.sliderEl.style.height  		= this.scrollSliderHeight + this.slideroverlap*2 + 'px'
		this.scrollbarbuttonbottom.style.bottom = - this.borderwidth +'px'
	} else {
		// report("--> this.refEl.id: " + this.refEl.id + " absLeft: " + absLeft(this.refEl) + " absTop: " + absTop(this.refEl)    )
		if (this.abspos) {
			this.scrollbarEl.style.left = absLeft(this.refEl) + this.refEl.offsetWidth - this.barwidth 	+ this.displace+ 'px'
			this.scrollbarEl.style.top  = absTop(this.refEl) + tTop + 'px'
		} else {
			this.scrollbarEl.style.left = this.refEl.offsetLeft + this.refEl.offsetWidth - this.barwidth + this.displace+ 'px'
			this.scrollbarEl.style.top  = this.refEl.offsetTop + tTop + 'px'
		}
		
		//report("--> this.sliderEl.style.height: " + this.sliderEl.style.height)
		//report("--> this.scrollSliderHeight: " + this.scrollSliderHeight)
		//report("--> this.slideroverlap: " + this.slideroverlap)
		
		var newHeight = this.scrollSliderHeight + this.slideroverlap*2 
		// report("--> newHeight: " + newHeight)
		this.sliderEl.style.height = newHeight + 'px'
		this.scrollbarbuttonbottom.style.top = this.refEl.offsetHeight - this.buttonheight + 'px'
		// return
		//report("--> this.refEl.id: " + this.refEl.id + " absLeft: " + absLeft(this.refEl) + " absTop: " + absTop(this.refEl)    )
		//report("--> this.scrollbarEl.id: " + this.scrollbarEl.id + " absLeft: " + absLeft(this.scrollbarEl) + " absTop: " + absTop(this.scrollbarEl)    )
		//report("--> this.scrollbarEl.id: " + this.scrollbarEl.id + " style.left: " + this.scrollbarEl.style.left + " style.top: " + this.scrollbarEl.style.top  )
		
	}
	// this.scrollbarEl.style.left = parseInt(this.scrollbarEl.style.left) + 10 +'px';
	// report("this.scrollbarEl.style.left: " + this.scrollbarEl.style.left)
	
	
	// this.scrollbarEl.style.left = paresInt(this.scrollbarEl.style.left) - 500 + 'px'
	// bestimmte Scrollposition anspringen?
	// Oberkannte Scrolltop + Hoehe des Containers
	this.scrolledFactor = this.refEl.scrollTop / (this.refEl.scrollHeight - this.refEl.offsetHeight)// Faktoer: beim zuueckspringen mit Anker: Faktor der Scrollposition ermitteln
	if (this.scrolledFactor != 0) {
		this.sliderEl.style.top = (this.scrolledFactor * this.scrollDist) + this.buttonheight + 'px'
	}
	this.maxTop 			= this.scrollbarbuttontop.offsetTop 	+ this.buttonheight			- this.slideroverlap
	this.maxBottom 			= this.scrollbarbuttonbottom.offsetTop 	- this.scrollSliderHeight 	+ this.slideroverlap
	this.dragObj.maxTop 	= this.maxTop								// dragObj nachjustieren!
	this.dragObj.maxBottom 	= this.maxBottom + (document.all ? 1 : 0) 	// warum auch immer!
	
	
	
	// report(posinfo(this.scrollbarEl))
	var sq = 0
	if (sq) {
		report(	
	"refEl.style.width: " 			+ this.refEl.style.width				+"\n" + 
	"refEl: " 						+ this.refEl.id 						+"\n" + 
	"scrollBarID: " 				+ this.scrollBarID						+"\n" + 
	"height: " 						+ this.height 							+"\n" + 
	"scrollHeight: " 				+ this.scrollHeight 					+"\n" + 
	"scrollFactor: " 				+ this.scrollFactor 					+"\n" + 
	"scrollSliderHeight: " 			+ this.scrollSliderHeight 				+"\n" + 
	"barwidth: " 					+ this.barwidth 						+"\n" + 
	"buttonheight: " 				+ this.buttonheight 					+"\n" + 
	"scrollDist: " 					+ this.scrollDist 						+"\n" + 
	"this.scrollbarEl.style.left: " 	+ this.scrollbarEl.style.left		+"\n" + 
	"this.scrollbarEl.style.top: " 		+ this.scrollbarEl.style.top		+"\n" + 
	"")
	}
}



scrollbarObj.prototype.scrollWheel = function(e,el) {
	// report("e.detail: " + e.detail)
	// report("this.scrollBarID: " + this.scrollBarID)
	var dir
	// report('scrollWheel')
	if (!this.hasFocus) return;
	if (!document.all) {
		if (e.detail > 0) 		dir = 'bottom'
		else 					dir = 'top'
	} else {
		if (e.wheelDelta < 0) 	dir = 'bottom'
		else 					dir = 'top'
	}
	this.scrollStep(e,el,dir)
	stopEvent(e);
}



scrollbarObj.prototype.scroll = function() {
	var scrollDistFromTop 	= this.sliderEl.offsetTop - this.buttonheight + this.slideroverlap
	//report("scrollDistFromTop: " + scrollDistFromTop + "\n")
	this.scrollPosFactor 	= scrollDistFromTop / this.scrollDist
	//report("scrollPosFactor: " + this.scrollPosFactor + "\n")
	// report("this.scrollheight * this.scrollPosFactor: " + (this.scrollHeight * this.scrollPosFactor) + "\n")
	this.refEl.scrollTop 	= (this.scrollHeight - this.height) * this.scrollPosFactor
}

scrollbarObj.prototype.deleteScrollbar = function() {
	// report(this.scrollbarEl.nodeName)
	if (this.scrollbarEl && this.scrollbarEl.parentNode) {
		// report(this.scrollbarEl.nodeName)
		this.scrollbarEl.parentNode.removeChild(this.scrollbarEl)
	}
}
















// R E N D E R T A B L E 
function renderTable(P) {
	if (!P.rootID) 		alert("renderTable: no rootID, can't go on")
	else 				this.rootID = P.rootID
	this.table = document.getElementById(this.rootID)
	// alert("renderTable: " + this.rootID);
}

renderTable.prototype.addRow = function(pos) {
	// alert("add");return;
	r 			= this.table.rows[pos]
	// alert(pos)
	// alert(r.innerHTML)
	clonedRow 	= r.cloneNode(true)
	for(var i=0;i<clonedRow.cells.length;i++) {clonedRow.cells[i].firstChild.value='';} // leeen
	var nS 		= this.table.rows[pos].nextSibling
	if (nS) 	r.parentNode.insertBefore(clonedRow,nS)
	else 		r.parentNode.appendChild(clonedRow)
	this.resetNumbers();
}

renderTable.prototype.deleteRow = function(pos) {
	if (!this.table.rows[2]) {alert('Sorry, can\'t delete the last row'); return;}
	r 		= this.table.rows[pos]
	pN 		= r.parentNode
	pN.removeChild(r)
	this.resetNumbers();
}

renderTable.prototype.moveRowUp = function(pos) {
	r 		= this.table.rows[pos]
	if (pos-1<0) {alert('Can\'t move up. It\'s the first row.'); return}
	newposNode =  this.table.rows[pos-1]
	r.parentNode.insertBefore(r,newposNode)
	this.resetNumbers();
}

renderTable.prototype.moveRowDown = function(pos) {
	r 		= this.table.rows[pos]
	var numRows = this.table.rows.length
	if (pos+2 == numRows) {alert('Can\'t move down. It\'s the last row.'); return}
	newposNode =  this.table.rows[pos+2]
	r.parentNode.insertBefore(r,newposNode)
	this.resetNumbers();
}


renderTable.prototype.addCol = function(pos) {
	// alert("addcol " + pos)
	var numRows = this.table.rows.length
	var numCols = this.table.rows[0].cells.length
	for (var i=0; i<numRows; i++) {
		var cell 	= this.table.rows[i].cells[pos]
		clonedCell 	= cell.cloneNode(true)
		clonedCell.firstChild.value='' // leeen
		var nS 		= cell.nextSibling
		if (nS) 	cell.parentNode.insertBefore(clonedCell,nS)
		else 		cell.parentNode.appendChild(clonedCell)
	}
	this.resetNumbers();
}

renderTable.prototype.deleteCol = function(pos) {
	var numRows = this.table.rows.length
	var numCols = this.table.rows[0].cells.length
	if (numCols==2) {alert('Sorry, can\'t delete the last col'); return;} // 2 wegen der 1. Spalte fuer die Buttons
	for (var i=0; i<numRows; i++) {
		var cell 	= this.table.rows[i].cells[pos]
		cell.parentNode.removeChild(cell)
	}
	this.resetNumbers();
}

renderTable.prototype.moveColRight = function(pos) {
	// alert("moveColRight pos " +pos)
	var numRows = this.table.rows.length
	var numCols = this.table.rows[0].cells.length
	// alert("moveColRight pos+1 " +(pos) + " numCols: "+numCols)
	if (pos+1==numCols) {alert('Can\'t move right. It\'s the right col.'); return}
	for (var i=0; i<numRows; i++) {
		var cell 	= this.table.rows[i].cells[pos]
		newposNode 	= cell.nextSibling.nextSibling
		if (newposNode) cell.parentNode.insertBefore(cell,newposNode)
		else  			cell.parentNode.appendChild(cell)
	}
	this.resetNumbers();
}

renderTable.prototype.moveColLeft = function(pos) {
	// alert("moveColLeft pos: " + pos)
	var numRows = this.table.rows.length
	var numCols = this.table.rows[0].cells.length
	if (pos<2) {alert('Can\'t move left. It\'s the left col.'); return}
	for (var i=0; i<numRows; i++) {
		var cell 	= this.table.rows[i].cells[pos]
		newposNode 	= cell.previousSibling
		if (newposNode) cell.parentNode.insertBefore(cell,newposNode)
	}
	this.resetNumbers();
}

renderTable.prototype.resetNumbers = function() {
	var numRows = this.table.rows.length
	var numCols = this.table.rows[0].cells.length
	for(var i=0; i<numRows; i++) {
		var _i = i
		for (var ii=1; ii<numCols;ii++) {
			//report("i: " + _i + " ii: " + ii + "\n")
			try {
				var td = this.table.rows[_i].cells[ii];
				if (td) {
					var textarea = td.firstChild
					var textareaName = textarea.getAttribute('name')
					//report("textareaName: " + textareaName + "\n")
					textareaNameArr = textareaName.split('######')
					newName = ('a' + i +'######c'+ ii + '######'+textareaNameArr[2])
					// report("newName: " + newName + "\n")
					textarea.setAttribute('name',newName)
				}
			} catch (err_MSXML2) {}
		}
	}
}





























// R E S I Z E R 
function resizerObj(P) {
/* I N F O 
	BorderWidth:		muss mit der im CSS definierten borderWidth uebereinstimmen
	

*/
	if (!window.resizerObjCounter) window.resizerObjCounter = 0;
	this.i = ++window.resizerObjCounter
	
	// alert("i " + i)
	P.top				? 	this.top 		 = 'top:'		+P.top 			+'px;'	: 	this.top 			= '';
	P.left				? 	this.left 		 = 'top:'		+P.top 			+'px;'	: 	this.left 			= '';
	P.width				? 	this.width 		 = 'width:'		+P.width 		+'px;'	: 	this.width 			= '';
	P.height			? 	this.height	 	 = 'height:'	+P.height 		+'px;'	: 	this.height 		= '';
	P.borderWidth		? 	this.borderWidth = 'height:'	+P.borderWidth 	+'px;'	: 	this.borderWidth 	= '1'; // Default: 1px border
	P.frameclass		? 	this.frameclass  = P.frameclass 	: 	this.frameclass 	= 'resizer_frame';
	P.handleclass		? 	this.handleclass = P.handleclass 	: 	this.handleclass 	= 'resizer_handle';
	P.display			? 	this.display = P.display 			: 	this.display 		= 'block';
	sideHandleDisplayStyle = 'display:block;';
	
	// Holder element (enthaelt frame + handles
	this.resizerElHolder 				= document.createElement('div')
	this.resizerElHolder.style.cssText 	= 'position:absolute; left:0; top:0; width:1px; height:1px;'
	// frame
	html = 			'<div class="'+this.frameclass+'" unselectable="on" id="resizeframe'+this.i+'"></div>'
	// handles
	html += 		'<div class="'+this.handleclass+'" unselectable="on" id="handle'+this.i+'_topLeft"		style="cursor:nw-resize;  	left:0; 		top:0;"		></div>'
	html += 		'<div class="'+this.handleclass+'" unselectable="on" id="handle'+this.i+'_topCenter" 	style="cursor:n-resize;  	left:50px; 		top:0; 		'+sideHandleDisplayStyle+';"></div>'
	html += 		'<div class="'+this.handleclass+'" unselectable="on" id="handle'+this.i+'_topRight"		style="cursor:ne-resize; 	left:100px; 	top:0; 		"></div>'
	html += 		'<div class="'+this.handleclass+'" unselectable="on" id="handle'+this.i+'_middleLeft" 	style="cursor:w-resize;  	left:0; 		top:50px; 	'+sideHandleDisplayStyle+'"></div>'
	html += 		'<div class="'+this.handleclass+'" unselectable="on" id="handle'+this.i+'_middleRight" 	style="cursor:w-resize;  	left:100px; 	top:50px; 	'+sideHandleDisplayStyle+'"></div>'
	html += 		'<div class="'+this.handleclass+'" unselectable="on" id="handle'+this.i+'_bottomLeft"  	style="cursor:ne-resize; 	left:0; 		top:100px; 	"></div>'
	html += 		'<div class="'+this.handleclass+'" unselectable="on" id="handle'+this.i+'_bottomCenter"  style="cursor:n-resize; 	left:50px; 		top:100px; 	'+sideHandleDisplayStyle+'"></div>'
	html += 		'<div class="'+this.handleclass+'" unselectable="on" id="handle'+this.i+'_bottomRight" 	style="cursor:nw-resize; 	left:100px; 	top:100px;	"></div>'
	this.resizerElHolder.innerHTML = html;
	document.body.appendChild(this.resizerElHolder)
	// alert(this.resizerEl.innerHTML)
	
	this.h_topLeft 			= document.getElementById('handle'+this.i+'_topLeft');				// 8 Griffe
	this.h_topCenter		= document.getElementById('handle'+this.i+'_topCenter');
	this.h_topRight			= document.getElementById('handle'+this.i+'_topRight');
	this.h_middleLeft 		= document.getElementById('handle'+this.i+'_middleLeft');
	this.h_middleRight		= document.getElementById('handle'+this.i+'_middleRight');
	this.h_bottomLeft		= document.getElementById('handle'+this.i+'_bottomLeft');
	this.h_bottomCenter		= document.getElementById('handle'+this.i+'_bottomCenter');
	this.h_bottomRight		= document.getElementById('handle'+this.i+'_bottomRight');
	this.resizerEl 			= document.getElementById('resizeframe'+this.i);					// der Frame
	// this.resizerEl
	this.handleW 			= this.h_topLeft.offsetWidth
	// alert(getCSSStyle(this.resizerEl,'border')) //geht nicht...
	this.setFrame(200,200,200,200)
	
	//alert(this.handleWidth)
	// this.positionHandles(this)
	
	var obj = this // Fuer call
	// 8 Griffe, und der resizeframe
	this.d_topLeft 		= new dragObj({dragEl:'handle'+this.i+'_topLeft',		constrainH:0, constrainV:0, call_drag:	function(){obj.positionHandles(this)}	})
	this.d_topCenter 	= new dragObj({dragEl:'handle'+this.i+'_topCenter', 	constrainH:0, constrainV:1, call_drag:	function(){obj.positionHandles(this)}	})
	this.d_topRight 	= new dragObj({dragEl:'handle'+this.i+'_topRight', 		constrainH:0, constrainV:0, call_drag:	function(){obj.positionHandles(this)}	})
	this.d_middleLeft 	= new dragObj({dragEl:'handle'+this.i+'_middleLeft', 	constrainH:1, constrainV:0, call_drag:	function(){obj.positionHandles(this)}	})
	this.d_middleRight 	= new dragObj({dragEl:'handle'+this.i+'_middleRight', 	constrainH:1, constrainV:0, call_drag:	function(){obj.positionHandles(this)}	})
	this.d_bottomLeft 	= new dragObj({dragEl:'handle'+this.i+'_bottomLeft', 	constrainH:0, constrainV:0, call_drag:	function(){obj.positionHandles(this)}	})
	this.d_bottomCenter = new dragObj({dragEl:'handle'+this.i+'_bottomCenter', 	constrainH:0, constrainV:1, call_drag:	function(){obj.positionHandles(this)}	})
	this.d_bottomRight 	= new dragObj({dragEl:'handle'+this.i+'_bottomRight', 	constrainH:0, constrainV:0, call_drag:	function(){obj.positionHandles(this)}	})
	// frame
	this.d_frame 		= new dragObj({dragEl:'resizeframe'+this.i, 			constrainH:0, constrainV:0, call_drag:	function(){obj.positionHandles(this)}	})
	// report(document.body.innerHTML)
}
resizerObj.prototype.setFrame = function(L,T,W,H) {

		if (L) this.resizerEl.style.left 	= L + 'px'
		if (T) this.resizerEl.style.top 	= T + 'px'
		if (W) this.resizerEl.style.width 	= W + 'px'
		if (H) this.resizerEl.style.height 	= H + 'px'
		PL 	= absLeft(this.resizerEl)							// left
		PT 	= absTop(this.resizerEl)							// top
		PR  = absLeft(this.resizerEl) + this.resizerEl.offsetWidth	- this.handleW		// right
		PB  = absTop(this.resizerEl)  + this.resizerEl.offsetHeight	- this.handleW		// bottom
		PC	= PL + ((PR - PL)/2)			// center
		PM  = PT + ((PB - PT)/2)			// middle
		this.h_topLeft.style.left 		= PL + 'px'
		this.h_topLeft.style.top  		= PT + 'px'
		this.h_topCenter.style.left 	= PC + 'px'
		this.h_topCenter.style.top  	= PT + 'px'
		this.h_topRight.style.left 		= PR + 'px'
		this.h_topRight.style.top  		= PT + 'px'
		
		this.h_middleLeft.style.left 	= PL + 'px'
		this.h_middleLeft.style.top  	= PM + 'px'
		this.h_middleRight.style.left 	= PR + 'px'
		this.h_middleRight.style.top  	= PM + 'px'
		
		this.h_bottomLeft.style.left 	= PL + 'px'
		this.h_bottomLeft.style.top  	= PB + 'px'
		this.h_bottomCenter.style.left 	= PC + 'px'
		this.h_bottomCenter.style.top  	= PB + 'px'
		this.h_bottomRight.style.left 	= PR + 'px'
		this.h_bottomRight.style.top  	= PB + 'px'
		
}

resizerObj.prototype.positionHandles = function(obj) {
		// obj ist das Object, das den caller sendet, z. B. das dragObj
		// aktuelle Masse erfassen
		PL 	= absLeft(this.h_topLeft)						// left
		PT 	= absTop(this.h_topLeft)						// top
		PR  = absLeft(this.h_bottomRight)	+ this.handleW // right
		PB  = absTop(this.h_bottomRight)	+ this.handleW // bottom
		var resizeFrameFlag = 0
		// report("\PL: "+ PL + " PT: " + PT + " PR: " + PR + " PB: " + PB, '','400px')
		switch(obj.dragEl) {
			case this.resizerEl:
				this.setFrame();
				resizeFrameFlag = 1
				break
			case this.h_topLeft:
				nL = absLeft(obj.dragEl)
				nT = absTop(obj.dragEl)
				nR = PR
				nB = PB
				break;
			case this.h_topCenter:
				nL = PL
				nT = absTop(obj.dragEl)
				nR = PR
				nB = PB
				break;
			case this.h_topRight:
				nL = PL
				nT = absTop(obj.dragEl)
				nR = absLeft(obj.dragEl) + this.handleW
				nB = PB
				break;
			case this.h_middleLeft:
				nL = absLeft(obj.dragEl)
				nT = PT
				nR = PR
				nB = PB
				break;
			case this.h_middleRight:
				nL = PL
				nT = PT
				nR = absLeft(obj.dragEl) + this.handleW
				nB = PB
				break;
			case this.h_bottomLeft:
				nL = absLeft(obj.dragEl)
				nT = PT
				nR = PR
				nB = absTop(obj.dragEl) + this.handleW
				break;
			case this.h_bottomCenter:
				nL = PL
				nT = PT
				nR = PR
				nB = absTop(obj.dragEl) + this.handleW
				break;
			case this.h_bottomRight:
				nL = PL
				nT = PT
				nR = absLeft(obj.dragEl) + this.handleW
				nB = absTop(obj.dragEl)  + this.handleW
				break;
			
		
		}
		// report("\nL: "+ nL + " nT: " + nT + " nR: " + nR + " nB: " + nB, '','400px') 
		// report("\n nB: " + nB, '','400px') 
		nW = nR - nL
		nH = nB - nT
		
		// report("\nL: "+ nL + " nT: " + nT + " nW: " + nW + " nH: " + nH, '','400px') 
		// obj.dragEl.style.left = 0;
		// obj.dragEl.style.top  = 0;
		
		if (!resizeFrameFlag) {
			this.resizerEl.style.left 	= nL + 'px'
			this.resizerEl.style.top 	= nT + 'px'
			this.resizerEl.style.width 	= (nW - this.borderWidth*2) + 'px'
			this.resizerEl.style.height = (nH - this.borderWidth*2) + 'px'
		}
		this.setFrame()
		/*
		left	= 0
		top 	= 0
		right 	= this.resizerEl.offsetWidth  	- this.handleW
		bottom 	= this.resizerEl.offsetHeight 	- this.handleW
		center  = this.resizerEl.offsetWidth/2  - this.handleW/2
		middle  = this.resizerEl.offsetHeight/2 - this.handleW/2
		*/
		/*alert(
			"left:" 	+ left 		+ "\n" + 
			"top:" 		+ top 		+ "\n" + 
			"right:" 	+ right 	+ "\n" + 
			"bottom:" 	+ bottom 	+ "\n" + 
			"center:" 	+ center 	+ "\n" + 
			"middle:" 	+ middle 	+ "\n" + 
			""
		)*/
		/*
		this.h_topLeft.style.left 		= left
		this.h_topLeft.style.top  		= top
		this.h_topMiddle.style.left 	= center
		this.h_topMiddle.style.top  	= top
		this.h_topRight.style.left 		= right
		this.h_topRight.style.top  		= top
		
		this.h_centerLeft.style.left 	= left
		this.h_centerLeft.style.top  	= middle
		this.h_centerRight.style.left 	= right
		this.h_centerRight.style.top  	= middle
		
		this.h_bottomLeft.style.left 	= left
		this.h_bottomLeft.style.top  	= bottom
		this.h_bottomMiddle.style.left 	= center
		this.h_bottomMiddle.style.top  	= bottom
		this.h_bottomRight.style.left 	= right
		this.h_bottomRight.style.top  	= bottom
		*/
		
		/*
		alert(
				"rootID " 							+ this.rootID	+ "\n" + 
				"absTop(this.rootEl) " 				+ absTop(this.rootEl)	+ "\n" + 
				"obj.posV " 						+ obj.posV 	+ "\n" + 
				"maxHeight " 						+ this.rootEl.offsetHeight 	+ "\n" + 
				"maxWidth " 						+ this.rootEl.offsetWidth 	+ "\n" + 
				"_areaframe.offsetHeight"			+ document.getElementById(this.rootID +'_areaframe').offsetHeight 	+ "\n" + 
				"_height " 							+ _height 					+ "\n" + 
				"_width " 							+ _width 					+ "\n" + 
				"defaultsize " 						+ defaultsize 				+ "\n" + 
				"this.defaultfactor " 				+ this.defaultfactor 			+ "\n" + 
				"this.slidersize " 					+ this.slidersize 			+ "\n" + 
				"this.area1.style.top " 			+ this.area1.style.top 		+ "\n" + 
				"this.area1.style.height " 			+ this.area1.style.height 	+ "\n" + 
				"this.slider.style.top " 			+ this.slider.style.top 	+ "\n" + 
				"this.slider.style.height " 		+ this.slider.style.height 	+ "\n" +
				"this.area2.style.top " 			+ this.area2.style.top 	+ "\n" +  
				"this.area2.style.height" 			+ this.area2.style.height 	+ "\n" + 
				"")
			*/
	
}














function pickerObj(P) {
/* I N F O 
	Es koennen unterschiedliche Style-Eigneschaften gepickt werden:
		Default:		(cssProperty,cssPropertyJS) background-color, backgroundColor

	Wenn der Picker geschlossen wird, ohne set(), dann wird der Ausgangswert wiederhergestellt. (this.startvalue)
	

*/
	if (!window.queryStr) window.queryStr = getQueryStr()
	if (!P.rootID) alert("pickerObj: no rootID, can't go on")
	else this.rootID 	= P.rootID
	this.saveMode 		= P['saveMode']
	this.onclick 		= P.onclick
	// alert("this.onclick: " +this.onclick)
	// alert(this.rootID)
	// registerEventListenersObj(document, "mouseup",  this, false, 'refreshArea');
	this.picker 			= document.getElementById(this.rootID)
	this.parentForm 		= findParentElementByNodeName(document.getElementById(this.rootID),'form')
	this.inputField 		= document.getElementById(this.rootID + '_pVal');
	this.cssPropertyJS 		= P.cssPropertyJS
	// alert(this.cssPropertyJS)
	this.pickerLayer 		= document.getElementById(this.rootID + '_pickerlayer')
	this.pickerInnerLayer 	= document.getElementById(this.rootID + '_pickerinnerlayer')
	// Updaten eines anderen Elements, z. B. einem Anzeigefeld
	this.targetFieldID 	= P.targetFieldID
	this.targetField   	= document.getElementById(this.targetFieldID);				// optional
	this.startvalue 	= P.activeValue
}

pickerObj.prototype.hide = function(e,el) {
	e = e ? e : event;
	if (!el.contains(e.relatedTarget || e.toElement)) {
		// report("!contains: "+ e.toElement.id)
		el.style.display = "none"
	}
	this.picker.style[this.cssPropertyJS] 		= this.startvalue
}
pickerObj.prototype.view = function(val,el) {
	// alert('val ' + val)
	this.picker.style[this.cssPropertyJS] = val
	this.inputField.value 				= val
	if (this.targetField) this.targetField.value= val
	// el.style.border = '1px solid red';
}
pickerObj.prototype.set = function(val) {
	// alert("pickerObj set: " + val)
	// report("this.onclick: " + this.onclick)
	this.pickerLayer.style.display 				= 'none'
	this.picker.style[this.cssPropertyJS] 		= val
	this.inputField.value 						= val
	this.startvalue								= val
	if (this.targetField) this.targetField.value= val
	window.queryStr = modifyQueryString(window.queryStr,0,this.rootID + '_pVal', escape(val))
	if (this.onclick) {
		// report("this.onclick: " + this.onclick)
		this.onclick();
	}
}

















function tabsObj(P) {
	if (!window.queryStr) window.queryStr = getQueryStr()
	/* I N F O 
	*/
	if (!P.rootID) alert("tabsObj: no rootID, can't go on")
	else this.rootID = P.rootID
	// alert(this.rootID)
	// registerEventListenersObj(document, "mouseup",  this, false, 'refreshArea');
	this.rootEl 		= document.getElementById(this.rootID)
	this.parentForm 	= findParentElementByNodeName(document.getElementById(this.rootID),'form')
	this.inputField 	= document.getElementById(this.rootID + '_activetab');
	this.inputField2 	= document.getElementById(this.rootID + '_activetabname');
	// alle Reiter erfassen
	this.tabcount 		= P['tabcount']
	this.tabnamesArr 	= P['tabnames'].split(';#;')
	this.saveMode 		= P['saveMode']
	this.tabs = {};
	for(i=0;i<this.tabcount; i++) {
		tab = document.getElementById(this.rootID + '_tab' + i);
		this.tabs['tab'+i] = tab
		registerEventListenersObj(tab, "mousedown",	this, false, 'activatetab',i);
	}
	imgPreloader(new Array('tabs_active1n.gif','tabs_active1r.gif','tabs_active2n.gif','tabs_active2r.gif','tabs_inactive1n.gif','tabs_inactive1r.gif','tabs_inactive2n.gif','tabs_inactive2r.gif'));
	// alert(showObject(this.tabs))
}

tabsObj.prototype.activatetab = function(e,el,tabNum) {
	activetab = document.getElementById(this.rootID + '_tab' + tabNum);
	//alert("activetab " + activetab.id)
	//alert(showObject(this.tabs))
	var i = 0;
	for (tab in this.tabs) {
		//alert(this.tabs[tab].id)
		this.tabs[tab].className = this.tabs[tab].className.replace('li_active','li_inactive');
		//alert(this.tabs[tab].className)
		// alert(this.rootID + '_layer' + i)
		if (document.getElementById(this.rootID + '_layer' + i)) {
			//alert(this.rootID + '_layer' + i)
			document.getElementById(this.rootID + '_layer' + i).style.display = 'none'
		}
		i++
	}
	activetab.className = activetab.className.replace('li_inactive','li_active');
	if (document.getElementById(this.rootID + '_layer' + tabNum)) {
			document.getElementById(this.rootID + '_layer' + tabNum).style.display = ''
	}
	// alert("this.id " + this.id + " pars " + pars)
	this.inputField.value = tabNum
	this.inputField2.value = this.tabnamesArr[tabNum]
	window.queryStr = modifyQueryString(window.queryStr,0,this.rootID + '_activetab', this.inputField.value)
	// alert("window.queryStr " + window.queryStr)
	// alert(this.saveMode + "this.parentForm " + this.parentForm.name)
	if (this.saveMode == 'POST') {
		this.parentForm.submit();
	}
	if (this.saveMode == 'GET')  {
		newUrl =  modifyQueryString('',1,'',window.queryStr)							// normal: 			varname, varvalue	
		// alert("newUrl: " + newUrl)
		document.location.href = newUrl
	}
}




function clapObj(P) {
	if (!window.queryStr) window.queryStr = getQueryStr()
	/* I N F O 
	Erwartet ein Parameterobject {}
	*/
	if (!P.rootID) alert("clapObj: no rootID, can't go on")
	else this.rootID = P.rootID
	
	// registerEventListenersObj(document, "mouseup",  this, false, 'refreshArea');
	this.rootEl = document.getElementById(this.rootID)
	// Bereiche
	this.openerID  		= this.rootID + '_opener';			this.opener 	= document.getElementById(this.openerID);   		if (!this.opener) 	alert("clapObj: no opener, can't go on")
	this.claptargetID  	= P['claptargetID'];				this.claptarget = document.getElementById(this.claptargetID);   	if (!this.claptarget) 	alert("clapObj: no claptarget, can't go on")
	this.parentForm 	= findParentElementByNodeName(document.getElementById(this.rootID),'form')
	this.inputField 	= document.getElementById(this.rootID + '_clapstate');	
	this.clapstate 		= P['clapstate']
	this.saveMode 		= P['saveMode']
	// report("this.saveMode: " + this.saveMode)
	this.resizewindow 	= P['resizewindow']
	this.autoClapTarget = P['autoClapTarget']
	registerEventListenersObj(this.opener, "click",	this, false, 'clap'); // IE hat ein Problem beim window.resize die richtige Hoehe zu berechnen, etwas spater geht es.
	// alert("claptargetID: " + this.claptargetID)
	// alert("this.clapstate: "+this.clapstate)
	// !autoClapTarget heisst, dass das Claptarget ausserhalb liegt, also ein beliebiges Element sein kann, dessen display nicht mir PHP geschrieben werden kann.
	// Es muss also ueber Javascript geoeffnet werden.
	// alert(this.clapstate)
	if (!this.autoClapTarget && this.clapstate=='opened') this.clap('opened')
}


clapObj.prototype.clap = function(state) {
// Fensterhoehe bestimmen IE mit Leisten?
	if (document.all) 	{
		this.windowWidth  = document.body.clientWidth + 8 // fuer Border
		this.windowHeight = document.body.clientHeight + 29
	} else {
		this.windowWidth  = window.outerWidth
		this.windowHeight = window.outerHeight
	}
	// alert("this.windowWidth " + this.windowWidth + " this.windowHeight " + this.windowHeight)
	// alert("this.clapstate " + this.clapstate)
	
	// O E F F N E N
	if (this.clapstate == 'closed' || state == 'opened') {
		this.opener.className = this.opener.className.replace('clap_closed','clap_opened');
		// alert(this.claptarget.className)
		if (hasClassName(this.claptarget,"claptarget_closed"))  this.claptarget.className = this.claptarget.className.replace('claptarget_closed','claptarget_opened');
		else 													this.claptarget.className += ' claptarget_opened';
		this.clapstate 				= 'opened'
		this.inputField.value 		= 'opened'
		this.claptarget.style.display = ''	// sicherheitshalber deise Eigenschaft entfernenm soll vom ClassName ueberschreiben werden
		window.queryStr 			= modifyQueryString(window.queryStr,0,this.rootID + '_clapstate', this.inputField.value)
		if (this.resizewindow) {
			clapTargetHeight = this.claptarget.offsetHeight
			//alert("clapTargetHeight " + clapTargetHeight)
			//alert(window.outerHeight + clapTargetHeight + 'px')
			//if (document.all) 	{window.resizeTo(this.windowWidth, this.windowHeight + clapTargetHeight)}
			//else 				{window.outerHeight = window.outerHeight + clapTargetHeight + 'px'}
			if (document.all) 	{window.resizeBy(0, clapTargetHeight)}
			else 				{window.outerHeight = '800px'}
		}
	// S C H L I E S S E N	
	} else {					
		if (this.resizewindow) {
			clapTargetHeight = this.claptarget.offsetHeight
			//alert("clapTargetHeight " + clapTargetHeight)
			if (document.all) 	{window.resizeBy(0, -clapTargetHeight)}
			else 				{window.outerHeight = window.outerHeight - clapTargetHeight + 'px'}
		}
		// alert(this.claptarget.className)
		if (hasClassName(this.claptarget,"claptarget_opened"))  this.claptarget.className = this.claptarget.className.replace('claptarget_opened','claptarget_closed');
		else 													this.claptarget.className += ' claptarget_closed';
		this.claptarget.style.display 				= ''
		this.opener.className = this.opener.className.replace('clap_opened','clap_closed');
		this.clapstate 				= 'closed'
		this.inputField.value 		= 'closed'
		window.queryStr 			= modifyQueryString(window.queryStr,0,this.rootID + '_clapstate', this.inputField.value)
	}
	// alert(this.saveMode)
	if (this.saveMode.toLowerCase() == 'post') document[this.parentForm.name].submit();
	/*
	alert(		"this.clapstate " 			+ this.clapstate 				+ "\n" + 
				"claptarget.id: " 			+ this.claptarget.id			+ "\n" + 
				"claptarget.className: " 	+ this.claptarget.className		+ "\n" + 
				
	"")
	*/
	
}

	
	
	
function areaObj(P) {
	
	if (!window.queryStr) window.queryStr = getQueryStr()
	/* I N F O 
	Erwartet ein Parameterobject {constrain_h:'20px', ...}
	*/
	if (!P.rootID) alert("areaObj: no rootID, can't go on")
	else this.rootID = P.rootID
	P.direction  ?  this.direction = P.direction  : this.direction  = 'h'
	// registerEventListenersObj(document, "mouseup",  this, false, 'refreshArea');
	this.rootEl = document.getElementById(this.rootID)
	// Bereiche
	this.area1ID  		= this.rootID + '_1';				this.area1 		= document.getElementById(this.area1ID);   			if (!this.area1) 	alert("areaObj: no area1, can't go on")
	this.area2ID  		= this.rootID + '_2';				this.area2 		= document.getElementById(this.area2ID);   			if (!this.area2) 	alert("areaObj: no area2, can't go on")
	this.sliderID 		= this.rootID + '_slider';			this.slider 	= document.getElementById(this.sliderID);			if (!this.slider) 	alert("areaObj: no areaSlider, can't go on")
	this.inputField 	= document.getElementById(this.rootID + '_a1f');														if (!this.inputField) 	alert("areaObj: no inputField '" +this.rootID + "_a1f,' can't go on") 
	this.framesize     	= P.framesize
	this.slidersize     = parseInt(P.slidersize)
	this.defaultfactor  = P.defaultfactor
	if (!this.defaultfactor) this.defaultfactor = 0.5; // Defaultverteilung
	this.slideroverlay  = P.slideroverlay
	this.parentForm		= findParentElementByNodeName(this.rootEl,'form')
	this.parentStartWidth  = this.rootEl.offsetWidth
	this.parentStartHeight = this.rootEl.offsetHeight
	// alert(this.rootID + " this.defaultfactor " + this.defaultfactor)
	// dragObj
	var obj = this // Fuer call
	if (document.all) 	registerEventListenersObj(window, "resize",	this, false, 'resizeAreaLater'); // IE hat ein Problem beim window.resize die richtige Hoehe zu berechnen, etwas spater geht es.
	else 				registerEventListenersObj(window, "resize",	this, false, 'resizeArea');
	// registerEventListenersObj(window, "resize",	this, false, 'resizeArea');
	
	// window.setInterval(function() {obj.checkForSizeChanges('')}, 100)
	// Slideroverlay einstellen
	if (this.slideroverlay == true) 	{
		if (this.direction == 'v') {
			document.getElementById(this.rootID + '_overlay1v').style.left 		= -this.framesize  + 'px'
			document.getElementById(this.rootID + '_overlay1v').style.width 	=  this.framesize  + 'px'
			document.getElementById(this.rootID + '_overlay1v').style.height 	=  this.slidersize + 'px'
			document.getElementById(this.rootID + '_overlay2v').style.width 	=  this.framesize  + 'px'
			document.getElementById(this.rootID + '_overlay2v').style.height 	=  this.slidersize + 'px'
		} else {
			document.getElementById(this.rootID + '_overlay1h').style.top 		= -this.framesize + 'px'
			document.getElementById(this.rootID + '_overlay1h').style.height 	=  this.framesize + 'px'
			document.getElementById(this.rootID + '_overlay2h').style.height 	=  this.framesize + 'px'
		}
	}

	// Startwerte
	this.resizeArea('')
	
	// alert(showObject(this))
	if (this.direction=='h') new dragObj({
					dragEl: 			this.rootID + '_slider', 
					constrainH:			1, 
					maxLeft: 			this.rootEl, 
					maxRight:			this.rootEl,  
					call_startdrag:		function(){obj.resetSlider(this,'absolute')}, 
					call_stopdrag:		function(){obj.resetSlider(this,'relative')}, 
					call_drag:			function(){obj.resizeArea(this)}   
					})
	if (this.direction=='v') new dragObj({
					dragEl: this.rootID + '_slider', 
					constrainV:			1, 
					maxTop: 			this.rootEl,  
					maxBottom:			this.rootEl,
					call_startdrag:		function(){obj.resetSlider(this,'absolute')}, 
					call_stopdrag:		function(){obj.resetSlider(this,'relative')}, 
					call_drag:			function(){obj.resizeArea(this)}   
					})
					
}

areaObj.prototype.resizeAreaLater = function() {
	var obj = this
	//report("resizeAreaLater " + this.rootID)
	// report("resizeAreaLater " + obj.rootID)
	window.setTimeout(function() {obj.resizeArea('')}, 100)
}


areaObj.prototype.checkForSizeChanges = function() {
	if (this.rootEl.offsetWidth != this.parentStartWidth) {
		this.parentStartWidth = this.rootEl.offsetWidth
		this.resizeArea('');
	}
	if (this.rootEl.offsetHeight != this.parentStartHeight) {
		this.parentStartHeight = this.rootEl.parentStartHeight
		this.resizeArea('');
	}
}
areaObj.prototype.resizeArea = function(obj) {
// obj ist das Object, das den caller sendet, z. B. das dragObj

		// alert("resizeArea " + this.rootID)
		// if (this.direction == 'h') this.area1.width  = obj.posH - absLeft(this.area1) + 'px'
		if (this.inputField.value) 	this.defaultfactor = this.inputField.value
		_height = 0;
		_width  = 0;
		if (this.direction == 'v') {
			if (this.defaultfactor) 	defaultsize = parseInt((this.rootEl.offsetHeight - this.slidersize) * this.defaultfactor)
			else 						defaultsize = parseInt((this.rootEl.offsetHeight - this.slidersize) * 0.5)
			if (!obj.posV) 				_height = defaultsize
			else 						_height = obj.posV - absTop(this.rootEl)
			this.area1.style.top 		= 0
			this.area1.style.height 	= _height 			+ 'px'
			this.slider.style.top 		= _height 			+ 'px'
			this.slider.style.height 	= this.slidersize 	+ 'px'						// slider
			this.area2.style.height 	= this.rootEl.offsetHeight - _height - this.slidersize + 'px'
			this.area2.style.top 		= (_height 			+ this.slidersize) + 'px'
		}
		if (this.direction == 'h') {
			if (this.defaultfactor) 	defaultsize = parseInt((this.rootEl.offsetWidth - this.slidersize) * this.defaultfactor)
			else 						defaultsize = parseInt((this.rootEl.offsetWidth - this.slidersize) * 0.5)
			if (!obj.posH) 				_width = defaultsize
			else 						_width = obj.posH - absLeft(this.rootEl)
			//this.area1.style.height 	= '100%'
			//this.area2.style.height 	= '100%'
			//this.slider.style.height 	= '100%'
			
			this.area1.style.left 		= 0
			this.area1.style.width 		= _width 			+ 'px'
			this.slider.style.left 		= _width 			+ 'px'
			this.slider.style.width 	= this.slidersize 	+ 'px'						// slider
			this.area2.style.width 		= this.rootEl.offsetWidth - _width - this.slidersize + 'px'
			this.area2.style.left 		= (_width 			+ this.slidersize) + 'px'
		}
		/*
		alert(
				"rootID " 							+ this.rootID	+ "\n" + 
				"absTop(this.rootEl) " 				+ absTop(this.rootEl)	+ "\n" + 
				"obj.posV " 						+ obj.posV 	+ "\n" + 
				"maxHeight " 						+ this.rootEl.offsetHeight 	+ "\n" + 
				"maxWidth " 						+ this.rootEl.offsetWidth 	+ "\n" + 
				"_areaframe.offsetHeight"			+ document.getElementById(this.rootID +'_areaframe').offsetHeight 	+ "\n" + 
				"_height " 							+ _height 					+ "\n" + 
				"_width " 							+ _width 					+ "\n" + 
				"defaultsize " 						+ defaultsize 				+ "\n" + 
				"this.defaultfactor " 				+ this.defaultfactor 			+ "\n" + 
				"this.slidersize " 					+ this.slidersize 			+ "\n" + 
				"this.area1.style.top " 			+ this.area1.style.top 		+ "\n" + 
				"this.area1.style.height " 			+ this.area1.style.height 	+ "\n" + 
				"this.slider.style.top " 			+ this.slider.style.top 	+ "\n" + 
				"this.slider.style.height " 		+ this.slider.style.height 	+ "\n" +
				"this.area2.style.top " 			+ this.area2.style.top 	+ "\n" +  
				"this.area2.style.height" 			+ this.area2.style.height 	+ "\n" + 
				"")
			*/
	
}
areaObj.prototype.resetSlider = function(obj, mode) {
	if (this.direction == 'h') 	this.inputField.value = (this.area1.offsetWidth/parseFloat(this.rootEl.offsetWidth   - this.slidersize))
	else 						this.inputField.value = (this.area1.offsetHeight/parseFloat(this.rootEl.offsetHeight - this.slidersize))
	window.queryStr = modifyQueryString(window.queryStr,0,this.rootID + '_a1f', this.inputField.value)
}
areaObj.prototype.refreshArea = function(e) {
	e  = (e) ? e : event;
	el = (e.target) ? e.target : e.srcElement;
	if (el == this.areaSlider) {
		// alert("refreshArea")
	}
}


















// ________________________________________________________________________________________________________________________________
// D R A G  +dragObj
function dragObj(P) {
	/* I N F O 
	
	
	I F R A M E S draggen:
	Dragen eines Fenster mit Iframe: testen in Formgenerator, new form...
	mit docRef werden die Events aus dem Iframe mit beruecksichtigt und mir denen des Divs um den Iframe zusammengemischt.
			this.drag = new opener.dragObj({
			dragEl: 			parent['cargowindow_'+q.cwCounter].rootEl, 
			controlEl: 			this.document.getElementById("cargowindow_headbar"), 
			docRef: 			parent['cargowindow_'+q.cwCounter].iframe
		})
	
	
	Erwartet ein Parameterobject {dragEl:dragEl...constrain_h:'20px', ...}
	-	dragEl
		das zu draggende ELement, wird erst nach Klick activert (this.activated)
	-	refEl
		ein Element, das fuer dropRaget Actions verwendet wird (z. B. tauscht die Position)
		das kann ein anderes sein als das gedraggte
	-	controlEl
		ein Element, daß das dragEl mitbewegt, z. B. der Griff am Editor bewegt die ganze Editorpalette
	
	Beim Klick auf ein bestimmtes Element soll gleichzeitig das dragObj erzeugt werden, aber auch der Dragvorgang beginnen
	Das DragObj ist beispielsweise eine gedimmte Kopie oder ein Rahmen
	previewmode: dummy | ghost
	*/
	// alert(typeof(P.dragEl))
	// window.EvLisObj = {} // nach jedem Refresh wieder leeren
	// alert("typeof P.dragEl: " + typeof(P.dragEl))
	if (typeof P.dragEl == 'object') 	this.dragEl = P.dragEl									// kann ein HTML object sein
	else 								this.dragEl = document.getElementById(P.dragEl)			// oder eine ID
	// report(this.dragEl.id)
	// report(this.dragEl.id)
	// this.sq = 1
	if (!this.dragEl) alert("dragObj: no dragEl. Can't go on")
	this.previewmode = P.previewmode 
	// report("this.dragEl.id: " +this.dragEl.id);
	
	/*
	// D R A G D U M M Y , z.B. roter Rahmen
	// wird fuer jeden Drag neu generiert
	if (this.previewmode == 'dummy'){
		var div = document.createElement("div")
		// es wird ein unsichtbares Element drübergelegt
		// Diese Angaben driekt als style definieren, der rest in class .dragDummy
		div.style.cssText 	= 'left:'+(absLeft(this.dragEl))+'px; top:'+absTop(this.dragEl) +'px; width:'+(this.dragEl.offsetWidth)+'px; height:'+this.dragEl.offsetHeight+'px;'
		div.className		= 'drag_dummy';
		div.id  			= 'dummy_'+this.dragEl.id // darf nur 1 '_' enthalten, z.B. dummydragEl_2
		document.body.appendChild(div)
		this.dragEl 	= div
		this.dragDummy 	= div
		// report("opacity: " + this.dragDummy.style.opacity)
		// report(this.dragEl.id)
	}
	*/
	if (this.previewmode == 'ghost'){
		this.refEl = this.dragEl
	}
	/*
	// G H O S T , Duplicat des zu draggenden Elements
	if (this.previewmode == 'ghost'){
		P.ghostopacity 	?  this.ghostopacity  = P.ghostopacity : this.ghostopacity = 50
		var ghost 			= this.dragEl.cloneNode(true)
		ghost.id  			 = 'ghost_'+this.dragEl.id // darf nur 1 '_' enthalten, z.B. dummydragEl_2
		ghost.style.position = 'absolute'
		ghost.style.left 	 = absLeft(this.dragEl) 		+ 'px' 
		ghost.style.top 	 = absTop(this.dragEl) 			+ 'px' 
		ghost.style.width 	 = this.dragEl.offsetWidth 		+ 'px' 
		ghost.style.height 	 = this.dragEl.offsetHeigth 	+ 'px' 
		if (document.all) 	ghost.style.filter = 'alpha(opacity =0);'
		else  				ghost.style.opacity = 0;
		document.body.appendChild(ghost)
		//this.dragEl = ghost
		this.dragEl 	= ghost
		this.dragDummy 	= ghost
		// alert(this.dragEl.innerHTML)
	}
	*/
	/*
	if (this.dragEl.parentNode.style.position == 'relative' || P.calcRelPosition) {
		this.calcRelPosition = 1
	}
	if (this.calcRelPosition) {
		this.parentEl 	= this.dragEl.parentNode	// wenn relative, dann mussen die Distanzen in Bezug auf den Parent berechnet werden
		this.parentLeft = absLeft(this.parentEl)
		this.parentTop  = absTop(this.parentEl)
		// report(this.parentEl.nodeName + " this.parentEl.id: "+ this.parentEl.id + " parentEl coords:  " + this.parentLeft	+ ' ' + this.parentTop)
	}
	*/
	if (P.controlEl) { // Element, dass das dragEl mitnimmt
		if (typeof(P.controlEl) == 'object') 	this.controlEl = P.controlEl									// kann ein HTML object sein
		else 									this.controlEl = document.getElementById(P.controlEl)			// oder eine ID
	} else {
		this.controlEl  = this.dragEl
	}
	// report(this.controlEl.id)
	// this.dummy 				= P.dummy 		// Es wird nicht das Original-Element bewegt, sondern ein Dummy (Rahmen oder so)
	P.constrainH 			?  this.constrainH  = P.constrainH  	: this.constrainH  	= 0		// Bewegung beschränken horizontal
	P.constrainV 			?  this.constrainV  = P.constrainV  	: this.constrainV  	= 0		// Bewegung beschränken vertikal
	P.maxLeft 				?  this.maxLeft 	= P.maxLeft  		: this.maxLeft 		= 0 	// Abstand zum Umfassenden Container left			Werte: %, px
	P.maxTop 			 	?  this.maxTop 		= P.maxTop  		: this.maxTop 		= 0		// Abstand top
	P.maxRight 				?  this.maxRight 	= P.maxRight  		: this.maxRight 	= 0		// Abstand right
	P.maxBottom 			?  this.maxBottom  	= P.maxBottom  		: this.maxBottom 	= 0		// Abstand bottom
	P.dropTargetClass 		?  this.dropTargetClass 		= P.dropTargetClass 		: this.dropTargetClass 			= ''		// koenne mehrere sein, ' ' sep. z.B. 'dropTargetClass dropTargetClass'
	P.dropTargetPositionMode?  this.dropTargetPositionMode 	= P.dropTargetPositionMode  : this.dropTargetPositionMode 	= 'hv'		// wenn ein DropTarhget verwendet wird, dann kann diesem eine Anordnung mitgegeben werden 
	P.ghostopacity 			?  this.ghostopacity  = P.ghostopacity 	: this.ghostopacity = 50
	P.dropTargetExpObj		?  this.dropTargetExpObj  = P.dropTargetExpObj 	: this.dropTargetExpObj = {}	// ein Object, das Elemente enthaelt {elementID: element}
	P.stopEvents 			?  this.stopEvents  	 = P.stopEvents  		: this.stopEvents 	= 0   		// preventDefault beim click, wird beim Einsatz eines resizeFramres benoetigt
	//if (P.cursor) 		this.cursor = P.cursor // cursor:move;
	//if (this.cursor)	this.dragEl.style.cursor = this.cursor
	this.inactive 		= null; // stoppen der eventbehandlung
	this.listeners = {}
	// report(this.cursor)
	// this.docRef = document
	
	// ________________________________________________________________________________________________ I F R A M E S
	// dragging Iframes
	// Das Problem liegt darin, daß man beim Draggen das Bezugsdocument wechselt: 
	// innerhalb des iframes, aussserhalb des iframes, beides muss eine fluessige Bewegung ergeben
	// Bsp Aufruf: drag = new dragObj({dragEl:iframeholder, controlEl: starter, docRef:iframe})
	// - frameborder des iframe 0
	// - Das DragObject wird in dem document erstellt, das den iframe enthaelt, nicht im document des iframes
	// - Die Distanz zur linken oberen Ecke ist dei Distanz innerhalb des Ifranes + dei Position des Iframes im umfassenden Element, das bewegt werden soll
	// - dem dragobje wird eine Refernz auf den iframe uebergeden -> docRef:iframe (iframe ist das iframe-Element)
	// - Das controlEl, das den drag startet, liegt innerhalb des iframes.
	// - Es werden eventlistener sowohl fuer de iframe als auch fuer das umfassene document erstellt
	//				docRef: der iframe
	// - bei "drag" wird ueber eine zusatzlichen Parameter unterschieden, ob der event aus dem document oder iframe.document kommt.
	// 				vgl. registerEventListenersObj(this.doc, 'mouseup', this, false, 'stopdrag', {doc:this.doc});	
	// - Das dragObject kann auch innerhalb des iframes fuer das Parent-document erzeugt werden.
	if (P.docRef) {	
		if (typeof(P.docRef) == 'string') 	this.docRef = document.getElementById(P.docRef)	
		else 								this.docRef = P.docRef 								// das iframe-Element
		
		if (this.docRef.nodeName.toLowerCase() == 'iframe') {this.doc = this.docRef.contentWindow.document}	// das document des iframe
		// alert("iframe.Element: " + this.docRef.nodeName)
		// report(this.doc.nodeName)
	}
	
	// report("this.docRef: " + this.docRef.nodeName)
	// Ein Referenzelement, Bsp: ein Dummy Rahmen wird gedraggt, er repraesentiert aber ein refEl, auf das eine DragDrop Action angewendet wird
	P.refEl 				?  this.refEl   	= P.refEl    		: this.refEl 		= null // Drop
	if (P.dropTargetMouseUpFunction) 	this.dropTargetMouseUpFunction  	= P.dropTargetMouseUpFunction	
	if (P.dropTargetMouseOverFunction)	this.dropTargetMouseOverFunction 	= P.dropTargetMouseOverFunction
	if (P.dropTargetMouseOutFunction)  	this.dropTargetMouseOutFunction 	= P.dropTargetMouseOutFunction
	P.dropTargetExcludeEl?     			this.dropTargetExcludeEl 			= P.dropTargetExcludeEl 	: this.dropTargetExcludeEl = null
	// +++ Das geht nicht:     this.dropTargetfunction = function(){...)}, fuehrt zu n-fach Ausfuehrung, wenn der Listener mehrfach an eine Element gehaengt wird.
	this.startDragInstantly = 1
	
	// this.dragEl.className += ' draggable_tmp'
	if (this.controlEl)	this.controlEl.className += ' draggable_tmp'
	else  				this.dragEl.className    += ' draggable_tmp'
	
	// Cursor
	/*
	this.firstCursor = getCSSStyle(this.dragEl,'cursor')   // report(this.firstCursor)
	if (this.cursor) {
			this.dragEl.style.cursor 	= this.cursor
			this.controlEl.style.cursor = this.cursor
	}
	*/
	// P.useSteps = 1;
	// P.useGuides = 1
	// P.useGrid = 1
	// P.useGlobalGuides = 1
	// P.useGlobalGrid   = 1
	
	// G U I D E S
	// Die uebermittelten Positionen muessen vorher in absolute Positionen bezogen uaf document.body umgerechnet werden.
	// Bsp: 100 in einem Div, das realtiv positioniert ist mit "left:22px" = 122 
	// Die Parameter feur Grid + Guides koenne direkt uebergeben werden, oder auch global verwednet werden.
	// Im letzteren Fall wird bei jeder Berechnung erneut auf das global Object (window.guidesObj, window.gridObj) zugegriffen, um einheitlichesVerhallten aller Drags zu ermoeglichen
	// Bsp. guidesObj: {horizontal: {start:0, positions:[]}, vertical:{start:0, positions:[]}} 
	if (P.useGuides) { 
		// Erwartet ein Object mit Guides {horizontal: [10,29,55], vertical:[22,100]}
		this.useGuides 					= 1
		if (P.guidesObj)				this.guidesObj = P.guidesObj
		if (this.useGlobalGuides)		this.guidesObj = window.globalGuidesObj
		P.guidesSnapDist  ? this.guidesSnapDist = P.guidesSnapDist 			: this.guidesSnapDist = 5
	}
	// G R I D S
	// Erwartet ein Object mit Grids {horizontal: [start:0, distance:20], vertical:[start:0, distance:50]}
	// Grids haben eine horizontalen und vertikalen Startpunkt und werden ab da als regelmaessige Distance angegeben
	// Bsp: gridObj:  {horizontal: {start:0, distance:20}, vertical:{start:0, distance:50}}
	if (P.useGrid) { 
		this.useGrid 					= 1
		if (P.gridObj)					this.gridObj = P.gridObj
		if (this.useGlobalGrid) 		this.gridObj = window.globalGridObj
		this.gridSnapDist 				= 5
	}
	// S T E P S
	// Bsp: stepsObj:  {horizontal: 10, vertical:20}
	if (P.useSteps) { 
		this.useSteps 					= 1
		if (P.stepsObj)					this.stepsObj = P.stepsObj
		else 							this.stepsObj = {horizontal: 10, vertical:10}
		if (this.useGlobalSteps) 		this.stepsObj = window.useGlobalSteps
	}
	
	// report(obj2Str(this.stepsObj))
	// alert(this.dropTargetClass)
	// alert(this.dropTargetfunction)
	// Funktionen, die gerufen wird bei drag, dragstart, dragstop, z. B. vom areaObj
	P.call_startdrag 		?  this.call_startdrag  = P.call_startdrag  	: this.call_startdrag 	= ''
	P.call_drag 			?  this.call_drag  		= P.call_drag  			: this.call_drag 		= ''
	P.call_stopdrag			?  this.call_stopdrag   = P.call_stopdrag  		: this.call_stopdrag 	= ''
	this.activated 	= null;
	// this.timed		= 1; // Beginn des Draggens verzoegern?
	this.width 		= this.dragEl.offsetWidth
	// Listener, Referenzen werden in listener-obj gespeichert zum removen  {f:..,c:...,el:...} (function, capture,element)
	this.listeners.mousedown = registerEventListenersObj(this.dragEl, 'mousedown', this, false, 'startdrag'); 
	this.listeners.mousemove = registerEventListenersObj(document, 'mousemove', this, false, 'drag');
	this.listeners.mouseup   = registerEventListenersObj(document, 'mouseup',   this, false, 'stopdrag');
	if (this.docRef) { // document des iframe mitgeben
		this.listeners.mousedownDocRef.f = registerEventListenersObj(this.doc, 'mousedown', this, false, 'startdrag',	{doc:this.doc});
		this.listeners.mousemoveDocRef.f = registerEventListenersObj(this.doc, 'mousemove', this, false, 'drag',		{doc:this.doc});
		this.listeners.mouseupDocRef.f   = registerEventListenersObj(this.doc, 'mouseup',   this, false, 'stopdrag',	{doc:this.doc});
	}	
	var obj = this
	// Ich erzeuge alle potentiellen Droptargets fuer dieses Dragobjet.
	// Das ist evtl. etwas ressourcenverschwenderisch, bei jedem Klick, aber ich habe für jedes Drag-Elenet die Moeglichkeit, individuelle Droptaregts zu definieren
	// es werden ebenfalls fuer alle dropTargets Listener erzeugt.
	this.getDropTargets()
	if (P.e) { // Automatisches Starten des Dragging, wenn ein event mitgeschickt wurde
		// report(eventInfo(P.e))
		// window.setTimeout(function() {})
		// report(eventInfo(P.e))
		// report(showObject(P.e))
		// V E R Z O E G E R U N G
		/*	 Anm: Das Object P.e kann scheinbar nicht ohne Verluste an eine Timeoutfunction weitergegeben werden. 
			Screenx, ScreenY gehen floeten sobald eventInfo i n n  e r h a l b  der timoutFunction aufgerufen wird! bzw. Sind 0, andere Werte bleiben gleich...
			window.setTimeout(function() {obj.startdrag(_e,'','start')},800)			-> Verluste!
			
		*/
		if (P.delay) {
			// report("P.delay" + P.delay)
			cX = P.e.clientX // wegen der Verluste im event werden die Clientx, clientY Werte hier ermittelt und mitgegeben
			cY = P.e.clientY
			window.dragObjTimeOut = window.setTimeout(function() {
				obj.startdrag(P.e,'','start', cX, cY)
				// report(eventInfo(P.e)) // hier kann man sich das Problem mit dem Versuten ausgeben...
			},P.delay);
		
		} else {
			this.startdrag(P.e,'','start') // der 2. Parameter ist scheinbar per default besetzt mit einem HTML-Element
		}
	}
}

dragObj.prototype.getDropTargets = function() {
	// Erweitert 15.04.09: Mehrer dropTaregtclasses erfassbar
	// report("this.dropTargetClass: " + this.dropTargetClass)
	// report("\n\ngetDropTargets")
	// report("this.dragEl: " + this.dragEl.id)
	// report("this.dropTargetClass: " + this.dropTargetClass)
	// report("this.drag dropTargetExpObj" + sO(this.dropTargetExpObj,2))
	// if (!this.activated) return
	if (this.inactive) return
	if (this.dropTargetClass) {
		var classArr = this.dropTargetClass.split(' ')
		// report("getDropTargets bin drin!!!<br>");
		
		//report(classArr.length)
		//report(sO(classArr))
		this.dropTargetArr = new Array();
		for (var i=0;i<classArr.length;i++) {
			// report("--> #" + classArr[i]+'#')
			var tempArr = getElementsByClassNameM(document,'',classArr[i])
			L = tempArr.length
			// Das Problem hier: Wenn ich eine literale Funktion oder eine Methode(wird auch als literale Funktion umgesetzt) für ein Element mehrfach registriere,
			// sammeln sich die Listener an und werden mehrfasch ausgefuehrt, ich bekomme sei auch mit removeEventListener nicht weg.
			// Das passiert bei einfachen Functionen icht, da kann ich aber weder Paramer mitgeben, noch auf Eigenschaftem des Objektes zugreifen
			for (var ii=0; ii<L; ii++) {
				if (tempArr[ii] != this.refEl && tempArr[ii] != this.dragEl && !this.dropTargetExpObj[tempArr[ii].id]) { // das DragEl darf nicht zur dropZone gehoeren
					this.dropTargetArr.push(tempArr[ii])
					// report("add to dropTargetArr: " + tempArr[i].id + " --> this.refEl: " + this.refEl.id + "\n")
				}
			}
		}
	}
}
dragObj.prototype.showDropTargets = function() {
	report("showDropTargets for: " + this.dragEl.id)
	// report("showDropTargets length: " + this.dropTargetArr.length)
	for (var i=0;i<this.dropTargetArr.length;i++) {
		report("showDropTargets: " + this.dropTargetArr[i].id)
	}
}

dragObj.prototype.startdrag = function(e,x,startmode,cX,cY) {
	if (this.inactive) return
	// report("drag: " + this)
	// report(eventInfo(e))
	// e = (e) ? e : event;
	// report(this.docRef.contentWindow)
	// report("this.call_startdrag: " + this.call_startdrag);
	e = (e) ? e : (window.event || this.docRef.contentWindow.event); // Explorer!
	el = (e.target) ? e.target : e.srcElement;
	
	// Erweitert: 02.02.09 contains(), damit das controlEl nicht durch Childnodes abgeschirmt wird.
	
	// if (window.activeSingleDragEl) report("window.activeSingleDragEl.id: " + window.activeSingleDragEl.id + " el.id: " + el.id)
	if (el.id.indexOf('resizefame')!=-1 || this.controlEl == el || startmode=='start' || (this.controlEl.contains && this.controlEl.contains(el))) {
		// nodrag?
		if (findParentWidthClassName(el,'nodrag')) {letEvent = 1; return;}
		this.activated = 1
		if (!window.activeSingleDrag) window.activeSingleDrag = this;
		if (window.activeSingleDrag != this) {
			this.activated = null;
			return;
		}
		// report(el.className)
		/*
		report("window.activeSingleDrag: "+ window.activeSingleDrag 	+ " " + window.activeSingleDrag.dragEl.id)
		report("this.controlEl: "		+ this.controlEl 	+ " " + this.controlEl.id)
		report("this.dragEl: "			+ this.dragEl 		+ " " + this.dragEl.id)
		report("this.refEl: "			+ this.refEl 		+ " " + this.refEl.id)
		*/
		// report("controlEl:" + this.controlEl.id + " dragEl:" + this.dragEl.id)
		// report("startdrag")
		// report("this.dragEl: " + this.dragEl.id)
		// report("this.inactive: " + this.inactive)
		
		
		this.getDropTargets() // Droptarget erfassen!
		this.getDummy()
		
		// report(this.controlEl.id + " startmode: " + startmode + "\n")
		var X = e.clientX
		var Y = e.clientY
		if (cX) X = cX
		if (cY) Y = cY
		// if (this.controlEl.style.display=='none') this.controlEl.style.display = 'block' // jetzt erst sichtbar machen!
		// report("clientX " 		+ e.clientX + "\n" + "clientY " 		+ e.clientY )
		// report("controlEl:" + this.controlEl.id + " " + " dragEl:" + this.dragEl.id + " el:" + el.id)
		if (this.call_startdrag) {
			// alert(typeof(this.call_drag))
			if 		(typeof(this.call_startdrag)=='function') 	this.call_startdrag()
			else if (window[this.call_startdrag]) 				window[this.call_startdrag]() // au
		}
		
		if (this.sq) report(el.id + "was activated<br>")
		// Berechnung des Offsests 
		// (Mouse-Clickpunkt zur linken oberen Kante des Elements)
		// ... kann schwierig werden, wenn kein Ghost oder Dummy bewegt wird, sondern das Original-Element gedraggt werden soll.
		// Je nach Bezugssystem des zu draggenden Objectes muss der Offset zum MouseClick anders berechnet werden.
		// Ist der ParentNode nicht "position: absolute bzw. relative", dann ist das drag-Element im Koordinatensystem des naechsten Parents mit Position
		// absLeft, absTop liefern den Abstand zum 
		// der Offset des Clicks muss in Bezug auf sich selbst berechnent werden, also die linke obere Kante
		// ist der ParenNode relativ oder absolut, dann ist der Offset in Bezug auf den Parent zu berechnen
		// report("this.dragEl.offsetParent: " + this.dragEl.offsetParent.nodeName)
		// report("this.dragEl.style.position: " + this.dragEl.style.position) 
		// report("this.dragEl.parentNode.style.position: " + this.dragEl.parentNode.style.position) 
		// report("absLeft	: " + parseInt(absLeft(this.dragEl)))
		// report("absTop	: " + parseInt(absTop(this.dragEl)))
		// Mouseclick - BezugsRahmen (parent mit position) = Distanz im relativen Raum
		//
		var sqV = 0
		this.OffsetLeft 	= this.dragEl.offsetLeft
		this.OffsetTop 	 	= this.dragEl.offsetTop 
		this.diffX 			= X - this.OffsetLeft - parseInt(absLeft(this.dragEl.offsetParent)) // Das ist deui Disatnz von Mouseclick zur linken oberen Kante des Elements
		this.diffY  		= Y - this.OffsetTop  - parseInt(absTop(this.dragEl.offsetParent)) 
		sLeft = parseInt(this.dragEl.style.left)
		sTop  = parseInt(this.dragEl.style.top) 
		if (!sLeft) sLeft = 0
		if (!sTop) sTop = 0
		this.dragdistLeft 	= parseInt(absLeft(this.dragEl.offsetParent)) + this.OffsetLeft - sLeft + this.diffX 
		this.dragdistTop  	= parseInt(absTop(this.dragEl.offsetParent))  + this.OffsetTop  - sTop  + this.diffY 
		this.posH  = e.clientX - this.dragdistLeft
		this.posV  = e.clientY - this.dragdistTop
		
		
		// report("this.posH: " + this.posH)
		// report("this.posV: " + this.posV)
		/*
		if (sqV) {
			report("Mouse X	: " + X)
			report("Mouse Y	: " + Y)
			report("absLeft offsetParent: " + absLeft(this.dragEl.offsetParent)) 
			report("absTop offsetParent: "  + absTop(this.dragEl.offsetParent)) 
			report("OffsetLeft	: " + this.dragEl.offsetLeft)
			report("OffsetTop	: " + this.dragEl.offsetTop)
			report("sLeft: " + sLeft)
			report("sTop: "  + sTop)
			report("dragdistLeft: " + this.dragdistLeft)
			report("dragdistTop: "  + this.dragdistTop)
			report("diffX: " + this.diffX)
			report("diffY: " + this.diffY)
			report("this.posH: " + this.posH)
			report("this.posV: " + this.posV)
		}
		*/
		// Iframe?
		if (this.docRef) {
			// report("refdoc")
			this.iframeX = e.clientX 				// X,Y des click in den Koordinaten des Iframe		
			this.iframeY = e.clientY
			// this.iframeLeft = this.docRef.offsetLeft // Distanz vom Click im Iframe bis linke obere Ecke des dragEl (das Element, das den iframe enthaelt)
			// this.iframeTop  = this.docRef.offsetLeft
			
			// Hier lag der Fehler! ich muss die Differenz von Iframe zu dragEl ermitteln! (nicht zum o-Punkt des Fenserts)
			// Wenn ich nur mit "offsetLeft" rechne, ist das 0/0, wenn zwischen dragEl und iframe noch eine Tabelle liegt (z. B. fuer die Schatten)
			// Wenn ich nur "absTop(this.docRef)" rechne, dann ist das die Distanz zur linken oberen Browserecke, man merkt den Rechenfehler erst, wenn man aus dem iframe rausrutsch beim Draggen,
			// dann verspringt es... gleich m mehrere hunder Pixel
			this.iframeLeft = absLeft(this.docRef) - absLeft(this.dragEl) // Distanz vom Click im Iframe bis linke obere Ecke des dragEl (das Element, das den iframe enthaelt)
			this.iframeTop  = absTop(this.docRef)  - absTop(this.dragEl)
			//report("offset: " + this.docRef.offsetLeft + " " + this.docRef.offsetTop)
			//report("abs: " + absLeft(this.docRef) + " " + absTop(this.docRef))
		}
		/*
		alert(	"startdrag " 	+ "\n" + 
				"clientX " 		+ e.clientX + "\n" + 
				"clientY " 		+ e.clientY + "\n" + 
				"X " 			+ X + "\n" + 
				"Y " 			+ Y + "\n" + 
				"OffsetLeft " 	+ this.OffsetLeft + "\n" + 
				"OffsetTop " 	+ this.OffsetTop + "\n" + 
				"dragdistLeft " + this.dragdistLeft + "\n" + 
				"dragdistTop "  + this.dragdistTop
		)
		*/
		//if (this.stopEvents) {
		// report("el.id: " + el.id + " this.dragEl.id: "  + this.dragEl.id + "letEvent: " + letEvent)
		//if (!letEvent) {
			//report('stopEvent')
			if (!document.all) 	{if (e.preventDefault) 	e.preventDefault()} // wichtig fuer Moz, nicht den Griff anklicken!
			else 				{if (e.cancelBubble) 	e.cancelBubble = true; e.returnValue = false}
		//}
		// stopEvent(e)
		//}
		window.dragActive = 1; // globale, die einen gerade laufenden Dragvorgang anzeigt
	}
}


dragObj.prototype.drag = function(e,el,P) {
	if (!this.activated) return
	if (this.inactive) 	 return
	// e = (e) ? e : event;
	e = (e) ? e : (window.event || this.docRef.contentWindow.event); // Explorer!
	// report("controlEl:" + this.controlEl.id + " " + " dragEl:" + this.dragEl.id + " el:" + el.id+"\n")
	// report(this.activated)
	
	if (this.dragEl && this.activated) {
		var iframeDiffX = 0
		var iframeDiffY = 0
		// report(this.dragEl.className)
		// report(sO(e))
		// if (P && P.doc) 	report("iframe")
		// else 				report("doc")
		//______________________________________________________________________________________ I F R A M E
		// draggen von iframes
		if (this.docRef) {
			// report("doc")
			var dragElLeft = absLeft(this.dragEl)
			var dragElTop  = absTop(this.dragEl)
			if (P && P.doc) { // dann kommt der event vom Iframe
				// report("iframe")
				this.posH = dragElLeft + e.clientX - this.iframeX
				this.posV = dragElTop  + e.clientY - this.iframeY
			} else { // dann kommt der event vom Doc
				//report("doc")
				this.posH  = e.clientX  - this.iframeX - this.iframeLeft 
				this.posV  = e.clientY  - this.iframeY - this.iframeTop
			}
		//______________________________________________________________________________________ D O C U M E N T
		// draggen von Elementen des documents,
		} else {
			this.posH  = e.clientX - this.dragdistLeft
			this.posV  = e.clientY - this.dragdistTop
		}
		//report("this.posH: " + this.posH)
		//report("this.posV: " + this.posV)	
		
		
		
		/*
		// deactiviert am 14.03.09
		if (this.calcRelPosition) {
			this.posH = this.posH - this.parentLeft 		// relative Positionierung
			this.posV = this.posV - this.parentTop 
			// report("parent ist relativ")
		}
		*/
		// report("this.posH " + this.posH)
		// report("this.maxLeft " + this.maxLeft.nodeName)
		
		
		
		
		// G R I D S
		// an einem Raster einrasten
		
		
		// G U I D E S
		// An Hilfslinien einrasten
		if (this.useGuides && (this.guidesObj || window.globalGuidesObj)) {
			// report("guidesObj")
			// Es werden alle Linien, horizontal + vertical ducrhgearbeitet. Wenn dei Differenz im SnapDist-Bereich liegt,
			// wird this.posH/posV auf die Position der Linen gesetzt.
			// report("useGuides")
			// guidesObj: {horizontal: {start:0, positions:[]}, vertical:{start:0, positions:[]}}
			if (!this.guidesObj) 	var gObj = globalGuidesObj
			else  					var gObj = this.guidesObj
			var ghL = gObj.horizontal.positions.length
			var gvL = gObj.vertical.positions.length
			var ghS = gObj.horizontal.start
			var gvS = gObj.vertical.start
			// report("ghL: " + ghL)
			// report("gvL: " + gvL)
			// report("ghS: " + ghS)
			// report("gvS: " + gvS)
			// report("guidesSnapDist: " + this.guidesSnapDist)
			// report("output gObj: " + obj2Str(gObj))	
			for (var i=0;i<ghL;i++) {  // horizontal
				var gh = gObj.horizontal.positions[i]
				var dif = (gh+ghS) - this.posH
				// report("gh: " + gh + ", posH: " + this.posH +  ", guidesSnapDist: " + this.guidesSnapDist + ", dif: " + dif)
				// report("Math.abs(dif): " + Math.abs(dif))
				if (Math.abs(dif) <= this.guidesSnapDist) {
					this.posH = gh + ghS;  
					// report("gh: " + gh + "this.posH: " + this.posH +  "dif: " + dif)
				}
			}
			
			for (var i=0;i<gvL;i++) {  // vertical
				var gv = gObj.vertical.positions[i]
				var dif = (gv+gvS) - this.posV
				// report("gv: " + gv + ", posV: " + this.posV +  ", guidesSnapDist: " + this.guidesSnapDist + ", dif: " + dif)
				if (Math.abs(dif)  <= this.guidesSnapDist) {
					this.posV = gv + gvS; 
					// report("gh: " + gh + "this.posH: " + this.posH +  "dif: " + dif)
				}	
			}
		}
		//report("this.posH: " + this.posH)
		
		
		// S T E P S
		// in bestimmten Schritten springen, Bezugspunkt ist die linke obere Ecke das zu Draggenden Objects selbst
		// oder ein globales Raster
		// stepsObj:  {horizontal: 10, vertical:20}
		// also: top100, step = 5 -> 100, 1005, 110, 115 etc
		this.selfRef = 0
		if (this.useSteps && (this.stepsObj || window.globalStepsObj)) {
			if (!this.stepsObj) 	var stObj = window.globalStepsObj			
			else  					var stObj = this.stepsObj
			// report(obj2Str(stObj))
			if (!this.selfRef) { // globale Abstaende: multiplizeren und dividieren als Integer
				if (stObj.horizontal) this.posH = (parseInt(this.posH / stObj.horizontal)) * stObj.horizontal
				if (stObj.vertical)   this.posV = (parseInt(this.posV / stObj.vertical))   * stObj.vertical
			} else {
				if (stObj.horizontal) this.posH = (parseInt(this.posH / stObj.horizontal)) * stObj.horizontal
				if (stObj.vertical)   this.posV = (parseInt(this.posV / stObj.vertical))   * stObj.vertical
			}
		}
		
		
		// M I N,  M A X
		// Als Constrain koenne Werte oder Elemente dienen
		if (this.maxLeft) {
			if (this.maxLeft.nodeName) 	_maxLeft = absLeft(this.maxLeft)
			else  						_maxLeft = this.maxLeft
			if (this.posH < _maxLeft) this.posH = _maxLeft
		}
		if (this.maxRight) {
			if (this.maxRight.nodeName) _maxRight = absLeft(this.maxLeft) + this.maxRight.offsetWidth - this.dragEl.offsetWidth
			else  						_maxRight = this.maxLeft
			if (this.posH > _maxRight) this.posH = _maxRight
		}
		if (this.maxTop) {
			if (this.maxTop.nodeName) 	_maxTop = absTop(this.maxTop)
			else  						_maxTop = this.maxTop
			if (this.posV < _maxTop) this.posV = _maxTop
		}
		if (this.maxBottom) {
			if (this.maxBottom.nodeName) _maxBottom = absTop(this.maxBottom) + this.maxBottom.offsetHeight - this.dragEl.offsetHeight
			else  						_maxBottom = this.maxBottom
			if (this.posV > _maxBottom) this.posV = _maxBottom
		}
		if (this.sq) report(" posH " + this.posH)
		
		
		
		
		// C O N S T R A I N S + Zuweisen der Werte
		if (!this.constrainV) this.dragEl.style.left = this.posH + 'px'
		if (!this.constrainH) this.dragEl.style.top  = this.posV + 'px'
		
		/*
		report("e.clientX/Y: " + e.clientX + " " + e.clientY  + " this.dragdistLeft/Top: " + this.dragdistLeft + " " + this.dragdistTop +  " this.posH/V: " + this.posH + " " + this.posV 
		+ " parentEl.offsetLeft/Top: " + this.parentEl.offsetLeft	 + ' ' +this.parentEl.offsetTop 
		+ " this.dragEl.style.left/top: " + this.dragEl.style.left +" " + this.dragEl.style.top)
		*/
		//report(absTop(this.dragEl))
		//report(this.dragEl.offsetTop)
		//report(this.dragEl.id)
		//report(this.dragEl.parentNode.id)
		//report(absTop(this.dragEl.parentNode))
		// report("dragEl style.position: " +  this.dragEl.style.position)
		
		if (this.call_drag) {
			// report(typeof(this.call_drag))
			// report(this.call_drag)
			if 		(typeof(this.call_drag)=='function') 	this.call_drag()
			else if (window[this.call_drag]) 				window[this.call_drag]() // au
		}
		
		// events
		if (!document.all) 	{e.preventDefault()} // wichtig fuer Moz, nicht den Griff anklicken!
		else 				{e.cancelBubble = true; e.returnValue = false}
		
		// report(this.ident)
		// DropZone ueberwachen
		this.dropTargetActive = 0
		// report(this.dropTargetMouseOverFunction)
		// Das Dragging soll erst ab einer bestimmten Verziegerumng beginnen...
		// report(sO(this.dropTargetArr))
		if (this.dropTargetArr) {
			this.dropTargetPars = {dropTargets:this.dropTargetArr}
			L = this.dropTargetArr.length
			// Test: erstmal alles ausschalten
			// report(this.dropTargetMouseOverFunction)
			//if (this.dropTargetMouseOutFunction) {
				// report(this.dropTargetMouseOutFunction)
				// report(sO(this.dropTargetPars))
				//if (window[this.dropTargetMouseOverFunction]) 	window[this.dropTargetMouseOutFunction](this.dropTargetPars)
				//else 											this.dropTargetMouseOutFunction(this.dropTargetPars)
			//}
			for (i=0; i<L; i++) {	
				var dEl 	= this.dropTargetArr[i]
				var left 	= absLeft(dEl)
				var top  	= absTop(dEl)
				var right 	= left + dEl.offsetWidth
				var bottom 	= top  + dEl.offsetHeight
				// report(this.refEl.className+"\n")
				// report("X " + e.clientX + " Y " + e.clientX + " left: " + left + " top: " + top + " right: "+ right + " bottom: " + bottom + "\n")
				// report("dEl.id: " + dEl.id)
				if (e.clientX > left && e.clientX < right && e.clientY > top && e.clientY < bottom) {
					this.dropTargetPars = {el:dEl, refEl: this.refEl, mouseX:e.clientX, mouseY:e.clientY, left:left,top:top, right:right, bottom:bottom, dropPositionMode: this.dropTargetPositionMode, dropTargets:this.dropTargetArr, dropTargetClass:this.dropTargetClass}
					// report("---> im in\n")
					// report("X " + e.clientX + " Y " + e.clientX + " left: " + left + " top: " + top + " right: "+ right + " bottom: " + bottom + "\n")
					// dEl.style.border = '5px solid blue'
					// bekommt die pos (left, top. right, bottom...) in this.dropTargetPars zurueckgegeben
					this.dropTargetActive = 1
					// report("this.dropTargetPars: " + this.dropTargetPars)
					if (this.dropTargetMouseOverFunction) {
						if (window[this.dropTargetMouseOverFunction]) 	window[this.dropTargetMouseOverFunction](this.dropTargetPars)
						else 											this.dropTargetMouseOverFunction(this.dropTargetPars)
					}
				} 
			} // end for
			//report("dropTargetActive: " + this.dropTargetActive)
			if (this.dropTargetMouseOutFunction) {
				if (!this.dropTargetActive) {
					// kein Droptarget akctiv? dann Mouseout feuern
					if (window[this.dropTargetMouseOutFunction]) 	window[this.dropTargetMouseOutFunction](this.dropTargetPars)
					else 											this.dropTargetMouseOutFunction(this.dropTargetPars)
				}
			}
		}
		// end dropZone
	}
}


dragObj.prototype.getDummy = function(e) {
	// P R E V I E W M O D E S
	// ghost | dummy
	if (!this.activated) return
	if (this.previewmode == 'dummy' && !this.dragDummy){
		var div = document.createElement("div")
		div.className		= 'drag_dummy draggable_tmp';						// report(div.style.cssText)
		div.id  			= 'dummy_'+this.refEl.id 			// darf nur 1 '_' enthalten, z.B. dummydragEl_2
		// if (this.cursor) div.style.cursor = this.cursor
		document.body.appendChild(div)
		var borderWidth = getBorderWidth(div)					// report(borderWidth)
		div.style.cssText 	= 'left:'+(absLeft(this.refEl))+'px; top:'+absTop(this.refEl) +'px; width:'+(this.refEl.offsetWidth-borderWidth*2)+'px; height:'+(this.refEl.offsetHeight-borderWidth*2)+'px; position:absolute;'
		this.dragEl 	= div
		this.dragDummy 	= div
		this.dragDummy.style.opacity 	= '1' 					
		this.dragDummy.style.filter 	= 'alpha(opacity = 100)'
		this.dragDummy.style.zIndex 	= 10000	
		
	}
	if (this.previewmode == 'ghost' && !this.dragDummy){
		// report("create ghost")
		var ghost 			= this.refEl.cloneNode(true)
		ghost.id  			 = 'ghost_'+this.refEl.id // darf nur 1 '_' enthalten, z.B. dummydragEl_2
		ghost.style.position = 'absolute'
		ghost.style.left 	 = absLeft(this.refEl) 			+ 'px' 
		ghost.style.top 	 = absTop(this.refEl) 			+ 'px' 
		ghost.style.width 	 = this.refEl.offsetWidth 		+ 'px' 
		ghost.style.height 	 = this.refEl.offsetHeigth 		+ 'px' 
		ghost.className 	= 'draggable_tmp ghost'
		// if (this.cursor) 	ghost.style.cursor = this.cursor
		if (document.all) 	ghost.style.filter = 'alpha(opacity =0);'
		else  				ghost.style.opacity = 0;
		document.body.appendChild(ghost)
		this.dragEl 	= ghost
		this.dragDummy 	= ghost
		if (document.all) 	this.dragDummy.style.filter = 'alpha(opacity ='+this.ghostopacity+');' // Volle deckung, wenn der Kapppfeil gedrueckt wurde
		else  				this.dragDummy.style.opacity = this.ghostopacity/100;
		this.dragDummy.style.zIndex 	= 10000	
	}
}	
		
		
dragObj.prototype.checkDragObjPosition = function(e) {
	if (!this.activated) 	return
	if (this.inactive) 		return
	el = (e.target) ? e.target : e.srcElement;
	var left 	= absLeft(el)
	var top  	= absTop(el)
	var right 	= left + el.offsetWidth
	var bottom 	= top + el.offsetHeight
	// report("left: " + left + " top: " + top + " right: "+ right + " bottom: " + bottom + "\n")
	if (e.clientX > left && e.clientX < right && e.clientY > top && e.clientX < bottom) {
		report("im in\n")
	}
}

dragObj.prototype.stopdrag = function(e) {
	window.activeSingleDrag = null
	// report("stopdrag activeSingleDrag")
	// report(sO(this.dropTargetPars))
	if (!this.activated) 	return
	if (this.inactive) 		return
	if (this.dragEl) {
		// report("Reset aktivated")
		this.activated = 0
		if (this.call_stopdrag) {
			// alert(typeof(this.call_drag))
			if 		(typeof(this.call_stopdrag)=='function') 	this.call_stopdrag()
			else if (window[this.call_stopdrag]) 				window[this.call_stopdrag]() // au
		}
		this.removeDummy()
		if (this.firstCursor) {
			// this.dragEl.style.cursor 	= this.firstCursor
			// this.controlEl.style.cursor = this.firstCursor
		}
		window.dragActive = 0; // globale, die einen gerade laufenden Dragvorgang anzeigt
		if (this.dropTargetActive == 1 && this.dropTargetMouseUpFunction) {
			// report("this.dropTargetActive " + this.dropTargetActive)
			// report("mouseOut: " + this.dropTargetPars)
			// report("mousup ... this dragEl:" + this.dragEl.id + " ####"  +sO(this.dropTargetExpObj,1))
			// report("####")
			if (window[this.dropTargetMouseUpFunction]) 	window[this.dropTargetMouseUpFunction](this.dropTargetPars)
			else 											this.dropTargetMouseUpFunction(this.dropTargetPars)
		}
	}
}

dragObj.prototype.removeDummy = function(e) {
	if (this.previewmode && this.dragDummy) {
		this.dragDummy.parentNode.removeChild(this.dragDummy)
		this.dragDummy = null;
	}
}

dragObj.prototype.removeListeners = function() {
	// Listener, Referenzen werden in listener-obj gespeichert zum removen  {f:..,c:...,el:...} (function, capture,element)
	// report("listeners:\n " + sO(this.listeners,1))
	this.dragEl.className.replace('draggable_tmp','')
	this.refEl.className.replace('draggable_tmp','')
	for (var l in this.listeners) {
		var listener = this.listeners[l]
		// report("listener: " + sO(listener,1))
		removeEventListeners(listener.el, listener.evt, listener.f, listener.c)			
	}
}















// ________________________________________________________________________________________________________________________________
// T R E E
function treeObj(rootID,saveMode,sq) {
	if (!window.queryStr) window.queryStr = getQueryStr()   // global
	// alert(window.queryStr)
/* I N F O 
-	SaveMode POST ist noch nicht fertigentwickelt

-	Um mehrere Bäume parallel betreiben zu koenne, muss der IDstr als globale definiert sein und von aalen Bäumen modizizeirt werden koennen.
	Das Problem ist, dass jeder einzelne Baum die Werte des anderen mitberuecksichtigen muss.
	Es muss also bei jedem Klick uf eine Link des Baumes die Url+qierystring ausgelesen werden und die entsprechenden Werte fuer  d i e s e n   Baum eingesetzt werden.
	Dabei mussen die Werte anderer Bäume erhlten bleiben.
		
	Bei Klick wird dei url des Links um ein paar query-Parameter erweitert: Die Zustandsvariablen des Baumes: IDstr + activeID
		
- 	window.treeIDstr:
		ist ein global Variable, die von allen Trees verwendet wird.
		Der window.treeIDstr wird bei jedem Klick auf eine open-Element aktualisiert

-	getTreeTargetUrl()
	wird direkt vom Link des Baumes aufgerufen
			
*/
	this.sq = sq // debug
	// this.sq = 1 // debug
	if (!rootID) alert('treeObj: Can\'t start, no rootID');
	this.rootID 		= rootID // tree_meinbaum, ist wichtig, um bei mehreren Bäumen die GET Varaiblen auseinanderhalten zu koennen
	this.startIDStr 	= '';
	this.saveMode		= saveMode
	// alert("this.saveMode " + this.saveMode)
	if (this.saveMode =='GET') {
		queryVarObj = parseQueryStr();			// querystring auslesen, um aktive ID zu erkennen
		// alert(queryVarObj.querystring + "\n" + queryVarObj[this.rootID + '_IDstr'])
		this.activeID 	= (queryVarObj[this.rootID + '_activeID'] ? queryVarObj[this.rootID + '_activeID'] : '')
		this.IDstr 	    = (queryVarObj[this.rootID + '_IDstr']    ? queryVarObj[this.rootID + '_IDstr'] : '')
		// +++ Achtung: globale Variable, um mehrere Strings von verschiedenen Trees zu speichern
		//if (!window.treeIDstr) window.treeIDstr = this.rootID + '_IDstr' + '=' + this.IDstr
		// if (!window.treeIDstr) window.treeIDstr = this.rootID + '_IDstr' + '=' + this.IDstr
		
		// alert("this.IDstr " + this.IDstr)
		//alert("queryVarObj.tree2_IDstr " + queryVarObj.tree2_IDstr)
	}
	this.parentForm = findParentElementByNodeName(document.getElementById(this.rootID),'form')
	if (this.saveMode =='POST') {
		// alert(this.parentForm.name)
		if (this.parentForm) {
			if (this.parentForm[this.rootID + '_IDstr'].value) 	  this.IDstr    = this.parentForm[this.rootID + '_IDstr'].value
			if (this.parentForm[this.rootID + '_activeID'].value) this.activeID = this.parentForm[this.rootID + '_activeID'].value;
			// if (document[this.parentForm.name][this.rootID + '_IDstr'].value) 	 this.IDstr    = document[this.parentForm.name][this.rootID + '_IDstr'].value
			//if (document[this.parentForm.name][this.rootID + '_activeID'].value) this.activeID = document[this.parentForm.name][this.rootID + '_activeID'].value;
			/*alert(	"POST "   	+ "\n" + 
					"IDstr "    + this.IDstr    + "\n" + 
					"activeID " + this.activeID + "\n")
			*/
		}
	}
	this.buildtree()
}



// this function apply the CSS style and the event
treeObj.prototype.buildtree = function() {
	this.tree = document.getElementById(this.rootID); 		// the root element
	this.lis = this.tree.getElementsByTagName('li'); 		// alle li in lis
	/*
	// alert(startIDstr)
	if (CatMode != 'folder') {
		ebene = 0
		checkforParentNodes(document.getElementById('lix'+activeID))
		if (IDstr.indexOf(startIDstr)==-1) IDstr += startIDstr // wnn es kein Ordner ist, muss die aktive Seite sichtbar werden, dann wird der IDstr um den Pfad der aktiven Seite erweitert
	}
	*/
	/*
	alert(	
			"rootID "    	  	+ this.rootID      	+ "\n" + 
			"IDstr "      		+ this.IDstr      	+ "\n" + 
			"startIDstr " 		+ this.startIDstr 	+ "\n" + 
			"activeID " 		+ this.activeID 	+ "\n"
	)
	*/
	// alert(activeID)
	// actives Elelement markieren
	// alert(this.activeID)
	if (this.activeID && document.getElementById(this.activeID)) document.getElementById(this.activeID).firstChild.className += ' activeelement'			// actives Element kennzeichnen
	this.IDstrObj = {}
	
	if (this.IDstr) {						// globale
		IDstrArr = this.IDstr.split("_")
		// alert(this.rootID + " this.IDstr " + this.IDstr)
		for(i=0;i<IDstrArr.length;i++) {
			// alert("IDstrArr[i] " + IDstrArr[i])
			if (IDstrArr[i]) {
				this.IDstrObj[IDstrArr[i]] = "open"; // es reicht, wenn die objecteigenschaften vorhanden sind
				// alert(IDstrObj[IDstrArr[i]])
			}
		}
	}
	for (var i=0; i<this.lis.length; i++) {
		ebene = 0
		this.checkforParentNodes(this.lis.item(i),0) 														// ebene ermitteln
		li_ebene = ebene/2; 																	// alert(ebene)
		if (this.lis[i].getElementsByTagName('ul').length > 0) { 
			registerEventListenersObj(this.lis[i], "mousedown", this, false, 'show');
			this.lis[i].getElementsByTagName('ul')[0].style.display = "none"; 
			// alert(this.lis[i].id)
			if (this.IDstrObj[this.lis[i].id] == "open") {													// ist es ein zu oeffnenedes li?						
				//alert("oeffne: " + IDstrObj["li"+i] + " " + lis[i].id)		
				this.lis[i].getElementsByTagName('ul')[0].style.display = "block"; 					// sichtbar machen
				this.lis[i].firstChild.style.backgroundImage = 'url(/cms/images/tree_icon_dirminus.gif)'
			}
		}
	}
	// adjustEditFormAction(this.rootID,this.IDstr)
}



treeObj.prototype.getOpenElements = function() {
	var lis     = this.tree.getElementsByTagName('li'); // all the li
	this.IDstr  = '';
	for (var i=0; i<lis.length; i++) {
		if (lis[i].getElementsByTagName('ul').length > 0) { 											//alert("lis[i].getElementsByTagName('ul')[0].style.display " + lis[i].getElementsByTagName('ul')[0].style.display)    
			if (lis[i].getElementsByTagName('ul')[0].style.display != "none") {
				// this.IDstr += ("_"+lis[i].id)
				this.IDstr += ("_"+lis[i].id)
			}
		}
	}
	// alert("getOpenElements " +this.IDstr)
	if (this.sq) {
	alert(			"this.IDstr " + this.IDstr  + "\n" + 
					"this.rootID " + this.rootID)
	}
	if (this.sq) alert("vorher " + "\n" + window.queryStr)
	// window.treeIDstr = modifyQueryString(window.treeIDstr,0,this.rootID + '_IDstr', this.IDstr)
	window.queryStr = modifyQueryString(window.queryStr,0,this.rootID + '_IDstr', this.IDstr)
	if (this.sq) alert(	"nachher" + "\n" + window.queryStr)
	// alert(this.parentForm.name)
	if (this.parentForm) {
		if (this.IDstr)    this.parentForm[this.rootID + '_IDstr'].value    = this.IDstr
		if (this.activeID) this.parentForm[this.rootID + '_activeID'].value = this.activeID;
		// adjustEditFormAction(this.rootID,this.IDstr)
	}
}



// show the first ul element found under this element
treeObj.prototype.show = function(e,handlerOwnerElement) {
	e = (e) ? e : event;
	// handlerOwnerElement ist das Element,m das den lsitener traegt.
	// Notloesung, da IE die Eigenschft "e.currentTarget "nicht unterstuetzt
	if (document.all) 	el = e.srcElement
	else  				el = e.target								//alert(handlerOwnerElement.nodeName)
	if (document.all) 	actuelLi = handlerOwnerElement
	else 				actuelLi = e.currentTarget
	if (hasClassName(el,"switch")) {
		actuelDisplay = actuelLi.getElementsByTagName('ul')[0].style.display
		if (actuelDisplay=="block") 	{
			actuelLi.getElementsByTagName('ul')[0].style.display = 'none';
			el.style.backgroundImage = 'url(/cms/images/tree_icon_dirplus.gif)'
		}
		if (actuelDisplay != "block") {
			actuelLi.getElementsByTagName('ul')[0].style.display = 'block';
			el.style.backgroundImage = 'url(/cms/images/tree_icon_dirminus.gif)'
		}
		if(!document.all) 	e.stopPropagation()
		else 				window.event.cancelBubble=true;
	}
	this.getOpenElements()
}

treeObj.prototype.checkforParentNodes = function(el,rootID) {
	if (el.parentNode.id == rootID) return;
	ebene++;
	if (el.id.indexOf("li") != -1) {this.startIDstr += "_"+el.id} 				// ermittelt auch noch die uebergeordneten li, um den ganzen Baum auszuklappen
	this.checkforParentNodes(el.parentNode)
}


function getTreeTargetUrl(activeID, rootID, url) {
	// Diese Funktion wird beim Klick auf den Link eines li Elements aufgrufen
	obj = window[rootID + '_tree'];	// +++ Achtung: hier mit obj arbeiten, statt this!
	// alert("obj.saveMode " + obj.saveMode)
	/*
	alert("getTreeTargetUrl obj.saveMode: " + obj.saveMode + "\n" + 
			"url: "					+ url + "\n" + 
			"activeID: "			+ activeID + "\n" + 
			"rootID: " 				+ rootID + "\n" + 
			"window.queryStr : " 	+ window.queryStr  + "\n"
	)
	*/
	// report(window.queryStr);
	newUrl = modifyQueryString('', 1, '', window.queryStr + ('&'+rootID + '_activeID='+activeID))
	if (!newUrl) newUrl = '?'													// Problem: wenn newUrl = '', der Baum also eingeklappt ist und keine anderen GET unterwegs sind, dann
	// Submit
	if (obj.saveMode == 'POST') {
		//alert("submit via POST")
		if (obj.parentForm) {
			if (activeID) obj.parentForm[obj.rootID + '_activeID'].value = activeID;
			obj.parentForm.submit();
		}
	} else {	
		// alert("via GET")			
		// alert("newUrl " + newUrl)
		document.location.href = newUrl
	}
}







// ________________________________________________________________________________________________________________________________
// H E L P E R    F U N C T I O N S
// hide the ul elements under the element identified by id
function hideUlUnder(id) {   
    document.getElementById(id).getElementsByTagName('ul')[0].style.display = 'none';
}

function hideAllOthersUls(currentLi) {													// hide all ul on the same level of  this list item
    var ul = currentLi.parentNode; 														// alert(lis.childNodes.length);
    for (var i=0; i<ul.childNodes.length; i++) {
        if (ul.childNodes[i].id && ul.childNodes[i].id != currentLi.id) {
            hideUlUnderLi(ul.childNodes[i] );
        }
    }
}
function adjustEditFormAction(rootID, IDstr) {
	// alert("adjustEditFormAction " + rootID + " " + IDstr)
	parentForm = findParentElementByNodeName(document.getElementById(rootID),'form')
	// alert("parentForm.name " + parentForm.name)
	if (parentForm) {
		// changeQueryPars: es werden Variablenname + Wert uebergebn und in die Url eingesetzt
		parentForm.action = modifyQueryString(parentForm.action, 0,rootID +'_IDstr', IDstr)		//
		// alert("parentForm.action " + parentForm.action)
	}
}

function hideUlUnderLi(li) {																	// hide all the ul wich are in the li element
    var uls = li.getElementsByTagName('ul');
    for (var i=0; i<uls.length; i++) {
        uls.item(i).style.display = 'none';
    }
} 














// ________________________________________________________________________________________________________________________________
// P O P U P L A Y E R 
// +popupLayerObj
function popupLayerObj(path,w,h,info,P) {
	var sq = 0;
	if (window.location.search.indexOf('sq_popup') != -1) sq = 1
	// alert("popupLayerObj")
	// alert(info)
	// alert(path)
	// alert(h)
	/* I N F O 
	Object, das mit position fixed arbeitet
	Das funktioniert im IE 7 nur, wenn ein Doctype vorhanden ist
	die alte Fassung arbeitete mit absolut, scrollTop und Javascript Positionierung, das geht in karcher2008 nicht mehr, wg. CSS Javascript Konflikten
	in Moz werden keine korrekten Werte mehr ausgegeben füuer scrohllHeight, scrollTop
	
	opener:		popupLayer('$url', 717, 360,'Infor string', {scrolling:'auto'})
				popupLayer( 'http://www.karcher.de/micrositeSound/index.php?version=followme', 796,560,'microsite follow me');
	
	Es wird jetzt doch mit position:fixed gearbeitet. Fuer IE7 wird mit Javasript nachgeholfen, da es Probleme mit expressions gab
	
	Height:
	Die "h", angegeben Hoehe ist der Innenraum. Das gesamte Popup mit Kopfbalken ist dann 21 px hoeher!
	Dei Hoehe des Kopfbalkens muss vorher bekannt sein -> "headBarheight"
	
	Positionierung
	-	h, w gegeben: Das Popup wird zentriert, allerdings darf eine Mindestabstand zur oberen Fensterkante nicht unterschritten werden
	-	h nicht gegeben: flexible Hoehe, Abstände zur oberen und unteren Fensterkante richten sich nach einem Mindestabstand -> "minVerticalDistToWindow"
	-	mmaxHeight: wenn keine h definiert, dehnt sich das Fesneter aus, bis eine maxHeight erreicht ist.
	
	Known Problems:
	Moz:
	-	In karcher_2008 kann document.body.scrollTop, scrollHeihgt nicht mehr ausgelesen werden,
		das liegt an bestimmten Floats #spalte 2, und body {heigt:100%}
		macht den umbau Auf Position Fixed noetig (wird von IE 6 nicht unterstuetzt!)
	IE
	-	sobald man mit eExpression arbeitet, gibt es Fehler mit den registrierten Eventlisteners, es wird z:B. das Body Element nicht mehr gefunden
	-	document.body.scrollTop, document.documentElement.scrollTop: evtl ueber verscheidne Objekte nachfragen
	-	Wenn kein Doctype definiert ist, geht position:fixed nicht
		<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
		dann werden bei position:fixed auch %-Werte fuer left akzeptiert
	
	*/
	// alert('w ' + w + ' h '+ h);
	// alert("window.is_editmode " + window.is_editmode);
	
	/* report(		"path: " 		+ path 				+ "\n" + 
					"w: " 			+ w 				+ "\n" + 
					"h: " 			+ h 				+ "\n" + 
					"info: " 		+ info 				+ "\n" + 
					"popupImgPos: " + popupImgPos 		+ "\n"
				)
	*/
	// alert(path)
	
	
	// alert(document.location.href)
	//if (this.useParent) 	this.doc = parent.document.body // Parent bei Iframes verwenden
	//else 					this.doc = document.body
	this.useParent = 1;
	this.doc 	= document // Parent bei Iframes verwenden
	this.body 	= document.body
	// alert(P.doc)
	if (document.location.href.indexOf('ceSingle') != -1 || (P && P.doc == 'parent')) {
		// alert("this.useParent: " + this.useParent)
		this.doc  = parent.document
		this.body = parent.document.body
	}
	// report(this.doc)
	// pos: die aktiuelle Bildposition in eine range
	// rangenum: die Anzahl der Bilder in der Range
	
	// Gestaffelte Popuplayer
	// Das Problem: verschiedene windows (z. B. die Kaercher Hauptseite und der iframe im 1. Popuplayer) oeffnen ein Popuplayer im Kaercher Hauptfenster
	// d.h. sie appenden an dasselbe document
	// deshalb den richtigen Stack finden und verwenden
	window.popupLayerStack = new Array()
	if (parent) {
		parent.window.popupLayerStack.push(this)
		this.nr = parent.window.popupLayerStack.length - 1
	} else {
		window.popupLayerStack.push(this)
		this.nr = window.popupLayerStack.length - 1
	}
	
	this.nr = popupLayerStack.length - 1
	// report(window.popupLayerStack.length)
	window.activePopup = this // ... und global zur Verfuegung stellen
	// this.nr = parseInt(Math.random()*100000) // Random Nr, weil der Popuplayer von 2 verscheidnene Windows geoeffnet wird, aber demselben Window appended wird
	// das fuert dazum, dass beide Fenster incrmeniteren
	// report("this nr: " + this.nr)
	
	// if (this.useParent) this.nr += 100 // incremntieren
	var agt = navigator.userAgent.toLowerCase();
	var minVerticalDistToWindow = 30 // Mindestabstand zur oberen und unteren Fensterkannte bei flexibler Hoehe
	var headBarheight 			= 21 // Hoehe des Kopfbalkens, muss bei Veraenderungen angepasst werden
	
	if (!h) this.flexHeight = 1
	w = parseInt(w)
	h = parseInt(h)
	if (!w) w = 796
	if (!h) h = 600
	
	if (window.is_editmode) return;
	if (!info) info = 'K&Auml;RCHER'
	// alert(info)
	if (!window.popupLayer_text_close) this.text_close 	= 'close popup'
	else 							   this.text_close 	= window.popupLayer_text_close
	this.text_close = ''
	if (!P) P = {}
	P.popupImgPos 			?   this.popupImgPos 	= P.popupImgPos 	:		this.popupImgPos 	= 0
	P.popupImgArr 			?   this.popupImgArr 	= P.popupImgArr 	:		this.popupImgArr 	= ''
	P.text_pdf 				?   this.text_pdf 		= P.text_pdf 		:		this.text_pdf 		= ''
	P.text_print 			?   this.text_print 	= P.text_print 		:		this.text_print 	= ''
	P.scrolling 			?   this.scrolling 		= P.scrolling 		:		this.scrolling 		= 'no'
	P.maxHeight 			?   this.maxHeight 		= P.maxHeight 		:		this.maxHeight 		= h
	P.onclose 				?   this.onclose 		= P.onclose 		:		this.onclose 		= ''
	P.onminimize 			?   this.onminimize 	= P.onminimize 		:		this.onminimize 	= ''
	P.flashVars 			?   this.flashVars 		= P.flashVars 		:		this.flashVars 		= ''
	P.style 				?   this.style 			= P.style 			:		this.style 			= ''
	P.function_print		? 	this.function_print = P.function_print	:		this.function_print	= 'window.print();'
	P.scrollbarclass		? 	this.scrollbarclass = P.scrollbarclass	:		this.scrollbarclass	= ''
	P.function_pdf			? 	this.function_pdf 	= P.function_pdf	:		this.function_pdf	= ''	// {nr} wird automatisch gegen die aktuelle nr ersetzt
	P.scaleContent			? 	this.scaleContent 	= P.scaleContent	:		this.scaleContent	= 0		// Bilder werden auf Fenstergroesse scaliert, default 0
	P.ajax					? 	this.ajax 			= P.ajax			:		this.ajax			= 0	
	P.flashInGallery		? 	this.flashInGallery = P.flashInGallery	:		this.flashInGallery	= ''	
	this.path = path
	if (P.closeEffect) 		this.closeEffect 	= P.closeEffect
	if (P.minimizeEffect)	this.minimizeEffect = P.minimizeEffect
	if (this.minimizeEffect) this.onminimize = 1
	// report(P.function_pdf)
	// this.onminimize = 1;
	// alert(this.function_print)
	// dynamische Variablen vergeben.
	if (P.xtraData) {
		for (var dynvar in P.xtraData) {
			evalstr = 'this.'+dynvar + ' = \''+addslashes(P.xtraData[dynvar])+'\'' 	// report("evalstr: " +evalstr)
			// report(evalstr);
			eval(evalstr)												// alert("this.test1 "+this.test1)
		}
	}
	if (this.popupImgArr) this.popupImgNum = this.popupImgArr.length
	if (this.maxHeight && h > this.maxHeight) h = this.maxHeight		// an Mkindestgroesse anpassen
	
	
	var zIndex  			= 1000
	var layerTrans			= 27
	var layerTop 			= 0;
	var popupLayerTransImg	= 'popupLayerTrans.png'
	var wH = getWindowHeight(parent.window)
	var wW = getWindowWidth(parent.window)
	
	this.layerContentTop 	= parseInt((wH-(h+headBarheight))/2)
	this.layerContentLeft 	= parseInt((wW-w)/2 -10)
	if (this.flexHeight) 	{
		h = wH - minVerticalDistToWindow *2 - headBarheight
		this.layerContentTop = minVerticalDistToWindow
	}
	if (this.top) this.layerContentTop = this.top;
	// report("wH: " + wH + " layerContentTop: " + this.layerContentTop)
	
	//Mindestabstand von oben
	if (this.layerContentTop < 10) this.layerContentTop = 10; // Mindestabstand von der Fensteroberkannte, es soll vermieden werden, daß der Kopfbalken verschwindet
	if (is_ie6) 			layerPosition = 'absolute';
	else 					layerPosition = 'fixed';
	
	// alert(this.layerContentLeft)
	if(sq) {
		alert(	"h: " 			+ h + "\n" + 
				"w: " 			+ w + "\n" + 
				"flexHeight: " 			+ this.flexHeight + "\n" + 
				"maxHeight: " 			+ this.maxHeight + "\n" + 
				"getWindowWidth(): " 			+ getWindowWidth() + "\n" + 
				"getWindowHeight(): " 			+ getWindowHeight() + "\n" + 
				"document.body.offsetHeight: " 	+ document.body.offsetHeight + "\n" + 
				"document.body.scrollHeight: " 	+ document.body.scrollHeight + "\n" + 
				"document.body.scrollTop: " 		+ document.body.scrollTop + "\n" + 
				"layerContentLeft: " 			+ this.layerContentLeft +"\n" + 
				"layerContentTop: " 			+ this.layerContentTop +"\n"
		)
	}
	
	
	// Der Dimmer
	this.popupLayerDimmer = this.doc.createElement('div')
	this.popupLayerDimmer.id = 'popupLayerDimmer_'+this.nr
	// alert(layerTrans)
	// Explorer bekommt CSS Transparenz, Moz/Firefox png, wegen des Firefox CSS-Transparenz-Flash-Pluginn Bugs
	//if (is_ie6) 		this.popupLayerDimmer.style.cssText 	= 'z-index:'+zIndex+'; position:'+layerPosition+'; background-color:black; left:0; top:'+layerTop+'px; width: expression(eval(document.body.clientWidth)); height:expression(eval(document.body.clientHeight)); filter: alpha(opacity = '+layerTrans+');-moz-opacity: 0.'+layerTrans+'; opacity: 0.'+layerTrans+';';
	//else  				this.popupLayerDimmer.style.cssText 	= 'z-index:'+zIndex+'; position:'+layerPosition+'; background-image:url(/cms/images/'+popupLayerTransImg+'); position:'+layerPosition+'; left:0; top:'+layerTop+'px; width:100%; height:100%;';
	//alert("document.body.clientHeight: " + document.body.clientHeight)
	//alert("document.body.scrollHeight: " + document.body.scrollHeight)
	//alert("absHeight: " + absHeight(document.body))
	// alert("wH: " + wH)
	if (is_ie6) {
		// alert(is_ie6 + "layerTrans: " + layerTrans)
		//this.popupLayerDimmer.style.cssText 	= 'z-index:'+zIndex+'; background-color:black; position:'+layerPosition+'; left:0; top:'+layerTop+'; width: expression(eval(document.body.clientWidth)); height:expression(eval(document.body.scrollHeight < getWindowHeight() ? getWindowHeight(): document.body.scrollHeight)); filter: alpha(opacity = '+layerTrans+');-moz-opacity: 0.'+layerTrans+'; opacity: 0.'+layerTrans+';';
		
		// popuplayerIE6Bg
		this.popupLayerDimmer.style.cssText = 'z-index:'+zIndex+'; position:'+layerPosition+'; left:0; top:'+layerTop+'; width: expression(eval(document.body.clientWidth)); height:expression(eval(document.body.scrollHeight < getWindowHeight() ? getWindowHeight(): document.body.scrollHeight));';
		// ok: Das Problem: In IE6 tritt inm Zusammenspiel von opacity alpha + expresseion das Speicher Problem auf: bei jedem Öffnen eines Popup-Fesnetrs erhöht sich der RAM um 40 - 50 MB
		// Loesung: ein Hintergrundbild einsetzten, mit der IE AlphaImageLoader Syntax und scale:
		// .popuplayerIE6Bg {background-image: none;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale src='/cms/templates/karcher/images/popuplayerIE6Bg.png'); }
		this.popupLayerDimmer.className = 'popuplayerIE6Bg';
		//this.popupLayerDimmer.style.cssText 	= 'z-index:'+zIndex+'; background-color:black; position:'+layerPosition+'; left:0; top:'+layerTop+'; width: 100%; height:100%; filter: alpha(opacity = 20);';
	} else {			
		this.popupLayerDimmer.style.cssText 	= 'z-index:'+zIndex+'; background-color:black; position:'+layerPosition+'; left:0; top:'+layerTop+'; width: 100%; height:100%; filter: alpha(opacity = '+layerTrans+');-moz-opacity: 0.'+layerTrans+'; opacity: 0.'+layerTrans+';';
	}
	//alert("bis hier");
	// alert(this.popupLayerDimmer.nodeName)
	// alert(window.parent.document.location.href)
	// alert(window.opener)
	// alert(parent.document.location.href)
	// if (parent.document) 	this.doc = parent.document
	// else 					this.doc = document
	
	//var popupLayerDimmer = parent.document.createElement('div')
	//popupLayerDimmer.innerHTML = 'das ist ein Test'
	this.body.appendChild(this.popupLayerDimmer); // hier IE6 Problem Speicherzuwachs 40 - 50 MB!
	
	// document.appendChild(this.popupLayerDimmer); // hier IE6 Problem Speicherzuwachs 40 - 50 MB!
	
	//alert("bis hier"); return 
	// return;
	// Layer
	this.popupLayerElement 					= this.doc.createElement('div')
	this.popupLayerElement.id 				= 'popupLayerElement_'+this.nr
	this.popupLayerElement.className 		= 'popuplayer'
	this.popupLayerElement.style.cssText 	= 'position:'+layerPosition+'; z-index:'+zIndex +'; left:0; top:0; width:100%; height:100%; border:0px solid red; ';
	this.body.appendChild(this.popupLayerElement);
	if (is_ie6) this.popupLayerElement.style.height = this.body.clientHeight + 'px'; // braucht der halt...
	
	// Frameholder
	this.frameholder 						=  this.doc.createElement('div')
	this.frameholder.id 					= 'popuplayerFrameHolder_'+this.nr
	this.popuplayerFrameId					= 'popuplayerFrame_'+this.nr
	// mit Javascript px Positionierung
	// this.frameholder.style.cssText 	 		= 'border:1px solid red; z-index:'+zIndex+'; position:'+layerPosition+'; left:'+this.layerContentLeft+'px; top:'+this.layerContentTop+'px; width:'+(w+10)+'px; height:'+(h+10)+'px;';
	// %-Position, ist schoener, geht aber nur mit Doctype
	this.frameholder.style.cssText 	 		= 'border:0px solid red; z-index:'+zIndex+'; position:'+layerPosition+'; left:50%; margin-left:-'+(w/2)+'px; top:'+this.layerContentTop+'px; width:'+(w+10)+'px; height:'+(h+10)+'px;';
	
	
	// alert(this.frameholder.style.cssText)
	// nur der click auf den schlissenbutton und die graue Flaechs soll schliessen
	registerEventListeners(this.frameholder,'click',function(e){e.cancelBubble=true;}); // +++ Achtung, kein Obj-Listener
	
	// frame Table
	var frame 	 	=  '<table id="'+this.popuplayerFrameId+'" class="popuplayerFrame" border="0" cellpadding="0" cellspacing="0"><tr><td width="'+w+'px" height="'+h+'px"  valign="top" id="popuplayer_content_td_'+this.nr+'" class="content_td">'
		frame		+= '<div class="titlebar" style=""><div class="title">'+info+'</div>'
		// frame 		+= '<a class="cargo9" href="Javascript: appadvisorMin(\'http://www.spiegel.de\')">minimize</a>'; // nur zum testen von Minimize
								frame	+= '<div class="button_close" unselectable="on" style="-moz-user-select:none;" id="popuplayerCloser_'+this.nr+'">'+this.text_close+'&nbsp;</div>'
		if (this.onminimize) 	frame	+= '<div class="button_minimize" unselectable="on" style="-moz-user-select:none;" id="popuplayerMinimizer_'+this.nr+'">'+this.text_close+'&nbsp;</div>'
		if (this.text_pdf) 		frame	+= '<div class="button_pdf"   onclick = "'+this.function_pdf.replace('{nr}',this.nr)+'">'+this.text_pdf+'</div>'
		if (this.text_print) 	frame	+= '<div class="button_print" onclick = "'+this.function_print+'">'+this.text_print+'</div>'
		frame       += '</div>{popupcontent}</td><td width="10px" class="rt">&nbsp;</td></tr>'
		frame 		+= '<tr><td class="lb"></td><td class="rb"></td></tr></table>'
	// alert("this.function_print: " + this.function_print)
	
	
	// A J A X
 	if (this.ajax) {
		// alert("bin ajax: " + path)
		var ajaxElID = 'popupLayer_ajax_'+this.nr
		var content  = '<div id="'+ajaxElID+'">'
		this.frameholder.innerHTML = frame.replace('{popupcontent}',content)
		this.popupLayerElement.appendChild(this.frameholder);
		// Ajax update
		updateElementViaAjax(ajaxElID,path+'&ajaxElID='+ajaxElID+'&popupNr='+this.nr,'voting','1') // voting: ein Formname, 1 = showpostvars, mitschicken von Postvars
	
	
	// F L A S H
	// +++ Achtung: wenn 'flashInGallery', dann soll ein Image verwednet werden. Deas schaltet dann innerhalb der GAllery weiter von img auf swf.
	} else if (path.match(/.swf/) && !this.flashInGallery) { // geandert 27.01.08, vorher path.match(/.swf/), .swf mußte am Ende stehen
		if(sq) alert("bin Flash:" + path)
		
		// alert("hier")
		// Flash direkt einbetten
		// alert("flash")
		// wmode auf opaque? fuer firefox mac?
		// report("swf" + layerContentTop+"\n")
		// Hier wird der Flashfilm direkt eingebunden, wmode = opaque
		// this.frameholder.style.cssText = xcssText
		// this.frameholder.style.cssText = 'z-index:'+zIndex+'; position:'+layerPosition+'px; left:50%; top:'+this.layerContentTop+'px; width:'+(w+10)+'px; height:'+(h+10)+'px; margin-left:-'+w/2+'px;';
		// alert(path)
		// report("this.flashVars: " + this.flashVars)
		if (this.flashName) {var fn 	= this.flashName}
		else 				{var fn 	= 'flash_' + this.nr}
		if (this.flashVars) {var fpObj 	= '<param name="FlashVars" value="'+this.flashVars+'">'; 	var fpEmb = ' FlashVars="'+this.flashVars+'"'}
		else 				{var fpEmb 	= ''; 														var fpObj = ''}
		// alert('fpEmb: ' + fpEmb)
		flashCode  = '<object id="'+fn+'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="'+w+'" height="'+h+'" id="backgroundSound" align="">'
		flashCode += '<param name="movie"  value="'+ path +'">'
		flashCode += '<param name="quality" value="high">'
		flashCode += '<param name="bgcolor" value="#FFFFFF">' 
		flashCode += '<param name="wmode"  value="transparent">' 
		flashCode += '<param name="allowScriptAccess" value="sameDomain">'
		flashCode +=  fpObj
		flashCode += '<embed name="'+fn+'" id="'+fn+'" allowScriptAccess="sameDomain" wmode="transparent" src="'+ path +'" quality="high" bgcolor="#FFFFFF"  width="'+w+'px" height="'+h+'px" align="" type="application/x-shockwave-flash" pluginspace="http://www.macromedia.com/go/getflashplayer"'+fpEmb+'></embed>'
		flashCode += '</object>'
		this.frameholder.innerHTML = frame.replace('{popupcontent}',flashCode)
		// report(flashCode)
		// alert(this.frameholder.innerHTML)
		this.popupLayerElement.appendChild(this.frameholder);
		if (document.all) { // IE Probleme: Das ist eine Doppelkruecke: Die 1. Zeile brauche ich, damit der Flashfilm auf Scripte reagiert, 2. Zeile damit IE danach die Flashvars erkennt, die gehen wegen Zeioe 1 verloren!
			this.frameholder.innerHTML = this.frameholder.innerHTML
			document.getElementById(fn).Flashvars = this.flashVars;
		}
		// if (document.all) this.frameholder.style.display = this.frameholder.style.display
	// I M A G E S
	} else if (this.flashInGallery || path.match(/.((jpg)|(gif)|(png))$/)) {
		//report("img" + layerContentTop+"\n")
		if (sq) alert("bin Image:" +path)
		// this.scaleContent = 1
		// this.frameholder.style.cssText = cssText
		// this.frameholder.style.cssText 	= 'z-index:'+zIndex+'; position:'+layerPosition+'px; left:50%; top:'+this.layerContentTop+'px; width:'+(w+10)+'px; height:'+(h+10)+'px; margin-left:-'+w/2+'px;'
		// report('path: ' + path)
		// report('flashInGallery: ' + this.flashInGallery)
		if (path.indexOf('.swf') != -1) {var imgDispl = 'display:none;'; 	var flaDispl = ''}
		else 							{var imgDispl = ''; 				var flaDispl = 'display:none;'}
		if (!this.scaleContent) var content = '<img style="'+imgDispl+'" id="popupImage" src="'+path+'">'
		else 					var content = '<img style="'+imgDispl+'" id="popupImage" src="'+path+'" width="100%" height="100%">'
		// src fuer IE: [0], moz: [3]
		if (this.flashInGallery) {
			content += '<object id="popupImageFlash" style="'+flaDispl+'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="100%" height="100%"><param name="movie" value="'+path+'"><param name="wmode" value="transparent"><param name="quality" value="high"><embed src="'+path+'" quality="high" type="application/x-shockwave-flash" width="100%" height="100%" wmode="transparent"></embed></object>';
		}
		this.frameholder.innerHTML = frame.replace('{popupcontent}',content)
		this.popupLayerElement.appendChild(this.frameholder);
		
	// D I V,    H T M L  Element
	} else if (document.getElementById(path)) { // wenn es ein Element mit dieser ID gibt, dann nehmen
		// report("this.frameholder" + layerContentTop+"\n")
		if(sq) alert("bin html-Element:" + path)
		this.frameholder.innerHTML = frame
		this.popupLayerElement.appendChild(this.frameholder);
		this.frameholder.innerHTML = frame.replace('{popupcontent}','')
		this.popupLayerElement.appendChild(this.frameholder);
		document.getElementById('popuplayer_content_td_'+this.nr).appendChild(document.getElementById(path))
		document.getElementById(path).style.display = 'block' // sichtbar machen
		// S C R O L L B A R 
		// alert("cargoScrollbarsObjArr " + window.cargoScrollbarsObjArr)
		if (window.cargoScrollbarsObjArr && window.cargoScrollbarsObjArr[path] && window.cargoScrollbarsObjArr[path].scrollbarEl) {
			window.cargoScrollbarsObjArr[path].positionScrollBar();
			window.cargoScrollbarsObjArr[path].scrollbarEl.style.zIndex = zIndex + 1;
			this.popupScrollbarRefEl = window.cargoScrollbarsObjArr[path].scrollbarEl // merken fuer close
		}
	
	// I F R A M E
	} else {
		// path = 'http://www.karcher.de';
		//path = 'http://www.karcher.de/cms/templates/karcher/mod/application_advisor/application_advisor2008.swf?versionID=206&projecttype=karcher2008&advisortype=karcher2008'
		// path = 'http://www.karcher.de/cms/templates/karcher/mod/application_advisor/application_advisor2008.htm'
		// alert("bin iframe:" +path)
		var content = '<iframe name="popuplayerIframe_'+this.nr+'" class="'+'" id="popuplayerIframe_'+this.nr+'" frameborder="0" width="100%" height="100%" scrolling="'+this.scrolling+'" src="'+path+'" style="'+this.style+'"></iframe>'; // this.scrolling
		// default print austauschen gegen print fuer Iframe
		// frame = frame.replace('window.print();','parent.frames[\'popuplayerIframe_'+this.nr+'\'].focus(); parent.frames[\'popuplayerIframe_'+this.nr+'\'].print();');
		// frame = frame.replace('window.print();','parent.frames[\'popuplayerIframe_'+this.nr+'\'].focus(); parent.frames[\'popuplayerIframe_'+this.nr+'\'].print();');
		frame = frame.replace('window.print();','parent.frames[\'popuplayerIframe_'+this.nr+'\'].focus(); parent.frames[\'popuplayerIframe_'+this.nr+'\'].window.print();');
		
		// frame = frame.replace('window.print();','document.getElementById(\'popuplayerIframe_'+this.nr+'\').contentWindow.p();');
		/* geht alles nicht, EI druckt die dahinterleigende Seite...
		// frame = frame.replace('window.print();','document.getElementById(\'popuplayerIframe_'+this.nr+'\').contentWindow.printFromInside();');
		// frame = frame.replace('window.print();','parent.adam.contentWindow.print();');
		// frame = frame.replace('window.print();','document.getElementById(\'popuplayerIframe_'+this.nr+'\').contentWindow.p();');
		// parent.NameMeinesFrames.print()
		// alert(frame)
		*/
		// frame = frame.replace('window.print();','document.getElementById(\'popuplayerIframe_'+this.nr+'\').contentWindow.printFromInside();');
		this.frameholder.innerHTML = frame.replace('{popupcontent}',content);
		// Das erzeugt in Firefox eine Error mit der iframSource: Permission denied to call method Location.toString
		// allerdings nur, wenn ich auf das swf file direkt verlinke....
		this.popupLayerElement.appendChild(this.frameholder)
	}
	
	// Pfeile zum weiterschalten
	if (this.popupImgArr && this.popupImgArr.length > 1) {
		var arrowLeft 				 = document.createElement('img')
		var arrowRight 				 = document.createElement('img')
		arrowLeft.style.cssText 	 = 'z-index:500; cursor:pointer; border:0px solid red; position:absolute; left:10px; top:'+(h-30)+'px;'
		arrowRight.style.cssText 	 = 'z-index:500; cursor:pointer; border:0px solid red; position:absolute; left:'+(w-30)+'px; top:'+(h-34)+'px;'
		arrowLeft.src 				 = "/cms/templates/karcher2008/images/arrow_popuplayer_left.gif" 
		arrowRight.src 				 = "/cms/templates/karcher2008/images/arrow_popuplayer_right.gif" 
		this.frameholder.appendChild(arrowLeft);
		this.frameholder.appendChild(arrowRight);
		// alert(popupImgArr.join("\n"))
		// Kreisfoermiges weiterschalten: Die Pfeile springen von n auf 0 zuruecke, bzw. 0 -> n
		// alert("hier")
		// registerEventListenersObj(this.lis[i], "mousedown", this, false, 'show');
		// report('flashInGallery: '+this.flashInGallery)
		registerEventListenersObj(arrowLeft,	'click', this, false, 'previousImage');
		registerEventListenersObj(arrowRight,	'click', this, false, 'nextImage');
	}
	
 	// Listener
	if (this.useParent) eDoc = parent.document // fuer den close Listener
	else 				eDoc = document
	// report(eDoc.location.href)
	// report(this.popupLayerCloseButton.id)
	// alert(document.getElementById('popuplayerCloser_'+this.nr).id)
	// alert(this.nr)
	registerEventListenersObj(eDoc.getElementById('popuplayerCloser_'+this.nr),  						'click', this, false, 'popupLayerClose');
	registerEventListenersObj(this.popupLayerElement, 													'click', this, false, 'popupLayerClose');
	if (this.onminimize) registerEventListenersObj(eDoc.getElementById('popuplayerMinimizer_'+this.nr), 'click', this, false, 'popupLayerMinimize');
	if (is_ie6) {
		registerEventListenersObj(window, 'scroll', this, false, 'popupLayerIE6Position');
		this.popupLayerIE6Position()
	}
	this.popuplayerFrame 	 = document.getElementById('popuplayerFrame_'+this.nr)
	this.popuplayerContentTd = document.getElementById('popuplayer_content_td_'+this.nr)
	this.h = h
	this.w = w

	
}

popupLayerObj.prototype.previousImage = function(e) {
	this.popupImgPos--
	if (this.popupImgPos < 0) this.popupImgPos  = this.popupImgNum-1 
	var src   = this.popupImgArr[this.popupImgPos]; 
	var elFla 	= document.getElementById('popupImageFlash')
	var elImg 	= document.getElementById('popupImage')
	// report('src: ' + src)
	if (src.indexOf('.swf') != -1) {		// Flash src austauschen und Flas-Node sichtbar machen, Img-Node unsichtbar
		// src fuer IE: [0], moz: [3]
		elImg.style.display 		= 'none'
		elFla.style.display 		= 'block'
		elFla.childNodes[0].movie 					= src 		// ie
		if (!document.all) elFla.childNodes[3].src 	= src 		// Moz
	} else { 
		// report('src: ' + src)						// Img src austauschen
		elImg.src 					= src 
		elImg.style.display 		= 'block'
		elFla.style.display 		= 'none'
	}
	e.cancelBubble=true
}

popupLayerObj.prototype.nextImage = function(e) {
	this.popupImgPos++
	if (this.popupImgPos == this.popupImgNum) 	this.popupImgPos = 0
	var src   = this.popupImgArr[this.popupImgPos]; 
	// report(sO(this.popupImgArr))
	var elFla 	= document.getElementById('popupImageFlash')
	var elImg 	= document.getElementById('popupImage')
	if (src.indexOf('.swf') != -1) {		// Flash src austauschen und Flas-Node sichtbar machen, Img-Node unsichtbar
		// report('src: ' + src)
		elImg.style.display 		= 'none'
		elFla.style.display 		= 'block'
		elFla.childNodes[0].movie 					= src 		// ie
		if (!document.all) elFla.childNodes[3].src 	= src 		// Moz
	} else { 
		// report('src: ' + src)						// Img src austauschen
		elFla.style.display 		= 'none'
		elImg.style.display 		= 'block'
		elImg.src 					= src 
	}
	e.cancelBubble=true
	// document.getElementById('popupImage').src = this.popupImgArr[this.popupImgPos]; e.cancelBubble=true
}

popupLayerObj.prototype.popupLayerIE6Position = function() {
	// report("scrollTop: " + document.documentElement.scrollTop+"\n")
	// report("scrollTop: " + document.body.scrollTop+"\n")
	// report("this.layerContentTop: " + this.layerContentTop+"\n")
	this.frameholder.style.top = (document.documentElement.scrollTop + this.layerContentTop) + 'px'
}

function isReadyFlash() {
	return 1
}

popupLayerObj.prototype.popupLayerMinimize = function() {
	// last change: 21.01.09
	// Scrollbar aus
	var loc = ''
	var loc = thisMovie('flash_0').getLocation();
	// alert(loc)
	if (loc) {locArr = loc.split('_');
		defID  = locArr[0]
		stepID = locArr[1]
		// defID  = 33
		// stepID = 12
		// alert("defID: " + defID + ", stepID: " + stepID)
		this.flashVars += ('&pointID='+ defID + '&stepID=' + stepID)
		// alert("alert(this.flashVars) 1: " + this.flashVars)
		this.flashVars = modifyQueryStr(this.flashVars)
		var url 	   = '/cms/templates/karcher/mod/application_advisor/setapplicationdata.php?appadvisor_saveddefID='+defID+'&appadvisor_savedstepID='+stepID;
		var callback    = function(state, vals, status, statusText) {
			alert(vals)	
		}
		var tmp = new ajax(url,'','get',0,'','');
		// alert("tmp url:" + url);
	}
	
	if (this.popupScrollbarRefEl) this.popupScrollbarRefEl.style.display = 'none'
	// dimmer aus
	this.body.removeChild(this.popupLayerDimmer); 
	var fHw = this.frameholder.offsetWidth	// diese Werte muessen erfasst werden, bevor das Element geloescht wird...
	var fHh = this.frameholder.offsetHeight
	
	
	//var embedx  = document.getElementById('embed_'+this.nr)
	//var objectx = document.getElementById('object_'+this.nr)
	//alert("nobject.src: " + objectx.src)
	//alert("embedx.src: " + embedx.src)
	//alert("objectx.id: " + objectx.id)
	//alert("objectx.movie: " + objectx.movie)
	//embedx.src  = '';
	//if (document.all) objectx.movie = '';
	//alert("embedx.src: " + embedx.src + "\nobjectx.src: " + objectx.src)
	// this.iframe
	// this.frameholder.innerHTML = ''; // entladen?
	this.body.removeChild(this.popupLayerElement);
	window.popupLayerStack.pop()
	
	
	// alert("this.minimizeEffect : " +this.minimizeEffect)
	// alert("document.voting.captcha_code.value: " + document.voting.captcha_code.value)
	if (this.minimizeEffect) {
		if (this.minimizeEffect == 'appadvisorzoom') {
			// this.frameholder.innerHTML = '<img src="/cms/templates/karcher/mod/application_advisor/closedummy.jpg" width="100%" height="100%">'
			// alert("hier")
			
			// Button platzieren
			if (!document.getElementById('appadvisor_opener_button')) {
				var div = document.createElement('div')
				var img = new Image(); img.src = '/cms/templates/karcher2008/images2008/appadvisor_opener_button.gif';
				var swf, para, flashVars
				// alert(this.flashVars)
				var pars = '&forkarcherstandard'
				var swf  = 'application_advisor2008.swf'
				if (this.flashVars) {
					// flashVars 	= escape(this.flashVars)
					// flashVars 	= this.flashVars
					flashVars 	= escape(this.flashVars)
					swf 		= 'application_advisor2010.swf'
					pars 		= '&outtype=flash2010'
					
					// alert("flashVars: " + flashVars)
				}
				div.innerHTML = "<a onfocus=\"if(this.blur)this.blur()\" id=\"appadvisor_opener_button\" href=\"javascript:popupLayer('/cms/templates/karcher/mod/application_advisor/"+swf+"?versionID="+appadvisor2008_versionID+"&projecttype=karcher2008&advisortype=karcher2008&language="+appadvisor2008_language+pars+"',860,565,'"+addslashes(appadvisor2008_headline_window_title)+"',{flashVars:'"+flashVars+"',usePopupLayerObj:1,closeEffect:appadvisorClose,minimizeEffect:'appadvisorzoom', xtraData:{minbuttontext:'"+addslashes(this.minbuttontext)+"'}})\" class=\"appadvisor_opener_button\">"+this.minbuttontext+"</a>";
				pEl = document.getElementById('spalte1_inhalt')
				if (pEl) pEl.insertBefore(div,pEl.firstChild)	
			}
			
			// Zoomeffekt	
			this.frameholder.style.position = 'relative';
			this.frameholder.innerHTML 		= '<div style="border:3px solid #CECECE; width:100%; height:100%">&nbsp;</div>'
			var div = document.createElement('div')
			div.innerHTML 		= '<div style="border:3px solid #CECECE; width:100%; height:100%">&nbsp;</div>'
			div.style.cssText 	= 'z-index:100000; position:absolute; left:'+this.frameholder.offsetLeft+'px; top:'+this.frameholder.offsetTop+'px; width:'+this.frameholder.offsetWidth+'px; height:'+this.frameholder.offsetHeight+'px';
			document.body.appendChild(div);
			// this.popuplayerContentTd
			//report("this.frameholder.offsetLeft: " + this.frameholder.offsetLeft)
			//report("this.frameholder.offsetTop: " + this.frameholder.offsetTop)
			//report("this.frameholder.offsetWidth: " + this.frameholder.offsetWidth)
			//report("this.frameholder.offsetHeight: " + this.frameholder.offsetHeight)
			
			var appadvisor_opener_button = document.getElementById('appadvisor_opener_button')
			//report("appadvisor_opener_button.offsetLeft: " + appadvisor_opener_button.offsetLeft)
			//report("appadvisor_opener_button.offsetTop: " + appadvisor_opener_button.offsetTop)
			
			//report("absLeft(appadvisor_opener_button): " + absLeft(appadvisor_opener_button))
			//report("absTop(appadvisor_opener_button): " + absTop(appadvisor_opener_button))
			//
			//report("appadvisor_opener_button.offsetWidth: " + appadvisor_opener_button.offsetWidth)
			//report("appadvisor_opener_button.offsetHeight: " + appadvisor_opener_button.offsetHeight)
			// alert("popupLayerClose");
			// alert(this.minimizeUrl)
			var obj = this;
			// callbackFunction = function() {document.location.href = this.minimizeUrl};
			var fader = new faderObj({		el:					div, 
											mode:				'in', 
											limit:				30,
											properties:			['position','size'],
											offset_x:			absLeft(appadvisor_opener_button)-3, 
											offset_y:			absTop(appadvisor_opener_button)-3, 
											offsetStart_x:		this.frameholder.offsetLeft,
											offsetStart_y:		this.frameholder.offsetTop,
											offset_w:			appadvisor_opener_button.offsetWidth, 
											offset_h:			appadvisor_opener_button.offsetHeight, 
											offsetStart_w:		fHw, 
											offsetStart_h:		fHh, 
											clearAfterFade:		1,
											accelerate:			0.5, // kleiner als 0.5! n % der Strecke
											decelarate:			0.3
										}) // ,'size','position'
			// url nach faden, wenn definiert
			
			if (this.minimizeUrl) {
				var qNow = parseQueryStr()
				var qGo  = parseQueryStr(this.minimizeUrl)
				// report("qNow: " + showObject(qNow))
				// report("qGo" + showObject(qGo))
				// report("qNow ac: " + qNow.ac)
				// report("qGo ac: "  + qGo.ac)
				
				// Url Vergleich aktuelle url und neue url.
				// wenn ich schon auf der Ziel-Zubehörseeite bin, verhindert ein anchor in der url,z. B. #1234653, dass die Seite neu laedt, es wird stattdessn in der Seite nur an die Anchorpos. gesprungen
				// also kein neues Detailfenster geoeffnet, weil kein "onload" stattfindet.
				// +++ Achtung: IE6 hier gibt es ein ganz raetselhaftes Problem mit der Laenge der Parameter: Bei 'acc' statt 'ac' wird der Link aus Flash heraus ignoriert.
				if (qGo.ac && qGo.ac == qNow.ac) {
					// alert("relaod")
					fader.callbackonFinish = function() {document.location.reload()};
				} else { 	
					// if (document.location.search.indexOf('sq_app')!= -1) alert(obj.minimizeUrl)	
					fader.callbackonFinish = function() {document.location.href = obj.minimizeUrl};
				}
				// fader.callbackonFinish = function() {document.location.href = obj.minimizeUrl};
			}
		}
	}
	// an eine Url springen
	// if (this.minimizeUrl) document.location.href = this.minimizeUrl
}


popupLayerObj.prototype.popupLayerClose = function() {
	// last change: 21.01.09
	// Scrollbar aus
	// alert(this.path)
	if (this.popupScrollbarRefEl) this.popupScrollbarRefEl.style.display = 'none'
	// dimmer aus
	this.body.removeChild(this.popupLayerDimmer); 
	//var fHw = this.frameholder.offsetWidth	// diese Werte muessen erfasst werden, bevor das Element geloescht wird...
	//var fHh = this.frameholder.offsetHeight
	//report("this.frameholder.offsetWidth: "  + this.frameholder.offsetWidth)
	// report("this.frameholder.offsetHeight: " + this.frameholder.offsetHeight)
	// var iframex = document.getElementById('popuplayerIframe_'+this.nr)
	// iframex.src = '' // Versuch, den Speicher in IE6 freizugeben
	// alert(iframex.id)
	
	this.body.removeChild(this.popupLayerElement);
	window.popupLayerStack.pop()
	if (this.onclose=='back') 		window.history.back();
	if (this.onclose=='refresh') 	document.location.reload()
	if (this.onclose=='reload') 	document.location.href = document.location.href
	
	if (this.oncloseAjaxUrl) {
		// alert("this.oncloseAjaxUrl: " + this.oncloseAjaxUrl)
		if (this.oncloseAjaxUrl) {var ajaxProcess = new ajax(this.oncloseAjaxUrl,'','get',0,'','');} // function(state, vals){report(vals)}
	}
	if (this.closeEffect) {
		// erwartet einen functionsnamen
		this.closeEffect()
	}
	// window.popupLayerStack = '';
}



function appadvisorMin(url) {
	//alert(url)
	url = url.replace(/_pp/g,'%')
	url = url.replace(/_eq/g,'=')
	// url = url.replace('getAccessoriesDetails','getAccessoriesDetailsX')
	//url = url.replace('http://www.karcher.de/de/Produkte/Haus_und_Garten/Zubehoer.htm','http://www.karcher.de/de/Home.htm')
	// alert(url)
	
	if (activePopup) {
		activePopup.minimizeUrl = url; 
		activePopup.popupLayerMinimize();
	}
}

function appadvisorClose(url) {
	var button = document.getElementById('appadvisor_opener_button')
	if (button) button.parentNode.removeChild(button)
}



















// ________________________________________________________________________________________________________________________________
// M U L T I B O X S E L E C T
// +multiboxselect
function multiboxselectObj(P) {
	if (!P.rootID) alert("multiboxselectObj: no rootID, can't go on")
	else this.rootID = P.rootID
	// alert(this.rootID)
	P.boxesactive 		?  this.boxesactive  = P.boxesactive  	: this.boxesactive  = 1
	P.getVarName 		?  this.getVarName  = P.getVarName  	: this.getVarName  	= ''
	P.getVars 			?  this.getVars  	= P.getVars  		: this.getVars  	= ''
	P.dataArr 			?  this.dataArr 	= P.dataArr  		: this.dataArr  	= ''
	P.dataArr 			?  this.dataArr 	= P.dataArr  		: this.dataArr  	= ''
	P.scrollclass 		?  this.scrollclass	= P.scrollclass  	: this.scrollclass  = ''
	P.anchor 			?  this.anchor		= P.anchor  		: this.anchor 		= ''
	
	// dataArr aus einer globalen entenhmen, um das IE& closure Speicher Problem zu umgehen
	if (!this.dataArr && window.multiboxselectDataArr) this.dataArr = window.multiboxselectDataArr;
	if (!this.dataArr) alert("multiboxselectObj: dataArr not found")
	this.queryStr 		= getQueryStr()
	// report(this.queryStr)
	this.queryVarObj 	= parseQueryStr()
	// alert(this.dataArr);
	if (queryVarObj[P.getVarName]) {
		// alert(queryVarObj[P.getVarName])
		this.createBoxPath(queryVarObj[P.getVarName])
	} else {
		this.createNextBox('',this.dataArr,0);
	}
}

multiboxselectObj.prototype.createNextBox = function(arrkey,arr,boxlevel,activeID) {
	var lastlevel,i,box
	// alert(showObject(arr))
	// alert(showObject(arr.children))
	
	boxID 	= this.rootID + '_' +boxlevel
	box 	= document.getElementById(boxID)
	if (boxlevel == this.boxesactive-1) 	lastlevel = 1
	else 									lastlevel = 0;
	
	
	// sub Boxen leeren
	for (var i=boxlevel;i<this.boxesactive;i++) {
		var clearboxID = this.rootID+'_'+i 
		var clearbox = document.getElementById(clearboxID)
		if (clearbox) clearbox.innerHTML = ''
		// Scrollbars? Wenn da, dann loeschen
		// if (window.cargoScrollbarsObjArr && window.cargoScrollbarsObjArr[clearboxID]) window.cargoScrollbarsObjArr[clearboxID].deleteScrollbar()
	}
	// Schleife
	var i = 0
	//alert(showObject(arr.children[child].children))
	for (child in arr) {
		var div = document.createElement('div')
		// alert(showObject(arr[child]))
		nextarrkey 		= arrkey + '['+i+'].children'
		div.className 	= 'multiboxselect_element'
		div.onclick 	= "alert(this.className);"	
		// report("activeID: " + activeID+"\n")
		// report(arr[child].content+"\n")
		if (arr[child].ID == activeID) div.className +=  ' multiboxselect_active'		// Active?
		var elementID = this.rootID+'_'+arr[child].ID
		// this.parentNode.className+=\' multiboxselect_active\'
		var _anchor = ''
		if (this.anchor) _anchor = '#' +this.anchor
		_lastlevel = lastlevel
		if (!arr[child].children) {
			_lastlevel = 1
		}
		// report(arr[child].content + " lastlevel: " + lastlevel)
		if (!_lastlevel) 	div.innerHTML 	= '<a style="text-decoration:none" id="'+elementID+'" href="javascript:'+this.rootID+'_multiboxselect.highlight(\''+elementID+'\',\''+this.rootID+'_'+boxlevel+'\'); '+this.rootID+'_multiboxselect.createNextBox(\''+nextarrkey+'\','+this.rootID+'_multiboxselect.dataArr'+nextarrkey+','+(boxlevel+1)+',\'\')">'+arr[child].content+'</a>';
		else 				div.innerHTML 	= '<a style="text-decoration:none" id="'+elementID+'"         onclick="'+this.rootID+'_multiboxselect.highlight(\''+elementID+'\',\''+this.rootID+'_'+boxlevel+'\');" href="?'+ this.getVars+'&'+this.getVarName +'='+ arr[child].ID +_anchor+'">'+arr[child].content+'</a>';
		if (box) box.appendChild(div)
		i++
	}
		
	// S C R O L L B A R S
	// Die 3 Boxen wurden bereits als Leerboxen erstellt, d.h. die Scrollbars mit der ID der Leerboxen sind bereits vorhanden
	// Sie werden hier neu erstellt.
	// if (window.cargoScrollbarsObjArr) {
	
	if (this.scrollclass=='scrollable') {
		if (!window.cargoScrollbarsObjArr)  		window.cargoScrollbarsObjArr = {}
		if (!window.cargoScrollbarsObjArr[boxID]) {
			var P = {barwidth:15, buttonheight:15, slideroverlap:1, scrollbarLeftoverlap: 1, barOutside: 1, refEl:box, overflow:'hidden'} // hier refEl einsetzten
			window.cargoScrollbarsObjArr[boxID] = new scrollbarObj(P)
		} else {
			window.cargoScrollbarsObjArr[boxID].positionScrollBar();
		}
	}
	
	
}

multiboxselectObj.prototype.highlight = function(activeElID,boxID) {
	var box 	 = document.getElementById(boxID)
	var activeEl = document.getElementById(activeElID) // active el ist das <a>
	allActiveArr = getElementsByClassNameM(box,'div','multiboxselect_active')
	for (var i=0;i<allActiveArr.length;i++) {
		// report("deactivere: "+ allActiveArr[i].nodeName+"\n")
		allActiveArr[i].className = allActiveArr[i].className.replace(' multiboxselect_active','')
		//alert(allActiveArr[i].className)
	}
	activeEl.parentNode.className += ' multiboxselect_active'
}

multiboxselectObj.prototype.createBoxPath = function(ID) {
	var arrkey 	= ''
	// Boxenpfad finden
	// report("ID: " + ID+"<br>")
	ID = decodeURIComponent(ID) // bei Text-IDs Url-Encoding entfernen: Fl%C3%A4chenreiniger -> Flächenreiniger
	//alert("ID: " + ID)
	IDObj 		= findInArray(this.dataArr,ID,{keys:[],IDs:[],Names:[]});
	if (!IDObj || !IDObj.keys) return;
	// report(showObject(IDObj)+"\n")
	// Boxen generieren
	for (var i=0;i<IDObj.keys.length;i++) {
		var boxlevel = i
		var activeID = IDObj.IDs[i]
		// report("this.dataArr"+arrkey+"\n")
		this.createNextBox(arrkey,eval("this.dataArr"+arrkey),boxlevel,activeID)
		arrkey += "["+IDObj.keys[i]+"].children"
	}
}


function findInArray(arr,ID,obj) {
	// gibt ein Object zurueck {keys:[],IDs:[],Names:[]}
	// Bsp: {keys: [2,11,0), IDs: [10002117,10002125,15182500], Names: [Consumer Indoor,Dampfbügelstationen,SI 2125]}
	var i = 0
	for (child in arr) {
		var _i 		= i
		var _ID 	= arr[child].ID
		var _Name 	= arr[child].content
		if (arr[child].children) {
			Myobj = findInArray(arr[child].children,ID,obj)
			if(Myobj) {
				obj.keys.unshift(_i) 
				obj.IDs.unshift(_ID) 
				obj.Names.unshift(_Name) 
				return Myobj
			}
		}
		if (arr[child] && arr[child].ID == ID) {
			obj.keys.unshift(i) 
			obj.IDs.unshift(arr[child].ID) 
			obj.Names.unshift(arr[child].content) 
			return obj
		}
		i++
	} 
}







// M U L T I S E L E C T B O X
// Peter Singewald
function get_next_multibox(akt, gid, orgbox) {
    var bgc = eval ('bgcolor_'+gid);
    var row_class = eval('main_row_class_'+gid);
    if (document.getElementById('box_hidden_'+orgbox+'_'+gid).value != '' ) {
        document.getElementById(document.getElementById('box_hidden_'+orgbox+'_'+gid).value+'_'+orgbox).style.backgroundColor = '';   
        document.getElementById(document.getElementById('box_hidden_'+orgbox+'_'+gid).value+'_'+orgbox).removeAttribute('class');
		document.getElementById(document.getElementById('box_hidden_'+orgbox+'_'+gid).value+'_'+orgbox).setAttribute("class", row_class);
	}
    document.getElementById('box_hidden_'+orgbox+'_'+gid).value = akt;
    var maxlevel    = document.getElementById('maxlevel_'+gid).value;
    var nextbox     = (1*orgbox)+1;
    var val_eval    = eval('val_'+gid);
    var betw_arr    = val_eval;
    for (var i=nextbox;i<=maxlevel;i++){
        document.getElementById('box_hidden_'+i+'_'+gid).value = '';
        document.getElementById('box_'+i+'_'+gid).innerHTML = '';
    }
    for (var i=0;i<nextbox;i++){
        betw_arr    = betw_arr[document.getElementById('box_hidden_'+i+'_'+gid).value];
        if (document.getElementById('box_hidden_'+i+'_'+gid).value != '' ) {
        	document.getElementById(document.getElementById('box_hidden_'+i+'_'+gid).value+'_'+i).style.backgroundColor = bgc;
        }
    }
    var str_    = '';
    var ender   = ';return false;';
    if (!document.getElementById('box_hidden_'+(nextbox+1)+'_'+gid) ) {
        ender   = '';
	}
    var searchS = /(~-~)/g
    
    for (var Eigenschaft in betw_arr) {
        if (Eigenschaft == 'content') {continue;}
        outputEi        = Eigenschaft;
        if (outputEi.match(searchS)) {
            outputA     = outputEi.split('~-~');
            outputEi    = '<b class="mb_split_output_front" style="cursor:pointer;font-weight:normal">'+outputA[0]+'</b><span class="mb_split_output_back">'+outputA[1]+'</b>'
        }
        str_ += "<a href=\"#\" id=\""+Eigenschaft+"_"+nextbox+"\" onclick=\""+betw_arr[Eigenschaft]['content']+""+ender+"; return false\" class=\""+document.getElementById('row_class_'+gid).value+"\">"+outputEi+"</a>";   
           
    } 
   //  document.getElementById('box_'+nextbox+'_'+gid).style.marginRight = 0
	document.getElementById('box_'+nextbox+'_'+gid).innerHTML = str_;
   	// Scrollbars
	
	//if (this.scrollclass=='scrollable') {
		if (!window.cargoScrollbarsObjArr) window.cargoScrollbarsObjArr = {}
		if (!window.cargoScrollbarsObjArr['box_'+nextbox+'_'+gid]) {
			var P = {barwidth:15, buttonheight:15, slideroverlap:1, scrollbarLeftoverlap: 1, refEl:box} // hier refEl einsetzten
			window.cargoScrollbarsObjArr['box_'+nextbox+'_'+gid] = new scrollbarObj(P)
		} else {
			window.cargoScrollbarsObjArr['box_'+nextbox+'_'+gid].positionScrollBar();
		}
	//}
}
      
	    
function send_multibox(akt, gid, orgbox) {
    document.getElementById('box_hidden_'+orgbox+'_'+gid).value = akt;
	document.getElementById('form_'+gid).submit();
}















// F A D E R
/* Info:
-	neu und zu Ubernehmen:
			P.callbackonFinish		?  this.callbackonFinish = P.callbackonFinish	: this.callbackonFinish = null
			if (typeof(this.callbackonFinish)=='function') 	this.callbackonFinish()
			else 											this.callbackonFinish



*/
// Interpolation von Animationen
// Bsp Aufruf: var fader = new faderObj({el:cargoUpdateFrame, mode:'in', cycle:2, properties:['opacity'],faderStep:4, limit:50})
function faderObj(P) {
	// P.autostart = 'test'
	if (!P.el) alert('Fader: targetelement not given')
	this.el = P.el
	P.display 				?  this.display 		= P.display  			: this.display 			= 'block'
	P.properties 			?  this.properties 		= P.properties  		: this.properties 		= ['opacity']
	P.mode 			 		?  this.mode 			= P.mode  				: this.mode 			= 'in'
	P.cycle 			 	?  this.cycle 			= P.cycle  				: this.cycle 			= 0
	P.faderStep 			?  this.faderStep 		= P.faderStep  			: this.faderStep 		= 1	// Schritte des faderCounters
	P.faderInterval 		?  this.faderInterval 	= P.faderInterval  		: this.faderInterval 	= 1	// Aufrufhäufigkeit des Intervals
	P.offsetStart_x 		?  this.offsetStart_x 	= parseInt(P.offsetStart_x) : this.offsetStart_x 	= 0	// die aufrufende Anwendung sollte sicherhetishalber die korrekten Startpositionen berechnen und uebergeben, da das nicht immer automatisch mit absLeft geht (z. B. beim Popuplayer ist absLeft() = 0)
	P.offsetStart_y 		?  this.offsetStart_y 	= parseInt(P.offsetStart_y) : this.offsetStart_y 	= 0	
	P.offset_x 				?  this.offset_x 		= parseInt(P.offset_x)  	: this.offset_x 		= 0	
	P.offset_y				?  this.offset_y 		= parseInt(P.offset_y) 		: this.offset_y 		= 0	
	P.offsetStart_w 		?  this.offsetStart_w 	= parseInt(P.offsetStart_w) : this.offsetStart_w 	= 0	// die aufrufende Anwendung sollte sicherhetishalber die korrekten Startpositionen berechnen und uebergeben, da das nicht immer automatisch mit absLeft geht (z. B. beim Popuplayer ist absLeft() = 0)
	P.offsetStart_h 		?  this.offsetStart_h 	= parseInt(P.offsetStart_h) : this.offsetStart_h 	= 0	
	P.offset_w 				?  this.offset_w 		= parseInt(P.offset_w)  	: this.offset_w 		= 0	
	P.offset_h				?  this.offset_h 		= parseInt(P.offset_h) 		: this.offset_h 		= 0	
	P.clearAfterFade		?  this.clearAfterFade 	= P.clearAfterFade      : this.clearAfterFade 	= 0
	P.accelerate			?  this.accelerate 		= P.accelerate       	: this.accelerate 		= 0 // Beschleunigen
	P.decelarate			?  this.decelarate 		= P.decelarate      	: this.decelarate 		= 0 // Bremsen
	P.delay					?  this.delay 			= P.delay      			: this.delay 			= 0
	P.callbackonFinish		?  this.callbackonFinish = P.callbackonFinish	: this.callbackonFinish = null
	// alert("faderInterval: " + this.faderInterval)
	// offset_x
	// P.wait
	// alert(typeof P.autostart)
	if (typeof P.autostart == 'undefined') 	this.autostart = 1 // geht eigenartigerweise nicht mit ?:
	else 									this.autostart = P.autostart
	// report("this.autostart: " + this.autostart)
	
	this.limit = P.limit
	if (!this.limit) {
		if (document.all) 	this.limit = 108 	// IE soll etwas laneger laufen, da der Blockfader sont nicht frueh genug wirkt (erst nach dem mouseout, d.h. es wird ein fader-Schritt ausgefuehrt, man sieht eine leichte Transparenz)
		else 				this.limit = 99 	
	}
	// Position: Startposition merken:
	//report(this.nase)
	//report(this.nase == undefined)
	//report(this.el.nodeName + " this.el.id:" + this.el.id + " " + this.el.style.cssText)
	if (in_array(this.properties,'position')) {
		if (!this.startOffset_x) this.startOffset_x = absLeft(this.el)
		if (!this.startOffset_y) this.startOffset_y = absLeft(this.el)
		if (!this.el.position == 'absolute') this.el.position = 'absolute'
		
		//report(this.el.nodeName + " this.el.id:" + this.el.id + " " + this.el.style.cssText)
		//report("this.offsetStart_x: " + this.offsetStart_x);
		//report("this.offsetStart_y: " + this.offsetStart_y);
	}
	if (in_array(this.properties,'size')) {
		if (!this.startOffset_w) this.startOffset_w = this.el.offsetWidth
		if (!this.startOffset_h) this.startOffset_h = this.el.offsetHeight
		if (!this.el.position == 'absolute') this.el.position = 'absolute'
		// report(this.el.nodeName + " this.el.id:" + this.el.id + " " + this.el.style.cssText)
		//report("this.offset_w: " + this.offset_w);
		//report("this.offset_h: " + this.offset_h);
		//report("this.offsetStart_w: " + this.offsetStart_w);
		//report("this.offsetStart_h: " + this.offsetStart_h);
	}
	// A C C E L E R A T E
	// Das ist etwas komplizierter. Ich will beim Start als auch am Ende eine Sinuskurve einrechnen. Dies soll aber nur eine Teil der Strecke beeinflussen
	// Bsp: 100 steps, 1-20 Beschleunigen, 70 - 100 Bremsen
	// Ich berechne alle Factoren im Voraus und korrigrierr das Ergebnis nach Beschleunigung und Bremsen so, daß am Ende der Faktor 1 rauskommt (sonst wäre es < 1, weil ich ja bremse und beschleunige)
	// es gibt eine Stecke: limit, z. B. 30
	// ueber n% dieser Strecke wird beschleunigt, z. B. accelerate = 0.33
	// brechnen: n% von 30 = 10 -> Die Beschleunigung geht ueber die 1. 10 Schritte
	// um von 0 auf 90 zu kommen, muß ein sinusfactor berechnet werden: 90 / 10 
	// Da beim Bechleunigen und Abbremsen dei Schritte verkleinert werden, wird dei kompeltte reihe im Voraus druchgerechnet. 
	//Das Ergebnis faellt niedriger aus, als ohne Bechleunigung und Abbremsen, deshalb wird am Endne jeder Wert nochnal mit einem faktor Multipliziert, um auf den Endwert zu kommen.
	
	if (this.accelerate) {
		if (this.accelerate > 0.5) this.accelerate = 0.5 				// Begrenzen, Beschleunigung darf nicht über mehr als die halbe Strecke laufen
		this.accSteps       = parseInt(this.limit * this.accelerate) 	// Anzahl der Steps, auf denen Dei Beshcleunigung laueft
		this.accStepValue   = 90/this.accSteps							// die Bechleunigung muß von 0 - 90 laufen, deshalb wird bei jedem Step ein eigner Zähler hinzugerechnet (90/accSteps)			
		this.accStepCounter = 0				
		// report("this.limit: " + this.limit + " accSteps: " + this.accSteps + " accStepValue: " + this.accStepValue)
	}
	if (this.decelarate) {
		if (this.decelarate > 0.5) this.decelarate = 0.5 				// Begrenzen, Beschleunigung darf nicht über mehr als die halbe Strecke laufen
		this.decSteps       = parseInt(this.limit * this.decelarate) 	// Anzahl der Steps, auf denen die Beschleunigung laueft
		this.decStepValue   = 90/this.decSteps							// die Bechleunigung muß von 0 - 90 laufen, deshalb wird bei jedem Step ein eigner Zähler hinzugerechnet (90/accSteps)			
		this.decStepCounter = 0				
		// report("this.limit: " + this.limit + " accSteps: " + this.accSteps + " accStepValue: " + this.accStepValue)
	}
	if (this.accelerate || this.decelarate) {
		this.valAccArr = new Array()
		var iDec 	= 0;
		var factorDegrease = 1/this.limit
		var factor = 1
		for (var i=0;i<this.limit;i++) {
			var sinCos = 1;
			if (i < this.accSteps) {
				sinCos = Math.sin((this.accStepCounter*0.017453293))
				this.accStepCounter += this.accStepValue
			}
			if (i == this.limit - this.decSteps) iDec = i
			if (i > (this.limit - this.decSteps)) {
				sinCos = Math.sin(((90 + this.decStepCounter)*0.017453293))
				this.decStepCounter += this.decStepValue
			}
			// sinCos = 1;
			factor = factor - (factorDegrease * sinCos)
			this.valAccArr[i] = factor
			// report("faderCounter: " + i + " "+ sinCos + " f: "+factor)
		} // end for
		//report("factor: " + factor);
		var reducer = this.valAccArr[this.limit-1]
		//report("valAccArr[0]: " + this.valAccArr[0])
		//report("valAccArr[this.limit-1]: " + this.valAccArr[this.limit-1])
		//report("reducer: " + reducer);
		// Der factorAccFactor darf nicht linear angewandt, sonder muß ebenfalls am Anfang 0 sein und sich dann auf 1 steigern
		// Deshalb multiplizere ich ihn nochmal mit i/this.limit, d. h. am Anfang ist das fast 0, am Ende 1
		// Bsp: factor 1.0 - 0.0 in 100 Steps
		for (var i=0;i<this.limit;i++) {
			this.valAccArr[i] = this.valAccArr[i] - (((i+1)/this.limit) * reducer) 
			//report("faderCounter: " + i + " " + this.valAccArr[i] + " reducerFactor:" + ((i+1)/this.limit)     )
		}
		//report("valAccArr[0]: " + this.valAccArr[0])
		//report("valAccArr[this.limit-1]: " + this.valAccArr[this.limit-1])
	}
	
	
	
	if (this.mode=='in') this.faderCounter = 0
	else 				 this.faderCounter = this.limit // es ruckelt bei 100
	var obj = this
	this.el.style.display 	= this.display
	
	
	if (this.autostart) {
		if (this.delay) window.setTimeout(function() {	obj.fade(this.mode)}, this.delay)
		else 											obj.fade(this.mode)
	}
	/*
	alert(	"properties " 	+ this.properties 					+ "\n" + 
			"mode " 		+ this.mode 						+ "\n" + 
			"faderStep " 	+ this.faderStep 					+ "\n" + 
			"faderInterval "+ this.faderInterval 				+ "\n" + 
			"limit " 		+ this.limit 						+ "\n" + 
			"offset_x " 	+ this.offset_x 					+ "\n" + 	
			"offset_y " 	+ this.offset_y 					+ "\n" + 
	'')
	*/
}









faderObj.prototype.fade = function(mode) {
	if (window.blockFader) return;
	
	if (mode) this.mode = mode
	// report("mode: "+ mode)
	// report(" fader faderCounter:" +  this.faderCounter + " mode: " + mode+"<br>")
	this.mode == 'in' ? this.faderDirection = 1 : this.faderDirection = -1;
	this.faderCounter = this.faderCounter + this.faderDirection * this.faderStep;
	if (this.faderCounter < 0) this.faderCounter 	= 0;
	if (this.faderCounter > this.limit) this.faderCounter = this.limit;
	// report(obj.objID + " faderCounter:" +  obj.faderCounter + " mode: " + obj.mode+ " fInterval " + obj.fInterval +"<br>")	
	var obj = this;
	if ((this.mode=='in' && this.faderCounter >= this.limit) || (this.mode=='out' && this.faderCounter <= 0)) {
		this.cycle--
		if (this.cycle <= 0) {
			window.clearInterval(obj.fInterval)
			this.fInterval = ''
			if (this.clearAfterFade) {
				// report("fader: removeChild " + obj.el.id)
				this.el.parentNode.removeChild(this.el)
			}
			//alert("this.callbackonFinish: " + this.callbackonFinish)
			//alert(typeof(this.callbackonFinish))
			if (typeof(this.callbackonFinish)=='function') 	this.callbackonFinish()
			else 											this.callbackonFinish
		} else {
			this.mode=='in' ? this.mode = 'out' : this.mode = 'in'
		}
		
	} else {
		if (!this.fInterval) this.fInterval = window.setInterval(function(){obj.fade()},obj.faderInterval)
	}
	
	// A C C E L E R A T E 
	// var sinCos = 1;
	var factor = (this.limit-this.faderCounter) / this.limit
	if (this.valAccArr) factor = this.valAccArr[this.faderCounter] // Asu dem vorausgrechnete rray nehmen, mit Beschleunigung und Bremsen
	/*
	// report("factor: " + factor)
	// es gibt eine Stecke: limit, z. B. 30
	// ueber n% dieser Strecke wird beschleunigt, z. B. accelerate = 0.33
	// brechnen: n% von 30 = 10 -> Die Beschleunigung geht ueber die 1. 10 Schritte
	// um von 0 auf 90 zu kommen, muß ein sinusfactor berechnet werden: 90 / 10 
	if (this.accelerate) {
		if (this.accStepCounter < 90) {
			this.accStepCounter += this.accStepValue
			if (this.accStepCounter > 90) this.accStepCounter = 90
			sinCos = Math.sin((this.accStepCounter*0.017453293))
		}
		// report("sinCos:" + sinCos + " factor: " + factor)
		var factor = (this.limit-this.faderCounter*sinCos) / this.limit
	}
	if (this.decelarate) {
		if (this.decStepCounter < 90 && this.faderCounter > (this.limit - this.decSteps)) {
			this.decStepCounter += this.decStepValue
			if (this.decStepCounter > 90) this.decStepCounter = 90
			sinCos = Math.sin(((this.decStepCounter)*0.017453293)) // hier cos verwenden
		}
		var factor = (this.limit-this.faderCounter*sinCos) / this.limit
	}
	report("faderCounter: " + this.faderCounter + "sinCos: " + sinCos)
	// var factor = (this.limit-this.faderCounter*sinCos) / this.limit
	// factor: am start 1, am Ende 0
	*/
	
	
	//___________________________________________________________________________________________
	// O P A C I T Y
	if (in_array(this.properties,'opacity')) {
		// report(" obj.faderCounter " +  obj.faderCounter + "\n")
		
		if (this.faderCounter <= 0) 	this.el.style.display = 'none'
		else 							this.el.style.display = this.display
		if (!document.all) {
			this.el.style.opacity   = this.faderCounter * 0.01;
			// report(" fader faderCounter:" +  this.faderCounter + " mode: " + mode + " cycle: " + this.cycle + " opacity: " + this.el.style.opacity + "<br>")
		} else {
			// report(this.el)
			this.el.style.filter   = 'alpha(opacity = '+ this.faderCounter + ')';
			l = this.el.childNodes.length
			for (i=0;i<l;i++) {
				child = this.el.childNodes[i]
				// report("ie")
				// report("child: " + child.nodeName)
				// if (!child.style) child.style.cssText = '';
				if (child.nodeType != 3) child.style.filter  = 'alpha(opacity = ' + this.faderCounter + ')';
			}
		}
	}
	
	//___________________________________________________________________________________________
	// P O S I T I O N
	if (in_array(obj.properties,'position')) {
		
		// alert("Animate position: offset_x " + this.P.offset_x)
		// report("this.faderCounter: "+this.faderCounter + " this.faderStep: " + this.limit)
		// report("factor: " + factor
		// report(this.offset_x)
		// report(this.offsetStart_x)
		// report('factor: ' + factor)
		
		if (!factor) factor = 0;
		// factor = 1;
		// report(this.el.id)
		this.el.style.left = parseInt(this.offset_x  + (factor * (this.offsetStart_x - this.offset_x))) + 'px';
		this.el.style.top  = parseInt(this.offset_y  + (factor * (this.offsetStart_y - this.offset_y))) + 'px';
		// report("faderC.: " + this.faderCounter  + ", offsetStart_x: " + this.offsetStart_x +  ", offset_x "+ this.offset_x + ", factor: " + factor + ", style.left: "+ this.el.style.left)
		
		//report("this.faderCounter: " + this.faderCounter  + " this.offset_y "+ this.offset_y + " this.el.style.top: " + this.el.style.top)
		/*
		if (parseInt(this.el.style.left) > document.body.clientWidth) {
			// alert(document.body.clientWidth + "kill")
			window.clearInterval(this.fInterval)
			this.fInterval = ''
		}
		*/
	}
	
	
	//___________________________________________________________________________________________
	// S I Z E
	if (in_array(obj.properties,'size')) {
		if (!factor) factor = 0;
		//if (factor) {
			this.el.style.width  = parseInt(this.offset_w  + (factor * (this.offsetStart_w - this.offset_w))) + 'px';
			this.el.style.height = parseInt(this.offset_h  + (factor * (this.offsetStart_h - this.offset_h))) + 'px';
			// report("this.faderCounter: " + this.faderCounter  + " this.offset_w "+ this.offset_w + " this.el.style.width: "  + this.el.style.width)
			// report("this.faderCounter: " + this.faderCounter  + " this.offset_h "+ this.offset_h + " this.el.style.height: " + this.el.style.height)
		//}
	}
}












// S T A T U S B A R  +statusbar
/* I N F O

*
*   status-Bar-Widget
*   Parameters:
*       displayMessageBlock:    	true/false, default: valse, Setzt, ob ein Nachrichtenfeld angelegt werden soll,
*       path:   					default: /cms/ajax_answer.php, der Pfad zur Datei, die über Ajax angesteuert werden soll
*       offset: 					der Startwert
*       noQuery: 					default: 0, If set to 1, no Ajax-Query will be started
*       max: 						default: 10, setzt maximale Schrittzahl.
*       displayText: 				default '', setzt den ersten im Nachrichtenfeld erscheinenden Text
*       wait:   					default: 1, sec, eine Verzögerung der Ajaxaufrufe
*       statusBar_style: 			default: '', CSS-Angaben zur Gestaltung der statusbar
*       statusBar_css: default: 	default_statusBar, CSS-Klasse zur Gestaltung der statusbar
*       statusMessage_style: 		default: '', CSS-Angabe zur Gestaltung des Nachrichtentextes
*       statusMessage_css: 			default: default_statusMessage, CSS-Klasse zur Gestaltung des Nachrichtentextes
*       statusInBar_style: 			default: '', CSS-Angabe zur Gestaltung des Statusbar-Balken
*       statusInBar_css: 			default: default_statusInBar, CSS-Klasse zur Gestaltung des Statusbar-Balken
*       statusBar_id: 				default: statusBarInner, ID des Statusbars
*       statusText_id: 				default: statusBarText, ID des Nachrichtentextes
*       jsFunc: 					Eine Javascript-Funktion, die beim Erstaufruf ausgeführt wird
*       jsOnEnd: 					Eine Javascript-Funktion, die nach dem letzten Durchlauf ausgeführt wird.
* 
*   Die aufgerufene Ajaxdatei kann entweder einen JSON-String oder eine Zahl zurückgeben
*   Die Zahl wird schlicht zum fortsetzen des Balkens verwendet. Ist die Zahl so groß oder
*   größer als die Zahl, die durch "max" festgelegt wurde, endet das Script.
*   Der JSON-String kann ein bis drei Elemente enthalten
*   {'vals':'12','displayText':'Ein Text mit blaj','jsFunc':'location.href=\"http://www.heise.de\"'}
*       vals: eine Zahl, die den Statusbalken vorantreibt (s.o.). Muß gegeben werden.
*       displayText:  Ein Text, der als Nachrichtentext eingetragen wird.
*       jsFunc: eine Javascript-Funktion oder ein Code, der asugeführt wird.
*
*/




var statusBarPar;
function statusBarObj(P) {
	this.params             = P;
    P.statusBar_style       ? this.params.statusBar_style       = 'style="'+P.statusBar_style+'"'       : this.params.statusBar_style       = '';
    P.statusBar_css         ? this.params.statusBar_css         = 'class="'+P.statusBar_css+'"'         : this.params.statusBar_css         = 'class="statusBarOuter"';
    P.statusMessage_style   ? this.params.statusMessage_style   = 'style="'+P.statusMessage_style+'"'   : this.params.statusMessage_style   = '';
    P.statusMessage_css     ? this.params.statusMessage_css     = 'class="'+P.statusMessage_css+'"'     : this.params.statusMessage_css     = 'class="statusBarMessage"';
    P.statusInBar_style     ? this.params.statusInBar_style     = 'style="'+P.statusInBar_style+'"'     : this.params.statusInBar_style     = '';
    P.statusInBar_css       ? this.params.statusInBar_css       = 'class="'+P.statusInBar_css+'"'       : this.params.statusInBar_css       = 'class="statusBarInner"';
	P.statusBar_id          ? this.params.statusBar_id          = P.statusBar_id                        : this.params.statusBar_id          = 'statusBarInner'; 
    P.statusText_id         ? this.params.statusText_id         = P.statusText_id                       : this.params.statusText_id         = 'statusBarMessage';
    P.offset                ? this.params.offset                = P.offset                       		: this.params.offset        		= '0.1';
    P.noQuery               ? this.params.noQuery               = P.noQuery                       		: this.params.noQuery         		= 0;
    P.wait                  ? this.params.wait                  = P.wait                           		: this.params.wait         			= 1;
	P.sq                  	? this.params.sq                  	= P.sq                           		: this.params.sq         			= '';
    this.valsC                                              	= 0;
   	if (!this.params.max) 	this.params.max = 100;
    this.buildStatusBar();
	var bwidth = this.calcBarWidth(this.params.offset,this.valsC,this.params.max)
	this.statusBarSetBar(bwidth,this.params.statusBar_id)
	that = this;
    this.interV = window.setInterval(function() {that.startStatusQuery('', that.params.offset, that.params)}, this.params.wait*1000)
}

// hier kommen die Ajax Daten an
statusBarObj.prototype.startStatusx = function(state, vals, params) {
  	this.valsC = vals;
	if (params.sq) report("startStatusx state:" + state + " this.valsC: " + this.valsC)
	// report("startStatusx state:" + state + " this.valsC: " + this.valsC)
}

statusBarObj.prototype.startStatusQuery = function(status, offset, params) {
 	statusBarPar = params;
	sq = ''
	var that      	= this
	var valsC     	= 0;
    var bwidth 		= 0;
	// Ergebnis: Json oder String
	if (String(this.valsC).match(/\{/g)) {
        // report("this.valsC is Json")
		var jsonRes                     = eval("("+this.valsC+")")
        valsC                           = jsonRes.vals
        if (jsonRes.displayText) 		{statusBarPar.displayText = jsonRes.displayText}
		if (jsonRes.jsFunc) 			{eval(jsonRes.jsFunc)}
	  } else {
        valsC                           = this.valsC
        if (!statusBarPar.displayText) 	{statusBarPar.displayText = ''}
        if (statusBarPar.jsFunc) 		{eval(statusBarPar.jsFunc)}
    }
	if (statusBarPar.displayMessageBlock) {
		document.getElementById(statusBarPar.statusText_id).innerHTML = statusBarPar.displayText
	}
	if (!valsC) valsC = 0; 
	if (params.sq) report("valsC: " + valsC)
   
  	// Statusbar berechnen und anzeigen
    bwidth = that.calcBarWidth(this.params.offset, valsC, this.params.max)
	if (params.sq) report("bwidth: " +  bwidth)
	// report("valsC: " + valsC + ", bwidth: " +  bwidth)
	
	
	
	// Groesse setzten
	that.statusBarSetBar(bwidth, statusBarPar.statusBar_id)
	
	// Weiter mit Ajax
	var path = params.path ? params.path : 'http://local/cargotest/cms/ajax_answer.php' // Warum setht das hier? Parameter sollten am Anfang gesetzt werden
	
	if (params.sq) {
		report("x valsC: "						+ valsC)
		report("parseInt(valsC): "				+ parseInt(valsC))
		report("parseInt(statusBarPar.max): " 	+ parseInt(statusBarPar.max))
		report("parseInt(valsC) < parseInt(statusBarPar.max) ? " + (parseInt(valsC) < parseInt(statusBarPar.max)))
	}
	if (parseInt(valsC) < parseInt(statusBarPar.max) && statusBarPar.noQuery != 1) {
		if (params.sq) report("new ajaxRequest: " + path)
		// report("new ajaxRequest: " + path)
		ajaxProcess = new ajax(path,function(state,vals) {that.startStatusx(state,vals,params)},'post',0,'','');
		// ajaxProcess = new ajax(path, function(state,vals) {alert("ok")},'post',0,'','');
	} else {
		if (sq) report("clearInterval")
		// report("clearInterval")
		clearInterval(this.interV)
        if (statusBarPar.jsOnEnd) {eval(statusBarPar.jsOnEnd)}
		document.getElementById(statusBarPar.statusBar_id).className = 'statusBarInnerFinish'
    }
}

statusBarObj.prototype.calcBarWidth = function(offset,valsC,valsMax) {
	sq = '';
	if (!valsC) valsC 	= 0;
	valsMax 			= '' + valsMax // in string umwandeln
	valsC 				= '' + valsC
	offset 				= '' + offset
	
	/* I N F O
		alle Werte, valsC + Offset muessen auf das Endformat (max) umgerechnet werden.
		alle Werte muessen passen, also offset, valsC, max immer einheitlich als flaot, integer, % oder px
		z. B.
		65px 		-> 65%
		65% 		-> 65%
		0.65		-> 0.65 von 1, 			1 	= 100% width des parentNode
		65			-> 0.65 von max			max = 100% width des parentNode
	
	offset 				= '20px'
	valsMax 			= '200px'
	valsC				= '190px'
	
	offset 				= '20%'
	valsMax 			= '100%'
	valsC				= '50%'
	
	offset 				= '0.3'
	valsMax 			= '1'
	valsC				= '0.9'
	
	offset 				= '3.9'
	valsMax 			= '4'
	valsC				= '3'
	*/
	
	// Werte angeleichen
	if (valsMax.indexOf('%') != -1) {
		if (offset.indexOf('%') == -1) offset = offset + '%'
		if (valsC.indexOf('%')  == -1) valsC  = valsC 	+ '%'
	}
	else if (valsMax.indexOf('px') != -1) {
		if (offset.indexOf('px') == -1) offset = offset + 'px'
		if (valsC.indexOf('px')  == -1) valsC  = valsC 	+ 'px'
	}
	else if (valsMax <= 1) {
		offset = parseFloat(offset)
		valsC  = parseFloat(valsC)
	} else {
		offset = parseFloat(offset)
		valsC  = parseFloat(valsC)
	}
	if (parseFloat(valsC) < parseFloat(offset)) valsC = offset; // wenn kleiner als offset, dann offset verwenden
	valsC = '' + valsC;
   // report("typeof(valsC): " + typeof(valsC))
	if 		(valsC.indexOf('px') != -1) 		bwidth = valsC
	else if (valsC.indexOf('%')  != -1) 		bwidth = valsC	    
	else 										bwidth = parseInt((100*(valsC/parseFloat(valsMax))))+'%';
   	if (sq) {
		report('valsMax: ' 	+ valsMax 	+ "\n" + 
				'offset: ' 	+ offset 			+ "\n" + 
				'valsC: '  	+ valsC 			+ "\n" + 
				'bwidth: '  + bwidth 			+ "\n"
		)
    }
	// report("calcBarWidth offset: " + offset + " valsC: " + valsC + " valsMax: " + valsMax + " bwidth: " + bwidth)
	return bwidth
}

statusBarObj.prototype.statusBarSetBar = function(bwidth,sid) {
	document.getElementById(sid).style.width = bwidth
}


statusBarObj.prototype.buildStatusBar = function(){
	var docW = '<div " '+this.params.statusBar_css+' '+this.params.statusBar_style+'><div '+this.params.statusInBar_css+' '+this.params.statusInBar_style+' id="'+this.params.statusBar_id+'"></div></div>'
	document.writeln(docW);
	//report("buildStatusBar docW: " + source(docW))
	if (this.params.displayMessageBlock) {
		var docW = '<div '+this.params.statusMessage_css+' '+this.params.statusMessage_style+' id="'+this.params.statusText_id+'"></div>'
       	document.writeln(docW);
		//report("buildStatusBar docW: " + source(docW))
    }
}












function producttipObj(P) {
	this.rootID = P.rootID
	if (!document.getElementById(this.rootID)) alert('productTipObj: rootID "'+this.rootID+'" not found, can\'t go on');
	P.step		? 	this.step 		= P.step		: this.step 		= 0
	P.cols		? 	this.cols 		= P.cols		: this.cols 		= 4
	P.elements  ? 	this.elements 	= P.elements	: this.elements 	= 0		 // Integer: Anzahl der Elemente
	P.elemWidth ? 	this.elemWidth 	= P.elemWidth	: this.elemWidth 	= 179
	P.leftShift ? 	this.leftShift 	= P.leftShift	: this.leftShift 	= -18	// Basisverschiebung des moveEl
	P.infotext ? 	this.infotext 	= P.infotext	: this.infotext 	= ''	// Products {n-m} of {m}
	this.maxStep 		= this.elements - this.cols
	this.interpolate 	= 1;
	this.moveEl  		= document.getElementById(this.rootID + '_mover')
	this.buttonLeft  	= document.getElementById(this.rootID + '_button_left')
	this.buttonRight 	= document.getElementById(this.rootID + '_button_right')
	this.infoEl 		= document.getElementById(this.rootID + '_infotext')
	// alert(this.infoEl.id)
	registerEventListenersObj(this.buttonLeft,  'mouseup', this, false, 'setStep', -1);
	registerEventListenersObj(this.buttonRight, 'mouseup', this, false, 'setStep', 1);
	// this.setStep('','',0)
}

producttipObj.prototype.setStep = function(e,el,direction) {
	// direction: 0  |  1  | -1
	this.step = this.step + direction
	if (this.step < 0) this.step = 0;
	if (this.step > this.maxStep) this.step = this.maxStep;
	newpos = this.step * this.elemWidth
	// this.el.style.left = parseInt(this.offset_x  + (factor * (this.offsetStart_x - this.offset_x))) + 'px';
	if (direction != 0) {
		// Interpolate?
		if (!this.interpolate) {
			this.moveEl.style.left = (-newpos + this.leftShift) + 'px'
		} else {
			fadestartPos = parseInt(this.moveEl.offsetLeft)
			fadePos		 = parseInt((-newpos + this.leftShift) + 'px')
			// report('fade from ' + fadestartPos + ' to ' + fadePos)
			// var fader = new faderObj({el:this.messageEl, mode:'out', properties:['opacity'], faderStep:1, limit:100, clearAfterFade:1, delay:this.livetime})
			var fader = new faderObj({			el:					this.moveEl, 
												mode:				'in', 
												faderStep:			10,
												properties:			['position'],
												offsetStart_x:		fadestartPos,
												offset_x:			fadePos,
												clearAfterFade:		0,
												accelerate:			0.5, // kleiner als 0.5! n % der Strecke
												decelarate:			0.5
											}) // ,'size','position'
		
			fader.fade();
		}
		// report("this.cols: " 				+ this.cols)
		// report("this.maxStep: " 			+ this.maxStep)
		// report("this.step: " 				+ this.step)
		// report("this.moveEl.style.left: " 	+ this.moveEl.style.left)
		// Anpassen des linken und rechten Randelementes
		var leftEl  = document.getElementById(this.rootID+'_element_' + (this.step))
		var rightEl = document.getElementById(this.rootID+'_element_' + (this.step + this.cols-1))
		//report("left: "  + this.rootID+'_element_'+this.step)
		// report("right: " + this.rootID+'_element_'+(this.step + this.cols))
		// report("leftEl.id: "  + leftEl.id)
		// report("rightEl.id: " + rightEl.id)
		// Shifts...vorher vergeben shift-classes entfernen
		for (var i=0; i<this.elements; i++) {
			var el = document.getElementById(this.rootID+'_element_'+ i)		//report("1 el.className: " + el.className)
			removeClassName(el,'shiftLeft')
			removeClassName(el,'shift')
		}
		addClassName(leftEl, 'shiftLeft') 	// link: Bild etwas verschieben
		addClassName(rightEl,'shift')		// rechts: Shoppingcart Icon + Bild etwas verschieben
		// report(this.step)
		
		var bLeft 	= document.getElementById(this.rootID + '_button_left')	 // Pfeilbuttons 
		var bRight 	= document.getElementById(this.rootID + '_button_right')
		
		// report("bLeft: " + bLeft  + " bRight"  + bRight)
		if (this.step == this.maxStep) 	addClassName(		bRight, 'inactive')
		else 							removeClassName(	bRight, 'inactive')
		if (this.step == 0) 			addClassName(		bLeft,  'inactive')
		else 							removeClassName(	bLeft,  'inactive')
		// Infotext anpassen, Bsp: 1-4 von 9
		var infotext = this.infotext
		infotext = this.infotext.replace('{n-m}',((this.step+1) + ' - ' + (this.step + this.cols))     )
		infotext = infotext.replace('{max}',this.elements)
		// report(infotext)
		this.infoEl.innerHTML = infotext
	}
}


