var colorMenuActive = "#0051a5";
var colorMenuInactive = "#7ba2ce";
var colorMenuHover = "#B2C8E2";

function getAmountToScroll()
{

	menuLayer = new PLayer("floatingMenuLayer",true);
	animHandler = new pAnim(menuLayer);
	animHandler.initPosTween(menuLayer.getX(),menuLayer.getY(),menuLayer.getX(),document.body.scrollTop + 50,15,10);
	animHandler.startPosTween(animHandler.LOOP_NORMAL,1);
	distance = (document.body.scrollTop + 50) - menuLayer.getY();
}

function reposThread()
{
	getAmountToScroll();
	setTimeout("reposThread()",500);
}

function init()
{
	if (top.frames && top.frames["menu"] && top.frames["menu"].document)
	{
		contentLocation = (new String(top.frames["content"].document.location));
		if (contentLocation.indexOf("01") != -1) top.frames["menu"].activateMenu("care");
		else if (contentLocation.indexOf("02") != -1) top.frames["menu"].activateMenu("patient");
		else if (contentLocation.indexOf("intern") != -1) top.frames["menu"].activateMenu("intern");
//		else if (contentLocation.indexOf("whatwecando") != -1) top.frames["menu"].activateMenu("whatwecando");
//		else if (contentLocation.indexOf("team") != -1) top.frames["menu"].activateMenu("team");
//		else if (contentLocation.indexOf("standard") != -1) top.frames["menu"].activateMenu("standard");
//		else if (contentLocation.indexOf("staff") != -1) top.frames["menu"].activateMenu("staff");
//		else if (contentLocation.indexOf("history") != -1) top.frames["menu"].activateMenu("history");		
//		else if (contentLocation.indexOf("future") != -1) top.frames["menu"].activateMenu("future");
//		else if (contentLocation.indexOf("basis") != -1) top.frames["menu"].activateMenu("basis");

		else top.frames["menu"].activateMenu("none");
	}
	else 
	{
		setTimeout("init()",1000);			
	}
}

insWiz = new inWin;
function inWin() { this.closed="true"; }
function popUp(URL,breite,hoehe)
{
	if (!insWiz.closed) insWiz.close();
	params = "width="+ breite + ",height=" + hoehe;
	insWiz = window.open(URL,"hans",params);
}

if (top.frames.length==0)
{
	top.document.location.href="/index.jsp?startPage="+document.location.href;
}
			


			
/**
 * Formular-Validierungsklasse.
 */
function FormValidator(formReference)
{
	this.formReference = formReference;
	this.errorHeader = new String();
	this.errorFooter = new String();
	this.errorMessage = new String();
	this.rulesCounter = 0;
	this.rules = new Array();
	this.failed = false;
	
	/**
	 * Setzt die überschrift der Fehlermeldung
	 */ 
	this.setErrorHeader = function(errorHeader)
	{
		this.errorHeader = errorHeader+"\n";
	}
	
	/**
	 * Setzt die Abschlussabsatz der Fehlermeldung
	 */
	this.setErrorFooter = function(errorFooter)
	{
		this.errorFooter = errorFooter+"\n";
	}
	
	/**
	 * Bindet an eine Formularelementreferenz einen validator.
	 * @param elementReference - HTML Formular-Element Referenz
	 * @param validator - Instanz-Referenz eines Validator-Plugins
	 */
	this.addRuleByElementReference = function(elementReference,validatorCallback)
	{
		this.rules[this.rulesCounter] = {reference: elementReference,validator: validatorCallback};
		this.rulesCounter++;
	}
	
	/**
	 * Bindet an eine Formularelementreferenz einen validator.
	 * @param elementReference - HTML Formular-Element Name 
	 *                          (Formular-Referenz muss in dem fall in dem Konstruktor angegeben werden)
	 * @param validator - Instanz-Referenz eines Validator-Plugins
	 */
	this.addRuleByElementName = function(elementName,validatorCallback)
	{
		this.rules[this.rulesCounter] = {reference: this.formReference[elementName],validator: validatorCallback};
		this.rulesCounter++;
	}

	/**
	 * Validiert alle Formular-Element bildungen. Falls ein Validierungsfehler auftritt, werden für alle
	 * Validierungsfehler eine Warnnachricht erstellt (abrufbar mit .getErrorMessage())
	 * 
	 * @return false bei Validierungsfehlern, true im Erfolgsfall.
	 */
	this.validateForm = function()
	{
		for (i=0; i<this.rulesCounter; i++)
		{
			this.errorMessage += this.rules[i].validator.validate(this.rules[i].reference);			
		}
		
		if (this.errorMessage == "")
		{
			this.failed = false;
			return (true);
		}
		else
		{
			this.failed = true;
			this.errorMessage = this.errorHeader+this.errorMessage+this.errorFooter;
		}
		return (false);
	}
	
	/**
	 * @return fehlermeldung als String, oder null falls Validierung erfolgreich war.
	 */ 
	this.getErrorMessage = function()
	{
		if (this.failed)
			return (this.errorMessage)
		else
			return (null);
	}
}


