﻿/**
 * Eventim JavaScript Framework - Eve
 *
 * WICHTIG: Sollte diese Datei gepackt werden (dean.edwards.name/packer/), dann nur Base64-Encode nutzen, sonst kommt es
 * zu Fehlern mit Variablen die in Strings notiert werden. Beispiel: var keks = "ok", wird zu var x = "ok", wobei die gleiche
 * Variable, z. B. fuer ein eval("keks = 'ok') im Eval nicht zu x geandert wird - was natuerlich dann ein Problem ist.
 *
 * WAS STELLT DIESE DATEI ZUR VERFUEGUNG?
 *
 * 		- Basisklasse mit Funktionssammlung
 * 		- Ergaenzungen zu verschiedenen Javascript-Befehlen
 *
 * WAS BENOETIGT DIESE DATEI?
 *
 * 		- jquery.js (jQuery-Framework)
 *
 * WAS IST DAS EVENTIM JAVASCRIPT FRAMEWORK?
 * 		Dieses Framework hat die Aufgabe Funktionen zu sammeln, die immer wieder genutzt
 * 		werden und dabei helfen schneller Code-Anforderungen mit JavaScript umzusetzen. Bevor
 * 		eine temporaere Funktion ausserhalb dieses Frameworks geschrieben wird, ist vorab
 * 		zu pruefen, ob diese Funktion in dieser Sammlung bereits existiert.
 *
 * WORAUF SOLLTE ICH ACHTEN?
 *
 * 		Alle weiteren Eve.*-Klassen sollten von dieser Klasse ableiten, um die Javascript-
 * 		Sammlungen nutzen zu koennen.
 *
 * 		Darueber hinaus koennen alle hier gesammelten Funktion auch per
 *		eveJs.methode('#beispielIdEinesDomElements') aufgerufen werden.
 *
 * WICHTIG:
 *
 * 		Alle hier notierten Methoden sind entsprechend dokumentiert, es wird daher auch
 * 		darum gebeten, sollte diese Sammlung erweitert werden, die Dokumentation entsprechend
 * 		fortzusetzen.
 *
 * 		Klassen werden grundsaetzlich mit einem Grossbuchstaben begonnen, Methoden mit einem
 * 		Kleinbuchstaben.
 *
 * LETZTE AENDERUNGEN:
 *		2010-02-03 13:15	Methoden zum (de)kodieren von Strings zu Base64 / UTF8 integriert (hans-peter.beck@eventim.de).
 *		2010-01-19 11:10	In der Function.prototype.scope-Erweiterung ein try-catch-handler in der Container-Funktion eingebunden,
 *							um unbeabsichtigte Rekursions-Fehler aus anderen Aufrufen zu verhindern (hans-peter.beck@eventim.de).
 *		2010-01-08 11:45	Die Methode "getType" aus der Eve-Klasse in den Function.prototype verlegt, da Function.prototype.scope diese
 *							Methode bereits benoetigt bevor die Eve-Klasse existiert. (hans-peter.beck@eventm.de)
 *		2010-01-08 11:30	Die Methoden "bindEvent", "unbindEvent" und "triggerEvent" als EventHandler zur Klasse hinzugefuegt.
 *							Die Methode "setUpEventHandler" hinzugefuegt, um auch andere Objekte/Elemente mit EventHandler versehen zu
 *							koennen. (hans-peter.beck@eventm.de)
 *		2009-10-20 17:00	In der Methode "setHoverFx" mouseover gegen mouseenter und mouseout gegen mouseleave ausgetauscht, da dies
 *							keine Flacker-Effekte erzeugt, wie eben mouseover und mouseout...
 *		2009-09-16 12:00	Function.prototype.defer angepasst, so dass bei der Option "once=false" die Funktion im Loop aufgerufen wird,
 *							entsprechend der angegebenen Zeit (hans-peter.beck@eventim.de).
 *		2009-08-20 15:00	In der Methode inputAltInitialize() noch fuer Formular den Fall eines "Reset"-Events abgefangen, sodass dann
 *							die alt-Texte wieder ins Formular eingetragen werden (hans-peter.beck@eventim.de).
 *		2009-08-03 16:30	Neue Methode modulMiniTicketSetHeight() integriert. (hans-peter.beck@eventim.de)
 *		2009-05-11 11:30	HBX-Support in die Methode setHoverFx() integriert. (hans-peter.beck@eventim.de)
 *		2009-05-11 10:00	RegExp.escape hinzugefuegt. (hans-peter.beck@eventim.de)
 * 		2008-09-25			Erstellt (hans-peter.beck@eventim.de)
 *
 * Copyright 2008-2009 by CTS Eventim AG.
 */
 
	
