﻿function isEmpty(str){return (str===undefined||str===null||str==="");}
function isString(obj){return (!isEmpty(obj) && (typeof(obj)=="string" || obj instanceof String));}
function isFunction(obj){return (!isEmpty(obj) && (typeof(obj)=="function" || obj instanceof Function));}
function isMSIE() {return (document.all && navigator.userAgent.toLowerCase().indexOf('msie')!=-1);}
function isMSIE7() {return (document.all && navigator.userAgent.toLowerCase().indexOf('msie 7.0')!=-1);}
function isSafari(){return (window.openDatabase && navigator.userAgent.toLowerCase().indexOf("safari") != -1);}
function getFromArray(arr, i, def) {return (!arr || arr.length<i || !arr[i-1])?def:arr[i-1];}
function getFromObject(obj, key, def){return (obj && (key in obj)&& obj[key])?obj[key]:def;}
function getCurDateString(){
	var d = new Date(),f = function(m){return m>9?m:("0"+m);};
	return d.getFullYear() +"-"+(d.getMonth()+1)+"-" + d.getDate()+" " +d.getHours()+":"+f(d.getMinutes()) +":"+f(d.getSeconds());
}
function cvtToKMG(n, unitN){
	unitN = unitN.toUpperCase();
	var units = {K:1024, M:1048576, G:1073741824};
	return  (unitN in units)?(Math.ceil(n/units[unitN])+ unitN):n ;
}

function composeUrl(xurl){
	if (xurl.toLowerCase().indexOf("http")<0 ) {
		var list = (window.location.href.split("?")[0]).split("/");
		list.length-=1;
		xurl=list.join("/") + "/" + xurl;
	}
	return xurl;
}
function getValueFromHref(key, defV){
	var paramList = window.location.search.substring(1).split("&");
	for(var i=0; i<paramList.length; i+=1){
		if(paramList[i].indexOf(key+"=")==0){return paramList[i].substring(key.length+1);}
	}
	return defV;
}

function $Frame(name){
    for (var i=0; i<window.frames.length; i+=1){
        try {
            if(window.frames[i].name==name){return window.frames[i];}
        }catch (e){}
    }
    return null;
}

window.IX = {
	isFn : function(obj){
		return (obj!=undefined && obj != null && (typeof(obj)=="function" || obj instanceof Function));
	},
	_nsLoop : function(nsname, fn){
		var names = nsname.split(".");
		if (names[0]=="window"){
			names.shift();
		}
		var nsObj = window;
		var flag = true;
		while(names.length>0 && flag){
			var curname = names.shift();
			flag = fn(curname, nsObj);
			if(flag){
				nsObj = nsObj[curname];
			}
		}
		return flag;
	},
	ns : function(nsname){
		IX._nsLoop(nsname, function(name, obj){
			if (!(name in obj)) {
				obj[name] = {};
			}
			return true;
		});
	},
	nsExisted : function(nsname){
		return IX._nsLoop(nsname, function(name, obj){
			return (name in obj);
		});
	},
	execute : function(fname, args) {
		var fn = IX._nsLoop(fname, function(name, obj){
			return (name in obj)?obj[name]:false;
		});
		if (IX.isFn(fn)){
			fn.apply(null, args);
		}
	}
};