//////////////////////////////////////////////////////////////////////////////////////////////
// Plugins für FormValidator

/**
 * Text-Längen Validator-Plugin
 */
function TextLengthValidator(minLenght, maxLenght, errorMessage)
{
	this.errorMessage = errorMessage;
	this.minLenght = minLenght;
	this.maxLenght = maxLenght;
	
	this.validate = function(formReference)
	{
		if (formReference.value.length < this.minLenght || formReference.value.length > this.maxLenght)
			return (this.errorMessage+"\n")
		return ("");
	}
}

/**
 * Zahlenwert Validator-Plugin
 */
function IntegerLengthValidator(minLen,maxLen,errorMessage)
{
	this.minLen = minLen;
	this.maxLen = maxLen;
	this.errorMessage = errorMessage;
	
	this.validate = function(formReference)
	{
		if (!formReference.value.match(new RegExp ("[0-9]+")))
			return (this.errorMessage+"\n");
		if (this.minLen != 0 && this.maxLen != 0)
		{
			if (formReference.value < this.minLen || formReference.value > this.maxLen)
				return (this.errorMessage+"\n");
		}
		return ("");
	}
}

/**
 * PLZ Validator-Plugin
 */
function PLZValidator(errorMessage)
{
	this.errorMessage = errorMessage;
	this.validate = function(formReference)
	{
		if (!formReference.value.match(new RegExp ("[0-9]+")))
			return (this.errorMessage+"\n");
		if (formReference.value.length != 5)
				return (this.errorMessage+"\n");
		return ("");
	}
}


/**
 * Emailadressen Validator-Plugin
 */
function EmailValidator(errorMessage)
{
	this.errorMessage = errorMessage;
	this.validate = function(formReference)
	{
		if (!formReference.value.match(new RegExp (".+@.+[.].+")))
			return (this.errorMessage+"\n");
		return ("");
	}
}

/**
 * Emailadressen Validator-Plugin fuer nicht-muss-Felder. 
 */
function OptionalEmailValidator(errorMessage)
{
	this.errorMessage = errorMessage;
	this.validate = function(formReference)
	{
		if (!formReference.value || formReference.value=="") return ("");
		if (!formReference.value.match(new RegExp ("(.+@.+[.].+)")))
			return (this.errorMessage+"\n");
		return ("");
	}
}

/**
 * Plugin für die Validierung einer <select></select> auswahlliste. 
 * Überprüft in einer NON-Multiplechoice selectbox ein Eintrag 
 * ausgewält wurde
 */
function SelectValidator(errorMessage)
{
	this.errorMessage = errorMessage;
	
	this.validate = function(elementReference)
	{
		if (elementReference.selectedIndex == -1)
			return (this.errorMessage+"\n");
		else
			return ("");
	}
}

function PhoneValidator(errorMessage)
{
	this.errorMessage = errorMessage;
	
	this.validate = function(elementReference)
	{
		if (!elementReference.value || elementReference.value=="") return ("");
		
		if (!elementReference.value.match(new RegExp ("^0[0-9]+-[0-9]+$")))
			return (this.errorMessage+"\n");
		return (""); 
	}
}





var instcounter = 0;
var instanceArray = new Array();



function pLayerCollector()
{
	this.layerArray		=	new Array();
	this.add			=	pcAdd;
}
function pcAdd(layername,reference)
{
	this.layerArray[layername] = reference;
}
var totalLayers = new pLayerCollector();

