/*******************************************************************************
 * There are two styles of using this function.<br>
 * If popup a div of current page, using TSPopup.showDiv(id), and using
 * TSPopup.closeDiv() to close it. Note that this couple is global function, so
 * never invoke showDiv() more than one times before you closing it.<br>
 * If an external page is expected, using window.open(target, instanceID, width,
 * height) to generate a popup. the first parameter must given, others can be
 * omitted.<br>
 * window.close() can be used in the child window to close itself. <br>
 * If the original window.open() expected, pass all the 3 parameters( sURL,
 * sName, sFeatures ) in.<br>
 ******************************************************************************/

window._open = window.open;
window.open = function(src, name, width, height) {
	if (arguments.length == 3 && typeof (arguments[2]) == 'string')
		window._open(arguments[0], arguments[1], arguments[2]);
	else {
		new TSPopup(name, src, width, height).show();
	}
}
/**
 * @param instanceID
 * @param target
 *            either URL of a page or a DIV Element
 * @param width
 *            can omitted
 * @param height
 *            can omitted
 * @return instance of TSPopup
 */
var TSPopup = function(instanceID, target, width, height) {
	if (instanceID == null)
		instanceID = '__default__instance__';
	this.id = instanceID;

	var instance = TSPopup['_' + instanceID];
	if (!instance) {
		instance = TSPopup['_' + instanceID] = this;
	}
	if (typeof (target) == 'string') {
		instance.DivMode = false;
		instance.URL = target;
		// clear the Layer
		instance.Layer = null;
	} else {
		instance.DivMode = true;
		instance.Layer = target;
	}
	instance.width = width;
	instance.height = height;

	// instance.show();
	return instance;
};

TSPopup.showDiv = function(id) {
	TSPopup._divHandler = new TSPopup(null, document.getElementById(id));
	TSPopup._divHandler.show();
}
TSPopup.closeDiv = function() {
	TSPopup._divHandler.close();
}

TSPopup.version = '1.2.1';
TSPopup.file = 'popup.js';
TSPopup.minWidth = 200;
TSPopup.minHeight = 150;
TSPopup.debugMode = false;

TSPopup.debug = function() {
	if (!TSPopup.debugMode)
		return;
	var msg = arguments[0];
	for ( var i = 1; i < arguments.length; i++) {
		msg = msg.replace('{}', arguments[i]);
	}
	alert(msg);
}

TSPopup.prototype.initCurtain = function() {
	if (this.curtain)
		return;

	var oCoverDiv = document.createElement("DIV");
	oCoverDiv.style.position = 'absolute';
	oCoverDiv.style.zIndex = '8990';
	oCoverDiv.style.top = '0px';
	oCoverDiv.style.left = '0px';
	oCoverDiv.style.width = '100px';
	oCoverDiv.style.height = '100px';
	oCoverDiv.style.display = 'none';
	oCoverDiv.style.backgroundColor = '#000';
	oCoverDiv.style.border = '0';
	document.all ? oCoverDiv.style.filter = "alpha(opacity=50);"
			: oCoverDiv.style.opacity = 0.5; // IE or the other
	document.body.appendChild(oCoverDiv);

	if (document.all) {
		// for IE6, add a frame to hidden 'select' element
		oCoverDiv.innerHTML = '<iframe style="position:absolute;z-index:8989;filter:alpha(opacity=0);'
				+ 'width:expression(this.parentElement.offsetWidth);'
				+ 'height:expression(this.parentElement.offsetHeight);'
				+ 'left:expression(this.parentElement.offsetLeft);'
				+ 'top:expression(this.parentElement.offsetTop);'
				+ 'display:expression(this.parentElement.style.display);" '
				+ 'scrolling="no" frameborder="0"></iframe>';
	}

	this.curtain = {
		coverDiv :oCoverDiv,
		show : function() {
			if (window._popupHandler) {
				/*
				 * make bgColor different from parent, but only works in FF, in
				 * IE the child is fully transparent at all! why?
				 */
				TSPopup
						.debug(
								'parent cutain color: {}',
								window._popupHandler.curtain.coverDiv.style.backgroundColor);
				this.coverDiv.style.backgroundColor = '#333';
			}
			this.resize();
			this.coverDiv.style.display = '';
		},
		resize : function() {
			this.coverDiv.style.height = 0;
			this.coverDiv.style.width = 0;

			var stage = TSPopup.stage();
			/*
			 * minus 1 here, for firefox will show the scrollbar, then hidden it
			 * quickly when it's a full screen size.
			 */
			var width = (stage.offsetWidth > stage.width ? stage.offsetWidth - 1
					: stage.width) + 'px';
			var height = (stage.offsetHeight > stage.height ? stage.offsetHeight - 1
					: stage.height) + 'px';

			this.coverDiv.style.height = height;
			this.coverDiv.style.width = width;
		},
		hide : function() {
			this.coverDiv.style.display = 'none';
		}
	};
}