IX.Utils= {
	_partLoop:function(varr,sIdx,eIdx, acc0, fun, isAscLoop) {
		if (varr==null || sIdx>=eIdx){return acc0;}
		var acc =acc0, len =varr.length, j=0;
		for (var i=0; i<len; i+=1) {
			j = isAscLoop?i:(len-1-i);
			if (Math.inRange(j, Math.max(0, sIdx),Math.min(len, eIdx)) && (j in varr)){acc=fun(acc, varr[j], j);}
		}
		return acc;
	},
	_loop:function(varr, acc0, fun, isAscLoop) {
		return (varr!=null && varr.length>0)?this._partLoop(varr, 0, varr.length, acc0, fun, isAscLoop):acc0;
	},
	loop:function(varr, acc0, fun) {return this._loop(varr, acc0, fun, true);},
	partLoop:function(varr,sIdx,eIdx, acc0, fun) {return this._partLoop(varr,sIdx,eIdx, acc0, fun, true);},
	loopDsc:function(varr, acc0, fun) {return this._loop(varr, acc0, fun, false);},

	each:function(obj, acc0, fun){
		var acc = acc0,idx = 0;
		for (p in obj){acc = fun(acc, obj[p], p, idx);idx+=1;}
		return acc;
	},

	isFound:function(elem, arr){return this.loop(arr, false, function(acc, item){return acc || (elem==item);});},
	isSameArray:function(arr1, arr2){
		if (arr1==null && arr2==null){return true;}
		if (arr1==null || arr2==null || arr1.length!=arr2.length){return false;}
		return this.loop(arr1, true, function(acc, item){return acc && IX.Utils.isFound(item,arr2);});
	},
	compact: function(arr) {return IX.Utils.loop(arr, [], function(acc, item) {
		if (item){acc.push(item);}
		return acc;
	});},
	pushx:function(acc, item){acc.push(item);return acc;},
	splice:function(arr, start, deleteCount, insertArray) {
		var count = isNaN(deleteCount)?1:deleteCount;
		if (start<0 || start>arr.length || count<0 || (start+count)>arr.length){return [];}
		return [].concat(arr.slice(0, start), insertArray?insertArray:[], arr.slice(start+count));
	},
	_sortByPreOrderTravelTree:function(xarr, posId, posPid, posIdx){
		var arr = this.loop(xarr, [], function(acc, item){
			var pid = item[posPid];
			if (isEmpty(pid) || pid=="0" || pid.charAt(0)=="r"){
				item[posPid]="";
			}
			acc.push(item);
			return acc;
		});
		var narr = [];
		var a, b;
		for (var i=0;i<arr.length; i+=1){
			a = arr[i];
			for(var j=0;j<narr.length; j+=1){
				b = narr[j];
				if ((b[posPid] == a[posPid] && b[posIdx]>a[posIdx]) || (b[posPid] == a[posId])) {
					// A is B's previous sibling or parent, insert A before B;
					narr =this.splice(arr, j, 0, [a]);
					a = null;
					break;
				}
			}
			if (a!=null){narr.push(a);}
		}
		return narr;
	},
	sort:function(arr, posId, posPid, posIdx, stype){ //stype: 0:PreOrderTravelTree; 1:MidOrderTravelTree; 2:PostOrderTravelTree
		if (!stype) {return this._sortByPreOrderTravelTree(arr, posId, posPid, posIdx);}
		return arr;
	}
};

IX.Net ={
	_getRequest:function(){
		if (window.XMLHttpRequest) {return new XMLHttpRequest();}
		if (window.ActiveXObject){return new ActiveXObject("Microsoft.XMLHTTP");}
		return null;
	},
	_doGet:function(request, durl, queryString){
		request.open("GET", durl, true);
		request.send(queryString);
	},
	_doPost:function(request, durl, queryString){
		request.open("POST", durl, true);
		request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		request.send(queryString);
	},
	loadFile:function(durl, cbFun){
		var request = this._getRequest();
		if(!request){alert("unsupport AJAX. Failed");return;}
		request.onreadystatechange  = function(){
			if (request.readyState == 4){
				if (request.status == 200){if (cbFun){cbFun(request.responseText);}}
				else { alert("There was an error: (" + request.status + ") " + request.statusText);}
			}
		}
		this._doGet(request, durl, "");
	},
	_loadJsFilesInSeq:function(jsFiles, nextFun){
		var idx =0;
		var fun = function(){
			IX.Net.loadFile(jsFiles[idx], function(rspTxt){
				eval(rspTxt);
				idx +=1;
				return (idx>=jsFiles.length)?nextFun():fun();
			});
		};
		(jsFiles && jsFiles.length>0)?fun():nextFun();
	},
	loadJsFiles:function(jsFiles, nextFun, mode){
		//if (!mode || mode=="seq" ){
			this._loadJsFilesInSeq(jsFiles, nextFun);
		//}
	},
	tryFn:function(fnName, argList,dependencyConfig){
		if (!IX.nsExisted(fnName)){
			if (!dependencyConfig){
				return;
			}		
			if (IX.isFn(dependencyConfig.beforeFn)){
				dependencyConfig.beforeFn();
			}
			var cssFiles = dependencyConfig.cssFiles;
			if (cssFiles && cssFiles.length>0){
				for (var i=0; i<cssFiles.length; i++){
					this.loadCss(cssFiles[i]);
				}
			}
			this._loadJsFilesInSeq(dependencyConfig.jsFiles, function(){
				setTimeout(function(){				
					IX.execute(fnName, argList);
					if (IX.isFn(dependencyConfig.afterFn)){
						dependencyConfig.afterFn();
					}
				},dependencyConfig.delaySecond || 300);
			});
			return;
		}
		IX.execute(fnName, argList);
	},
	loadCss:function(cssFile){
		var headObj = document.getElementsByTagName("head")[0];
		var cssNode = document.createElement('link');
		cssNode.type = 'text/css';
		cssNode.rel = 'stylesheet';
		cssNode.href = cssFile;
		cssNode.media = 'screen';
		headObj.appendChild(cssNode);
	}
};