////////////////////////////////////
// Klassenkonstruktor
function PLayer(layername,verbose)
{
	var retval = true;

	this.browser = new pBrowser();
	
	
	
	if (layername)
	{
		///////////////////////////////////////
		// Methoden
		this.show						=	pshow;					// layer anzeigen
		this.hide						=	phide;					// layer verstecken
		this.writedoc				=	pwrite;					// html ersetzen
		this.toggle					=	pToggle;
		this.moveTo					=	pmoveto;				// verschieben zu
		this.moveBy					=	pmoveby;				// verschieben um
		this.getWidth				=	pGetWidth;			// breite holen
		this.getHeight			=	pGetHeight;			// höhe holen
		this.setClip				=	pSetClip;				// Clipping setzen, no-go auf ie4+ aufm MAC
		this.getX						=	pGetX;					// x position holen
		this.getY						=	pGetY;					// y position holen
		this.getLayer				=	pGetLayer;			// construcotr, sucht den layer anhand des namens.

		this.getLayerReference		=	pGetLayerReference;
		this.getCSSReference			=	pGetCSSReference;
		
		this.getImage							=	pGetImage;		// ein bild aus dem layer holen (nur fuer ns4 sinnvoll)
		
		////////////////////////////////////////
		// Eigenschaften
		this.sweepHIn				=	null;				// Horizontal Sweepen
		this.sweepVIn				=	null;				// Vertical Sweepen
		this.devFlag				=	true;				// development flag
		this.debugFlag			= false 			// debugflag
		this.verbose 				= verbose;		// verbose-flag
		this.sweepX					=	0;					// sweep variable
		this.sweepY					=	0;					// sweep variable
		this.sweeping				=	false;			// sweep variable
		this.sweepsWaiting	=	0;					// sweep-stape-counter
		this.maxSweepCount	=	0;					// maximale anzahl der stapel fuer sweeps
		this.moving					= false;		// wird grad gemoved ? 
		
		this.object					= null;				// verweist auf den layer bzw. beim ie4 auf die style eigenschaft des layers
		this.docname				= layername;	// name des layers
		this.docref					=	null;				// verweist auf das layerdocument
		this.imgRef					= null;				// array auf images[], nur fuer ns sinnvoll
		
		
		this.styleReference			=	null;
		this.layerReference			=	null;
		this.layerName					=	layername;
		this.imageReference			=	null;
		
		this.visible						= true;			// sichtbarkeitsflag
		
		this.failed							= false;			// initialisierung erfolgreich ? 
		this.timeoutHandler  		= null;			// timeouthandler fuer sweep && scroll
		this.timeoutHandlerWait = null;			// ummm... weiss nicht mehr...
		
		
		if (this.browser.isMac && this.browser.isIe) 
			this.sweepHIn = pFakeSweep ; 
		else this.sweepHIn = pSweepHIn // Mac + IE -> umbiegen der sweeping funktionen
		
		if (this.browser.isMac && this.browser.isIe) 
			this.sweepVIn = pFakeSweep ; 
		else 
			this.sweepVIn = pSweepVIn; // Mac + IE -> umbiegen der sweeping funktionen
		
		this.sweepToggle		=	pSweepToggle;	// hin und her sweepen *g*
		
		//////////////////////////
		// Constructor...
		if (this.browser.isIe4) 
		{
			this.imageReference			= document.all
			this.layerReference			= this.getLayer(this.layerName)

			if (!this.layerReference) 
				this.failed = true;
			else 
				this.styleReference		= this.layerReference.style;
		}
		if (this.browser.isNs4)
		{
			this.layerReference			= this.getLayer(this.layerName);
			
			if (this.layerReference) 
			{
				this.imageReference 	= this.layerReference.document.images;
				this.styleReference		= this.layerReference; // double trouble
			}
			else 
			{
				this.failed = true;
			}
		}
		
		if (this.browser.isNs5 || this.browser.isKonqueror)
		{
			this.layerReference 		=	this.getLayer(this.layerName);
			if (this.layerReference)
			{
				this.imageReference			= 	document.images;
				this.styleReference			=	this.layerReference.style;			
			}
			else
			{
				this.failed = true;
			}
		}
		
		if (!this.failed)
		{
			this.startWidth		=this.getWidth();
			this.startHeight	=this.getHeight();
		}
	}
	
	if (this.failed) 
	{
		if (this.verbose) alert ("layer : "+layername+" was not found in DOM");
		this.show=this.hide=this.writedoc=this.getReference=this.moveTo=this.moveBy=this.debug=this.getWidth=this.getHeight=this.setClip=this.getX=this.getY=pTheMegaFooMaster;
	}

}

////////////////////////////////////////////////////////////////////////////////////////////7
// Methoden
/////////////////////////////////////////////////////////////////////////////////////////////
function pTheMegaFooMaster(){}

