//Mock console object when console not available
if (!this.console) {
	this.console = {};
	this.console.log = function() {};
}
/** 
 * extend Modernizr tests
 */
Modernizr.addTest('utf8', function() {
	return navigator.userAgent.match(/Windows/) ? false : true;
});
Modernizr.addTest('ios', function() {
	return !!navigator.platform.match(/iPhone|iPod|iPad/);
});
Modernizr.addTest('ioslt4', function() {
	var ios = navigator.userAgent.match(/OS ([0-9_]{5}) like Mac OS X/);
	if (!ios) {
		return false;
	}
	return ios[1].replace(/_/g, '') < 400;
});
Modernizr.addTest('filereader', function() {
	return typeof FileReader != 'undefined';
});

/**
 * @namespace Holds functionality
 */
YUI.namespace('SIM');  

YUI({ 
	bootstrap : false,
	classNamePrefix : "sim",
	modules : {
		swfobject : {
			path : "../../swfobject-2.2/swfobject.js" // relative from base
		}
	}
}).use('*', function(Y) {

	/**
	 * DOM Nodes that are used frequently
	 */
	YUI.SIM.Nodes = function() {
		return {
			Body : Y.one('body'),
			Document : Y.one('document'),
			Content : Y.one('.innerShadowWrapper')
		};
	}();

	/**
	 * @Class holds UiHelpers
	 */
	YUI.SIM.UiHelpers = function() {
		return {
			/**
			 * Formats a number as german number string
			 * 
			 * @function
			 * @param {Integer|Float}
			 *            zahl Number
			 * @param {Integer}
			 *            decimals Number of decimals
			 * @param {Boolean}
			 *            fill Defines if missing decimals should be filled up
			 *            or not
			 * @return (String) Formatted number
			 */
			formatNumber : function(zahl, decimals, fill) {
				if (!decimals) {
					decimals = 0;
				}
				var neu = '';
				var dec_point = ',';
				var thousands_sep = '.';

				// Runden
				var f = Math.pow(10, decimals);
				zahl = '' + parseInt(zahl * f + (0.5 * (zahl > 0 ? 1 : -1)), 10) / f;

				// Komma ermittlen
				var idx = zahl.indexOf('.');

				// fehlende Nullen einfügen
				if (fill) {
					zahl += (idx == -1 ? '.' : '') + f.toString().substring(1);
				}

				var sign = (zahl < 0);
				if (sign) {
					zahl = zahl.substring(1);
				}
				idx = zahl.indexOf('.');

				// Nachkommastellen ermittlen
				if (idx == -1) {
					idx = zahl.length;
				} else {
					neu = dec_point + zahl.substr(idx + 1, decimals);
				}

				while (idx > 0) {
					if (idx - 3 > 0) {
						neu = thousands_sep + zahl.substring(idx - 3, idx) + neu;
					} else {
						neu = zahl.substring(0, idx) + neu;
					}
					idx -= 3;
				}
				return (sign ? '-' : '') + neu;

			},
			/**
			 * Parse and convert german format string to float
			 * 
			 * @function
			 * @param {Number}
			 *            value Value to coerce to float
			 */
			cleanFloat : function(value) {
				value = (value + '').replace(/\./g, '');
				value = parseFloat(value.replace(',', '.'), 10);
				return isNaN(value) ? 0 : value;
			},
			/**
			 * Find a class based on prefix and return the remaining chunk of
			 * the name
			 * 
			 * @function
			 */
			getPrefixedClass : function(prefix, classAttributeString) {
				var classList = classAttributeString.split(' ');
				for ( var cName in classList) {
					var className = classList[cName];

					if (0 <= className.indexOf(prefix)) {
						return className.substr(prefix.length);
					}
				}
				return false;
			},

			/**
			 * StepIteratorController
			 * 
			 * @class Steps through a given set of elements
			 */
			StepIterator : function(stepList, config, cbLastElement) {
				var _cbLastElement, _currentElement = 1, /*
															 * Mayb ould make
															 * this onfigureable
															 * later
															 */
				_toggleClass, _stepList;

				// private functions
				/**
				 * Triggers the last element event
				 */
				var _triggerLast = function() {
					if (!!_cbLastElement) {
						_cbLastElement(); // trigger callback
					}
				};
				/**
				 * Triggers the next element event
				 */
				var _triggerNext = function() {
					_stepList.item(_currentElement).toggleClass(_toggleClass);
					if (_currentElement == _stepList.size() - 1) {
						_triggerLast();
					} else {
						++_currentElement;
					}
				};

				// public functions
				/**
				 * Shows the next step
				 */
				this.showNext = function() {
					if (!!_stepList.size() && 0 < _stepList.size()) {
						_triggerNext();
					}
				};

				// constructor
				_stepList = stepList;
				_cbLastElement = cbLastElement;
				_toggleClass = config.cssClass || 'jsHidden';
			},
			/**
			 * Strip HTML-Tags
			 */
			stripHtmlTags : function(str) {
				var str = str.replace(/&(lt|gt);/g, function(strMatch, p1) {
					return (p1 == "lt") ? "<" : ">";
				});
				str = str.replace(/<\/?[^>]+(>|$)/g, "");
				str = str.replace(/&nbsp;/g, " ");
				return str;
			},
			trimLeft : function(str) {
				var str = str.replace(/^\s+/, "");
				return str;
			},
			trimRight : function(str) {
				var str = str.replace(/\s+$/, "");
				return str;
			},
			trimSpaces : function(str) {
				var str = str.replace(/(\r\n|\n|\r|\t)/gm, "");
				str = str.replace(/\s+/gm, " ");
				return str;
			},
			trimWhitespace : function(str) {
				var str = YUI.SIM.UiHelpers.trimSpaces(str);
				str = YUI.SIM.UiHelpers.trimLeft(str);
				str = YUI.SIM.UiHelpers.trimRight(str);
				return str;
			},
			createCookie : function(name,value,days) {
				if (days) {
					var date = new Date();
					date.setTime(date.getTime()+(days*24*60*60*1000));
					var expires = "; expires="+date.toGMTString();
				}
				else if(days===0){
					var expires = "; expires=0";					
				}
				else {
					var expires = "";
				}				
				document.cookie = name+"="+value+expires+"; path=/";				
			},			
			readCookie : function(name) {
				var nameEQ = name + "=";
				var ca = document.cookie.split(';');
				for(var i=0;i < ca.length;i++) {
					var c = ca[i];
					while (c.charAt(0)==' ') c = c.substring(1,c.length);
					if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
				}
				return null;			
			},
			eraseCookie : function(name) {
				YUI.SIM.UiHelpers.createCookie(name,"",-1);			
			}
		};
	}();

	YUI.SIM.Utils = function() {
		return {
			/**
			 * Provides a utility function to create constant properties for
			 * classes. Use it within a constructor function like this:
			 * YUI.SIM.Utils.defineConstantProperty(this, 'EXAMPLE_PROP',
			 * 'exampleValue');
			 */
			defineConstantProperty : function(obj, name, value) {
				if ('defineProperty' in Object) {
					Object.defineProperty(obj, name, {
						value: value,
						writable: false,
						enumerable: false,
						configurable: false
					});
				} else {
					obj[name] = value;
				}
			}
		};
	}();
	
	YUI.SIM.TagEmbed = function() {
		var elmList = Y.all('.js_tagembed');
		if (elmList.size() > 0) {
			elmList.each(function(elm) {
				var tag = elm.getAttribute('data-tag');
				if (!tag) return;
				tag = decodeURIComponent(tag);
				elm.removeAttribute('data-tag').append(tag);
			});
		}
		var iframes = Y.all('.js_asynciframe');
		if (iframes.size() > 0) {
			iframes.each(function(elm) {
				var src = elm.getAttribute('data-src');
				if (!src) return;
				elm.removeAttribute('data-src');
				elm.setAttribute('src', src);
			});
		}
	};

	/**
	 * @Class Tracking handles custom tracking requirements
	 * @TODO We may want to inject the tracking object as dependency here.
	 */
	YUI.SIM.Tracking = function() {
		/**
		 * fetches the tracking vars from the dom
		 * 
		 * @param {Node}
		 *            node teasernode
		 */
		var getTeaserTrackingString = function(node) {
			var slotNumber = node.one('.js_teaserSlotNumber').get('value');
			var slotPosition = node.one('.js_teaserSlotPosition').get('value');
			var teaserName = node.one('.js_teaserName').get('value');
			return 's' + slotNumber + 'p' + slotPosition + '|' + teaserName;
		};

		return {
			/**
			 * Initializes the tracking eventhandlers
			 * 
			 * @function
			 */
			initialize : function() {

				// Load SiteCatalyst:
				Y.Get.script("/extensions/js/lib/sitecatalyst-h-20.3/simyo_s_code.js", {
					onSuccess: function(){
						for (var key in t) { 
							if (t.hasOwnProperty(key)) {
								s[key] = t[key]; 
							}
						}
						try{ 
							s.t(); 
							t = s;
							Y.fire('tracking:sitecatalystAvailable');
						} 
						catch (e) { 
							console.log('Tracking: ' + e.description); 
						} 
					}, 
					onFailure: function(){
						return;
					} 
				});
				
				Y.on('tracking:sitecatalystAvailable', function(){
					// print
					Y.delegate("click", YUI.SIM.Tracking.printButton, YUI.SIM.Nodes.Body, '.js_printButton');
	
					// teaser
					Y.delegate("click", YUI.SIM.Tracking.teaser, YUI.SIM.Nodes.Body, '.js_teaser .js_teaserTrigger');
					Y.delegate("click", YUI.SIM.Tracking.teaser, YUI.SIM.Nodes.Body, '.js_campaignTeaser .js_teaserTrigger');
	
					// login tracking
					Y.delegate("click", YUI.SIM.Tracking.login, YUI.SIM.Nodes.Body, '.js_loginButton');
	
					// Orderbutton tracking
					Y.delegate("click", YUI.SIM.Tracking.order, YUI.SIM.Nodes.Body, '.js_orderButton');
	
					// social bar elements
					// Y.delegate("click", YUI.SIM.Tracking.simRecommendButton,
					// YUI.SIM.Nodes.Body, '.socialmail>a');
					// Y.delegate("click", YUI.SIM.Tracking.simRecommendSend,
					// YUI.SIM.Nodes.Body, '.socialmail .js_send_recommendation');
	
					// mein simyo dashboard items
					Y.delegate("click", YUI.SIM.Tracking.meinSimyoDashboard, '.js_dashboard_container', 'a');
	
					// Seitenbereiche
					/*
					 * Y.delegate("click", YUI.SIM.Tracking.palMainNav,
					 * YUI.SIM.Nodes.Body, 'ul.mainNavigation a');
					 * Y.delegate("click", YUI.SIM.Tracking.palTagCloud,
					 * YUI.SIM.Nodes.Body, '#tagCloud ul a');
					 * Y.delegate("click", YUI.SIM.Tracking.palValuable,
					 * YUI.SIM.Nodes.Body, '.valuableCol a');
					 * Y.delegate("click", YUI.SIM.Tracking.palFooterNav,
					 * YUI.SIM.Nodes.Body, '.footnotesLine .bd a, #footer a');
					 * Y.delegate("click", YUI.SIM.Tracking.palMainContent,
					 * YUI.SIM.Nodes.Body, '.contentArea div.fullLine a,
					 * .contentArea div.line a, .contentArea div.standardLine
					 * a');
					 */

				});
					
			},
			/**
			 * track print clicks
			 * 
			 * @function
			 * @param {Event}
			 *            e Event Object
			 */
			printButton : function(e) {
				try {
					var tracker = s;
					tracker.events = "event31";
					tracker.linkTrackVars = "events,eVar10";
					tracker.linkTrackEvents = "event31";
					tracker.tl(e, "o", 'Print');
				} catch (ex) {
					console.log('Tracking: ' + ex.description);
				}
			},
			/**
			 * track page area links
			 */
			/*
			 * palMainNav: function(e) {
			 * YUI.SIM.Tracking.pageAreaTracking(e,'MainNav'); }, palTagCloud:
			 * function(e) { YUI.SIM.Tracking.pageAreaTracking(e,'TagCloud'); },
			 * palValuable: function(e) {
			 * YUI.SIM.Tracking.pageAreaTracking(e,'ValuableCol'); },
			 * palFooterNav: function(e) {
			 * YUI.SIM.Tracking.pageAreaTracking(e,'FooterNav'); },
			 * palMainContent: function(e) {
			 * YUI.SIM.Tracking.pageAreaTracking(e,'MainContent'); },
			 * pageAreaTracking: function(e, area) { try { var t =
			 * e.currentTarget; var extern = t.get('href').indexOf('simyo.de') ==
			 * -1 && t.get('href').indexOf('localhost') == -1; if(!extern) { var
			 * tracker = s; tracker.linkTrackVars="prop3"; var name =
			 * t.get('text').replace(/^\s*([\S\s]*?)\s*$/, '$1'); var prop3 =
			 * area + '_' + name; tracker.prop3 = prop3; tracker.tl(e, "o",
			 * 'PageArea'); } } catch (ex) { console.log('Tracking: ' +
			 * ex.description); } },
			 */
			meinSimyoDashboard : function(e) {
				try {
					var t = e.currentTarget;
					var extern = t.get('href').indexOf('simyo.de') == -1 && t.get('href').indexOf('localhost') == -1;
					if (!extern) {// nicht bei externen links, diese werden
						// extra getrackt
						var tracker = s;
						var ttitle = t.one('img') ? 'icon' : t.get('text');
						if (!t.hasClass('js_itemTitle')) {
							var b = t.ancestor('.js_optionBox');
							var btitle = b.one('.js_itemTitle').get('text');
							var item = btitle + '_' + ttitle;
						} else {
							var item = t.get('text');
						}
						tracker.eVar31 = item;
						tracker.linkTrackVars = "eVar31";
						tracker.tl(e, "o", item);
					}
				} catch (ex) {
					console.log('Tracking: ' + ex.description);
				}
			},
			/*
			 * simRecommendButton : function(e) { e.preventDefault(); try { var
			 * tracker = s; tracker.events = "event57"; tracker.linkTrackVars =
			 * "events,eVar30"; tracker.linkTrackEvents = "event57";
			 * tracker.eVar30 = "Recommend_mail"; tracker.tl(e, "o",
			 * 'Recommend_mail'); } catch (ex) { console.log('Tracking: ' +
			 * ex.description); } }, simRecommendSend : function(e) {
			 * e.preventDefault(); try { var tracker = s; tracker.events =
			 * "event58"; tracker.linkTrackVars = "events";
			 * tracker.linkTrackEvents = "event58"; tracker.tl(e, "o",
			 * 'Recommend_mail'); } catch (ex) { console.log('Tracking: ' +
			 * ex.description); } },
			 */

			/**
			 * track teaser clicks
			 * 
			 * @function
			 * @param {Event}
			 *            e Event Object
			 */
			teaser : function(e) {
				try {
					var teaserNode, teaserTrackingString, tracker = s;

					teaserNode = e.currentTarget.ancestor('.js_teaser, .js_campaignTeaser', true);

					teaserTrackingString = tracker.pageName + '_' + getTeaserTrackingString(teaserNode);

					// console.log('Tracking: ' + teaserTrackingString);
					tracker.eVar1 = teaserTrackingString;
					tracker.linkTrackVars = "eVar1";
					tracker.tl(e, "o", teaserTrackingString);
				} catch (ex) {
					console.log('Tracking: ' + ex.description);
				}
			},
			/**
			 * track login clicks
			 * 
			 * @function
			 * @param {Event}
			 *            e Event Object
			 */
			login : function(e) {
				try {
					var tracker = s;

					tracker.eVar16 = tracker.pageName;
					tracker.linkTrackVars = "eVar16";
					tracker.tl(e, "o", 'Loginbutton');
				} catch (ex) {
					console.log('Tracking: ' + ex.description);
				}
			},
			/**
			 * track orderbutton clicks NOTE! This most likely not combineable
			 * with other tl tracking functions (testing needed)
			 * 
			 * @function
			 * @param {Event}
			 *            e Event Object
			 */
			order : function(e) {
				try {
					var tracker = s, buttonIndex = Y.all('.js_loginButton').indexOf(node);

					tracker.eVar14 = tracker.pageName + '-' + buttonIndex;
					tracker.linkTrackVars = "eVar14";
					tracker.tl(e, "o", 'Orderbutton');
				} catch (ex) {
					console.log('Tracking: ' + ex.description);
				}
			}
		};
	}();

	/**
	 * @Class Static methods for site behaviour
	 */
	YUI.SIM.Behaviour = function() {
		var _bindTriggers = function() {
			Y.all('.js_chgTriggerNextSubmit').on('change', YUI.SIM.Behaviour.triggerNextSubmitButton);
		};
		return {
			initialize : function() {
				// Default submit button
				Y.delegate("keypress", YUI.SIM.Behaviour.defaultSubmitButton, YUI.SIM.Nodes.Body, 'input[type="text"],input[type="password"],input.typeText');

				// Print button
				Y.delegate("click", YUI.SIM.Behaviour.print, YUI.SIM.Nodes.Body, '.js_printButton');

				// Prevent paste
				Y.delegate("paste", YUI.SIM.Behaviour.preventPaste, YUI.SIM.Nodes.Body, '.js_preventPaste');

				// Autosubmit on change
				// Y.delegate("change",
				// YUI.SIM.Behaviour.triggerNextSubmitButton, 'body',
				// '.js_chgTriggerNextSubmit'); // change does not bubble in IE
				// so we have to bind and rebind on xhr
				YUI.SIM.JsfFacade.addAjaxEventListener(YUI.SIM.Behaviour.onXHR);
				_bindTriggers();

				// Autofocus if element is visible
				var focusNode = Y.one('.js_focus');
				if (focusNode && focusNode.get('region').height > 0) {
					focusNode.focus();
				}
			},
			/**
			 * Reinitialization after partial page rendering
			 * 
			 * @function
			 * @param {object}
			 *            data Jsf XHR data object
			 */
			onXHR : function(data) {
				if ('success' === data.status) {
					_bindTriggers();
				}
			},
			/**
			 * Find and submits a defined default button if found
			 * 
			 * @function
			 * @param {Event}
			 *            e Event Object
			 */
			triggerNextSubmitButton : function(e) {
				var button = e.target.next('input[type="submit"]');
				if (button) { // we found a button execute it
					e.halt();
					button.invoke('click');
				}
			},
			/**
			 * Find and submits a defined default button if found
			 * 
			 * @function
			 * @param {Event}
			 *            e Event Object
			 */
			defaultSubmitButton : function(e) {
				if (13 == e.keyCode) {
					var section = e.currentTarget.ancestor('.js_formSection');
					if (section) {
						var button = section.one('.js_formDefaultButton');

						if (button) { // we found a button execute it
							e.halt();
							if (button.get('localName') === 'a') {
								var domButton = Y.Node.getDOMNode(button);
								if (domButton.onclick) domButton.onclick();
							}
							else {
								button.invoke('click');
							}
						}
					}
				}
				// fallback to browser default behaviour
			},
			/**
			 * Triggers browser prinf function
			 * 
			 * @param {Event}
			 *            e Event object
			 */
			print : function(e) {
				e.preventDefault();
				window.print();
			},
			/**
			 * prevents paste
			 * 
			 * @param {Event}
			 *            e Event object
			 */
			preventPaste : function(e) {
				e.preventDefault();
			}
		};
	}();

	/**
	 * JSF Facade
	 * 
	 * @class Provides a facade to the jsf api
	 * @requires jsf
	 * @TODO jsf should be mocked in prototype
	 */
	YUI.SIM.JsfFacade = function() {
		/**
		 * Handles jsf Ajax Errors
		 * 
		 * @param {Object}
		 *            data dataobject representing the error
		 */
		var handleError = function(data) {
			console.log('JsfFacade: Ajax error ', data);
		};

		var handleEvent = function(data) {
			console.log('JsfFacade: event ', data);
		};

		// Register error handler cb
		if (typeof (jsf) !== 'undefined') {
			jsf.ajax.addOnError(handleError);
		}

		return {

			executeAjaxCall : function(params) {
				var options = {
					execute : params.execute,
					render : params.render
				};
				var ev = {
					type : 'click'
				};
				jsf.ajax.request(params.id, ev, options);
			},
			executeWidgetAjaxCall : function(widget, handler) {
				// the boundingbox is the source of the event
				// the widgetComponent shall be executed and rerendered
				var elid = widget.get('boundingBox').get('id');
				var id = widget.get('jsfComponentId');
				var render= widget.get('render') || id;
				var execute= widget.get('execute') || id;
				var options = {
					execute : execute,
					render : render
				};
				options.onevent = function(e) {
					if (handler && handler.onSuccess && e.status == 'success') {
						handler.onSuccess(e);
					}
					if (handler && handler.onComplete && e.status == 'complete') {
						handler.onComplete(e);
					}
					if (handler && handler.onError && e.status == 'complete') {
						handler.onError(e);
					}
				}
				var ev = {
					type : 'click'
				};
				jsf.ajax.request(elid, ev, options);
			},
			/**
			 * Executes ajax buttons
			 * 
			 * @function
			 * @param {Event}
			 *            e Event object
			 * @param {Node}
			 *            button Button node
			 * @throws {InvalidButton}
			 *             If no Button element passed to function
			 */
			submitAjaxButton : function(e, button, render, onevent, tempOptions) {
				if (typeof (jsf) === 'undefined' && (!!button)) {
					return true;
				} // No submit without jsf api
				if (button === null) {
					throw {
						name : 'InvalidButton',
						message : 'No valid button given to submit'
					};
				}
				var buttonId = (button.get('id') === "") ? button.set('id', Y.guid()).get('id') : button.get('id');

				// we need to add the input name to the request to execute the
				// action
				var options = tempOptions || {};
				options.execute = options.execute + " " + buttonId;
				options.render = render ? render : '@none';
				options.onevent = onevent ? onevent : null;
				options[buttonId] = '';

				console.log('JsfFacade: submitAjaxButton render:' + options.render);
				try {
					jsf.ajax.request(buttonId, e, options);
				} catch (ex) {
					console.log('JsfFacade: Exception ' + ex.description);
				}
			},
			submitAjaxCheckbox : function(e, checkbox, render) {
				if (typeof (jsf) === 'undefined' && (!!checkbox)) {
					return true;
				} // No submit without jsf api
				if (checkbox === null) {
					throw {
						name : 'InvalidCheckbox',
						message : 'No valid checkbox given to change'
					};
				}
				var checkId = (checkbox.get('id') === "") ? checkbox.set('id', Y.guid()).get('id') : checkbox.get('id');

				// we need to add the input name to the request to execute the
				// action
				var options = {};
				options.execute = checkId;
				options.render = render ? render : '@none';
				options[checkId] = '';

				console.log('JsfFacade: submitAjaxCheckbox render:' + options.render);
				try {
					jsf.ajax.request(checkId, e, options);
				} catch (ex) {
					console.log('JsfFacade: Exception ' + ex.description);
				}
			},
			/**
			 * Adds a listener to the jsf ajax event queue
			 * 
			 * @function
			 * @param {function}
			 *            callback function
			 */
			addAjaxEventListener : function(callback) {
				if (typeof (jsf) === 'undefined') {
					return true;
				} // Nothing should happen then
				// console.log('JsfFacade: Added event listener');
				return jsf.ajax.addOnEvent(callback);
			}
		};
	}();

	YUI.SIM.FormController = function() {
		/**
		 * filter Creditcard Data
		 * 
		 * @param {Node}
		 *            node Form object
		 */
		var filterCCData = function(node) {
			var fieldList = node.all('.js_CCFormFilterFiltered');
			fieldList.each(function(elm) {
				switch (elm.get('tagName')) {
				case 'INPUT':
					elm.set('value', '');
					break;
				case 'SELECT':
					elm.set('selectedIndex', -1);
					break;
				}
			});
		};
		return {
			initialize : function() {

				// js_CCFormFilter
				Y.delegate("submit", (function(e) {
					var secureURL = e.currentTarget.one('.js_CCFormFilterSecureURL');
					if (!!secureURL && e.currentTarget.get('action') != secureURL.get('href')) {
						filterCCData(e.currentTarget);
					}
				}), YUI.SIM.Nodes.Body, 'form.js_CCFormFilter');

			}
		};
	}();

	/**
	 * TagSlideShow
	 * 
	 * @class
	 */
	YUI.SIM.TagSlideShow = function() {
		var defaultTiming, isWindowFocused = true, onfocusEvent;
		var fadeSlide = function(node, targetValue, callback) {
			YUI({
				base: '/extensions/js/lib/yui-3.3.0/build/'
			}).use("anim", function(Y) {
				var anim = new Y.Anim({
					node : node,
					to : {
						opacity : targetValue
					},
					duration : 1
				});

				callback && anim.on("end", function() {
					callback();
				});

				anim.run();
			});
		};
		var slideImages = function(allImgNode, idx, allImgArr) {
			if (onfocusEvent) {
				onfocusEvent.detach();
				onfocusEvent = null;
				//console.log('detached focus event');
			};
			var current = idx,
				currentObj = allImgArr[idx],
				slideOutId = currentObj.node.generateID(),
				next = (++idx == allImgArr.length) ? 0 : idx,
				slideInId = allImgArr[next].node.generateID();

			if (isWindowFocused){
				window.setTimeout(function() {
					fadeSlide("#" + slideOutId, 0);
					fadeSlide("#" + slideInId, 1);
					//console.log(currentObj.timing);
					slideImages(allImgNode, next, allImgArr);
				}, currentObj.timing);
			}
			else {
				//slideImages(allImgNode, current, allImgArr);
				//console.log('window is not focused, waiting for focus');
				onfocusEvent = Y.one(Y.config.win).on("focus", function(e) {
					isWindowFocused = true;
					//console.log('window has focus',isWindowFocused);
					slideImages(allImgNode, current, allImgArr);
				});
				var stopit;
			}
		};

		return {
			initialize : function() {
				var elmList = Y.all('.js_teasershow');
				if (0 < elmList.size()) {
					elmList.each(function(elm) {
						var JSONElm = elm.one([ '#', elm.getAttribute('data-teasershowimages') ].join('')),
						noscriptElm = elm.one('.noscriptImg');
						defaultTiming = ~~(elm.getAttribute('data-teasershowtiming')) || 5000;
						var imageObjects = JSON.parse(JSONElm.get('innerHTML')).images;
						elm.setStyles({
							'position' : 'relative',
							'display' : 'block'
						});
						var allImgNode = Y.Node.create('<span></span>');
						var allImgArr =[];
						Y.each(imageObjects, function(item) {
							var img = Y.Node.create('<img alt="" />');
							img.set("src", item.file);
							img.setStyles({
								'position' : 'absolute',
								'left' : '0',
								'top' : '0',
								'opacity' : 0
							});
							allImgNode.append(img);
							allImgArr.push({'node':img,'timing':item.timing || defaultTiming});
						});
						// optional - remove JSON from DOM
						elm.append(allImgNode).removeChild(JSONElm);
						Y.on("load", (function() {
							allImgArr[0].node.setStyle('opacity',1);
							elm.removeChild(noscriptElm);
							if(allImgArr.length > 1){
								slideImages(allImgNode, 0, allImgArr);
							}
						}), window, Y);
					});

					Y.one(Y.config.win).on("blur", function(e) {
						isWindowFocused = false;
						//console.log('window lost focus',isWindowFocused);
					});
				}
			}
		};
	}();

	/**
	 * SwfController
	 * 
	 * @class Initializes all swf objects on the page
	 */
	YUI.SIM.SwfController = function() {

		var onSwfEmbedEvent = function(e) {
			if (!e.success) {
				var imgNode = Y.one('#' + e.id + ' img.flashAlternate');
				if (!!imgNode) {
					imgNode.addClass('show');
				}
			}
		};

		return {
			/**
			 * initializes a given set of swf objects
			 * 
			 * @function
			 * @param {NodeList}
			 *            elmList SWF Object node list
			 */
			initialize : function() {
				var elmList = Y.all('.js_swfobject');
				if (0 < elmList.size()) { // Load swfobject only when
					// necessary
					// Y.use('swfobject', function(Y) {
					elmList.each(function(elm) {
						if (!elm.get('id')) {
							elm.set('id', Y.guid());
						} // Fallback for missing ID, swfobj requires one}
						var containerId = elm.get('id');
						var img = elm.one('img.flashAlternate');
						if (!img) {
							return false;
						} // no flash found

						var params = {
							wmode : "opaque"
						};
						var attributes = {};
						attributes.id = containerId;

						swfobject.embedSWF(img.getAttribute('data-flash'), containerId, img.get('width'), img.get('height'), "9.0.0", "swfobject/expressInstall", null, params, attributes, onSwfEmbedEvent);
					});
					// });
				}
			}
		};
	}();

	/**
	 * Navigation Controller
	 * 
	 * @class Controls the functionality of the main navigation
	 */
	YUI.SIM.NavigationController = function(config) {

		var Navigation = function(config) {
			// private
			var _delay = 0, _hideDelay = 0, _extendedHideDelay = 0, _showDelay = 0, _activeElm, _hideTimer, _showTimer, _docHandle, _self = this;

			// private functions
			/**
			 * Auto attach/detach document event handler based on menu
			 * visibility
			 */
			var _attachDocumentListener = function() {
				_docHandle = YUI.SIM.Nodes.Document.on("navigation|click", function(e) {
					_self.triggerClick(e);
				});
			};
			var _detachDocumentListener = function() {
				if (_docHandle) {
					Y.detach('navigation|click');
				}
			};
			/**
			 * hide the active navigation element
			 */
			var _hide = function() {
				if (_activeElm) {
					_activeElm.removeClass('open');
					_detachDocumentListener();
				}
			};
			/**
			 * show the given navigation element
			 * 
			 * @param {Node}
			 *            node Navigation element
			 */
			var _show = function(node) {
				_clearTimer();
				_clearShowTimer();
				_hide();
				Y.Object(node).addClass('open');
				_activeElm = Y.Object(node);
				_attachDocumentListener();
			};
			/**
			 * Clear the hide timer
			 */
			var _clearTimer = function() {
				if (_hideTimer) {
					_hideTimer.cancel();
					_hideTimer = null;
				}
			};
			/**
			 * Clear the show timer
			 */
			var _clearShowTimer = function() {
				if (_showTimer) {
					// console.log('clear show timer');
					_showTimer.cancel();
					_showTimer = null;
				}
			};
			/**
			 * Reset the hide timer
			 */
			var _resetHideTimer = function() {
				if (_hideTimer) {
					_clearTimer();
				}
				_hideTimer = Y.later(_delay, this, _hide);
			};
			/**
			 * Reset the show timer
			 */
			var _resetShowTimer = function(node) {
				if (_showTimer) {
					_clearShowTimer();
				}
				// console.log('set _showTimer: ' + _showDelay);
				_showTimer = Y.later(_showDelay, this, _show, node);
			};

			// setters
			/**
			 * Set the current delay
			 * 
			 * @param {Object}
			 *            delay Defines the current active delay
			 */
			this.setDelay = function(delay) {
				// console.log('NavigationController: Set delay ' + delay);
				_delay = parseInt(delay, 10);
			};
			/**
			 * Set the default delay
			 * 
			 * @param {Object}
			 *            delay The default delay
			 */
			this.setHideDelay = function(delay) {
				_hideDelay = parseInt(delay, 10);
			};
			/**
			 * Set the extended delay
			 * 
			 * @param {Object}
			 *            delay The extended delay
			 */
			this.setExtendedHideDelay = function(delay) {
				_extendedHideDelay = parseInt(delay, 10);
			};
			/**
			 * Set the optional show delay
			 * 
			 * @param {Object}
			 *            delay The show delay
			 */
			this.setShowDelay = function(delay) {
				_showDelay = parseInt(delay, 10);
			};

			// public functions
			/**
			 * Triggers the Enter event
			 * 
			 * @param {Event}
			 *            e YUI event object
			 */
			this.triggerEnter = function(e) {
				// console.log('NavigationController: Enter triggered');
				if (_activeElm && !_activeElm.compareTo(e.currentTarget)) {
					this.setDelay(_hideDelay);
					_show(e.currentTarget);
				} else {
					_resetShowTimer(e.currentTarget);
				}
			};
			/**
			 * Triggers the Enter Leave
			 * 
			 * @param {Event}
			 *            e YUI event object
			 */
			this.triggerLeave = function(e) {
				// console.log('NavigationController: Leave triggered');
				_resetHideTimer();
				_clearShowTimer();
			};
			/**
			 * Triggers the Slowdown event
			 * 
			 * @param {Event}
			 *            e YUI event object
			 */
			this.triggerDelaySlowdown = function(e) {
				// console.log('NavigationController: DelaySlowdown triggered');
				this.setDelay(_extendedHideDelay);
				_resetHideTimer();
			};
			/**
			 * Triggers the click event
			 * 
			 * @param {Event}
			 *            e YUI event object
			 */
			this.triggerClick = function(e) {
				if (_activeElm && !_activeElm.contains(e.target)) {
					_hide();
				}
			};
			this.hideAll = function() {
				_hide();
			};

			// constructor
			if (config.hideDelay) {
				this.setDelay(config.hideDelay);
				this.setHideDelay(config.hideDelay);
			}
			if (config.extendedHideDelay) {
				this.setExtendedHideDelay(config.extendedHideDelay);
			}
		};

		return {
			initialize : function() {
				var elm = Y.one('.js_navigation'), nodes = Y.all('.js_navigation > li'), formFields = Y.all('.js_navigation li.login input[type="text"], .js_navigation li.login input[type="password"]'), navigation;

				if (nodes.size() <= 0) {
					return;
				}

				navigation = new Navigation({
					hideDelay : 500,
					extendedHideDelay : 12000,
					showDelay : 300
				});

				elm.addClass('jsPrepared');
				nodes.on('mouseenter', function(e) {
					navigation.triggerEnter(e);
				});
				nodes.on('mouseleave', function(e) {
					navigation.triggerLeave(e);
				});

				// console.log('mobile: ' + Y.UA.mobile);
				if (Y.UA.mobile) {
					navigation.setHideDelay(0);
					navigation.setExtendedHideDelay(12000);
					navigation.setShowDelay(0);
					nodes.on('touchstart', function(e) {
						if (!e.currentTarget.hasClass('open')) {
							e.preventDefault();
							navigation.hideAll();
							navigation.triggerEnter(e);
						}
					}, false);
				}

				formFields.on('keypress', function(e) {
					navigation.triggerDelaySlowdown(e);
				});
				formFields.on('click', function(e) {
					navigation.triggerDelaySlowdown(e);
				});

				return navigation;
			}
		};
	}(); // YUI.SIM.NavigationController

	/**
	 * FaqTopicController
	 * 
	 * @class switches to faq topic selector
	 */
	YUI.SIM.FaqController = function() {
		return {
			/**
			 * switches Link to topic selector
			 * 
			 * @function
			 * @param {Node}
			 *            tigger link
			 */
			switchSearchSelector : function(node) {
				var wrapper = node.ancestor('.js_faqTopicWrapper'), topicSelector = wrapper.one('select');

				node.toggleClass('hidden');
				topicSelector.toggleClass('hidden');
			}
		};
	}();

	/**
	 * TeaserToggle Controller
	 * 
	 * @class Controls the functionality of the teaserToggle Module, e.g. tariff
	 *        options
	 */
	YUI.SIM.TeaserToggleController = function() {
		/**
		 * toggles the modules
		 * 
		 * @function
		 * @private
		 * @param {Object}
		 *            elm Element that was clicked
		 * @param {Object}
		 *            items All elements
		 * @param {Object}
		 *            e Event Object
		 */
		var toggleTariff = function(elm, items, e) {
			if (!elm.hasClass('active')) {
				items.toggleClass('active');
				var rd = elm.one('input.typeRadio');
				// todo: status halten/auslesen/initialstatus berücksichtigen
			}
		};
		/** @scope YUI.SIM.TeaserToggleController */
		return {
			/**
			 * initalizes TeaserToggle Element
			 * 
			 * @function
			 * @param {Object}
			 *            list List element containing teasers to toggle
			 * @param {Object}
			 *            listItems List items that represent one teaser each
			 */
			initialize : function() {
				var list = Y.one('.js_teaserToggle'), listItems = Y.all('.js_teaserToggle > li');

				if (list) {
					list.addClass('jsPrepared');
					
					Y.delegate("click", (function(e) {
						toggleTariff(this.ancestor('li'), listItems, e);
					}), list, 'li > h2');

					Y.delegate("focus", (function(e) {
						toggleTariff(this.ancestor('li'), listItems, e);
					}), list, 'li > h2 input.typeRadio');
				}
			}
		};
	}();

	/**
	 * TafController
	 * 
	 * @class Manages tell a friend objects
	 */
	/*
	 * YUI.SIM.TafController = function () { var boundingBox, recipientField,
	 * previewField, previewText;
	 * 
	 * var onRecipientBlur = function (e) { var newValue =
	 * recipientField.get('value') || null; if(newValue) {
	 * previewField.set('value',
	 * previewText.replace(/\[[\w\säöüßÄÖÜ]+\]/,newValue )); } else {
	 * previewField.set('value',previewText); } }; return { initializeSMStaf:
	 * function () { boundingBox = Y.one('.js_smspreview') || null;
	 * if(boundingBox) { recipientField =
	 * boundingBox.one('.js_smspreview_name'); previewField =
	 * boundingBox.one('.js_smspreview_target'); previewText =
	 * Y.one('.js_smspreview_default').get('value');
	 * 
	 * recipientField.on('blur', onRecipientBlur); } } }; }();
	 */
	/**
	 * TopupController
	 * 
	 * @class Provides topup functionality (stateless)
	 */
	YUI.SIM.TopupController = function() {

		/**
		 * Previews the new charge state
		 * 
		 * @param {Node}
		 *            topupNode The associated topup base node
		 * @param {Number}
		 *            charge The amount which is going to be charged
		 */
		var previewTopup = function(topupNode, charge) {
			var currentValue = getCurrentValue(topupNode), chargeValue = YUI.SIM.UiHelpers.cleanFloat(charge), newValue = currentValue + chargeValue, ceiling = getCeiling(topupNode), minimumCharge = getMinimum(topupNode);

			if (chargeValue === 0) {
				triggerHideError(topupNode);
			} else {
				if (ceiling >= newValue && minimumCharge <= chargeValue) {
					triggerHideError(topupNode);
					setDisplayValue(topupNode, newValue);
				} else if (ceiling < newValue) {
					setDisplayValue(topupNode, currentValue);
					triggerShowError(topupNode, 'Ceiling');
				} else {
					triggerShowError(topupNode, 'Minimum');
				}
			}
		};

		/**
		 * Retrieves the current charge state from the document
		 * 
		 * @param {Node}
		 *            topupNode The associated topup base node
		 * @return {Float} Current charge state
		 */
		var getCurrentValue = function(topupNode) {
			return YUI.SIM.UiHelpers.cleanFloat(topupNode.one('.js_topupValueInput').get('value'));
		};

		/**
		 * Retrives the maximum possible charge state from the document
		 * 
		 * @param {Node}
		 *            topupNode The associated topup base node
		 * @return {Float} Maximum total charge
		 */
		var getCeiling = function(topupNode) {
			return YUI.SIM.UiHelpers.cleanFloat(topupNode.one('.js_topupCeiling').get('text'));
		};

		/**
		 * Retrieves the minimum charge from the document
		 * 
		 * @param {Node}
		 *            topupNode The associated topup base node
		 * @return {Float} Minimum charge amount
		 */
		var getMinimum = function(topupNode) {
			return YUI.SIM.UiHelpers.cleanFloat(topupNode.one('.js_topupMinimum').get('text'));
		};

		/**
		 * Sets the current displayed total charge
		 * 
		 * @param {Node}
		 *            topupNode The associated topup base node
		 * @param {Number}
		 *            value The new value
		 */
		var setDisplayValue = function(topupNode, value) {
			topupNode.one('.js_topupDisplayValue').set('text', YUI.SIM.UiHelpers.formatNumber(value, 2, true));
		};

		/**
		 * Set the charge amount of the free charge field
		 * 
		 * @param {Node}
		 *            topupNode The associated topup base node
		 * @param {Number}
		 *            value new free charge field value
		 */
		var setChargeInputValue = function(topupNode, value) {
			topupNode.one('.js_topupChargeValue').set('value', value);
		};

		/**
		 * Retrieves the charge amount from the free charge field
		 * 
		 * @param {Node}
		 *            topupNode The associated topup base node
		 * @return {String} value new free charge field value
		 */
		var getChargeInputValue = function(topupNode, value) {
			return topupNode.one('.js_topupChargeValue').get('value');
		};

		/**
		 * Triggers to show the error of the given type
		 * 
		 * @param {Node}
		 *            topupNode The associated topup base node
		 * @param {String}
		 *            type Type of error
		 */
		var triggerShowError = function(topupNode, type) {
			triggerHideError(topupNode);
			topupNode.one('.js_topupErrorMessage.js_topupError' + type).removeClass('hidden');
		};

		/**
		 * Hide all errormessages
		 * 
		 * @param {Node}
		 *            topupNode The associated topup base node
		 */
		var triggerHideError = function(topupNode) {
			topupNode.all('.js_topupErrorMessage').each(function(v) {
				v.addClass('hidden');
			});
		};

		/**
		 * Reset the display value and free charge field
		 * 
		 * @param {Node}
		 *            topupNode The associated topup base node
		 */
		var resetValue = function(topupNode) {
			setDisplayValue(topupNode, getCurrentValue(topupNode));
			setChargeInputValue(topupNode, '');
			triggerHideError(topupNode);
		};

		/**
		 * Toggles the current display mode
		 * 
		 * @param {Node}
		 *            topupNode The associated topup base node
		 */
		var toggleMode = function(topupNode) {
			topupNode.toggleClass('topupModeSelect');
			resetValue(topupNode);
		};

		return {
			/**
			 * Initialize all delegates for TopupController
			 * 
			 * @function
			 */
			initialize : function() {
				Y.delegate('mouseenter', (function(e) {
					var topupNode = e.currentTarget.ancestor('.js_topup');
					previewTopup(topupNode, e.currentTarget.get('value'));
				}), YUI.SIM.Nodes.Body, '.js_topup input.js_chargebutton');

				Y.delegate('mouseout', (function(e) {
					var topupNode = e.currentTarget.ancestor('.js_topup');
					resetValue(topupNode);
				}), YUI.SIM.Nodes.Body, '.js_topup input.js_chargebutton');

				Y.delegate('click', (function(e) {
					var topupNode = e.currentTarget.ancestor('.js_topup');
					toggleMode(topupNode);
					e.preventDefault();
					YUI.SIM.JsfFacade.submitAjaxButton(e, e.currentTarget);
				}), YUI.SIM.Nodes.Body, '.js_topup .js_topupToggleMode');

				Y.delegate('keypress', (function(e) {
					if (!/^\d*$/.test(String.fromCharCode(e.charCode))) {
						if (8 !== e.charCode && /* backspace */
						13 !== e.charCode && /* enter */
						35 !== e.charCode && /* end */
						36 !== e.charCode && /* home */
						37 !== e.charCode && /* left */
						39 !== e.charCode && /* right */
						0 !== e._event.charCode /* del */) {
							e.halt();
						}
					}
				}), YUI.SIM.Nodes.Body, '.js_topup .js_topupChargeValue');

				Y.delegate('keyup', (function(e) {
					var topupNode = e.currentTarget.ancestor('.js_topup');
					previewTopup(topupNode, e.currentTarget.get('value'));
				}), YUI.SIM.Nodes.Body, '.js_topup .js_topupChargeValue');
			}
		};
	}();

					
	/**
	 * Random number selection
	 * 
	 * @class Controlls the selection of random numbers
	 */
	YUI.SIM.MsisdnRandomController = (function() { // [[MsisdnRandomController]]
		// Singleton

		return {
			/**
			 * get the total page count
			 * 
			 * @function
			 * @returns {Integer} Total number of pages
			 */
			getPagesCount : (function(node) {
				return node.one('.msisdnList').get('children').size();
			}),
			/**
			 * set the current displayed page
			 * 
			 * @function
			 * @param {Integer}
			 *            The new index
			 * @param {Integer}
			 *            The current index
			 * @param {Node}
			 *            Base node used for dom operations
			 */
			setIndex : (function(newIndex, currentIndex, node) {
				var buttonList = node.previous('.msisdnSelectButtons'), numberList = node.one('.msisdnList'), pager = node.next('.pagerMsisdn').one('.pager');

				currentIndex = YUI.SIM.MsisdnRandomController.getIndex(node);

				// set displaynumber
				numberList.replaceClass('currentIndex_' + currentIndex, 'currentIndex_' + (newIndex));

				// set button
				// @TODO: not needed anymore? Serverside only needs one button
				// for all numbers now
				/*
				 * buttonList.item(currentIndex-1).toggleClass('active');
				 * buttonList.item(newIndex-1).toggleClass('active');
				 */
				// set pager
				pager.get('children').item(currentIndex - 1).toggleClass('active');
				pager.get('children').item(newIndex - 1).toggleClass('active');

				YUI.SIM.JsfFacade.submitAjaxButton(null, pager.get('children').item(newIndex - 1).one('input'));
			}),
			/**
			 * Retrieve the current page index
			 * 
			 * @function
			 * @returns {Integer} current page index
			 * @param {Node}
			 *            Base node for operations
			 */
			getIndex : (function(node) {
				var numberList = node.one('.msisdnList');
				return parseInt(numberList.get('className').match('currentIndex_(\\d+)')[1], 10);
			}),
			/**
			 * Handles event when a page is directly addressed
			 * 
			 * @function
			 * @param {Event}
			 *            Event object
			 */
			selectPage : (function(e) {
				var pager = e.currentTarget.ancestor('.pager'), node = e.currentTarget.ancestor('.pagerMsisdn').previous('.chooseMsisdn'), currentPage = e.currentTarget.ancestor(), newIndex = pager.get('children').indexOf(currentPage) + 1, currentIndex = YUI.SIM.MsisdnRandomController.getIndex(node);
				e.preventDefault();
				if (newIndex != currentIndex) {
					YUI.SIM.MsisdnRandomController.setIndex(newIndex, currentIndex, node);
				}
			}),
			/**
			 * Jumps to the previous page or jumps to last if first page is
			 * reached
			 * 
			 * @function
			 * @param {Event}
			 *            Event object
			 */
			prev : (function(e) {
				var node = e.currentTarget.ancestor('.chooseMsisdn'), currentIndex = YUI.SIM.MsisdnRandomController.getIndex(node), pageCount = YUI.SIM.MsisdnRandomController.getPagesCount(node);

				e.preventDefault();
				if (currentIndex > 1) {
					YUI.SIM.MsisdnRandomController.setIndex(currentIndex - 1, currentIndex, node);
				} else {
					YUI.SIM.MsisdnRandomController.setIndex(pageCount, currentIndex, node);
				}
			}),
			/**
			 * Jumps to the next page or jumps to first if last page is reached
			 * 
			 * @function
			 * @param {Event}
			 *            Event object
			 */
			next : (function(e) {
				var node = e.currentTarget.ancestor('.chooseMsisdn'), currentIndex = YUI.SIM.MsisdnRandomController.getIndex(node), pageCount = YUI.SIM.MsisdnRandomController.getPagesCount(node);

				e.preventDefault();
				if (currentIndex < pageCount) {
					YUI.SIM.MsisdnRandomController.setIndex(currentIndex + 1, currentIndex, node);
				} else {
					YUI.SIM.MsisdnRandomController.setIndex(1, currentIndex, node);
				}
			}),

			highlightMessage : (function(e) {
				if (e.status == 'success') {
					var nodeId = 'msisdnSearchNumberResultMessage';
					var node = Y.one('#' + nodeId);
					if (node) {
						YUI({
							base : '/extensions/js/lib/yui-3.3.0/build/'
						}).use("anim", function(Y) {
							var anim = anim || new Y.Anim({
								node : '#' + nodeId,
								from : {
									backgroundColor : '#ffc'
								},
								to : {
									backgroundColor : '#e6e6e6'
								},
								duration : 2,
								easing : Y.Easing.easeBothStrong
							});
							anim.run();
						});
					}
				}
			})
		};

	})(); // [[MsisdnRandomController]] Singleton

	/**
	 * ToggleboxController
	 * 
	 * @class Controls simple toggleboxes
	 */
	YUI.SIM.ToggleboxController = function() {
		var getButton = function(node) {
			return node.hasClass('open') ? node.one('.showExpanded input[type="submit"]') : node.one('.showCollapsed input[type="submit"]');
		};
		var closeOpposites = function(opposites) {
			if (!!opposites) { // close oposed elements
				opposites.removeClass('open').addClass('closed');
			}
		};

		return {
			initialize : function() {
				Y.delegate("click", (function(e) {
					if (e.target.ancestor('.infoBubble')) {
						return null; // we don't catch those for folding
					}
					e.preventDefault();
					var node = e.currentTarget.ancestor('.js_toggleBox');
					var opposites = Y.all('.js_toggleBox');
					if (node) {
						YUI.SIM.ToggleboxController.toggle(node, e, opposites);
					}
				}), YUI.SIM.Nodes.Body, '.js_toggleBox div.hd,.js_toggleBox .js_toggleHead');

				// SimpleToggleBox
				Y.delegate("click", (function(e) {
					if (e.target.ancestor('.infoBubble')) {
						return null; // we don't catch those for folding
					}
					e.preventDefault();
					var node = e.currentTarget.ancestor('.js_simpleToggleBox');
					if (node) {
						YUI.SIM.ToggleboxController.toggle(node, e);
					}
				}), YUI.SIM.Nodes.Body, '.js_simpleToggleBox div.hd');

				/*
				 * @example use .js_anchorSimpleToggleBox on TR or Anchor in
				 * overviewTable (verbindungsuebersicht)
				 */
				Y.delegate("click", (function(e) {
					var linkNode = e.currentTarget;
					var jumpto = false;
					if (e.currentTarget._node.nodeName.toLowerCase() !== "a") {
						linkNode = e.currentTarget.one('a[href*="#"]');
						jumpto = true;
					}
					var nodeId = linkNode.get('href').substring(linkNode.get('href').indexOf('#') + 1);
					var node = Y.one('#' + nodeId);
					if (node) {
						YUI.SIM.ToggleboxController.open(node, e);
						if (jumpto) {
							window.location.hash = "#" + nodeId;
						}
					}
				}), YUI.SIM.Nodes.Body, '.js_anchorSimpleToggleBox');
			},

			/**
			 * toggles the box state
			 * 
			 * @function
			 * @param {Nodes}
			 *            node Basenode for togglebox
			 * @param {Event}
			 *            e Event object
			 * @param {NodeList}
			 *            opposites Opposing elements which will be closed
			 */
			toggle : function(node, e, opposites) {
				var button = getButton(node);
				if (node.hasClass('open')) {
					node.toggleClass('open').toggleClass('closed');
					return true;
				}
				closeOpposites(opposites);
				node.toggleClass('open').toggleClass('closed');
				if (button) {
					this.triggerAjaxButton(button, e);
				}
				Y.fire('togglebox:toggle', node);
			},
			/**
			 * triggers the ajax action
			 * 
			 * @function
			 * @param {Node}
			 *            button Button to be ajax submitted
			 * @param {Event}
			 *            e Event object
			 */
			triggerAjaxButton : function(button, e) {
				YUI.SIM.JsfFacade.submitAjaxButton(e, button);
			},
			/**
			 * opens the togglebox
			 * 
			 * @function
			 * @param {Node}
			 *            node Node of togglebox
			 * @param {Event}
			 *            e Event Object
			 * @param {NodeList}
			 *            opposites Opposite elements which will be closed
			 */
			open : function(node, e, opposites) {
				var button = getButton(node);
				closeOpposites(opposites);
				node.addClass('open').removeClass('closed');
				this.triggerAjaxButton(button, e);
				Y.fire('togglebox:open', node);
			}
		};
	}();

	/**
	 * SlideshowController
	 * 
	 * @class Handles slideshows
	 */
	YUI.SIM.SlideshowController = function() {

		/**
		 * Retrieve the current slide index
		 * 
		 * @function
		 * @param {Node}
		 *            node Base node for operations
		 * @returns {Integer} current slide index
		 */
		var getIndex = function(node) {
			var slideList = node.one('.js_slideshowList'), currentSlide = slideList.one('.active');
			return slideList.get('children').indexOf(currentSlide);
		};

		/**
		 * get the total slide count
		 * 
		 * @function
		 * @param {Node}
		 *            node Base node
		 * @returns {Integer} Total number of slides
		 */
		var getSlideCount = function(node) {
			return node.one('.js_slideshowList').get('children').size();
		};

		/**
		 * set the current displayed slide
		 * 
		 * @function
		 * @param {Integer}
		 *            newIndex The new index
		 * @param {Integer}
		 *            currentIndex The current index
		 * @param {Node}
		 *            node Base node used for dom operations
		 */
		var setIndex = function(newIndex, currentIndex, node) {
			var pagerList = node.one('.js_slideshowSelect').get('children'), slideList = node.one('.js_slideshowList').get('children');

			pagerList.item(currentIndex).toggleClass('active');
			pagerList.item(newIndex).toggleClass('active');

			slideList.item(currentIndex).toggleClass('active');
			slideList.item(newIndex).toggleClass('active');

			sync(node);
		};

		/**
		 * Synchronize controls to current view state
		 * 
		 * @function
		 * @param {Node}
		 *            node base node
		 */
		var sync = function(node) {
			var currentIndex = getIndex(node), slideCount = getSlideCount(node);

			if (currentIndex > 0) {
				enablePrev(node);
			} else {
				disablePrev(node);
			}

			if (currentIndex < slideCount - 1) {
				enableNext(node);
			} else {
				disableNext(node);
			}
		};

		/* FIXME: Bundle those four functions in one parameterized? */
		/**
		 * Disable the next control
		 * 
		 * @function
		 * @param {Node}
		 *            node Base node
		 */
		var disableNext = function(node) {
			node.all('.js_slideshowNext').each(function(v) {
				v.addClass('disabled');
			});
		};

		/**
		 * Disable the previous control
		 * 
		 * @function
		 * @param {Node}
		 *            node Base node
		 */
		var disablePrev = function(node) {
			node.all('.js_slideshowPrev').each(function(v) {
				v.addClass('disabled');
			});
		};

		/**
		 * Enable the next control
		 * 
		 * @function
		 * @param {Node}
		 *            node Base node
		 */
		var enableNext = function(node) {
			node.all('.js_slideshowNext').each(function(v) {
				v.removeClass('disabled');
			});
		};

		/**
		 * @function Enable the previous control
		 * @param {Node}
		 *            node Base node
		 */
		var enablePrev = function(node) {
			node.all('.js_slideshowPrev').each(function(v) {
				v.removeClass('disabled');
			});
		};

		return {
			/**
			 * Initializes the slideshow controller by binding delegates (should
			 * be done lazy on "available")
			 */
			initialize : function() {

				Y.delegate("click", (function(e) {
					e.preventDefault();
					var node = e.currentTarget.ancestor('.js_slideshow');
					if (node) {
						YUI.SIM.SlideshowController.next(e, node);
					}
				}), YUI.SIM.Nodes.Body, '.js_slideshowNext');

				Y.delegate("click", (function(e) {
					e.preventDefault();
					var node = e.currentTarget.ancestor('.js_slideshow');
					if (node) {
						YUI.SIM.SlideshowController.prev(e, node);
					}
				}), YUI.SIM.Nodes.Body, '.js_slideshowPrev');

				Y.delegate("click", (function(e) {
					e.preventDefault();
					var node = e.currentTarget.ancestor('.js_slideshow');
					if (node) {
						YUI.SIM.SlideshowController.selectPage(e, node);
					}
				}), YUI.SIM.Nodes.Body, '.js_slideshowSelect a');

			},
			/**
			 * Handles event when a slide is directly addressed
			 * 
			 * @function
			 * @param {Event}
			 *            e Event object
			 * @param {Node}
			 *            node base node
			 */
			selectPage : (function(e, node) {
				var currentIndex = getIndex(node), newIndex = node.one('.js_slideshowSelect').all('a').indexOf(e.currentTarget);

				setIndex(newIndex, currentIndex, node);
			}),
			/**
			 * Jumps to the previous page or jumps to last if first page is
			 * reached
			 * 
			 * @function
			 * @param {Event}
			 *            e Event object
			 * @param {Node}
			 *            node base node
			 */
			prev : (function(e, node) {
				var currentIndex = getIndex(node), slideCount = getSlideCount(node);

				if (currentIndex > 0) {
					setIndex(currentIndex - 1, currentIndex, node);
				} else {
					setIndex(slideCount - 1, currentIndex, node);
				}

			}),
			/**
			 * Jumps to the next page or jumps to first if last page is reached
			 * 
			 * @function
			 * @param {Event}
			 *            e Event object
			 * @param {Node}
			 *            node base node
			 */
			next : (function(e, node) {
				var currentIndex = getIndex(node), slideCount = getSlideCount(node);

				if (currentIndex < slideCount - 1) {
					setIndex(currentIndex + 1, currentIndex, node);
				} else {
					setIndex(1, currentIndex, node);
				}
			})
		};
	}();

	YUI.SIM.CarouselController = (function() {
		var animating = false, minSwipe = 10, node, index, targetIndex, duration, interval, oldInterval = 0, preStartDelay, preContinueDelay, autoplayTimer, contentUl, teaserCount, animationsCount = 1, rotationsCount = 0, tooltipTimer;

		return {

			/**
			 * @param options
			 * @options node - the carousel node,
			 * @options index - the slide to start with,
			 * @options duration - duration of slide animation,
			 * @options interval - delay between automatic slide switching,
			 * @options preStartDelay - initial waiting time before autoplay
			 *          starts,
			 * @options preContinueDelay - time until autoplay is continued
			 *          after mouseenter/mouseleave (w/o click)
			 * @options maxRotations - number of rotations after which autoplay
			 *          is stopped
			 */
			initialize: function(options) {

				// options
				if (typeof options != "object") var options = {};
				node = options.node || Y.one(".js_carousel");
				index = options.index || 0;
				duration = options.duration || .6;
				interval = options.interval || 5000;
				preStartDelay = options.preStartDelay || 5000;
				preContinueDelay = options.preContinueDelay || 5000;
				maxRotations = options.maxRotations || 1;

				if (!node) {
					return;
				}

				if (!Modernizr || !Modernizr.csstransitions) {
					if (typeof window.Animator === 'undefined') {
						Y.Get.script([ "/extensions/js/lib/animator-1.1.1/animator-min.js" ], {
							onSuccess: function() {
								YUI.SIM.CarouselController.initialize(options);
							}
						});
						return;
					}
				}

				contentUl = node.one(".js_carouselContent");
				teaserCount = contentUl.all(".js_item").size();
				if ( teaserCount < 2) {
					return;
				}
				// initialize + autoplay
				YUI.SIM.CarouselController.fetchContent(false, node, null, false);
				YUI.SIM.CarouselController.selectPage(false, node, index, true);

				if (!!interval && !Y.UA.mobile) {
					autoplayTimer = window.setTimeout(function() {
						YUI.SIM.CarouselController.autoplay(false, node);
					}, preStartDelay);
				}

				YUI.SIM.CarouselController.bindEvents();
			},

			bindEvents: function() {
				Y.on("mouseenter", function(e) {
					// var node = e.currentTarget.ancestor(".js_carousel");
					YUI.SIM.CarouselController.pauseAutoplay(e, this);
				}, ".js_carousel");

				Y.on("mouseleave", function(e) {
					// var node = e.currentTarget.ancestor(".js_carousel");
					YUI.SIM.CarouselController.resumeAutoplay(e, this);
				}, ".js_carousel");

				Y.delegate("click", function(e) {
					YUI.SIM.CarouselController.trackClickTeaser();
				}, YUI.SIM.Nodes.Body, ".js_carousel .carouselContent li a");

				Y.one(Y.config.win).on("blur", function(e) {
					YUI.SIM.CarouselController.pauseAutoplay(e, node);
				}, node);

				Y.one(Y.config.win).on("focus", function(e) {
					YUI.SIM.CarouselController.resumeAutoplay(e, node);
				}, node);

				Y.delegate("click", function(e) {
					e.preventDefault();
					// e.currentTarget.blur(); // removed because IE7/8 also
					// fire window.blur => autoplay starts when it shouldn't
					if (animating) return;
					if (node) {
						YUI.SIM.CarouselController.next(e, node);
					}
				}, YUI.SIM.Nodes.Body, ".js_next", node);

				Y.delegate("click", function(e) {
					e.preventDefault();
					// e.currentTarget.blur(); // removed because IE7/8 also
					// fire window.blur => autoplay starts when it shouldn't
					if (animating) return;
					if (node) {
						YUI.SIM.CarouselController.prev(e, node);
					}
				}, YUI.SIM.Nodes.Body, ".js_prev", node);

				Y.delegate("click", function(e) {
					e.preventDefault();
					// e.currentTarget.blur(); // removed because IE7/8 also
					// fire window.blur => autoplay starts when it shouldn't
					if (animating) return;
					// var node = e.currentTarget.ancestor(".js_carousel");
					if (node) {
						var index = node.all(".js_pager > li").indexOf(e.target.ancestor("li"));
						YUI.SIM.CarouselController.selectPage(e, node, index);
					}
				}, YUI.SIM.Nodes.Body, ".js_pager a", node);

				// delay for displaying pager item tooltips
				Y.delegate("mouseenter", function(e) {
					var tooltip = e.target.next(".info").removeClass("hover");
					if (!!tooltipTimer) clearTimeout(tooltipTimer);
					tooltipTimer = setTimeout(function() {
						tooltip.addClass("hover");
					}, 100);
				}, YUI.SIM.Nodes.Body, ".js_pager a", node);

				if (Y.UA.mobile) {
					YUI({
						base: '/extensions/js/lib/yui-3.3.0/build/'
					}).use("node-base", "node-event-delegate", "transition", "event-move", function(Y) {
						Y.Node.one("body").delegate("gesturemovestart", function(e) {
							var item = e.currentTarget, node = item.ancestor(".js_carousel"), target = e.target;
							YUI.SIM.CarouselController.pauseAutoplay(e, node);
							item.setData("swipeStart", e.pageX);
							item.once("gesturemoveend", function(e) {
								var swipeStart = item.getData("swipeStart"), swipeEnd = e.pageX;
								if (node && (swipeStart - swipeEnd) > minSwipe) {
									YUI.SIM.CarouselController.next(e, node);
								}
								if (node && (swipeStart - swipeEnd) < -minSwipe) {
									YUI.SIM.CarouselController.prev(e, node);
								}
							});
						}, ".js_carouselContent", {
							preventDefault: true
						});
					});
				}

				// kein carousel bei geöffneten layern (betrifft videos)
				Y.on('overlay:show', function(video) {
					YUI.SIM.CarouselController.pauseAutoplay(video, node);
				}, node);
				Y.on('overlay:close', function(video) {
					YUI.SIM.CarouselController.resumeAutoplay(video, node);
				}, node);

			},

			autoplay: function(e, newNode) {
				// console.log("autoplay: ", interval);
				var currentNode = newNode || node;
				if (!!interval && rotationsCount < maxRotations) {
					if (!!autoplayTimer) clearTimeout(autoplayTimer);
					autoplayTimer = null;
					autoplayTimer = setTimeout(YUI.SIM.CarouselController.autoplay, interval);
					YUI.SIM.CarouselController.next(e, currentNode);
					animationsCount++;
					if (animationsCount == teaserCount+1) {
						rotationsCount++;
						animationsCount = 0;
					}								
					// console.log('animationsCount: ' + animationsCount + ',
					// rotationsCount: ' + rotationsCount);
				} else {
					if (!!autoplayTimer) clearTimeout(autoplayTimer);
					autoplayTimer = null;
					// console.log('autoplay stopped, rotationsCount: ' +
					// rotationsCount);
				}
			},

			pauseAutoplay: function(e, node) {
				// console.log("pauseAutoplay");
				if (node) {
					if (!!interval) oldInterval = interval;
					interval = 0;
					rotationsCount = maxRotations;
					YUI.SIM.CarouselController.autoplay(e, node);
				}
			},

			resumeAutoplay: function(e, node) {
				// console.log("resumeAutoplay");
				if (node) {
					if (!!oldInterval) interval = oldInterval;
					if (!!interval && !autoplayTimer) {
						if (!!autoplayTimer) clearTimeout(autoplayTimer);
						autoplayTimer = null;
						// animationsCount = index+1;
						autoplayTimer = window.setTimeout(function() {
							YUI.SIM.CarouselController.autoplay(e, node);
						}, preContinueDelay);
					}
				}
			},

			fetchContent: function(e, node, index, force) {
				var currentContentLis = contentUl.all(".js_item"), animate = false;
				if (typeof index == "number") {
					currentContentLis = Y.all(Y.Node.getDOMNode(contentUl.all(".js_item").item(index))), animate = true;
				}

				Y.each(currentContentLis, function(contentLi) {
					if (force || !contentLi.get('firstElementChild')) {
						path = contentLi.getAttribute("data-content");
						YUI({
							base: '/extensions/js/lib/yui-3.3.0/build/'
						}).use("io-base", function(Y) {
							node.addClass("waiting");
							// Y.Get.css([path + ".css"]);
							// Y.Get.script([path + ".js"]);
							
							var params = contentLi.getAttribute("data-params");
							params = params ? params.replace(/vid=[a-zA-Z0-9_\-|]+/,'') : null;// ggf
																								// vid
																								// parameter
																								// entfernen
							params = params ? params.replace(/&amp;/, '&') : null; // &
							// müssen
							// im
							// HTML
							// zunächst
							// codiert
							// sein
							
							var config = {
								data: params
							}
							Y.on("io:success", function(id, o, args) {
								node.removeClass("waiting");
								args.contentLi.setContent(o.responseText);
								if (animate) YUI.SIM.CarouselController.animate(args.e, args.node, args.index);
							}, Y, {
								e: e,
								node: node,
								index: index,
								contentLi: contentLi
							});

							// var request = Y.io(path + '.html');
							var request = Y.io(path +'.html', config);
						});
					} else {
						if (animate) {
							YUI.SIM.CarouselController.animate(e, node, index);
						};
					}
				});
			},

			animate: function(e, node, index) {
				if (Y.UA.mobile) node = Y.one(Y.Node.getDOMNode(node)); // warum
																		// auch
																		// immer...
				node.all(".js_pager > li").removeClass("active").item(index).addClass("active");

				YUI({
					base: '/extensions/js/lib/yui-3.3.0/build/'
				}).use("anim", function(Y) {
					var anim = new Y.Anim({
						node: Y.Node.getDOMNode(node.one(".js_carouselContent")),
						to: {
							left: node.one(".js_carouselContent").getX() - node.one("#item" + (index + 1)).getX()
						},
						duration: duration,
						easing: Y.Easing.easeBoth
					});

					anim.on("end", function() {
						// reposition nodes
						targetIndex = contentUl.all(".js_item").indexOf(contentUl.one("#item" + (index + 1)));
						if (targetIndex == 0) { // one item back
							contentUl.prepend(contentUl.all(".js_item").item(contentUl.all(".js_item").size() - 1));
						} else {
							for ( var i = 1; i < targetIndex; i++) {
								contentUl.append(contentUl.one(".js_item"));
							}
						}
						contentUl.setStyle("left", -1 * parseInt(contentUl.one(".js_item").getComputedStyle("width"), 10));

						if (typeof YUI.SIM.CarouselTeaserController != "undefined" && typeof YUI.SIM.CarouselTeaserController.stopTeasers != "undefined" && typeof YUI.SIM.CarouselTeaserController.startTeaser != "undefined") {
							// stop all old, start new content animations
							// visible slide is always index 1 (one before for
							// back animation, the rest is behind)
							try {
								YUI.SIM.CarouselTeaserController.stopTeasers();
								YUI.SIM.CarouselTeaserController.startTeaser(1);
								YUI.SIM.CarouselController.trackShowTeaser(1);
							} catch (ex) {
								console.log(ex);
							}
						}
						animating = false;
					});

					anim.run();
					delete anim;
					animating = true;
				});
			},

			next: function(e, node) {
				index = index + 1;
				if (index == node.all(".js_item").size()) index = 0;
				YUI.SIM.CarouselController.fetchContent(e, node, index);
			},

			prev: function(e, node) {
				index = index - 1;
				if (index < 0) index = node.all(".js_item").size() - 1;
				YUI.SIM.CarouselController.fetchContent(e, node, index);
			},

			selectPage: function(e, node, newIndex) {
				index = newIndex;
				YUI.SIM.CarouselController.fetchContent(e, node, index);
			},
			getNowDate: function() {
				 var servertime = parseFloat(Y.one('.js_carousel').getAttribute('data-servertime'),10);
				 return servertime ? new Date(servertime) : new Date();
			},
			trackShowTeaser: function(index) {
				try {
					var teasername = contentUl.all(".js_item").item(index).getAttribute("data-teasername");
					var tracker = s;
					tracker.eVar35 = "Buehne_" + teasername;
					tracker.events = "event67";
					tracker.linkTrackEvents = "event67";
					tracker.linkTrackVars = "events,eVar35";
					tracker.tl(window, "o", "Buehnenteaser");
				} catch (ex) {
					console.log('Tracking: ' + ex.message);
				}
			},
			trackClickTeaser: function() {
				try {
					var tracker = s;
					tracker.events = "event66";
					tracker.linkTrackEvents = "event66";
					// tracker.linkTrackVars = "events";
					tracker.tl(window, "o", "Buehnenteaser");
				} catch (ex) {
					console.log('Tracking: ' + ex.message);
				}
			}
		};
	})();

	/**
	 * DaysCounter
	 * 
	 * @class Handles days counter updates
	 */
	YUI.SIM.DaysCounter = function(baseNode, targetDate, nowDate) {
		if (!baseNode) {
			return;
		}

		var digit0 = baseNode.one('.js_digit0'), digit1 = baseNode.one('.js_digit1'), digit2 = baseNode.one('.js_digit2'), digit3 = baseNode.one('.js_digit3'), targetDate = targetDate.split('.');
		daysCounterEndDate = new Date(targetDate[2], targetDate[1] - 1, targetDate[0]); // monat
																						// beginnt
																						// bei
																						// 0

		/**
		 * Calculate difference between two Date objects
		 * 
		 * @function
		 * @param {Date}
		 *            endDate The end date
		 * @returns {Object} time difference between endDate & now
		 */
		var calculateTimeDiff = function(endDate) {
			var now = nowDate,
				timeLeft = endDate.getTime() - now.getTime(),
				timeDiff = {};

			timeDiff.daysLeft = Math.floor(timeLeft / 1000 / 60 / 60 / 24);
			timeLeft -= (timeDiff.daysLeft * 1000 * 60 * 60 * 24);

			timeDiff.hoursLeft = Math.floor(timeLeft / 1000 / 60 / 60);
			timeLeft -= (timeDiff.hoursLeft * 1000 * 60 * 60);

			if (timeDiff.daysLeft < 0) {
				timeDiff.daysLeft = 0;
				timeDiff.hoursLeft = 0;
			}
			
			/*
			 * timeDiff.minutesLeft = Math.floor(timeLeft / 1000 / 60);
			 * timeLeft -= (timeDiff.minutesLeft * 1000 * 60);
			 * 
			 * timeDiff.secondsLeft = Math.floor(timeLeft / 1000);
			 */

			return timeDiff;
		},

		/**
		 * Format number with leading zero
		 * 
		 * @function
		 * @param {Integer}
		 *            n The number
		 * @returns {String} formatted string
		 */
		formatLeadingZero = function(n) {
			if (String(n).length < 2) {
				return n = "0" + n;
			}
			return String(n);
		},

		/**
		 * Update the 4 digits on screen
		 * 
		 * @function
		 * @param {String}
		 *            n The left number as string (2 digits)
		 * @param {String}
		 *            n The right number as string (2 digits)
		 */
		updateDisplay = function(leftNo, rightNo) {
			var showChar = function(node, c) {
				if (node.getContent() !== c) {
					/*
					 * var anim = new Y.Anim({ node: node, from: { top:
					 * node.getY() }, to: { top: node.getY() + 40 },
					 * duration: 0.5, easing: Y.Easing.easeOut });
					 * anim.on('end', function(){ }); anim.run();
					 */
					node.get('childNodes').remove();
					node.appendChild(c);
				}
			};
			showChar(digit0, leftNo.charAt(0));
			showChar(digit1, leftNo.charAt(1));
			showChar(digit2, rightNo.charAt(0));
			showChar(digit3, rightNo.charAt(1));
		},

		timeDiff = calculateTimeDiff(daysCounterEndDate);

		updateDisplay(formatLeadingZero(timeDiff.daysLeft), formatLeadingZero(timeDiff.hoursLeft));

		//todo: testen: clear interval wenn window keinen fokus hat - neu initialisieren on focus
		var startUpdateTimer = (60 - new Date().getMinutes()) * 60000; //Zeit bis zur nächsten vollen Stunde in Milisekunden
		
		window.setTimeout(function() {
			var timeDiff = calculateTimeDiff(daysCounterEndDate);
		updateDisplay(formatLeadingZero(timeDiff.daysLeft), formatLeadingZero(timeDiff.hoursLeft));

		window.setInterval(function() {
			var timeDiff = calculateTimeDiff(daysCounterEndDate);
				updateDisplay(formatLeadingZero(timeDiff.daysLeft), formatLeadingZero(timeDiff.hoursLeft));
			}, 3600000); // ab jetzt stündlich
			
		}, startUpdateTimer)
		
		
	};

	/**
	 * SeparateDaysCounter
	 * 
	 * @class Handles separate DaysCounter (DaysCounter outside of CarouselTeasers)
	 */
	YUI.SIM.SelfContainedDaysCounterController = function() {
		var doJSAnimations = (Modernizr && Modernizr.csstransitions) ? false : true,
		
			getServerTime = function (nodeList) {
				var serverTime,
					parseAttr = function (node) {
						if (typeof serverTime === 'undefined') {
							var timeStr = node.getAttribute('data-servertime');
							if (timeStr !== '') {
								var timeNum = parseInt(timeStr, 10);
								if (!isNaN(timeNum)) {
									serverTime = new Date(timeNum);
								}
							}
						}
					};
				
				// try getting server time from node data attribute
				nodeList.each(parseAttr);
				if (typeof serverTime !== 'undefined') {
					return serverTime;
				}

				// try getting server time from any node data attribute on page (warning: expensive)
				Y.all('[data-servertime]').each(parseAttr);
				if (typeof serverTime !== 'undefined') {
					return serverTime;
				}

				// no server time found, use client time
				console.info('using client time');
				return new Date();
			};
		
		return {
			/**
			 * @param options
			 * @options nodeList - the counter nodeList,
			 */
			initialize: function(options) {
				// options
				if (typeof options != "object") var options = {};
				var nodeList = options.nodeList || Y.all('.selfContainedDaysCounter');

				if (!nodeList || nodeList.isEmpty()) {
					return;
				}

				if (doJSAnimations) {
					if (typeof window.Animator === 'undefined') {
						Y.Get.script([ "/extensions/js/lib/animator-1.1.1/animator-min.js" ], {
							onSuccess: function() {
								YUI.SIM.SelfContainedDaysCounterController.initialize(options);
							}
						});
						return;
					}
				}

				var serverTime = getServerTime(nodeList);

				nodeList.each(function (node) {
					var targetDateStr = node.getAttribute('data-targetdate'),
						posStr = node.getAttribute('data-pos'),
						pos = (posStr !== '') ? JSON.parse(posStr) : null,
						counter = new YUI.SIM.DaysCounter(node, targetDateStr, serverTime),
						styles = {
							display: 'block'
						};
					
					if (pos) {
						styles.left = pos.out.x + 'px';
						styles.top = pos.out.y + 'px';
					} else {
						styles.opacity = 0;
					}
					
					node.setStyles(styles);
					
					setTimeout(function () {
						if (pos) {
							if (doJSAnimations) {
								new Animator({
									transition: Animator.makeElastic(0.8),
									duration: 600
								})
								.addSubject(new CSSStyleSubject(Y.Node.getDOMNode(node), 'left: ' + pos['in'].x + 'px; top: ' + pos['in'].y + 'px;'))
								.play();
							} else {
								node.setStyles({
									left: pos['in'].x + 'px',
									top: pos['in'].y + 'px'
								});
							}
						} else {
							node.setStyles({
								opacity: 1
							});
						}
					}, 1000);
				});
			}
		};
	}();

	/**
	 * CarouselTeaserController
	 * 
	 * @class Handles carousel teasers
	 */
	YUI.SIM.CarouselTeaserController = function() {

		var doJSAnimations = (Modernizr && Modernizr.csstransitions) ? false : true;
		var teasers = [], daysCounter = null, daysCounterEndDate, daysCounterNowDate;

		// console.log('doJSAnimations: ', doJSAnimations);

		/**
		 * Start animation of given teaser module
		 * 
		 * @function
		 * @param {Object}
		 *            teaser The current teaser data object
		 * @param {String}
		 *            moduleID The current module id
		 * @param {Integer}
		 *            duration The animation duration
		 */
		var startModuleAnimation = function(teaser, moduleID, duration, elasticism) {
			if (doJSAnimations) {
				if (!teaser['ani' + moduleID]) {
					teaser['ani' + moduleID] = Animator.apply(teaser['nodeDOM' + moduleID], 'carouselTeaser' + moduleID + 'In', {
						transition: Animator.makeElastic(elasticism),
						duration: duration
					});
				}
				teaser['ani' + moduleID].seekTo(1);
			} else {
				if (teaser && teaser['node' + moduleID]) {
					teaser['node' + moduleID].addClass('carouselTeaser' + moduleID + 'In');
				}
			}
		};

		/**
		 * Reset animation of given teaser module
		 * 
		 * @function
		 * @param {Object}
		 *            teaser The current teaser data object
		 * @param {String}
		 *            moduleID The current module id
		 */
		var resetModuleAnimation = function(teaser, moduleID) {
			if (doJSAnimations) {
				if (teaser && teaser['ani' + moduleID]) {
					teaser['ani' + moduleID].jumpTo(0);
				}
			} else {
				if (teaser && teaser['node' + moduleID]) {
					teaser['node' + moduleID].removeClass('carouselTeaser' + moduleID + 'In');
				}
			}
		};

		return {
			/**
			 * Start teaser animation by teaser index
			 * 
			 * @function
			 * @param {Integer}
			 *            teaserIndex The current index
			 */
			startTeaser: function(teaserIndex) {
				var teaserNode = Y.all('.js_carouselTeaser').item(teaserIndex);
				if (!teaserNode) {
					throw 'YUI.SIM.CarouselTeaserController::startTeaser(): teaser node with index=' + teaserIndex + ' not found!';
				}

				var teaser = null;
				if (teasers && (teasers.length > 0)) {
					for ( var i = 0; i < teasers.length; i++) {
						if (teasers[i].node._yuid == teaserNode._yuid) {
							teaser = teasers[i];
							break;
						}
					}
				}
				daysCounterNowDate = daysCounterNowDate || YUI.SIM.CarouselController.getNowDate();
				// console.log('now is ',daysCounterNowDate);

				if (!teaser) {
					var nodeMainText = teaserNode.one('.carouselTeaserMainText'),
						nodeDaysCounter = teaserNode.one('.carouselTeaserDaysCounter'),
						nodeDaysCounterMitte = teaserNode.one('.carouselTeaserDaysCounterMitte'),
						daysCounterDate,
						nodeStoerer = teaserNode.one('.carouselTeaserStoerer'),
						nodeStoererMitte = teaserNode.one('.carouselTeaserStoererMitte');
					
					if (nodeDaysCounter) {
						daysCounterDate = nodeDaysCounter.getAttribute('data-targetdate');
					}	
					if (nodeDaysCounterMitte) {
						daysCounterDate = nodeDaysCounterMitte.getAttribute('data-targetdate');
					}	

					teaser = {
						index: teaserIndex,
						node: teaserNode,
						// nodeDOMMainText : Y.Node.getDOMNode(nodeMainText),
						// nodeMainText : nodeMainText,
						nodeDOMDaysCounter: Y.Node.getDOMNode(nodeDaysCounter),
						nodeDOMDaysCounterMitte: Y.Node.getDOMNode(nodeDaysCounterMitte),
						nodeDaysCounter: nodeDaysCounter,
						nodeDaysCounterMitte: nodeDaysCounterMitte,
						daysCounter : (nodeDaysCounter ? new YUI.SIM.DaysCounter(nodeDaysCounter, daysCounterDate, daysCounterNowDate) : new YUI.SIM.DaysCounter(nodeDaysCounterMitte, daysCounterDate, daysCounterNowDate)),
						nodeDOMStoerer: Y.Node.getDOMNode(nodeStoerer),
						nodeStoerer: nodeStoerer,
						nodeDOMStoererMitte: Y.Node.getDOMNode(nodeStoererMitte),
						nodeStoererMitte: nodeStoererMitte
					};
					teasers.push(teaser);
				}

				// startModuleAnimation(teaser, 'MainText', 600, 1);
				startModuleAnimation(teaser, 'DaysCounter', 600, 1);
				startModuleAnimation(teaser, 'DaysCounterMitte', 600, 0.7);
				startModuleAnimation(teaser, 'Stoerer', 600, 1);
				startModuleAnimation(teaser, 'StoererMitte', 600, 0.7);
			},

			/**
			 * Stop all teaser animations
			 * 
			 * @function
			 */
			stopTeasers: function() {
				if (!teasers || (teasers.length < 0)) {
					return;
				}
				for ( var i = 0; i <= teasers.length; i++) {
					var teaser = teasers[i];
					// resetModuleAnimation(teaser, 'MainText');
					resetModuleAnimation(teaser, 'DaysCounter');
					resetModuleAnimation(teaser, 'DaysCounterMitte');
					resetModuleAnimation(teaser, 'Stoerer');
					resetModuleAnimation(teaser, 'StoererMitte');
				}
			}
		};
	}();

	/**
	 * VideoController
	 * 
	 * @class handles integration of jwplayer
	 */
	YUI.SIM.VideoController = function() {
		var jwscript, players = {};
		/**
		 * @function setOptions Startwerte aus dem Video-Element auslesen
		 * @param elm
		 *            HTML-Video-Element auf dem der jwplayer aufsetzen soll
		 * @param config
		 *            Objekt, das bereits Konfigurationswerte enthält, die
		 *            übernommen werden
		 * @returns obj options Konfigurationsobjekt für jwplayer
		 */
		var setOptions = function(elm, config) {
			var configObj = (window.SIM && window.SIM.configuration && window.SIM.configuration.video) ? window.SIM.configuration.video : false;
			if (config) { // temp
				configObj = config;
			}
			var options, opts, videoSize, file, videoId = elm.get('id') || Y.guid('video');
			try {
				if (configObj && configObj[videoId]) {
					opts = configObj[videoId];
					file = opts.file;
					var ind = file.indexOf('.');
					if (ind != -1) {
						file = file.slice(0, ind);
					}
					opts.file = file;
				} else {
					videoSize = elm.get('region');
					if (videoSize.width < 1) {
						videoSize = {
							width: elm.get('width'),
							height: elm.get('height')
						};
					}
					file = elm.getAttribute("data-file");
					var ind = file.indexOf('.');
					if (ind != -1) {
						file = file.slice(0, ind);
					}

					opts = {
						height: videoSize.height + 'px',
						width: videoSize.width + 'px',
						file: file,
						poster: elm.getAttribute("data-poster") || elm.get('poster')
					};
				}
			} catch (ex) {
				console.log('error: ' + ex);
			}
			var protocolExists = opts.poster.match(/^http/);
			if (!protocolExists) {
				opts.poster = window.location.protocol+opts.poster;
			}
			return options = {
				id: videoId,
				file: opts.file,
				width: opts.width,
				height: opts.height,
				poster: opts.poster
			};
		};
		/**
		 * @constructor Video Video-Objekt, hält Methoden zur Videokonfiguration
		 *              und -Steuerung bereit
		 * @param elm
		 *            HTML-Video-Element
		 * @param opts
		 *            Konfigurationsobject aus setOptions
		 * @param overlay
		 *            HTML-Element des Overlays
		 * @param triggerlink
		 *            HTML-Anchor-Element Link, der das Öffnen des Layers
		 *            auslöst
		 */
		var Video = function(elm, opts, overlay, triggerlink) {
			this.videoElm = elm;
			this.opts = opts;
			this.autoplay = false;
			this.loaded = false;
			this.overlay = overlay || null;
			this.triggerlinks = [];
			this.triggerlinks.push(triggerlink);
			this.trackedOnce = false;
			var video = this, player = '', trackFinished = false;

			var trackMovieStart = function(videoname, videolength) {
				try {
					var videolength = videolength || 0;
					var tracker = s;
					// TODO: implement Media tracking
					// tracker.Media.trackVars="eVar35,events";
					// tracker.Media.trackEvents="event68";
					tracker.events = "event68";
					tracker.eVar36 = videoname;
					tracker.linkTrackVars = "events,eVar36";
					tracker.linkTrackEvents = "event68";
					// tracker.Media.open(videoname, videolength, 'jwplayer');
					tracker.tl(this, "o", 'Video-' + videoname + '-Start');
					video.trackedOnce = true;
					tracker.linkTrackVars = "none";
					tracker.linkTrackEvents = "none";
				} catch(ex){
					console.log('Tracking: ' + ex.description);
				}
			};
			
			var trackMovieFinish = function(videoname) {
				try {
				if (!trackFinished) {
					var tracker = s;
					// tracker.Media.trackVars="events";
					// tracker.Media.trackEvents="event69";
					tracker.events = "event69";
					tracker.linkTrackVars = "events";
					tracker.linkTrackEvents = "event69";
					// tracker.Media.close(videoname);
					tracker.tl(this, "o", 'Video-' + videoname + '-Finish');
					trackFinished = true;

					tracker.linkTrackVars = "none";
					tracker.linkTrackEvents = "none";
				}
				} catch(ex){
					console.log('Tracking: ' + ex.description);
				}
			};

			var triggerLinkHandler = function(e) {
				e.preventDefault();
				if (video.overlay && !Y.UA.mobile) {
					if (!video.loaded || Y.UA.ie) { // IE doesn't play correctly after the wrapper was set to display:none;
						createPlayer(); // ... so we create the player every time
					}
					YUI.SIM.OverlayController.show(video.overlay, e, {
						centered: true,
						scroll: false
					});
					video.play();
				} else {
					video.play();
				}
			};

			/**
			 * @function addTriggerLink Link zum öffnen des Videolayers
			 *           hinzufügen
			 * @param lnk
			 *            HTML-Anchor-Element
			 */
			this.addTriggerLink = function(lnk) {
				this.triggerlinks.push(lnk);
				lnk.on("click", triggerLinkHandler);
			};

			/**
			 * Methoden zur Videosteuerung
			 */
			this.play = function() {
				try {
					if (player != '') {
						player.play(true);
					} else {
						try {
							video.videoElm.play();
						} catch (ex) {
							console.log('player error (while trying to play): ' + ex);
						}
					}
					/*
					 * var state = player.getState(); // getState verursacht bei
					 * Flash manchmal Fehler - Vorsicht if (state == undefined ||
					 * state != "PLAYING") { player.play(); }
					 */
				} catch (ex) {
					console.log('player error (while trying to play): ' + ex);
				}
			};
			this.stop = function() {
				try {
					player.stop();
				} catch (ex) {
					console.log('player error (while trying to stop): ' + ex);
				}
			};
			this.pause = function() {
				try {
					player.pause(true);
					/*
					 * var state = player.getState(); if (state == undefined ||
					 * state == "PLAYING") { player.pause(); }
					 */
				} catch (ex) {
					console.log('player error (while trying to pause): ' + ex);
				}
			};

			/**
			 * @function createPlayer Initialisierung des jwplayers
			 */
			var createPlayer = function() {
				var options = {
					'id': 'player_' + video.opts.id,
					// 'file': video.opts.file + ".mp4",
					// 'file': video.opts.file + ".ogv",
					'width': video.opts.width + 'px',
					'height': video.opts.height + 'px',
					'poster': video.opts.poster,
					'autostart': video.autoplay ? true : false, // autostart nur im layer
					'dock': false,
					'provider': 'video',
					'volume': 50,
					'screencolor': 'ffffff',
					'stretching': 'exactfit',
					'controlbar': 'bottom',
					'dock': true,
					'modes': [ { // erst html5 probieren, dann flashfallback, dann download anbieten falls alles nix hilft
						'type': "html5"
					}, {
						'type': "flash",
						'src': "/extensions/js/lib/jwplayer/player.swf",
						'file': video.opts.file + '.mp4'
					}, {
						'type': "download"
					} ],
					/*
					 * plugins: { "sharing-2": { link: "http://www.simyo.de" } },
					 */
					'events': {
						onReady: function() {
							Y.fire('video:ready', video);
						},
						onPlay: function() {
							Y.fire('video:play', video);
							if (!video.trackedOnce) {
								trackMovieStart(this.id, this.getDuration());
							}
							// console.log('playing ' + id);
						},
						onPause: function() {
							Y.fire('video:pause', video);
							// console.log('paused ' + id);
						},
						onComplete: function() {
							Y.fire('video:complete', video);
							trackMovieFinish(this.id);
						}
					}
				};
				
				// console.log('video ogg: '+ Modernizr.video.ogg + ', video
				// h264: '+ Modernizr.video.h264);
				if (Modernizr.video.ogg && Modernizr.video.ogg != "") {
					options.file = video.opts.file + '.ogv';
				}
				else {
					options.file = video.opts.file + '.mp4';
				}
				/*
				 * if (!Modernizr.video) { // IE: jwplayer can't find src of
				 * file because video element is unknown, so we need to help.
				 * options.file = video.opts.file + '.mp4'; }
				 */
				
				video.loaded = true;
				return player = jwplayer(video.opts.id).setup(options);
			};
			
			if (this.overlay && !Y.UA.mobile) {
				// this.autoplay = true;
				if (!video.loaded) {
					var p = this.videoElm.get('parentNode');
					var thumbnail = p.siblings('.videoThumbnail').item(0);
					if (thumbnail) {
						thumbnail.setStyle('display', 'block');
						p.setStyle('display', 'none');
					}
					if (Y.UA.ie) {
						p.removeChild(this.videoElm);
						this.overlay.one('.overlayBody').append(Y.Node.create('<div id="' + video.opts.id + '"></div>'));
					} else {
						this.overlay.one('.overlayBody').append(this.videoElm);
					}
					createPlayer();
				}
				Y.on('overlay:beforeClose', function(e, ov) {
					if (Y.UA.ie) {
						video.stop();
					} else {
						video.pause();
					}
				});
			} else if (!video.loaded) {
				if (!Y.UA.mobile || Y.UA.android && Y.UA.android < 2.3) {
					video.opts.width  = parseInt(video.videoElm.getStyle('width')) || parseInt(video.videoElm.get('parentNode').getStyle('width'));
					video.opts.height = parseInt(video.videoElm.getStyle('height')) || parseInt(video.videoElm.get('parentNode').getStyle('height'));
					createPlayer();
				} else {
					video.videoElm.set('controls', 'controls');
				}
			}

			players[this.opts.id] = this;
			return this;
		};

		return {
			/**
			 * @function loadScript jwplayer nachladen, dann callback ausführen
			 * @param onLoadingSuccess
			 *            callbackfunktion zum Ausführen nach dem Laden des
			 *            jwplayers
			 */
			loadScript: function(onLoadingSuccess) {
				jwscript = Y.Get.script('/extensions/js/lib/jwplayer/jwplayer.js', {
					onSuccess: function(e) {
						if (onLoadingSuccess) {
							onLoadingSuccess();
						}
					}
				});
			},
			initialize: function() {
				// initialisiere alle Player, die nicht im Layer laufen
				var videoElms = Y.all('.js_videoplayer'), ln = videoElms.size(), triggerLinks = Y.all('.js_videotrigger'), lnn = triggerLinks.size(), videoElm, hashID, opts, player, videoIds = [];
				if (ln > 0) {
					for ( var i = 0; i < ln; i++) {
						try {
							videoElm = videoElms.item(i);
							opts = setOptions(videoElm);
							videoIds.push(opts.id);
							var overlay = videoElm.get('parentNode').siblings('.overlay').item(0);
							player = new Video(videoElm, opts, overlay);
						} catch (ex) {
							console.log('error videoplayer: ' + ex);
						}
					}
					for (i = 0; i < lnn; i++) {
						hashID = triggerLinks.item(i).get('hash').substring(1);
						if (hashID && videoIds.length > 0 && Y.Array.indexOf(videoIds, hashID) != -1) {
							player = players[hashID];
							player.addTriggerLink(triggerLinks.item(i));
						}
					}
				}

				Y.on('overlay:show', function(e, ov) {
					YUI.SIM.VideoController.pauseAllPlayers();
				});
			},
			pauseAllPlayers: function() {
				for (var i in players) {
					if (players.hasOwnProperty(i)) {
						players[i].pause();
					}
				}
			}
		};
	}();

	/**
	 * PreloaderController
	 * 
	 * @class assists jsf and provides helpers for ajax preloading animation
	 */
	YUI.SIM.PreloaderController = function() {
		return {
			/**
			 * shows the preloader
			 * 
			 * @function
			 */
			show : function() {
				Y.one('.jsPreloader').addClass('jsPreloading');
			},
			hide : function() {
				Y.one('.jsPreloader').removeClass('jsPreloading');
			}
		};
	}();

	YUI.SIM.PopupController = function() {

		var openNewPopup = function(e, paramsObj, elm) {
			var params = {
				width : paramsObj.width || 655,
				height : paramsObj.height || 500,
				url : paramsObj.url || e.currentTarget.get('href')
			};
			window.open(params.url, '', "menubar=no,width=" + params.width + ",height=" + params.height + ",toolbar=no,status=no,titlebar=no,scrollbars=yes,resizable=yes,directories=false");
		};

		return {
			openPopup : function(e, eventObj, options) {
				if (e) {
					e.preventDefault();
				}
				var options = options || {};
				if (!options.width) {
					options.width = eventObj && eventObj.hasClass('popupWide') ? 710 : null;
				}
				openNewPopup(e, options, eventObj);
			}
		};
	}();

	YUI.SIM.PasswordController = function() {
		var pwString, pwChars, pwSecurityElm, pwSecurityMask, pwSecurityDefaultClass, pwMinLength = 8, baseScore = 0, score = 0, num = {}, bonus = {}, multiplier = {// bonus
			// multipliers
			excess : 1, // more letters than needed
			upper : 3,
			lower : 0,
			numbers : 3,
			symbols : 5
		};

		var escapeRegexp = function(text) {
			return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
		}, checkPasswordSecurity = function(e) {
			if (pwString.length >= pwMinLength) {
				baseScore = 50;
			} else {
				baseScore = 0;
			}
			clearCounters();
			analyzeString();
			calcComplexity();
			displayResult();
		}, clearCounters = function() {
			score = 0;
			num = { // number of characters
				excess : 0, // more than minlength
				upper : 0,
				lower : 0,
				numbers : 0,
				symbols : 0,
				repetitions : 0
			};
			bonus = { // extra boni
				combo : 0, // combination of different chars
				flatLower : 0, // only lowercase
				flatNumber : 0, // only numbers
				flatRepetition : 0
			// repeated characters
			};
		}, analyzeString = function() {
			var length = pwString.length;
			for (i = 0; i < length; i++) {
				if (pwString.charAt(i).match(/[A-Z]/g)) {
					num.upper++;
				}
				if (pwString.charAt(i).match(/[a-z]/g)) {
					num.lower++;
				}
				if (pwString.charAt(i).match(/[0-9]/g)) {
					num.numbers++;
				}
				if (pwString.charAt(i).match(/(.*[!,@,#,$,%,^,&,*,?,_,~])/)) {
					num.symbols++;
				}

				ra = new RegExp(escapeRegexp(pwString.charAt(i)), 'g'), re = pwString.match(ra);
				if (re.length > 1) {
					num.repetitions++;
				}
			}
			num.excess = length - pwMinLength;

			if (num.upper && num.lower && num.numbers && num.symbols) {
				bonus.combo = 55;
			} else if (num.upper && num.numbers && num.symbols) {
				bonus.combo = 35;
			} else if ((num.upper && num.numbers) || (num.upper && num.symbols) || (num.numbers && num.symbols)) {
				bonus.combo = 15;
			}
			if (num.repetitions) {
				bonus.flatRepetition = num.repetitions * -10;
			}

			if (pwString.match(/^[\sa-z]+$/)) {
				bonus.flatLower = (num.excess > 0) ? -100 * num.excess : -100;
			}
			if (pwString.match(/^[\s0-9]+$/)) {
				bonus.flatNumber = (num.excess > 0) ? -100 * num.excess : -100;
			}
		}, calcComplexity = function() {
			score = baseScore + (num.excess * multiplier.excess) + (num.upper * multiplier.upper) + (num.numbers * multiplier.numbers) + (num.symbols * multiplier.symbols) + bonus.combo + bonus.flatLower + bonus.flatNumber + bonus.flatRepetition;
		}, displayResult = function() {
			var pwstateClass = pwSecurityDefaultClass, pwStateName = 'schwaches Passwort';

			if (pwString == "") {
				pwstateClass = pwSecurityDefaultClass;
				pwStateName = 'schwaches Passwort';
			}
			/*
			 * else if (charPassword.length < pwMinLength){ }
			 */
			else if (score < 25) {
				pwstateClass += " pwstate_1";
				pwStateName = 'Passwortstärke: sehr schwach';
			} else if (score >= 25 && score < 50) {
				pwstateClass += " pwstate_2";
				pwStateName = 'Passwortstärke: schwach';
			} else if (score >= 50 && score < 75) {
				pwstateClass += " pwstate_3";
				pwStateName = 'Passwortstärke: mittel';
			} else if (score >= 75 && score < 100) {
				pwstateClass += " pwstate_4";
				pwStateName = 'Passwortstärke: stark';
			} else if (score >= 100) {
				pwstateClass += " pwstate_5";
				pwStateName = 'Passwortstärke: sehr stark';
			}
			pwSecurityMask.setAttribute('class', pwstateClass);
			pwSecurityMask.set('text', pwStateName);
			pwSecurityElm.set('title', pwStateName);
		};

		return {
			initialize : function() {
				var pwBox = Y.one('.js_passwordsecurity');
				if (pwBox) {
					try {
						var pwField = pwBox.one('input[type="password"]');
						pwSecurityElm = pwBox.one('.passwordsecurity');
						pwSecurityMask = pwBox.one('.passwordsecurity_mask');
						pwSecurityDefaultClass = pwSecurityMask.getAttribute('class');
						if (pwField && pwSecurityElm && pwSecurityMask) {
							pwField.on('keyup', function(e) {
								pwString = pwField.get('value');
								checkPasswordSecurity(e);
							});
						}
					} catch (ex) {
						// console.log('PasswordController warning: ' + ex);
					}
					;
				}
			},
			reinit : function(e) {
				if (e && e.responseCode === 200) {
					YUI.SIM.PasswordController.initialize();
				}
			}
		};
	}();

	YUI.SIM.OverlayController = function() {
		var bodyElm = YUI.SIM.Nodes.Body, params = {}, ajaxContainer, wrapper, overlay, dimmer, dimmerIframe, close, browser = Y.UA, dom = Y.DOM,

		wrapLayer = function() {
			var layercontent = ajaxContainer.getContent();
			ajaxContainer.setContent('');
			dimmer = Y.one('#dimmer');
			dimmerIframe = Y.one('#dimmerIframe');
			if (!dimmer) {
				dimmer = Y.Node.create('<div id="dimmer"></div>');
				ajaxContainer.append(dimmer);
			}
			if (browser.ie && browser.ie < 7 && !dimmerIframe) {
				dimmerIframe = Y.Node.create('<iframe id="dimmerIframe" src="/pages/blank.html" name="dimmerIframe"></iframe>');
				ajaxContainer.append(dimmerIframe);
			}
			var container = Y.Node.create('<div class="overlay js_overlay"><div class="overlayContent cl"><div class="overlayHead"><a href="#" class="buttonWrapper textButtonWrapper buttonTypCloseWrapper closeOverlay js_closeOverlay" title="Hinweis schließen"><span class="button">Schließen</span></a></div><div class="overlayBody cl">' + layercontent + '</div></div></div></div>');
			return container;
		}, 
		wrapOverlay = function(content) {
			var wrapper = Y.one('.overlayWrapper');
			if (wrapper) {
				var dontreusewrapper = wrapper.one('.js_overlay_noreuse'); // used
				// on
				// recommend
				// layer
				if (dontreusewrapper) {
					// check if there is another div we can recycle
					var wrappers = Y.all('.overlayWrapper'), ln = wrappers.size();
					if (ln > 1) {
						for ( var i = 1; i < ln; i++) {
							if (!wrappers.item(i).one('.js_overlay_noreuse')) {
								wrapper = wrappers.item(i);
								dontreusewrapper = false;
							}
						}
					}
				}
			}

			var w = (wrapper && !dontreusewrapper) ? wrapper.setContent('') : Y.Node.create('<div class="overlayWrapper"></div>');
			
			/*var w = (wrapper && !dontreusewrapper) ? wrapper.setContent('').setStyles({
				'top' : 0,
				'position' : 'absolute'
			}) : Y.Node.create('<div class="overlayWrapper"></div>');
			 */
			bodyElm.append(w);
			return w.append(content);
		}, setDimmerPosition = function() {
			dimmer.setStyle('height', dom.docHeight() + 'px');
		}, setOverlayPosition = function() {
			if (params.centered) {
				var vportreg = Y.DOM.viewportRegion(), topvalue = (vportreg.height - 100 - overlay.get('clientHeight')) / 2 + 'px';

				wrapper.setStyles({
					'top' : topvalue
				});
				wrapper.addClass('fixed');
				/*
				 * overlay.setStyles({ 'margin' : "0 auto", 'top' : 0, 'left' :
				 * 0, 'position' : 'relative' });
				 */
			} else {
				var contentmode = Y.one('.shadowWrapperFullSize') ? 'fullsize' : 'normal';
				if (contentmode == 'fullsize') {
					overlay.addClass('modeTemplateWide');
				}
				wrapper.removeClass('fixed');
			}
		}, resetDimmerHeight = function() {
			if (dimmer && dom.docHeight() > dimmer.get('region').height) {
				dimmer.setStyle('height', dom.docHeight() + 'px');
			}
		}, registerEvents = function() {
			Y.delegate("click", (function(e) {
				e.preventDefault();
				if (this.get('id') == 'dimmer') {
					close = overlay.one('.js_closeOverlay');
					if (close && close.get('onclick')) {
						(close.get('onclick'))(); // falls ein jsf-button
						// ausgelöst werden muss
						// (taflayer)
						return;
					}
				}
				hideOverlay(e);
			}), YUI.SIM.Nodes.Body, '.js_closeOverlay,#dimmer');
			
			Y.all('.js_openLayer').on('click',function(e) {
				var node = e.currentTarget, hash = node.get('hash');
				if (hash) {
					var layer = Y.one(hash);
					if (!layer) {
						return true;
					}
					e.preventDefault();
					YUI.SIM.OverlayController.show(layer,e,{wrap:false});
				}

			});
			
			Y.on('expandable:toggle', function(area) {
				resetDimmerHeight();
			});
			Y.on('togglebox:toggle', function(area) {
				resetDimmerHeight();
			});
			
		}, showOverlay = function(overlay, e) {
			if (overlay) {
				bodyElm.addClass('showOverlay');
				wrapper.setStyles({
					'display' : 'block',
					'visibility' : 'visible'
				});
				overlay.setStyles({
					'display' : 'block'
				});
				setOverlayPosition();
				overlay.setStyles({
					'visibility' : 'visible'
				});

				if (browser.ie) {
					if (browser.ie < 7) {
						dimmerIframe.setStyle('width', dom.docWidth() + 'px');
						dimmerIframe.setStyle('height', dom.docHeight() + 'px');
						dimmerIframe.setStyle('display', 'block');
					}
				}
				setDimmerPosition();
				Y.fire('overlay:show', e, overlay);
				if (params.scroll) {
					try {
						overlay.scrollIntoView(); // todo: alternative für IE
					} catch (ex) {
						console.log('scroll error: ' + ex);
					}
				}
			}
		}, hideOverlay = function(e) {
			Y.fire('overlay:beforeClose', e, overlay);
			bodyElm.removeClass('showOverlay');
			wrapper.setStyles({
				'display' : 'none'
			});
			overlay.setStyles({
				'display' : 'none',
				'visibility' : 'hidden'
			});
			if (browser.ie && browser.ie < 7) {
				dimmerIframe.setStyle('display', 'none');
			}
			Y.fire('overlay:close', e, overlay);
		}, removeOverlay = function(e) {
			dimmer.remove();
			dimmerIframe.remove();
			overlay.remove();

		};

		return {
			show : function(ov, e, p) {
				var p = p || {};
				params.scroll = p.scroll != undefined ? p.scroll : false;
				params.wrap = p.wrap != undefined ? p.wrap : true;
				params.centered = p.centered != undefined ? p.centered : false;

				overlay = ov || Y.one('.overlay');
				if (!overlay.ancestor){
					overlay = Y.one(ov);
				}
				if (params.wrap) {
					wrapper = wrapOverlay(overlay);
				} else {
					wrapper = overlay.ancestor('.overlayWrapper');
				}

				dimmer = dimmer ? dimmer : Y.one('#dimmer') || (function() {
					var d = Y.Node.create('<div id="dimmer"></div>');
					bodyElm.append(d);
					return d;
				})();
				if (browser.ie && browser.ie < 7) {
				dimmerIframe = dimmerIframe ? dimmerIframe : Y.one('#dimmerIframe') || (function() {
					var i = Y.Node.create('<iframe id="dimmerIframe" src="/pages/blank.html" name="dimmerIframe"></iframe>');
					bodyElm.append(i);
					return i;
				})();
				}		
				close = Y.one('.js_closeOverlay');
				showOverlay(overlay, e);
			},
			hide : function(e) {
				hideOverlay(e);
			},
			initialize : function() {
				overlay = Y.one('.js_overlay');
				if (overlay) {
					setDimmerPosition();
				}
				registerEvents();

				// used in html prototyp only
				if(window.Development && window.Development.prototyp) {
					YUI.SIMPROTO.OverlayController.initialize();
				}
				
			},
			onajaxload : function(e) {
				if (e && e.status === 'success' || (e.statusText && e.statusText === 'OK')) {
					ajaxContainer = Y.one('.js_overlayAjaxContainer');
					if (ajaxContainer) {
						var c = wrapLayer();
						YUI.SIM.OverlayController.show(c, e, {
							scroll : true
						});
						YUI.SIM.HandyoptionController.trackLayerOpen();
					}
				}
			}
		};
	}();
	YUI.SIM.HandyoptionController = function() {
		return {
			trackLayerOpen : function() {
				try {
					var tracker = s;
					var eventNo = Y.one('#ho-tracking-serial').get('value'), products = Y.one('#ho-tracking-phone').get('value');
					tracker.events = 'prodView,event47:' + eventNo;
					tracker.linkTrackEvents = 'prodView,event47:' + eventNo;
					tracker.products = ';' + products;
					tracker.pageName = tracker.eVar10 = tracker.eVar17 = "handy-angebote-detail/" + products;
					tracker.t();
				} catch (ex) {
					console.log('Tracking: ' + ex.message);
				}
			},
			initialize : function() {
				/*
				 * Y.on('overlay:show', function(e, overlay) {
				 * window.scrollTo(overlay.getX(),overlay.getY()); });
				 */
			}
		};
	}();
	YUI.SIM.InterstitialController = function() {
		var overlay, config = {}, tracker, trackInterstitial = function(e, eventNo, eventName, eventVar) {
			try {
				tracker = s;
				tracker.events = eventNo;
				tracker.linkTrackVars = eventVar ? "events," + eventVar : "events";
				tracker.linkTrackEvents = eventNo;
				tracker.tl(e, "o", eventName);
			} catch (ex) {
				console.log('Tracking: ' + ex.description);
			}
		}, avoidInterstitial = function() {
			Y.use('io', function(Y) {
				actionURL = config.host + config.avoidAction;
				var cfg = {
					data : 'action=decline',
					headers : {
						'Content-Type' : 'application/json'
					},
					on : {
						failure : function(id, o, args) {
							return true;
						},
						success : function(id, o, args) {
							return true;
						},
						context : Y
					}
				};
				var request = Y.io(actionURL, cfg);
				hide();
			});
		}, show = function(overlay) {
			// track start evtl über seitenaufruf direkt
			try {
				tracker = s;
				tracker.eVar11 = config.name;
				trackInterstitial(this, 'event18', 'Interstitial show', 'eVar11');
			} catch (ex) {
				console.log('Tracking: ' + ex.description);
			}
			YUI.SIM.OverlayController.show(overlay);
		}, hide = function() {
			YUI.SIM.OverlayController.hide();
		}, registerEvents = function() {
			Y.on('overlay:close', function(e) {
				trackInterstitial(e.target, 'event19', 'Interstitial close');
			});
			Y.delegate("click", (function(e) {
				e.preventDefault();
				trackInterstitial(e.target, 'event21', 'Interstitial avoid');
				avoidInterstitial();
			}), '.overlay', '.js_avoidInterstitial');
			Y.delegate("click", (function(e) {
				trackInterstitial(e.target, 'event20', 'Interstitial rate change');
			}), '.overlay', '.js_submitInterstitial');
		};

		return {
			initialize : function() {
				try {
					config = SIMInterstitialOptions;
					config.host = window.location.protocol + '//' + window.location.host;
				} catch (ex) {
					//console.log('SIMInterstitialOptions not available: ' + ex.description);
				}
				
				overlay = Y.one('.js_interstitial');
				if (overlay) {
					config.avoidAction = overlay.one('.js_avoidInterstitial').get('href') || '/mein-simyo/interstitials-abmelden.html';
					registerEvents();
					show(overlay);
				}
			}
		};
	}();

	YUI.SIM.NboTeaserController = function() {
		var nbo, nbos, config = {}, tracker, trackNboTeaser = function(e, eventNo, eventName, eventVar) {
			try {
				tracker = s;
				tracker.events = eventNo;
				tracker.linkTrackVars = eventVar ? "events," + eventVar : "events";
				tracker.linkTrackEvents = eventNo;
				tracker.tl(e, "o", tracker.pageName + '|' + eventName);
			} catch (ex) {
				console.log('Tracking: ' + ex.description);
			}
		}, avoidNboTeaser = function(settingId) {
			sID = 'settingId=' + settingId;

			Y.use('io', function(Y) {
				actionURL = config.avoidAction;
				var cfg = {
					data : sID,
					headers : {
						'Content-Type' : 'application/json'
					},
					on : {
						failure : function(id, o, args) {
							return true;
						},
						success : function(id, o, args) {
							return true;
						},
						context : Y
					}
				};
				var request = Y.io(actionURL, cfg);
				hide(settingId);
			});
		}, show = function(nbo) {
			var nboname = nbo.one('.js_teaserName').get('value');
			// track start evtl über seitenaufruf direkt
			try {
				tracker = s;
				tracker.eVar11 = tracker.pageName + '|' + 'NboTeaser ' + nboname;
			} catch (ex) {
				console.log('Tracking: ' + ex.description);
			}
			trackNboTeaser(this, 'event18', 'NboTeaser ' + nboname + ' show', 'eVar11');
		}, hide = function(settingId) {
			YUI({
				base: '/extensions/js/lib/yui-3.3.0/build/'
			}).use("anim", function(Y) {
				Y.one('#' + settingId).addClass('anim');
				var anim = new Y.Anim({
					node : '#' + settingId,
					to : {
						opacity : 0,
						height : 0
					},
					easing : Y.Easing.backIn
				});
				anim.run();
			});
		}, registerEvents = function() {
			YUI.SIM.Nodes.Body.delegate('click', (function(e) {
				e.preventDefault();
				var settingId = e.currentTarget._node.offsetParent.attributes.id.nodeValue;
				var nboname = Y.one('#' + settingId).one('.js_teaserName').get('value');
				trackNboTeaser(e.target, 'event21', 'NboTeaser ' + nboname + ' avoid');
				avoidNboTeaser(settingId);
			}), '.js_avoidNboTeaser');
			YUI.SIM.Nodes.Body.delegate('click', (function(e) {
				trackNboTeaser(e.target, 'event20', 'NboTeaser rate change');
			}), '.js_submitNboTeaser');
		};
		return {
			initialize : function() {
				config.host = window.location.protocol + '//' + window.location.host;

				nbos = Y.all('.nbobox');
				if (nbos.size() > 0) {
					config.avoidAction = '/mein-simyo/nbo-abmelden.html';
				}
				Y.on('tracking:sitecatalystAvailable', function(){
					registerEvents();
					nbos.each(function(nbo) {
						show(nbo);
					});
				});
			}
		};
	}();

	YUI.SIM.RecommendController = function() {
		var socialbars, headline, intro, taflink = '', recLayer, boundingBox, tweettext = "";

		var registerEvents = function() {

			// socialbar -> layer öffnen
			Y.all('.js_twitter_share,.js_mail_share,.js_facebook_share,.js_code_share').on('click', function(e) {
				e.preventDefault();
				tweettext = e.currentTarget.getAttribute('data-text');

				var button = e.currentTarget.next('input[type="submit"]'), render = YUI.SIM.UiHelpers.getPrefixedClass('js_jsfrender_-', button.get('className')), onevent = YUI.SIM.RecommendController.onRecommendlayerLoad;
				// used for production
				if (!window.Development || !window.Development.prototyp) {
					YUI.SIM.JsfFacade.submitAjaxButton(e, button, render, onevent);
				}
				// used in html prototyp only
				if (window.Development && window.Development.prototyp) {
					YUI.SIMPROTO.RecommendController.onShareClick(button, e, recLayer);
				}
			});

			// social layer geöffnet -> twitter nicht eingeloggt abschicken
			Y.delegate('click', function(e) {
				YUI.SIM.RecommendController.trackTweetLoggedOut(e);
			}, '.js_layerboundingbox', '.js_twitter_share_extern');
			
			// social layer geöffnet -> facebook nicht eingeloggt abschicken
			Y.delegate('click', function(e) {
				YUI.SIM.RecommendController.trackFBShareLoggedOut(e);
			}, '.js_layerboundingbox', '.js_facebook_share_extern');

			Y.delegate('click', function(e) {
				selectShortlink(e);
			}, '.js_layerboundingbox', '.js_selectOnClick');
			
			
			/*Y.delegate('click', function(e) {
				YUI.SIM.RecommendController.copyShortlink(e);
			}, '.js_layerboundingbox', '.js_copy_shortlink');
			*/
			// aufruf durch shortLinkWidget
			// warum klappt das nicht??
			/*
			 * Y.on('shortlink:generated', function(e, elm, shortlink){
			 * if(elm.hasClass('.js_twitter_share_loggedin')) { //weiter gehts
			 * mit twitterlink zusammenstellen, twitter im popup öffnen
			 * console.log('twitterlink geklickt, shortlink ist: ' + shortlink) }
			 * });
			 */
		};
		var openTwitterPopup = function(elm, params) {
			var twitterURL = elm ? elm.get('href') || 'https://twitter.com/share?lang=de' : 'https://twitter.com/share?lang=de';
			var text = tweettext || elm.getAttribute('data-text');
			var link = params.link;
			if (text) {
				text = "&text=" + encodeURIComponent(text);
			}
			if (link) {
				link = link.indexOf('http') != -1 ? "&url=" + encodeURIComponent(link) : "&url=" + encodeURIComponent('https://' + link);
			}

			var obj = {
				url : twitterURL + link + text
			};
			YUI.SIM.PopupController.openPopup(null, elm, obj);
		};

		var selectShortlink = function(e) {
			var inputelm = e.currentTarget.one('input');
			inputelm.focus();
			inputelm.select();
		};
		
		var fbSend = function (o) {
			var link = o.link ? o.link : (Y.one('link[rel=canonical]') ?  Y.one('link[rel=canonical]').get('text') : document.location.href);
			/*var pagetitle =  Y.one('meta[property=og:title]') ? Y.one('meta[property=og:title]').get('content') : (Y.one('title') ? Y.one('title').get('text') : null);
			var pagedescription = Y.one('meta[property=og:description]') ? Y.one('meta[property=og:description]').get('content') : (Y.one('meta[name=description]') ? Y.one('meta[name=description]').get('text') : null);*/

		    // tile, description and picture are taken from <link>
			FB.ui({
				method: 'send',
				link: link/*,
				name: pagetitle,
				description: pagedescription,
				picture: 'optional/picture'*/
			}/*,
			function(response) {
				if (response && response.post_id) {
					console.log('Post was sent.');
				} else {
					console.log('Post was not sent.');
				}
			}*/);
		};

		var fbFeed = function (o) {
			var link = o.link ? o.link : (Y.one('link[rel=canonical]') ?  Y.one('link[rel=canonical]').get('text') : document.location.href);
			FB.ui({
				method: 'feed',
				link: link
			}/*,
			function(response) {
				if (response && response.post_id) {
				//	console.log('Post was posted.');
				} else {
				//	console.log('Post was not posted.');
				}
			}*/);
		};
		return {
			initialize : function() {
				var sbar = Y.one('.js_socialbar'), sbox = Y.one('.js_sociallikebox');
				
				if(!(sbar || sbox)) {return}
				
				recLayer = Y.one('#jsfplaceholder_socialmail');
				registerEvents();
				
				// prototyp: load google+ and facebook scripts
				if(!window.Development || !window.Development.prototyp) {
				
					if(sbar && sbar.one('.js_googleplus')) {
						window.___gcfg = {lang: 'de'};
						(function() {
						  var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
						  po.src = '//apis.google.com/js/plusone.js';
						  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
						})();
					}
					
					(function() {
					  var e = document.createElement('script'), r =document.getElementById('fb-root');
					  e.src = '//connect.facebook.net/de_DE/all.js';
					  e.async = true;
					  if(r) {r.appendChild(e)};
					}());
					
					window.fbAsyncInit = function () {
						//console.log('init fb');
						var loggedin = false;
						
						var localAppId, localname = document.location.hostname.split('.')[0];
						switch (localname) {
							case 'www':
								localAppId = '240759959275097';
								break;
							case 'integration':
								localAppId = '148177225285584';
								break;
							case 'stage':
								localAppId = '231257903609943';
								break;
							case 'localhost':
								localAppId = '102627259857098'; //apitest localhost isavar
								break;
							default:
								localAppId = '240759959275097';
						}
						
						FB.init({
							appId: localAppId,
							//cookie: true,
							//channelUrl : '//localhost:8080/channel.html', // Channel File
							oauth : true,
							xfbml  : true  // parse XFBML
						});
						FB.getLoginStatus(function (response) {
						//	console.log(response.status);
							if(response.status !== "unknown") {
								var fpElm = Y.one('#fb-facepile-condition');
								if(fpElm) {
									var fpBox = Y.Node.getDOMNode(fpElm.ancestor('.socialLikeBox'));
									fpElm.addClass('fb-facepile loggedin');
									FB.XFBML.parse(fpBox);
								}
							}
						});

					};
				}
				else {
					YUI.SIMPROTO.RecommendController.loadExternalScripts();
				}
			},
			/*copyShortlink : function(e) {
				var shortlink = e.container.one('.js_copy_shortlink_content').get('text');
				//http://yuilibrary.com/gallery/show/clipboard
			},*/
			onRecommendlayerLoad : function(e) {
				if (e && e.status === 'success' || (e.statusText && e.statusText === 'OK')) {
					recLayer = Y.one('#jsfplaceholder_socialmail');
					YUI.SIM.OverlayController.show(recLayer, e, {
						centered : true,
						wrap : false
					});
				}
			},
			openTwitterSharePopup : function(elm, shortlink) {
				var obj = {
					'link' : shortlink || null
				};
				openTwitterPopup(elm, obj);
			},
			shareOnFacebook : function(elm, shortlink) {
				var obj = {
					'link' : shortlink || null
				};
				fbFeed(obj);
				//console.log('shareOnFacebook eingeloggt');
			},
			onTwitterShared : function(e) {
				if (e && e.status === 'success' || (e.statusText && e.statusText === 'OK')) {
					var shortlinkelm = recLayer.one('.js_shortlink');
					if (shortlinkelm) {
						var link = shortlinkelm.get('text') || shortlinkelm.getAttribute('data-shortlink') || null;
						var obj = {
							'link' : link
						};
						openTwitterPopup(null, obj);						
					}
				} else {
					YUI.SIM.PreloaderController.show();
				}
			},
			onFacebookShared : function(e) {
				if (e && e.status === 'success' || (e.statusText && e.statusText === 'OK')) {
					var shortlinkelm = recLayer.one('.js_shortlink');
					if (shortlinkelm) {
						var link = shortlinkelm.get('text') || shortlinkelm.getAttribute('data-shortlink') || null;
						var obj = {
							'link' : link
						};
						//console.log('und nu: facebook share nicht eingeloggt');
						fbFeed(obj);
					}
				} else {
					YUI.SIM.PreloaderController.show();
				}
			},
			onCodeShared : function(e) {
				if (e && e.status === 'success' || (e.statusText && e.statusText === 'OK')) {
					//tracken? oder hier serverseitig?
					//console.log('und nu: Code share nicht eingeloggt und eingeloggt?');
				} else {
					YUI.SIM.PreloaderController.show();
				}
			},
			onEmailLogin : function(e) {
				if (e && e.status === 'success' || (e.statusText && e.statusText === 'OK')) {
					// tracking?
				} else {
					YUI.SIM.PreloaderController.show();
				}
			},
			onEmailNotLoggedin : function(e) {
				if (e && e.status === 'success' || (e.statusText && e.statusText === 'OK')) {
					// tracking?
				} else {
					YUI.SIM.PreloaderController.show();
				}
			},
			trackTweetLoggedIn : function(e, sessionid) {
				try {
					var tracker = s;
					tracker.events = "event12:" + sessionid;
					tracker.eVar15 = "Tafsitelink-Twitter_lg";
					tracker.pageName = "/de/tafsitelinkstart_twitter_lg.html";
					tracker.linkTrackVars = "events,eVar15";
					tracker.linkTrackEvents = "event12";
					tracker.tl(e, "o", 'Tafsitelink-Twitter_lg');
				} catch (ex) {
					console.log('Tracking: ' + ex.description);
				}
			},
			trackTweetLoggedOut : function(e) {
				try {
					var tracker = s;					
					tracker.eVar15 = "Tafsitelink-Twitter_nl";
					tracker.pageName = "/de/tafsitelink_twitter_exit_nl.html";
					tracker.linkTrackVars = "eVar15";					
					tracker.tl(e, "o", 'Tafsitelink-Twitter_exit_nl');
				} catch (ex) {
					console.log('Tracking: ' + ex.description);
				}
			},
			trackFBShareLoggedIn : function(e, sessionid) {
				try {
					var tracker = s;
					tracker.events = "event12:" + sessionid;
					tracker.eVar15 = "Tafsitelink-Facebook_lg";
					tracker.pageName = "/de/tafsitelinkstart_facebook_lg.html";
					tracker.linkTrackVars = "events,eVar15";
					tracker.linkTrackEvents = "event12";
					tracker.tl(e, "o", 'Tafsitelink-Facebook_lg');
				//	console.log('track facebook loggedin');
				} catch (ex) {
					console.log('Tracking: ' + ex.description);
				}
			},
			trackFBShareLoggedOut : function(e) {
				try {
					var tracker = s;					
					tracker.eVar15 = "Tafsitelink-Facebook_nl";
					tracker.pageName = "/de/tafsitelink_facebook_exit_nl.html";
					tracker.linkTrackVars = "eVar15";					
					tracker.tl(e, "o", 'Tafsitelink-Facebook_exit_nl');
				//	console.log('track facebook not loggedin');
				} catch (ex) {
					console.log('Tracking: ' + ex.description);
				}
			}
		};
	}();

	YUI.SIM.ToggleGroupController = function() {

		var showTarget = function(target, mode) {
			if (mode == 'hide') {
				target.removeClass('js_hidden');
			} else if (mode == 'mute') {
				target.removeClass('js_muted');
				target.all('input').each(function(elm) {
					elm.removeAttribute('disabled');
				});
			}
		};
		var hideTarget = function(target, mode) {
			if (mode == 'hide') {
				target.addClass('js_hidden');
			} 
			else if (mode == 'mute') {
				target.addClass('js_muted');
				target.all('input').set('disabled', 'disabled').set('checked', false);
			}
		};
		var showTargets = function(targets) {
			targets.each(function(t,idx,arr){
				var mode = t.getData('togglemode');
				if(!mode) {
					mode = t.getAttribute('data-togglemode');
					t.setData('togglemode', mode);
				}
				if (mode == 'hide') {
					t.removeClass('js_hidden');
				} 
				else if (mode == 'mute') {
					t.removeClass('js_muted');
					t.all('input').each(function(elm) {
						elm.removeAttribute('disabled');
						if(elm.test('input[type=checkbox]') && elm.getData('checkstate')) {
							elm.set('checked',elm.getData('checkstate'));
						}
					});
				}
			});
		};
		var hideTargets = function(targets, wipemode) {
			targets.each(function(t,idx,arr){
				var mode = t.getData('togglemode');
				if(!mode) {
					mode = t.getAttribute('data-togglemode');
					t.setData('togglemode', mode);
				}
				
				if (mode == 'hide') {
					t.addClass('js_hidden');
				} else if (mode == 'mute') {
					t.addClass('js_muted');
					
					t.all('input').each(function(elm){
						elm.set('disabled', 'disabled');
						if(elm.test('input[type=checkbox]') && !elm.getData('checkstate')) {
							elm.set('checked', false);
						}
					});
				}
				
				if (wipemode) {
					t.all('input[type=checkbox]').each(function(elm) {
						elm.clearData('checkstate');
						elm.set('checked', false);
					});
				}
			});
		};
		var syncTargets = function(self, sElms) {
			sElms.each(function(elm){
				var checkboxes = elm.all('input[type=checkbox]');
				checkboxes.each(function(el){
					var isChecked = self.get('checked');
					el.set('checked',isChecked);
					el.setData('checkstate',isChecked);
					self.setData('checkstate',isChecked);
					var stopit;
				});
			});	
			
		};
		var init = function(g) {
			var version = g.getAttribute('data-toggle') ? 'data' : 'classic';
			// TODO classic version aufloesen
			if(version=='classic'){
				var mode = g.hasClass('js_toggleMute') ? 'mute' : 'hide', 
					triggerOn = g.all('input.js_toggleOn'), 
					triggerOff = g.all('input.js_toggleOff'), 
					target = g.one('.js_toggleGroupElement');
					
				if (triggerOn.size() > 0 || triggerOff.size() > 0) {
					var type = triggerOn.item(0).get('type') || triggerOff.item(0).get('type');
	
					triggerOn.each(function(elm, idx) {
						if (elm.get('checked')) {
							showTarget(target, mode);
						}
	
					});
					triggerOff.each(function(elm, idx) {
						if (elm.get('checked')) {
							hideTarget(target, mode);
						}
					});
	
					triggerOn.on('click', function(e) {
						if (e.currentTarget.get('checked')) {
							showTarget(target, mode);
						} else {
							hideTarget(target, mode);
						}
					});
					triggerOff.on('click', function(e) {
						if (e.currentTarget.get('checked')) {
							hideTarget(target, mode);
						} else {
							showTarget(target, mode);
						}
					});
				}
			}
			else if(version=='data') {
				var triggers = g.all('.js_toggleTrigger');
				triggers.each(function(elm,idx,arr) {
					var wipemode = elm.getAttribute('data-toggletargetWipe') || elm.ancestor().getAttribute('data-toggletargetWipe'),
						elementsOnIDs = elm.getAttribute('data-toggletargetOn') || elm.ancestor().getAttribute('data-toggletargetOn'),
						elementsOffIDs = elm.getAttribute('data-toggletargetOff') || elm.ancestor().getAttribute('data-toggletargetOff'),
						tOn = g.all(elementsOnIDs), 
						tOff = g.all(elementsOffIDs),
						labelelm = elm.next('label');
					
					if (elm.get('checked')) {
						showTargets(tOn);
						hideTargets(tOff);
						labelelm.addClass('active');
					}
						
					elm.on('click', function(e){
						if (e.currentTarget.get('checked')) {
							showTargets(tOn);
							hideTargets(tOff, wipemode);
							if(labelelm) {
								labelelm.addClass('active');
							}
						} else {
							showTargets(tOff);
							hideTargets(tOn, wipemode);
							if(labelelm) {
								labelelm.removeClass('active');
							}
						}
					});
						
					
					
				});
				
				
				var triggers = g.all('.js_syncTrigger');
				triggers.each(function(elm,idx,arr) {
					var synctargetIDs = elm.getAttribute('data-togglesync') || elm.ancestor().getAttribute('data-togglesync'),
					sElms = g.all(synctargetIDs);

					if (elm.get('checked')) {
						syncTargets(elm, sElms);
					}
					
					elm.on('click',function(e){
						syncTargets(e.currentTarget, sElms);
					});
				});
			}
		};

		return {
			initialize : function() {
				var groups = Y.all('.js_toggleGroup');
				if (groups.size() > 0) {
					groups.each(function(group, idx) {
						init(group);
					});
				}
			}
		};
	}();

	YUI.SIM.ChangeUiController = function() {
		var eventChangeUi = function(e) {
			var val = Y.one(e.target).get('value'); // checkbox-value
			changeUi(val);
		}, show = function(groups) {
			groups.setStyle('display', '').removeClass('hidden');
		}, hide = function(groups) {
			groups.setStyle('display', 'none');
		}, slideDown = function(groups) {

		}, slideUp = function(groups) {

		}, changeUi = function(val) {
			var triggerElem = '.js_from_' + val;

			var groups = Y.all(triggerElem + '_hide');
			if (groups.size() > 0) {
				hide(groups);
			}

			var groups = Y.all(triggerElem + '_show');
			if (groups.size() > 0) {
				show(groups);
			}

			var groups = Y.all(triggerElem + '_slideDown');
			if (groups.size() > 0) {
				slideDown(groups);
			}

			var groups = Y.all(triggerElem + '_slideUp');
			if (groups.size() > 0) {
				slideUp(groups);
			}
		}, initUi = function() {
			var ts = Y.all('.js_change_ui');
			if (ts.size() > 0) {
				ts.each(function(t) {
					if (t.get('checked')) {

						// var val = t._node.defaultValue; // checkbox-value
						var val = Y.one(t).get('value');
						changeUi(val);
					}
				});
			}
		}, registerEvents = function() {
			YUI.SIM.Nodes.Body.delegate('click', (function(e) {
				eventChangeUi(e);
			}), '.js_change_ui');
		};
		return {
			initialize : function() {
				registerEvents();
				initUi();
			}
		};
	}();

	YUI.SIM.OptionBoxController = function() {

		return {
			initialize : function() {
//				// tariffOption only
//				Y.delegate("click", (function(e) {
//					e.preventDefault();
//					var editable = this.hasClass("js_editable");
//					if (this.hasClass('disabled')) {
//						this.toggleClass('disabledInfo');
//						return;
//					}
//					if (!editable) {
//						return;
//					}
//					var button = this.one('input[type="submit"]'), render = false;
//					if (button) {
//						render = YUI.SIM.UiHelpers.getPrefixedClass('js_jsfrender_', button.get('className'));
//						YUI.SIM.JsfFacade.submitAjaxButton(e, button, render);
//					}
//				}), '.js_tariffOptionWrapper', '.js_optionBox');
//
//				// tariffOption as list only
//				Y.delegate("click", (function(e) {
//					var check = this.one('input[type="checkbox"]');
//					if (check) {
//						var editable = this.hasClass("js_editable");
//						if (!editable) {
//							return;
//						}
//						var checknode = Y.Node.getDOMNode(check), targetnode = e.target.get('nodeName').toLowerCase(), render = false;
//						if (e.target.ancestor('label') || targetnode == 'label') {
//							return true;
//						} else {
//							if (targetnode != 'input') {
//								checknode.checked = checknode.checked ? false : true;
//							}
//							render = YUI.SIM.UiHelpers.getPrefixedClass('js_jsfrender_', check.get('className'));
//							YUI.SIM.JsfFacade.submitAjaxCheckbox(e, check, render);
//						}
//					}
//				}), '.js_tariffOptionWrapper', '.js_optionList');

				// tariffOption + handybundle
				Y.delegate("mouseenter", (function(e) {
					this.addClass('over');
				}), '.js_optionBoxWrapper', '.js_optionBox');

				Y.delegate("mouseleave", (function(e) {
					this.removeClass('over');
					if (this.hasClass('disabled')) {
						this.removeClass('disabledInfo');
					}
				}), '.js_optionBoxWrapper', '.js_optionBox');
			}
		};
	}();
	
	// domready will fire after dom is ready, but before window.load event
	Y.on("domready", (function() {
		// console.log('on dom ready');
		
		YUI.SIM.InterstitialController.initialize();
		/*
		 * if( Y.one('.js_handyoption') ){
		 * YUI.SIM.HandyoptionController.initialize(); }
		 */
		YUI.SIM.TagEmbed();
		YUI.SIM.TagSlideShow.initialize();

		YUI.SIM.NboTeaserController.initialize();
		YUI.SIM.ChangeUiController.initialize();

		YUI.SIM.CarouselController.initialize();
		
		YUI.SIM.SelfContainedDaysCounterController.initialize();

		Y.all('.js_goback').on('click', function(e) {
			e.preventDefault();
			window.history.back();
		});
		// socialbar
		YUI.SIM.RecommendController.initialize();
		
		// videoplayer
		if (Y.one('.js_videoplayer')) {
			YUI.SIM.VideoController.loadScript(function() {
				if (Y.one('.js_videoplayer')) {
					YUI.SIM.VideoController.initialize();
				}
			});
		}

		if (Y.UA.mobile) {
			// console.log('you are mobile');
			Y.all('.infoIcon, .infoIconGeneral').on("touchstart", (function(e) {
				e.halt();
				var infoBubble = e.currentTarget;
				var layer = infoBubble.one('.infoBubble');
				this.removeClass('touched'); // this = alle auf der seite
				if (layer && (layer.getStyle('opacity') == 0)) {
					infoBubble.addClass('touched');
				} else {
					infoBubble.removeClass('touched');// wieder schließen beim
					// 2. touch
				}
			}));

			/**
			 * SIMWSN-1271 Weiter-Buttons für iOS < 3
			 */
			if (window.Modernizr.ioslt4) {
				var iconButtons = Y.all('span.buttonWrapper:not(.textButtonWrapper) input[type=submit]');
				iconButtons.each(function(elm) {
					elm.set('value', elm.get('value') + "   ");
				});
			}
		}

		// Preview Inputs (see below for delegate events)
		var previewElms = Y.all('.js_inputPreview, .js_inputPreviewWrapper .mega'); // extra
		// safety
		// for
		// iOS
		// 3.2.2
		if (previewElms.size() > 0) {
			if (Y.UA.mobile) {// iOS & android
				previewElms.removeAttribute('maxlength');
				for (elm in previewElms) {
					if (previewElms.hasOwnProperty(elm)) {
						if (elm.getAttribute && elm.getAttribute('title')) {
							elm.setAttribute('value', elm.getAttribute('title'));
						}
					}
				}
			}
		}

		YUI.SIM.OverlayController.initialize();
		
		YUI.SIM.ComponentManager.onContentReady();
	}), Y);
	// end of domready block
	
	
	// window.load will fire after domready, when all images and other resources have been fetched
	Y.on("load", (function() {
		// console.log('on window load');
		
		YUI.SIM.Tracking.initialize();
		
		
		
	}), window, Y);
	// end of window.load block

	
	YUI.SIM.SwfController.initialize();

	YUI.SIM.NavigationController.initialize();

	YUI.SIM.Behaviour.initialize();

	// Tarifoptionwähler + handyliste
	YUI.SIM.OptionBoxController.initialize();

	// Preview Inputs
	Y.delegate("focus", (function(e) {
		var elm = e.currentTarget, def = elm.get('placeholder') || elm.get('title');
		if (def.toString() == elm.get('value').toString()) {
			elm.set('value', '');
			elm.removeClass('preview');
		}
	}), YUI.SIM.Nodes.Body, '.js_inputPreview, .js_inputPreviewWrapper .mega');
	Y.delegate("blur", (function(e) {
		var elm = e.currentTarget, def = elm.get('placeholder') || elm.get('title');
		if ('' == elm.get('value')) {
			elm.addClass('preview');
			elm.set('value', def);
		}
	}), YUI.SIM.Nodes.Body, '.js_inputPreview, .js_inputPreviewWrapper .mega');

	// FAQ Topic Selector
	Y.delegate("click", (function(e) {
		e.preventDefault();
		var node = e.currentTarget;
		if (node) {
			YUI.SIM.FaqController.switchSearchSelector(node);
		}
	}), YUI.SIM.Nodes.Body, '.js_faqTopicSelect');

	// formActionBox
	Y.delegate("click", (function(e) {
		var node = e.currentTarget.ancestor('.js_formActionBox');
		var newAction = node.one('a.js_formAction').get('href');
		var form = e.currentTarget.ancestor('form');
		if (newAction) {
			form.set('action', newAction);
		}
	}), YUI.SIM.Nodes.Body, '.js_formActionBox div.hd');

	YUI.SIM.ToggleboxController.initialize();

	// ExpandableArea
	// TODO: Maybe move to a controller
	Y.delegate("click", (function(e) {

		var node = e.currentTarget, hash = node.get('hash');
		if (hash) {
			if (!Y.one(hash)) {
				return true;
			}
			e.preventDefault();
			// internal link? open expandable area surrounding linktarget
			var area = Y.one(hash) ? Y.one(hash).ancestor('.js_expandableArea') : false;
		} else {
			var area = node.ancestor('.js_expandableArea');
			e.preventDefault();
		}
		if (!area) {
			return;
		}
		var render = false;

		if (hash) {
			area.addClass('open');
		} else {
			area.toggleClass('open');
		}

		// this sets the open class
		Y.fire('expandable:toggle', area);
		
		var expanding = area.hasClass('open');

		var button = area.hasClass('open') ? area.one('.showCollapsed input[type="submit"]') : area.one('.showExpanded input[type="submit"]');

		if (button) {
			if (expanding) {
				area.addClass("loading");
			}
			render = YUI.SIM.UiHelpers.getPrefixedClass('js_jsfrender_', button.get('className'));
			var onevent = function(e) {
				if ((e.status=='complete' || e.status=='error') && expanding) {
					area.removeClass("loading"); 
				}
			}
			YUI.SIM.JsfFacade.submitAjaxButton(e, button, render,onevent);
		}
	}), YUI.SIM.Nodes.Body, '.js_expandableAreaTrigger');

	// PopupLink
	Y.delegate("click", (function(e) {
		YUI.SIM.PopupController.openPopup(e, e.currentTarget);
	}), YUI.SIM.Nodes.Body, '.popup, .popupWide'); // Bound to without js_
	// prefix because of RedDot
	// directive

	// MsisdnNumberselection
	// TODO: Maybe we want a wrapping element here with a class that listens to
	// all events and searchs for its children
	Y.delegate("click", YUI.SIM.MsisdnRandomController.prev, YUI.SIM.Nodes.Body, '.chooseMsisdn .js_previousMsisdn');
	Y.delegate("click", YUI.SIM.MsisdnRandomController.next, YUI.SIM.Nodes.Body, '.chooseMsisdn .js_nextMsisdn');
	Y.delegate("click", YUI.SIM.MsisdnRandomController.selectPage, YUI.SIM.Nodes.Body, '.pagerMsisdn .pager input');

	YUI.SIM.ToggleGroupController.initialize();

	// YUI.SIM.TafController.initializeSMStaf();

	YUI.SIM.TopupController.initialize();

	YUI.SIM.FormController.initialize();
	// YUI.SIM.FormFilterController.initialize();

	YUI.SIM.PasswordController.initialize();

	// }), Y);

	YUI.SIM.TeaserToggleController.initialize();

	YUI.SIM.SlideshowController.initialize();

});




