/*
* jQuery Frame Dialog 1.1.2
*
* Copyright (c) 2009 SolutionStream.com & Michael J. Ryan (http://www.solutionstream.com/)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
* 
* Requires:
*	jquery ui dialog
*
*	jQuery.FrameDialog namespaced
*		.create()	function will create an iframe, pass on the options 
*					and return from a jQueryUI Dialog.
*					additional url option
*
*	TODO:	- Add logic to allow for relative URLs.
*
*	CUSTOMIZATION:
*		see FrameDialog._defaultOptions below for additional changes from ui dialog defaults
*		Returns a jQuery.dialog extension, with the same options passed in.
*
*		refer to jQueryUI Dialog for more customization options
*
*
*	LOCALIZATION: create a window.localization object
*				localization.OK			override text for the OK button
*				localization.Cancel		override text for the Cancel button
*
*
*	FROM PARENT WINDOW: use the full url, including protocol://host/ portions
*				jQuery.FrameDialog
*					.create({
*						url: baseURL + 'framed-modal-test.aspx',
*						title: 'test title',
*						... Other jQueryUI Dialog Options ...
*					})
*					.bind('dialogclose', function(event, ui) {
*						alert("result: " + event.result);
*					});
*
*	INSIDE MODAL:
*				jQuery.FrameDialog.setResult(value);	//sets the result value
*				jQuery.FrameDialog.clearResult();		//clears the result value
*				jQuery.FrameDialog.closeDialog();		//close the dialog (same as OK)
*				jQuery.FrameDialog.cancelDialog();		//cancel the dialot (same as Cancel
*
*
*
*	!!!!!!!!!! WARNING WARNING WARNING WARNING !!!!!!!!!!
*	Modal must set the result from the same host address in order to access 
*	the parent for setting the result.
*/
(function($) {

	//create FrameDialog namespace
	$.FrameDialog = $.FrameDialog || {};

	//array for return values, placeholder
	$.FrameDialog._results = $.FrameDialog._results || {};
	$.FrameDialog._arguments = $.FrameDialog._arguments || {};
	$.FrameDialog._frames = $.FrameDialog._frames || [];

	//set localized variables
	var OK = (window.localization && window.localization.OK) || "OK";
	var Cancel = (window.localization && window.localization.CANCEL) || "Cancel";
	var buttons = {};
	
	//remove default button
//	buttons[OK] = function() {
//				$(this).dialog("close");
//			}
//	buttons[Cancel] = function() {
//				var frame = $(this);
//				$.FrameDialog.clearResult(frame.attr("id"));
//				frame.dialog("close");
//			}

	//default options
	$.FrameDialog._defaultOptions = {
		modal: true,
		closeOnEscape: false,
		position: 'center',
		buttons: buttons
	};

	var retry = false;
	$.FrameDialog.create = function(options) {
		try	{
			//generate unique id
			var uid = Math.random().toString(16).replace(".", "") + (new Date()).valueOf().toString(16);

			//extend frame dialog options with passed in options.
			var opts = $.extend(
				$.FrameDialog._defaultOptions,
				options || {}
			);
			
			var url = (opts && opts.url) || null;
			if (url === null)
				throw new Error("MODAL ERROR: Option 'url' not specified!"); //diagnostic error

			//clean up redundant forward slashes in the url.
			url = url.replace(/(^|[^:])\/+/g, "$1/");

			//remove url argument from options to be passed to dialog.
			try {
				delete opts.url;
			} catch (err) { }

			// set arguments
			$.FrameDialog._arguments[uid] = opts.args;
			$.FrameDialog._frames.push(uid);
			
			//create iframe object
			//	object type="text/html doesn't seem to work in IE :(
			//	using iframe, which seems to work cross browser, tested in IE7, and Firefox 3.0.7
			var iframe = $("<iframe frameborder='0' scrolling='auto' background='transparent' />")
				.attr("id", uid + "-VIEW")
				.attr("name", uid + "-VIEW")
				.attr("src", url)
				.css("margin", "0")
				.css("border", "0")
				.css("padding", "0")
				.css("top", "0")
				.css("left", "0")
				.css("right", "0")
				.css("bottom", "0")
				.css("width", "100px")
				.css("height", "100px")
				;

			var overlay = $("<div>&nbsp;</div>")
				.css("position", "absolute")
				.css("margin", "0")
				.css("border", "0")
				.css("padding", "0")
				.css("top", "0")
				.css("left", "0")
				.css("right", "0")
				.css("bottom", "0")
				.css("width", "100%")
				.css("height", "100%")
				.css("display", "none")
				;
			var ret = $("<div></div>")
				.attr("id", uid)
				.css("margin", "0")
				.css("border", "0")
				.css("padding", "0")
				.css("top", "0")
				.css("left", "0")
				.css("right", "0")
				.css("bottom", "0")
				.css("overflow", "hidden")
				.hide()
				.append(iframe)
				.append(overlay)
//				.appendTo(opts.container ? opts.container : document.body)
				.bind("dialogbeforeclose", function(event, ui) {
					var frame = $(this);
					var uid = frame.attr("id");

					//default close (firefox) - clear response
					if (event && event.originalTarget && event.originalTarget.nodeName && event.originalTarget.nodeName == "SPAN")
						$.FrameDialog.clearResult(uid);

					//default close (IE7) - clear response
					if (event && event.originalEvent && event.originalEvent.currentTarget && event.originalEvent.currentTarget.tagName && event.originalEvent.currentTarget.tagName == "A")
						$.FrameDialog.clearResult(uid);

					//get the response value, attach to the object.
					var result = $.FrameDialog._results[uid] || null; //result or an explicit null

					return result;
				})
				.bind('dialogclose', function(event, ui) {
					var frame = $(this);
					var uid = frame.attr("id");
					iframe.attr("src", ""); // 1.IE memory leak
					var result = $.FrameDialog._results[uid]; //result or an explicit null
					frame.attr("result", result);
					
					//cleanup the dialog
					frame.dialog('destroy');
					
					//destroy the iframe, remove from the DOM
					iframe.remove(); // 2.IE memory leak
					frame.remove();
					overlay.remove();
					ret.remove();
				
					frame = null; // 3.IE memory leak
					//remove the placeholder for the result
					try {
						delete $.FrameDialog._results[uid];
						delete $.FrameDialog._arguments[uid];
						// 移除frames数组
						var array = $.FrameDialog._frames;
						var index = jQuery.inArray(uid, array);
						if (index > -1) {
							$.FrameDialog._frames.splice(index, 1);
						}
						
						iframe = null;
					} catch (err) { /*nothing to delete*/ }
					
					//Cleanup remnants in 15 seconds
					//		Should be enough time for the results of the close to finish up.

//					window.setTimeout(
//						// 清空对象
//						function() {
//							//cleanup the dialog
//							frame.dialog('destroy');
//							
//							//destroy the iframe, remove from the DOM
//							iframe.remove(); // 2.IE memory leak
//							frame.remove();
//							overlay.remove();
//							ret.remove();
//						
//							frame = null; // 3.IE memory leak
//							//remove the placeholder for the result
//							try {
//								delete $.FrameDialog._results[uid];
//								delete $.FrameDialog._arguments[uid];
//								// 移除frames数组
//								var array = $.FrameDialog._frames;
//								var index = jQuery.inArray(uid, array);
//								if (index > -1) {
//									$.FrameDialog._frames.splice(index, 1);
//								}
//								
//								iframe = null;
//							} catch (err) { /*nothing to delete*/ }
//						},
//						100
//					);

					return result;
				})
				.dialog(opts);
			
			/*** BEGIN FIX FOR jQueryUI 1.7 Dialog's sizing bug *************************************************/
			//store the window width at the start
			var winw = $(document).width();
			var winh = $(document).height();
			var wrap = ret.parent(".ui-resizable");

			//set the window to the appropriate size - fix bug with jQueryUI's Dialog
			//	uses an overlay over the iframe, to prevent focus change.
			wrap.css('width', (opts.minWidth || opts.width || 200) + 'px')
					.css('height', (opts.minHeight || opts.height || 120) + 'px')
					.bind('dragstart', function() {
						overlay.show();
					})
					.bind('dragstop', function() {
						overlay.hide();
					})
					.bind('resizestart', function() {
						overlay.show();
					})
					.bind('resize', function() {
						var height = $(this).height()-50;
						var width = $(this).width();
						// 根据div调整高度、宽度
						//ret.css('height', height + 'px').css('width', width + 'px');
						//iframe.css('height', height + 'px').css('width', width + 'px');
						ret.css('height','90%').css('width','100%');
						iframe.css('height','100%').css('width','100%');
					})
					.bind('resizestop', function() {
						overlay.hide();
						var height = $(this).height()-50;
						var width = $(this).width();
						// 根据div调整高度、宽度
						//ret.css('height', height + 'px').css('width', width + 'px');
						//iframe.css('height', height + 'px').css('width', width + 'px');
						ret.css('height','90%').css('width','100%');
						iframe.css('height','100%').css('width','100%');
					});


			//force resize event.
			window.setTimeout(function(){ 
				wrap.trigger('resizestop');
			}, 100);

			//get window's new width
			var ww = wrap.width();
			var wh = wrap.height();

			//reset the center position, if needed
			if (opts.position == 'center' || (opts.position && (opts.position[0] == 'center' || opts.position[1] == 'center'))) {
				// 默认居中显示
				var pos = parseInt(parseFloat(winw - ww) / 2);
				var top = parseInt(parseFloat(winh - wh) / 2)+$(document).scrollTop();
				
				if (pos < 0) pos = 0;
				if (top < 0) top = 0;
				
				
				wrap.css('left', pos + 'px');
				wrap.css('top', top + 'px');
			}

			//reset right position, as needed
			if (opts.position == 'right' || (opts.position && (opts.position[0] == 'right' || opts.position[1] == 'right'))) {
				var pos = winw - ww - 5; //set to rightmost, - 5 px
				if (pos < 0) pos = 0;

				wrap.css('left', pos + 'px');
			}
			/*** END FIX FOR jQueryUI 1.7 Dialog's sizing bug *************************************************/
			retry = false; //reset the retry state.
			return ret;
		} catch (err) {
			//cleanup any left over ui elements...
			try { ret.dialog('destroy'); } catch(err) {}
			try { ret.remove(); } catch(err) {}
			try { overlay.remove(); } catch(err) {}
			try { iframe.remove(); } catch(err) {}

			//it was a TypeError (seems to be happening with the modal's overlay mask, retry once.
			if (err instanceof TypeError && !retry) {
				retry = true;
				return $.FrameDialog.create(options); //retry once only
			}
			throw err; //rethrow error if something else
		}
	};

	//retrieves the uid for the current frame within the parent.
	$.FrameDialog._getUidOld = function() {
		//find the current frame within the parent window
		if (window.parent && window.parent.frames && window.parent.document && window.parent.document.getElementsByTagName) {
			var iframes = window.parent.document.getElementsByTagName("IFRAME");
			for (var i = 0; i < iframes.length; i++) {
				var id = iframes[i].id || iframes[i].name || i;
				if (window.parent.frames[id] == window) {
					return id.replace("-VIEW", "");
				}
			}
		}
		return null; //no match
	};
	
	var templocation = "";
	/**
	 * 向上递归获取Dialog打开者uid
	 */
	$.FrameDialog._getUid = function(){
		var opener = $.FrameDialog._getOpener();
		if (opener && opener.jQuery && opener.jQuery.FrameDialog) {
			var array = opener.jQuery.FrameDialog._frames;
			if (array.length > 0) {
				var id = array[array.length - 1];
				return id;
			}
		}
			
		return "";
	};
	
	/**
	 * 向上递归获取打开者
	 */
	$.FrameDialog._getOpener = function(){
		var opener = window;
		while (opener) {
			// 向上递归第一个_frames长度大于0的为打开窗口
			if (opener.jQuery && opener.jQuery.FrameDialog  && opener.jQuery.FrameDialog._frames.length > 0){
				return opener;
			} else if(opener == window.top){
				break;
			}
			opener = opener.parent;
		}
		
		return null; //no match
	};

	//Returns the current dialog handle in the parent window as a jquery object.
	$.FrameDialog.current = function() {
		if (window.parent && window.parent.jQuery)
			return window.parent.jQuery("#" + $.FrameDialog._getUid());
		
		return null;
	};


	//clear the result value
	//	uid - id for child window, or empty for current in parent.
	$.FrameDialog.clearResult = function(uid) {
		if (uid) {
			//clear child's value
			try {
				delete $.FrameDialog._results[uid];
			} catch (err) { /*nothing to delete*/ }
		} else {
			//clear for current dialog
			var uid = $.FrameDialog._getUid();
			var opener = $.FrameDialog._getOpener();
			if (uid != null && opener && opener.jQuery && opener.jQuery.FrameDialog && opener.jQuery.FrameDialog._results) {
				try {
					delete opener.jQuery.FrameDialog._results[uid];
				} catch (err) { /*nothing to delete*/ }
			}
		}
	};

	$.FrameDialog.getArguments = function(uid) {
		if (uid) {
			//set child value
			return jQuery.FrameDialog._arguments[uid];
		} else {
			//set value from inside
			var uid = $.FrameDialog._getUid();
			var opener = $.FrameDialog._getOpener();
			if (uid != null && opener && opener.jQuery && opener.jQuery.FrameDialog && opener.jQuery.FrameDialog._arguments) {
				return opener.jQuery.FrameDialog._arguments[uid];
			}
		}
	};
	
	//helper function to set response value	to the parent
	//	value - result value for the given FrameDialog
	//	uid - child id, or empty for current FrameDialog
	$.FrameDialog.setResult = function(value, uid) {
		if (uid) {
			//set child value
			jQuery.FrameDialog._results[uid] = value;
		} else {
			//set value from inside
			var uid = $.FrameDialog._getUid();
			var opener = $.FrameDialog._getOpener();
			if (uid != null && opener && opener.jQuery && opener.jQuery.FrameDialog && opener.jQuery.FrameDialog._results) {
				opener.jQuery.FrameDialog._results[uid] = value;
			}
		}
	};

	//same as clicking OK button
	//	uuid - for a child node, or empty for current
	$.FrameDialog.closeDialog = function(uid) {
		if (uid) {
			//close child
			jQuery("#" + uid).dialog('close');
		} else {
			//close self			
			var uid = $.FrameDialog._getUid();
			var opener = $.FrameDialog._getOpener();
			if (uid != null && opener && opener.jQuery) {
				opener.jQuery("#" + uid).dialog('close');
			}
		}

		return false;
	};
	
	$.FrameDialog.resize = function(width, height, left , top, uid) {
		if (uid) {
			var wrap = jQuery("#" + uid).parent(".ui-resizable");
			//resize child
			if (width > -1) {
				wrap.css('width', width + 'px');
			}
			if (height > -1) {
				wrap.css('height', height + 'px');
			}
			if(left>=0 && typeof left!="string"){
				//var dleft=parseInt(parseFloat(cWidth - width) / 2);
				wrap.css('left', left + 'px');
			}
			if(top>=0 && typeof top!="string"){
				//var dheight=parseInt(parseFloat(cHeight - height) / 2);
				wrap.css('top', top + 'px');
			}
		} else {
			var uid = $.FrameDialog._getUid();
			var opener = $.FrameDialog._getOpener();
			if (uid != null && opener && opener.jQuery && opener.jQuery.FrameDialog) {
				var wrap = opener.jQuery("#" + uid).parent(".ui-resizable");
				//resize self
				if (width > -1) {
					wrap.css('width', width + 'px');
				}
				if (height > -1) {
					wrap.css('height', height + 'px');
				}
				
				if(left>=0 && typeof left!="string"){
					//var dleft=parseInt(parseFloat(cWidth - width) / 2);
					wrap.css('left', left + 'px');
				}
				if(top>=0 && typeof top!="string"){
					//var dheight=parseInt(parseFloat(cHeight - height) / 2);
					wrap.css('top', top + 'px');
				}
			}
		}
	};

	//same as clicking Cancel button
	//	uid - for a child node, or empty for current frame
	$.FrameDialog.cancelDialog = function(uid) {
		$.FrameDialog.clearResult(uid);
		$.FrameDialog.closeDialog(uid);
		return false;
	};


	//extension methods for shortcuts in dealing with a framedialog handle
	$.fn.setResult = function(result) {
		return this.each(function() {
			$.FrameDialog.setResult(result, $(this).attr("id"));
		});
	};

	$.fn.clearResult = function() {
		return this.each(function() {
			$.FrameDialog.clearResult($(this).attr("id"));
		});
	};
	
	$.fn.closeDialog = function() {
		return this.dialog('close');
	};

	$.fn.cancelDialog = function() {
		return this.clearResult().closeDialog();
	};
	
	//get the window context for the object/iframe in question
	$.fn.window = function() {
		//this item is a frame or iframe
		if (this.attr('tagName') == "IFRAME" || this.attr('tagName') == "FRAME")
			return window.frames[this.attr('name') || this.attr('id')];
			
		//get the first frame/iframe child
		var frame = this.find('iframe, frame')[0];
		return (frame && window.frames[frame.name || frame.id]) || null;
	};

})(jQuery);