////////////////////////////////////////////////////////////////////////////////////////////
// 3.0
function pGetLayer(layerName,iteratorPos)
{
	var i;
	var retVal = false;
	var startingLayer = iteratorPos;
	if (!startingLayer) startingLayer = document.layers;
	
	
	if (this.browser.isNs4 && startingLayer.length != 0)
	{
		for (i=0; i<startingLayer.length; i++)
		{
			if (startingLayer[i].document.layers.length) retVal = this.getLayer (layerName,startingLayer[i].document.layers);
			if (!retVal) if (layerName == startingLayer[i].name) retVal = startingLayer[i];
		}
	}
	else
	{
		if (this.browser.isIe4) retVal = document.all[layerName];
		else retVal = startingLayer;
	}
	if (this.browser.isNs5 || this.browser.isKonqueror)
	{
		retVal = document.getElementById(layerName)
		
	}
	return (retVal);
}

/////////////////////////////////////////////////////////////////////////////////////////////
//
// Einfaden eines Layers -> keine funktionalitaet auf MAC / IE4.x
//
function pSweepHIn(step,delay,direction,selfFlag,lokinstance)
{

	// Klassenpointer aufm stack schieben bzw. zurueckholen.	
	instanceArray[instcounter] = this;
	if (!lokinstance) lokinstance = instcounter;
	instcounter++;


 	if (!this.sweeping || selfFlag)
	{
		if (this.sweepX > this.startWidth)
		{
			this.sweepX = 0;
			if (direction) this.setClip (0,0,this.startWidth,this.startHeight);
			else this.hide();
			this.sweeping = false;
			if (this.sweepsWaiting) this.sweepsWaiting--;
		}
		else
		{
			this.show();
			this.sweeping = true;
			if (direction)	this.setClip(0,0,this.sweepX,this.startHeight)
			else this.setClip(this.sweepX,0,this.startWidth,this.startHeight)
			this.sweepX = this.sweepX + step;
			this.timeoutHandler = setTimeout ("instanceArray["+lokinstance+"].sweepHIn("+step+","+delay+","+direction+",true,"+lokinstance+")",delay);
		}
	}
	else
	{
		if (this.sweepsWaiting < this.maxSweepCount)
		{
			this.sweepsWaiting++;
			setTimeout ("instanceArray["+lokinstance+"].sweepHIn("+step+","+delay+","+direction+",false,"+lokinstance+")",1000);
		}
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////
//
// Einfaden eines Layers -> keine funktionalitaet auf MAC / IE4.x
//
function pSweepVIn(step,delay,direction,selfFlag,lokinstance)
{
	// Klassenpointer aufm stack schieben bzw. zurueckholen.	
	instanceArray[instcounter] = this;
	if (!lokinstance) lokinstance = instcounter;
	instcounter++;

	if (!this.sweeping || selfFlag)
	{
		if (this.sweepY > this.startHeight)
		{
			this.sweepY = 0;
			if (direction) this.setClip (0,0,this.startWidth,this.startHeight);
			else this.hide();
			this.sweeping = false;
			if (this.sweepsWaiting) this.sweepsWaiting--;
		}
		else
		{
			this.show();
			this.sweeping = true;
			if (direction)	this.setClip(0,0,this.startWidth,this.sweepY)
			else this.setClip(0,this.sweepY,this.startWidth,this.startHeight)
			this.sweepY = this.sweepY + step;
			this.timeoutHandler = setTimeout ("instanceArray["+lokinstance+"].sweepVIn("+step+","+delay+","+direction+",true,"+lokinstance+")",delay);
		}
	}
	else
	{
		if (this.sweepsWaiting < this.maxSweepCount)
		{
			this.sweepsWaiting++;
			this.timeoutHandlerWait = setTimeout ("instanceArray["+lokinstance+"].sweepVIn("+step+","+delay+","+direction+",false,"+lokinstance+")",1000);
		}
	}
}


/////////////////////////////////////////////////////////////////////////////////////////////
//
// Fake Sweep methode fuer Inetrnet explorer 4.x auf MAC
//
function pFakeSweep(n1,n2,direction)
{
	if (direction) this.show()
	else this.hide()
}
function pSweepHOut(){} // Not Implemented!

////////////////////////////////////////////////////////////////////////////////////////////
// Clipping Setzen
// function pSetClip(left,top,right,bottom) IE STYLE!
//
function pSetClip (cleft,ctop,cright,cbottom)		// i prefer that order
{
	if (this.browser.isNs4)
	{
		this.layerReference.clip.left 	= 	cleft;
		this.layerReference.clip.top	= 	ctop;
		this.layerReference.clip.right	=	cright;
		this.layerReference.clip.bottom	=	cbottom;
	}
	if	(this.browser.isIe4 || this.browser.isNs5 || this.browser.isKonqueror) // konqueror not supportet here yet.... ask harri once more whats up with clipping.
		this.styleReference.clip = 'rect('+ctop+'px '+cright+'px '+cbottom+'px '+cleft+'px)';  // warum so rum ? 
}

//////////////////////////////////////////////////////////////////////////////////////////////
// Layer Anzeigen
//
function pshow() 
{
	if (this.browser.isNs4) this.layerReference.visibility = "show";
	if (this.browser.isNs5 || this.browser.isIe4 || this.browser.isKonqueror) this.styleReference.visibility = "visible";
	this.visible	=	true;
}

//////////////////////////////////////////////////////////////////////////////////////////////
// Layer verstecken
//
function phide() 
{
	if (this.browser.isNs4) this.layerReference.visibility = "hide";
	if (this.browser.isNs5 || this.browser.isIe4 || this.browser.isKonqueror) this.styleReference.visibility = "hidden";
	this.visible = false;
}

function pToggle()
{
	if (this.visible) this.hide();
	else this.show();
}

function pSweepToggle(step,delay,direction)
{
	if(direction)
	{
		if (this.visible) this.sweepVIn(step,delay,0);
		else this.sweepVIn(step,delay,1);
	}
	else
	{
		if (this.visible) this.sweepHIn(step,delay,0);
		else this.sweepHIn(step,delay,1);
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////
// Neuen content in einen Layer Schreiben
//
function pwrite (string)
{
	if (this.browser.isIe4 || this.browser.isNs5)
		this.layerReference.innerHTML=string;
		
	if (this.browser.isKonqueror)
	{
		for (i=0; i<document.getElementById(this.docname).childNodes.length; i++)
			document.getElementById(this.docname).removeChild(document.getElementById(this.docname).childNodes[i]);
		document.getElementById(this.docname).appendChild(document.createTextNode(string));
	}
	if (this.browser.isNs4)
	{		
		this.layerReference.document.write(string);
		this.layerReference.document.close();
	}
}


function pGetLayerReference()
{
	return (this.layerReference);
}

function pGetCSSReference()
{
	if (this.browser.isNs4) return (this.layerReference);
	else return (this.styleReference);
}


//////////////////////////////////////////////////////////////////////////////////////////////
// Layer um x/y pixel verschieben, funktioniert nur wenn
// layer auch ueber die API positioniert wurde..
//
function pmoveby(dx,dy)
{
	this.moving = true;
	if (this.browser.isIe4 || this.browser.isNs5 || this.browser.isKonqueror)
	{
		this.styleReference.left 	= (new String(this.layerReference.offsetLeft+dx))+"px";
		this.styleReference.top 	= (new String(this.layerReference.offsetTop+dy))+"px";
	}
	if (this.browser.isNs4)
	{
		this.layerReference.moveBy (dx,dy)
	}
	this.moving=false;
}


//////////////////////////////////////////////////////////////////////////////////////////////
// Positioniert einen Layer auf x/y
//
function pmoveto(x,y)
{
	
	if (this.browser.isIe4)
	{
		if (x) this.styleReference.pixelLeft = x;
		if (y) this.styleReference.pixelTop  = y;
	}
	if (this.browser.isNs4)
	{
		this.layerReference.moveTo (x,y);
	}
	
	if (this.browser.isNs5 || this.browser.isKonqueror)
	{
		if (x) this.styleReference.top 		= y+"px";
		if (y) this.styleReference.left 	= x+"px";
	}
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// position abfragen
// ie4-5 keine möglichkeit ein layer das durch die api nicht positioniert wuerde auf die
// konventionale art (.style) abzufragen. einzige möglichkeit besteht in dem root object selbst
// ueber offsets zu gehen. -> BETA!
//
function pGetX()
{
	if (this.browser.isNs4) retval = this.layerReference.left;
	if (this.browser.isIe4 || this.browser.isNs5 || this.browser.isKonqueror) retval = this.layerReference.offsetLeft;
	return retval;
}	
function pGetY()
{
	if (this.browser.isNs4) retval = this.layerReference.top;
	if (this.browser.isIe4 || this.browser.isNs5 || this.browser.isKonqueror) retval = this.layerReference.offsetTop;
	return retval;
}	

//////////////////////////////////////////////////////////////////////////////////////////////
// Gibt die breite des Layers zurueck
//
function pGetWidth()
{
	var retval;
	if (this.browser.isIe4 || this.browser.isNs5 || this.browser.isKonqueror) retval = this.layerReference.offsetWidth;
	if (this.browser.isNs4) retval = this.layerReference.clip.width;
	return (retval);
}

//////////////////////////////////////////////////////////////////////////////////////////////
// Gibt die Hoehe des Layers zurueck
//
function pGetHeight()
{
	var retval;
	if (this.browser.isIe4 || this.browser.isNs5 || this.browser.isKonqueror) retval = this.layerReference.offsetHeight;
	if (this.browser.isNs4) retval = this.layerReference.clip.height;
	return (retval);
}


//////////////////////////////////////////////////////////////////////////////////////////////
// Gibt die referenz auf das layerobjekt zurueck
//
function pGetReference()
{
	return (this.layerReference);
}

function pGetImage(imagename)
{
	return (this.imageReference[imagename]);
}


function pBrowser()
{

	
	this.isNs4 			= false;
	this.isNs5 			= false;
	this.isWin32 		= false;
	this.isIe4 			= false;
	this.isOpera		= false;
	this.isKonqueror 	= false;
	this.isMac			= false; 		  
	this.toString		= pBrowserDebug; // konqueror : toString must defined here, not below, dont ask me why....
	
	if (document.all) 		this.isIe4 = true;
	if (document.layers) 	this.isNs4 = true;
	if (navigator.appVersion.indexOf("Macintosh") != -1) 	this.isMac 			= true;
	if (navigator.userAgent.indexOf("Gecko") != -1)			
	{
		this.isNs5 			= true;
		this.isIe4			= false;
	}
	if (navigator.appVersion.indexOf("Win") != -1) 			this.isWin32 		= true;
	
	if (navigator.userAgent.indexOf("Konqueror") != -1)  	
	{
		this.isKonqueror	= true;
		this.isIe4			= false;
	}	
}


function pBrowserDebug()
{
	outstr = new String();
	
	outstr += "isIe4 : "		+this.isIe4			+"\n";
	outstr += "isNs4 : "		+this.isNs4			+"\n";
	outstr += "isNs5 : "		+this.isNs5			+"\n";
	outstr += "isWin32 : "		+this.isWin32		+"\n";
	outstr += "isMac : "		+this.isMac			+"\n";
	outstr += "isKonqueror:"	+this.isKonqueror	+"\n";
	
	return (outstr);

}





//////////////////////////////////////////////////////
// pAnim
// Construcotr

pAnimRefCounter = 0;
pAnimRefCollector = new Array();

function pAnim(pLayer)
{
	///////////////////
	// Methoden Public
	this.initPosTween			=	pInitScroll;			// initialisierung des Position-Tweenings (EXTERN)
	this.startPosTween		=	pStart;						// x/y position tweening starten (EXTERN)
	this.startRevTween		= pStartReverse;
	this.initPathAnim			=	pInitPathAnim;		// initialisierung der Pfad Animation (EXTERN)
	this.startPathAnim		=	pStartPathAnim;		// starten der Path-Animation (EXTERN)
	this.setDelay					=	pSetDelay;				// nachträglich fps / delay Seten (EXTERN && INTERN)


	////////////////////
	// Methoden Private
	this.scroll					=	pScroll;				// Scroll Thread (intern)
	this.checkScroll		=	pCheckScroll;		// tweening fertig ?  (intern)
	this.initFactors		=	pInitFactors;		// scale factors berechnen, bei x/y tweening. (intern)
	this.animate				=	pAnimate;				// pfad-animations-thread (INTERN)


	// Subklassen
	this.layer				=	pLayer;				// referen auf ein pLayer

	// Lineares Position Tweening:
	this.startX				=	null;				// Tweening : start x position
	this.startY				= 	null;			// Tweening : start y position
	this.endX					=	null;				// Tweening : destination x position
	this.endY					=	null;				// Tweening : destination y position
	this.delay				=	null;				// Tweening : delay between animation steps

	// Path Animation
	this.posArray				=	new Array();		// Path Anim : holds animation - path - coords array
	this.posIterator		=	null;						// Path Anim : position iterator
	this.animLength			=	null;						// Path Anim : holds total length of animation-steps


	// AnimRelated
	this.step					=	null;				// Tweening : initial step for position tweening
	this.stepx				=	null;				// Tweening : factorized step for position tweening
	this.stepy				=	null;				// Tweening : factorized step for position tweening
	this.x 						=	null;				// Common 	: current x position
	this.y						=	null;				// Common 	: current y position


	this.LOOP_NORMAL				=	1;					// Common 	: loop-type constants
	this.LOOP_REVERSE				=	2;					// Common 	: loop-type constants
	this.loop								= false;			// Common 	: Holds type of loop
	this.maxLoop						=	0;					// Common 	: maximum loops allowed
	this.currentLoop				=	0;					// Common 	: current loop counter
	this.directionx					=	null;				// Common 	: direction (true|false) (a>b|b>a)
	this.directiony					=	null;				// Common 	: direction (true|false) (a>b|b>a)
	this.timeoutHandler			= null;				// Common 	: reference to the thread handler
	this.scrollInitialized	=	false;			// Common 	: may we tween ? flag.

	this.instanceCounter = pAnimRefCounter;
	this.debug = true;

	pAnimRefCollector[this.instanceCounter] = this;
	pAnimRefCounter++;

}

//////////////////////////////////////////////////////
// alter the animation-step delay
function pSetDelay(delay)
{
	this.delay = delay;
}
//////////////////////////////////////////////////////
// initialize position-tweening
//
function pInitScroll(x1,y1,x2,y2,step,delay)
{
	// initialize counters, positions
	this.startX				=	x1;
	this.startY				= y1;
	this.endX					=	x2;
	this.endY					=	y2;
	this.delay				=	delay
	this.step					=	step;
	this.stepx				=	step;
	this.stepy				=	step;
	this.x 						=	this.startX;
	this.y						=	this.startY;
	this.initFactors();
	this.scrollInitialized	= 	true;
}

//////////////////////////////////////////////////////
// initialize Path-Animation
//
function pInitPathAnim(positionArray,delay)
{

	if (this.layer && positionArray.length)
	{
		this.animLength 	= 	positionArray.length;
		this.posArray		= 	positionArray;
		this.posIterator	=	0;
		this.x	=	this.posArray[0][0];
		this.y	=	this.posArray[0][1];
		this.setDelay (delay);

		// this.startPathAnim();
	}

}

//////////////////////////////////////////////////////
// initialize animation loop
//
function pStartPathAnim(loop,maxloop)
{
	this.loop 			= loop;
	this.maxLoop 		= maxloop;
	this.currentLoop 	= 0;
	this.layer.moveTo	(this.x,this.y)
	this.animate();
}

//////////////////////////////////////////////////////
// Animation Thread
//
function pAnimate()
{
	this.layer.moveTo(this.posArray[this.posIterator][0],this.posArray[this.posIterator][1])
	this.posIterator ++;
	if (this.posIterator >= this.animLength)
	{
		if (this.loop == false) return; // no looping

		if (this.loop == this.LOOP_NORMAL) // dont invert, reset counters and play animation.
		{
			this.posIterator = 0;
			this.currentLoop ++;
			if (this.currentLoop >= this.maxLoop) return; // max loop-count reached, exit.
		}

		if (this.loop == this.LOOP_REVERSE) // invert path and replay
		{
			this.posArray = invertArray (this.posArray)
			this.posIterator = 0;
			this.currentLoop ++;
			if (this.currentLoop >= this.maxLoop) return; // max loop-count reached, exit.
		}
	}
	setTimeout ("pAnimRefCollector["+this.instanceCounter+"].animate()",this.delay) // recurse animation.
}

//////////////////////////////////////////////////////
// Calculate Scale-Factors for Position Tweening
//
function pInitFactors()
{
	if (this.startX < this.endX) // check if motionvector are positive(true) or negative(false)
		this.directionx = true;
	else
		this.directionx = false;

	if (this.startY < this.endY) // check if motionvector are positive(true) or negative(false)
		this.directiony = true;
	else
		this.directiony = false;

	this.stepx = this.step;
	this.stepy = this.step;

	this.distanceX = Math.abs(this.endX-this.startX) // how far are we moving ?
	this.distanceY = Math.abs(this.endY-this.startY) // how far are we moving ?

	if (this.distanceX ==0)
	{
		this.stepx = 0;
		return(1);
	}
	if (this.distanceY ==0)
	{
		this.stepy = 0;
		return(1);
	}

	if (this.distanceX != this.distanceY) 	// make the shorter distances step matching the animation-length (based on the longest distance)
	{
		if (this.distanceX > this.distanceY)
			this.stepx = this.stepx * (this.distanceX / ((this.distanceY==0)?1:this.distanceY));
		else
			this.stepy = this.stepy * (this.distanceY / ((this.distanceX==0)?1:this.distanceX));
	}

}
//////////////////////////////////////////////////////
// end-position reached, looks funny.... ?
//
function pCheckScroll()
{
	return 	(
						(
							((this.directionx)?(this.endX>=this.x):(this.endX<=this.x))&&
							((this.directiony)?(this.endY>=this.y):(this.endY<=this.y))
						)
					);
}

//////////////////////////////////////////////////////
// Position Tweening Thread
//
function pScroll()
{
	// change position according to step and motion direction

	if (this.directionx)
		this.x += this.stepx;
	else
		this.x -= this.stepx;

	if (this.directiony)
		this.y += this.stepy;
	else
		this.y -= this.stepy;
	das = this;

	if (this.checkScroll()) // end pos reached ?
	{
		this.layer.moveTo(this.x,this.y);
		this.timeoutHandler = setTimeout ("pAnimRefCollector["+this.instanceCounter+"].scroll()",this.delay)
	}
	else // yep... done
	{
		clearTimeout (this.timeoutHandler) // release timeout mem for netscape (dumb animal!)
		this.layer.moveTo(this.endX,this.endY); // set the final coordinates
		if (this.loop) // loop enabled ?
		{
			if (this.loop == this.LOOP_NORMAL && (this.currentLoop < this.maxLoop - 1)) // restart anim, no invert
			{
				// this.initFactors(); // reinitialise factors and posisitons....
				this.x = this.startX;
				this.y = this.startY;
				this.layer.moveTo(this.startX,this.startY);

				this.currentLoop++;
				this.scroll(); // recall

			}
			if (this.loop == this.LOOP_REVERSE && (this.currentLoop < this.maxLoop - 1 )) // restart anim, reverse
			{


				temp = this.startX;
				this.startX = this.endX;
				this.endX = temp;
				temp = this.startY;
				this.startY = this.endY;
				this.endY	= temp;

				this.initFactors(); // recalculate move-directions

				this.x = this.startX;
				this.y = this.startY;
				this.layer.moveTo(this.startX,this.startY);

				this.currentLoop++;
				this.scroll(); // recall
			}
		}
	}
}

//////////////////////////////////////////////////////
// initialize position-tweening Thread
//
function pStart(loop,maxloop)
{
	if (this.scrollInitialized)
	{
		// initialise counters, positions and start the thread
		this.layer.moveTo(this.startX,this.startY);
		this.layer.show();
		this.currentLoop = 0;
		this.loop = loop;
		this.maxLoop = maxloop;
		this.x	= this.startX;
		this.y	= this.startY;
		this.initFactors();
		this.scroll();
	}
}

//////////////////////////////////////////////////////
// initialize reverse-position-tweening Thread
//
function pStartReverse(loop,maxloop)
{
	if (this.scrollInitialized)
	{
		// initialise counters, positions and start the thread
		this.layer.moveTo(this.startX,this.startY);
		this.layer.show();
		this.currentLoop = 0;
		this.loop = loop;
		this.maxLoop = maxloop;

		// reverse parameters
		rx = this.endX;
		ry = this.endY;
		this.endX = this.startX;
		this.endY = this.startY;
		this.startY = ry;
		this.startX = rx;

		this.x	= this.startX;
		this.y	= this.startY;
		this.initFactors();

		this.scroll();
	}
}


//////////////////////////////////////////////////////
//////////////////////// HELPERS /////////////////////


//////////////////////////////////////////////////////
// Invert the order of an array
//
function invertArray(array)
{
	tempArray = new Array();
	for (i=0;i<array.length; i++) tempArray[(array.length - i)-1] = array[i];
	return (tempArray);
}

function linearInterpolate(array,step)
{
	tempArray = new Array();
	for (i=0; i<array.length-1;i++)
	{
		for (j=0; j<step; j++)
		{
			x1 = array[i][0];
			x2 = array[i+1][0];

			y1 = array[i][1];
			y2 = array[i+1][1];

			dx = x2 - x1;
			dy = y2 - y1;
			tempArray[(step*i)+j] = [( x1 + ((dx/step)*j)),( y1 + ((dy/step)*j))]
		}
	}
	return (tempArray)
}


