var isIE = /microsoft/i.test(navigator.appName);
var isIE7 = /7\./.test(navigator.appVersion);
var isFX = /netscape/i.test(navigator.appName);

var $cover = '';
function showCover(){
	if($cover){
		show($cover);
	}else{
		var w = document.documentElement.scrollWidth || document.body.scrollWidth;
		var h = document.documentElement.scrollHeight || document.body.scrollHeight;
		$cover = document.createElement('div');
		$cover.className = 'global-covering';
		$cover.style.width = w+'px';
		$cover.style.height = h+'px';
		//$cover = $buildElement('div',{className:'global-covering'},{width:w+'px',height:h+'px'});
		document.body.appendChild($cover);
		show($cover);
	}
}
function hideCover(){
	if($cover){
		hide($cover);
	}
}//
/*
if(window.console){
	$log = function (s){
		console.log(s);
	}
	$info = function (s){
		console.info(s);
	}
	$dir = function (o){
		console.dir(o);
	}
}
else{
	$log = function (s){
		document.title = s;
	}
}
*/
function byName(sName){
	return document.getElementsByName(sName);
}//byName
function byTagName(parent, tagName){
	if(parent){
		return parent.getElementsByTagName(tagName);
	}else{
		return document.getElementsByTagName(tagName);
	}
}//byTagName

function byId(sId){
	return document.getElementById(sId);
}//byId

function hasCls(dom, sCls){
	return (new RegExp('\\b' + sCls + '\\b')).test(dom.className);
}//hasCls

function addCls(dom, sCls){
	if(!hasCls(dom, sCls)){
		dom.className += ' ' + sCls;
	}
}//addCls

function delCls(dom, sCls){
	if(hasCls(dom, sCls)){
		dom.className = dom.className.replace((new RegExp('\\b' + sCls + '\\b')), '').replace('  ', ' ');
	}
}//delCls

function show(dom){
	dom.style.display = '';
}//show

function hide(dom){
	dom.style.display = 'none';
}//hide

