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']
	
	// 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)) {
		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) {
	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))
}

















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']
	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)
	// alert(this.parentForm.name)
	if (this.saveMode =='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
	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 
function dragObj(P) {
	/* I N F O 
	Erwartet ein Parameterobject {dragEl:dragEl...constrain_h:'20px', ...}
	-	dragEl
		das zu draggende ELement, wird erst nach Klick activert (this.activated)
	
	*/
	this.dragEl = document.getElementById(P.dragEl)
	// this.sq = 1
	if (!this.dragEl) alert("dragObj: no dragEl. Can't go on")
	// alert("this.dragEl.id " + this.dragEl.id)
	
	if (this.dragEl.style.position == 'relative') {
		this.parentEl = this.dragEl.parentNode	// wenn relative, dann mussen die Distancen in Bezug auf den Parent berechnet werden
		this.parentLeft = absLeft(this.parentEl)
		this.parentTop  = absTop(this.parentEl)
		// report(this.parentEl.nodeName + " parentEl coords:  " + this.parentLeft	+ ' ' + this.parentTop)
	}
	if(P.controlEl)	this.controlEl  = document.getElementById(P.controlEl) // ein anderes Element, dass als Ausloeser dient
	else 			this.controlEl  = this.dragEl
	// alert(this.controlEl.id)
	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
	
	// 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.width = this.dragEl.offsetWidth
	registerEventListenersObj(document, 	"mousedown",	this, false, 'startdrag');
	registerEventListenersObj(document, 	"mousemove",	this, false, 'drag');
	registerEventListenersObj(document, 	"mouseup",		this, false, 'stopdrag');											// alert(is_ie)
}

dragObj.prototype.startdrag = function(e) {
	// alert("startdrag")
	e  = (e) ? e : event;
	el = (e.target) ? e.target : e.srcElement;
	// report(this.controlEl.id + " " + this.dragEl.id)
	if (el == this.controlEl) {
		el = this.dragEl
		X = e.clientX
		Y = e.clientY
		// alert(  "clientX " 		+ e.clientX + "\n" + "clientY " 		+ e.clientY )
		if (this.call_startdrag) this.call_startdrag()
		this.activated = 1
		if (this.sq) report(el.id + "was activated<br>")
		// alert(this.dragEl.id)
		// this.OffsetLeft 	= parseInt(this.dragEl.offsetLeft) // wird in ie bis zum Rand, in Moz bis rum naechsten Blocllevel gerehcnet
		// this.OffsetTop 	 	= parseInt(this.dragEl.offsetTop) 
		this.OffsetLeft 	= parseInt(absLeft(this.dragEl))
		this.OffsetTop 	 	= parseInt(absTop(this.dragEl)) 
		this.dragdistLeft 	= X - this.OffsetLeft								// report(this.dragEl.offsetLeft + "  " + absLeft(this.dragEl))
		this.dragdistTop  	= Y - this.OffsetTop
		
		/*
		alert(	"startdrag " 	+ "\n" + 
				"clientX " 		+ e.clientX + "\n" + 
				"clientY " 		+ e.clientY + "\n" + 
				"OffsetLeft " 	+ this.OffsetLeft + "\n" + 
				"OffsetTop " 	+ this.OffsetTop + "\n" + 
				"dragdistLeft " + this.dragdistLeft + "\n" + 
				"dragdistTop "  + this.dragdistTop
		)
		*/
		if (!document.all) 	{e.preventDefault()} // wichtig fuer Moz, nicht den Griff anklicken!
		else 				{e.cancelBubble = true; e.returnValue = false}
	}
}
dragObj.prototype.drag = function(e) {
	e = (e) ? e : event;
	if (this.dragEl && this.activated){
		this.posH  = e.clientX - this.dragdistLeft
		this.posV  = e.clientY - this.dragdistTop
		// e.preventDefault();
		// e.cancelBubble = true
		
		// e.stopPropagation();
		if (this.dragEl.style.position == 'relative') {
			// report("dragEl " + this.posH + " " + this.posV + " parentEl " + this.parentEl.offsetLeft	 + ' ' +this.parentEl.offsetTop + "<br/>")
			this.posH = this.posH - this.parentLeft 		// relative Positionierung
			this.posV = this.posV - this.parentTop 
		}
		
		//report("this.maxLeft " + this.maxLeft.nodeName)
		
		// C O N S T R A I N S
		// 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)
		if (!this.constrainV) this.dragEl.style.left = this.posH + 'px'
		if (!this.constrainH) this.dragEl.style.top  = this.posV + 'px'
		if (this.call_drag) this.call_drag()
		// return false;
		//if (this.dragEl) {
		//if (document.all) return false;
		//e.cancelBubble = true;
		//e.preventDefault()
		//return false;
		// }
		if (!document.all) 	{e.preventDefault()} // wichtig fuer Moz, nicht den Griff anklicken!
		else 				{e.cancelBubble = true; e.returnValue = false}
	}
}

dragObj.prototype.stopdrag = function(e) {
	if (this.dragEl && this.activated){
		this.activated = 0
		if (this.call_stopdrag) this.call_stopdrag()
	}
}

















// ________________________________________________________________________________________________________________________________
// 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 url " + url)
	newUrl = modifyQueryString(url, 1, '', window.queryStr + ('&'+rootID + '_activeID='+activeID))	//alert("adjustLinkTarget newTargerurl "+newTargerurl)
	//alert(newUrl)
	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")			
		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';
    }
} 