IX.Xml = {
	parser:function(str){
		if(isEmpty(str)){str="";}
		var doc = null;
		if (window.DOMParser) {
			var p = new DOMParser();
			doc = p.parseFromString(str, "text/xml");
		}else if (window.ActiveXObject){
			doc=new ActiveXObject("Microsoft.XMLDOM");
			doc.async="false";
			doc.loadXML(str);
		} else {
			alert("this browser can't support XML parser.");
			return null;
		}
		return doc;
	},
	getXmlString:function(xmlDoc){
		if(xmlDoc==null){xmlDoc=this.parser();}
		if(document.implementation && document.implementation.createDocument) {
			return (new XMLSerializer()).serializeToString(xmlDoc);
		}else if (window.ActiveXObject){
			return xmlDoc.xml;
		} else {
			alert("this browser can't support XML parser.");
		}
		return "";
	},
	duplicate:function(xmlDoc){
		return this.parser(this.getXmlString(xmlDoc));
	}
};

IX.I18N = {
	load:function(path, cbFun){IX.Net.loadFile(path, function(rspTxt){eval(rspTxt);cbFun();});}
};

IX.Window = {
	stopEvent: function(ev) {
		//if (isMSIE()) {
			ev.cancelBubble = true;
			ev.returnValue = false;
		//} else {
		//	ev.preventDefault();
		//	ev.stopPropagation();
		//}
	},
	getScrollingPos:function(){
		var position = [0, 0];
		if ("pageYOffset" in window){
			position = [window.pageXOffset,window.pageYOffset];
		} else if ("scrollTop" in document.documentElement && (document.documentElement.scrollTop > 0 || document.documentElement.scrollLeft > 0)){
			position = [document.documentElement.scrollLeft,document.documentElement.scrollTop];
		} else if ("scrollTop" in document.body){
			position = [document.body.scrollLeft,document.body.scrollTop];
		}
		return position;
	},
	_getHelpDiv:function(){
		var divId ="ix_window_help_div";
		var div =  $X(divId);
		if (!div){
			div = document.createElement('div');
			div.id = divId;
			document.body.appendChild(div);
		}
		return div;
	},	
	getInnerSize:function(){
		var size = [];
		if(isMSIE()){ // be careful: on IE: the offsetHeight  may be zero when start up;
			var div = this._getHelpDiv();
			size = [div.offsetWidth, div.offsetHeight];
		} else {size = [window.innerWidth, window.innerHeight];}
		return size;
	}
};

function $X(id){return document.getElementById(id);}
function $XS(id){return $X(id).style;}
function $XA(iterable) {
	if (!iterable) return [];
	if (iterable.toArray) {return iterable.toArray();}
	else {
		var results = [];
		for (var i = 0, length = iterable.length; i < length; i++){results.push(iterable[i]);}
    		return results;
  	}
}
function $XH(el, html){
	var oldEl = typeof el === "string" ?$X(el) : el;
	var newEl = oldEl.cloneNode(false);
	newEl.innerHTML = html;
	oldEl.parentNode.replaceChild(newEl, oldEl);
	return newEl;
}

Object.extend = function(dst, src) {for (var p in src) {dst[p] = src[p];}return dst;};
Object.inherit = function(){return IX.Utils.loop($XA(arguments), new Object(), function(acc, item){return Object.extend(acc, item);});};
Math.inRange=function(i, min, max){return i>=min && i<max;};

Object.extend(String.prototype, {
	trim:function(){return this.replace(/(^\s*)|(\s*$)|\r|\n/g, "");},
	replaceAll:function(os, ns) {return this.replace(new RegExp(os,"gm"),ns);},
	loopReplace:function(varr){return IX.Utils.loop(varr, this, function(acc, item){return acc.replaceAll(item[0], item[1]);});},
	stripTags:function() {return this.replace(/<\/?[^>]+>/gi, '');},
	unhtml:function(){return this.replaceAll("<", "&lt;");},

	inTag:function(tagName, params){//params should like [[pramName, paramValue],...
		return "<"+tagName+ IX.Utils.loop(params, '', function(acc, item){return acc+ ' ' + item[0] + '="' +item[1] +'"';})+">" + this + "</"+tagName+">";
	},
	inPureTag:function(tagName, params){return ("<![CDATA[" + this + "]]>").inTag(tagName, params);},
	stripScripts: function() {return this.replace(new RegExp( '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', 'img'), '');},
	stripFormTag:function(){return this.replace(new RegExp( '(?:<form.*?>)|(?:<\/form>)', 'img'), '');},
	trunc:function(len){return (this.length>len)?(this.substring(0, len-3)+"..."):this;},
	tail:function(len){return (this.length>len)?(this.substring(this.length-len)):this;},
	strip:function() {return this.replace(/^\s+/, '').replace(/\s+$/, '');},
	isSpaces:function() {return (this.replace(/(\n)|(\r)|(\t)/g, "").strip().length==0);},
	multi:function(len){var str = "";for(var i=0;i<len; i+=1){str +=this;} return str;}
});

