﻿/**
 * Eve.DynamicLayers
 *
 * WAS STELLT DIESE DATEI ZUR VERFUEGUNG?
 *
 * 		- dynamische Layer, z. B. fuer besondere Dropdowns, Menuelayer, usw. ...
 *
 * WAS BENOETIGT DIESE DATEI?
 *
 * 		- jquery.js (jQuery-Framework)
 *		- Eve.js
 * 
 * BEISPIEL FUER DIE HTML-INITIALISIERUNG:
 *
 * 		<div class="eveJs">
 *			<input type="hidden" class="eveJsCfg" value="{ 'Eve.DynamicLayers' : { parameter:'value', listener:[{eventName:'change', functionName:'setToSameHeightAtRow', params:['eventimInfoPhotoRow']}]} }" />
 *			...
 * 		</div>
 *
 * LETZTE AENDERUNGEN:
 * 		
 * 		2010-11-10 12:00	Neues Profil fuer spiegelverkehrte Inhalte hinzugefuegt, da z. B. in Isreal der Textfluss
 * 							von Rechts nach Links gestaltet ist (hans-peter.beck@eventim.de)
 * 		2010-07-28 12:00	Den Aufruf der Methode trackHbxReInitialize() veraendert, es wird jetzt das DOM-Element des
 * 							Layers mitgegeben, da sich die Funktion der Methode gaendert hat und nun dieses erfordert
 * 							(hans-peter.beck@eventim.de).
 *		2010-01-19 11:10	In der Methode initializeLayer() ein Stopflag "this.reInitialize" eingerichtet, welches verhindert,
 *							dass bei nicht gefundenem Layer-Element by jQuery.ready die Methode im Dauer-Loop aufgerufen
 *							wird (hans-peter.beck@eventim.de).
 *		2010-01-07 11:25	Die Methode initializeLayer() so erweitert, dass Select-Tags automatisch in die ignoreElements-Liste
 *							aufgenommen wird (siehe Aenderung 2010-01-07 11:00). (hans-peter.beck@eventim.de)
 *		2010-01-07 11:00	In der Methode openLayer() fuer das ignoreElements-Feature einen "Bug" behoben. Dieses Feature soll ja
 *							verhindern, dass sollte auf eines der darin aufgefuehrten Elemente geklickt werden, das der Layer nicht
 *							zu geht. Es wurde daher immer das zuletzt angeklickte Element bzw. falscherweise dessen Parent zuerst geprueft
 *							und das urspruenglich ausloesende Element uebersprungen. Bei SELECT-Tags liefert der Firefox das OPTION-Tag
 *							und pruefte dann direkt das Select, was funktioniert, der IE liefert aber immer direkt das SELECT-Tag -
 *							auch, wenn man in eine OPTION geklickt hatte. Dies wurde nun behoben. (hans-peter.beck@eventim.de)
 *		2009-08-12 18:00	In der Methode checkModalLayerAndCreate() den bestehenden Workaround fuer alle IEs so angepasst, dass das
 *							iFrame nicht mehr per write() Inhalte bekommt, da es zu Fehlern kam, wenn document.domain in der Website
 *							geaendert wurde und somit der Inhalt des iFrames nicht mehr in der selben Domain lag, was nicht behebbar
 *							ist. (hans-peter.beck@eventim.de)
 *		2009-07-11 11:00	HBX-Support fuer geklonte Elemente in der Methode checkLayerAndCreate erweitert. Diese verlieren nach dem
 *							klonen die Referenz zu den Eventhandlern von HBX, daher wird jetzt danach HBX noch einmal reinitialisiert,
 *							um die Referenz wieder herzustellen (hans-peter.beck@eventim.de).
 *		2009-05-11 16:30	Integration der Eve.DynamicLayers.quickFx-Methode. (hans-peter.beck@eventim.de)
 *		2009-05-11 10:00	HBX-Support in die Methode openLayer() integriert. (hans-peter.beck@eventim.de)
 * 		2008-10-23 10:29	Erstellt (hans-peter.beck@eventim.de)
 *
 * Copyright 2008-2009 by CTS Eventim AG.
 */
 
// @HAPE: Weiter an setLayerPosition() arbeiten!


