﻿/*
Class对象 1.0.0.0 Beta
接受参数:无
返回类型:无

应用技术：
javascript,ajax

制作人：
黄若儒 Roy.Huang

注意:
1、全部采用静态写法，方便继承且减少资源耗损
2、本类为全局管理类（类似于工厂类），用于全局控制整个包系统中的创建包、获取包、设置命名空间、获取类、动态导入类、继承等
*/
var Class=function(){};

Class.PACKAGE_PATH="/SCRIPT/";//默认包路径
Class.SCRIPT_ENCODE="utf-8";//script默认编码
Class.SCRIPT_TYPE="text/javascript";//script默认类型
Class.SCRIPT_LANGUAGE="javascript";//script默认语言
Class.AJAX_VERSIONS=["MSXML2.XMLHttp.5.0","MSXML2.XMLHttp.4.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp","Microsoft.XMLHttp"];//ajax创建版本
Class.SCRIPT_LOADED_PATHS=[];//已经用加载过的js文件地址

/**
*创建一个命名空间包
*@param pn 命名空间包路径
*@return 命名空间包;
*/
Class.createPackage=function(pn){
	var p=pn.split(".");
	var o=window;
	for(var i=0;i<p.length;i++){
		if(!o[p[i]])
			o[p[i]]={};
		o=o[p[i]];
	}
	return o;
};

/**
*返回一个命名空间包
*@param pn 命名空间包名
*@return 命名空间包
*/
Class.getPackage=function(pn){
	var p=null;
	try{
		p=eval(pn);
	}
	catch(e){
		this.onError(4,pn);
	}
	return p;
};

/**
*为一个类设置命名空间
*@param pn 命名空间包名
*/
Class.setNameSpace=function(pn,c){
	var p=pn.lastIndexOf(".");
	var f=pn.substring(p+1);
	p=this.createPackage(pn.substring(0,p));
	if(p[f] && p[f]!=c)
		this.onError(2,pn);
	else
		p[f]=c;
};

/**
*通过命名空间获取一个类
*@param n:类名命空间,l:是否动态加载
*@return 类对象
*/
Class.getClass=function(n,l){
	var c=null;
	try{
		c=eval(n);
		if(!c) throw "Can't Load";
	}
	catch(e){
		try{
			if(l!=false){
				this.loadClass(n);
				c=eval(n);
				if(!c) throw "Can't Load";
			}
			else
				throw "Can't Load";
		}
		catch(e){
			this.onError(5,n);
		}
	}
	return c;
};
 
/**
*根据命名空间加载类
*@param ns:类名命名空间(多个用,分隔),fn:异步加载完成要执行的方法
*/
Class.loadClass=function(ns,fn){
	ns=ns.split(",");
	for(var i=0;i<ns.length;i++)
		ns[i]=this.NameSpaceToPath(ns[i]);
	this.loadFile(ns.join(","),fn);
};

/**
*根据文件地址加载类
*@param ps:文件名(多个用,分隔),fn:异步加载完成要执行的方法
*/
Class.loadFile=function(ps,fn){
	var loadList=[];
	var pa=ps.split(",");
	for(var i=0;i<pa.length;i++){
		var pn=pa[i];
		pn=this.relPathToAbsPath(pn);
		if(!this.isLoaded(pn))
			loadList.push(pn);
	}
	if(loadList.length<=0 && fn)
		fn();
	else if(loadList.length>0)
		this.loadFileByAjax(loadList.join(","),fn);
};

/**
*通过ajax加载类
*@param ps:要加载的文件名(多个用,分隔),fn:加载后执行的方法
*/
Class.loadFileByAjax=function(ps,fn){
	try{
		var base=this;
		var loadeds=0;
		var asynchronous=fn?true:false;
		var ajax=null;
		var loadList=ps.split(",");
		for(var i=0;i<loadList.length;i++){
			base.SCRIPT_LOADED_PATHS.push(loadList[i]);
			ajax=base.createAjax();
			ajax.onreadystatechange=base.bind(function(){
				if(this.readyState==4 && fn){
					if(this.status==200 || this.status==0){
						base.setScript(this.responseText);
						if(++loadeds>=loadList.length)
							fn();
					}
					else
						base.onError(14,loadList[i]);
				}
			},ajax);
			ajax.open("get",loadList[i],asynchronous);
			ajax.send(null);
			if(!asynchronous){
				if(ajax.status==200 || ajax.status==0)
					base.setScript(ajax.responseText);
				else
					throw 14;
			}
		}
	}
	catch(e){
		this.onError(14,ps);
	}
};

