/**
 * DOM操作
 */
var JTK = window.JTK || {};

JTK.Dom = {
	/**
	 * 通过元素的id属性获取DOM对象,参数为字符串，或多个字符串
	 * @param {String} id the id attribute 
	 * @return {HTMLElement | Object} The HTMLElement with the id, or null if none found. 
	 */
	getById: function() {
		var els = [];
		for (var i = 0; i < arguments.length; i++) {
			var el = arguments[i];
			if (typeof el == "string") {
				el = document.getElementById(el);
			}
			if (arguments.length == 1) {
				return el;
			}
			els.push(el);
		}
		return els;
	},
	/**
	 * get 获取对象，可以传入对象或字符串，如果传入字符串者以document.getElementById（）的方式获取对象
	 * @param {String} el html element
	 * @return {Object} HTMLElement object. 
	 * @todo 增加缓存功能 ,把对象暂时存储到临时变量中
	 */
	get: function(el) {
		if (el && (el.tagName || el.item)) {
			return el;
		}
		return this.getById(el);
	},
	/** 
	 * 某元素是否有某样式
	 * @param {String} el 要获取的对象的id
	 * @param {String} className 要获取的对象的样式名
	 * @return {Boolean} ture or false 
	 */
	hasClass: function(el, className) {
		el = this.get(el);
		if (!el.className) {
			return false;
		}
		return new RegExp('(\\s|^)' + className + '(\\s|$)').test(el.className);
	},
	/** 
	 * 通过元素的样式名属性获取DOM对象,参数为字符串，或多个字符串
	 * @param {String} className 要获取的对象的样式名
	 * @param {String} tagName 要获取的对象的标签名
	 * @param {String} parent 要获取的对象的父级元素
	 * @return {Array} els元素数组 
	 */
	getByClass: function(className, tagName, parent) {
		//获取parent的所有子元素数组
		var elChild = (this.get(parent) || document.body).getElementsByTagName(tagName || '*');
		var els = [], child;
		for (i = 0; i < elChild.length; i++) {
			child = elChild[i];
			if (this.hasClass(child, className)) {
				els.push(child);
			}
		}
		return els;
	},
	/** 
	 * 通过元素的标签名属性获取DOM对象,参数为字符串，或多个字符串
	 * @param {String} tagName 要获取的对象的标签名
	 * @param {String} parent 要获取的对象的父级元素，如果没有就取document
	 * @return {Array} els元素数组 
	 */
	getByTag: function(tagName, parent) {
		return (this.get(parent) || document).getElementsByTagName(tagName);
	},
	/**
	* 获取元素的前一个元素
	* @param {String} el html element
	* @return {Object} HTMLElement object. 
	*/
	getPrev: function(el) {
		el = this.get(el);
		do {
			el = el.previousSibling;
		} while (el && el.nodeType != 1)
		return el;
	},
	/**
	* getNext 获取元素的后一个元素
	* @param {String} el html element
	* @return {Object} HTMLElement object. 
	*/
	getNext: function(el) {
		el = this.get(el);
		do {
			el = el.nextSibling;
		} while (el && el.nodeType != 1)
		return el;
	},
	/**
	* 获取元素下的第一个子元素
	* @param {String} el html element
	* @return {Object} HTMLElement object. 
	*/
	getFirst: function(el) {
		el = this.get(el);
		el = el.firstChild;
		return el && el.nodeType != 1 ? this.getNext(el) : el;
	},
	/**
	* 获取元素下的最后一个子元素
	* @param {String} el html element
	* @return {Object} HTMLElement object. 
	*/
	getLast: function(el) {
		el = this.get(el);
		el = el.lastChild;
		return el && el.nodeType != 1 ? this.getPrev(el) : el;
	},
	/**
	* 获取元素的父元素
	* @param {String} el html element
	* @param {Number} Number 层级
	* @return {Object} HTMLElement object. 
	*/
	getParent: function(el, num) {
		el = this.get(el);
		num = num || 1;
		for (i = 0; i < num; i++) {
			if (el != null) {
				el = el.parentNode;
			}
		}
		return el;
	},
	/** 
	 * todo
	 */
	getText: function(el) {
	
	},
	/** 
    * 判读元素是否拥有该属性
    * @param {String} el DOM对象
    * @param {String} name 属性名
    * @return {Boolean} 
	 */
	hasAttr: function(el, attrName) {
		el = this.get(el);
        return el.getAttribute(attrName) != null;
	},
	/** 
	 * todo
	 */
	attr: function(el, attrs) {
	
	},
	/** 
	* 创建一个Element，
	* @param {String} taagName DOM对象
	* @return {Object} 文本内容
	*/
	createElement: function(tagName) {
		return document.createElementNS ? document.createElementNS("http://www.w3.org/1999/xhtml", tagName) : document.createElement(tagName);
	},
	/**
	 * 查询Element
	 * 缓存测试
	 */
	getElementsByTagName: function(tagName){
		return JTK.varCatch[tagName] = JTK.varCatch[tagName] || document.getElementsByTagName( tagName );
	},
	/** 
	* 移除一个Element
	* @return {Object} 删除的元素
	*/
	removeElement: function(el) {
		var _parentElement = el.parentNode;
		if(_parentElement){
			_parentElement.removeChild(el);
		}
	},
	/** 
	* 检查并格式化元素
	* 如果需要处理的数据的格式是字符串，则把字符串转换成文本节点<TextNode textContent="字符串">
	* 如果需要处理的数据是NodeList或者是其它类似数组数据，则每一个节点都会放到返回的数组中
	* 如果是一般的节点对象，或者是节点对象数组，则直接返回它
	* 这个方法的主要作用就是确保任何节点类型或者节点数组都能够得到只能处理节点数据类型的方法处理
	* @id checkElem
	* @param {String|HTMLElement} tagName DOM对象
	* @return {Object} 文本内容
	*/
	
	checkEl: function(a) {
		var r = [];
		if (JTK.getType(a) != "array") {
			a = [a];
		}
		for (var i = 0; i < a.length; i++) {
			if (JTK.getType(a[i]) == "string") {
				var _div = document.createElement("div");
				_div.innerHTML = a[i];
				for (var j = 0; j < _div.childNodes.length; j++) {
					r[r.length] = _div.childNodes[j];
				}
			} else if (a[i].length) {
				for (var j = 0; j < a[i].length; j++) {
					r[r.length] = a[i][j];
				}
			} else {
				r[r.length] = a[i];
			}
		}
		return r;
	},
	/** 
	* 追加一个，checkEl检查后的dom元素或数组或字符串到父级节点
	* @param {HTMLElement} parent 父级DOM对象
	* @param {Array} el 要插入的元素
	* @return {None} 文本内容
	*/
	
	appendTo: function(parent, el) {
		var _el = this.checkEl(el);
		parent = this.get(parent);
		for (var i = 0; i <_el.length; i++) {
			parent.appendChild(_el[i]);
		}
	},
	/** 
	* 在某一元素前插入一个元素
	* @param {HTMLElement} parent 父级DOM对象
	* @param {HTMLElement} before 在某元素前
	* @param {Array} el 要插入的元素
	* @return {None} 文本内容
	*/
	inBefore: function(parent, before, el) {
		before = this.get(before);
		parent = this.get(parent);
		if(el==null){
			el=before;
			before=parent;
			parent=parent.parentNode;
		}
		var _el = this.checkEl(el);
		for (var i = 0; i <_el.length; i++) {
			parent.insertBefore(_el[i],before);
		}
	},
	/** 
	* 在某一元素后插入一个元素
	* @param {HTMLElement} parent 父级DOM对象
	* @param {HTMLElement} after 在某元素前
	* @param {Array} el 要插入的元素
	* @return {None} 文本内容
	*/
	inAfter: function(parent, after, el) {
		before = this.get(after);
		parent = this.get(parent);
		if(el==null){
			el=after;
			after=parent;
			parent=parent.parentNode;
		}
		var _el = this.checkEl(el);
		for (var i = 0; i <_el.length; i++) {
			if(parent.lastChild==after){
				parent.appendChild(_el[i]);
			}else{
				parent.insertBefore(_el[i],after.nextSibling);
			}
		}
	},
	/**
	 * outerHTML
	 * @param {HTMLElement} el 在某元素前
	 * @return {String} outerHTML
	 */
	getOuterHTML: function (el) {
		var element;
		if (!el) return null;
		element = document.createElement("div");
		element.appendChild(el.cloneNode(true));
		return element.innerHTML;
	},
	/**
	 * DOM加载完毕之后执行某方法
	 */
	ready : function(func){
		if(document.addEventListener){
			document.addEventListener("DOMContentLoaded",func,false);
			return false;
		}else if(document.attachEvent){
			this._isReady();
			if (JTK._ready) {
				func();
			}
			else{
				JTK._fnList.push(func);
			}
			return false;
		}else{
			window.onload += func;
		}
	},
	_isReady : function(){
		try {
			document.documentElement.doScroll('left');
		} catch (e) {
			setTimeout(arguments.callee, 1)
			return;
		} 
		if (JTK._fnList) {
			for (var i = 0; i < JTK._fnList.length; i++) {
				if (JTK._fnList[i]) {
					JTK._fnList[i]()
				}
			}
			JTK._fnList = null;
		}
		JTK._ready = true;
		return false;
	},
	//
	
	/*
	 * 获取“document.body”
	 * 在HTML4.0标准下用document.body，在XHTML标准下就要换成document.documentElement
	 * XHTML下document.body仅仅表示body对象，而不能代表文档内容所渲染的整个表面
	 */
	getBodyObj : function(){
		return (document.documentElement) ? document.documentElement : document.body;
	},
	/**
	 * 动态加载script
	 * @这个方法风险,加载复杂的js,比如http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js会报错
	 * @ie6有问题
	 * @param {String} src 欲加载script的地址
	 */
	loadScript : function(src, callBack){
		var script = document.createElement('script');
		script.src = src;
		this.getBodyObj().appendChild(script);
		script.onload = script.onreadystatechange = function(){
			if(! this.readyState || this.readyState=='loaded' || this.readyState=='complete'){
				 callBack();
			}
		};
	},
	/**
	 * 执行带script的innerHTMl方法
	 * @ 执行效率不高,容易出现问题,请尽量使用innerHTML
	 */
	setDInnerHTML : function(obj_id, html, time){
	
		if(JTK.varCatch["html_pool"] == undefined){
			JTK.varCatch["html_pool"] = [];
		}
		if(JTK.varCatch["script_pool"] == undefined){
			JTK.varCatch["script_pool"] = [];
		}
		if(JTK.varCatch["script_src_pool"] == undefined){
			JTK.varCatch["script_src_pool"] = [];
		}
		if(JTK.varCatch["lock_pool"] == undefined){
			JTK.varCatch["lock_pool"] = [];
		}
		if(JTK.varCatch["innerhtml_lock"] == undefined){
			JTK.varCatch["innerhtml_lock"] = null;
		}
		if(JTK.varCatch["document_buffer"] == undefined){
			JTK.varCatch["document_buffer"] = "";
		}
		if (JTK.varCatch["innerhtml_lock"] == null) { 
			JTK.varCatch["innerhtml_lock"] = obj_id;
		} else if (typeof(time) == "undefined") { 
			JTK.varCatch["lock_pool"][obj_id + "_html"] = html; 
			window.setTimeout("JTK.Dom.setDInnerHTML('" + obj_id + "', JTK.varCatch['lock_pool']['" + obj_id + "_html']);", 10);
			return; 
		} else if (JTK.varCatch["innerhtml_lock"] != obj_id) { 
			JTK.varCatch["lock_pool"][obj_id + "_html"] = html; 
			window.setTimeout("JTK.Dom.setDInnerHTML('" + obj_id + "', JTK.varCatch['lock_pool']['" + obj_id + "_html'], " + time + ");", 10); 
			return; 
		}
		
		function get_script_id() { 
			return "script_" + (new Date()).getTime().toString(36) 
			+ Math.floor(Math.random() * 100000000).toString(36); 
		}
		
		document_buffer = "";
		document.write = function (str) { 
			document_buffer += str; 
		}
		document.writeln = function (str) { 
			document_buffer += str + "\n"; 
		}
		
		JTK.varCatch["html_pool"] = [];
		var scripts = []; 
		html = html.split(/<\/script>/i); 
		
		for (var i = 0; i < html.length; i++) { 
			JTK.varCatch["html_pool"][i] = html[i].replace(/<script[\s\S]*$/ig, ""); 
			scripts[i] = {text: '', src: '' }; 
			scripts[i].text = html[i].substr(JTK.varCatch["html_pool"][i].length); 
			scripts[i].src = scripts[i].text.substr(0, scripts[i].text.indexOf('>') + 1); 
			scripts[i].src = scripts[i].src.match(/src\s*=\s*(\"([^\"]*)\"|\'([^\']*)\'|([^\s]*)[\s>])/i); 
			if (scripts[i].src) { 
				if (scripts[i].src[2]) { 
					scripts[i].src = scripts[i].src[2]; 
				} 
				else if (scripts[i].src[3]) { 
					scripts[i].src = scripts[i].src[3]; 
				} 
				else if (scripts[i].src[4]) { 
					scripts[i].src = scripts[i].src[4]; 
				} 
				else { 
					scripts[i].src = ""; 
				} 
				scripts[i].text = ""; 
			} 
			else { 
				scripts[i].src = ""; 
				scripts[i].text = scripts[i].text.substr(scripts[i].text.indexOf('>') + 1); 
				scripts[i].text = scripts[i].text.replace(/^\s*<\!--\s*/g, ""); 
			} 
		}

		var s; 
		if (typeof(time) == "undefined") { 
			s = 0; 
		} 
		else { 
			s = time; 
		}
		
		var script, add_script, remove_script; 
		
		for (var i = 0; i < scripts.length; i++) { 
			var add_html = "document_buffer += JTK.varCatch['html_pool'][" + i + "];\n"; 
			add_html += "document.getElementById('" + obj_id + "').innerHTML = document_buffer;\n"; 
			script = document.createElement("script"); 
			if (scripts[i].src) { 
				script.src = scripts[i].src; 
				if (typeof(JTK.varCatch["script_src_pool"][script.src]) == "undefined") { 
					JTK.varCatch["script_src_pool"][script.src] = true; 
					s += 2000; 
				} 
				else { 
					s += 10; 
				} 
			} 
			else { 
				script.text = scripts[i].text; 
				s += 10; 
			} 
			script.defer = true; 
			script.type =  "text/javascript"; 
			script.id = get_script_id(); 
			JTK.varCatch["script_pool"][script.id] = script; 
			add_script = add_html; 
			add_script += "document.getElementsByTagName('head').item(0)"; 
			add_script += ".appendChild(JTK.varCatch['script_pool']['" + script.id + "']);\n"; 
			window.setTimeout(add_script, s); 
			remove_script = "document.getElementsByTagName('head').item(0)"; 
			remove_script += ".removeChild(document.getElementById('" + script.id + "'));\n"; 
			remove_script += "delete JTK.varCatch['script_pool']['" + script.id + "'];\n"; 
			window.setTimeout(remove_script, s + 10000); 
		} 
	},
	//判断 element 是否是参数 ancestor 指定元素的后代节点
	descendantOf: function(element, ancestor) {
		element = JTK.Dom.get(element), ancestor = JTK.Dom.get(ancestor);
		if (element.compareDocumentPosition)
		  return (element.compareDocumentPosition(ancestor) & 8) === 8;
		if (ancestor.contains)
		  return ancestor.contains(element) && ancestor !== element;
		while (element = element.parentNode)
		  if (element == ancestor) return true;
		return false;
    }
};
JTK.require('JTK.Dom.find');
