/**
 * common.js
 * 這裡是用來存放一些跟Service沒有相關(相依性較低)的Common Function
 * 日後可以直接整個Copy至其它Service使用
 */

// Creating Namespace
var Common = {
	// Page constants.
	DEBUG_MODE: true,
	initialize: function() {
	}
};
Common.initialize();

// Creating Namespace
var Message = {};

// system messages
Message.system = {};
Message.system.fail = "Our system is temporarily busy, please try again later.";
Message.system.wait = "Please wait...";

/**
 * Module: Utils
 * 提供各種共同的Utility Methods
 */
Common.Utils = (function()  {
	// Private members.

	return { // Public members.
		log : function(msg, doTransform) {
			if (!Common.DEBUG_MODE) {
				return true;
			}

			if (window.console != null) {
				if( doTransform ) {
					msg = this.tostr(msg);
				}
				console.log(msg);
			}
		},
		info : function(msg) {
			if (!Common.DEBUG_MODE) {
				return true;
			}

			if (window.console != null) {
				console.info(msg);
			}
		},
		warn : function(msg) {
			if (!Common.DEBUG_MODE) {
				return true;
			}

			if (window.console != null) {
				console.warn(msg);
			}
		},
		error : function(msg) {
			if (!Common.DEBUG_MODE) {
				return true;
			}

			if (window.console != null) {
				console.error(msg);
			}
		},
		tostr : function(data, showLevels, options) {
			if (!Common.DEBUG_MODE) {
				return true;
			}

			if (showLevels == null ) {
				showLevels = 2;
			}
			return DWRUtil.toDescriptiveString(data, showLevels, options);
		},
		trim : function(str, chars) {
			return ltrim(rtrim(str, chars), chars);
		},
		ltrim : function(str, chars) {
			chars = chars || "\\s";
			return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
		},
		rtrim : function(str, chars) {
			chars = chars || "\\s";
			return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
		},
		traceFunc : function(func, expanded) {
			if (!Common.DEBUG_MODE) {
				return true;
			}

			var detail = {};
			if (func != null && jQuery.isFunction(func)) {
				var name = /\W*function\s+([\w\$]+)\(/.exec(func);
				if (!name) {
					detail.name = "Anonymous";
				} else {
					detail.name = name[1];
				}
				detail.caller = func.caller;

				if (expanded) {
					detail.code = func.toString();
				} else {
					var code = func.toString();
					var limitLength = 100;
					if (code.length > limitLength) {
						code = code.substring(0, limitLength) + "...";
					}
					detail.code = code;
				}
			} else {
				detail.name = "It's not function";
			}
			return DWRUtil.toDescriptiveString(detail, 3);
		},
		stripTags : function(tagsString){
			return tagsString.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
		},
		isIE67 : function() { // check the current browser is IE6 or IE7?
			return ( navigator.userAgent.toLowerCase().indexOf("msie 7.0") >= 0
				|| navigator.userAgent.toLowerCase().indexOf("msie 6.0") >= 0 );
		},
		isIE: function() {
			return jQuery.browser.msie;
		},
		isFirefox: function() {
			return jQuery.browser.mozilla;
		},
		isChrome: function() {
			var ua = navigator.userAgent.toLowerCase();
			return (ua.indexOf("chrome") >= 0);
		},
		isSafari: function() {
			var ua = navigator.userAgent.toLowerCase();
			return (jQuery.browser.safari || ua.indexOf("safari") >= 0 ) && (ua.indexOf("chrome") == -1);
		},
		isOpera: function() {
			var ua = navigator.userAgent.toLowerCase();
			return (jQuery.browser.opera || ua.indexOf("opera") >= 0 );
		},
		isObject : function(data) {
  			return (data && typeof data == "object");
		},
		getScreenWidth: function() {
			return document.documentElement.clientWidth;
		},
		getScreenHeight: function() {
			return document.documentElement.clientHeight;
		},
		getScrollLeft: function () {
			var sl = window.pageXOffset ||
				document.body.scrollLeft ||
				document.documentElement.scrollLeft;

			return sl ? sl : 0;
		},
		getScrollTop: function() {
			var st = window.pageYOffset ||
				document.body.scrollTop ||
				document.documentElement.scrollTop;

			return st ? st : 0;
		},
		displayFileSize: function(size) {
			var displayStr = "";
			if( size != null && typeof size == 'number') {
				if( size >= 1048576 ) {
					displayStr = (size/1048576).toFixed(2) + " MB";
				} else if( size >= 1024 ) {
					displayStr = (size/1024).toFixed(2) + " KB";
				} else {
					displayStr = (size) + " Bytes";
				}
			}
			return displayStr;
		},
		getMessage : function(key, params) {
			var fullKey = "Message." + key;
			try {
				var message = eval(fullKey);
				if (Common.Utils.isObject(params)) {
					for( var i=0; i<params.length; i++ ) {
						if( params[i] != null ) {
							var replaceStr = "{"+i+"}";
							while ( message.indexOf( replaceStr ) != -1 ) {
								message = message.replace( replaceStr, params[i] );
							}
						}
					}
				}
				return message;
			} catch (e) {
				this.warn('?' + fullKey);
				return '?' + fullKey;
			}
		},
		getConfMessage: function(msg, params) {
			try {
				var message = msg;
				if (Common.Utils.isObject(params)) {
					for( var i=0; i<params.length; i++ ) {
						if( params[i] != null ) {
							var replaceStr = "{"+i+"}";
							while ( message.indexOf( replaceStr ) != -1 ) {
								message = message.replace( replaceStr, params[i] );
							}
						}
					}
				}
				return message;
			} catch (e) {
				this.warn('?' + key);
				return '?' + key;
			}
		},
		showMessage : function(key, lang) {
			var fullKey = key + '_' + lang;
			try {
				var message = eval(fullKey);
				alert(message);
			} catch (e) {
				alert('?' + fullKey);
			}
		},
		loadCaptcha : function() {
			var now = new Date();
			var captchaImage = document.getElementById('captchaImage');
			if (captchaImage == null) {
				captchaImage = new Image();
				captchaImage.id = 'captchaImage';
				captchaImage.name = 'captchaImage';
				captchaImage.style.cursor = 'pointer';
				jQuery('#randomCaptcha').prepend(captchaImage);
				jQuery(captchaImage).click(Common.Utils.loadCaptcha);
			}

			window.setTimeout(function() {
				var captchaImage = document.getElementById('captchaImage');
				captchaImage.src = '/captcha/secure.captcha?rand=' + now.getTime();
				Common.Utils.log("Generate new CAPTCHA image at " + now.getTime());
			}, 100);
		},
		// function to calculate local time
		// in a different city
		// given the timezone's UTC offset
		formatDate : function(dateTime, pattern, offset) {
		    // convert to msec
		    // add local time zone offset
		    // get UTC time in msec
		    var utc = dateTime.getTime() + (dateTime.getTimezoneOffset() * 60000);

		    // create new Date object for different timezone
    		// using supplied offset
    		var localTime = new Date(utc + (3600000 * offset));
    		var display = localTime.format(pattern);

    		// return time as a string
    		return display;
		},
		initTimeZoneCookie : function() {
			var tzoCookie = jQuery.cookie('timezone_offset');
			if (tzoCookie != null) {
				return true;
			}

			var hostname = window.location.hostname;
			if ("localhost" == hostname) {
				// It's so strang! only word "localhost" is not able to be assign.
				hostname = "";
			}

			// get the timezone offset (hour) in client side and keep it in browser cookies firstly.
			var offsetHours = -((new Date().getTimezoneOffset()) / 60);
			// this cookie will be pass to the server per HTTP request.
			jQuery.cookie('timezone_offset', offsetHours, {
				expires: 1,
				path: '/',
				domain: hostname
			});

			Common.Utils.log('Cookie timezone_offset is created. Offset: ' + offsetHours +
				' hours, Domain: ' + hostname);
		},
		// get DOM child element by different browser
		getChildNode: function(node, namespace, tagName, index) {
			if( index == null ) {
				index = 0;
			}
			var nodes = this.getChildNodes(node, namespace, tagName);
			if( nodes != null && nodes.length > index ) {
				return nodes[index];
			}
			return null;
		},
		getChildNodes: function(node, namespace, tagName) {
			if( node != null ) {
				if( namespace != null && jQuery.trim(namespace) != "" ) {
					if( jQuery.browser.safari ) { // safari & chrome browser must call getElementsByTagNameNS function
						return node.getElementsByTagNameNS("*", tagName);
					} else { // IE browser must call getElementsByTagName function
						return node.getElementsByTagName(namespace+":"+tagName);
					}
				} else {
					return node.getElementsByTagName(tagName);
				}
			} else {
				this.warn('there is no element!');
			}
		},
		// find domain url via passed full url
		findDomainUrl: function(fullUrl) {
			//this.log( '[findDomainUrl] fullUrl: '+fullUrl);
			var domainUrl = fullUrl;
			var protocol = null;
			var remain = null;
			if( fullUrl.substr(0, 'http://'.length) == 'http://' ) {
				remain = fullUrl.slice('http://'.length, fullUrl.length);
				protocol = 'http://';
			} else if( fullUrl.substr(0, 'https://'.length) == 'https://' ) {
				remain = fullUrl.slice('https://'.length, fullUrl.length);
				protocol = 'https://';
			} else {
				remain = fullUrl;
			}

			//this.log( '[findDomainUrl] remain: '+remain);
			var firstSlash = remain.indexOf('/');
			var domain = null;
			if( firstSlash >= 0 ) {
				domain = remain.slice(0, firstSlash);
			} else {
				domain = remain;
			}
			//this.log( '[findDomainUrl] domain: '+domain);

			domainUrl = protocol + domain + '/';
			return domainUrl;
		}
	};
})();

/**
 * Module: Object
 * 提供各種處理Javascript OOP的Methods
 */
Common.Object = (function()  {
	// static private methods

	return { // static public methods
		inherit: function(parent, child) { // global inherit method
			var grandParent = null;
			if( parent.prototype != null ) {
				grandParent = parent.prototype;
			}
			parent.prototype = {};
			for (var property in parent) {
				if( property != 'prototype' ) {
					parent.prototype[property] = parent[property];
				} else if( grandParent != null ) {
					parent.prototype.prototype = grandParent;
				}
			}
			for (var property in child) {
				parent[property] = child[property];
			}
			return parent;
		}
	}
})();

jQuery.fn.clearForm = function(ignoredNames) {
	Common.Utils.log("Ignored fields in form: \n" + Common.Utils.tostr(ignoredNames, 2));

	return this.each(function(){
		var type = this.type;
		var name = this.name;
		var tag = this.tagName.toLowerCase();

		if (tag == 'form') {
			return jQuery(':input', this).clearForm(ignoredNames);
		}

		if (ignoredNames != null) {
			for (var i = 0; i < ignoredNames.length; i++) {
				Common.Utils.log("element name: " + name + ", ignored names: " + ignoredNames[i]);
				if (name == ignoredNames[i]) {
					return true;
				}
			}
		}

		if (type == 'text' || type == 'password' || tag == 'textarea') {
			this.value = '';
		} else {
			if (type == 'checkbox' || type == 'radio') {
				this.checked = false;
			} else {
				if (tag == 'select') {
					this.selectedIndex = -1;
				}
			}
		}
	});
};

/**
 * Module: AJAX
 * 提供各種共同的 AJAX Methods
 * syntax:
 * 		Common.AJAX.getInstance().get(url, param, callback);
 */
Common.AJAX = (function() {
	/**
	 *@constructor
	 */
	function constructor() { // 物件的實作都寫在這裡
    	// Private members.
	    var _callback = null; // keep the callback in memory temporarily
	    var _param = {}; // keep the parameter object in memory temporarily

		/**
		 * Be delegated to call the callback after the response is returned.
		 * @param data the data returned from the server.
		 * @param textStatus a string describing the status.
 		 */
		function delegate(data, textStatus) {
			Common.Utils.log("Return from the server:\n" + Common.Utils.tostr(data, 3));

			if (data.type == 'WARN' || data.type == 'ERROR') {
				if (typeof data.cause != 'undefined') {
					if (data.cause.indexOf('SessionTimeout') >= 0) {
						alert(data.message);
						window.location.href = '/member/login.jsp';
						return false;
					}
				}
			}

			var result = null;
			if (_callback != null) {
				// execute the callback originated by the external caller
				result = _callback.apply(this, [data, textStatus]);
			}

			return result;
		}

		/**
		 * The pre-callback before the request is sent that is integrated with jQuery jGrowl plug-in.
 		 */
		function alertBeforeSend(XMLHttpRequest) {
			var message = "Loading...";
			if (_param != null && _param != '') {
				if (Common.Utils.isObject(_param)) {
					if (typeof _param.target != 'undefined') {
						message = Common.Utils.getMessage("load.growlMsg", [_param.target]);
					}
				} else if (_param.indexOf("&") > 0) {
					var pairs = _param.split("&");
				    for (var i = 0; i < pairs.length; i++) {
    				    var pair = pairs[i].split("=");
    				    if (pair[0] == 'target') {
    				    	if (pair[1].indexOf('%') >= 0) {
    				    		pair[1] = decodeURIComponent(pair[1]);
    				    	}
    				    	message = Common.Utils.getMessage("load.growlMsg", [pair[1]]);
    				     	break;
    				    }
    				}
				}
			}
			Common.UI.growlMessage(message);
		}

		/**
		 * The post-callback after the request is sent that is integrated with jQuery jGrowl plug-in.
 		 */
		function closeAlert(XMLHttpRequest, textStatus) {
		}

		/**
		 * The pre-callback before the request is sent that is integrated with jQuery BlockUI plug-in.
 		 */
		function blockBeforeSend(XMLHttpRequest) {
			var waitMsg = Common.Utils.getMessage("system.wait");
			if (waitMsg == null) {
				waitMsg = "Please wait...";
			}

			var contentPanel = document.getElementById('contentPanel');
			if (contentPanel) {
				jQuery('#contentPanel').block({
					message: '<img src="/js/jquery/loading.gif" /><font size="2">' + waitMsg + '</font>'
				});
			} else {
				jQuery.blockUI({
					message: '<img src="/js/jquery/loading.gif" /><font size="2">' + waitMsg + '</font>'
				});
			}
		}

		/**
		 * The post-callback after the request is sent that is integrated with jQuery BlockUI plug-in.
 		 */
		function closeBlock(XMLHttpRequest, textStatus) {
			var contentPanel = document.getElementById('contentPanel');
			if (contentPanel) {
				jQuery('#contentPanel').unblock();
			} else {
				jQuery.unblockUI();
			}
		}

		/**
		 * The callback if the request fails.
 		 */
		function error(XMLHttpRequest, textStatus, errorThrown) {
			var message = Common.Utils.getMessage("system.fail");
			alert(message);

			Common.Utils.log('Request fail! \nstatus: ' + XMLHttpRequest.status + '\nresponse text: \n' +
				XMLHttpRequest.responseText);
			jQuery.unblockUI();
		}

	    return { // Public members.
			/**
			 * Send a GET request to server via AJAX implementation without the UI effect.
			 * P.S. Indepenecy with any extra jQuery UI effect plug-in.
			 * @param url the requested URL.
		 	 * @param param the data are sent to the server.
			 * @param callback the function to be called if the request succeds.
		 	 * @param sync true if the request is sent synchronously, or false.
 		 	 */
			get : function(url, param, callback, sync) {
				var detail = "========================[AJAX detail Begin]========================\n";
				detail = detail + "url: " + url;
				detail = detail + "\nparam:\n" + Common.Utils.tostr(param);
				detail = detail + "\ncallback:\n" + Common.Utils.traceFunc(callback);
				detail = detail + "\nsync: " + sync + "\n";
				detail = detail + "========================[End AJAX detail]========================";
				Common.Utils.log(detail);

				if (typeof param == 'undefined' || param == null) {
					param = {};
				}
				if (typeof sync == 'undefined' || sync == null) {
					sync = false;
				}
				_param = param;
				param.dataType = 'json';
				_callback = callback;

				jQuery.ajax({
					cache : false,
					async : !sync,
					type : "GET",
					url : url,
					data : param,
					dataType : 'json',
					success : delegate
				});
			},
			/**
			 * Send a POST request to server via AJAX implementation without the UI effect.
			 * P.S. Indepenecy with any extra jQuery UI effect plug-in.
			 * @param url the requested URL.
		 	 * @param param the data are sent to the server.
			 * @param callback the function to be called if the request succeds.
		 	 * @param sync true if the request is sent synchronously, or false.
 		 	 */
			post : function(url, param, callback, sync) {
				var detail = "========================[AJAX detail Begin]========================\n";
				detail = detail + "url: " + url;
				detail = detail + "\nparam:\n" + Common.Utils.tostr(param);
				detail = detail + "\ncallback:\n" + Common.Utils.traceFunc(callback);
				detail = detail + "\nsync: " + sync + "\n";
				detail = detail + "========================[End AJAX detail]========================";
				Common.Utils.log(detail);

				if (typeof param == 'undefined' || param == null) {
					param = {};
				}
				if (typeof sync == 'undefined' || sync == null) {
					sync = false;
				}
				_param = param;
				param.dataType = 'json';
				_callback = callback;

				jQuery.ajax({
					cache : false,
					async : !sync,
					type : "POST",
					url : url,
					data : param,
					dataType : 'json',
					success : delegate
				});
			},
			/**
			 * Send a GET request to server via AJAX implementation with the UI effect showed by jQuery jGrowl plug-in.
			 * P.S. Depenecy with jQuery jGrowl plug-in.
			 * @param url the requested URL.
		 	 * @param param the data are sent to the server.
			 * @param callback the function to be called if the request succeds.
		 	 * @param sync true if the request is sent synchronously, or false.
 		 	 */
			getOnAlert : function(url, param, callback, sync) {
				var detail = "========================[AJAX detail Begin]========================\n";
				detail = detail + "url: " + url;
				detail = detail + "\nparam:\n" + Common.Utils.tostr(param);
				detail = detail + "\ncallback:\n" + Common.Utils.traceFunc(callback);
				detail = detail + "\nsync: " + sync + "\n";
				detail = detail + "========================[End AJAX detail]========================";
				Common.Utils.log(detail);

				if (typeof param == 'undefined' || param == null) {
					param = {};
				}
				if (typeof sync == 'undefined' || sync == null) {
					sync = false;
				}
				_param = param;
				param.dataType = 'json';
				_callback = callback;

				jQuery.ajax({
					global : false,
					cache : false,
					async : !sync,
					type : "GET",
					url : url,
					data : param,
					dataType : 'json',
					beforeSend : alertBeforeSend,
					complete : closeAlert,
					success : delegate,
					error : error
				});
			},
			/**
			 * Send a POST request to server via AJAX implementation with the UI effect showed by jQuery jGrowl plug-in.
			 * P.S. Depenecy with jQuery jGrowl plug-in.
			 * @param url the requested URL.
		 	 * @param param the data are sent to the server.
			 * @param callback the function to be called if the request succeds.
		 	 * @param sync true if the request is sent synchronously, or false.
 		 	 */
			postOnAlert : function(url, param, callback, sync) {
				var detail = "========================[AJAX detail Begin]========================\n";
				detail = detail + "url: " + url;
				detail = detail + "\nparam:\n" + Common.Utils.tostr(param);
				detail = detail + "\ncallback:\n" + Common.Utils.traceFunc(callback);
				detail = detail + "\nsync: " + sync + "\n";
				detail = detail + "========================[End AJAX detail]========================";
				Common.Utils.log(detail);

				if (typeof param == 'undefined' || param == null) {
					param = {};
				}
				if (typeof sync == 'undefined' || sync == null) {
					sync = false;
				}
				_param = param;
				param.dataType = 'json';
				_callback = callback;

				jQuery.ajax({
					global : false,
					cache : false,
					async : !sync,
					type : "POST",
					url : url,
					data : param,
					dataType : 'json',
					beforeSend : alertBeforeSend,
					complete : closeAlert,
					success : delegate,
					error : error
				});
			},
			/**
			 * Send a GET request to server via AJAX implementation with the UI effect showed by jQuery BlockUI plug-in.
			 * P.S. Depenecy with jQuery BlockUI plug-in.
			 * @param url the requested URL.
		 	 * @param param the data are sent to the server.
			 * @param callback the function to be called if the request succeds.
		 	 * @param sync true if the request is sent synchronously, or false.
 		 	 */
			getOnBlock : function(url, param, callback, sync) {
				var detail = "========================[AJAX detail Begin]========================\n";
				detail = detail + "url: " + url;
				detail = detail + "\nparam:\n" + Common.Utils.tostr(param);
				detail = detail + "\ncallback:\n" + Common.Utils.traceFunc(callback);
				detail = detail + "\nsync: " + sync + "\n";
				detail = detail + "========================[End AJAX detail]========================";
				Common.Utils.log(detail);

				if (typeof param == 'undefined' || param == null) {
					param = {};
				}
				if (typeof sync == 'undefined' || sync == null) {
					sync = false;
				}
				_param = param;
				param.dataType = 'json';
				_callback = callback;

				jQuery.ajax({
					global : false,
					cache : false,
					async : !sync,
					type : "GET",
					url : url,
					data : param,
					dataType : 'json',
					beforeSend : blockBeforeSend,
					complete : closeBlock,
					success : delegate,
					error : error
				});
			},
			/**
			 * Send a GET request to server via AJAX implementation with the UI effect showed by jQuery BlockUI plug-in.
			 * P.S. Depenecy with jQuery BlockUI plug-in.
			 * @param url the requested URL.
		 	 * @param param the data are sent to the server.
			 * @param callback the function to be called if the request succeds.
		 	 * @param sync true if the request is sent synchronously, or false.
 		 	 */
			postOnBlock : function(url, param, callback, sync) {
				var detail = "========================[AJAX detail Begin]========================\n";
				detail = detail + "url: " + url;
				detail = detail + "\nparam:\n" + Common.Utils.tostr(param);
				detail = detail + "\ncallback:\n" + Common.Utils.traceFunc(callback);
				detail = detail + "\nsync: " + sync + "\n";
				detail = detail + "========================[End AJAX detail]========================";
				Common.Utils.log(detail);

				if (typeof param == 'undefined' || param == null) {
					param = {};
				}
				if (typeof sync == 'undefined' || sync == null) {
					sync = false;
				}
				_param = param;
				param.dataType = 'json';
				_callback = callback;

				jQuery.ajax({
					global : false,
					cache : false,
					async : !sync,
					type : "POST",
					url : url,
					data : param,
					dataType : 'json',
					beforeSend : blockBeforeSend,
					complete : closeBlock,
					success : delegate,
					error : error
				});
			}
    	};
    }

    return {
    	getInstance : function() {
    		return constructor();
    	}
    }
})();

/**
 * Module: UI
 * 提供各種共同的 UI Methods
 */
Common.UI = (function()  {
	// Private members.

	return { // Public members.
		openDialog : function(dialog) {
			dialog.overlay.slideDown('normal', function () {
				dialog.container.fadeIn('normal');
				dialog.data.show();
			});
		},
		closeDialog : function(dialog) {
			dialog.container.slideUp('normal', function () {
				dialog.overlay.fadeOut('normal', function () {
					jQuery.modal.close();
				});
			});
		},
		confirmModal : function(message, callback) {
			jQuery("#confirm").modal({
				close : true,
				position : ["15%", "50%"],
				overlayId : 'confirmModalOverlay',
				containerId : 'confirmModalContainer',
				onOpen : this.openDialog,
				onClose : this.closeDialog,
				onShow : function(dialog) {
					dialog.data.find(".confirmmessage").append(message);
					dialog.data.find('#ButtonYes').click(function() {
						jQuery.modal.close();
						if (jQuery.isFunction(callback)) {
							callback.call(this);
						}
					});
				}
			});
		},
		pressEscKey : function() {
			jQuery(document.body).bind('keypress', function(evt) {
				var key = evt.which || evt.keyCode;
				if (key == 27) {
					// close modal dialog UI
					jQuery.modal.close();
					// unblock fool-proof UI
					jQuery.unblockUI();
					jQuery(document.body).unbind('keypress');
				}
			});
		},
		growlMessage : function(message) {
			jQuery.jGrowl(message, {
				life: 1200,
				speed: 'fast',
				easing: 'linear',
				corners: '14px'
			});
		},
		// open a browser window and align center
		openWindow: function(url, w, h) {
			w = (w == null)? 800:w;
			h = (h == null)? 600:h;
			var sw = document.documentElement.clientWidth;
			var sh = document.documentElement.clientHeight;
			var left = (sw-w)/2;
			var top = (sh-h)/2;
			var wnd = window.open(url,null,"height="+h+",width="+w+",top="+top+",left="+left+",status=yes,toolbar=no,menubar=no,location=no,resize=yes,scrollable=yes,resizable=1,scrollbars=yes");
			if( wnd.opener == null ) {
				wnd.opener = self;
			}
			return wnd;
		}
	};
})();

/**
 * Module: Validate
 * 提供各種共同的 Validate Methods
 */
Common.Validate = (function()  {
	// Private members.

	return { // Public members.
	    FORMAT : {
			REGNOW : /^[a-zA-Z0-9_-]{5,}$/,
			ACCOUNT : /^[a-zA-Z0-9._-]{6,12}$/,
	    	PASSWORD : /^[a-zA-Z0-9]{6,12}$/,
	    	EMAIL : new RegExp('^[\\w\\.-]+@[a-zA-Z0-9][\\w\\.-]*\\.[a-zA-Z][a-zA-Z\\.]*[a-zA-Z]$'),
	    	CAPTCHA : /^[a-zA-Z0-9]{4}$/,
	    	VERSION : new RegExp('^[0-9]+(\\.[0-9]+)+$'),
	    	BIRTHDAY : /^(19|20)\d\d([-])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$/
	    },
		validateFormat : function(regex, source) {
			return regex.test(source);
		}
	};
})();