/**
*全继承
*@param s:子对象,p父对象
*/
Class.extend=function(s,p){
	s.prototype=new p();
	s.prototype.constructor=s;
	this.extendStatic(s,p);
};

/**
*继承Prototype
*@param s:子对象,p父对象
*/
Class.extendPrototype=function(s,p){
	for(var i in p.prototype)
		if(!s.prototype[i])
			s.prototype[i]=p.prototype[i];
};

/**
*继承Static
*@param s:子对象,p父对象
*/
Class.extendStatic=function(s,p){
	for(var i in p)
		if(i.toLowerCase()!="prototype" && !s[i])
			s[i]=p[i];
};

/**
*创建ajax对象
*@return ajax对象
*/
Class.createAjax=function(){
	var ajax=null;
	try{
		ajax=new XMLHttpRequest();
		if(ajax.overrideMimeType)
			ajax.overrideMimeType("text/xml");
	}
	catch(e){
		for(var i=0;i<this.AJAX_VERSIONS.length;i++){
			try{
				ajax=new ActiveXObject(this.AJAX_VERSIONS[i]);
			}
			catch(e){}
		}
	}
	if(!ajax) this.onError(8);
	return ajax;
};

/**
*设置script
*@param str javascript代码
*/
Class.setScript=function(str){
	var h=document.getElementsByTagName("head")[0];
	var script=document.createElement("script");
	script.type=this.SCRIPT_TYPE;
	script.language=this.SCRIPT_LANGUAGE;
	script.charset=this.SCRIPT_ENCODE;
	script.text=str;
	h.appendChild(script);
};

/**
*将命名空间转为文件地址
*@param n 命名空间名
*@return js文件路径
*/
Class.NameSpaceToPath=function(n){
	n=this.replaceAll(n,"\\.","/");
	n=this.PACKAGE_PATH+n+".js";
	return n;
};

/**
*将相对地址转为绝对地址
*@param rp 相对地址
*@return 绝对地址
*/
Class.relPathToAbsPath=function(rp){
	var rst=rp;
	var p=-1;
	try{
		rst=this.replaceAll(rst,"\\\\","/");
		if(rst.indexOf("/")!=0 && rst.indexOf("http://")!=0){
			var np=location.pathname;
			np=this.replaceAll(np,"\\\\","/");
			if(np.lastIndexOf("/")!=np.length-1)
				np=np.substring(0,np.lastIndexOf("/")+1);
			rst=np+rst;
		}
		p=rst.indexOf("../");
		while(p>0){
			var ps=rst.substring(0,p);
			ps=ps.substring(0,ps.substring(0,ps.lastIndexOf("/")-1).lastIndexOf("/")+1);
			rst=ps+rst.substring(p+3,rst.length);
			p=rst.indexOf("../");
		}
		rst=this.replaceAll(rst,"\\./","");
		rst=this.replaceAll(rst,"http://"+location.host,"");//针对firefox,将本站域名也去除
	}
	catch(e){
		this.onError(12,rp);
	}
	return rst;
};

/**
*判断该js文件是否已经加载
*@param n 文件加载路径
*@return true/false
*/
Class.isLoaded=function(n){
	for(var i=0;i<this.SCRIPT_LOADED_PATHS.length;i++)
		if(this.SCRIPT_LOADED_PATHS[i]==n)
			return true;
	var s=document.getElementsByTagName("script");
	for(var i=0;i<s.length;i++){
		if(s[i].src && s[i].src.length>0 && this.relPathToAbsPath(s[i].src)==n)
			return true;
	}
	return false;
};

/**
*对象转置执行
*@param s:要执行的方法,t执行对象
*@return 方法
*/
Class.bind=function(s,t){
	return function(){return s.apply(t,arguments);};
};

/**
*替换字符
*@param str:原字符串,charA:要替换字符,charB:替换后字符
*@return 修改后的字符串
*/
Class.replaceAll=function(str,charA,charB){
	return str.replace(new RegExp(charA,"gm"),charB);
};

/**
*错误控制
*@param e:错误类型,e1:错误补充
*@return false
*/
Class.onError=function(e,e1){
	switch(e){
		case 2:alert("setNameSpace:在同一位置已存在同名的类:"+e1);break;
		case 4:alert("getPackage:该包不存在:"+e1);break;
		case 5:alert("getClass:无法获取该类:"+e1);break;
		case 8:alert("createAjax:无法创建AJAX对象");break;
		case 12:alert("relToAbsPath:无效相对路径:"+e1);break;
		case 14:alert("loadFileByAjax:无法找到该文件:"+e1);break;
		default:alert(e);
	}
	return false;
};