/**
 * Klasse fuer Layer-Funktionen
 *
 * Mit dieser Klasse koennen dynamische Layer erstellt werden, welche modal agieren koennen, Inhalte per HTML oder iFrame einbinden koennen
 * und vieles mehr. Weitere Informationen entnehmen Sie bitte den Optionen.
 *
 * CSS-Lock: Da es vorkommen kann, dass aus einem Layer heraus z. B. andere Layer geoffnet werden koennten und bei anklicken dieser
 *           theoretisch der aktuelle Layer den Fokus verlieren wuerde und sich schliessen wuerde, kann dies durch einen CSS-Lock
 *           verhindert werden, in dem einfach die CSS-Klasse "eveJsDynamicLayersLocked" auf den aktuellen Layer gesetzt wird.
 *
 * HBX-Tracking: In einigen Fällen, z. B. wenn auf einen Layer geklickt wird, soll der Click per HBX getrackt werden. Dazu befindet
 *               sich auf dem Link ein Attribut "name='&lid=...'". Kommt dieses Attribut vor, dann muss zusaetzlich noch das Tracking
 *               Script aufgerufen werden.
 *
 * @class	Eve.DynamicLayers
 * @base	Eve
 * @constructor
 * @param	{object}	options							Optionshash:
 * @param	{string}	options.layerEl					ID des zum Layer umzuwandelden Elements.
 * @param	{string}	options.layerReference			Optional: Bezugspunkt des zu erstellenden Layers (Default tl). Moegliche Werte vertikal t (Top), m (Middle), b (Bottom); horizontal l (Left), c (Center) r (Right). Die Wert definiert sich aus vertikaler und horizontaler Angabe. Funktioniert nicht mit der Option [constrained], diese setzt den Wert auf "mc".
 * @param	{string}	options.triggerEl				ID des Elementes, welches das Oeffnen des Layers ausloesen soll (Default none).
 * @param	{string}	options.triggerCss				Optional: CSS-Klasse(n) die solange, wie der Layer sichtbar ist, auf dem Trigger-Element gesetzt werden.
 * @param	{string}	options.openOn					Ausloeser fuer das oeffnen des Layers (Default mouseover). Moegliche Werte mouseover, click, none (kein Event zum Oeffnen auf dem Trigger Element).
 * @param	{string}	options.closeOn					Optional: Ausloeser fuer das schliessen des Layers (Default [options.openOn]). Moegliche Werte "mouseover", "click", "none" (kein Event zum Schliessen auf dem Trigger und Layer Element) ...
 * @param	{integer}	options.openDelay				Optional: Verzoegerung in Millisekunden bis der Layer geoeffnet wird (Default 0). Bei [openOn] gleich mouseover sinnvoll.
 * @param	{integer}	options.closeDelay				Optional: Verzoegerung in Millisekunden bis der Layer geschlossen wird (Default durch [openOn]-Type). 
 * @param	{boolean}	options.modal					Optional: Wenn true, wird Hintergrund hinter dem eigentlichen Layer gelegt (Default false). Eignet sich gut fuer Layerpopups...
 * @param	{string}	options.modalCss				Optional: CSS-Klasse(n) fuer den Hintergrundlayer (Default none).
 * @param	{string}	options.modalStyle				Optional: CSS-Style Attribut(e) fuer den Hintergrundlayer (Default none).
 * @param	{integer}	options.modalOpacity			Optional: Transparenzwert fuer den Hintergrund-Layer (Default 0, volle Transparenz).
 * @param	{boolean}	options.constrained				UNDONE > Optional: Wenn true, dann wird der Layer in der Mitte des sichtbaren Fensterinhaltes dargestellt (Default false). Ist der Fensterinhalt zu klein, wird von links oben an ausgerichtet.
 * @param	{boolean}	options.relative				UNDONE > Optional: Wenn true, dann scrolled der Layer in seiner relativen Position mit, wenn der Fensterinhalt veraendert wird (Default false). Nuetzlich bei [constrained].
 * @param	{boolean}	options.closeOutside			Optional: Wenn true, wird der Layer geschlossen, wenn die Maus außerhalb des Layers eine Aktion ausfuehrt (Default false). Abhaengig vom [openOn]-Typ.
 * @param	{string}	options.offsetEl				ID des Elements an dem der Layer ausgerichtet werden soll (Default [triggerEl]). Nicht erforderlich mit der Option [constrained].
 * @param	{string}	options.offsetElReference		Optional: Bezugspunkt des [offsetEl] an dem sich der Layer ausrichtet (Default tl). Moegliche Werte vertikal t (Top), m (Middle), b (Bottom); horizontal l (Left), c (Center) r (Right). Die Wert definiert sich aus vertikaler und horizontaler Angabe. Funktioniert nicht mit den Optionen [constrained] oder [relative].
 * @param	{integer}	options.offsetY					Optional: Offsetkorrektur in Bezug auf den vertikalen Abstand zum offsetEl (Default 0). Funktioniert nicht mit den Optionen [constrained] oder [relative].
 * @param	{integer}	options.offsetX					Optional: Offsetkorrektur in Bezug auf den horizontalen Abstand zum offsetEl (Default 0). Funktioniert nicht mit den Optionen [constrained] oder [relative].
 * @param	{string}	options.closeElements			Optional: jQuery-Selektor zusaetzlicher Elemente, welche - wenn angeklickt - die den Layer zusaetzlich schliessen sollen (Default none). Sinnvoll bei Layern die Schliessen-Buttons / - Symbole haben.
 * @param	{string}	options.openElements			Optional: jQuery-Selektor zusaetzlicher Elemente, welche - wenn angeklickt - die den Layer zusaetzlich oeffnen sollen (Default none).
 * @param	{string}	options.profile					Optional: Profile ermoeglichen Vorgegebene Konfigurationen fuer Layer an. Es ist somit moeglich standardisierte Layer Seitenweit konfigurierbar zu halten ohne alle Stellen aendern zu muessen, wenn sich Layer eines Profiles anders verhalten sollen (Default none).
 * @param	{integer}	options.depth					Optional: Tiefe des Layers - z-Index (Default 300).
 * @param	{string}	options.ignoreElements			Optional: Eine durch Leerzeichen getrennte Liste von DOM-Element-IDs, die falls ausserhalb des Layers (DOM-Tree) im Falle des [options.closeOutside]-Events nicht zum Schliessen des Layers fuehren (Default: none).
 *
 * @event	beforeOpen		Wird gefeuert, bevor der Layer geoeffnet wird.
 * @event	opened			Wird gefeuert, wenn der Layer geoffnet wurde.
 * @event	beforeClose		Wird gefeuert, bevor der Layer geschlossen wird.
 * @event	closed			Wird gefeuert, wenn der Layer geschlossen wurde.
 * @event	beforeDestroy	Wird gefeuert, bevor der Layer zerstoert (entfernt) wird.
 * @event	destroyed		Wird gefeuert, wenn der Layer zerstoert (entfernt) wurde.
 */
Eve.DynamicLayers = function(options) {
	
	/** Original-Options merken ..., man weiss ja nie, sowie validieren. */
	this.origOptions = options = options || {};
	
	/** Superclass-Constructor aufrufen, um alle veruegbaren Werte nutzen zu koennen, die dieser zur Verfuegung stellt ... */
	this.superclass(options);
	
	/** Defaults fuer Konfiguration */
	this.openOn            = options.openOn || 'mouseover';
	this.closeOn           = options.closeOn || this.openOn;
	this.openDelay         = options.openDelay || 0;
	this.modal             = options.modal || false;
	this.modalCss          = options.modalCss || false;
	this.modalStyle        = options.modalStyle || false;
	this.modalOpacity      = options.modalOpacity || 0;
	this.constrained       = options.constrained || false;
	this.relative          = options.relative || false;
	this.closeOutside      = options.closeOutside || false;
	this.offsetEl          = options.offsetEl || false;
	this.offsetElReference = options.offsetElReference || 'tl';
	this.offsetY           = options.offsetY || 0;
	this.offsetX           = options.offsetX || 0;
	this.layerEl           = options.layerEl || false;
	this.layerReference    = options.layerReference || 'tl';
	this.triggerEl         = options.triggerEl || false;
	this.profile           = options.profile || false;
	this.depth             = options.depth || 1000;
	this.closeDelay        = options.closeDelay || false;
	this.origCloseElements = this.closeElements = options.closeElements || false;
	this.origOpenElements  = this.openElements = options.openElements || false;
	this.triggerCss        = options.triggerCss || false;
	this.ignoreElements    = options.ignoreElements || '';
	
	/** Falls [containerEl] gesetzt ist, wurde die Klasse durch eveJs.initializeHtmlElements initialisiert. */
	if ((options.containerEl || false)) this.triggerEl = this.getElementId(options.containerEl);
	
	/** Wenn ein Profil angegeben wurde, dann die Vorgaben daraus in die Konfiguration uebernehmen. */
	if(this.profile) this.setProfile();
	
	/** Gibt es den openOn-Type ueberhaupt? */
	if (!(this.triggerOpenTypes[this.openOn] || false)) this.openOn = 'mouseover';
	
	/** Initialisieren des Layers */
	return this.initializeLayer();
};