Function.prototype.bind = function() {
	var __method = this, args = $XA(arguments), object = args.shift();
	return function() {return __method.apply(object, args.concat($XA(arguments)));}
};

IX.Utils.UUID = {
	generate:function() {
		var arr = [];
		for (var i=0; i<4; i+=1){arr[i] =("0".multi(8)+Math.floor( (Math.random() % 1) * Math.pow(2, 32) ).toString(16)). tail(8);}
		return  [arr[0], arr[1].substring(0,4), "4"+arr[1].substring(5, 8), "8"+arr[2].substring(1, 4), arr[2].substring(4, 8)+ arr[3]].join("");
	}
};

///////////////////////////////////////////////////// UTILS finished///////////
IX.Utils.Test = {
	detectAttrs:function(obj, checkFun, injector) { // injector: function(result, name, value)
		var count = 0;
		return  IX.Utils.each(obj, "", function(acc, item, nc){
			//log("DET:"+ ":A::" +count + ":B::" + (checkFun(item,name)) +":C::" + nc);
			try{if (checkFun(item,nc)){
				count += 1;
				return injector(acc,  nc, item) + (count%5==4?"\r\n":"");
			}}catch(e){alert(e);}
			return acc;
		});
	},
	_list:function(obj, matchor, type){
		if (type!="fun" && isString(obj)){return "String:" + obj.toString();}
		return (type!="fun"?"Props:":"Funcs:") + this.detectAttrs(obj, function(o, p){
			return (((type!="fun" && !isFunction(o)) || (type=="fun" && isFunction(o))));
		}, function(r, n, v) { return r + n + (type!="fun"?(':"' + (""+v).trunc(60) + '" '):"")+ ", ";});

	},
	listProp:function(obj, matchor) {return this._list(obj, matchor, "");},
	listFun:function(obj, matchor) {return this._list(obj, matchor, "fun");}
};
var IXLoggerId = null;
function initLog(logPanelId){ IXLoggerId = logPanelId;}
function log(s){
	var logDiv = $X(IXLoggerId);
	if(logDiv){
		logDiv.parentNode.style.display="block";
		logDiv.parentNode.style.overflowY = "scroll";
		logDiv.innerHTML+= (""+s).replaceAll("<","&lt;").replaceAll("\n", "<br>")+"<br>";
	}
}
//////////////////////////////////////////////////////////////////////////////
IX.Class={create:function(){return function() {this.initialize.apply(this, arguments);}}};
IX.Empty = IX.Class.create();
IX.Empty.prototype.initialize=function(){};
//////////////////////////////////////////////////// TEST-Utils finished////////
IX.Object = {
	getId:function(){return this._id;},
	getType:function(){return this._type;}
};
IX.IModel = {};// Model Interface;
IX.IModel.Tree={
	__Tree_VIRTUAL_FUN: ["__getNodeClass", "__inheritAttrib", "__genIdx"],

	__INVISIBLE:0,
	__VISIBLE:1,

	__COLLAPSE:0,
	__EXPAND_CHILD:1,
	__EXPAND_ALL:2,
// private interface ;
	__genIdx:function(idx){return idx?idx:0;},
	__initTreeIdx:function(idx) {
		this._level = this._isRoot?-1:((this._parent._level*1)+1);
		this._idx = this.__genIdx(idx);
	},
	__initTreeParent:function(pnode, idx){
		var isRoot = (pnode ===null || pnode===this);
		this._parent = isRoot?this:pnode;
		this._root = isRoot?this:pnode._root;
		this._isRoot = isRoot;
		this.__initTreeIdx(idx);
		this._subNodes = [];
	},
	__updateTreeAttrib:function(){
		var pes = this._parent._expand_stat;
		this._expand_stat = this._isRoot?2:(pes==2?2:0);
		this._visible = this._isRoot?1:(pes>0?1:0);
	},
	__initTreeAttrib:function(){
		this.__updateTreeAttrib();
		this.__inheritAttrib();
	},
	__initTreeChilds:function(noc, childDesc){
		IX.Utils.loop(childDesc, [], function(acc, item, index) {
			var mc = this.__getNodeClass();
			this._subNodes.push(new mc(this, index, item));
		}.bind(this));
		this._noc =noc>0?noc:0;
	},
	__updIdx:function(){this.loopDeep(0, function(acc, item, idx) {
		//log ("UPD IDX:" + item._id + ":" + idx + ":" + item._parent._id);
		item.__initTreeIdx(idx);
	});},

	__ifOutOfChilds:function(idx){return (this._noc<idx || idx<0);},
	__getNewChildIdx:function(){return this._noc;},
	__upd4NewChild:function(node){
		node._parent = this;
		this._noc = this._noc*1 + 1;
		this.__updIdx();
	},
	__doExpand:function(es){
		this._expand_stat = es<0?0:es;
		this[(es==2 || es<0)?"loopDeep":"loop"](0, function(acc, item){item.__updateTreeAttrib();});
	},
// protected interface ;
	_init_Tree:function(pnode, idx, noc, childDesc){
		this.__initTreeParent(pnode, idx);
		this.__initTreeAttrib();
		this.__initTreeChilds(noc, childDesc);
	},
	_upd_Tree:function(noc, childDesc){
		IX.Utils.loop(childDesc, [], function(acc, item, index) {
			if (index<this._noc){
				this._subNodes[index].update(item);
			} else {
				var mc = this.__getNodeClass();
				this._subNodes.push(new mc(this, index, item));
			}
		}.bind(this));
		this._noc =noc>0?noc:0;
	},
	_delChild:function(idx){
		if (this.__ifOutOfChilds(idx) || idx == this._noc) {return false;}
		log ("del child :" + idx +  ":"+ this._subNodes[idx]._id);
		this._subNodes = IX.Utils.splice(this._subNodes, idx);
		this._noc -=1;
		this.__updIdx();
		return true;
	},
	_newChild:function(node){
		this._subNodes[this._noc]=node;
		this.__upd4NewChild(node);
		return true;
	},
	_insChild:function(node, idx){
		if (this.__ifOutOfChilds(idx)){return false;}
		log ("ins child :" + idx +  ":"+ node._id);
		this._subNodes = IX.Utils.splice(this._subNodes, idx, 0, [node]);
		this.__upd4NewChild(node);
		return true;
	},
	_move:function(dst, dtype){ // dtype: 0:child; 1: above sibling; 2: below sibling; 3:parent
		if (this._parent._id == dst._id && dtype == 0) {return;}
		log ("move :" +  this._id +" as "+ dst._id +" : " + dtype + " ::::: parent:" + this._parent._id);
		// remove from older;
		this._parent._delChild(this._idx);
		// add to new parent
		var pnode = dst;
		var idx = dst.__getNewChildIdx();
		if (dtype>0) { // not child
			idx = dst._idx;
			pnode = dst._parent;
			if (dtype==3) {
				for (var i=idx; i<pnode._noc; i+=1) {this._newChild(pnode._subNodes[i]);}
				pnode._subNodes.length = idx;
				pnode._noc =  idx;
				idx = pnode._idx +1;
				pnode = pnode._parent;
			} else if (dtype==2) {idx +=1;}
		}
		pnode._insChild(this, idx);
	},
// public interface ;
	// loop all sons to call fun
	loop:function(acc0, fun) {return IX.Utils.loop(this._subNodes, acc0, fun);},
	// loop part of sons to call fun
	loopPart:function(acc0, fun, sIdx, eIdx){return IX.Utils.partLoop(this._subNodes, sIdx, eIdx, acc0, fun);},
	// loop all sons to call fun by descend
	loopDsc:function(acc0, fun) {return IX.Utils.loopDsc(this._subNodes, acc0, fun);},
	// loop all childs to call fun
	loopDeep:function(acc0, fun){return this.loop(acc0, function(acc, item, idx){return item.loopDeep(fun(acc, item, idx), fun);});},
	// loop itself and  all childs to call fun
	loopAll:function(acc0, fun){return this.loopDeep(fun(acc0, this, this._idx), fun);},

	getLevel:function(){ return this._level;},
	getParent:function(){return this._parent;},
	getRoot:function(){return this._root;},
	isRoot:function(){return this._level == -1;},
	hasChild:function(){return this._noc >0;},
	numOfChilds:function(){return this._noc;},
	isVisible:function(){return this._visible==1;},
	ifExpanded:function(){return this._expand_stat>0;}
};