TSPopup.prototype.initLayer = function() {
	if (this.Layer)
		return;
	// if this instance is DivMode of this function called more than once, the
	// Layer has been bound.

	/*
	 * create Layer
	 */
	var oLayer = this.Layer = document.createElement('DIV');
	oLayer.id = this.id;
	oLayer.style.position = 'absolute';
	oLayer.style.zIndex = '9000';
	// oLayer.style.width = '500px';
	// oLayer.style.height = '100px';
	oLayer.style.display = 'none';
	oLayer.style.border = '1px #5178a7 solid';
	oLayer.style.backgroundColor = '#fff';

	var baseURL = TSPopup.getBaseURL();
	oLayer.innerHTML = '<div style="height:22px; background: url('
			+ baseURL
			+ 'popup_bg.gif) repeat-x;">'
			+ '<img style="float:left; margin:2px 0 0 12px;" src="'
			+ baseURL
			+ 'popup_title.gif" width="20" height="18" />'
			+ '<div id="'
			+ this.id
			+ '_title" style="float:left; margin:3px 0px 0px 10px; color:#FFF;"></div>'
			+ '<div style="float:right; margin-right:4px;">' + '<img src="'
			+ baseURL
			+ 'popup_close.gif" width="31" height="19" onclick="TSPopup[\'_'
			+ this.id + '\'].close();" style="cursor:pointer;"/>'
			+ '</div></div>';
	document.body.appendChild(oLayer);
	oLayer.Title = document.getElementById(this.id + '_title');

	/*
	 * create content Frame
	 */
	var oFrm = oLayer.Frame = document.createElement('iframe');
	oFrm.frameBorder = '0';
	/*
	 * fix endless status bar when the first loading
	 */
	oFrm.src = null;
	// oFrm.scrolling = 'no';
	oFrm.allowTransparency = false;
	oLayer.appendChild(oFrm);
}

TSPopup.prototype.show = function() {
	/*
	 * maximize parent, if any
	 */
	if (window._popupHandler) {
		window._popupHandler.maximize();
	}

	var instance = this;

	/*
	 * initialize current window, bind events
	 */
	TSPopup.attachEvent(window, "resize", function() {
		instance.rePosition();
	});
	document.documentElement.style.overflow = 'hidden';
	document.oncontextmenu = function() {
		return false;
	}

	/*
	 * self initialize
	 */
	this.initCurtain();
	this.initLayer();
	this.curtain.show();

	if (this.DivMode) {
		// show the Layer directly
		this.fadeOut();
		this.Layer.style.position = 'absolute';
		this.Layer.style.display = '';
		this.rePosition();
		this.fadeIn();
	} else {
		/*
		 * bind child enhance action, show the Layer after loaded.
		 */
		var oFrm = this.Layer.Frame;
		TSPopup.attachEvent(oFrm, "load", function() {
			if (oFrm.contentWindow._popupHandler) {
				// in IE, moving or resize the iframe will cause the onload
				// event too!
				return;
			}
			oFrm.contentWindow._popupHandler = instance;
			instance.render();
			instance.registerAPI();
		});

		/*
		 * show the child
		 */
		this.fadeOut();
		oFrm.src = this.URL;
	}
}

