﻿/*
 * LETZTE AENDERUNGEN:
 * 		2010-11-09 16:04	In der Methode createLayerOnElement fuer den Fall dass die Option useWindowOn=true ist, wurde das
 * 							title-Attribut per escape-Befehl fuer die URL vorbereitet, dies kann aber mit UTF-8 und Umlauten
 * 							nicht besonders gut umgehen, daher wurde dies auf encodeURI umgestellt - aber nicht fuer den
 * 							Link selbst, da dieser sonst zerstoert wird (hans-peter.beck@eventim.de).
 * 
 * 		2010-08-11 13:45	In der Methode createLayer fuer den Modal-Layer (Hintergrund) die Hoehenberechnung angepasst,
 * 							um Fehler in der Darstellung zu vermeiden, wenn das Dokument nicht mind. so hoch wie das Fenster
 * 							ist (hans-peter.beck@eventim.de).
 * 
 *		2009-10-23 12:00	In den Methoden openLayer und closeLayer statt wie bisher eine Style-Angabe zum Verstecken der 
 *							SELECT-Elemente nun einen jQuery-Aufruf eingefuegt, der statt display:none nun visibility:hidden
 *							setzt, um einen Darstellungfehler im IE6 zu vermeiden (hans-peter.beck@eventim.de)
 *
 *		2009-08-12 17:30	Fuer den IE6-8 das Hintergrund-iFrame angepasst. Wurde in der Site document.domain geaendert, dann
 *							war der Inhalt des iFrames nich auf der gleichen Domain. Und da das iFrame bisher direkt per write()
 *							HTML-Code bekam ergab die nicht gleiche Domain einen Sandbox-Security-Fehler. Nun Wird das iFrame
 *							nur noch als SELECT-Blocker unsichtbar gesetzt und wie im Firefox davor dann der klickbare
 *							Hintergrundlayer gesetzt. (hans-peter.beck@eventim.de)
 * 		?					Erstellt (hans-peter.beck@eventim.de)
 *
 * Copyright 2008-2009 by CTS Eventim AG.
 */
 
/** Namespace sichern */
var eve = eve || {};

/** 
 * Erstellt ein Layerpopup mit einem iFrame.
 *
 * Wird dieser Klasse ein DOM-Element uebergeben, werden die Optionen aus dem rel-Attribut
 * und das anzuzeigende iFrame aus dem href-Attribut automatisch ermittelt.
 *
 * @class	eve.Popuplayer
 * @constructor
 * @param	{mixed}		options					Optionshash oder DOM-Element
 * @param	{string}	options.titleText		Title of layer as text
 * @param	{string}	options.titleCssCls		CSS-class for head-element, e.g. for background-images 
 * @param	{string}	options.titleImg		Path for Headline-Image
 * @param	{boolean}	options.constrain		False to disable constrain to viewport (defaults to true)
 * @param	{integer}	options.height			Inner height of iframe (defaults to 400)
 * @param	{integer}	options.width			Inner width of iframe (defaults to 500)
 * @param	{boolean}	options.draggable		True to allow the window to be dragged by the header bar, false to disable dragging (defaults to true). 
 * @param	{boolean}	options.modal			True to make the window modal and mask everything behind it when displayed(defaults to true).
 * @param	{string}	options.iframeSrc		Required: Source of the iframe.
 * @param	{boolean}	options.noScroll		Optional: If true, no scrollbar in iframe (defaults false)
 * @param	{string}	options.useWindowOn		Optional: If set to a special modi, the popup-layer will be created in a real window. Special modi are "all", "mozilla", "msie" (can be combined comma-seperated).
 * @param	{boolean}	options.autoResize		NOT DONE YET! Optional: If true, the Layer will be resized to the iframe-body if it will be resized (Default false).
 */