IX.IModel.MutliPage={
	__MultiPage_VIRTUAL_FUN: ["__getItemList", "__loadItemList", "__ifLoaded"],

	_getMaxPageNo:function(){return Math.floor((this._noc-(this._noc>0?1:0))/this._noipp);},
	_getCurSIdx:function(){return this._curPIdx * this._noipp;},
	_getCurEIdx:function(){return Math.min((this._getCurSIdx() + 1* this._noipp), this._noc)-1;},
	_setCurPageIdx:function(idx){this._curPIdx = idx;},
	_setNoipp:function(num){this._noipp = num;},

	_init_MultiPage:function(total, curPidx, numOfItemsPerPage){
		this._noc = total;
		this._curPIdx = curPidx;
		this._noipp = numOfItemsPerPage;
	},
	_loopPage:function(acc, fun){
		var acc0 = acc;
		for (var i=this._getCurSIdx(); i<=this._getCurEIdx(); i+=1){
			acc0 = fun(acc0,this.__getItemList()[i], i);
		}
		return acc0;
	},
	loopPage:function(acc, fun){
		return this._loopPage(acc, function(acc0, item, i) {
			return item?fun(acc0, item, i):acc0;
		});
	},
	ifPageLoaded:function(fun){
		return this._loopPage(true, function(acc0, item, i) {
			return (item!=null) && fun(acc0, item, i);
		});
	},
	getTotal:function(){return this._noc;},
	isMutilPage:function(){return this._noc>this._noipp;},
	isLastPage:function(){return this._curPIdx ==this._getMaxPageNo();},
	isFirstPage:function(){
		return this._curPIdx ==0;
	},
	jumpTo:function(wh){
		var v = [this._getMaxPageNo(), this._curPIdx, wh.substring(0,1)]; // Max, cur, op;
		var idxs = {f:0, l:v[0],p:Math.max(v[1]-1, 0), n: Math.min(v[1]*1+1, v[0])};
		var idx  =(v[2] in idxs)?idxs[v[2]]:0;
		if (v[1]==idx) {return false;}
		this._curPIdx = idx;
		var ifLoaded = this.__ifLoaded();
		if (!ifLoaded){this.__loadItemList();}
		return ifLoaded;
	},

	getPIArray:function(){return [this._noc, this._noc==0?0:(this._getCurSIdx()+1), this._getCurEIdx()+1];},
	getCurPageItem:function() {return this.loopPage([], IX.Utils.pushx);},
	getLastChild:function(){return this._subNodes[this._noc-1];}
};