TSPopup.prototype.render = function() {
	TSPopup.debug('render');
	var oLayer = this.Layer;
	var oFrame = oLayer.Frame;

	oLayer.style.top = '0';
	oLayer.style.left = '0';
	oLayer.style.display = '';

	var padding = 50 * 2;
	var stage = TSPopup.stage();
	oFrame.width = 1;
	oFrame.height = 1;

	var childDoc = oFrame.contentWindow.document;

	/*
	 * adjust width
	 */
	var minWidth = childDoc.documentElement.scrollWidth;
	minWidth = TSPopup.minWidth > minWidth ? TSPopup.minWidth : minWidth;
	if (stage.width < minWidth + padding) {
		oFrame.width = stage.width - padding;
	} else {
		if (this.width) {
			oFrame.width = (stage.width > this.width + padding ? this.width
					: stage.width - padding);
		} else {
			/*
			 * larger frame a little, to judge if the page width is fixed. In
			 * IE, the diff must large enough, at about 18, why? default margin?
			 * And in FF, either visibility or display must be set to it's
			 * visible value, Otherwise, the render will not happened
			 */
			oFrame.width = minWidth + 20;
			/*
			 * In IE, if a HTML(documentElement) tag has a fixed width, it's
			 * scrollWidth is fixed and the offsetWidth is related to the client
			 * size. But in FF, it's different, the offsetWidth is fixed and the
			 * scrollWidth is alterable.
			 */
			if (childDoc.body.scrollWidth == minWidth) {
				// fixed page width
				oFrame.width = (stage.width > minWidth + padding ? minWidth
						: stage.width - padding);
			} else {
				// set it to the max width
				oFrame.width = stage.width - padding;
			}
		}
	}
	oLayer.normalWidth = oFrame.width;
	oLayer.style.width = oLayer.normalWidth + 'px';
	/*
	 * adjust height
	 */
	var minHeight = childDoc.documentElement.scrollHeight;
	minHeight = TSPopup.minHeight > minHeight ? TSPopup.minHeight : minHeight;
	// diff between layer height and frame height
	var heightDiff = oFrame.offsetTop;
	if (stage.height < heightDiff + minHeight + padding) {
		oFrame.height = stage.height - heightDiff - padding;
		/*
		 * for IE6, there is always a x-scrollBar if there is a y-scrollBar. And
		 * for IE7, the margin isn't the right value either, force the
		 * y-scrollBar and hide the x.
		 * 
		 */
		childDoc.documentElement.style.overflowX = 'hidden';
	} else {
		if (this.height) {
			oFrame.height = (stage.height > this.height + heightDiff + padding ? this.height
					: stage.height - heightDiff - padding);
		} else {
			oFrame.height = minHeight;
		}
	}
	oLayer.normalHeight = parseInt(oFrame.height) + parseInt(oFrame.offsetTop);
	oLayer.style.height = oLayer.normalHeight + 'px';

	/*
	 * ok, show it
	 */
	this.rePosition();
	oLayer.Title.innerHTML = childDoc.title;
	// this.Layer.style.zIndex = '9000';
	this.fadeIn();
}
TSPopup.prototype.fadeOut = function(percent, offset, step) {
	this.Layer.style.zIndex = '8990';
//	document.all ? this.Layer.style.filter = 'alpha(opacity=1);'
//			: this.Layer.style.opacity = 0.01;
}