eve.Popuplayer = function(options) {
	
	/** Sicherstellen, dass das options-Objekt existiert */
	var options = options || {};
	
	/**
	 * Ist options ein DOM-Element, Optionen daraus ermitteln.
	 */
	if ((options.nodeName || false)) options = this.serializeElement(options);
	
	/**
	 * Element auf dem die Funktionalitaet erstellt werden soll.
	 */
	this.el = options.el || false;
	
	/**
	 * Wenn true, wird der Layer immer in der horizontalen und vertikalen Mitte der Seite
	 * angezeigt.
	 * @type	{boolean}
	 */
	this.constrain = (typeof options.constrain == 'boolean') ? options.constrain : true;
	
	/**
	 * Title of layer as text
	 * @type	{string}
	 */
	this.titleText = options.titleText || false;
	
	/**
	 * CSS-class for head-element, e.g. for background-images 
	 * @type	{string}
	 */
	this.titleCssCls = options.titleCssCls || false;
	
	/**
	 * True to allow the window to be dragged by the header bar.
	 * @type	{boolean}
	 */
	this.draggable = (typeof options.draggable == 'boolean') ? options.draggable : true;
	
	/**
	 * True to make the window modal and mask everything behind it when displayed.
	 * @type	{boolean}
	 */
	this.modal = (typeof options.modal == 'boolean') ? options.modal : true;
	
	/**
	 * Inner height of iframe
	 * @type	{integer}
	 */
	this.height = options.height || 400;
	
	/**
	 * Inner width of iframe
	 * @type	{integer}
	 */
	this.width = options.width || 500;
	
	/**
	 * Inner width of iframe
	 * @type	{integer}
	 */
	this.iframeSrc = options.iframeSrc || false;
	
	/**
	 * Layer-Autoresize on iframes body resize
	 * @type	{integer}
	 */
	this.autoResize = options.autoResize || false;
	
	/**
	 * Path for Headline-Image
	 * @type	{string}
	 */
	this.titleImg = options.titleImg || false;
	
	/**
	 * No Scrollbars?
	 * @type	{boolean}
	 */
	this.noScroll = options.noScroll || false;
	
	/**
	 * Used Elements in actuall object.
	 * @type	{object}
	 */
	this.usedEl = { body : jQuery('body').get(0) || null };
	
	/**
	 * If set to a special modi, the popup-layer will be created in a real window. Special modi are "all", "ff", "msie" (can be combined comma-seperated).
	 * @type	{array}
	 */
	this.useWindowOn = options.useWindowOn || false;
	
	/** Fehler? Wenn ja, abbrechen! */
	if (!this.el && !this.iframeSrc) return;
	
	/** Wenn nicht, dann initialisieren ... */
	this.createLayerOnElement();
};