/////////////////////////// MODEL Interface finished///////////////////
IX.IView = {};
IX.IView.View  = Object.inherit(IX.Object, {
	__View_VIRTUAL_FUN: ["getHandlerFun"],
	__DISPLAY:"",

	__JFunTmp:"#_HN#('#_FN#',#_PARAMS#);",
	__genFStr:function(fname, params){return this.__JFunTmp.loopReplace([["#_HN#", this.getHandlerFun()],["#_FN#", fname],["#_PARAMS#", params]]);},
	__genFunStr:function(fname){return this.__genFStr(fname, "'#ID#'");},
	__genEventFunStr:function(fname){return this.__genFStr(fname, "[event, '#ID#', '#PARAM#' ]");},

	__FLinkTmp:'<a #_PROPS# href="javascript:#_FUN#">#_NAME#</a>',
	__renderFLink:function(fname,lname, propsStr){return this.__FLinkTmp.loopReplace([["#_FUN#", this.__genFunStr(fname)],["#_NAME#", lname],["#_PROPS#", propsStr?propsStr:""]]);},

	__OpTmp:'[#_OP#]',
	__renderAOp:function(op){return this.__OpTmp.replace("#_OP#", this.__renderFLink(op[0], op[1]));},
	__renderOps:function(oplist, xStr){return IX.Utils.loop(oplist, "", function(acc, item){return acc+this.__renderAOp([item.toLowerCase()+(isEmpty(xStr)?"":xStr),item]);}.bind(this));},
	__renderOpList:function(oplist){return IX.Utils.loop(oplist, "", function(acc, item){return acc+this.__renderAOp(item);}.bind(this));},

	__ALinkTmp:'<a #_PROPS# href="#_LINK#">#_NAME#</a>',
	__renderALink:function(aname,alink, propsStr){return this.__ALinkTmp.loopReplace([["#_LINK#", alink],["#_NAME#", aname],["#_PROPS#", propsStr?propsStr:""]]);},

	__UlTmp:'<ul #_PROPS#>#_ITEMS#</ul>',
	__renderUl:function(items, propsStr){return this.__UlTmp.replace("#_ITEMS#", items).replace("#_PROPS#", propsStr?propsStr:"");},

	__LiTmp:'<li #_PROPS#>#_ITEM#</li>',
	__renderLi:function(item, propsStr){return this.__LiTmp.replace("#_ITEM#", item).replace("#_PROPS#", propsStr?propsStr:"");},

	__IconTmp: '<img src="#_IMG#" alt="#_ALT#" class="#_CLASS#" #_PROPS#/>',
	__renderAIcon:function(img,alt, clz, propsStr){return this.__IconTmp.loopReplace([["#_IMG#", img],["#_ALT#", alt],["#_CLASS#", clz], ["#_PROPS#", propsStr?propsStr:""]]);},
	__renderIcon:function(img, alt, clz){return this.__renderAIcon(img,alt, clz, "");},
	__renderFIcon:function(img,alt, clz, fname){return this.__renderFLink(fname, this.__renderAIcon(img,alt,clz));},

	__DivTmp: '<div class="#_CLASS#">#_INN#</div>',
	__renderADiv:function(clz,inn){return this.__DivTmp.replace("#_CLASS#", clz).replace("#_INN#", inn);},

	_refresh:function(node, pf) {if (node){node.innerHTML = pf;}},
	_display:function(node,isShow){if(node){node.style.display=isShow?this.__DISPLAY:"none";}},
	_createDiv:function(id, className){
		var divNode = document.createElement('div');
		divNode.className = className;
		divNode.id = id;
		return divNode;
	},
	_getDiv:function(pnode, className, id, befnode){
		var divNode = $X(id);
		if(!$X(id)){
		 	divNode = this._createDiv(id,  className);
			if(pnode){
				if(befnode){pnode.insertBefore(divNode, befnode);}
				else {pnode.appendChild(divNode);}
			}
		}		
		return divNode;
	},

	_initData:function(id){this._id = id;}
});

