/*--------------------------------------------------------------------
 * JQuery Plugin: "inlinepopup"
 * by:	Daniel Filzhut, daniel.filzhut@cgi.com
 *
 * Copyright (c) 2009 CGI Information Systems and Management Consultants Deutschland GmbH
 *
 * Description:   Adds a link to an inline popup to an element.
 * 				  Is able to load links using an AJAX call (same server) or an iFrame (external URL target).
 * 				  Additionally, inline DIV layers can be used as link target.
 *
 * Dependencies:  jQuery library (tested with 1.3.2)
 * 				  jqModal plugin (tested with r14)
 *
 * Version: 1.0.18      07.02.2011  - Fixed exception when checking name of cross-domain iframes.
 * Version: 1.0.17      19.01.2011  - Changed default background opacity to 20% black
 * Version: 1.0.16      09.12.2010  - Added workaround to add a way to keep control on HTTP STATUS 302 if needed
 * Version: 1.0.15		22.07.2010	- Added "close on ESC" event to iframe content
 * Version: 1.0.14		23.06.2010	- Added iframe print-ability when clicking popup's "print"-button.
 * Version: 1.0.13		08.06.2010	- Changed "isReloadIfIframeChanged" to "isRefreshIfIframeChanged".
 *                                    Added switch "reloadParams" to hand over some parameters being attached to the URL
 *                                    used with "isReloadWithoutParamsIfIframeChanged".
 * Version: 1.0.12		31.05.2010	- Added switch "isReloadWithoutParamsIfIframeChanged" to reload opener page
 * 									  without any given URL parameters in case user interacted within iframe
 * 									  (submitted form, clicked link).
 * Version: 1.0.11		28.05.2010	- Added switch "isReloadIfIframeChanged" to reload opener page in case user
 *                                    interacted within iframe (submitted form, clicked link).
 * Version: 1.0.10		06.05.2010	- Added support for fixed iframe widths/heights by using an injected CSS class.
 * Version: 1.0.9		27.10.2009	- Added removal of hidden Ajax/iFrame popup after closing it, to prevent it from
 * 									  possibly being printed when printing a page.
 * Version: 1.0.8		27.10.2009	- Added switch whether to refocus triggering element after closing popup.
 * Version: 1.0.7		22.10.2009	- Fixed FF2 issue of being not able to limit popup width to content size
 * 									  (AJAX, popup always consumed full screen width).
 * Version: 1.0.6		30.09.2009	- Added parameters iframeWidth/iframeHeight.
 * Version: 1.0.5		16.09.2009	- Parametrized the injection of CSS classes using option "classes".
 * Version: 1.0.4		15.09.2009	- Created plugin out of non-plugin implementation.
 * Version: 1.0.3		15.09.2009	- Added calculated, fixed height to content area
 * 									  to let the browser create scrollbars when size changes after popping up.
 * Version: 1.0.2		14.09.2009	- Avoided using .clone(true) method to get around JQuery/IE bug.
 * 									  Using internal "move" method instead.
 * Version: 1.0.1		11.09.2009	- Let the cloning process for DIV popups also include cloning event handlers.
 * Version: 1.0			10.09.2009	- Finalized as v1.0.
--------------------------------------------------------------------*/