/****************************************************************************************************************
 * ERGAENZUNGEN ZU JAVASCRIPT
 ***************************************************************************************************************/

	/**
	 * Ermittelt den Typ des uebergebenen Argumentes.
	 *
	 * Wurde vor den anderen Function.prototype's gelegt, da im EVE-Konstruktor bereits das scope-Feature aufgerufen
	 * wird, dieses aber getType() noch nicht kennen kann, da die Eve-Klasse noch nicht existiert...
	 *
	 * @param	{mixed}		toCheck		Der uebergebene Wert wird auf den Type geprueft.
	 * @return	Liefert den Typ des Elements zurueck.
	 * @type	{string}
	 */
	Function.prototype.getType = function(toCheck) {
		
		if (toCheck == null) return 'null';
		
		return ((typeof toCheck != 'undefined') ? (((toCheck.eveType || false)) ? toCheck.eveType() : (((toCheck.nodeName || false)) ? 'element' : typeof toCheck )) : 'undefined' );
	};
	
	/**
	 * Methode zum Vererben Klasse.
	 *
	 * Soll im Constructor der subclass der Constructor der superclass aufgerufen werden, so kann dies
	 * ueber this.superclass() getan werden. Die zu uebergebenden Parameter, die auch der superclass beim
	 * Instanzieren uebergeben werden wuerden muessen beruecksichtigt werden.
	 *
	 * Beispiel:
	 * --------------------------------------------------------------------------------------------------
	 *
	 *	// Constructor der Klasse
	 *	Eve.TestClass = function(options) {
	 *		
	 *		// Constructor der superclass (von der geerbt wurde) aufrufen
	 *		this.superclass(options);
	 *		
	 *		this.isExtended();
	 *	};
	 *	
	 *	// Methoden der Klasse
	 *	Eve.TestClass.prototype = {
	 *		
	 *		isExtended : function() {
	 *			window.alert("Wurde erfolgreich vererbt? " + this.baseClass);
	 *		}
	 *	};
	 *	
	 *	// Vererben von eve
	 *	Eve.TestClass.extendClassBy(Eve);
	 *	
	 *	// Instanzieren
	 *	var tmp = new Eve.TestClass();
	 *	
	 * --------------------------------------------------------------------------------------------------
	 * Im Beispiel sollte eine Alert-Meldung kommen:
	 * Wurde erfolgreich vererbt? true
	 * --------------------------------------------------------------------------------------------------
	 *
	 * @param	{function}	superclass	Klasse die als Quelle der zu vererbenden Methoden und Eigenschaften dienen soll.
	 */
	Function.prototype.extendClassBy = function(superclass) {
		
		var subclass = this;
		
		for (var indize in superclass.prototype) {
			
			// Wenn Element/Funktion/Objekt in der Child-Klasse schon existiert, dann nicht ueberschreiben!!!
			if ((subclass.prototype[indize] || false)) continue;
			
			subclass.prototype[indize] = superclass.prototype[indize];
		}
		
		/** 
		 * Um in der subclass den Constructor der superclass nutzen zu koennen,
		 * wird die superclass-Konstruktor-Funktion in den Prototype mit reingeschrieben
		 * und kann dann per this.superclass() aufgerufen werden.
		 */
		subclass.prototype.superclass = superclass;
		
		/** Immer wenn eine neue Klasse extended wurde, nachschauen ob im DOM-Tree etwas entsprechendes vorliegt ... */
		// if((eveJs || false)) eveJs.initializeHtmlElements();
	};
		
	/**
	 * Erweiterung fuer Funktionen, um diese auf einen ganz bestimmten Scope
	 * zu setzen.
	 *
	 * @param	{mixed}		scope	DOM-Element / Objekt, das als this fuer die Funktion gelten soll.
	 * @param	{array}		args	Argumente die immer in dieser Funktion als Attribute uebergeben werden.
	 * @param	{mixed}		append	True, haengt args hinten an. Position (Zahl), haengt args ab Position an.
	 * @return	Liefert die mit dem neuen Scope versehene Methode zurueck.
	 * @type	{function}
	 */
	Function.prototype.scope = function(scope, args, append) {
		
		var method = this.parent || this;
		
		var args   = args || false;
		var append = append || false;
		
		var overWriteArgs  = (!append && args) ? args : [] ;
		var appendArgs     = (append === true && args) ? args : [] ;
		var overWriteStart = (Function.prototype.getType(append) == "number") ? append : 0 ;
		
		var containerFunction = function() {
			
			var tmpArguments = [];
			
			/** Original Argumente ... */
			if (arguments.length > 0) for (var i = 0; i < arguments.length; i++) tmpArguments.push((typeof arguments[i] == 'undefined') ? null : arguments[i] );
			
			/** Zu ueberschreibende Argumente ... */
			if (overWriteArgs.length > 0) for (var i = overWriteStart; i < overWriteStart + overWriteArgs.length; i++) tmpArguments[i] = (typeof overWriteArgs[i] != "undefined") ? overWriteArgs[i] : ((typeof arguments[i] == 'undefined') ? null : arguments[i]) ;
			
			/** Anzufuegende Argumente ... */
			if (appendArgs.length > 0) for (var i = 0; i < appendArgs.length; i++) tmpArguments.push((typeof appendArgs[i] == 'undefined') ? null : appendArgs[i] );
			
			// Verhindern, dass durch fehlerhaften Aufruf zu viel Rekursion entsteht.
			try {
				
				var tmpResult = method.apply(scope || window, tmpArguments);
				
			} catch(e) {
				
				var tmpResult = null;
			}
			
			return tmpResult;
		};
		
		containerFunction.parent = method;
		
		return containerFunction;
	};
	
	
	Function.prototype.defer = function(defer, scope, once, args, append) {
		
		var tmpId     = eveJs.getUniqueId();
		var defer     = defer || 1;
		var once      = (typeof once != 'boolean') ? true : once ;
		var tmpArgs   = args || false;
		var tmpAppend = append || false;
		var tmpScope  = scope || this;
		
		var parent = this.scope(tmpScope, tmpArgs, tmpAppend);
		parent._id = tmpId;
		
		/** Merken der Funktion in einem globalen Register ueber eine unique ID ... */
		Eve._timeoutFunctions        = Eve._timeoutFunctions || {};
		Eve._timeoutFunctions[tmpId] = parent;
		
		parent.toFunc = function() {
			
			/** Wenn once gesetzt ist, dann timeout abbrechen, sollte ein Timeout laufen ... */
			if (once && parent.toFunc.getTimeoutId()) parent.toFunc.cancelTimeout();
			
			var tmpArguments = arguments || [];
			var tmpCode = '';
			
			for (var i = 0; i < tmpArguments.length; i++) tmpCode += (((tmpCode || '') != '') ? ',' : '' ) + 'tmpArguments[' + i + ']';
			
			var tmpDeferFunc = function() {
				
				eval("Eve._timeoutFunctions['" + tmpId + "'](" + tmpCode + ");");
			};
			
			Eve._timeoutFunctionsHelper = Eve._timeoutFunctionsHelper || {};
			Eve._timeoutFunctionsHelper[tmpId] = tmpDeferFunc;
			
			/** Timeout/Interval setzen ... */
			if((once || false)) {
				
				parent.toFunc.setTimeoutId(window.setTimeout("Eve._timeoutFunctionsHelper['" + tmpId + "']()", defer));
				
			} else {
				
				parent.toFunc.setTimeoutId(window.setInterval("Eve._timeoutFunctionsHelper['" + tmpId + "']()", defer));
			}
		};
		
		/** Funktion zum aufrufen dieser Funktion, mit der entsprechenden Zeitverzoegerung... */
		parent.toFunc.execute = function() { parent.toFunc.setTimeoutId(window.setTimeout("Eve._timeoutFunctionsHelper['" + tmpId + "']()", defer)); };
		
		/** Funktion zum ermitteln der Timeout-ID dieser Funktion. */
		parent.toFunc.getTimeoutId = function() { return parent.toFunc.timeoutId || false; };
			
		/** Funktion zum Setzen der Timeout-ID dieser Funktion. */
		parent.toFunc.setTimeoutId = function(timoutId) { parent.toFunc.timeoutId = timoutId || false; };
		
		/** Funktion zum abbrechen des Timeouts auf dieser Funktion. */
		parent.toFunc.cancelTimeout = function() {
			
			var timoutId = parent.toFunc.getTimeoutId();
			
			if (timoutId) {
			
				if((once || false)) {
				
					window.clearTimeout(timoutId);
					
				} else {
					
					window.clearInterval(timoutId);
				}
				
				parent.toFunc.setTimeoutId(false);
			}
		};
		
		return parent.toFunc;
	};
	
	
	/**
	 * Prueft ob die aktuelle Funktion uebergebenen Parameter valide sind, wenn
	 * nicht, dann wird eine Fehlermeldung ausgegeben, insofern Firebug vorhanden
	 * ist.
	 *
	 * @member	Function
	 * @param	{array}		toCheck			Wird ein Array uebergeben, wird dieses durchlaufen, um
	 *										um zu schauen, ob die Argumente je nach Anforderung vorhanden
	 *										sind oder nicht. Es kann auf * (alles erlaubt) oder Typen
	 *										geprueft werden.
	 * @param	{string}	functionName	Optional: Name der Funktion die geprueft wird.
	 * @return	Liefert true, wenn alles valide ist, andernfalls false.
	 * @type	{boolean}
	 */
	Function.prototype.isValid = function(toCheck, functionName) {
		
		var toCheck = toCheck || [];
		var hasErrors = [];
		var argumentNames = this.getArgumentNames();
		this.reqTypes = this.reqTypes || [];
		
		for (var i = 0; i < toCheck.length; i++) {
		
			if ((toCheck[i] || '')) continue;
			
			var actualType   = eveJs.getType((typeof this.arguments[i] != 'undefined') ? this.arguments[i] : null );
			var argumentName = (((argumentNames[i] || false)) ? argumentNames[i] : 'unnamed argument') + '(arg.' + i + ')' ;
			
			if (!(this.reqTypes[i] || false)) {
				
				this.reqTypes[i] = {};
				
				var tmpReqTypes  = toCheck[i].toLowerCase().split(' ');
				
				for (var j = 0; j < tmpReqTypes.length; j++) this.reqTypes[i][tmpReqTypes[j] || 'empty'] = true;
			}
			
			/** Nicht gesetzt? */
			if ((this.reqTypes[i]['empty'] || false) && (actualType == 'undefined' || this.arguments[i] == '')) {
				
				hasErrors.push([argumentName + ' is not set!', ((actualType == 'undefined') ? 'undefined' : ((actualType == 'string') ? '' : null ))] );
				
				continue;
			}
			
			/** Falscher Typ? */
			if (!(this.reqTypes[i][actualType] || false) && !(this.reqTypes[i]['*'] || false)) {
				
				hasErrors.push([argumentName + ' is no typeof ' + toCheck[i].toLowerCase().split(' ').join(' or ') + '!', this.arguments[i], actualType, this.reqTypes[i]]);
				
				continue;
			}
		}
		
		if (hasErrors.length > 0) {
		
			if ((console || false)) {
				
				if (hasErrors.length > 1) {
					
					console.group((functionName || 'unknown function') + ' - ERROR');
				
					for(var i = 0; i < hasErrors.length; i++) console.error.apply(console, hasErrors[i]);
					
					console.groupEnd();
					
				} else {
					
					hasErrors[0].unshift((functionName || 'unknown function') + ':');
					
					console.error.apply(console, hasErrors[0]);
				}
					
				return false;
			}
		}
		
		return true;
	};
	
	
	/**
	 * Liefert die Argumenten-Namen der Funktion.
	 *
	 * @member	Function
	 * @return Liefert namentliche Argumente zurueck.
	 * @type	{array}
	 */
	Function.prototype.getArgumentNames = function() {
		
		this._argumentsNames = this._argumentsNames || (this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",") || []);
																																  
		return this._argumentsNames;
	};
	
	/**
	 * Liefert einen fuer Regulaere Expressions escapten String zurueck.
	 *
	 * @member	RegExp
	 * @param	{string}	text	Text der escapedt werden soll.
	 * @return Liefert einen fuer Regulaere Expressions escapten String zurueck.
	 * @type	{array}
	 */
	RegExp.escapePattern = false;
	RegExp.escape = RegExp.prototype.escape = function(text) {
		
		if(!RegExp.escapePattern) RegExp.escapePattern = new RegExp('(\\' + (['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\']).join('|\\') + ')', 'g');
		
		return text.replace(RegExp.escapePattern, '\\$1');
	};
	
	/**
	 * Damit die verschiedensten Typen wirklich unterscheidbar werden, bekommen
	 * sie einmalige Typen zugeordnet, die es so in Javascript nicht gibt.
	 *
	 * Mit der Funktion Eve.getType(), bzw. eveJs.getType(), kann der Typ dann ermittelt
	 * werden, welche dann auch DOM-Elemente beruecksichtigen kann.
	 */
	Date.prototype.eveType     = function() { return 'date' };
	RegExp.prototype.eveType   = function() { return 'regexp' };
	
/****************************************************************************************************************
 * BASISKLASSE DES EVENTIM JAVASCRIPT FRAMEWORKS
 ***************************************************************************************************************/
 
	/**
	 * Basisklasse des Eventim Javascript Frameworks mit globalen Methoden-Sammlungen, welches
	 * als Plugin auch in jQuery verfuegbar gemacht wird.
	 *
	 * WICHTIG:
	 * Alle Methoden in dieser Basis-Klasse muessen als erstes Argument "options" als Optionshash
	 * haben!
	 *
	 * @class			eveJs
	 * @constructor
	 * @param		{object}	options				Optionshash
	 * @param		{array}		options.listener	Array mit Listenerobjekten bestehend aus eventName (string), functionName (string) und params (array).
	 */
	var Eve = function(options) {
		
		var options = options || {};
		
		/** Aktuelle Instanz global merken... */
		this.setInstanceToGlobal(this);
		
		/** Evtl. Listener initialisieren ... */
		this.initializeListener(options.listener || []);
	};
	
	Eve.prototype = {
		
		/** Typenbezeichnung fuer Klasse */
		eveType : 'class',
		
		/** Zeigt an, dass dies die Basis-Klasse ist, wird fuer ein Doku-Beispiel benoetigt. */
		baseClass : true,
		
		/** Ueber Eventnamen (Attribut) vermerkte Listener (Wert) die nach einem Event aufgerufen werden. */
		listener : {},
		
		/**
		 * Merkt sich die aktuelle Instanz in einem globalen Register ..., erstellt
		 * dafuer automatisch eine Instanz-ID.
		 *
		 * @member	Eve
		 * @param	{class}	instance		Zu setzende Instanz.
		 */
		setInstanceToGlobal : function(instance) {
			
			/** Eindeutige ID der aktuellen Instanz */
			instance._instanceId = instance._instanceId || this.getUniqueId();
		
			Eve.globalInstances = Eve.globalInstances || {};
			Eve.globalInstances[instance._instanceId] = instance;
		},
		
		/**
		 * Liefert eine Instanz ueber dessen ID ...
		 *
		 * @member	Eve
		 * @param	{string}	instaceId	ID der Instanz, welche geliefert werden soll.
		 * @return	iefert eine Instanz ueber dessen ID, wenn vorhanden, andernfalls false.
		 * @type	{class}
		 */
		getInstanceFromGlobal : function(instanceId) {
			
			instanceId = (instanceId || this._instanceId) || 'unknown';
			
			return (Eve.globalInstances || {})[instanceId] || false;
		},
		
		/**
		 * Liefert eine Instanz ueber dessen ID als JSON-String ...
		 *
		 * @member	Eve
		 * @param	{string}	instaceId	ID der Instanz, welche geliefert werden soll.
		 * @return	iefert eine Instanz ueber dessen ID als JSON-String, wenn vorhanden, andernfalls false.
		 * @type	{string}
		 */
		getInstanceFromGlobalString : function(instanceId) {
			
			var instanceId = (instanceId || this._instanceId) || 'unknown';
			var instance   = (Eve.globalInstances || {})[instanceId] || null;
			
			return (instance != null) ? "Eve.globalInstances['" + instanceId + "']" : false ;
		},
		
		/**
		 * Sucht nach DOM-Elementen mit der CSS-Klasse "eveJs", folgend nach einem
		 * verstecktem Input mit der CSS-Klasse "eveJsCfg", welches eine Konfiguration
		 * ueber einen JSON-String zur Verfuegung stellt. Ist das Element ein Link-Tag,
		 * dann wird im "rel"-Attribut nachgeschaut, ob dort eine Konfiguration
		 * hinterlegt wurde.
		 *
		 * <div class="eveJs">
		 *		<input type="hidden" class="eveJsCfg" value="{ ... }" />
		 *      ...
		 * </div>
		 *
		 * Oder:
		 *
		 * <a href="http://www.eventim.de" class="eveJs" rel="{ ... }">Eventim Homepage</a>
		 *
		 * Das Konfigurations-Objekt ist immer gleich aufgebaut, es besteht aus den Namen
		 * der Javascript-Klassen, die mit der Konfiguration gebildet werden sollen:
		 *
		 * { 'Eve.RegisterCards' : { paramA : 'keks', paramB : 'keks', listener : [...] }, 'Eve.AbstractTexts' : { paramA : 'keks', paramB : 'keks', listener : [...] } }
		 *
		 * Der Parameter "listener" ist besonders, ueber ihn koennen auf Events der
		 * zu erstellenden Instanz Funktionen ausgefuehrt werden, wenn die Instanz einen
		 * Event feuert. Zum Beispiel kann die Hoehe mehrere Boxen nach dem umschalten der
		 * Registerkarten somit per Event angeglichen werden ..., hier ein Beispiel:
		 *
		 * listener:[ {eventName:'change', functionName:'setToSameHeightAtRow', params:['eventimInfoPhotoRow']} ]
		 *
		 * Da es sein kann, dass mehrere Listener auf einem Event ausgefuehrt werden sollen,
		 * wird jeder Event als Objekt in dem Array notiert.
		 *
		 * @member	Eve
		 * @param	{string}	element		Optional: jQuery-Selektor oder Element zum finden der zu initialisierenden Elemente (Default eveJs).
		 */
		initializeHtmlElements : function(element) {
			
			var parent = this;
			
			jQuery(element || '.eveJs').each(function() {
				
				/** Element ID ermitteln ... */
				var tmpId = eveJs.getElementId(this);
				
				/** JSON-String fuer die Konfiguration ermitteln ... */
				if (this.nodeName.toLowerCase() == 'a') {
					
					var tmpJsonCfg = this.getAttribute('rel') || false;
					
				} else {
					
					var tmpInput = jQuery('#' + tmpId + ' input.eveJsCfg').get(0) || false;
					var tmpJsonCfg = (!tmpInput) ? false : tmpInput.value || false;
				}
				
				/** Wenn es kein CFG-String gibt, dann Ende, kaputt, Weltuntergang ... */
				if (!tmpJsonCfg) return false;
				
				/** Config auslesen ... */
				eval("var tmpToCreate = " + tmpJsonCfg + ";");
				
				/**
				 * Pruefen ob die Klassen vorhanden sind, wenn nicht, dann erstmal abbrechen ...,
				 * beim naechsten Extenden einer Klasse wird diese Methode erneut aufgerufen.
				 */
				for (var className in tmpToCreate) {
					
					eval("var existsClass = window." + className + " || false;");
					
					if (!existsClass) return;
				}
				
				/** Rel-Attribut / Hidden Input entfernen ... */
				if (this.nodeName.toLowerCase() == 'a') {
					
					this.removeAttribute('rel');
					
				} else {
					
					jQuery(tmpInput).remove();
				}
				
				/** Auf dem Element vermerken, dass eveJs genutzt wurde ... */
				jQuery(this).removeClass('eveJs');
				jQuery(this).addClass('eveJsDone');
				
				/** Instanzen erstellen, wenn die passende Klasse dazu existiert. */
				for (var className in tmpToCreate) {
					
					eval("var existsClass = window." + className + " || false;");
					
					if (!existsClass) continue;
					
					/** Config um benoetigte Parameter erweitern ... */
					var tmpCfg = tmpToCreate[className] || {};
					tmpCfg.containerEl = this;
					
					new existsClass(tmpCfg);
				}
			});
		},
		
		
		/**
		 * Parsed einen String, wie DOM-Elemente, durch und gibt diese als verschachteltes
		 * Array mit Objekten (aehnlich eines DOM-Trees zurueck ...).
		 *
		 * @member	Eve
		 * @param	{object}	o				Optionshash
		 * @param	{string}	o.htmltext		Text der umegwandelt werden soll.
		 * @param	{boolean}	o.stripTags		Optional: Wenn true, werden alle HTML-Tags entfernt (Default false).
		 * @return	Verschachteltes Array mit Objekten fuer Tags und Texte.
		 * @type	{array}
		 */
		serializeDom : function(o) {
			
			var sd = function(o) {
				
				var o = o || {};
				
				o.htmltext = o.htmltext.replace("\t", "", "gi").replace("\r", "", "gi").replace("\n", " ", "gi");
				
				var regAnyTag   = /<\/?([\w]+)[\w\s]*[^><]*\/?>/i;
				var regCloseTag = /<\/(\w*)[^><]*>/i; 
				var regOpenTag  = /<([^\/]\w*)[\w\s]*[^><]*>/i;
				var res, childs = [], searchText = o.htmltext;
				var stripTags   = o.stripTags || false;
				
				if (!regAnyTag.test(searchText)) return { htmltext : '', childs : [{ type:'text', value:searchText, childs:false, single:true }] };
				
				/**
				 * Fehlerhafte Tags abfangen ...
				 */
				if ((o.parent || false)) {
					
					var closeResult;
					var closeText  = (o.preCode || '') + searchText;
					
					var regCloseThisText = new RegExp("<\/" + o.parent + ">", "gi");
					var regOpenThisText  = new RegExp("(<" + o.parent + ">)|(<" + o.parent + " [\w\s]*[^><]*>)", "gi");
					
					var openLinks  = (closeText.match(regOpenThisText) || []).length;
					var closeLinks = (closeText.match(regCloseThisText) || []).length;
					
					if (openLinks != closeLinks) return { htmltext : searchText, childs : childs };	
				}
				
				/**
				 * Saubere Tagliste bilden ...
				 */
				while(res = regAnyTag.exec(searchText)) {
					
					var tmpCode     = res[0];
					var tmpNodeName = res[1].toLowerCase();
					var tmpTextnode = searchText.split(tmpCode).shift();
					
					//console.debug("SearchText:\n\t",searchText, "\nRes:\n\t", res,"\nTextnode:\n\t", tmpTextnode);
					
					if (tmpTextnode != '') childs.push({ type:'text', value:tmpTextnode, childs:false, single:true });
					
					var searchText = searchText.substring((tmpTextnode + '' + tmpCode).length);
					
					/** Oeffnendes Tag oder Single-Tag? */
					if (regOpenTag.test(tmpCode)) {
						
						/** Single-Tag? */
						if (tmpNodeName == 'img' || tmpNodeName == 'br' || tmpNodeName == 'input' || tmpNodeName == 'hr') {
							
							if (!stripTags) childs.push({ type:'tag', value:tmpCode, name:tmpNodeName, childs:false, single:true });
						
						/** Oeffnendes Tag? */
						} else {
							
							/**
							 * Es muss jetzt rekursiv mit dem uebrigen Text wieder diese Funktion
							 * aufgerufen werden, bis entweder der schliessende Tag nicht passt
							 * oder eben passt oder der Text zuende ist.
							 */
							var result = sd({ htmltext:searchText, parent:tmpNodeName, preCode:tmpCode });
							
							var searchText = result.htmltext;
							
							if (!stripTags) {
								
								childs.push({ type:'tag', value:tmpCode, name:tmpNodeName, childs:((result.childs.length > 0) ? result.childs : false), single:false });
								
							} else if (stripTags && result.childs.length > 0) {
								
								for (var i = 0; i < result.childs.length; i++) childs.push(result.childs[i]);
							}
						}
					
					/** Schliessendes Tag? */
					} else if (regCloseTag.test(tmpCode)) {
						
						/** Wenn das letzte Schliessen-Tag kommt und es ist noch Code da, der kein Tag ist, dann Als Text-Child merken ... */
						/** Testweise auskommentiert, da in einem Fall der Resttext mit zu dem Tag gezaehlt wurde, was ja so nicht ganz richtig ist */
						/*if(searchText != '' && !regAnyTag.exec(searchText)) {
					
							console.debug(searchText);
							
							childs.push({ type:'text', value:searchText, childs:false, single:true });
							
							searchText = '';
						}*/
						
						/** Wenn das schliessende Tag nicht dem parent enstricht, dann ignorieren! */
						if ((o.parent || '') == tmpNodeName) {
							
							/**
							 * Hier muss geprueft werden, ob das schliessende Tag dem parent entspricht, wenn ja
							 * dann ist hier Ende fuer die aktuelle Pruefung.
							 */
							return { htmltext : searchText, childs : childs };
						}
					}
				}
				
				if (searchText != "") childs.push({ type:'text', value:searchText, childs:false, single:true });
				
				return { htmltext : searchText, childs : childs };
			};
			
			var result = sd(o || {});
			
			return result.childs || [];
		},
		
		
		/**
		 * Entfernt aus einem String alle Whitespaces bis auf Leerzeichen.
		 *
		 * @member	Eve
		 * @param	{string}	text		Der zu bearbeitende String
		 * @return	Liefert String ohne Whitespaces (ausser Leerzeichen).
		 * @type	{string}
		 */
		cleanText : function(text) {
		
			return text.replace(new RegExp('\n', 'g'), ' ').replace(new RegExp('\r', 'g'), '').replace(new RegExp('\t', 'g'), '');
		},
		
		
		/**
		 * Parsed den uebergebenen HTML-Code wie einen DOM-Tree durch und teilt den HTML-Code
		 * bis zu angegebenen Laenge.
		 * 
		 * @member	Eve
		 * @param	{object}	o				Optionshash:
		 * @param	{string}	o.htmlText		Array mit Elementen aus der Funktion Eve.serializeDom(), ist der uebergebene Wert ein String, wird Eve.serializeDom() darauf ausgefuehrt.
		 * @param	{boolean}	o.returnString	Optional: Wenn true, wird der gekuerzte Text als String (HTML-Code) zurueck gegeben (Default false).
		 * @param	{string}	o.cutType		Optional: Art des Abschneidens, nach Buchstaben (letter), Woertern (word) oder Saetzen (sentence) (Default letter).
		 * @param	{number}	o.maxLength		Position, an der abgeschnitten werden soll (Default 150).
		 * @param	{string}	o.elType		Optional: Alternative Container-Typ fuer abstract und rest (Default div).
		 * @param	{boolean}	o.stripAllTags	Optional: Wenn true, werden alle HTML-Tags entfernt (Default false).
		 * @return	Liefert ein Objekt mit dem gekuerzten Text und dem Rest { abstract : ..., rest : ... }
		 * @type	{object}
		 */
		cutHtmlText : function(o) {
			
			var o = o || {};
			
			o.returnString = o.returnString || false;
			
			var cutType      = o.cutType || 'letter';
			var limitReached = false;
			var plainText    = '';
			var plainAllText = '';
			var parent       = this;
			var maxLength    = o.maxLength || 150;
			var elType       = o.elType || 'div';
			var stripTags    = o.stripAllTags || false;
			
			o.elements = this.serializeDom({ htmltext : o.htmlText, stripTags : stripTags });
			
			var cet = function(o) {
				
				o.elements      = o.elements || [];
				o.abstract      = o.abstract || document.createElement(elType);
				o.rest          = o.rest || document.createElement(elType);
				o.noRememberPlain = o.noRememberPlain || false;
				
				for (var i = 0; i < o.elements.length; i++) {
					
					var tmpElement = o.elements[i];
					
					/** DOM-Tag */
					if (tmpElement.type == 'tag') {
						
						var isNoReg         = new RegExp("eveJsAbstractNo", "gi");
						var noRememberPlain = isNoReg.test(tmpElement.value);
						
						if (!(tmpElement.single || false)) {
							
							if ((tmpElement.childs || false)) {
								
								var result = cet({ elements : tmpElement.childs, noRememberPlain : (o.noRememberPlain || noRememberPlain) });
								
								if (result.abstract.innerHTML != '') jQuery(o.abstract).append(tmpElement.value + result.abstract.innerHTML + '</' + tmpElement.name + '>');
								
								if (result.rest.innerHTML != '') jQuery(o.rest).append(tmpElement.value + result.rest.innerHTML + '</' + tmpElement.name + '>');
								
							} else {
								
								jQuery(o[((limitReached !== true) ? 'abstract' : 'rest' )]).append(tmpElement.value + '</' + tmpElement.name + '>');
							}
							
						} else {
							
							/** <br />, <img />, <input /> ... */
							jQuery(o[((limitReached !== true) ? 'abstract' : 'rest' )]).append(tmpElement.value);
						}
					
					/** Text */
					} else {
						
						var tmpText     = tmpElement.value || '';
						var lettersLeft = (limitReached) ? (-1) : parent.getTextLengthLeft((plainText + tmpText), maxLength) ;
						
						if (lettersLeft >= 0 && !limitReached) {
						
							jQuery(o.abstract).append(tmpText);
							
						} else if (lettersLeft < 0 && !limitReached) {
							
							/** Der neue Text ist zulang und muss abgeschnitten werden... */
							var cuttedText = parent.cutText(tmpText, (lettersLeft * (-1)), cutType) || { pre : '', rest : '' };
							
							jQuery(o.abstract).append(cuttedText.pre || '');
							jQuery(o.rest).append(cuttedText.post || '');
							
							/** Merker setzen, dass der Text ab jetzt nicht mehr in this.abstractText kann */
							limitReached = true;
							
						} else if (limitReached) {
							
							jQuery(o.rest).append(tmpText);
						}
						
						plainText += tmpText;
						
						//console.debug(o.noRememberPlain, plainAllText, "\n\n", tmpText);
						
						if(!o.noRememberPlain) {
							
							plainAllText += tmpText;
						}
					}
				}
				
				return o;
			};
			
			var result = cet({ elements : o.elements  });
			
			result.totalLength = this.cleanText(plainAllText).length;
			
			if(o.returnString) {
				
				result.abstract = result.abstract.innerHTML;
				result.rest = result.rest.innerHTML;
			}
			
			return result;
		},
		
		
		/**
		 * Schneidet einen String ab einer bestimmten Laenge ab (beruecksichtigt dabei unterschiedliche Typen),
		 * und liefert die beiden String-Teile zurueck.
		 *
		 * @member	Eve
		 * @param	{string}	text		Der zu bearbeitende String
		 * @param	{number}	length		Laenge ab der abgeschnitten werden soll.
		 * @param	{string}	type		Zeichen (letter), Woerter (word), Satz (sentence), (Default letter).
		 * @param	{boolean}	preOnly		Optional: Wenn true wird der erste String-Teil direkt zurueckgegeben (Default false).
		 * @return	Liefetr ein Objekt mit den zwei String-Teilen { pre : ..., post : ... }
		 * @type	{object}
		 */
		cutText : function(text, length, type, preOnly) {
		
			var type   = (type || 'letter').toLowerCase();
			var length = length || 0;
			var text   = this.cleanText((text || '').toString());
			var toCut  = text.length - length;
			
			switch (type) {
				
				case 'word':
				case 'sentence' :
				
					var spacer = (type == 'word') ? ' ' : '.' ;
					
					var post = text.split(spacer);
					var pre = [];
					var tmpLength = post.length;
					
					for (var i = 0; i < tmpLength; i++) {
						
						pre.push(post.shift());
						
						if (pre.join(spacer).length >= toCut) {
						
							if (pre.join(spacer).length > toCut) post.unshift(pre.pop());
						
							break;
						}
					}
					
					var tmpCut = {
					
						'pre' : pre.join(spacer),
						'post' : post.join(spacer)
					};
					
					break;
				
				/** Bei 'letter' einfach harten Cut! */
				default : 
				
					var tmpCut = {
						
						'pre' : text.substring(0, toCut),
						'post' : text.substring(toCut)
					};
					
					break;
			}
			
			return ((preOnly || false)) ? tmpCut.pre || '' : tmpCut;
		},
		
		
		/**
		 * Liefert die Differenz zwischen der maximalen Laenge und der
		 * tatsaechlichen Laenge des Strings. Ist der Wert positiv, sind
		 * somit noch [n] Zeichen uebrig. Ist der Wert negativ, ist der
		 * String [n] Zeichen zu lang.
		 *
		 * @type	Eve
		 * @param	{string}	text		Zu bemessender String.
		 * @param	{number}	maxLength	Die maximal erlaubte Laenge des Strings.
		 * @return	Liefert die Differenz zwischen der aktuellen und der maximal erlaubten Laenge des Strings.
		 * @type	{number}
		 */
		getTextLengthLeft : function(text, maxLength) {
				
			var tmpText = this.cleanText(text || '');
			
			return (maxLength - tmpText.length);
		},
		
		
		/**
		 * Setzt die im Array uebergebenen Elemente auf die gleiche Hoehe des hoechsten
		 * Elements.
		 *
		 * @member	Eve
		 * @param	{object}	options					Optionshash:
		 * @param	{array}		options.elements		Elemente die auf die gleiche Hoehe gesetzt werden sollen.
		 * @param	{integer}	options.toHeight		Optional: Hier kann eine feste Hoehe angegeben werden, die auf jeden Fall gesetzt werden soll.
		 */
		setToSameHeight : function(options) {
			
			/** Argumente der Funktion valide? */
			if(!(this.setToSameHeight.isValid(['object'], 'setToSameHeight'))) return;
			
			var options = options || {};
			var tmpElements = options.elements || [];
			var tmpNewHeight = options.toHeight || 0;
			
			/** Wenn toHeight nicht gesetzt ist, dann das groesste Element ermitteln! */
			if (!(options.toHeight || false)) {
				 
				for (var i = 0; i < tmpElements.length; i++) {
					
					var tmpElement = tmpElements[i] || false;
					
					if (!(tmpElement)) continue;
					
					if (tmpElement.style.display == 'none') continue;
					
					tmpElement.style.height = '';
					
					var tmpHeight = jQuery(tmpElement).height();
					
					if (tmpHeight > tmpNewHeight) tmpNewHeight = tmpHeight;
				}
			}
			
			/** Hoehe setzen ... */
			for (var i = 0; i < tmpElements.length; i++) {
				
				var tmpElement = tmpElements[i] || false;
					
				if (!(tmpElement)) continue;
				
				jQuery(tmpElement).height(tmpNewHeight);
			}
		},
		
		
		/**
		 * Sucht die Child-Elemente der ersten Ebene und gleicht deren Hoehe ab.
		 *
		 * @member	Eve
		 * @param	{mixed}		rowElement		ID oder Element, dessen Childs abgeglichen werden sollen.
		 * @param	{string}	elementsByCls	Optional: CSS-Class, Default *.
		 */
		setToSameHeightAtRow : function(rowElement, elementsByCls) {
			
			/** Argumente der Funktion valide? */
			if (!(this.setToSameHeightAtRow.isValid(['string element'], 'setToSameHeightAtRow'))) return;
			
			if (this.getType(rowElement) == 'string') rowElement = jQuery('#' + rowElement).get(0) || false;
			
			if (!rowElement) return;
			
			this.setToSameHeight({ elements : jQuery('#' + this.getElementId(rowElement) + ' ' + (((elementsByCls || false)) ? '.' + elementsByCls : '> *' )).get() || [] });
		},
		
		/**
		 * Ermittelt die ID eines DOM-Elements, gibt es keine ID wird eine erzeugt und
		 * auf das DOM-Element gesetzt.
		 *
		 * @member	Eve
		 * @param	{element}	element		DOM-Element, von welchem die ID ermittelt werden soll.
		 * @return	Liefert die ID des uebergebenen DOM-Elements.
		 * @type	{string}
		 */
		getElementId : function(el) {
			
			/** Argumente der Funktion valide? */
			if(!(this.getElementId.isValid(['el'], 'getElementId'))) return;
			
			var tmpId = (el.attributes['id'] || {}).nodeValue || false;
			
			if (!tmpId) {
				
				tmpId = this.getUniqueId();
				this.setElementId(el, tmpId);
			}
			
			return tmpId;
		},
		
		
		/**
		 * Setzt die ID eines DOM-Elements.
		 *
		 * @member	Eve
		 * @param	{element}	element		DOM-Element, auf dem die ID gesetzt werden soll.
		 * @param	{string}	newId		Zu setzende ID.
		 */
		setElementId : function(element, newId) {
			
			/** Argumente der Funktion valide? */
			if(!(this.setElementId.isValid(['element', 'string'], 'setElementId'))) return;
			
			element.setAttribute('id', newId);
		},
		
		
		/**
		 * Liefert eine einmalige und unbenutzte ID zurueck.
		 *
		 * @member	Eve
		 * @return  Liefert eine einmalige und unbenutzte ID zurueck.
		 * @type	{string}
		 */
		getUniqueId : function() {
			
			Eve.uniqueIdCtr = (Eve.uniqueIdCtr || 0) + 1;
			
			return 'eve_uId_' + Eve.uniqueIdCtr;
		},
		
		
		/**
		 * Immer wenn fireEvent aufgerufen wird, fand ein Event statt, 
		 * es wird dann in der this.registeredEvents nachgeschaut, ob Events
		 * auf den jeweiligen eventName'n registriert sind, wenn ja, 
		 * werden diese ausgefuehrt.
		 *
		 * @member	Eve
		 * @param	{string}	eventName		Name des gefeuerten Events
		 * @param	{mixed}		eventParams		Parameter fuer den Event
		 */
		fireEvent : function(eventName, eventParams) {
			
			/** Argumente der Funktion valide? */
			if(!(this.fireEvent.isValid(['string number'], 'fireEvent'))) return;
			
			var listener  = this.listener[eventName.toLowerCase()] || false;
			
			if (!listener) return;
			
			for (var id in listener) listener[id]();
		},
		
		
		/**
		 *
		 */
		initializeListener : function(listenerArray) {
			
			/** Argumente der Funktion valide? */
			if(!(this.initializeListener.isValid(['object'], 'initializeListener'))) return;
			
			if(listenerArray.length == 0) return;
			
			for (var i = 0; i < listenerArray.length; i++) {
				
				var tmpListenerCfg = listenerArray[i] || {};
				
				var tmpParams = (eveJs.getType(tmpListenerCfg.params || null) == 'array') ? [tmpListenerCfg.params || null] : tmpListenerCfg.params;
				
				this.registerListener(tmpListenerCfg.eventName || null, tmpListenerCfg.functionName || null, tmpParams);
			}
		},
		
		/**
		 * Registriert eine Funktion die auf einen Event hoert und ausgefuehrt wird,
		 * wenn der Event gefeuert wird.
		 *
		 * @member	Eve
		 * @param	{string}	eventName		Eventname auf den eine Funktion lauschen soll.
		 * @param	{mixed}		listenerFunc	Funktion (inkl. Scope und Parameter) oder String mit Namen der aufzurufenden Funktion auf der aktuellen Klasse.
		 * @param	{array}		listenerParams	Parameter fuer die aufzurufende Funktion.
		 * @return	Liefert die Listener-ID zurueck, ueber welche der Listener wieder entfernt werden kann.
		 * @type	{string}
		 */
		registerListener : function(eventName, listenerFunc, listenerParams) {
			
			/** Argumente der Funktion valide? */
			if(!(this.registerListener.isValid(['string', 'string function'], 'registerListener'))) return;
			
			var eventName = eventName.toLowerCase();
			var listenerId = eventName + '___' + this.getUniqueId();
			
			var scope = listenerFunc;
			if (this.getType(listenerFunc) == 'string') {
				
				listenerFunc = this[listenerFunc] || false;
				scope        = this;
			}
			
			if (this.getType(listenerFunc) != 'function') return false;
			
			this.listener[eventName] = this.listener[eventName] || {};
			this.listener[eventName][listenerId] = listenerFunc.scope(scope, listenerParams || []);
			
			return listenerId;
		},
		
		
		/**
		 * Entfernt einen Listener von einem Event, ueber die Listener-ID.
		 *
		 * @member	Eve
		 * @param	{string}	listenerId		ID des Listeners der entfernt werden soll.
		 */
		unregisterListener : function(listenerId) {
			
			/** Argumente der Funktion valide? */
			if(!(this.unregisterListener.isValid(['string'], 'unregisterListener'))) return;
			
			var tmpArray   = listenerId.toLowerCase().split('___');
			var eventName  = tmpArray[0];
			var listenerId = tmpArray[0];
			
			this.listener[eventName] = this.removeFromObj(this.listener[eventName] || {}, listenerId);
		},
		
		/**
		 * Ermittelt den Typ des uebergebenen Argumentes.
		 *
		 * @member	Eve
		 * @param	{mixed}		toCheck		Der uebergebene Wert wird auf den Type geprueft.
		 * @return	Liefert den Typ des Elements zurueck.
		 * @type	{string}
		 */
		getType : Function.prototype.getType.scope(this),
		
		/** 
		 * Prueft ob die uebergebenen Werte/Objekte/usw. identisch sind oder nicht,
		 * dabei wird darauf geachtet, dass keine zeitraubenden Vergleiche verschiedener
		 * Typen ausgefuehrt wird.
		 *
		 * @member	Eve
		 * @param	{mixed}		a		Wert A
		 * @param	{mixed}		b		Wert B
		 * @return	Liefert true, wenn Wert A und Wert B identisch sind, andernfalls false.
		 * @type	{boolean}
		 */
		isEqual : function(a, b) {
			
			if (this.getType(a) != this.getType(b)) return false;
			
			if (a != b) return false;
			
			return true;
		},
		
		
		/**
		 * Entfernt aus einem Objekt, je nach Typ, entsprechende Inhalte und gibt
		 * das aufgeraeumte Objekt zurueck.
		 * 
		 * @member	Eve
		 * @param	{object}	obj			Das zu bearbeitende Objekt.
		 * @param	{mixed}		toRemove	Value, RegExp, Indize ueber welches entfernt werden soll.
		 * @return	Liefert das bereinigte Objekt zurueck.
		 * @type	{object}
		 */
		removeFromObj : function(obj, toRemove) {
			
			/** Argumente der Funktion valide? */
			if(!(this.removeFromObj.isValid(['object', '*'], 'removeFromObj'))) return;
			
			var newObject = {};
			
			for (var indize in obj) {
				
				switch(eveJs.getType(toRemove)) {
					
					case 'string' : if (toRemove != indize) newObject[indize] = obj[indize]; break;
						
					case 'regexp' : if (!toRemove.test(obj[indize])) newObject[indize] = obj[indize]; break;
						
					case 'null' : if (obj[indize] != null) newObject[indize] = obj[indize]; break;
					
					default : newObject[indize] = obj[indize]; break;
				};
			}
			
			return newObject;
		},
		
		
		/**
		 * Scrollt animiert zu einem Element.
		 *
		 * @member	Eve
		 * @param	{mixed}		el			Element, zu dem hingescrollt werden soll oder Position in der Seite.
		 * @param	{number}	time		Optional: Zeit in Millisekunden (Default 1000ms = 1s).
		 * @param	{function}	callback	Optional: Calback der aufgerufen werden soll, wenn fertig.
		 * @param	{number}	offsetY		Optional: Offset vertikal.
		 */
		scrollToElement : function(el, time, callback, offsetY) {
		
			this.getPageHeight();
		
			if (!(el || false)) return;
			
			var pageHeight = this.getInnerWindowSize().height;
			var bodyHeight = this.getPageHeight();
			
			var targetOffset = (typeof el == "number") ? el : jQuery(el).offset().top;
			targetOffset += ((typeof offsetY != 'undefined') ? offsetY :  0 );
			
			var maxHeight = targetOffset + pageHeight;
			
			if (maxHeight > bodyHeight) targetOffset = bodyHeight - pageHeight - 10;
			
			var time = time || 1000;
			var cfg  = { scrollTop : ((targetOffset > 10) ? targetOffset - 10 : targetOffset ) };
			
			if ((callback || false) && typeof callback == 'function') {
				
				jQuery('html,body').animate(cfg, time, callback);
				
			} else {
				
				jQuery('html,body').animate(cfg, time);
			}
		},
		
		/**
		 * Ermittelt die aktuelle Scrollposition des Dokumentes ...
		 *
		 * @member	Eve
		 * @return	Liefert die aktuelle Scrollposition.
		 * @type	{number}
		 */
		getScrollPosition : function() {
		
			/** IE Browser ticken wie immer anders ... */
			if (jQuery.browser.msie) {
				
				return jQuery('html,body').offset();
			
			} else {
			
				return (typeof window.pageXOffset != 'undefined') ? { top : window.pageYOffset, left : window.pageXOffset } : { top : document.body.scrollTop, left : document.body.scrollLeft } ;
			}
		},
		
		/**
		 * Ermittelt die aktuelle Groesse des Dokumentes ...
		 *
		 * @member	Eve
		 * @return	Liefert die aktuelle Groesse des Fensters bzw. Dokumentes zurueck.
		 * @type	{object}
		 */
		getInnerWindowSize : function() {
			
			if (typeof window.innerHeight != 'undefined') {
				
				var width = window.innerWidth;
				var height = window.innerHeight;
				
			} else {
			
				var width = ((jQuery.browser.msie) ? document.documentElement.clientWidth || document.body.clientWidth : document.body.clientWidth );
				var height = ((jQuery.browser.msie) ? document.documentElement.clientHeight || document.body.clientHeight : document.body.clientHeight );
			}
			
			return { width : width, height : height };
		},
		
		/**
		 * Liefert die tatsaechliche Groesse der Seite zurueck indem an das Ende ein Element gesetzt
		 * wird und dann gemessen wird.
		 *
		 * @member	Eve
		 * @param	{el}	docEl	Optional: Dokument, welches geemessen werden soll (Default document).
		 * @return	Liefert die tatsaechliche Groesse der Seite.
		 * @type	{integer}
		 */
		getPageHeight : function(docEl) {
			
			var docEl = docEl || document;
			
			var tmpEl = docEl.createElement('div');
			tmpEl.style.height = "0px";
			tmpEl.style.overflow = "hidden";
			tmpEl.style.clear = "both";
			jQuery(docEl.body).append(tmpEl);
			
			var pageHeight = jQuery(tmpEl).offset().top;
			
			jQuery(tmpEl).remove();
			
			return pageHeight;
		},
		
		/**
		 * Liefert die Position des uebergebenen Elementes gemessen an der oberen linken
		 * Ecke des Dokumentes.
		 *
		 * @member	Eve
		 * @param	{element}	el		DOM-Element von welchem das Offset ermittelt werden soll.
		 * @return	Liefert den Offset des Elements zurueck.
		 * @type	{object}
		 */
		getElementOffset : function(el) {
			
			return { top : jQuery(el).scrollTop(), left : jQuery(el).scrollLeft() };
		},
		
		/**
		 * Setzt die Transparenz eines DOM-Elements Cross-Browser-Kompatibel.
		 *
		 * @member	Eve
		 * @param	{element}	el		DOM-Element von welchem die Transparenz gesetzt werden soll.
		 * @param	{integer}	alpha	Transparenz-Wert zwischen 100 (sichtbar) und 0 (unsichtbar).
		 */
		setAlpha : function(el, alpha) {
			
			el.style.opacity = (alpha > 0) ? alpha / 100 : 0 ;
			
			if (jQuery.browser.msie) el.style.filter = "Alpha(opacity=" + alpha + ")";
		},
		
		/**
		 * Sucht nach allen Eingabefeldern innerhalb des .mods-CSS-Selektor mit einem gesetzten
		 * Alt-Attribut und belegt diese mit den entsprechenden Focus/Blur Funktionen ...
		 *
		 * WICHTIG: Sind Formulare in Layern untegebracht, die mit Eve.DynamicLayer erstellt werden, dann ist es wichtig,
		 * diesen Formularen die CSS-Klasse "ignoreBecauseLayer" mitzugeben, was folgendes bewirkt: Nachdem die Seite
		 * geladen wurde, werden ja alle Formulare und Eingabefelder per JavaScript mit Validierungen versehen. Ist die
		 * CSS-Klasse "ignoreBecauseLayer" auf einem Formular, wird die Validierung dort nicht durchgefuehrt - meist in
		 * Layern. Wird der Layer nun ueber Eve.DynamicLayer erstellt, dann wird geprueft ob in dem Layer ein Formular
		 * mit "ignoreBecauseLayer" als CSS-Klasse enthalten ist und holt jetzt die Validierung nach. Der Grund dafuer ist
		 * dass die Layer geklont werden, ans Ende vom DOM geschoben werden und dann zwar entsprechend mit Events und
		 * Validierung versehen wären, aber jQuery.validator nach dem Klonen damit nichts anfangen kann - die Referenzen
		 * auf die Objekte stimmen dann nicht mehr. Durch diesen Workaround wird das Problem entsprechend umgangen.
		 *
		 * @member	Eve
		 * @param	{string}	selektor	jQuery Selektor in dem Input-Felder initialisiert werden sollen. Alternativ
		 *									koennen auch direkte DOM-Elemente uebergeben werden.
		 */
		inputAltInitialize : function(selektor) {
			
			var tmpThis = this;
			
			var selektor = selektor || '.mods';
			
			if (typeof selektor == "string") {
				
				formSelektor = selektor + ' form';
				inputSelektor = selektor + ' input';
				
			} else {
			
				formSelektor  = this.findParent(selektor, 'form');
				inputSelektor = selektor;
				selektor      = "element";
			}
			
			// Events - onSubmit, onClick, usw. - funktionieren in der Reihenfolge, wie man diese setzt. Setzt man also
			// erst eine Funktion A auf und folgend noch eine Funktion B auf den onSubmit-Handler, dann wird bei einem
			// Submit erst Funktion A und dann Funktion B ausgefuehrt.
			//
			// Im Fall von Formular-Ueberpruefungen ist es wichtig die Default-Texte vor der Ueberpruefung bzw. generell
			// vor dem Absenden eines Formulares zu entfernen. Was aber passiert, wenn eine Formular-Ueberpruefung fehl
			// schlaegt, dann soll der Ursprungszustand der Default-Texte wieder hergestellt werden.
			// Dies bedeutet, dass in der oben geschilderten Reihenfolge an erste Stelle eine Funktion kommt, die die
			// Default-Texte entfernt. Danach kommen alle normalen Event-Funktionen. Abschliessend kommt eine Funktion
			// die prueft ob das Formular abgesendet wird oder nicht, wenn nicht stellt es die Default-Texte wieder
			// her.
			//
			// Das Hauptproblem besteht darin, dass das aktuelle Script gerade nicht weiss, welche Event-Funktionen der
			// Handler noch erfahren wird. Daher wird die erste Funktion, welche die Defaulttexte entfernt, erst pruefen,
			// wenn diese ausgefuehrt wird, ob die Abschlussfunktion vorhanden ist oder nicht. So wird erreicht, dass
			// dazwischen alle sonstigen Funktionen unterkommen, bis der Nutzer auf "Senden" klickt.
			//
			// 1. Aufruf der Initial-Funktion, prueft ob Final-Funktion verfuegbar ist,
			//    - Ja: Es entfernt nun alle Defaulttexte.
			//    - Nein: Es setzt die Final-Funktion im Submit-Handler am Ende des Stapels. Stoppt alles und loest 5ms 
			//      spaeter erneut ein Submit-Event aus.
			// 2. Alle weiteren Event-Funktion werden ausgefuehrt.
			// 3. Die letzte Event-Funktion sollte nun die Final-Funktion sein, welche bei erhaltenem Sende-Wert
			//    - false: Die Defaulttexte werden wieder angezeigt. Es wird false an das Formular zurueckgegeben.
			//    - true: Es wird true an das Formular zurueckgegeben und somit das Formular abgesendet.
			
			jQuery(formSelektor).each(function() {
				
				if(jQuery(this).hasClass('ignoreBecauseLayer')) return;
				
				// 1. Initial-Funktion
				this.initialRemoveDefaults = function(e) {
					
					// Ist die finalRemoveDefaults schon am Ende?
					if(!(this.isFinalRemoveDefaults || false)) {
						
						// Wenn nicht, dann setze jetzt einen neuen Submit-Handler, so dass finalRemoveDefaults() am Ende der
						// Event-Bubble ist.
						jQuery(this).bind('submit', this.finalRemoveDefaults);
						
						// Flag setzen, dass finalRemoveDefaults() jetzt am Ende der Event-Bubble ist.
						this.isFinalRemoveDefaults = true;
						
						// Aktuelle Bubble hier erst einmal stoppen / unterbrechen...
						e.stopImmediatePropagation();
						
						// ..., um den Submit-Event zeitversetzt noch einmal komplett von vorn auszuloesen.
						var tmpDeferedSubmit = function() { jQuery(this).submit(); }.defer(10, this);
						
						tmpDeferedSubmit();
						
						// Abbruch der aktuellen Bubble und Ende der aktuellen Methode.
						return false;
					};
					
					// Wenn isFinalRemoveDefaults true zurueckgegeben hat, wird die Methode fortgesetzt und
					// alle Default-Texte entfernt.
					jQuery(this).find('input[alt]').each(function() {
						
						if (this.getValue() == "") this.value = "";
						
					});
				};
				
				// 3. Final-Funktion
				this.finalRemoveDefaults = function(e) {
					
					// Die finalRemoveDefaults entfernen, um sicherzustellen, dass sie das naechste Mal,
					// wenn sie von initialRemoveDefaults wieder ans Ende gesetzt wird, da man ja nie wissen
					// kann ob inzwischen neue Eventhandler auf submit gesetzt wurden.
					jQuery(this).unbind('submit', this.finalRemoveDefaults);
					this.isFinalRemoveDefaults = false;
					
					// Wenn es ein Result aus der Event-Bubble gab, dann weiterverarbeiten ...
					if(typeof e.result != 'undefined') {
						
						// ... war das Result false, dann alle Default-Texte wieder setzen, da das Absenden abgebrochen wurde.
						if(!e.result) {
						
							var tmpId = eveJs.getElementId(this);
							
							jQuery(this).find('input[alt]').each(function() {
																		  
								eveJs.inputAltOnBlur(this, true);
							});
						};
						
						// ... das Result noch zurueckgeben.
						return e.result;
					};
				};
				
				// Submit-Event fuer das Entfernen / Setzen der "alt"-Defaultexte nun aktiv setzen.
				jQuery(this).bind('submit', this.initialRemoveDefaults);
				
				// Bei einem Reset-Event dafuer Sorge tragen, dass die "Alt"-Texte wieder eingesetzt werden.
				this.onreset = function() {
					
					jQuery(this).find('input[alt]').each(function() {
																		  
						eveJs.inputAltOnBlur(this, true);
					});
			
				}.defer(25, this);
				
				//jQuery(this).append('<input type="reset" />');
				
				// Automatisierte Form Validierung setzen (evtl. einzelnes Eingabefeld validieren)
				if (selektor != "element") eveJs.initializeFormValidation({ formEl : this });
			});
			
			// Jedes Input mit der getValue() Funktion versehen und evtl. den "alt"-Effekt darauf legen.
			jQuery(inputSelektor).each(function() {
				
				this.getValue = function() {
					
					return ((this.value == '' || this.value == (this.getAttribute('alt') || '')) ? '' : this.value );
					
				}.scope(this);
				
				if (this.getAttribute('type') == 'submit' || this.getAttribute('type') == 'image') return;
				
				// Hat das betreffende Input ein gesetztes Alt-Attribut, so wird dieses als Default-Text
				// gesetzt. Wenn nicht, dann wird das Input zumindest sichtbar auf "gesetzt" gestellt, 
				// damit es keinen grauen Text mehr hat.
				if((this.getAttribute('alt') || "") != "") {
					
					// Auf Rotations-Konfiguration pruefen
					this.rotationValue = this.getAttribute('alt') || '';
					this.rotation = false;
					this.activeRotationItem = 0;
					this.resetPosition = false;
					
					if(this.rotationValue.indexOf('{') >= 0 && this.rotationValue.indexOf('}') >= 0) {
					
						var tmpRotationCfg = false;
						
						try { eval("var tmpRotationCfg = " + this.rotationValue.replace("\n", "").replace("\r", "") + ";"); } catch(e) { var tmpRotationCfg = false; };
						
						if((tmpRotationCfg || false)) {
						
							if((tmpRotationCfg.rotation || false)) this.rotation = tmpRotationCfg.rotation || false;
						
							if(typeof tmpRotationCfg.resetPosition == 'number') this.resetPosition = tmpRotationCfg.resetPosition || 0;
							
						} else {
							
							// Wenn aus irgendeinem Grund die Rotation fehl schlegt, das ALT-Attribut leeren, um keine falschen Informationen
							// als Vorbelegung zu haben.
							this.setAttribute('alt', '');
							
							jQuery(this).addClass('set');
							
							return;
						}
					}
					
					// onFocus
					jQuery(this).focus(tmpThis.inputAltOnFocus.scope(this));
					
					// onBlur
					jQuery(this).blur(tmpThis.inputAltOnBlur.scope(this));
					
					// Initial die Default-Texte setzen, insofern das aktuelle Element
					// nicht bereits fokusiert wurde.
					eveJs[(((document.activeElement || false) != this) ? 'inputAltOnBlur' : 'inputAltOnFocus' )](this);
					
				} else {
					
					jQuery(this).addClass('set');
				}
			});
		},
		
		/**
		 * Prueft ob das Value des Eingabefeldes dem Alt-Attribut entspricht, wenn ja, wird das
		 * Eingabefeld geleert und auf eine neutrale Farbe gesetzt. Wird bei "onfocus"-Events
		 * fuer Eingabefelder benoetigt, die Default-Werte darstellen sollen. Siehe auch inputAltOnBlur.
		 *
		 * @member	Eve
		 * @param	{element}	el		Optional: Element, welches geprueft wird (Default this, bei Eventhandlern).
		 */
		inputAltOnFocus : function(el) {
		
			var tmpEl = ((el.nodeName || false) != false) ? el : this;
			
			if (tmpEl.value == tmpEl.getAttribute('alt')) tmpEl.value = '';
			
			tmpEl.isActive = true;
			
			jQuery(tmpEl).addClass('set');
		},
		
		/**
		 * Prueft ob das Value des Eingabefeldes dem Alt-Attribut entspricht, wenn ja ist der
		 * Default-Text aktiv, der Text wird in grau dargestellt. Ist das Eingabefeld leer, wird
		 * der Default-Text eingefuegt, anderfalls erhaelt das Eingabefeld eine neutrale Textfarbe.
		 * Wird fuer onBlur-Events auf Eingabefeldern genutzt. Siehe auch inputAltOnFocus.
		 *
		 * @member	Eve
		 * @param	{element}	el				Optional: Element, welches geprueft wird (Default this, bei Eventhandlern).
		 * @param	{boolean}	checkIfActive	Optional: Wenn true, wird geprueft ob das aktuelle Element aktiv ist, wenn ja, dann wird nicht geblured (Default false) ...
		 */
		inputAltOnBlur : function(el, checkIfActive) {
		
			var tmpEl = ((el.nodeName || false) != false) ? el : this;
			
			// Ob ein Element aktiv bzw. fokusiert wurde nur pruefen, wenn entsprechend angefordert,
			// z. B. beim Absenden eines Formulars, wenn nach Abbruch die Felder wieder mit den
			// Default-Werten bestueckt werden, sonst nicht, da es sonst zu Fehlern kommnt.
			var tmpCheckIfActive = checkIfActive || false;
			
			var tmpActiveEl = (((checkIfActive || false)) ? document.activeElement || (tmpEl.isActive || false) : false );
			
			// Verhindern, dass bei einer Rotation der Wert als "Eingabe" erkannt wird nach einen reload der Seite,
			// da bis dahin die Rotation noch nicht initialisiert wurde ...
			if(tmpActiveEl != tmpEl && (tmpEl.rotation || false) && tmpEl.value != '') {
				
				for (var i = 0; i < tmpEl.rotation.length; i++) {
				
					var tmpVal = tmpEl.rotation[i].title || '';
					
					if(tmpVal == tmpEl.value) {
						
						tmpEl.alt = tmpVal;
						
						tmpEl.activeRotationItem = i;
						
						break;
					}
				}
			}
			
			if((tmpEl.activeRotationFunc || false)) tmpEl.activeRotationFunc.cancelTimeout();
			
			if ((tmpEl.value == '' || tmpEl.value == tmpEl.getAttribute('alt')) && tmpActiveEl != tmpEl) {
				
				tmpEl.isActive = false;
				
				// Wenn Rotationsitems gegeben sind, dann manipuliere diese entsprechend. Es muss zudem darauf geachtet werden,
				// dass die Zusammenhaenge mit der jQuery-Validation auch funktionieren, die triggern aber nur "blur" ...
				if ((tmpEl.rotation || false)) {
				
					if(!(tmpEl.activeRotationFunc || false)) {
						
						tmpEl.startRotation = function(startPos, force) {
							
							if(typeof startPos != 'number' && (force || false)) this.activeRotationItem = (this.activeRotationItem == 0) ? (this.rotation.length - 1) : (this.activeRotationItem - 1);
							
							if (typeof startPos == 'number') this.activeRotationItem = startPos;
							
							var actItem     = this.rotation[this.activeRotationItem];
							var actTitle    = actItem.title || '';
							var actDuration = actItem.duration || 1000;
							
							if((this.isActive || false) !== true) {
							
								this.value = actTitle;
								this.alt = actTitle;
							
								if(this.activeRotationItem < (this.rotation.length - 1)) {
											
									this.activeRotationItem++;
											
								} else {
											
									this.activeRotationItem = 0;
								}
							}
							
							this.activeRotationFunc = this.startRotation.defer(actDuration, this);
							this.activeRotationFunc();
							
						}.scope(tmpEl);
						
						tmpEl.startRotation();
						
					} else {
						
						// Wenn die Funktion bereits existiert, einfach Timeout unterbrechen, neu starten ...
						tmpEl.startRotation(tmpEl.resetPosition, true);
					}
				}
				
				tmpEl.value = tmpEl.getAttribute('alt');
				jQuery(tmpEl).removeClass('set');
				
			} else {
				
				eveJs.inputAltOnFocus(tmpEl);
			}
		},		
		
		
		/**
		 * Stellt eine API zu jQuery.validate zur Verfuegung, die nach Eventim Standards dem Layout angepasst wurde. Die Default-Konfiguration
		 * kann durch individuelle Parameter erstezt werden, dabei sind errorClass, errorPlacement und errorElement und focusInvalid gesperrt.
		 *
		 * Achtung: Diese Funktion steht auch im automatisiertem Zusammenhang mit Eve.inputAltInitialize, dort werden Submit-Handler gesetzt,
		 * die vor dem Submit die Default-Texte entfernen und nach einem abgebrochenen Submit diese wieder einsetzen.
		 *
		 * @member	Eve
		 * @param	{object}	options					Options-Hash:
		 * @param	{mixed}		options.formEl			jQuery-Selektor oder Form-Element fuer das zu validierende Formelement.
		 * @param	{object}	options.validateCfg		Optional: jQuery.validate - Konfiguration fuer das zu validerende Formular.
		 * @parm	{element}	options.validateEl		Optional: Wenn nur ein Element angegeben wird, wird dieses Element der Validation des
		 *												Formulares hinzugefuegt, setzt allerdings voraus, dass das Formular bereits eine
		 *												Validation hat ...
		 */
		initializeFormValidation : function(cfg) {
			
			var cfg            = cfg || {};
			var tmpFormEl      = cfg.formEl || false;
			var tmpValidateCfg = cfg.validateCfg || {};
			var tmpValidateEl  = cfg.validateEl || false;
			
			// Wenn kein Element angegeben wurde, dann Abbruch.
			if(!tmpFormEl) return;
			
			// Wenn das Formular schon validiert wurde und ein einzelnes Element hinzugefuegt
			// wurde, dann dieses per Rule der Validation hinzufuegen. Andernfalls einfach
			// das Formular normal validieren.
			if((tmpFormEl.valCfg || false) && (tmpValidateEl || false)) {
				
				jQuery(tmpFormEl).validate(tmpFormEl.valCfg);
				
				return;
			};
			
			// Validation-Cfg fuer das Layout von Eventim anpassen.
			tmpValidateCfg.errorClass     = 'modsError';
			tmpValidateCfg.errorElement   = 'li';
			tmpValidateCfg.focusInvalid   = false;
			tmpValidateCfg.onfocusout     = false;
			tmpValidateCfg.onkeyup        = false;
			tmpValidateCfg.onclick        = false;
			tmpValidateCfg.errorPlacement = function(error, element) {
				
				// Sucht den naechsthoeheren Div-Container, wenn der nicht gefunden wird,
				// dann wird der parent des aktuellen Objektes genommen.
				var tmpParent = element.parents().map(function () { 
																
						if (this.tagName.toLowerCase() == 'div') return this;
						
				}).get(0) || element.parent();
				
				// Rausfinden, ob es bereits eine UL mit Fehlern gibt, denn dann soll diese
				// genutzt werden, statt da zwei hinzupacken ...
				var tmpParentId = eveJs.getElementId(tmpParent);
				
				var tmpExistingContainer = jQuery('#' + tmpParentId + ' ul.error').get(0) || false;
				
				if(tmpExistingContainer) {
					
					var tmpContainer = tmpExistingContainer;
					
				} else {
					
					var tmpContainer = document.createElement('ul');
					jQuery(tmpContainer).addClass('plain error last');
					jQuery(tmpParent).append(tmpContainer);
				}
				
				error.appendTo(tmpContainer);
			};
			
			// Leider ist es im aktuellen Layout so, dass oftmals mehrere Fehlermeldungen untereinander identisch
			// sind. Dies sieht oftmals unschoen aus, daher mit diesem Workaround die doppelten Meldungen
			// wieder entfernen.
			tmpValidateCfg.invalidHandler = function(a, b) {
				
				var tmpFunc = function(a, b) {
					
					jQuery(b.currentForm).find('ul.error').each(function() {
						
						var schonda = {};
						
						for(var i = 0; i < this.childNodes.length; i++) {
						
							/*
								var tmpNode = this.childNodes[i];
								var ctr = i + 1;
								
								tmpNode.innerHTML = tmpNode.innerHTML + ' (' + ctr + '. Eingabefeld)';
							*/
							
							var tmpNode = this.childNodes[i];
							
							if((schonda[tmpNode.innerHTML] || false)) {
								
								jQuery(tmpNode).remove();
								
							} else {
								
								schonda[tmpNode.innerHTML] = true;
							}
						};
					});
					
				}.defer(10);
				
				tmpFunc(a, b);
			};
			
			// Form Validation jetzt setzen.
			tmpFormEl.valCfg = jQuery(tmpFormEl).validate(tmpValidateCfg);
		},
		
		
		/**
		 * Sucht nach allen Links mit einem Anchor und setzt einen Click-Eventhandler darauf,
		 * klickt ein Nutzer den Link zum Anchor an, sucht das Script nach dem Anchor und wenn
		 * es gefunden wird, scrollt es zu diesem Element, laesst es zweimal blinken.
		 *
		 * @member Eve
		 * @param	{string}	selektor	jQuery Selektor in dem Anchor-Links initialisiert werden sollen.
		 */
		scrollToAnchorInitialize : function(selektor) {
			
			var tmpThis = this;
			
			var selektor = selektor || '.mods';
			
			if (typeof selektor == "string") selektor = selektor + ' a[href*=#]';
			
			jQuery(selektor).each(function() {
		
				// Wenn die CSS-Klasse ignoreScrollFx auf dem Element ist, dann soll / darf dort das
				// aktuelle Feature nicht implementiert werden. Wird auf der Startseite eingesetzt, da JavaScript
				// dort einfach zuviel initialisiert.
				if(jQuery(this).hasClass('ignoreScrollFx')) return;
				
				var tmpHref = eveJs.getRealHref(this);
				
				/** Keine Anchor nutzen, die einen Link voran stehen haben! */
				if(tmpHref.split('#').shift() != '') {
					
					var tmpReg = new RegExp("&amp;", "gi");
					var linkAnchor = tmpHref.split('#');
					
					this.setAttribute('href', linkAnchor[0].replace(tmpReg, "&") + '&scrollToAnchor=' + linkAnchor[1]);
					
					return;
				}
				
				jQuery(this).click(function() {
				
					this.tmpToEl = this.tmpToEl || (jQuery('[name=' + this.hash.slice(1) + ']').get(0) || false);
					if (!this.tmpToEl) return;
					
					eveJs.scrollToElement(this.tmpToEl, 1000, function() {
				
						var nodeName = (this.parentNode.nodeName || '').toLowerCase();
						
						if (nodeName == "div" || nodeName == "body") return;
						
						jQuery(this.parentNode).fadeOut('fast').fadeIn('slow');
				
					}.scope(this.tmpToEl), -10);
				
					return false;
				});
			});
			
			/**
			 * Rausfinden, ob "scrollToAnchor" mit in den Params ist, so dass erst nach dem Laden der Seite
			 * zu dem entsprechenden Anchor gescrolled wird.
			 */
			var tmpParameter = (window.location.search || '').split('scrollToAnchor=');
			
			if (tmpParameter[1] != "") {
				
				this.tmpToEl = this.tmpToEl || (jQuery('[name=' + tmpParameter[1] + ']').get(0) || false);
				if (!this.tmpToEl) return;
				
				eveJs.scrollToElement(this.tmpToEl, 1, false, -10);
			};
		},
		
		getRealHref : function(linkEl) {
		
			if(jQuery.browser.msie) {
				
				var tmpEl = document.createElement('div');
				
				jQuery(tmpEl).html(linkEl.cloneNode(true));
				
				var tmpReg = new RegExp('href="(.*?)"', 'gi');
				var tmpResult = (tmpReg.exec((tmpEl.innerHTML || '')) || [])[1] || linkEl.getAttribute('href');
				
				return tmpResult;
				
			} else {
				
				return linkEl.getAttribute('href');
			}
		},
		
		
		/**
		 * Wird diese Methode ohne jede Angabe ausgefuehrt durchsucht sie den DOM-Tree nach Elementen mit der CSS-Klasse "eveJsHover",
		 * wird ein Selektor angegeben, dann nur der jeweilige Bereich oder direkt das Element. Gefundene Elemente werden mit einem
		 * Hover-Effekt ausgeruestet, wenn die Maus ueber dem betreffendem Element steht, wird dem Element die CSS-Klasse "mouseover"
		 * hinzugefuegt, bei Verlassen des Elements durch die Maus diese CSS-Klasse wieder entfernt.
		 *
		 * Zusaetzlich wird in dem Hover-Element noch nach Kindelementen mit der CSS-Klasse "eveJsLinkToHover" gesucht. Wird dieses
		 * gefunden, so wird davon ausgegangen, dass dieses einen Link bietet, der bei Klick auf das Hover-Element ausgefuehrt werden
		 * soll.
		 *
		 * HBX-Anpassung: Wird die Hoverflaeche oder der gefundene Link angeklickt, muss nun noch zusaetzlich das HBX-Tracking
		 * darueber informiert werden.
		 *
		 * @member	Eve
		 * @param	{mixed}		selektor	Optional: String fuer jQuery-Selektor oder Element, welches den Hover-Effekt erhalten soll.
	     */
		setHoverFx : function(selektor) {
			
			var tmpThis = this;
			
			var isMouseOver = false;
			
			var selektor = selektor || '.mods';
			
			if (typeof selektor == "string") {
				
				selektor = selektor + ' .eveJsHover';
				
			} else {
				
				// Wenn dieser Effekt instant per MouseOver erstellt wurde, dann dies weiterreichen ...
				isMouseOver = eveJs.removeInstant(selektor, true) || false;
			}
			
			jQuery(selektor).each(function() {
				
				this.checkForLink = function() {
					
					this.checkedForLink = true;
					
					/** Nachschauen ob in dem Container ein Link ist, der auf das aktuelle Element gelegt werden soll. */
					var tmpLink = jQuery(this).find('.eveJsLinkToHover').get(0) || false;
					
					if(tmpLink) {
						
						var tmpFunc = function(e) {
							
							// Wenn das Original-Klick-Target des Events ein Link war, dann behalte diesen
							// bei!
							if((e.originalTarget || false)) {
								
								// War das Original-Target ein Link? Dann abbrechen, damit die Klicks nicht
								// doppelt ausgefuehrt werden und HBX das richtige Element trackt.
								if ((e.originalTarget.nodeName || '').toLowerCase() == "a") return;
								
								// War eines der Parents des Original-Targets ein Link, dann ist ebenfalls
								// davon auszugehen, dass dieses angeklickt wurde. Dann abbrechen, damit 
								// die Klicks nicht doppelt ausgefuehrt werden und HBX das richtige Element 
								// trackt.
								var tmpParantLink = jQuery(e.originalTarget).parents().map(function () {
										
									if((this.nodeName || '').toLowerCase() == "a") return this;
								});
								
								if(tmpParantLink.length > 0) return;
							}
							
							// Tracking Anpassung: Da es sein kann, dass auf dem Link ein Tracking stattfinden soll,
							// dies entsprechend vor dem Absenden noch ausfuehren.
							if(typeof trackAndOpenLink != "undefined" && this.name != "") 
								return trackAndOpenLink({ el : this, code: this.name });
							
							// Wenn das target-Attribut des Links gesetzt ist, dann nutze dieses auch.
							var tmpTarget = this.target || false;
							
							if (tmpTarget && tmpTarget != "_self") {
							
								window.open(eveJs.getRealHref(this), tmpTarget);
								
							} else {
								
								window.location.href = eveJs.getRealHref(this); 
							}
							
							return false; 
							
						}.scope(tmpLink);
						
						jQuery(tmpLink).bind('click', tmpFunc);
						jQuery(this).bind('click', tmpFunc);
						jQuery(tmpLink).removeClass('eveJsLinkToHover');
					}
					
				}.scope(this);
				
				jQuery(this).bind('mouseenter', function() {
					
					// Jetzt erst nach einem Link schauen, da es sonst zu drastischen Performance-Einbussen kommen
					// kann, wenn dies bei Initialisierung der Website gemacht wird.
					if(!(this.checkedForLink || false)) this.checkForLink();
					
					jQuery(this).addClass('mouseover');
					
				}).bind('mouseleave', function() {
												  
					jQuery(this).removeClass('mouseover');
					
				}).removeClass('eveJsHover');
				
				// ... wenn dieser Effekt per MouseOver erstellt wurde, dann jetzt, nachdem alle Events erstellt
				// wurden noch "mouseover" triggern ...
				if(isMouseOver) jQuery(this).triggerEvent('mouseenter');
			});
		},
		
		
		/**
		 * Sucht nach allen Textareas mit einer "maxLength" und belegt diese mit einem grafischen
		 * Counter, wieviel Platz noch ist.
		 *
		 * Dies einmal so umaendern, dass die Layer erst dann erstellt werden, wenn in das Feld geklickt
		 * wurde ...
		 *
		 * @member Eve
		 * @param	{string}	selektor	jQuery Selektor in dem Anchor-Links initialisiert werden sollen.
		 */
		textareaLeftLettersInitialize : function(selektor) {
			
			var tmpThis = this;
			
			var selektor = selektor || '.mods';
			
			jQuery(selektor + ' textarea[maxLength]').each(function() {
														   
				/** MaxLength ermitteln */
				if (!(this.countMax = (this.getAttribute('maxLength') || false))) return;
				
				/** Container erstellen */
				var tmpContainer = document.createElement('div');
				jQuery(tmpContainer).addClass('mods');
				tmpContainer.style.position = 'absolute';
				tmpContainer.style['z-index'] = '5';
				
				var tmpContainer1 = document.createElement('div');
				jQuery(tmpContainer1).addClass(' reset lettersLeft');
				
				var tmpContainer2 = document.createElement('div');
				jQuery(tmpContainer2).addClass('lettersLeftInner');
				
				jQuery(tmpContainer).append(tmpContainer1);
				jQuery(tmpContainer1).append(tmpContainer2);
				jQuery('body').append(tmpContainer);
				
				// Layer richtig positionieren.
				var tmpResize = function() {
					
					var tmpTextPos = jQuery(this).offset();
					var tmpTextSize = { width : jQuery(this).outerWidth(), height : jQuery(this).outerHeight() };
					
					tmpContainer.style.top = (Math.ceil(tmpTextPos.top) + tmpTextSize.height) + 'px';
					tmpContainer.style.left = (Math.ceil(tmpTextPos.left) + tmpTextSize.width) + 'px';
					
				}.scope(this);
				
				tmpResize();
				
				jQuery(tmpContainer2).hide();
				
				// Hat einen Defer bekommen, damit die jQuery.validate Methode, die auch die Klasse aendern kann
				// nicht schneller ist als diese Pruefung hier.
				jQuery(this).bind("keydown keypress keyup focus blur click change", function() {
				
					if (this.value.length > this.countMax) this.value = this.value.substr(0, this.countMax);
					
					tmpContainer2.className = this.className + (((this.className || false)) ? ' ' : '' )  + "lettersLeftInner";
					
					jQuery(tmpContainer2).html(eveMessages.textareaLeftLettersInitialize.remaining + ' ' + (this.countMax - this.value.length) + ' ' + eveMessages.textareaLeftLettersInitialize.letters);
					
				}.defer(10, this));
			
				jQuery(this).bind("focus", function() {
					
					tmpResize();
					
					jQuery(tmpContainer2).stop(true, true).fadeIn('slow');
				});
				
				jQuery(this).bind("blur", function() {
							
					jQuery(tmpContainer2).stop(true, true).fadeOut('slow');
				});
				
				jQuery(this).keyup();				
			});
		},
		
		/**
		 * Findet das [n]te Vorkommen eines bestimmten Elternelements.
		 * @member	Eve
		 * @param	{element}	el			Element, dessen Elternelemente durchsucht werden sollen.
		 * @param	{string}	key			Wert nach dem das Elternelement gesucht werden soll (in Abhaengigkeit von type).
		 * @param	{string}	type		Optional: Typ ueber den gesucht werden soll, "id", "nodeName", "className" ... (Default nodeName).
		 * @param	{integer}	pos			Optional: Das wievielte Ergebnis relevant ist (Default 0, also das erste).
		 * @return	Liefert das gefundene Element oder false zurueck.
		 * @type	{mixed}
		 */
		findParent : function(el, key, type, pos) {
		
			var tmpEl   = el || false;
			var tmpKey  = key || false;
			var tmpType = type || 'nodeName';
			var tmpPos  = pos || 0;
			
			if (!tmpEl || !tmpKey) return false;
			
			return jQuery(tmpEl).parents().map(function () {
				
				switch(tmpType) {
					
					case "className" : case "cls" : if(jQuery(this).hasClass(tmpKey)) return this; break;
					
					case "id" : if((this.getAttribute('id') || '') == tmpKey) return this; break;
						
					case "nodeName" : default : if(this.tagName.toLowerCase() == tmpKey.toLowerCase()) return this; break;
				};
			
			}).get(tmpPos) || false;
		},
		
		
		/**
		 * Wird eine Funktion instant, also per mouseover aufgerufen, dann wird das mouseover nicht mehr
		 * benoetigt, die aktuelle Methode prueft dies und entfernt das mouseover ggf. ...
		 * 
		 * @member	Eve
		 * @param	{element}	el			Container-Element.
		 * @param	{boolean}	isInstant	True oder False, wenn True, dann werden bestimmte Attribute entfernt.
		 */
		removeInstant : function(el, isInstant) {
			
			if (!(isInstant || false) || !(el || false)) return;
			
			if (!(el.getAttribute('onmouseover') || false)) return;
			
			el.onmouseover = null;
			
			el.removeAttribute('onmouseover');
			
			return true;
		},
		
		/**
		 * Pruef ein Element auf Inhalt, gibt den gefundenen Wert zurueck, wenn ein Inhalt gesetzt wurde oder die im Falle
		 * einer Checkbox, Select oder Radiobox etwas ausgewaehlt wurde. Andernfalls fale.
		 *
		 * @member	Eve
		 * @param	{element}	el		Zu pruefendes Formular-Element.
		 * @return	Liefert den gefundenen Wert oder false.
		 * @type	{mixed}
		 */
		isFieldSet : function(el) {
			
			if (!(el || false)) return false;
			
			var tmpFoundValue = false;
			
			switch(el.nodeName.toLowerCase()) {
			
				case "input" : case "textarea" :
				
					switch((el.type || '').toLowerCase()) {
						
						case 'radio' : case 'checkbox' : tmpFoundValue = ((el.checked || false)) ? 'checked' : false ; break;
						
						default : tmpFoundValue = el.value; break;
					};
					
					break;
				
				case "select" :
				
					tmpFoundValue = el.options[el.selectedIndex].value;
					
					break;
			};
			
			return (typeof tmpFoundValue != 'undefined' && tmpFoundValue != '') ? tmpFoundValue : false;
		},
		
		/**
		 * Passt die Hoehe der MiniTicketTeaser (siehe Styleguide-Bibliothek und Makro "modulMiniTicketOpen")
		 * an, damit diese immer richtige Abrisskanten haben.
		 *
		 * @member	Eve
		 * @param	{string}	id		ID der Container-Elements.
		 */
		modulMiniTicketSetHeight : function(id) {
			
			jQuery('#' + id + ' .leftEdgeUnsized').each(function() {
			
				// Anzupassendes Hoehenelement ermitteln ...
				var tmpGradient = jQuery(this).find('.gradient').get(0);
				
				// Sicherstellen, dass kein Overflow:hidden drauf ist ...
				jQuery(tmpGradient).css({ 'overflow' : 'visible' });
				
				// Nun Hoehe ermitteln, weniger sichtbaren Abstand unten, damit der Abstand nachher nicht zu enorm wird.
				var actualHeight = jQuery(this).height(); // - 8;
				
				//window.alert(actualHeight);
				
				// Wieviel Pixel von 15 sind schon erreicht?
				var tmpDiff = (15 - (actualHeight % 15));
				
				//window.alert(tmpDiff);
				
				// Ist die Differenz niedriger als 14, dann mach die Box hoeher.
				if(tmpDiff <= 14) jQuery(tmpGradient).css({ 'height' : (actualHeight + tmpDiff + 1) + 'px', 'overflow' : 'hidden' });
				
				// Damit nicht nochmal gemessen wird, die identifizierende CSS-Klasse entfernen.
				jQuery(this).removeClass('leftEdgeUnsized');
			});
		},
		
		oldmsie : ((jQuery.browser.msie && (jQuery.browser.version * 1) > 6) ? false : true ),
		
		encodeURIByCharset : function(text, charset) {

			var text           = text || '';
			var encodedText    = '';
			var defaultCharset = 'ISO-5589-1';
			
			var charsets = {
				
				// Hier werden nur die wesentlichsten Zeichen neu kodiert, da es durch den /packer evtl. sonst zu Problemen kommen
				// kann.
				'ISO-5589-1' : { 
					' ':'%20', '!':'%21', '"':'%22', '#':'%23', '$':'%24', '%':'%25', '&':'%26', "'":'%27', '(':'%28', ')':'%29', 
					'*':'%2A', '+':'%2B', ',':'%2C', '-':'%2D', '.':'%2E', '/':'%2F', ':':'%3A', ';':'%3B', '<':'%3C', '=':'%3D', 
					'>':'%3E', '?':'%3F', '@':'%40', '[':'%5B', ']':'%5D', '^':'%5E', '_':'%5F', '`':'%60', '{':'%7B', '|':'%7C', 
					'}':'%7D', '~':'%7E', '€':'%80', '‚':'%82', 'ƒ':'%83', '„':'%84', '…':'%85', 'Š':'%8A', '‹':'%8B', 'Œ':'%8C', 
					'Ž':'%8E', '‘':'%91', '’':'%92', '“':'%93', '”':'%94', '–':'%96', '—':'%97', 'š':'%9A', '›':'%9B', 'œ':'%9C',
					'ž':'%9E', 'Ÿ':'%9F', '¢':'%A2', '£':'%A3', '¥':'%A5', '|':'%A6', '§':'%A7', '«':'%AB', '´':'%B4', 'µ':'%B5',
					'¶':'%B6', '»':'%BB', 'À':'%C0', 'Á':'%C1', 'Â':'%C2', 'Ã':'%C3', 'Ä':'%C4', 'Å':'%C5', 'Æ':'%C6', 'Ç':'%C7',
					'È':'%C8', 'É':'%C9', 'Ê':'%CA', 'Ë':'%CB', 'Ì':'%CC', 'Í':'%CD', 'Î':'%CE', 'Ï':'%CF', 'Ð':'%D0', 'Ñ':'%D1', 
					'Ò':'%D2', 'Ó':'%D3', 'Ô':'%D4', 'Õ':'%D5', 'Ö':'%D6', 'Ø':'%D8', 'Ù':'%D9', 'Ú':'%DA', 'Û':'%DB', 'Ü':'%DC',
					'Ý':'%DD', 'Þ':'%DE', 'ß':'%DF', 'à':'%E0', 'á':'%E1', 'â':'%E2', 'ã':'%E3', 'ä':'%E4', 'å':'%E5', 'æ':'%E6',
					'ç':'%E7', 'è':'%E8', 'é':'%E9', 'ê':'%EA', 'ë':'%EB', 'ì':'%EC', 'í':'%ED', 'î':'%EE', 'ï':'%EF', 'ð':'%F0',
					'ñ':'%F1', 'ò':'%F2', 'ó':'%F3', 'ô':'%F4', 'õ':'%F5', 'ö':'%F6', '÷':'%F7', 'ù':'%F9', 'ú':'%FA', 'û':'%FB',
					'ü':'%FC', 'ý':'%FD', 'þ':'%FE', 'ÿ':'%FF', '°':'%B0'
				}
			};
			
			var charset = (charsets[(charset || defaultCharset)] || charsets[defaultCharset]);
			
			for(var i = 0; i < text.length; i++) {
				
				var tmpLetter = text.substr(i, 1);
				encodedText += (charset[tmpLetter] || tmpLetter);
			};
			
			return encodedText;
		},
		
		/**
		 * Belegt ein Javascript-Objekt oder DOM-Element mit einem Eventhandler
		 *
		 * @member	Eve
		 * @param	{element/object}	target		JavaScript-Objekt oder DOM-Element, welches einen EventHandler erhalten soll.
		 */
		setUpEventHandler : function(target) {
			
			target.bindedEvents = target.bindedEvents || {};
			
			// Event registrieren.
			target.bindEvent = this.bindEvent.scope(target);
			
			// Event entfernen
			target.unbindEvent = this.unbindEvent.scope(target);
			
			// Event feuern ...
			target.triggerEvent = this.triggerEvent.scope(target);
		},
		
		/**
		 * Event registrieren.
		 *
		 * @member	Eve
		 * @param	{string}	eventName		Name des zu registrierenden Events.
		 * @param	{function}	callback		Funktion die auf diesen Event als Callback registriert wird.
		 */
		bindEvent : function(eventName, callback) {
			
			// Innerhalb der Methode initialisieren, da es aktuell noch Probleme beim Extenden der JavaScript-Klasse
			// gibt und sonst alle die gleiche Variable nutzen (08-01-2010, hpb).
			this.bindedEvents = this.bindedEvents || {};
			
			this.bindedEvents[eventName] = this.bindedEvents[eventName] || {};
			
			callback.id = eveJs.getUniqueId();
			
			this.bindedEvents[eventName][callback.id] = callback;
		},
		
		/**
		 * Event entfernen.
		 *
		 * @member	Eve
		 * @param	{string}	eventName		Name des zuvor registrierten Events.
		 * @param	{function}	callback		Funktion die auf diesen Event zuvor als Callback registriert wurde.
		 */
		unbindEvent : function(eventName, callback) {
			
			if(!(callback.id || false)) return;
			
			// Innerhalb der Methode initialisieren, da es aktuell noch Probleme beim Extenden der JavaScript-Klasse
			// gibt und sonst alle die gleiche Variable nutzen (08-01-2010, hpb).
			this.bindedEvents = this.bindedEvents || {};
			
			if(!(this.bindedEvents[eventName] || false)) return;
			
			if(!(this.bindedEvents[eventName][callback.id] || false)) return;
			
			this.bindedEvents[eventName][callback.id] = null;
		},
		
		/**
		 * Event feuern / ausloesen. Es wird der Eventname gefeuert und alle darauf horchenden Listener bzw. deren
		 * registrierten Callbacks aufgerufen.
		 *
		 * @member	Eve
		 * @param	{string}	eventName		Name des zu feuernden Events.
		 */
		triggerEvent : function(eventName) {
			
			// Innerhalb der Methode initialisieren, da es aktuell noch Probleme beim Extenden der JavaScript-Klasse
			// gibt und sonst alle die gleiche Variable nutzen (08-01-2010, hpb).
			this.bindedEvents = this.bindedEvents || {};
			
			if(!(this.bindedEvents[eventName] || false)) return;
			
			for(var i in this.bindedEvents[eventName]) {
				
				if((this.bindedEvents[eventName][i] || false)) this.bindedEvents[eventName][i](this);
			};
		},
		
		/**
		 * private property for base64-methods.
		 * @param	{string}	_keyStr
		 */
		_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
		 
		/**
		 * Kodiert die Eingabe in einen Base64-String und gibt diesen zurueck.
		 *
		 * @member	Eve
		 * @param	{string}	input		Zu kodierender String.
		 * @return	{string}	Liefert einen Base64 kodierten String zurueck.
		 */
		base64_encode : function (input) {
				
			var output = "";
			var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
			var i = 0;
		 
			input = this.utf8_encode(input);
		 
			while (i < input.length) {
		 
				chr1 = input.charCodeAt(i++);
				chr2 = input.charCodeAt(i++);
				chr3 = input.charCodeAt(i++);
	 
				enc1 = chr1 >> 2;
				enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
				enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
				enc4 = chr3 & 63;
	 
				if (isNaN(chr2)) {
					enc3 = enc4 = 64;
				} else if (isNaN(chr3)) {
					enc4 = 64;
				}
	 
				output = output + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
			};
		 
			return output;
		},
		 
		/**
		 * Dekodiert die Eingabe (Base64-String) in einen normalen String und gibt diesen zurueck.
		 *
		 * @member	Eve
		 * @param	{string}	input		Zu dekodierender Base64-String.
		 * @return	{string}	Liefert einen unkodierten String zurueck.
		 */
		base64_decode : function (input) {
				
			var output = "";
			var chr1, chr2, chr3;
			var enc1, enc2, enc3, enc4;
			var i = 0;
	 
			input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
	 
			while (i < input.length) {
	 
				enc1 = this._keyStr.indexOf(input.charAt(i++));
				enc2 = this._keyStr.indexOf(input.charAt(i++));
				enc3 = this._keyStr.indexOf(input.charAt(i++));
				enc4 = this._keyStr.indexOf(input.charAt(i++));
	 
				chr1 = (enc1 << 2) | (enc2 >> 4);
				chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
				chr3 = ((enc3 & 3) << 6) | enc4;
	 
				output = output + String.fromCharCode(chr1);
	 
				if (enc3 != 64) output = output + String.fromCharCode(chr2);
				if (enc4 != 64) output = output + String.fromCharCode(chr3);	 
			};
	 
			output = this.utf8_decode(output);
	 
			return output;
	 
		},
		 
		/**
		 * Kodiert die Eingabe in einen UTF8-String und gibt diesen zurueck.
		 *
		 * @member	Eve
		 * @param	{string}	input		Zu kodierender String.
		 * @return	{string}	Liefert einen UTF8 kodierten String zurueck.
		 */
		utf8_encode : function (string) {
			
			string = string.replace(/\r\n/g,"\n");
			var utftext = "";
	 
			for (var n = 0; n < string.length; n++) {
	 
				var c = string.charCodeAt(n);
	 
				if (c < 128) {
					
					utftext += String.fromCharCode(c);
					
				} else if((c > 127) && (c < 2048)) {
				
					utftext += String.fromCharCode((c >> 6) | 192);
					utftext += String.fromCharCode((c & 63) | 128);
					
				} else {
				
					utftext += String.fromCharCode((c >> 12) | 224);
					utftext += String.fromCharCode(((c >> 6) & 63) | 128);
					utftext += String.fromCharCode((c & 63) | 128);
				}	 
			};
	 
			return utftext;
		},
		 
		/**
		 * Dekodiert die Eingabe (UTF8-String) in einen normalen String und gibt diesen zurueck.
		 *
		 * @member	Eve
		 * @param	{string}	input		Zu dekodierender UTF8-String.
		 * @return	{string}	Liefert einen unkodierten String zurueck.
		 */
		utf8_decode : function (utftext) {
			
			var string = "";
			var i = 0;
			var c = c1 = c2 = 0;
	 
			while ( i < utftext.length ) {
	 
				c = utftext.charCodeAt(i);
	 
				if (c < 128) {
					
					string += String.fromCharCode(c);
					i++;
					
				} else if((c > 191) && (c < 224)) {
					
					c2 = utftext.charCodeAt(i+1);
					string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
					i += 2;
					
				} else {
					
					c2 = utftext.charCodeAt(i+1);
					c3 = utftext.charCodeAt(i+2);
					string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
					i += 3;
				}	 
			};
	 
			return string;
		},
		
		/**
		 * Beispiel-Methode, als Vorlage fuer neu zu erstellende Methoden.
		 *
		 * @member	Eve
		 * @param	{object}	options			Optionshash:
		 * @param	{element}	options.el		DOM-Element.
		 */
		exampleMethod : function(options) {
			
			console.debug(options);
			
			return 'juju';
		}
	};
	
	var eveJs = new Eve();
	var initializeElements = function() {
		
		eveJs.initializeHtmlElements();
		
		initializeElements();
		
	}.defer(100);
	
	//initializeElements();
	
jQuery(function() {
	
	/** 
	 * Beispiel fuer eine Kombination zwischen jQuery und eveJs:
	 * Ruft fuer jedes a-Element die Beispiel-Methode auf und uebergibt das Element.
	 */
	// jQuery('a').each(function() { eveJs.exampleMethod({ el:this }); });
	
	/** 
	 * Beispiel fuer eine Kombination zwischen jQuery und eveJs:
	 * Ruft die Beispiel-Methode auf und uebergibt ein per jQuery uebergebenes Element.
	 */
	// eveJs.exampleMethod({ el:jQuery('a').get(0) });
	
	/**
	 * Wenn die Seite geladen wurde, dann koennen alle eveJs-Elemente ausgelesen
	 * werden und zwecks Funktion belegt werden.
	 */
	eveJs.initializeHtmlElements();
	
	/**
	 * Input-Felder fuer Alt-Feature initialisieren ...
	 */
	eveJs.inputAltInitialize();
	
	/**
	 * ScrollToElements durch Anchor initialisieren ...
	 */
	eveJs.scrollToAnchorInitialize();
	
	/**
	 * Textareas mit Counter initialisieren
	 */
	eveJs.textareaLeftLettersInitialize();
	
	/**
	 * Initalisieren alle Elemente, die einen Hover-Effekt haben sollen, wenn man mit
	 * der Maus darueber geht.
	 */
	eveJs.setHoverFx();
});