// state transaction: A-->B--> ....-->A
IX.IView.STView = Object.inherit(IX.IView.View, {
	__ST_VIRTUAL_FUN: ["_getSTName", "_getSTFun", "_actST", "_getSTClz"],
	__STTmp:'<span id="st_#ID#_stCtl" class="#CSS#">#ST#</span>',

	_getSTFun:function(){return this._st_stat?"hide":"show";},
	_actST:function(){},
	__renderSTOp:function(){return this.__renderAOp([this._getSTFun(), this._getSTName()]);},
	render:function(){return this.__STTmp.replace("#ST#", this.__renderSTOp()).replace("#CSS#", this._getSTClz()).replaceAll("#ID#", this._id);},
	updView:function(stat){this._refresh($X('st_'+this._id+ '_stCtl'), this.__renderSTOp().replaceAll("#ID#", this._id));},
	enable:function(isEnabled){$X('st_'+this._id+ '_stCtl').enabled = isEnabled;},
	setStat:function(stat){this._st_stat = stat;},
	getStat:function(){return this._st_stat;},
	stCtl:function(stat){
		this.setStat(stat);
		this.updView();
		this._actST(stat);
	},
	_initST:function() {this._st_stat = 1;}// only used for first time;
});

IX.IView.ImageSTView = Object.inherit(IX.IView.STView, {
	__ST_VIRTUAL_FUN: ["_getSTImage", "_getSTName", "_getSTFun", "_actST", "_getSTClz"],
	__STTmp:'<span id="st_#ID#_stCtl">#ST#</span>',
	__renderSTOp:function(){return this.__renderFIcon(this._getSTImage(), this._getSTName(), this._getSTClz(),  this._getSTFun());}
});