(function($) {

	$.fn.inlinePopup = function(options) {

		var defaults = {
				isAjax : false,
				isIframe : false,
				isDiv : false,
				isOnLoad : false,
				targetUrl : "",
				isModal : false,
				isButtonBarTop : true,
				isButtonBarBottom : false,
				isPrintButtons : true,
				isRefocussing : true,
				isRefreshIfIframeChanged: false,
				isReloadWithoutParamsIfIframeChanged: false,
				reloadParams : "",
				classes : "",
				opacity : 20,
				maxSize : 0.9,
				iframeWidth : 99999,
				iframeHeight : 99999
		};

		// Set default options in case none given
		var options = $.extend({}, defaults, options);

		// CSS Classes used
		var idDiv = "popupLinkCSSDivPopup";
		var classPopupActive = "popupLinkActive";
		var classHasButtons = "popupLinkCSSDivPopupWithButtons";
		var classHead = "popupLinkCSSDivHeader";
		var classContent = "popupLinkCSSDivContent";
		var nameContentIframe = "popupLinkIframe";
		var classFoot = "popupLinkCSSDivFooter";
		var classOverlay = "popupLinkCSSDivOverlay";
		var classClose = "popupLinkCloseButton";
		var classDivLayer = "popupLinkDivLayer";

		// Selectors
		var selPop = '#' + idDiv;
		var selPopBtns = selPop + '.' + classHasButtons;
		var selPopHead = selPop + ' .' + classHead;
		var selPopFoot = selPop + ' .' + classFoot;
		var selPopCon = selPop + ' .' + classContent;
		var selPopConIframe = selPop + ' .' + classContent + ' iframe';
		var selPopDiv = selPopCon + ' .' + classDivLayer;
		var selInputFocus = selPop + ' a, ' + selPop + ' input';
		var selMatrix = 'div.divMatrix';

		return $(this).each(function() {

			var triggerElement = $(this);
			var iframeUrlChanged = false;

			// AJAX / IFrame popup
			if(options.isAjax || options.isIframe) {

				$(this).bind("click", function() {

					// Add popup DIV
					$(selPop).remove();
					$("body").append(popupCode($(this), options.isButtonBarTop, options.isButtonBarBottom));
					
					// Activate jqmodal
				    $(selPop).jqm({
				        
                        //Do AJAX manually to process manually the response, see "AJAX manually" comment below 
                        //ajax: (options.isAjax ? options.targetUrl : ""),

				    	trigger: false,
			            closeClass: classClose,
			            overlay: options.opacity,
			            overlayClass: classOverlay,
			            modal: options.isModal,
				    	onShow: function(hash) {

				    		// Mark that popup is open (for print-ability)
				    		$(selMatrix).addClass(classPopupActive);

				    		// Display data in case of iFrame popup
				    		if(options.isIframe) {
				    			$(selPopCon).append('<iframe name="' + nameContentIframe + '" src="' + options.targetUrl + '" frameborder="0" border="0" cellpadding="0" cellspacing="0" marginwidth="0" marginheight="0" leftmargin="0" topmargin="0" />');
				    			hash.w.show();
				    			var definedWidth = cssIframeWidth(options.classes);
				    			var definedHeight = cssIframeHeight(options.classes);
				    			if (definedWidth) {
				    				$(selPopCon + " iframe").css("width", definedWidth);
					    			$(selPopCon).css("width", $(selPopCon + " iframe").outerWidth());
					    			$(selPopCon).css("float", "right");
				    			} else {
					    			$(selPopCon).css("width", options.iframeWidth);
				    			}
				    			if (definedHeight) {
				    				$(selPopCon + " iframe").css("height", definedHeight);
					    			$(selPopCon).css("height", $(selPopCon + " iframe").outerHeight());
				    			} else {
					    			$(selPopCon).css("height", options.iframeHeight);
				    			}
						    	fitPopupOnScreen(options.maxSize);
				    			centerPopupByContent();

				    			// Capture on load event
				    			$(selPopCon + " iframe").bind("load", function() {

				    				// Focus iframe to make it printable with browser-internal print button
				    				parent[nameContentIframe].focus();

				    				// Monitor whether iframe SRC is changed by user
					    			$(selPopCon + " iframe").bind("load", function() {
					    				iframeUrlChanged = true;
					    			});

						    		// Bind ESC event to iframe content
					    			if ($.browser.msie) {
					    				$(selPopCon + " iframe")[0].contentWindow.attachEvent('onkeydown', closePopupOnEsc);
					    			} else {
					    				$(selPopCon + " iframe")[0].contentWindow.addEventListener('keydown', closePopupOnEsc, false);
					    			}					    			
					    			
				    			});
				    		}

				    		// Display loading indicator for AJAX popup and call url
				    		else if(options.isAjax){
				    			$('.' + classOverlay).append('<img src="/static/images/loading.gif" align="center" style="background-color:#fff;position:fixed;top:' + (windowHeight()/2) + 'px;left:' + ($(window).width()/2) + 'px;"/>');

                                //AJAX manually to keep control on the result
                                //-------------------------------------------
                                //==> When displaying page after HTTP STATUS 302, sometime, rather than displaying 
                                //==> the page into jQM, we want to redirect the browser to the 302 REDIRECT LOCATION
                                //==> *note : Will do that only if we detect special parameter into HTTP HEADER
                                //
                                // AJAX_STATUS   : if contain 302, indicate to redirect the page to AJAX_LOCATION
                                // AJAX_LOCATION : contain the URL to be use for the redirection
                                //
                                $.ajax({
                                    type: 'GET',
                                    cache: false,
                                    url: options.targetUrl,
                                    complete: function(request, status) {
                                        if (request.getResponseHeader('AJAX_STATUS') == "302") {
                                            window.location = request.getResponseHeader('AJAX_LOCATION');
                                        } else {
                                            $(selPopCon).html(request.responseText);
                                            jQMOnLoadAjaxIframe(hash);
                                        }
                                    }
				    			});
				    		}

				    		// Bind ESC event to window in case not modal
					    	if (!options.isModal) {
								$(document).bind("keydown", closePopupOnEsc);
					    	}
				    	},
				    	onLoad : jQMOnLoadAjaxIframe,
				    	onHide: function(hash) {
				    		
				    		hash.o.remove();
				    		hash.w.hide();
							$(selPop).remove();

					    	if (!options.isModal) {
								$(document).unbind("keydown", closePopupOnEsc);
					    	}

					    	// Focus triggering link after closing popup
					    	if (options.isRefocussing) {
					    		triggerElement.focus();
					    	}

				    		// Mark that popup is closed (for print-ability)
				    		$(selMatrix).removeClass(classPopupActive);

				    		// Refresh/reload opener page in case iframe page has been changed by user
				    		if (options.isIframe && options.isRefreshIfIframeChanged && iframeUrlChanged) {
					    		document.location.reload();
				    		} else if (options.isIframe && options.isReloadWithoutParamsIfIframeChanged && iframeUrlChanged) {
				    			var regex = /https?:\/\/[^?]*/;
				    			var result = regex.exec(document.location);
				    			if (result.length && options.reloadParams) {
					    			document.location.href = result[0] + "?" + options.reloadParams;
				    			} else if (result.length) {
				    				document.location.href = result[0];
				    			} else {
				    				document.location.reload();
				    			}
				    		}

				    	},
			            target: $(selPopCon)}
				    ).jqmShow();

				    // De-activate HREF function of link
				    return false;
				});

			}

			// DIV inline popup
			else if(options.isDiv) {
				$(this).bind("click", function() {

					// Add popup DIV
					$(selPop).remove();
					$("body").prepend(popupCode($(this), options.isButtonBarTop, options.isButtonBarBottom));
				    $(options.targetUrl).show();

				    // Move popup DOM node from current DOM position into popup DIV
					$(selPopCon).append($(options.targetUrl));

					// Activate jqmodal
				    $(selPop).jqm({
				    	trigger: false,
			            closeClass: classClose,
			            overlay: options.opacity,
			            overlayClass: classOverlay,
			            modal: options.isModal,
				    	onShow: function(hash) {

			    			// Mark that popup is open (for print-ability)
			    			$(selMatrix).addClass(classPopupActive);

				    		// Display DIV popup
				    		hash.w.show();
					    	fitPopupOnScreen(options.maxSize);
					    	centerPopupByContent();

				    		// Bind ESC event to window in case not modal
					    	if (!options.isModal) {
								$(document).bind("keydown", closePopupOnEsc);
					    	}

					    	// Focus first input element of layer
					    	if($(selInputFocus).length) {
					    		$(selInputFocus).get(0).focus();
					    	}

				    	},
				    	onHide: function(hash) {

				    		// Move popup DOM node out of generic popup DIV
			    			hash.o.remove();
			    			hash.w.hide();
			    			$(selPop).replaceWith($(options.targetUrl));
			    			$(options.targetUrl).hide();

					    	if (!options.isModal) {
								$(document).unbind("keydown", closePopupOnEsc);
					    	}

					    	// Focus triggering link after closing popup
					    	if (options.isRefocussing) {
					    		triggerElement.focus();
					    	}

				    		// Mark that popup is closed (for print-ability)
				    		$(selMatrix).removeClass(classPopupActive);

				    	}
				    });
				    $(selPop).jqmShow();

				    // De-activate HREF function of link
				    return false;
				});
			}

			// Trigger popup display if necessary
			if (options.isOnLoad) {
				$(this).trigger("click");
			}
			
			/**
			 * function called automatically when jQM AJAX is done 
			 * @param hash (see jQM documentation)
			 */
			function jQMOnLoadAjaxIframe(hash) {

                // Display AJAX popup
                $('.' + classOverlay).empty();

                // Fix for FF2, which is not able to limit the popup width to the contents size,
                // since the button bar always forces the full width of the popup.
                if ($.browser.mozilla && $.browser.version.substr(0,3) == "1.8") {
                    $(selPopHead).hide();
                    $(selPopFoot).hide();
                    hash.w.show();
                    $(selPopHead).css("width", $(selPopCon).innerWidth());
                    $(selPopFoot).css("width", $(selPopCon).innerWidth());
                    $(selPopHead).show();
                    $(selPopFoot).show();
                } else {
                    hash.w.show();
                }

                fitPopupOnScreen(options.maxSize);
                centerPopupByContent();

                // Focus first input element of layer
                if($(selInputFocus).length) {
                    $(selInputFocus).get(0).focus();
                }
            }

			/**
			 * Returns HTML code for popup.
			 *
			 * @return	string
			 */
			function popupCode(obj, top, bottom) {
				// Return code
				var buttonBar = '<a class="aLink iconCloseComprehensive ' + classClose + '" href="#">Fenster schliessen</a>'
					+ (options.isPrintButtons ? '<a class="aLink iconPrintComprehensive" href="#" onclick="'
					+ 'if($(\'' + selPopConIframe + '\').length) { parent.' + nameContentIframe + '.focus();parent.' + nameContentIframe + '.print();return false; } else { window.print();return false; }'
					+ '">Drucken</a>' : '');
				return '<div id="' + idDiv + '" class="' + (top || bottom ? classHasButtons : '') + ' ' + options.classes + '" style="display:none; overflow:hidden;">'
				+ (top ? '<div class="' + classHead + '">' + buttonBar + '</div>' : '')
				+ '<div class="' + classContent + '"></div>'
				+ (bottom ? '<div class="' + classFoot + '">' + buttonBar + '</div>' : '')
				+ '</div>';
			}

			/**
			 * Centers popup on canvas.
			 *
			 */
			function centerPopupByContent() {
				$(selPop).css("top", popupCenteredTop());
				$(selPop).css("left", popupCenteredLeft());
				if ($.browser.msie && $.browser.version.substr(0,1) == "6" ) {
		    		$(selPop).css("top", popupCenteredTop() + document.documentElement.scrollTop + "px");
				}
			}

			/**
			 * Returns necessary top value of popup to center it on canvas.
			 *
			 * @return	int
			 */
			function popupCenteredTop() {
				return (windowHeight()/2) - ($(selPop).outerHeight()/2);
			}

			/**
			 * Returns necessary left value of popup to center it on canvas.
			 *
			 * @return	int
			 */
			function popupCenteredLeft() {
				return ($(window).width()/2) - ($(selPop).outerWidth()/2);
			}

			/**
			 * Checks whether popup is to large for canvas and resizes it if necessary.
			 *
			 * @param	percentage		Value between 0-1, describes padding between canvas border and popup border.
			 *
			 */
			function fitPopupOnScreen(percentage) {
				// Fallback for browsers with different scrollbar-width calculation (IE6/FF2/Opera)
				var incScrollbars = (
						($.browser.msie && $.browser.version.substr(0,1) == "6")
						|| ($.browser.mozilla && $.browser.version.substr(0,3) == "1.8")
						|| ($.browser.opera)
					);
				if ($(selPopDiv).length && incScrollbars) {
					$(selPopCon).css("width", $(selPopDiv).outerWidth() + 17);
					if ($(selPopDiv).css("height") != "auto") {
						$(selPopCon).height(intValue($(selPopDiv).css("height")) + 20); // IE6 won't accept .height() for inner div
					}
				} else if ($(selPopCon).length && incScrollbars) {
					$(selPop).css("width", $(selPopCon).outerWidth() + 17);
				}
				// Adjust width to match content
				$(selPop).width($(selPopCon).outerWidth() + ($(selPop).outerWidth() - $(selPop).width()) - (incScrollbars ? 17 : 0));
				// Change width if wider than canvas
				if ($(selPop).outerWidth() >= $(window).width()) {
					$(selPop).width(($(window).width() - ($(selPop).outerWidth() - $(selPop).width())) * percentage);
					$(selPopCon).width($(selPop).width());
				}
				// Change height if higher than canvas
				if ($(selPop).outerHeight() >= windowHeight()) {
					$(selPopCon).height((windowHeight() - ($(selPop).outerHeight() - $(selPopCon).height())) * percentage);
				}
				// Make space for scrollbar if none left in popup
				if ($(selPopHead).length + $(selPopFoot).length == 0) {
					$(selPop).css("width", $(selPop).width() + 16);
				}
				// Set fixed height so that popup displays scrollbars when height changes later
				$(selPopCon).css("height", $(selPopCon).height());
				$(selPop).css("height", $(selPop).height());
			}

			/**
			 * Resized the popup to full canvas size.
			 *
			 * @param	percentage		Value between 0-1, describes padding between canvas border and popup border.
			 *
			 */
			function fullscreenPopup(percentage) {
				$(selPop).width(($(window).width() - ($(selPop).outerWidth() - $(selPop).width())) * percentage);
				$(selPopCon).height((windowHeight() - ($(selPop).outerHeight() - $(selPop).height() + $(selPopHead).outerHeight() + $(selPopFoot).outerHeight())) * percentage);
			}

			/**
			 * Event handler: Hides popup if ESC pressed.
			 *
			 */
			function closePopupOnEsc(e) {
				var kC  = (window.event) ? event.keyCode : e.keyCode;
				if (kC == 27) {
					$(selPop).jqmHide();
				}
			}

			/**
			 * Returns full canvas height of window.
			 *
			 * @return	int
			 */
			function windowHeight() {
				if ($.browser.opera && $.browser.version >= 9.50) {
					return window.innerHeight;
				}
				return $(window).height();
			}

			/**
			 * Parses integer value, returns 0 if NaN.
			 *
			 * @param	val		String
			 * @return	int
			 */
			function intValue(val) {
				return (isNaN(parseInt(val)) ? 0 : parseInt(val));
			}

			/**
			 * Returns CSS width of an iframe within an element having the given CSS classes.
			 *
			 * @param	val		String
			 * @return	int
			 */
			function cssIframeWidth(classes) {
				var defaultWidth= '';
				var definedWidth= '';
				$("body").append('<div class="widthTestElement" style="display:none"><iframe></iframe></div>');
				defaultWidth = intValue($('div.widthTestElement iframe').css("width"));
				$('div.widthTestElement').addClass(classes);
				definedWidth = intValue($('div.widthTestElement iframe').css("width"));
				$('div.widthTestElement').remove();
				return (definedWidth != defaultWidth ? definedWidth : 0);
			}

			/**
			 * Returns CSS height of an iframe within an element having the given CSS classes.
			 *
			 * @param	val		String
			 * @return	int
			 */
			function cssIframeHeight(classes) {
				var defaultHeight= '';
				var definedHeight= '';
				$("body").append('<div class="heightTestElement" style="display:none"><iframe></iframe></div>');
				defaultHeight = intValue($('div.heightTestElement iframe').css("height"));
				$('div.heightTestElement').addClass(classes);
				definedHeight = intValue($('div.heightTestElement iframe').css("height"));
				$('div.heightTestElement').remove();
				return (definedHeight != defaultHeight ? definedHeight : 0);
			}

		});

	}

})(jQuery);