TSPopup.prototype.fadeIn = function(percent, offset, step) {
	this.Layer.style.zIndex = '9000';
//	if (!percent) {
//		percent = 70;
//		offset = step = 5;
////		document.all ? this.Layer.style.filter = 'alpha(opacity=' + percent + ');'
////				: this.Layer.style.opacity = (percent / 100);
//		this.Layer.style.zIndex = '9000';
//	}

//	percent = percent > 100 ? 100 : percent;
//
//	var oLayer = this.Layer;
////	document.all ? oLayer.style.filter = 'alpha(opacity=' + percent + ');'
////			: oLayer.style.opacity = (percent / 100);
//	if (percent != 100) {
//		percent += offset;
//		offset += step;
//		// step += 5;
//		var instance = this;
//		setTimeout( function() {
//			instance.fadeIn(percent, offset, step);
//		}, 100);
//	}
}
TSPopup.prototype.registerAPI = function() {
	var windw = this.Layer.Frame.contentWindow;
	var instance = this;

	windw.close = function() {
		instance.close();
	};

	windw.document.oncontextmenu = function() {
		return false;
	};
}

TSPopup.prototype.rePosition = function() {
	this.curtain.resize();
	var stage = TSPopup.stage();
	var oLayer = this.Layer;
	oLayer.style.top = stage.top + (stage.height - oLayer.offsetHeight) / 2
			+ 'px';
	oLayer.style.left = stage.left + (stage.width - oLayer.offsetWidth) / 2
			+ 'px';
}

TSPopup.prototype.maximize = function() {
	var oLayer = this.Layer;
	oLayer.style.top = '0px';
	oLayer.style.left = '0px';

	var stage = TSPopup.stage();
	var maxWidth = parseInt(stage.width)
			- (parseInt(oLayer.offsetWidth) - parseInt(oLayer.clientWidth));
	oLayer.style.width = maxWidth + 'px';
	oLayer.Frame.width = maxWidth;

	var maxHeight = parseInt(stage.height)
			- (parseInt(oLayer.offsetHeight) - parseInt(oLayer.clientHeight));
	oLayer.style.height = maxHeight + 'px';
	oLayer.Frame.height = maxHeight - oLayer.Frame.offsetTop;

	this.rePosition();
}

TSPopup.prototype.normalize = function() {
	this.fadeOut();
	this.Layer.style.width = this.Layer.normalWidth + 'px';
	this.Layer.Frame.width = this.Layer.normalWidth;
	this.Layer.style.height = this.Layer.normalHeight + 'px';
	this.Layer.Frame.height = this.Layer.normalHeight
			- this.Layer.Frame.offsetTop;
	this.rePosition();
	this.fadeIn();
}

TSPopup.prototype.close = function() {
	this.Layer.style.display = 'none';
	this.curtain.hide();

	window.document.documentElement.style.overflow = 'auto';
	window.document.oncontextmenu = null;
	if (window._popupHandler) {
		window._popupHandler.normalize();
	}
};

TSPopup.getBaseURL = function() {
	var scripts = document.getElementsByTagName('script');
	for ( var i = 0; i < scripts.length; i++) {
		if (eval('/' + TSPopup.file.replace('.', '\\.') + '$/').test(
				scripts[i].src)) {
			return scripts[i].src.substring(0, scripts[i].src.length
					- TSPopup.file.length);
		}
	}
};

TSPopup.attachEvent = function(obj, evt, fucn) {
	if (document.all) {
		obj.attachEvent("on" + evt, fucn);
	} else {
		obj.addEventListener(evt, fucn, false);
	}
};

TSPopup.stage = function() {
	var isXhtml = false; // if current Doctype is Xhtml
	try {
		isXhtml = document.compatMode == 'CSS1Compat';
	} catch (e) {
	}

	var body = isXhtml ? document.documentElement : document.body;

	return {
		top :body.scrollTop,
		left :body.scrollLeft,
		width :body.clientWidth,
		height :body.clientHeight,
		offsetWidth :body.scrollWidth,
		offsetHeight :body.scrollHeight
	};
};