Eve.DynamicLayers.prototype = {
	
	/** vordefinierte Profile */
	profiles : {
		
		/** typisches Popup als Layer fuer Eventim */
		'popupLayer' : {
			
			openOn         : 'click',
			openDelay      : 0,
			modal          : true,
			modalStyle     : 'background:#002C52 none;',
			modalOpacity   : 25,
			constrained    : true,
			relative       : true,
			closeOutside   : true,
			layerReference : 'mc'		// Vertikal middle, Horizontal center
		},
		
		/** typischer Mouse-Over-Layer */
		'simpleLayer' : {
			
			openOn            : 'mouseover',
			openDelay         : 100,
			offsetElReference : 'bl',	// Vertikal bottom, Horizontal left
			layerReference    : 'tl'	// Vertikal top, Horizontal left
		},
		
		/** typischer Mouse-Over-Layer spiegelverkehrt (z. B. fuer Isreal, da dort Textfluss andersrum) */
		'simpleLayerTurned' : {
			
			openOn            : 'mouseover',
			openDelay         : 100,
			offsetElReference : 'br',	// Vertikal bottom, Horizontal left
			layerReference    : 'tr'	// Vertikal top, Horizontal left
		},
		
		/** Layer der sich bei Click des Triggers oeffnet oder jeweils schliesst, bei Click in Layer schliesst und bei Click ausserhalb schliesst. */
		'clickLayerBottom' : {
			
			openOn            : 'click',
			offsetElReference : 'bl',	// Vertikal bottom, Horizontal left
			layerReference    : 'tl',	// Vertikal top, Horizontal left
			closeOutside      : true
		},
		
		/** wie 'clickLayerBottom', nur dass sich speziell der Layer bei Click NICHT schliesst. */
		'openOnlyByClickLayer' : {
			
			openOn            : 'click',
			closeOn           : 'none',
			offsetElReference : 'bl',	// Vertikal bottom, Horizontal left
			layerReference    : 'tl',	// Vertikal top, Horizontal left
			closeOutside      : true
		},
		
		/** wie 'clickLayerBottom', nur dass sich speziell der Layer bei Click NICHT schliesst. */
		'openCloseOnlyByClickLayer' : {
			
			openOn            : 'click',
			closeOn           : 'none',
			offsetElReference : 'bl',	// Vertikal bottom, Horizontal left
			layerReference    : 'tl',	// Vertikal top, Horizontal left
			closeOutside      : false
		}
		
	},
	
	/** Trigger Typen zum Oeffnen */
	triggerOpenTypes : {
		
		'mouseover' : 'mouseover',
		'click'     : 'click',
		'none'      : 'click'	// Auch wenn 'none' bedeutet, dass auf dem Trigger-Element kein Event gesetzt wird, so kann es ja noch [this.openElements] geben ...
	},
	
	/** Trigger Typen zum Schliessen */
	triggerCloseTypes : {
		
		'mouseover' : 'mouseout',
		'click'     : 'click',
		'none'      : 'click'	// Auch wenn 'none' bedeutet, dass auf dem Trigger/Layer-Element kein Event gesetzt wird, so kann es ja noch [this.closeElements] geben ...
	},
	
	/** Definition welche Elemente den Open-Trigger bei bestimmten Triggern bekommen. */
	triggerOpenElements : {
		
		'mouseover' : ['layerEl', 'triggerEl'],
		'click'     : ['triggerEl'],
		'none'      : []
	},
	
	/** Definition welche Elemente den Close-Trigger bei bestimmten Triggern bekommen. */
	triggerCloseElements : {
		
		'mouseover' : ['workLayerEl', 'triggerEl'],
		'click'     : ['workLayerEl'],
		'none'      : []
	},
	
	triggerToggleClose : {
		
		'mouseover' : false,
		'click'     : true,
		'none'      : false
	},
	
	/** Definition der Verzoegerung beim Schliessen eines Layers oder dem Uebergang vom Trigger-Element auf das Layerelement, sinnvoll bei mouseover. */
	triggerCloseDelays : {
		
		'mouseover' : 100,
		'click'     : 0,
		'none'      : 0
	},
	
	/** Definition der Verzoegerung beim Oeffnen eines Layers oder dem Uebergang vom Trigger-Element auf das Layerelement, sinnvoll bei mouseover. */
	triggerOpenDelays : {
		
		'mouseover' : 100,
		'click'     : 0,
		'none'      : 0
	},
	
	/** Register fuer aktive Verzoegerungs-Funktionen ... */
	activeDelayFunctions : [],
	
	/** Container fuer den Layer */
	workLayerEl : false,
	
	/** Kopie des Original-Layers */
	workLayerInnerEl : false,
	
	/** Modal-Layer */
	modalLayerEl : false,
	
	/** Referenz-Punkte in mathematischem Zusammenhang */
	mathRef : { t:0, m:1, b:2, l:0, c:1, r:2 },
	
	/** Layer da? */
	isOpen : false,
	
	/** Maus im Layer? */
	mouseIsOver : false,
	
	browserOffsetX : ((jQuery.browser.msie) ? 0 : ((jQuery.browser.mozilla && jQuery.browser.version.substr(0,4) != '1.9.') ? -1 : 0 ) ),
	
	browserOffsetY : ((jQuery.browser.msie) ? 0 : ((jQuery.browser.mozilla && jQuery.browser.version.substr(0,4) != '1.9.') ? -1 : 0 ) ),
	
	closeLock : false,
	
	/**
	 * Ergaenzt die Konfiguration des aktuellen Layers um die Vorgaben aus
	 * einem Profil, wenn vorhanden.
	 *
	 * @member	Eve.DynamicLayers
	 */
	setProfile : function() {
		
		/** Profil ermitteln ... */
		var tmpProfile = this.profiles[this.profile] || false;
		
		/** Wenn das Profile nicht existiert, dann Abbruch ... */
		if(!tmpProfile) return;
		
		/** Die Werte aus dem Profil in die aktuelle Konfiguration uebernehmen ... */
		for (var key in tmpProfile) this[key] = ((typeof this.origOptions[key] != 'undefined') ? this.origOptions[key] : (tmpProfile[key] || this[key]));
	},
	
	/**
	 * Initialisiert den zu erstellenden Layer, prueft ob dafuer alle notwendigen
	 * Angaben vorhanden sind und bereitet einige Anforderungen vor.
	 *
	 * @member	Eve.DynamicLayers
	 */
	initializeLayer : function() {
		
		/** Wurde kein Layer-Element angegeben, dann wird komplett abgebrochen. */
		if(!this.layerEl) return false;
		
		// Das DOM-Element ermitteln, wenn es keins gibt, dann nochmal versuchen es zu ermitteln, wenn das Dokument vollstaendig geladen wurde.
		// Wichtig, das neu ausprobieren darf nur einmal geschehen, da sich das Ganze sonst in einer Dauerschleife aufhaengt (this.reInitialize).
		var tmpLayerEl = false;
		
		if(!(tmpLayerEl = jQuery('#' + this.layerEl).get(0) || false) && !(this.reInitialize || false)) {
			
			// Merker setzen, dass nach onDocumentReady nochmal initialisiert wird.
			this.reInitialize = true;
			
			jQuery(function() { this.initializeLayer(); }.scope(this));
							
			return false;
			
		} else {
			
			this.layerEl = tmpLayerEl;
		}
		
		jQuery(this.layerEl).hide();
		
		/** Wurde kein Trigger-Element angegeben, dann wird komplett abgebrochen. */
		if(!this.triggerEl) return false;
		
		/** Das DOM-Element ermitteln, wenn es keins gibt, dan komplett abbrechen. */
		var tmpTriggerEl = false;
		
		if(!(tmpTriggerEl = jQuery('#' + this.triggerEl).get(0) || false)) {
			
			jQuery(function() { this.initializeLayer(); }.scope(this));
							
			return false;
			
		} else {
			
			this.triggerEl = tmpTriggerEl;
		}
		
		/** Zu ignorierende Elemente vormerken ... */
		var tmpIgnoreElements = (this.ignoreElements != '') ? this.ignoreElements.split(' ') : [] ;
		
		// Da Selects in einem Layer grundsaetzlich ignoriert werden sollten, da sie im IE/Safari sonst zu Fehlverhalten fuehren,
		// alle Selects aus dem Layer suchen und ggf. wenn keine ID vorhanden, eine ID draufsetzen und der Liste hinzufuegen.
		var tmpSelectsInLayer = jQuery(this.layerEl).find('select').each(function() {
			
			tmpIgnoreElements.push(eveJs.getElementId(this));
		});
		
		this.ignoreElements = false;
		
		if (tmpIgnoreElements.length > 0) {
			
			this.ignoreElements = {};
			for (var i = 0; i < tmpIgnoreElements.length; i++) this.ignoreElements[tmpIgnoreElements[i]] = true;	
		}
		
		/**
		 * Wenn normaler Darstellungsmodus, dann muss ein Offset-Element ermittelt werden, notfalls
		 * kann auch das Trigger-Element als Offset genommen werden.
		 */
		if (!this.constrained) {
			
			/** Offset-Element ermitteln, alternativ Layer-Element nehmen, gibts keins, Abbruch. */
			if(!(this.offsetEl = ((!this.offsetEl) ? this.triggerEl : jQuery('#' + this.offsetEl).get(0) || false ))) return false;
				
			/** Urspruengliches Offset merken ... */
			this.initialElOffset = this.getElementOffset(this.offsetEl);
		}
		
		/** Evtl. Offsets berechnen */
		this.calculateMathRef();
		
		/** Events initialisieren (Oeffnen / Schliessen) */
		this.initializeEvents();
	},
	
	/**
	 * Initialisiert die Events zum Oeffnen und Schliessen des Layers.
	 *
	 * @member	Eve.DynamicLayers
	 */
	initializeEvents : function() {
		
		/** Open/Close-Trigger Typen ermitteln ... */
		this.openTriggerType  = this.triggerOpenTypes[this.openOn];
		this.closeTriggerType = this.triggerCloseTypes[this.openOn];
		
		/** Event zum Oeffnen auf das Trigger Element setzen. */
		this.setUpOpenCloseEvents('open');
		
		/** Einige weitere Werte vorbereiten. */
		this.openDelay = this.openDelay || this.triggerOpenDelays[this.openOn] || 0;
		
		/** 
		 * Es waere wichtig zu pruefen, ob die Maus bei einem Maus-Over-Element bereits
		 * ueber dem Element ist, wenn ja, dann kann der Layer bereits jetzt geoeffnet
		 * werden! Dazu muss:
		 * 1. Rausgefunden werden wo, relativ zum Viewport die Maus ist.
		 * 2. Wo genau das TriggerElement relativ zum Viewport ist.
		 */
		 
		/** Bei [modal] bzw. [closeOutside] muessen noch weitere Close-Events gesetzt werden. */
		// COMING SOOON!
	},
	
	/**
	 * Im Safari-Browser gibt es einen Bug, sobald ein <select>-Dropdown angeklickt wird,
	 * signalisiert der Browser einen mouseOut-Effekt und dieser schliesst ggf. den Layer.
	 * 
	 * Wenn also this.closeOn = 'mouseover' ist, dann sollte dies durch eine Sperre verhindert
	 * werden.
	 *
	 * @member	Eve.DynamicLayers
	 */
	setCloseLock : function() {
		
		this.closeLock = true;
	},
	
	/**
	 * Siehe setCloseLock() ...
	 *
	 * @member	Eve.DynamicLayers
	 */
	removeCloseLock : function() {
		
		this.closeLock = false;
	},
	
	/**
	 * Setzt auf alle Select-Elemente eine Sperre, die das Schliessen des Layers verhindert, solange
	 * ein Select offen ist (nur im Mouseover-Mode).
	 *
	 * @member	Eve.DynamicLayers
	 * @param	{string}	openOrClose		"open" oder "close", bei open werden die Events gesetzt, bei close entfernt.
	 */
	setupLockEvents : function(openOrClose) {
		
		var bindMode = (((openOrClose || 'close') == 'open') ? 'bind' : 'unbind' );
		
		this.setLockEventFunction    = this.setLockEventFunction || this.setCloseLock.scope(this);
		this.unsetLockEventFunction  = this.unsetLockEventFunction || this.removeCloseLock.defer(25, this); // Mit Zeitverzoegerung, da im Safari sonst sofort ein onMouseOut geschmissen wird.
		
		if (this.closeOn == 'mouseover') {
			
			var tmpSelector = '#' + this.getElementId(this.workLayerEl) + ' select';
			
			jQuery(tmpSelector)[bindMode]('mouseover', this.setLockEventFunction);
			jQuery(tmpSelector)[bindMode]('mouseout', this.unsetLockEventFunction);
		}
	},
	
	/**
	 * Diese Methode versucht je nach uebergebenen [openOrClose]-Mode Events auf
	 * die Elemente zum schliessen oder oeffnen zu setzen ...
	 *
	 * @member	Eve.DynamicLayers
	 * @param	{string}	openOrClose		"open" oder "close" Modus, um die entsprechenden Events setzen zu koennen.
	 */
	setUpOpenCloseEvents : function(openOrClose, bindOrUndbind) {
		
		var bindOrUndbind = bindOrUndbind || 'bind';
		
		this.openLayerEventFunction  = this.openLayerEventFunction || this.openLayer.scope(this);
		this.closeLayerEventFunction = this.closeLayerEventFunction || this.closeLayer.scope(this);
		
		/** Oeffnen? */
		if ((openOrClose || '') == 'open') {
			
			var otherElements   = 'openElements';
			var onType          = this.openOn;
			var givenElements   = 'triggerOpenElements';
			var triggerType     = this.openTriggerType;
			var triggerFunction = this.openLayerEventFunction;
			
		} else {
			
			var otherElements   = 'closeElements';
			var onType          = this.closeOn;
			var givenElements   = 'triggerCloseElements';
			var triggerType     = this.closeTriggerType;
			var triggerFunction = this.closeLayerEventFunction;
		}
		
		/** 
		 * Wenn Oeffnen/Schliessen-Events gesetzt werden, dann noch speziell die [this.openElements]-Elemente
		 * beruecksichtigen, wenn gesetzt wurden, und im Register fuer [this.triggerOpenElements] als Indize
		 * merken und die Elemente selbst in [this] ueber das Indize ablegen.
		 *
		 * Sollten spaeter einmal Events entfernt werden sollen, ist dies somit kein Problem.
		 */
		if ((this[otherElements] || false)) {
			
			jQuery(this[otherElements]).each(function(pos, el) {
				
				var tmpId = "additional_" + otherElements + "_" + this.getElementId(el);
				
				this[givenElements][onType].push(tmpId);
				this[tmpId] = el;
				
			}.scope(this));
			
			/** Damit dieser Vorgang nur einmal stattfinden kann, Merker resetten ... */
			this[otherElements] = false;
		}
		
		var triggerElements = this[givenElements][onType] || [];
		
		/** Events setzen */
		for (var ctr in triggerElements) if ((this[triggerElements[ctr]] || false)) jQuery(this[triggerElements[ctr]])[bindOrUndbind](triggerType, triggerFunction);
	},
	
	/**
	 * Oeffnet den Layer und zeigt ihn an. Um dies zu tun, wird eingang geprueft ob der
	 * Layer bereits an das Ende des DOM-Elements verschoben wurde und existiert. Wenn
	 * nicht, dann wird dies zuvor getan.
	 *
	 * Weiterhin wird geprueft, ob es eine Verzoegerung gibt, wenn ja, wird allem voran
	 * die Verzoegerung durchgefuehrt, die nur closeLayer wieder aufheben kann.
	 *
	 * Sollte closeLayer ebenfalls eine Verzoegerung haben, zum Beispiel bei dem Trigger-Typ
	 * "mouseover", dann unterbricht openLayer diesen.
	 *
	 * HBX-Tracking: Immer wenn der Layer geoeffnet wurde und auf dem Link, der das Oeffnen
	 * ausloest das Attribute "name='&lid=...'" liegt, dann muss eine Tracking-Funktion
	 * aufgerufen werden.
	 *
	 * @member	Eve.DynamicLayers
	 * @return	Liefert immer false zurzueck, falls der Event auf einem Link liegt.
	 * @type	{boolean}
	 */
	openLayer : function(mode) {
		
		/** Evtl. Verzoegerungen stoppen! */
		this.cancelActiveDelayFunctions();
		
		/** Trigger, falls vorhanden, bluren ... */
		if (this.triggerEl) jQuery(this.triggerEl).blur();
		
		/** Wenn schon offen, dann Ende ... */
		if (this.isOpen) return;
		
		/** Pruefen ob der Layer schon am Ende des DOM-Trees existiert. */
		this.checkLayerAndCreate();
		
		/** Evtl. Delay pruefen und setzen ... */
		if (this.checkForDelayAndCreate(mode || false, this.openDelay || 0, 'openLayer')) return;
		
		/** Merker setzen, dass Layer offen ist! */
		this.isOpen = this.mouseIsOver = true;
		
		/** Layer (und (Background Layer) positionieren */
		this.setLayerPosition(true);
		
		/** Event auf das Fenster setzen, dass bei resize die Position neu berechnet werden muss! */
		this.onResizeFunction = this.setLayerPosition.scope(this);
		jQuery(window).bind('resize', this.onResizeFunction);
		
		/** Layer und Modal-Layer sichtbar machen ... */
		jQuery(this.modalLayerEl).show();
		jQuery(this.workLayerEl).show();
		
		
		/** Wenn getoggled werden soll, zwischen Open/Close, dann erstmal alle Events zuruecksetzen und dann neu setzen ... */
		if ((this.triggerToggleClose[this.openOn] || false)) {
		
			this.setUpOpenCloseEvents('open', 'unbind');
			this.setUpOpenCloseEvents('close', 'unbind');
			
			this.setUpOpenCloseEvents('close', 'bind');
		}
		
		/** 
		 * Wenn die Option [closeOutside] angegeben wurde, muss ein Click ausserhalb des Layers diesen 
		 * wieder schliessen, daher wird ein click-Event auf das Fenster gesetzt ... bzw. wenn modal
		 * true ist, dann auf den Modal-Layer bzw. den Body des iFrames wenn es ein IE.
		 */
		if (this.closeOutside) {
			
			this.closeOutsideFunction = function(e) {
				
				/** Nicht schliessen, wenn eines der zu ignorierenden Elemente angeklickt wurde ... */
				if (this.ignoreElements) {
					
					var actualNode = e.target;
					
					while (actualNode != false) {
						
						try {
							var tmpId = actualNode.getAttribute('id') || 'totalUnbekannteIdDieKeinerKennt';
						} catch(e) {
							var tmpId = 'totalUnbekannteIdDieKeinerKennt';
						}
						
						if ((this.ignoreElements[tmpId] || false)) return;
						
						actualNode = actualNode.parentNode || false;
						if (!actualNode || !(actualNode.getAttribute || false)) continue;
					}
				}
				
				/** Ist die Maus ausserhalb des Layers, dann Layer schliessen! */
				if(!this.mouseIsOver) this.closeLayer('done');
				
			}.scope(this);
			
			jQuery(document.body).bind('mousedown', this.closeOutsideFunction);
		}
		
		/**
		 * Wenn eine CSS-Klasse fuer das Trigger Element angegeben wurde, waehrend der Layer angezeigt wird,
		 * dann setze diese jetzt ...
		 */
		if (this.triggerCss && this.triggerEl) jQuery(this.triggerEl).addClass(this.triggerCss);
		
		/** Workaround fuer Safari-Select-Bug ... */
		this.setupLockEvents('open');
	},
	
	/**
	 * Schliesst den aktuellen Layer.
	 *
	 * Weiterhin wird geprueft, ob es eine Verzoegerung gibt, wenn ja, wird allem voran
	 * die Verzoegerung durchgefuehrt, die nur openLayer wieder aufheben kann.
	 *
	 * Sollte openLayer ebenfalls eine Verzoegerung haben, zum Beispiel bei dem Trigger-Typ
	 * "mouseover", dann unterbricht closeLayer diesen.
	 *
	 * @member	Eve.DynamicLayers
	 * @return	Liefert immer false zurzueck, falls der Event auf einem Link liegt.
	 * @type	{boolean}
	 */
	closeLayer : function(mode) {
		
		/** Evtl. Verzoegerungen stoppen! */
		this.cancelActiveDelayFunctions();
		
		/** Evtl. liegt eine Sperre vor, zum Beispiel zwecks Select-Safari-Bug ... */
		if (this.closeLock) return;
		
		/**
		 * Evtl. liegt eine weitere Sperre vor, zum Beispiel durch einen ueber dem Layer geoeffneten Dialog,
		 * welcher ansich im Dom-Tree nicht zum Layer gehoert, aber von der Funktion her aus einem Element des
		 * Layers heraus geoffnet wurde. Dies wird durch einen "CSS-Lock" erreicht. Der this.workLayerEl
		 * wurde dazu evtl. von einem unbekannten dritten mit der CSS-Klasse "eveJsDynamicLayersLocked"
		 * versehen. Solange diese CSS-Klasse auf dem Worklayer ist, wird dieser nicht geschlossen.
		 */
		if (jQuery(this.workLayerInnerEl).hasClass('eveJsDynamicLayersLocked')) return;
		
		/** Trigger, falls vorhanden, bluren ... */
		if (this.triggerEl) jQuery(this.triggerEl).blur();
		
		/** Wenn schon geschlossen, dann Ende ... */
		if (!this.isOpen) return;
		
		/** Evtl. Delay pruefen und setzen ... */
		if (this.checkForDelayAndCreate(mode || false, this.closeDelay || 0, 'closeLayer')) return;
		
		/** Event vom das Fenster entfernen, dass bei resize die Position nicht mehr neu berechnet werden muss! */
		if ((this.onResizeFunction  || false)) jQuery(window).unbind('resize', this.onResizeFunction);
		
		/** 
		 * Wenn die Option [closeOutside] angegeben wurde und eine this.closeOutsideFunction  existiert,
		 * dann Event nun wieder entfernen.
		 */
		if (this.closeOutside && (this.closeOutsideFunction  || false)) jQuery(document.body).unbind('mousedown', this.closeOutsideFunction);
		
		/** Wenn getoggled werden soll, zwischen Open/Close, dann erstmal alle Events zuruecksetzen und dann neu setzen ... */
		if ((this.triggerToggleClose[this.openOn] || false)) {
		
			this.setUpOpenCloseEvents('open', 'unbind');
			this.setUpOpenCloseEvents('close', 'unbind');
			
			this.setUpOpenCloseEvents('open', 'bind');
		}
		
		/**
		 * Wenn eine CSS-Klasse fuer das Trigger Element angegeben wurde, waehrend der Layer angezeigt wird,
		 * dann setze diese jetzt ...
		 */
		if (this.triggerCss && this.triggerEl) jQuery(this.triggerEl).removeClass(this.triggerCss);
		
		
		jQuery(this.workLayerEl).hide();
		jQuery(this.modalLayerEl).hide();
		
		/** Merker setzen, dass Layer geschlossen wurde... */
		this.isOpen = this.mouseIsOver = false;
		
		/** Workaround fuer Safari-Select-Bug ... */
		this.setupLockEvents('close');
	},
	
	/**
	 * Unterbricht, wenn entsprechende Timeout-Funktionen vorhanden, den Timeout.
	 *
	 * @member	Eve.DynamicLayers
	 */
	cancelActiveDelayFunctions : function() {
		
		/** Alle vorhandenen aktiven Delays abbrechen ... */
		for (var tmpDelayFunction in this.activeDelayFunctions) if((this.activeDelayFunctions[tmpDelayFunction].cancelTimeout || false)) this.activeDelayFunctions[tmpDelayFunction].cancelTimeout();
		
		/** Reset */
		this.activeDelayFunctions = [];
	},
	
	/**
	 * Wenn kein [mode] gesetzt ist, aber es einen [delay] hoeher 0 gibt, dann die uebergebene
	 * [delayFunction] mit Verzoegerung erneut aufrufen und dabei den setzen, damit der Delay kein
	 * zweites mal erstellt wird, wenn checkForDelayAndCreate erneut aufgerufen wird.
	 *
	 * @member	Eve.DynamicLayers
	 * @private
	 * @param	{string}	mode			Ist der mode leer und der delay hoeher als 0, wird eine Verzoegerung erstellt. Andernfalls nicht.
	 * @param	{integer}	delay			Verzoegerung in Millsekunden (Default 0).
	 * @param	{string}	delayFunction	Name der Funktion die nach der Verzoegerung aufgerufen werden soll.
	 * @return	Liefert true zurueck, wenn ein Delay erstellt wurde, andernfalls false.
	 * @type	{boolean}
	 */
	checkForDelayAndCreate : function(mode, delay, delayFunction) {
		
		if ((mode || '') != 'done' && delay > 0) {
			
			var tmpFunction = this[delayFunction].defer(delay, this, true, ['done']);
			
			this.activeDelayFunctions.push(tmpFunction);
			
			tmpFunction();
			
			return true;
			
		} else {
			
			return false;
		}
	},
	
	/**
	 * Prueft ob der anzuzeigende Layer als Kopie am Ende des DOM-Trees erstellt wurde,
	 * wenn nicht, wird dies nachgeholt.
	 *
	 * @member	Eve.DynamicLayers
	 */
	checkLayerAndCreate : function() {
		
		/** Wenn der Work-Layer bereits existiert, dann fertig ... */
		if (this.workLayerEl) return;
		
		/** Pruefen ob, wenn gewuenscht, der Modal-Layer vorhanden ist ..., wenn nicht, wird er erstellt. */
		this.checkModalLayerAndCreate();
		
		/** Layer clonen, inkl. Events (das ist wichtig, zwecks zuvor gesetzter Events fuer den Layer) ... */
		this.workLayerEl = document.createElement('div');
		this.workLayerInnerEl = jQuery(this.layerEl).clone(true).get(0);
		jQuery(this.workLayerInnerEl).appendTo(this.workLayerEl);
		
		/** Tiefe (z-index) des Layers setzen ... */
		this.workLayerEl.style.zIndex           = this.depth + 1;
		this.workLayerEl.style['position']      = 'absolute';
		this.workLayerEl.style.textAlign        = 'left';
		this.workLayerInnerEl.style['position'] = 'relative';
		this.workLayerInnerEl.style['top']      = '0px';
		this.workLayerInnerEl.style['left']     = '0px';
		
		/** Da IDs nicht doppelt vorkommen duerfen, wird der Original-Layer entfernt. */
		jQuery(this.layerEl).remove();
		
		/** Erstmal sicherstellen, dass der Work-Layer nicht sichtbar ist, der Inhalt aber schon. */
		jQuery(this.workLayerEl).hide();
		jQuery(this.workLayerInnerEl).show();
		
		/** Layer ans Ende des DOM-Trees setzen ... */
		jQuery(this.workLayerEl).appendTo('body');
		
		/** Element ermitteln, welches den Close-Trigger bekommen soll. */
		this.setUpOpenCloseEvents('close');
		
		/** Einige weitere Werte vorbereiten. */
		this.closeDelay = this.closeDelay || this.triggerCloseDelays[this.openOn] || 0;
		
		/** Auf den Layer noch einige zusaetzliche Events setzen, um immer zu wissen, ob die Maus innerhalb oder ausserhalb ist ... */
		jQuery(this.workLayerEl).mouseover(function() { this.mouseIsOver = true; }.scope(this));
		jQuery(this.workLayerEl).mouseout(function() { this.mouseIsOver = false; }.scope(this));
		
		if (this.triggerEl) {
			
			jQuery(this.triggerEl).mouseover(function() { this.mouseIsOver = true; }.scope(this));
			jQuery(this.triggerEl).mouseout(function() { this.mouseIsOver = false; }.scope(this));		 
		}
		
		// Noch Formvalidierung usw. drauf haun, wenn benoetigt
		var tmpFunc = function() {
			
			var tmpId = '#' + eveJs.getElementId(this.workLayerInnerEl);
			
			jQuery(tmpId + ' form').removeClass('ignoreBecauseLayer');
			
			eveJs.inputAltInitialize('#' + eveJs.getElementId(this.workLayerInnerEl));
			
		}.defer(10, this);
		
		// Verzoegert ausfuehren, da es sonst nicht funktioniert...
		tmpFunc();
		
		// Da die urspruenglichen Inhalte gecloned wurden, sind die Referenzen von HBX zu evtl. Links
		// nicht mehr gegeben, daher HBX reinitialisieren.
		if((trackReInitialize || false)) trackReInitialize(this.workLayerEl);
	},
	
	/**
	 * Prueft ob ein Modal-Layer angezeigt werden soll und dieser im DOM-Tree bereits existiert,
	 * wenn nicht wird er erstellt. Dabei ist es wichtig, dass fuer den IE6 ein iFrame im Hintergrund
	 * erstellt wird, bei allen anderen Browsern lediglich ein DIV-Element.
	 *
	 * Wichtig: Layer muessen im IE grundsaetzlich ein iFrame als Background haben, um durchscheinende
	 * SELECTS zu verhindern.
	 *
	 * Da also grundsaetzlich ein Hintergrund-Layer vorhanden sein muss, muss je nach [modal]-Status
	 * nur entschieden werden wo und wie gross dieser platziert werden muesste, welche Farbe er hat
	 * und so weiter.
	 *
	 * Wenn [modal] gleich true ist, dann werden auch evtl. Styles und CSS-Klassen auf den Modal-Layer
	 * gesetzt, sowie Transparenz-Werte, usw...
	 *
	 * @member	Eve.DynamicLayers
	 */
	checkModalLayerAndCreate : function() {
		
		/** Wenn schon einer erstellt wurde, dann brauch es nicht noch einen ... */
		if (this.modalLayerEl) return;
		
		this.modalLayerClickEl = this.modalLayerEl = document.createElement('div');
		this.modalLayerId = this.getElementId(this.modalLayerEl);
		
		this.modalLayerEl.style['z-index']    = this.depth;
		this.modalLayerEl.style['position']   = 'absolute';
		this.modalLayerEl.style['background'] = 'transparent none';
		
		jQuery(this.modalLayerEl).appendTo('body');
		
		jQuery(this.modalLayerEl).hide();
		
		if (jQuery.browser.msie) {
		
			this.modalLayerIframeId = this.modalLayerId+'Iframe';
			
			/** iFrame erzeugen ... */
			jQuery(this.modalLayerEl).append('<iframe id="' + this.modalLayerIframeId + '" name="' + this.modalLayerIframeId + '" style="width:100%; height:100%; background:'+this.modalLayerEl.style['background']+';' + (this.modalStyle || '') + '" framespacing="0" frameborder="0" border"0" src="'+eveJsIframeBlank+'"></iframe>');
			this.modalLayerElIframe = jQuery('#' + this.modalLayerIframeId).get(0);
			
		}
			
		
		/** Wenn der Layer [modal] ist, dann pruefe ob evtl. noch Transparenz-Werte oder sonstige CSS-Klassen oder Styles zu setzen sind ... */
		if (this.modal) {
			
			/** Opacity */
			this.setAlpha(this.modalLayerEl, this.modalOpacity);
			
			/** Modal CSS Style? */
			if (this.modalStyle) this.modalLayerEl.setAttribute('style', this.modalStyle);
			
			/** Modal CSS Class? */
			if (this.modalCss) this.modalLayerEl.className = this.modalCss;
			
			/** Close on click modal layer? */
			if (this.closeOutside) jQuery(this.modalLayerClickEl).click(this.closeLayer.scope(this));
			
		} else {
			
			this.setAlpha(this.modalLayerEl, 0);
		}
	},	
	
	/**
	 * Positioniert den Layer an die gewuenschte Stelle. Auch der Hintergrund-Layer wird
	 * an die gewuenschte Stelle gesetzt und in der Groesse angepasst. Bei [modal] gleich 
	 * true, wird der Hintegrund-Layer auf die gesamte Hoehe und Breite des Fensters gesetzt
	 * und oben links im Dokument platziert.
	 *
	 * @member	Eve.DynamicLayers
	 * @param	{boolean}	initial		Wenn true, werden Groessen und Positionen gesetzt, andernfalls nur Positionen, um Ressourcen zu sparen.
	 */
	setLayerPosition : function(initial) {
		
		/** Wenn Layer nicht offen, dann brauch auch nix bewegt werden ... */
		if(!this.isOpen) return;
		
		var initial = initial || false;
		
		/** Layer positionieren ..., liefert die Position des Layers zurueck. */
		this.updateLayerPosition(initial);
	},
	
	/**
	 * Unter Beruecksichtigung der Bezugspunkte des Offset-Elements und des Layerelements
	 * (insofern nicht constrained aktiv ist) muss der Layer nun positioniert werden.
	 *
	 * @member	Eve.DynamicLayers
	 * @param	{boolean}	initial		Wenn true, dann ist dies die erste Berechnung in der auch Groessen beruecksichtigt werden.
	 */
	updateLayerPosition : function(initial) {
		
		var initial = initial || false;
		
		if (!this.constrained) {
			
			/** Position des Offset-Elements in der Website ermitteln ... */
			var layerOffset = jQuery(this.offsetEl).offset();
			
			/** Verschiebung an Hand der Referenzpunkte des Layer- und Offset-Elements berechnen ... */
			var offsetElOffset = { top : Math.ceil(jQuery(this.offsetEl).height() * this.offsetVerRef), left : Math.ceil(jQuery(this.offsetEl).width() * this.offsetHorRef) };
			var layerElOffset  = { top : Math.ceil(jQuery(this.workLayerEl).height() * this.layerVerRef), left : Math.ceil(jQuery(this.workLayerEl).width() * this.layerHorRef) };
			
			this.realLayerOffset = {
				
				top  : layerOffset.top + offsetElOffset.top + layerElOffset.top + this.browserOffsetY + this.offsetY,
				left : layerOffset.left + offsetElOffset.left + layerElOffset.left + this.browserOffsetX + this.offsetX
			};
			
			/** 
			 * NOT DONE YET!
			 * Wenn der Layer nach unten ausserhalb der Seite sein sollte, dann muss umgerechnet werden und der Layer oben hoeher angezeigt werden, 
			 * aber nur, wenn es ein Offset-Element gibt ...
			 */
			/**
			if (this.getPageHeight() < (this.realLayerOffset.top + jQuery(this.workLayerEl).height())) {
				
				// Werte der Referenz-Punkte umdrehen
				var origOffsetElReference = this.offsetElReference;
				var tmpOffsetReference    = origOffsetElReference.split('');
				this.offsetElReference    = 't' + tmpOffsetReference[1];
				
				var origLayerReference = this.layerReference;
				var tmpLayerReference  = origLayerReference.split('');
				this.layerReference    = 'b' + tmpLayerReference[1];
				
				this.offsetY = (this.offsetY * (-1));
				this.calculateMathRef();
				
				// Neu berechnen und Positionieren
				this.updateLayerPosition(initial);
				
				// Original-Werte wieder herstellen
				this.offsetElReference = origOffsetElReference;
				this.layerReference    = origLayerReference;
				
				this.offsetY = (this.offsetY * (-1));
				this.calculateMathRef();
				
				return;
			};
			*/
			
		} else {
			
			// Constrained Mode not done yet!
			/** @todo: Fertigstellen! */
		}
		
		/** Vor dem Verschieben die Seitenhoehe merken ... */
		var origPageHeight = this.getPageHeight();
		
		this.workLayerEl.style.top  = this.realLayerOffset.top + 'px';
		this.workLayerEl.style.left = this.realLayerOffset.left + 'px';
		
		/** Background Layer positionieren und Groesse anpassen ... */
		this.updateModalPosition(initial, this.realLayerOffset);
		
		/** Nun noch ueberpruefen ob das Element im "Sichtbaren Bereich liegt ... */
		var tmpFunction = function() {
			
			var scrollTop = this.getScrollPosition().top;
			var windowHeight = this.getInnerWindowSize().height;
			var elTop = jQuery(this.workLayerEl).offset().top;
			var elHeight = jQuery(this.workLayerEl).height();
			
			var scrollBottom = scrollTop + windowHeight;
			var elBottom = elTop + elHeight;
			
			if(scrollTop > elTop ) {
				
				this.scrollToElement(this.workLayerEl, 500, false, -10);
			
			} else if (scrollBottom < elBottom) {
				
				if(origPageHeight < elBottom) {
					
					var tmpCfg = { parent : this, scrollByPx : (elBottom - scrollBottom) };
					
					var scrollToFunction = function() {
						
						if (this.scrollByPx <= 0) return;
						
						var tmpLower = Math.ceil(this.scrollByPx / 10);
						this.scrollByPx -= tmpLower;
						
						window.scrollBy(0, tmpLower);
						
						scrollToFunction();
						
					}.defer(10, tmpCfg, false);
					
					scrollToFunction();
					
				} else {
				
					this.scrollToElement(scrollTop + (elBottom - scrollBottom), 500, false, 25);
				}
			}
			
		}.defer(25, this);
		
		tmpFunction();
	},
	
	/**
	 * Positioniert den Modal-Layer (Background Layer), sowie passt ggf. die Groesse an.
	 *
	 * @member	Eve.DynamicLayers
	 * @param	{boolean}	initial		Wenn true, werden Groessen und Positionen gesetzt, andernfalls nur Positionen, um Ressourcen zu sparen.
	 */
	updateModalPosition : function(initial, layerOffset) {
		
		var initial = initial || false;
		
		if (this.modal) {
			
			if (initial) {
				
				this.modalLayerEl.style['height'] = this.getPageHeight() + 'px';
				this.modalLayerEl.style['width']  = '100%';
				this.modalLayerEl.style['top']    = '0px';
				this.modalLayerEl.style['left']   = '0px';
			}
			
		} else {
			
			if (initial) {
			
				var actualLayerSize = { height : jQuery(this.workLayerEl).height(), width : jQuery(this.workLayerEl).width() };
				
				this.modalLayerEl.style['height'] = actualLayerSize.height + 'px';
				this.modalLayerEl.style['width']  = actualLayerSize.width + 'px';
				
				if(jQuery.browser.msie) {
					
					this.modalLayerElIframe.style['height'] = actualLayerSize.height + 'px';
					this.modalLayerElIframe.style['width']  = actualLayerSize.width + 'px';
				}
			}
			
			/** Hier evtl. einfach den Style vom this.workLayerEl uebernehmen, anstatt es neu zu berechnen ... */
			var layerOffset = layerOffset ||jQuery(this.workLayerEl).offset();
			
			this.modalLayerEl.style['top']    = layerOffset.top + 'px';
			this.modalLayerEl.style['left']   = layerOffset.left + 'px';
		}
	},
	
	
	/**
	 * Berechnet an Hand der Referenz-Punkte des Offset-Layers und des Layer-Elements,
	 * um wieviel % diese verschoben dargestellt werden muessen.
	 *
	 * @member	Eve.DynamicLayers
	 */
	calculateMathRef : function() {
		
		var tmpOffsetReference = this.offsetElReference.split('');
		this.offsetVerRef = this.mathRef[tmpOffsetReference[0] || 't'] * 0.5;
		this.offsetHorRef = this.mathRef[tmpOffsetReference[1] || 'l'] * 0.5;
		
		var tmpLayerReference = this.layerReference.split('');
		this.layerVerRef  = this.mathRef[tmpLayerReference[0] || 't'] * 0.5 * (-1);
		this.layerHorRef  = this.mathRef[tmpLayerReference[1] || 'l'] * 0.5 * (-1);
	}
};

/** Ableiten */
Eve.DynamicLayers.extendClassBy(Eve);

/**
 * quickFx-Funktion, zum Starten von Funktionen, bevor die Seite zu Ende geladen hat.
 *
 * Beispiel:
 * <a onmouseover="javascript:if(((Eve || {}).DynamicLayers || false)) Eve.DynamicLayers.quickFx(this, { layerEl:'languageSelector', offsetY:1, offsetX:2, profile:'clickLayerBottom' });" ...>Link</a>
 *
 * @member	Eve.DynamicLayers
 * @param	{element}	el		Ausloeser-Element fuer den Layer.
 * @param	{object}	cfg		Optionen fuer den Layer.
 */
Eve.DynamicLayers.quickFx = function(el, cfg) {
	
	// Cfg validieren und mit Element befuellen.
	var cfg = cfg || {};
	cfg.containerEl = el;
	
	// onMouseOver-resetten, da dieser ja nur zum initialisieren da war ...
	el.onmouseover = null;
	el.removeAttribute('onmouseover');
	
	// Layer initialisieren
	new Eve.DynamicLayers(cfg);
	
	// mouseover-triggern, koennte ja sein, dass der Layer sofort aufgehen muss.
	jQuery(el).triggerEvent('mouseover');
};