eve.Popuplayer.prototype = {
	
	createLayerOnElement : function() {
		
		/** Aktuelles Objekt dem DOM-Element als parent mitteilen */
		this.el.parent = this;
		
		/**
		 * Wenn es eine Einschraenkung gibt, damit sich in einem bestimmten Fall ein Fenster oeffnen
		 * soll, dann setze den entsprechenden Event zum Oeffnen eines Fensters, statt eines Layers.
		 */
		if (this.useWindowOn) {
		
			var tmpOptions = this.useWindowOn.split(' ').join('').split(',');
			
			for (var i = 0; i < tmpOptions.length; i++) {
				
				var tmpOption = (tmpOptions[i] || '').toLowerCase();
				
				if ((jQuery.browser[tmpOption] || false) || tmpOption == 'all') {
					
					jQuery(this.el).removeClass('popuplayer');
					jQuery(this.el).addClass('popupwindow');
					
					this.el.setAttribute('rel', 'windowNoStatus');
					
					this.el.href = eveJsUrl
								 + '&doc=popup/popupLayerAlternative'
								 + '&title=' + encodeURI(this.titleText)
								 + '&height=' + this.height
								 + '&width=' + this.width
								 + '&link=' + escape(this.iframeSrc);
					
					
					jQuery(this.el).popupwindow(profiles);
					
					return;
				}
			}
		}
		
		jQuery(this.el).click(function() {
			
			this.parent.openLayer();
			
			return false;
		});
	},
	
	/**
	 * Liest aus einem DOM-Element (Linktag) ueber rel-, title- und href-Attribute Optionen
	 * aus und liefert diese als Object zurueck.
	 *
	 * @member	eve.Popuplayer
	 * @param	{element}	el				DOM-Element (Linktag)
	 * @return	Liefert ein Konfigurations-Objekt zurueck.
	 * @type	{object}
	 */
	serializeElement : function(el) {
		
		var JSONString = el.getAttribute('rel') || false;
		
		var tmpOptions = {};
		
		if (JSONString) {
			
			// Sicherstellen, dass keine Zeilenumbrueche vorhanden sind ...
			JSONString = unescape(escape(JSONString).replace(new RegExp("\%0D", "gi"), "").replace(new RegExp("\%0A", "gi"), ""));
			
			// Im eval darf nich tmpOptions stehen, sondern erstmal eine leere Variable,
			// da sonst der Packer durcheinander kommt.
			eval("var tmpNewOptions = " + JSONString + ";");
			
			tmpOptions = tmpNewOptions;
		};
		
		/** Weitere Optionen aus den anderen Attributen auslesen. */
		tmpOptions.iframeSrc = tmpOptions.iframeSrc || (el.getAttribute('href') || false);
		tmpOptions.titleText = tmpOptions.titleText || (el.getAttribute('title') || el.innerHTML);
		tmpOptions.el = el; 
		
		return tmpOptions;
	},
	
	/**
	 * Erstellt ein neues Element und fuegt dieses einem anderen hinzu.
	 *
	 * @member	eve.Popuplayer
	 * @param	{object}	options				optionshash:
	 * @param	{string}	options.nodeName	Name of node to create, like 'div' (defaults to div)
	 * @param	{element}	options.to			Optional: Element to append the new node
	 * @param	{element}	options.cls		Optional: CSS-class for the new element
	 * @param	{element}	options.id			Optional: ID of the element
	 * @param	{element}	options.text		If this is set, a textnode will be created
	 * @return	returns the new element
	 * @type	{element}
	 */
	addDom : function(options) {

		
		var options = options || {};
		
		/** Create new element */
		var newEl = ((options.text || null) == null) ? document.createElement(options.nodeName || 'div') : document.createTextNode(options.text) ;
		
		/** Adding CSS-class? */
		if ((options.cls || null) != null) newEl.className = options.cls;
		
		/** Adding ID? */
		if ((options.id || null) != null) newEl.setAttribute('id', options.id);
		
		/** Add the new element to an given element? */
		if ((options.to || null) != null) options.to.appendChild(newEl);
		
		return newEl;
	},
	
	/**
	 * Undocumented by now.
	 *
	 * @member	eve.Popuplayer
	 */
	openLayer : function() {
		
		this.createLayer();
		
		var scrollbars = ((!this.noScroll) ? '' : 'scrolling="no"' );
		
		this.iFrameCtr = (this.iFrameCtr || 0) + 1;
		
		var tmpId = eveJs.getElementId(this.usedEl.contentElReal) + 'popupLayerIframe' + this.iFrameCtr;
		
		this.usedEl.contentElReal.innerHTML = '<iframe onload="javascript:this.tmpLoad();" onunload="javascript:this.tmpUnload();" name="'+tmpId+'" id="'+tmpId+'" src="' + this.el.getAttribute('href') + '" width="' + this.width + '" height="' + this.height + '" border="0" frameborder="0" framespacing="0" ' + scrollbars + '></iframe>';
		
		jQuery('select').css({ 'visibility':'hidden' });
		
		jQuery(this.usedEl.modal).show();
		
		jQuery(this.usedEl.el).show();
		
		if((this.usedEl.modal.ieFrame || false)) jQuery(this.usedEl.modal.ieFrame).show();
		
		// iFrame Element merken fuer autoResize
		this.iFrameId = tmpId;
		
		var tmpFrame = document.getElementById(tmpId);
		
		tmpFrame.tmpLoad = function() {
			
			this.isLoaded = true;
			
		}.scope(tmpFrame);
		
		tmpFrame.tmpUnload = function() {
			
			this.isLoaded = false;
			
		}.scope(tmpFrame);
		
		tmpFrame.isLoaded = false;
		
		/** Initial positionieren ... */
		this.centerLayer();
		
		/** Funktion vorbereiten zum repositionieren, wenn gescrollt wird. */
		this.centerEver = function() {
			
			if ((this.autoResize || false)) this.autoResizeLayer();
			
			this.centerLayer(true);
			
			this.centerEver();
			
		}.defer(100, this);
		
		/** Starten ... */
		this.centerEver();
	},
	
	/**
	 * Wenn der Inhalt des Layers, also des iFrames geladen wurde, dann auf dessen Window ein onResize
	 * Event legen, wenn this.autoResize aktiv ist.
	 *
	 * Solange der Layer offen ist, muss mit dem "neu Positionieren"-Intervall auch einfach der Inhalt
	 * des iFrames ueberprueft werden!
	 */
	autoResizeLayer : function() {
		
		this.iframeEl = document.getElementById(this.iFrameId) || false;
		
		// Wenn es kein iFrame gibt, dann Ende
		if (!(this.iframeEl || false)) return;
		
		// Wenn der Inhalt des iFrames noch nicht geladen ist, dann auch Ende
		if (!this.iframeEl.isLoaded) return;
		
		/**
		 * Das iFrame-Element liegt bereits in this.iframeEl vor, da das iFrame auch neu geladen werden kann
		 * muss die Ebene darunter immer frisch ermittelt werden.
		 */
		var iFrameWindow = parent[this.iframeEl.name] || false;
		
		// Gibt es aktuell kein Fenster, dann Ende um Fehler zu vermeiden!
		if(!iFrameWindow) return;
		
		// Wenn es keinen Body gibt, dann ist auch Ende
		try {
			
			if(!(iFrameWindow.document.body || false)) return;
		
		} catch(e) {
			
			// Fehler, wahrscheinlich ist nun ein HTTPS-Dokument geladen worden, dann
			// einfach Ende ...
			return;
		}
		
		if (!jQuery.browser.msie && (iFrameWindow.document.baseURI || 'about:blank') == 'about:blank') return;
		
		/** Original-Werte merken ... */
		this.iframeOrigSettings = this.iframeOrigSettings || {
		
			height    : this.iframeEl.height,
			scrolling : this.iframeEl.scrolling,
			width     : jQuery(iFrameWindow.document.body).width()
		};
		
		// Die Hoehe aus dem Fenster ermitteln (dort muss ebenfalls die eveJs vorhanden sein ...) ...
		iFrameWindow.Eve = iFrameWindow.Eve || Eve;
		iFrameWindow.eveJs = iFrameWindow.eveJs || eveJs;
		iFrameWindow.jQuery = iFrameWindow.jQuery || jQuery;
		
		var actHeight = iFrameWindow.eveJs.getPageHeight() || false;
		
		// Wenns keine Hoehe gibt, dann Ende ...
		if (!actHeight) return;
					
		var tmpMaxHeight = eveJs.getInnerWindowSize().height - 100;
		
		if(this.iframeEl.height != actHeight) {
			
			if(tmpMaxHeight < actHeight) {
				
				actHeight = tmpMaxHeight;
				
				this.iframeEl.scrolling = "auto";
				
				iFrameWindow.document.body.style.width = this.iframeOrigSettings.width + 'px';
				
			} else {
				
				this.iframeEl.scrolling = ((this.noScroll) ? 'no' : this.iframeOrigSettings.scrolling || '' );
				iFrameWindow.document.body.style.width = '';
			}
						
			this.iframeEl.height = actHeight;
		}
	},
	
	/**
	 * Undocumented by now.
	 *
	 * @member	eve.Popuplayer
	 */
	closeLayer : function() {
		
		this.centerEver = function() {};
		
		jQuery(this.usedEl.el).remove();
		
		jQuery(this.usedEl.modal).remove();
		
		if((this.usedEl.modal.ieFrame || false)) jQuery(this.usedEl.modal.ieFrame).remove();
		
		jQuery('select').css({ 'visibility':'visible' });
		
		//jQuery(document.body).append('<style type="text/css"> select { visibility:visible; } </style>');
		
		//this.usedEl.contentElReal.innerHTML = '<style type="text/css"> select { visibility:visible; } </style>';
	},
	
	createLayer : function() {
		
		/** Shortcuts */
		var ue = this.usedEl;
		var ad = this.addDom;
		
		if (this.modal) {
			
			// Wenn IE, dann noch zusaetzlich ein iFrame als Layer hinter den klickbaren Layer legen,
			// damit SELECTs und Co nicht durchscheinen.
			if (jQuery.browser.msie) {
				
				var tmpId = eveJs.getElementId(this.el) + 'popupLayer';
				
				// Wenn src auf den in der Variablen eveJsIframeBlank hinterlegten Wert gesetzt wird, gibt es keine "Unsichere Objekte" Warnung im IE6/7/8
				jQuery(document.body).append('<iframe src="'+eveJsIframeBlank+'" id="'+tmpId+'" name="'+tmpId+'" class="eplModal" style="height:'+document.body.scrollHeight+'px; width:100%;" framespacing="0" frameborder="0" border"0"></iframe>');
				
				var tmpIframe = jQuery('#'+tmpId).get(0);
				
			} else {
				
				var tmpIframe = false;
			}
				
			ue.modal = ad({ to : ue.body, cls : 'eplModal' });
			
			// Ist die Hoehe des Bodys kleiner als die Fensterhoehe, dann nimm fuer den Modal-
			// Layer die Hoehe des Fensters, ansonsten wie gehabt die Hoehe des Dokumentes.
			if(document.body.scrollHeight < jQuery(window).height()) {
				
				var tmpModalHeight = jQuery(window).height();
				
			} else {
				
				var tmpModalHeight = document.body.scrollHeight;
			}
			
			ue.modal.style.height = tmpModalHeight + 'px'; //document.body.scrollHeight+'px';
			ue.modal.style.background = '#002C52 none';
			ue.modal.clickElement = ue.modal;
			ue.modal.ieFrame = tmpIframe;
			
			jQuery(ue.modal.clickElement).click(function() {
					
				this.closeLayer();
					
			}.scope(this));
		}
		
		/** Basis-Container erstellen */
		ue.el                      = ad({ to : ue.body, cls : 'epl' });
		ue.innerEl                 = ad({ to : ue.el, cls : 'eplInner' });
		ue.rightShadow             = ad({ to : ue.innerEl, cls : 'eplRightShadow alphaPng' });					
		ue.rightTopShadowCorner    = ad({ to : ue.el, cls : 'eplRightTopShadowCorner alphaPng' });
		ue.shadowFooter            = ad({ to : ue.el, cls : 'eplShadowFooter' });
		ue.leftBottomShadowCorner  = ad({ to : ue.shadowFooter, cls : 'eplLeftBottomShadowCorner alphaPng' });
		ue.rightBottomShadow       = ad({ to : ue.shadowFooter, cls : 'eplBottomShadow alphaPng' });
		ue.rightBottomShadowBack   = ad({ to : ue.rightBottomShadow, cls : 'eplBottomShadowBack alphaPng' });
		ue.rightBottomShadowCorner = ad({ to : ue.shadowFooter, cls : 'eplRightBottomShadowCorner alphaPng' });
		
		/** Header erstellen */
		ue.headerEl                = ad({ to : ue.innerEl, cls : 'eplHeader alphaPng' });
		ue.headerRightEnd          = ad({ to : ue.headerEl, cls : 'eplHeaderRightEnd alphaPng' });
		ue.headerBack              = ad({ to : ue.headerRightEnd, cls : 'eplHeaderBack' });
		ue.headerContent           = ad({ to : ue.headerBack, cls : 'eplHeaderContent' });
		
		if (this.titleCssCls) {
			
			jQuery(ue.headerContent).addClass(this.titleCssCls);
			
		} else if (this.titleImg) {
			
			ue.headerContentTitleImage = ad({ nodeName : 'img', to : ue.headerContent, cls : 'eplHeaderImages' });
			ue.headerContentTitleImage.src = this.titleImg;
			
		} else if (this.titleText) {
			
			ue.headerContentTitle = ad({ to : ue.headerContent, cls : 'eplHeaderText' });
			jQuery(ue.headerContentTitle).html(this.titleText);
		}
		
		ue.headerCloseBtnContainer  = ad({ to : ue.headerBack, cls : 'eplHeaderCloseBtn' });
		
		/** Content-Element erstellen */
		ue.contentEl               = ad({ to : ue.innerEl, cls : 'eplContent' });
		ue.contentElReal           = ad({ to : ue.contentEl, cls : 'eplRealContent' });
		ue.contentElFooter         = ad({ to : ue.contentEl, cls : 'eplContentFooter' });
		
		/** Schliessen-Links erstellen */
		ue.footerCloseBtn = this.createCloseLink(ue.contentElFooter);
		
		jQuery(ue.contentElFooter).append("<div class='clearFloat'></div>");
		
		ue.headerCloseBtn = this.createCloseLink(ue.headerCloseBtnContainer);
		
		ue.el.style.width = (this.width + 20) + 'px';
	},
	
	createCloseLink : function(to) {
		
		var tmpEl = document.createElement('a');
		var closeMsg = ((eveMessages || {}).PopupLayer || {}).closePopup || 'close';
		
		tmpEl.setAttribute('href', 'javascript:void(0);');
		tmpEl.setAttribute('title', ((this.titleText) ? this.titleText + " " : "" ) + closeMsg );
		
		tmpEl.innerHTML = closeMsg;
		tmpEl.parent    = this;
		
		jQuery(tmpEl).addClass('eplCloseLink');
		
		jQuery(tmpEl).click(function() {
				
				this.parent.closeLayer();
		});
		
		jQuery(to).append(tmpEl);
		
		return tmpEl;
	},
	
	/**
	 * Setzt den Layer in die Mitte des Viewports ...
	 *
	 * @member	eve.Popuplayer
	 */
	centerLayer : function(animated) {
		
		var animated = animated || false;
		
		/** Shortcuts */
		var el = this.usedEl.el;
		
		/** Positionieren */
		var actScroll = ((jQuery.browser.msie) ? jQuery('html,body').offset() : this.getScrollPosition());
		var actSize   = eveJs.getInnerWindowSize();
		
		var layerSize = { width : jQuery(el).width(), height : jQuery(el).height() };
		
		if ((actSize.height + actScroll.top) < (layerSize.height + actScroll.top)) {
		
			tmpTop = actScroll.top + 10;
		
		} else {
			
			tmpTop = (actScroll.top + ((actSize.height - layerSize.height) / 2));
		}
		
		if ((actSize.width + actScroll.left) < (layerSize.width + actScroll.left)) {
		
			tmpLeft = actScroll.left + 10;
		
		} else {
			
			tmpLeft = (actScroll.left + ((actSize.width - layerSize.width) / 2));
		}
		
		var actualLeft = ((tmpLeft > 5) ? tmpLeft : 5 );
		var actualTop  = ((tmpTop > 5) ? tmpTop : 5 );
		var aniCfg     = { isSet : false };
		
		if (actualLeft != (el.actualLeft || '')) {
			
			if (animated) {
				
				aniCfg.isSet = true;
				aniCfg['left'] = actualLeft;
				
			} else {
				el.style.left = actualLeft + 'px';
			}
		}
		
		if (actualTop != (el.actualTop || '')) {
			
			if (animated) {
				
				aniCfg.isSet = true;
				aniCfg['top'] = actualTop;
				
			} else {
				el.style.top  = actualTop + 'px';
			}
		}
		
		if (aniCfg.isSet) jQuery(el).stop().animate(aniCfg, 500);
		
		if ((aniCfg.left || false)) el.actualLeft = aniCfg.left;
		if ((aniCfg.top || false)) el.actualTop  = aniCfg.top;
	},
	
	/**
	 * Ermittelt die aktuelle Scrollposition des Dokumentes ...
	 *
	 * @member	eve.Popuplayer
	 */
	getScrollPosition : function() {
	
		return (typeof window.pageXOffset != 'undefined') ? { top : window.pageYOffset, left : window.pageXOffset } : { top : document.body.scrollTop, left : document.body.scrollLeft } ;
	}
};

/**
 * Diese Methode sucht nach Links mit der Klasse "popuplayer" und
 * belegt diese mit entsprechenden Events und der Klasse eve.Popuplayer.
 */
eve.Popuplayer.foundAndSet = function() {
	
	var links = jQuery('a.popuplayer').get() || false;
	
	if (!links) return;
		
	for (var i = 0; i < links.length; i++) new eve.Popuplayer(links[i]);
};

/** On document loaded, search for popuplayers */
jQuery(eve.Popuplayer.foundAndSet);