/************************************************/
/*
功能与 common.js 中同名函数相同，而不用担心冲突
*/
new function (){
	if(window.ENV){
		return;
	}
	/*
	将 oFrom 的所有属性覆盖到 o 中。尤其适用于 o 为某种默认设置、 oFrom 作为其局部调整的情况。
	当 bKeepOriginal 为 true 时，不覆盖 o 中已经存在的属性。
	*/
	$apply = function (o, oFrom, bKeepOriginal){
		if(o && oFrom){
			if($isO(o) && $isO(oFrom)){
				for(var i in oFrom){
					if(i == i.toUpperCase() && $isO(oFrom[i])){
						$apply(o[i], oFrom[i]);
					}
					else{
						if(bKeepOriginal && o[i] != null){
							continue;
						}
						o[i] = oFrom[i];
					}
				}
			}
		}
		return o;
	}//$apply


	$tpl = function (vTpl){
		if(arguments.length > 1){
			for(var i = 1; i < arguments.length; i++){
				vTpl += arguments[i];
			}
		}
		else if($isA(vTpl)){
			vTpl = vTpl.join('');
		}

		var tpl = function (v){
			var s = vTpl;
			if($isO(v)){
				for(var i in v){
					s = s.replace(new RegExp('\{' + i + '\}', 'g'), v[i]);
				}
			}
			else{
				s = s.replace(new RegExp('__', 'g'), arguments[0]);
				for(var i = 0; i < arguments.length; i++){
					s = s.replace(new RegExp('_' + i + '_', 'g'), arguments[i]);
				}
			}
			return s;
		}
		tpl.s = vTpl;
		return tpl;
	}//$tpl

	/************************************************/
	/*
	判断变量 v 的类型
	*/

	$isB = function (v){
		return typeof(v) == 'boolean';
	}//$isB

	$isN = function (v){
		return typeof(v) == 'number';
	}//$isN

	$isS = function (v){
		return typeof(v) == 'string';
	}//$isS

	$isO = function (v){
		return v?
			typeof(v) == 'object':
			false;
	}//$isO

	$isF = function (v){
		return typeof(v) == 'function';
	}//$isF

	$isA = function (v){
		return v instanceof Array;
	}//$isA

	$isR = function (v){
		return v instanceof RegExp;
	}//$isR

	$isH = function (v){
		if(v === window){
			return true;
		}
		return IE ? !!v.tagName : v instanceof HTMLElement;
	}//$isH

	$isJ = function (v){
		return ($isO(v) && !$isA(v));
	}//$isJ

	$isU = function (v){
		return (v == null);
	}//$isU

	/************************************************/
	/*
	扩展数组的功能
	*/
	var $A = {
		indexOf: function (v){
			for(var i = 0; i < this.length; i++){
				if(v === this[i]){
					return i;
				}
			}
			return -1;
		}//indexOf
		,
		has: function (v){
			return this.indexOf(v) > -1;
		}//has
		,
		//如果数组中还没有，则增加此成员 v
		add: function (v){
			if(this.indexOf(v) == -1){
				this.push(v);
				return v;
			}
			return null;
		}//add
		,
		//得到本数组的一个副本（注意：成员如果是对象，那么这些成员并非副本）
		clone: function (){
			var a = [];
			for(var i = 0; i < this.length; i++){
				a.push(this[i]);
			}
			return a;
		}//clone
		,
		//把 v 插入到 v2Insert 之前（!bAfter）或之后（bAfter）
		insert: function (v, v2Insert, bAfter){
			var nIndex = this.indexOf(v);
			if(nIndex >= 0){
				if(bAfter){
					this.splice(nIndex, 1, v, v2Insert);
				}
				else{
					this.splice(nIndex, 1, v2Insert, v);
				}
			}
			return this;
		}//insert
		,
		//对数组成员依次用 f 处理，得到并返回另一个新数组
		map: function (f){
			var a = [];
			for(var i = 0; i < this.length; i++){
				a.push(f.call(this[i], this[i]));
			}
			return a;
		}//map
		,
		//剔除重复的成员
		removeDup: function (bKeepLast){
			var v;
			for(var i = 0; i < this.length; i++){
				v = this[i];
				var nIndex = this.indexOf(v, i + 1);
				if(nIndex > i){
					if(bKeepLast){
						this.splice(i--, 1);
					}
					else{
						this.splice(nIndex, 1);
					}
				}
			}
			return this;
		}//removeDup
		,
		kick: function (v, bMultiple){
			for(var i = 0; i < this.length; i++){
				if(this[i] === v){
					this.splice(i--, 1);
					if(!bMultiple){
						return;
					}
				}
			}
		}//kick
		,
		//用于 jo 的数组：将每个成员(jo)中指定名称/索引的字段的值取出来，得到并返回另一个新数组
		extract: function (sName, bThrowException){
			var a = [];
			for(var i = 0; i < this.length; i++){
				try{
					a.push(this[i][sName]);
				}
				catch(e){
					if(bThrowException){
						$('下面数组在extract时，第' + i + '项无法获取名为' + sName + '的字段');
					}
				}
			}
			return a;
		}//extract
		,
		//用于 jo 的数组：根据每个成员(jo)中指定名称/索引的值将数组排序
		//fSorter为空时，使用默认排序规则。除非 fCompare 特别规定，否则字段值相等的成员之间的相互次序不变
		/*例： 
			[{a: 3}, {a: 5}, {a: 4}].sortBy('a');
			[{a: 'b'}, {a: 'a'}, {a: 'c', b: 1}, {a: 'c'}].sortBy('a');
			[{a: 'b'}, {b: 2}, {a: 'c', b: 1}, {c: false}, {a: 'd'}].sortBy('a');
		*/
		sortBy: function (sName, fCompare, bNullFirst){
			if(fCompare){
				this.sort(function (v0, v1){
					if( (bNullFirst && $isU(v0[sName])) || (!bNullFirst && $isU(v1[sName]) && !$isU(v0[sName])) ){
						return -1;
					}
					else{
						return fCompare(v0[sName], v1[sName]);
					}
				});
			}
			else{
				this.sort(function (v0, v1){
					if( (bNullFirst && $isU(v0[sName])) || (!bNullFirst && $isU(v1[sName]) && !$isU(v0[sName])) ){
						return -1;
					}
					else{
						return v0[sName] < v1[sName] ? -1 : 0;
					}
				});
			}
			return this;
		}//sortBy
		,
		toJ: function (sIdName){
			var jo = {};
			for(var i = 0; i < this.length; i++){
				jo[this[i][sIdName]] = this[i];
			}
			return jo;
		}//toJ
		,
		toSJ: function (sIdName, sValueName){
			var jo = {};
			for(var i = 0; i < this.length; i++){
				jo[this[i][sIdName]] = this[i][sValueName];
			}
			return jo;
		}//toSJ

	};

	$apply(Array.prototype, $A, true);


	/*
	扩展字符串的功能
	*/
	var $S = {
		trim: function (){
			return this.replace(/(^\s*)|(\s*$)/g, '');
		}
		,
		//得到以自身为模板后再代入 v 的结果
		feed: function (){
			return $tpl(this).apply(this, arguments);
		}//feed
	};

	$apply(String.prototype, $S);


	/*
	处理 JO 的通用功能
	*/
	$J = {
		/*
		判断是否没有成员
		*/
		isEmpty: function (jo){
			var b = true;
			for(var i in jo){
				b = false;
			}
			return b;
		}//isEmpty
		,
		/*
		获取其值等于 v 的那个成员在 jo 中的索引
		*/
		indexOf: function (jo, v){
			for(var i in jo){
				if(jo[i] === v){
					return i;
				}
			}
			return null;
		}//indexOf
		,
		migrate: function (jo, f, bApply2Child){
			var o = {};
			for(var i in jo){
				if(bApply2Child && $isO(jo[i])){
					o[i] = this.migrate(jo[i], f, bApply2Child);
				}
				else{
					o[i] = f(jo[i]);
				}
			}
			return o;
		}//migrate
		,
		toArray: function (jo, sIdName){
			var a = [];
			for(var i in jo){
				if($isF(sIdName)){
					a.push(sIdName(i, jo[i]));
				}
				else{
					jo[i][sIdName] = i;
					a.push(jo[i]);
				}
			}
			return a;
		}//toArray
		,
		//按照索引来排序
		sort: function (jo, fCompare){
			var aIndex = [];
			for(var i in jo){
				aIndex.push(i);
			}
			fCompare?
				aIndex.sort(fCompare):
				aIndex.sort();
			var o = {};
			for(var i = 0; i < aIndex.length; i++){
				o[aIndex[i]] = jo[aIndex[i]];
			}
			return o;
		}//sort
	};

	/************************************************/
	/*
	将 sUrl 和 jParam 连接成为适用于 GET 方式的 url 。如果 bTimestamp 为真，则加上时间戳以避免网页缓存。
	*/
	$url = function (sUrl, jParam, bTimestamp){
		//TODO: bTimestamp
		if(!/\?/.test(sUrl)){
			sUrl += '?';
		}
		sUrl += $post(jParam);
		return sUrl;
	}//$url

	$post = function (jParam){
		if(jParam == null){
			return '';
		}
		if($isS(jParam)){
			 return jParam;
		}
		else{
			var a = $J.toArray(jParam, function(sIndex, vValue){return sIndex + '=' + vValue;})
			return a.join('&');
		}
	}//$post


	$eval = function (s){
		return eval('(' + s + ')');
	}//$eval


	/*
	快速新建一个 DOM 对象
	*/
	$dom = function (sTagName, jAttribute, sHtml, aStyle){
		var aSplit = sTagName.split('.');
		sTagName = aSplit[0];
		var dom = document.createElement(sTagName);
		if(aSplit[1]){
			dom.className = aSplit[1];
		}
		for(var i in jAttribute){
			dom.setAttribute(i, jAttribute[i]);
		}
		if(sHtml){
			dom.innerHTML = sHtml;
		}
		if(aStyle){
			$(dom).css(aStyle);		
		}
		return dom;
	}//$dom

	$ajax = function (sUrl, jParam, fSuccess, fFailure, bGetMode){
		if(fFailure === true){
			bGetMode = true;
			fFailure = null;
		}

		//用于绕开 Firefox 的一个 bug：在 POST 而数据为空时，请求头部没有 Content-Length，可能造成 HTTP 411 错误。
		if($J.isEmpty(jParam)){
			bGetMode = true;
		}

		var oHttpRequest;

		//Judge if Not IE
		if(window.XMLHttpRequest){
			oHttpRequest=new XMLHttpRequest();
			//Set request mime is text/xml
			if(oHttpRequest.overrideMimeType){
	//			oHttpRequest.overrideMimeType('text/plain');
			}
		}else if(window.ActiveXObject){
			try{
				oHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
			}catch(ex){
				try{
					oHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
				}catch(ex){
					return false;
				}
			}
		}
		if(bGetMode){
			sUrl = $url(sUrl, jParam);
		}
		oHttpRequest.open((bGetMode ? 'GET' : 'POST'), sUrl);
		oHttpRequest.onreadystatechange=function(){
			if(oHttpRequest.readyState == 4){
				if(oHttpRequest.status==200){
					if(fSuccess){
						fSuccess(oHttpRequest.responseText);
					}
				}else{
					if(fFailure){
						fFailure(oHttpRequest.status);
					}
					else{
						$log('request failure!');
					}
				}
			}      
		}

		oHttpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		oHttpRequest.send($post(jParam));

		return oHttpRequest;
	}//$ajax
	hideFlashObj = function (){
		var oEmbeds = byTagName(null, 'embed');
		var oObjects = byTagName(null, 'object');
		for(var i = 0; i < oEmbeds.length; i++){
			oEmbeds[i].style.visibility = 'hidden';
		}
		for(var i = 0; i < oObjects.length; i++){
			oObjects[i].style.visibility = 'hidden';
		}
	}//show
	showFlashObj = function(){
		var oEmbeds = byTagName(null, 'embed');
		var oObjects = byTagName(null, 'object');
		for(var i = 0; i < oEmbeds.length; i++){
			oEmbeds[i].style.visibility = 'visible';
		}
		for(var i = 0; i < oObjects.length; i++){
			oObjects[i].style.visibility = 'visible';
		}
	}//hide

	_dlg = function (q){
		if(isIE && !isIE7){
			q.realign = function (){
				if(q.css('display') == 'none'){
					return;
				}
				q.css('top', $('html')[0].scrollTop + ($('html')[0].clientHeight - q.height())/2);
				q.css('left', $('html')[0].scrollLeft + ($('html')[0].clientWidth - q.width())/2);
			}//realign

			q.css('position', 'absolute');
			$(window).bind('scroll', function (){
				q.realign();
			});
			$(window).bind('resize', q.realign);
		}
		else{
			q.realign = function (){
				if(q.css('display') == 'none'){
					return;
				}
				var nInnerHeight = isIE7 ? $('html')[0].clientHeight : window.innerHeight;
				var nInnerWidth = isIE7 ? $('html')[0].clientWidth : window.innerWidth;
				q.css('top', (nInnerHeight - q.height())/2);
				q.css('left', (nInnerWidth - q.width())/2);
			}//realign

//			q.css('position', 'fixed');
			$(window).bind('resize', q.realign);
		}

		q.show = function (){//让用户察觉不到重定位的过程
			q.addClass('transparent');
			q.css('display', 'block');
			q.realign();
			q.removeClass('transparent');
			if(isIE && !isIE7){
				$('select').css('visibility', 'hidden');
				$('object').css('visibility', 'hidden');
			}
		}

		if(isIE && !isIE7){
			q.hide = function (){
				$('select').css('visibility', 'visible');
				$('object').css('visibility', 'visible');
				this.css('display', 'none');
			}
		}

		return q;
	}//_dlg

	_alert = function (sText, sTitle, nTime, sOk){
		var dlgAlert = _alert.dlgConfirm = _alert.dlgConfirm || $('#dlgAlert');
		if(!dlgAlert.bReady){
			_dlg(dlgAlert);
			dlgAlert.bReady = true;
			dlgAlert.sOk = $('.btn', dlgAlert).val();
		}
		var sTitle, sText, nTime;
		if($isN(sTitle) && $isU(nTime)){
			nTime = sTitle;
			sTitle = '';
		}
		sTitle = sTitle || '';
		var qTitle = $('.title', dlgAlert);
		var qText = $('.text', dlgAlert);
		if(sTitle){
			qTitle.html(sTitle).show();
		}
		else{
			qTitle.hide();
		}
		qText.html(sText);
		var qOk = $('.btn', dlgAlert);
		qOk.val(sOk || dlgAlert.sOk);
		var nTimer;
		qOk[0].onclick = function (){
			showFlashObj();
			dlgAlert.hide();
			if(nTimer){
				clearTimeout(nTimer);
			}
		};
		if(nTime){
			nTimer = setTimeout(
				function (){
					showFlashObj();
					dlgAlert.hide();
				},
				nTime * 1000
			);
		}
		hideFlashObj();
		dlgAlert.show();
	}//_alert

	_confirm = function (sTitle, sText, fOk, sOk, fCancel, sCancel){
		var dlgConfirm = _confirm.dlgConfirm = _confirm.dlgConfirm || $('#dlgConfirm');
		if(!dlgConfirm.bReady){
			_dlg(dlgConfirm);
			dlgConfirm.bReady = true;
			dlgConfirm.sOk = $('.ok', dlgConfirm).val();
			dlgConfirm.sCancel = $('.cancel', dlgConfirm).val();
		}

		if($isS(fOk)){
			sOk = fOk;
			fOk = null;
		}

		var qTitle = $('.title', dlgConfirm);
		var qText = $('.text', dlgConfirm);
		if(sTitle){
			qTitle.html(sTitle).show();
		}
		else{
			qTitle.hide();
		}
		qText.html(sText);
		var qOk = $('.ok', dlgConfirm);
		var qCancel = $('.cancel', dlgConfirm);
		qOk.val(sOk || dlgConfirm.sOk);
		qCancel.val(sCancel || dlgConfirm.sCancel);
		qOk[0].onclick = function (){
			if(fOk){
				if(fOk.call(dlgConfirm) !== false){
					showFlashObj();
					dlgConfirm.hide();
				}
			}
			else{
				showFlashObj();
				dlgConfirm.hide();
			}
		};
		qCancel[0].onclick = function (){
			if(fCancel){
				if(fCancel.call(dlgConfirm) !== false){
					showFlashObj();
					dlgConfirm.hide();
				}
			}
			else{
				showFlashObj();
				dlgConfirm.hide();
			}
		};
		hideFlashObj();
		dlgConfirm.show();
	}//_confirm

	//略微增强的输入框
	_txt = function (q){
		var dom = q[0];
		q.validate = function (){
			if(dom.title){
				dom.value = $.trim(dom.value) || dom.title;
				if(dom.value == dom.title){
					q.addClass('empty');
					return '';
				}
				else{
					q.removeClass('empty');
				}
			}
			if(q.r){//q.r是验证的正则
				return q.r.test(s);
			}
			return true;
		}
		dom.value = dom.value || dom.title;
		q.validate();
		dom.onfocus = function (){
			if(dom.title && dom.title == q.val()){
				dom.value = '';
			}
			q.removeClass('empty');
		}
		dom.onblur = function (){
			q.validate();
		}
	}//_txt

}();