IX.IView.Window =Object.inherit(IX.IView.View, {
	__Window_VIRTUAL_FUN: ["getHandlerFun", "__getCSS", "__getLayerCSS"],

	__POP: 0,
	__DIALOG:1,
	__VIEW:2,

	__DISPLAY:"block",

	_init:function(id, pid, type) {
		this._initData(id);
		this._pid = pid;
		this._type=type;
		this._createLayer();
		this._createWin();
	},

	_createWin:function(){this._win = this._getDiv(this._layer,this.__getCSS(), this._id);},
	_createLayer:function(){this._layer =this._getDiv(document.body,this.__getLayerCSS(), this._pid);},
	remove:function() {this._layer.removeChild(this._win);},
	__getViewWindow:function(){return this._layer;},
	_show:function(v) {this._display(this.__getViewWindow(), v);},
	show:function(){this._show(true);},
	hide:function(){this._show(false);}
});
IX.IView.Popup = Object.inherit(IX.IView.Window, {
	__Popup_VIRTUAL_FUN:["render"],
	__getViewWindow:function(){return this._win;},

	_initBase:function(id, pid, nohide){
		this._init(id, pid, this.__POP);
		if(!nohide) {this._win.onmouseout= function(evt){ this.tryHide(evt);}.bind(this);}
	},
	getAbosulatePos:function(node) {
		log("ABS:" + node.nodeName+":"+ node.id + ":x:"+ node.offsetLeft + ":"+node.offsetTop+ ":"+ node.offsetWidth + ":"+ node.offsetHeight + ":Z:"+ node.scrollLeft + ":"+node.scrollTop+ ":"+ node.scrollWidth + ":"+ node.scrollHeight);
		if (node.nodeName=='BODY' || node.nodeName=="HTML"|| node.id == this._pid || node== this._offsetParent ) {return [0,0];}
		var wh = this.getAbosulatePos(node.offsetParent);
		if ("scrollTop" in node) {
			wh[0] -= node.scrollLeft;
			wh[1] -= node.scrollTop;
		}
		return [node.offsetLeft*1+wh[0]*1,node.offsetTop*1+wh[1]*1];
	},
	getPos:function(node) {
		var t = this._win.style.display;
		this._show(true);
		this._offsetParent = this._win.offsetParent;
		var wh = this.getAbosulatePos(node);
		log("POS:" + wh + ":x:" + ((this._offsetParent==null)?"null":( this._offsetParent.nodeName + ":" + this._offsetParent.id)));
		wh[0] += node.offsetWidth;
		this._win.style.display = t;
		return wh;
	},
	_createLayer:function(){this._layer = $X(this._pid);},
	_setPanelPos:function( x, y, w){
		var style = this._win.style;
		style.left=x+"px";
		style.top=y+"px";
		style.width= w+ "px";
	},
	show:function(type, node, x, y) {
		this.setPanelPos(type, x, y);
		this._refresh(this._win, this.render(type, node));
		this._show(true);
	},
	_checkDstIsSelf:function(node){
		if (!node){return false;}
		if (node.id==this._id){return true;}
		return this._checkDstIsSelf(node[isMSIE()?"parentElement":"offsetParent"]);
	},
	tryHide:function(evt){
		if (this._win.style.display=="none"){return;}
		if (!evt) {evt=window.event;}
		if (!this._checkDstIsSelf(evt[isMSIE()?"toElement":"relatedTarget"])) {this.hide();}
	}
});
IX.IView.Dialog=Object.inherit(IX.IView.Window, {
	__Dialog_VIRTUAL_FUN:["open", "close", "_resize"],
	_initDialog:function(id, pid){this._init(id,pid, this.__DIALOG);},
	_resize:function(){},
	_resetHeight:function(){
		var h = 0;
		if(isMSIE()){
			h = document.body.scrollHeight;
		}
		else{
			h = document.documentElement.scrollHeight;
		}
		this._layer.style.height = (h==0)?"100%":(h+"px");
	},
	show:function() {
		this._show(true);
		this._resetHeight();
	},
	resize:function(){
		if (this._layer.style.display=="none"){return;}
		this._resetHeight();
		this._resize();
	}
});

IX.IView.ModalDialog= {
	_open:function(url, param, w, h) {
		var href = url + "?" + param + "&t=" + (new Date()).getTime();
		var f = function(x,d){return Math.max(0, x/2-d);};
		var wh = [f(screen.availWidth-w,80), f(screen.availHeight-h, 10)];
		if ("showModalDialog" in window){
			return window.showModalDialog(href, window,
				"dialogHeight: " + h + "px; dialogWidth: " + w + "px; dialogTop:"+ (wh[0]) +"px;dialogLeft:" + (wh[1]) + "px;"
				+"edge: Raised; center: yes; status: no; help: no; close:no;resizable: yes; dialogHide:yes;");
		} else {
			return window.open(href, "_blank",
				"width=" + w + "px,height=" + h + "px,top="+ wh[1] +"px,left=" + wh[0] + "px,"
				+"menubar=no,toolbar=no,location=no,center=yes,scrollbars=no,close=no;status=yes,statusbar=yes,modal=yes,resizable=yes, titlebar=no,dialog=yes");
		}
	}
};

/////////////////////////////// View Interface endes ! //////////////////
IX.ViewContainer = IX.Class.create();
Object.extend(IX.ViewContainer.prototype, {
	show:function(pf) {this._container.innerHTML = pf;},
	resize:function(w,h){
		this._container.style.width = w+"px"
		if(h>0){this._container.style.height = h +"px";}
	},
	replace:function(os, ns){this.show(this._container.innerHTML.replaceAll(os, ns));},
	insert:function(src, dst, pos) {
		if(pos=="before"){
			if (dst!=null){this._container.insertBefore(src,dst);}
			else {this._container.appendChild(src);}
		}
	},
	remove:function(node){if(node) {this._container.removeChild(node);}},
	initialize: function(container) {this._container = container;}
});
