PageRenderTime 104ms CodeModel.GetById 28ms app.highlight 64ms RepoModel.GetById 1ms app.codeStats 1ms

/KitJs/src/js/kit.js

https://github.com/wuxq/KitJs
JavaScript | 1778 lines | 1183 code | 7 blank | 588 comment | 413 complexity | cdfd6099af964f6a04d4b2db161eb4f7 MD5 | raw file
   1/*
   2* a javascript library used to mobile phone web develop
   3* 3q & enjoy it!
   4* @author 薛端阳<xueduanyang1985@163.com>
   5* @copyright 薛端阳  since 2011.10
   6*/
   7
   8/**
   9 * Kit Js 基类,包含基本dom操作,object类型判断以及ready方法,还有事件委托等
  10 * @constructor $Kit
  11 * @param {Object} config 组件配置
  12 * @see <a href="https://github.com/xueduany/KitJs/blob/master/KitJs/src/js/kit.js">Source code</a>
  13 */
  14$Kit = function(config) {
  15	var me = this;
  16	var defaultConfig = {
  17		//默认配置
  18	}
  19	me.config = me.join(config, defaultConfig);
  20	// -----------------------------init------------------------------------
  21	window[me.CONSTANTS.KIT_EVENT_STOPALLEVENT] = false;
  22	window[me.CONSTANTS.KIT_EVENT_STOPIMMEDIATEPROPAGATION] = false;
  23	// me.SYSINFO = {}
  24	// var inf = me.iOSInfo();
  25	// if(inf != null) {
  26	// me.merge(me.SYSINFO, inf);
  27	// }
  28	/**
  29	 * @namespace $kit.ui
  30	 */
  31	me.ui = {};
  32}
  33$Kit.prototype = {
  34	constructor : $Kit,
  35	//----------------------CONSTANTS----------------------
  36	/**
  37	 * KitJs内部常量
  38	 * @enum
  39	 * @const
  40	 * @public
  41	 * @type {Object}
  42	 */
  43	CONSTANTS : {
  44		/**
  45		 * 异常处理,最大循环次数
  46		 */
  47		MAX_CYCLE_COUNT : 1000,
  48		/**
  49		 * element节点
  50		 */
  51		NODETYPE_ELEMENT : 1,
  52		NODETYPE_ELEMENT_ATTR : 2,
  53		/**
  54		 * 文本节点
  55		 */
  56		NODETYPE_TEXTNODE : 3,
  57		/**
  58		 * 注释
  59		 */
  60		NODETYPE_COMMENT : 8,
  61		/**
  62		 * 根
  63		 */
  64		NODETYPE_ROOT : 9,
  65		/**
  66		 * doc fragment
  67		 */
  68		NODETYPE_FRAGMENT : 11,
  69		/**
  70		 * contains比较结果-同一个
  71		 */
  72		DOCUMENT_POSITION_SAME : 0, //同一个
  73		/**
  74		 * contains比较结果-不在一个文档
  75		 */
  76		DOCUMENT_POSITION_DISCONNECTED : 1, //不在一个文档
  77		/**
  78		 * contains比较结果-b在a前面
  79		 */
  80		DOCUMENT_POSITION_PRECEDING : 2, //b在a前面
  81		/**
  82		 * contains比较结果-b在a后面
  83		 */
  84		DOCUMENT_POSITION_FOLLOWING : 4, //b在a后面
  85		/**
  86		 * contains比较结果-b是a祖先
  87		 */
  88		DOCUMENT_POSITION_CONTAINS : 10, //b是a祖先
  89		/**
  90		 * contains比较结果-b是a儿子
  91		 */
  92		DOCUMENT_POSITION_CONTAINED_BY : 20, //b是a儿子
  93		/**
  94		 * contains比较结果-不常用
  95		 */
  96		DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC : 32, //不常用
  97		/**
  98		 * 空格正则
  99		 */
 100		REGEXP_SPACE : /\s+/g,
 101		/**
 102		 * kit事件注册前缀
 103		 */
 104		KIT_EVENT_REGISTER : "_kit_event_register_",
 105		/**
 106		 * kit事件注册前缀
 107		 */
 108		KIT_EVENT_REGISTER_EVENT : "_kit_event_register_event",
 109		/**
 110		 * kit事件注册前缀
 111		 */
 112		KIT_EVENT_REGISTER_FUNCTION : "_kit_event_register_function",
 113		/**
 114		 * kit事件信号--立即停止所有事件
 115		 */
 116		KIT_EVENT_STOPIMMEDIATEPROPAGATION : "_kit_event_stopimmediatepropagation_",
 117		/**
 118		 * kit事件信号--停止所有事件
 119		 */
 120		KIT_EVENT_STOPALLEVENT : "_kit_event_stopallevent_",
 121		/**
 122		 * kit DOM ID 默认前缀
 123		 */
 124		KIT_DOM_ID_PREFIX : "J_Kit_"
 125	},
 126	// -----------------------------------is
 127	// something-----------------------------------
 128	/**
 129	 * 判断是否IE
 130	 * @return {Boolean}
 131	 */
 132	isIE : function() {
 133		return /MSIE/i.test(navigator.userAgent);
 134	},
 135	/**
 136	 * 是否是chrome
 137	 * @return {Boolean}
 138	 */
 139	isChrome : function() {
 140		return /Chrome/i.test(navigator.userAgent);
 141	},
 142	isWebKit : function() {
 143		return /WebKit/i.test(navigator.userAgent);
 144	},
 145	/**
 146	 * 是否是火狐
 147	 * @return {Boolean}
 148	 */
 149	isFirefox : function() {
 150		return /Firefox/i.test(navigator.userAgent);
 151	},
 152	/**
 153	 * 是否已定义
 154	 * @param {Object}
 155	 * @return {Boolean}
 156	 */
 157	isDefined : function(o) {
 158		return typeof (o) != "undefined";
 159	},
 160	/**
 161	 * 是否是字符串
 162	 * @param {Object}
 163	 * @return {Boolean}
 164	 */
 165	isStr : function(o) {
 166		return typeof (o) == "string";
 167	},
 168	/**
 169	 * 是否数字
 170	 * @param {Object}
 171	 * @return {Boolean}
 172	 */
 173	isNum : function(o) {
 174		return isFinite(o)
 175	},
 176	/**
 177	 * 是否是日期
 178	 * @param {Object}
 179	 * @return {Boolean}
 180	 */
 181	isDate : function(o) {
 182		return (null != o) && !isNaN(o) && ("undefined" !== typeof o.getDate);
 183	},
 184	/**
 185	 * 是否是对象类型
 186	 * @param {Object}
 187	 * @return {Boolean}
 188	 */
 189	isObj : function(o) {
 190		return !!(o && typeof (o) == "object" );
 191	},
 192	/**
 193	 * 是否是方法类型
 194	 * @param {Object}
 195	 * @return {Boolean}
 196	 */
 197	isFn : function(o) {
 198		return !!(o && typeof (o) == "function");
 199	},
 200	/**
 201	 * 是否是可以迭代
 202	 * @param {Object}
 203	 * @return {Boolean}
 204	 */
 205	isAry : function(o) {
 206		var me = this;
 207		return !!(o && (o.constructor && o.constructor.toString().indexOf("Array") > -1 || me.isNodeList(o)));
 208	},
 209	/**
 210	 * 是否是节点列表
 211	 * @param {Object}
 212	 * @return {Boolean}
 213	 */
 214	isNodeList : function(o) {
 215		return !!(o && (o.toString() == '[object NodeList]' || o.toString() == '[object HTMLCollection]' || (o.length && this.isNode(o[0]))));
 216	},
 217	/**
 218	 * 是否是节点
 219	 * @param {Object}
 220	 * @return {Boolean}
 221	 */
 222	isNode : function(o) {
 223		return !!(o && o.nodeType);
 224	},
 225	/**
 226	 * 一个字符串能否根据空格拆分成一个数组,数组内元素个数大于1
 227	 * @param {String}
 228	 * @return {Boolean}
 229	 */
 230	isCanSplit2Ary : function(o, sign) {
 231		var me = this;
 232		return me.isStr(o) && o.split(sign || /\s+/g).length > 1;
 233	},
 234	/**
 235	 * 是否为空
 236	 * @param {Object}
 237	 * @return {Boolean}
 238	 */
 239	isEmpty : function(o) {
 240		var me = this;
 241		return typeof (o) == "undefined" || o == null || (!me.isNode(o) && me.isAry(o) && o.length == 0 || (me.isStr(o) && o == ""));
 242	},
 243	// -----------------------------------string-----------------------------------
 244	/**
 245	 * 去除所有空格
 246	 * @param {String}
 247	 * @return {String}
 248	 */
 249	trimAll : function(str) {
 250		if(str == null) {
 251			return null;
 252		}
 253		str = str.toString();
 254		return str.replace(/\s+/ig, "");
 255	},
 256	// -----------------------------------array-----------------------------------
 257	/**
 258	 * 从一个数组里面剔除部分元素
 259	 * @param {String|Array}
 260	 * @return {Array}
 261	 */
 262	aryDel : function(ary, del) {
 263		var me = this;
 264		if(!me.isAry(ary)) {
 265			return;
 266		}
 267		if(me.isAry(del)) {
 268			for(var i = 0; i < del.length; i++) {
 269				me.aryDel(ary, del[i]);
 270			}
 271		} else {
 272			for(var j = 0; j < ary.length; j++) {
 273				if(ary[j] == del) {
 274					ary.splice(j, 1);
 275				}
 276			}
 277		}
 278		return ary;
 279	},
 280	/**
 281	 * 判断是否数组中是否存在参数
 282	 * @param {String|Array}
 283	 * @return {Boolean}
 284	 */
 285	inAry : function(ary, o) {
 286		var me = this, flag = false;
 287		if(!me.isAry(ary)) {
 288			return;
 289		}
 290		for(var i = 0; i < ary.length; i++) {
 291			if(me.isAry(o)) {
 292				for(var j = 0; j < o.length; j++) {
 293					if(ary[i] == o[j]) {
 294						flag = true;
 295						break;
 296					}
 297				}
 298			} else {
 299				if(ary[i] == o) {
 300					flag = true;
 301					break;
 302				}
 303			}
 304		}
 305		return flag;
 306	},
 307	// -----------------------------------find dom-----------------------------------
 308	/**
 309	 * ==document.getElementById 根据id选择
 310	 * @param {String}
 311	 * @param {Element} [root] 可选,从哪个根节点查找
 312	 * @return {Element}
 313	 */
 314	el8id : function(id, root) {
 315		var me = this, re = document.getElementById(id);
 316		if(root) {
 317			if(me.contains(root, re)) {
 318				return re;
 319			}
 320			return null;
 321		}
 322		return re;
 323	},
 324	/**
 325	 * ==document.getElementsByClassName 根据className选择,返回第一个找到的
 326	 * @param {String}
 327	 * @param {Element} [root] 可选,从哪个根节点查找
 328	 * @return {Element|Null}
 329	 */
 330	el8cls : function(cls, root) {
 331		var re = (root || document).getElementsByClassName(cls);
 332		return (re != null && re.length ) ? re[0] : null;
 333	},
 334	/**
 335	 * ==document.getElementsByClassName 根据className选择,返回所有找到的
 336	 * @param {String}
 337	 * @param {Element} [root] 可选,从哪个根节点查找
 338	 * @return {[Element]|Null}
 339	 */
 340	els8cls : function(cls, root) {
 341		var re = (root || document).getElementsByClassName(cls);
 342		return re != null && re.length ? re : null;
 343	},
 344	/**
 345	 * ==document.getElementsByTagName 根据tagName选择,返回所有找到的
 346	 * @param {String}
 347	 * @param {Element} [root] 可选,从哪个根节点查找
 348	 * @return {[Element]|Null}
 349	 */
 350	els8tag : function(tagName, root) {
 351		var re = (root || document).getElementsByTagName(tagName);
 352		return re != null && re.length ? re : null;
 353	},
 354	/**
 355	 * ==document.getElementsByTagName 根据tagName选择,返回第一个找到的
 356	 * @param {String}
 357	 * @param {Element} [root] 可选,从哪个根节点查找
 358	 * @return {[Element]|Null}
 359	 */
 360	el8tag : function(tagName, root) {
 361		var me = this;
 362		var re = me.els8tag(tagName, root);
 363		return re != null && re.length ? re[0] : null;
 364	},
 365	/**
 366	 * ==document.getElementsByName 根据name选择,返回第一个找到的
 367	 * @param {String}
 368	 * @param {Element} [root] 可选,从哪个根节点查找
 369	 * @return {[Element]|Null}
 370	 */
 371	el8name : function(name, root) {
 372		var me = this, re = document.getElementsByName(name);
 373		if(root) {
 374			for(var i = 0; i < re.length; i++) {
 375				if(me.contains(root, re[i])) {
 376					return re[i];
 377				}
 378			}
 379			return null;
 380		}
 381		return (re != null && re.length ) ? re[0] : null;
 382	},
 383	/**
 384	 * ==document.getElementsByName 根据name选择,返回所有找到的
 385	 * @param {String}
 386	 * @param {Element} [root] 可选,从哪个根节点查找
 387	 * @return {[Element]|Null}
 388	 */
 389	els8name : function(name, root) {
 390		var me = this, re = document.getElementsByName(name);
 391		if(root) {
 392			var _re = [];
 393			for(var i = 0; i < re.length; i++) {
 394				if(me.contains(root, re[i])) {
 395					_re.push(re[i]);
 396				}
 397			}
 398			return _re.length ? _re : null;
 399		}
 400		return re != null && re.length ? re : null;
 401	},
 402	/**
 403	 * 简单Css选择器 支持#id,.className,@formName,还有tagName.className,四种格式
 404	 * @param {String}
 405	 * @param {Element} [root] 可选,从哪个根节点查找
 406	 * @return {[Element]|Null}
 407	 */
 408	el : function(selector, root) {
 409		var me = this;
 410		if(me.isEmpty(selector)) {
 411			return;
 412		} else if(me.isNode(selector) || me.isNodeList(selector)) {
 413			return selector;
 414		}
 415		var selector = selector.toString().trim();
 416		if(selector.indexOf("#") == 0) {
 417			return me.el8id(selector.substring(1), root);
 418		} else if(selector.indexOf(".") == 0) {
 419			var a = me.els8cls(selector.substring(1), root), re = [];
 420			if(a.constructor && a.constructor.toString().indexOf("Array") > -1) {
 421				re = a;
 422			} else {
 423				for(var i = 0; i < a.length; i++) {
 424					re.push(a[i]);
 425				}
 426			}
 427			return re;
 428		} else if(selector.indexOf("@") == 0) {
 429			var a = me.els8name(selector.substring(1), root), re = [];
 430			for(var i = 0; i < a.length; i++) {
 431				re.push(a[i]);
 432			}
 433			return re;
 434		} else {
 435			var re = [];
 436			if(selector.indexOf(".") > 0 && selector.indexOf(".") < selector.length) {
 437				var a = me.els8tag(selector.substring(0, selector.indexOf(".")), root);
 438				var cls = selector.substr(selector.indexOf(".") + 1);
 439				for(var i = 0; !me.isEmpty(a) && i < a.length; i++) {
 440					if(me.hsCls(a[i], cls)) {
 441						re.push(a[i]);
 442					}
 443				}
 444			} else {
 445				re = me.els8tag(selector, root);
 446			}
 447			return re;
 448		}
 449
 450	},
 451	// -----------------------------------dom manipulate-----------------------------------
 452	/**
 453	 * 比较element位置 如果a包含b返回true,否则返回false
 454	 * @param {Element}
 455	 * @param {Element}
 456	 * @reutn {Boolean}
 457	 */
 458	contains : function(a, b) {
 459		return a.contains ? a != b && a.contains(b) : !!(a.compareDocumentPosition(b) & 16);
 460	},
 461	/**
 462	 * 设置或者获取Element的attribute
 463	 * @param {Element}
 464	 * @param {String|Object} attr 可以为属性值,也可以为一个枚举对象,按照key,value顺序批量设置
 465	 * @param {String} [value]
 466	 * @reutn {String|Null}
 467	 */
 468	attr : function(el, attr, value) {
 469		var me = this;
 470		if(me.isEmpty(el)) {
 471			return;
 472		}
 473		if(!me.isDefined(value)) {
 474			if(me.isObj(attr)) {
 475				for(var l in attr) {
 476					el.setAttribute(l, attr[l]);
 477				}
 478			} else {
 479				return el.getAttribute(attr);
 480			}
 481		} else {
 482			if(value == null) {
 483				if( attr in el) {
 484					try {
 485						el[attr] = null;
 486					} catch(e) {
 487					}
 488				}
 489				if(el.removeAttribute) {
 490					el.removeAttribute(attr);
 491				} else {
 492					el.setAttribute(attr, null);
 493				}
 494				try {
 495					delete el[attr];
 496				} catch(e) {
 497				}
 498			} else {
 499				el.setAttribute(attr, value);
 500			}
 501		}
 502	},
 503	/**
 504	 * 设置或者获取Element的css
 505	 * @param {Element}
 506	 * @param {String|Object} attr 可以为属性值,也可以为一个枚举对象,按照key,value顺序批量设置
 507	 * @param {String} [value]
 508	 * @reutn {String|Null}
 509	 */
 510	css : function(el, attr, value) {
 511		var me = this;
 512		if(me.isEmpty(el)) {
 513			return;
 514		}
 515		if(value == null) {
 516			if(me.isObj(attr)) {
 517				for(var l in attr) {
 518					if(l.indexOf('-moz-') == 0) {
 519						var l1 = '';
 520						$kit.each(l.split('-'), function(o) {
 521							if(o.length) {
 522								l1 += o.substring(0, 1).toUpperCase() + o.substring(1, o.length);
 523							}
 524						});
 525						el.style[l1] = attr[l];
 526					} else {
 527						if(!me.isWebKit()) {
 528							l = me._camelCssName(l);
 529						}
 530						el.style[l] = attr[l];
 531					}
 532				}
 533			} else {
 534				var re = getComputedStyle(el, null)[this._camelCssName(attr)];
 535				try {
 536					re = isNaN(parseFloat(re)) ? re : parseFloat(re);
 537				} catch(e) {
 538					//
 539				}
 540				return re;
 541			}
 542		} else {
 543			if(attr.indexOf('-moz-') == 0) {
 544				var attr1 = '';
 545				$kit.each(attr.split('-'), function(o) {
 546					if(o.length) {
 547						attr1 += o.substring(0, 1).toUpperCase() + o.substring(1, o.length);
 548					}
 549				});
 550				el.style[attr1] = value;
 551			} else {
 552				if(!me.isWebKit()) {
 553					attr = me._camelCssName(attr);
 554				}
 555				el.style[attr] = value;
 556			}
 557		}
 558	},
 559	_camelCssName : function(str) {
 560		var a = str.split('-');
 561		for(var i = 1; i < a.length; i++) {
 562			a[i] = a[i].substr(0, 1).toUpperCase() + a[i].substr(1);
 563		}
 564		return a.join('');
 565	},
 566	/**
 567	 * 获取Element的cssStr
 568	 * @param {Element}
 569	 * @param {String}
 570	 */
 571	cssStr : function(el, attr) {
 572		var me = this;
 573		if(me.isEmpty(el)) {
 574			return;
 575		}
 576		if(attr.indexOf('-moz-') == 0) {
 577			var attr1 = '';
 578			$kit.each(attr.split('-'), function(o) {
 579				if(o.length) {
 580					attr1 += o.substring(0, 1).toUpperCase() + o.substring(1, o.length);
 581				}
 582			});
 583			attr = attr1;
 584		} else {
 585			attr = this._camelCssName(attr);
 586		}
 587		var re = el.style[attr] || getComputedStyle(el, null)[attr];
 588		return re;
 589	},
 590	_camelCssName : function(str) {
 591		var firstLetter = str.substring(0, 1);
 592		var mainStr = str.substr(1);
 593		var a = mainStr.split('-');
 594		for(var i = 1; i < a.length; i++) {
 595			a[i] = a[i].substr(0, 1).toUpperCase() + a[i].substr(1);
 596		}
 597		return firstLetter.toLowerCase() + a.join('');
 598	},
 599	/**
 600	 * 取值 div等取innerHTML textarea等form元素取value
 601	 * @param {Element}
 602	 * @return {String}
 603	 */
 604	val : function(el) {
 605		var me = this;
 606		if(me.isEmpty(el)) {
 607			return;
 608		}
 609		if(me.isNode(el) && ('value' in el)) {
 610			return el.value;
 611		} else if(me.isNodeList(el) && el.length > 1) {
 612			var a = [];
 613			for(var i = 0; i < el.length; i++) {
 614				if(el[i].checked && el[i].value) {
 615					a.push(el[i].value);
 616				}
 617			}
 618			return a.join(',');
 619		} else if(el.length == 1) {
 620			return me.val(el[0]);
 621		}
 622		return el.innerHTML;
 623	},
 624	/**
 625	 * 插入元素
 626	 * @param {Object} config
 627	 * @param {String} config.pos pos表示插入位置,有last,first,before(previous),after(nextSibling),4种类型值
 628	 * @param {Element} config.where where为被插入目标Element
 629	 * @param {Element|String} config.what what为插入值,可以为一段HTML,也可以为一个HTML Node
 630	 */
 631	insEl : function(config) {
 632		var me = this, defaultConfig = {
 633			pos : "last",
 634			what : null,
 635			where : null
 636		}
 637		config = me.join(defaultConfig, config);
 638		var what = config.what, where = config.where;
 639		if(!me.isEmpty(what) && me.isNode(where)) {
 640			switch (config.pos.toString().toLowerCase()) {
 641				case "first" :
 642					if(me.isStr(what)) {
 643						me.insertHTML(where, "afterBegin", what);
 644					} else {
 645						me.insertNode(where, "afterBegin", what);
 646					}
 647					break;
 648				case "before" :
 649				case "previous" :
 650					if(me.isStr(what)) {
 651						me.insertHTML(where, "beforeBegin", what);
 652					} else {
 653						me.insertNode(where, "beforeBegin", what);
 654					}
 655					break;
 656				case "after" :
 657				case "nextsibling" :
 658					if(me.isStr(what)) {
 659						me.insertHTML(where, "afterEnd", what);
 660					} else {
 661						me.insertNode(where, "afterEnd", what);
 662					}
 663					break;
 664				case "last" :
 665					if(me.isStr(what)) {
 666						me.insertHTML(where, "beforeEnd", what);
 667					} else {
 668						me.insertNode(where, "beforeEnd", what);
 669					}
 670					break;
 671				default:
 672				//i don`t know how to do that
 673			}
 674		}
 675	},
 676	/**
 677	 * @private
 678	 */
 679	insertNode : function(el, where, parsedNode) {
 680		switch(where) {
 681			case "beforeBegin":
 682				el.parentNode.insertBefore(parsedNode, el);
 683				break;
 684			case "afterBegin":
 685				el.insertBefore(parsedNode, el.firstChild);
 686				break;
 687			case "beforeEnd":
 688				el.appendChild(parsedNode);
 689				break;
 690			case "afterEnd":
 691				if(el.nextSibling) {
 692					el.parentNode.insertBefore(parsedNode, el.nextSibling);
 693				} else {
 694					el.parentNode.appendChild(parsedNode);
 695				}
 696				break;
 697		}
 698	},
 699	/**
 700	 * @private
 701	 */
 702	insertHTML : function(el, where, html) {
 703		where = where.toLowerCase();
 704		if(el.insertAdjacentHTML) {
 705			switch(where) {
 706				case "beforebegin":
 707					el.insertAdjacentHTML('BeforeBegin', html);
 708					return el.previousSibling;
 709				case "afterbegin":
 710					el.insertAdjacentHTML('AfterBegin', html);
 711					return el.firstChild;
 712				case "beforeend":
 713					el.insertAdjacentHTML('BeforeEnd', html);
 714					return el.lastChild;
 715				case "afterend":
 716					el.insertAdjacentHTML('AfterEnd', html);
 717					return el.nextSibling;
 718			}
 719			throw 'Illegal insertion point -> "' + where + '"';
 720		}
 721		var range = el.ownerDocument.createRange();
 722		var frag;
 723		switch(where) {
 724			case "beforebegin":
 725				range.setStartBefore(el);
 726				frag = range.createContextualFragment(html);
 727				el.parentNode.insertBefore(frag, el);
 728				return el.previousSibling;
 729			case "afterbegin":
 730				if(el.firstChild) {
 731					range.setStartBefore(el.firstChild);
 732					frag = range.createContextualFragment(html);
 733					el.insertBefore(frag, el.firstChild);
 734					return el.firstChild;
 735				} else {
 736					el.innerHTML = html;
 737					return el.firstChild;
 738				}
 739			case "beforeend":
 740				if(el.lastChild) {
 741					range.setStartAfter(el.lastChild);
 742					frag = range.createContextualFragment(html);
 743					el.appendChild(frag);
 744					return el.lastChild;
 745				} else {
 746					el.innerHTML = html;
 747					return el.lastChild;
 748				}
 749			case "afterend":
 750				range.setStartAfter(el);
 751				frag = range.createContextualFragment(html);
 752				el.parentNode.insertBefore(frag, el.nextSibling);
 753				return el.nextSibling;
 754		}
 755		throw 'Illegal insertion point -> "' + where + '"';
 756	},
 757	/**
 758	 * 替换元素
 759	 * @param {Element}
 760	 * @param {Element|String} html 为一个html元素或者一段HTML string
 761	 */
 762	rpEl : function(element, html) {
 763		var me = this;
 764		if(me.isEmpty(element) || me.isEmpty(html)) {
 765			return;
 766		}
 767		if($kit.isStr(html)) {
 768			var range = element.ownerDocument.createRange();
 769			range.selectNodeContents(element);
 770			element.parentNode.replaceChild(range.createContextualFragment(html), element);
 771			range.detach();
 772		} else if($kit.isNode(html)) {
 773			element.parentNode.replaceChild(html, element);
 774		}
 775	},
 776	/**
 777	 * 删除元素
 778	 * @param {Element}
 779	 */
 780	rmEl : function(element) {
 781		var me = this;
 782		if(me.isEmpty(element)) {
 783			return;
 784		}
 785		if(me.isAry(element)) {
 786			for(var i = 0; i < element.length; i++) {
 787				me.rmEl(element[i]);
 788			}
 789		} else {
 790			me.traversal({
 791				root : element,
 792				fn : function(node) {
 793					me.delEv({
 794						el : node
 795					});
 796				}
 797			});
 798			element.parentNode.removeChild(element, true);
 799		}
 800	},
 801	/**
 802	 * 添加className
 803	 * @param {Element}
 804	 * @param {String}
 805	 */
 806	adCls : function(el, cls) {
 807		var me = this;
 808		if(me.isEmpty(el)) {
 809			return;
 810		}
 811		/*
 812		 if(me.isAry(clss)) {
 813		 for(var i = 0; i < clss.length; i++) {
 814		 me.adCls(el, clss[i]);
 815		 }
 816		 } else {
 817		 var a = me.isEmpty(el.className) ? [] :
 818		 el.className.split(me.CONSTANTS.REGEXP_SPACE), flag = true;
 819		 for(var i = 0; i < a.length; i++) {
 820		 if(a[i] == clss) {
 821		 flag = false;
 822		 break;
 823		 }
 824		 }
 825		 if(flag) {
 826		 a.push(clss);
 827		 el.className = a.join(" ");
 828		 }
 829		 }*/
 830		var re = new RegExp('(\\s|^)' + cls + '(\\s|$)');
 831		if(re.test(el.className))
 832			return;
 833		//el.className += ' ' + cls;
 834		el.className = el.className.split(/\s+/).join(' ') + ' ' + cls;
 835	},
 836	/**
 837	 * 删除ClassName
 838	 * @param {Element}
 839	 * @param {String}
 840	 */
 841	rmCls : function(el, cls) {
 842		var me = this;
 843		if(me.isEmpty(el)) {
 844			return;
 845		}
 846		/*
 847		 var a = me.isEmpty(el.className) ? [] :
 848		 el.className.split(me.CONSTANTS.REGEXP_SPACE), b = [];
 849		 if(a.length) {
 850		 b = me.aryDel(a, clss);
 851		 }
 852		 if(b.length) {
 853		 el.className = b.join(" ");
 854		 } else {
 855		 el.className = "";
 856		 me.attr(el, 'class', null);
 857		 }*/
 858		var clsAry = cls.split(/\s+/g);
 859		var reCls = el.className;
 860		for(var i = 0; i < clsAry.length; i++) {
 861			var cls = clsAry[i];
 862			var re = new RegExp('(\\s|^)' + cls + '(\\s|$)');
 863			if(reCls) {
 864				reCls = reCls.replace(re, ' ');
 865			}
 866		}
 867		reCls = reCls.trim();
 868		el.className = reCls;
 869	},
 870	/**
 871	 * 判断是否含有某个className
 872	 * @param {Element}
 873	 * @param {String}
 874	 */
 875	hsCls : function(el, cls) {
 876		var me = this;
 877		if(me.isEmpty(el)) {
 878			return;
 879		}
 880		/*
 881		 if(!me.isEmpty(el.className)) {
 882		 var a = el.className.split(me.CONSTANTS.REGEXP_SPACE);
 883		 for(var i = 0; i < a.length; i++) {
 884		 if(a[i] == cls) {
 885		 flag = true;
 886		 break;
 887		 }
 888		 }
 889		 }
 890		 return flag;
 891		 */
 892		var re = new RegExp('(\\s|^)' + cls + '(\\s|$)');
 893		return re.test(el.className);
 894	},
 895	/**
 896	 * 切换css,有则删,无则加
 897	 * @param {Element}
 898	 * @param {String}
 899	 */
 900	toggleCls : function(el, cls) {
 901		var me = this;
 902		if(me.hsCls(el, cls)) {
 903			me.rmCls(el, cls);
 904		} else {
 905			me.adCls(el, cls);
 906		}
 907	},
 908	/**
 909	 * Dom遍历
 910	 * @param {Object} config
 911	 * @param {Object} config.root 遍历的根节点,表示从哪儿开始遍历
 912	 * @param {Object} config.fn 每遍历一个节点,执行的方法fn(node,root)
 913	 */
 914	traversal : function(config) {
 915		var me = this, defaultConfig = {
 916			root : document.body
 917		}
 918		me.mergeIf(config, defaultConfig);
 919		if(me.isEmpty(config.node)) {
 920			config.node = config.root;
 921		}
 922		if($kit.isFn(config.fn)) {
 923			config.fn.apply(config.node, [config.node, config.root])
 924		} else {
 925			return;
 926		}
 927		for(var i = 0; i < config.node.childNodes.length; i++) {
 928			var o = config.node.childNodes[i];
 929			me.traversal(me.join(config, {
 930				node : o
 931			}));
 932		}
 933
 934	},
 935	/**
 936	 * 返回当前元素满足条件的下一个元素
 937	 * @param {Element}
 938	 * @param {Function} condition 用于检测是否满足条件的方法,返回true表示满足
 939	 * @param {Obejct} [scope] 执行condition时候的this指针
 940	 * @return {Element}
 941	 */
 942	nextEl : function(el, condition, scope) {
 943		var me = this;
 944		if(me.isEmpty(el)) {
 945			return;
 946		}
 947		var next = null;
 948		if(el.nextElementSibling != null) {
 949			next = el.nextElementSibling;
 950		} else {
 951			var parent = el.parentNode;
 952			while(parent != null && parent.parentNode != null && parent == parent.parentNode.lastElementChild) {
 953				parent = parent.parentNode;
 954			}
 955			var firstEl = parent.nextElementSibling.firstElementChild;
 956			while(firstEl != null && firstEl.children.length > 0 && firstEl.firstElementChild != null) {
 957				firstEl = firstEl.firstElementChild;
 958			}
 959			next = firstEl;
 960		}
 961		if(next != null) {
 962			var condition = condition || null, scope = scope || null;
 963			if(me.isFn(condition)) {
 964				if(condition.call(scope, next, el) == true) {
 965					return next;
 966				} else if(condition.call(scope, next, el) == false) {
 967					return null;
 968				} else {
 969					var allNodes = document.getElementsByTagName("*");
 970					if(next != allNodes[allNodes.length - 1]) {
 971						return me.nextEl(next, condition, scope);
 972					} else {
 973						return null;
 974					}
 975				}
 976			}
 977		}
 978		return next;
 979	},
 980	/**
 981	 * 返回当前元素满足条件的前一个元素
 982	 * @param {Element}
 983	 * @param {Function} condition 用于检测是否满足条件的方法,返回true表示满足
 984	 * @param {Obejct} [scope] 执行condition时候的this指针
 985	 * @return {Element}
 986	 */
 987	prevEl : function(el, condition, scope) {
 988		var me = this;
 989		if(me.isEmpty(el)) {
 990			return;
 991		}
 992		var prev = null;
 993		if(el.previousElementSibling != null) {
 994			prev = el.previousElementSibling;
 995		} else {
 996			var parent = el.parentNode;
 997			while(parent != null && parent.parentNode != null && parent == parent.parentNode.firstElementChild) {
 998				parent = parent.parentNode;
 999			}
1000			var lastEl = parent.previousElementSibling.lastElementChild;
1001			while(lastEl != null && lastEl.children.length > 0 && lastEl.lastElementChild != null) {
1002				lastEl = lastEl.lastElementChild;
1003			}
1004			prev = lastEl;
1005		}
1006		if(prev != null) {
1007			var condition = condition || null, scope = scope || null;
1008			if(me.isFn(condition)) {
1009				if(condition.call(scope, prev, el) == true) {
1010					return prev;
1011				} else if(condition.call(scope, prev, el) == false) {
1012					return null;
1013				} else {
1014					var allNodes = document.getElementsByTagName("*");
1015					if(prev != allNodes[0]) {
1016						return me.prevEl(prev, condition, scope);
1017					} else {
1018						return null;
1019					}
1020				}
1021			}
1022		}
1023		return prev;
1024	},
1025	/**
1026	 * 返回当前元素满足条件的父元素
1027	 * @param {Element}
1028	 * @param {Function} condition 用于检测是否满足条件的方法,返回true表示满足
1029	 * @param {Obejct} [scope] 执行condition时候的this指针
1030	 * @return {Element}
1031	 */
1032	parentEl : function(el, condition, scope) {
1033		var me = this;
1034		if(me.isEmpty(el)) {
1035			return;
1036		}
1037		var parent = null;
1038		if(el.parentNode != null && el.parentNode != el) {
1039			parent = el.parentNode;
1040			var condition = condition || null, scope = scope || null;
1041			if(me.isFn(condition)) {
1042				if(condition.call(scope, parent, el) == true) {
1043					return parent;
1044				} else if(condition.call(scope, parent, el) == false) {
1045					return null;
1046				} else {
1047					return me.parentEl(parent, condition, scope);
1048				}
1049			}
1050		}
1051		return parent;
1052	},
1053	/**
1054	 * 返回一个 documentFragment,包含了HTML
1055	 * @param {String}
1056	 * @return {DocumentFragment}
1057	 */
1058	newHTML : function(html) {
1059		var me = this;
1060		if(me.isEmpty(html)) {
1061			return;
1062		}
1063		var box = document.createElement("div");
1064		box.innerHTML = html;
1065		var o = document.createDocumentFragment();
1066		while(box.childNodes && box.childNodes.length) {
1067			o.appendChild(box.childNodes[0]);
1068		}
1069		box = null;
1070		return o;
1071	},
1072	/**
1073	 * 计算元素相对于doc的 绝对偏移
1074	 * @param {Element}
1075	 * @return {Number} top 距离顶部
1076	 * @return {Number} left 距离左边
1077	 * @return {Number} height 高度
1078	 * @return {Number} width 宽度
1079	 * @return {Number} bottom 底部距离顶部
1080	 * @return {Number} right 右边距离最左边
1081	 * @return {Number} middleTop 中间距离顶部
1082	 * @return {Number} middleLeft 中间距离最左边
1083	 */
1084	offset : function(el) {
1085		var me = this;
1086		if(me.isEmpty(el)) {
1087			return;
1088		}
1089		var top = el.offsetTop, //
1090		left = el.offsetLeft, //
1091		width = el.offsetWidth, //
1092		height = el.offsetHeight;
1093		while(el.offsetParent != null && el.offsetParent != el) {
1094			el = el.offsetParent;
1095			top += el.offsetTop;
1096			left += el.offsetLeft;
1097		}
1098		return {
1099			top : top,
1100			left : left,
1101			width : width,
1102			height : height,
1103			bottom : top + height,
1104			right : left + width,
1105			middleTop : top + height / 2,
1106			middleLeft : left + width / 2
1107		}
1108	},
1109	/**
1110	 * 计算元素相对于doc的 绝对偏移
1111	 * @param {Element}
1112	 * @return {Number} clientWidth 可视内容的宽度
1113	 * @return {Number} clientHeight 可视内容的高度
1114	 * @return {Number} scrollWidth 滚动条的宽度
1115	 * @return {Number} scrollHeight 滚动条的高度
1116	 * @return {Number} scrollLeft 滚动条距离左边的宽度
1117	 * @return {Number} scrollTop 滚动条距离顶部的高度
1118	 */
1119	viewport : function() {
1120		var cWidth, cHeight, sWidth, sHeight, sLeft, sTop;
1121		if(document.compatMode == "BackCompat") {
1122			cWidth = document.body.clientWidth;
1123			cHeight = document.body.clientHeight;
1124			sWidth = document.body.scrollWidth;
1125			sHeight = document.body.scrollHeight;
1126			sLeft = document.body.scrollLeft;
1127			sTop = document.body.scrollTop;
1128		} else {//document.compatMode == "CSS1Compat"
1129			cWidth = document.documentElement.clientWidth;
1130			cHeight = document.documentElement.clientHeight;
1131			sWidth = document.documentElement.scrollWidth;
1132			sHeight = document.documentElement.scrollHeight;
1133			sLeft = document.documentElement.scrollLeft == 0 ? document.body.scrollLeft : document.documentElement.scrollLeft;
1134			sTop = document.documentElement.scrollTop == 0 ? document.body.scrollTop : document.documentElement.scrollTop;
1135		}
1136		return {
1137			clientWidth : cWidth,
1138			clientHeight : cHeight,
1139			scrollWidth : sWidth,
1140			scrollHeight : sHeight,
1141			scrollLeft : sLeft,
1142			scrollTop : sTop
1143		}
1144	},
1145	// -----------------------------------event-----------------------------------
1146	// -----------------------------------event-----------------------------------
1147	/**
1148	 * kit事件注册方法
1149	 * kitjs的事件对象event拥有以下属性
1150	 * target: 当前事件触发元素
1151	 * currentTarget:注册该事件的元素
1152	 * relatedTarget: 事件触发相关的元素,当事件在两个元素之间发生时候,这个有值,兼容了toElement,fromElement
1153	 * offsetX/Y: 事件相当于target的x,y
1154	 * clientX/Y: 事件相当于viewport的x,y
1155	 * pageX/Y: 事件相当于doc的
1156	 * firstFingerClientX/Y: 移动设备的touchmove
1157	 * firstFingerPageX/Y: 移动设备的touchmove
1158	 * stopNow(): 立即停止所有
1159	 * stopDefault(): 停止默认事件触发
1160	 * stopGoOn(): 停止冒泡
1161	 * @param {Object} config
1162	 * @param {Selector|Element|NodeList} config.el 触发事件的元素,等于event.currentTarget
1163	 * @param {String} config.ev 事件type,如click
1164	 * @param {Function} config.fn 事件方法
1165	 * @param {Object} config.scope this指针
1166	 */
1167	ev : function(config) {
1168		var me = this, defaultConfig = {
1169			el : window,
1170			ev : null,
1171			fn : null,
1172			scope : null
1173		}
1174		config = me.join(defaultConfig, config);
1175		if(me.isAry(config.el)) {
1176			for(var i = 0; i < config.el.length; i++) {
1177				me.ev(me.join(config, {
1178					el : config.el[i]
1179				}));
1180			}
1181		} else if(me.isCanSplit2Ary(config.el)) {
1182			var a = config.el.split(me.CONSTANTS.REGEXP_SPACE)
1183			for(var i = 0; i < a.length; i++) {
1184				var _el = me.el8id(a[i]);
1185				if(!me.isEmpty(_el)) {
1186					me.ev(me.join(config, {
1187						el : _el
1188					}));
1189				}
1190			}
1191		} else if(me.isStr(config.el)) {
1192			var _el = me.el(config.el);
1193			if(me.isEmpty(_el)) {
1194				_el = me.el("#" + config.el);
1195			}
1196			if(!me.isEmpty(_el)) {
1197				me.ev(me.join(config, {
1198					el : _el
1199				}));
1200			}
1201		} else if(me.isAry(config.ev)) {
1202			for(var i = 0; i < config.ev.length; i++) {
1203				me.ev(me.join(config, {
1204					ev : config.ev[i]
1205				}));
1206			}
1207		} else if(me.isCanSplit2Ary(config.ev)) {
1208			var a = config.ev.split(me.CONSTANTS.REGEXP_SPACE);
1209			for(var i = 0; i < a.length; i++) {
1210				me.ev(me.join(config, {
1211					ev : a[i]
1212				}));
1213			}
1214		} else {
1215			if(!me.isEmpty(config.el) && !me.isEmpty(config.ev) && !me.isEmpty(config.fn)) {
1216				config.ev = config.ev.toString().trim();
1217				// -------webkit support stopImmediatePropagation, so comment
1218				// this template
1219				var evReg = config.el[me.CONSTANTS.KIT_EVENT_REGISTER] = config.el[me.CONSTANTS.KIT_EVENT_REGISTER] || {};
1220				var evRegEv = evReg[me.CONSTANTS.KIT_EVENT_REGISTER_EVENT] = evReg[me.CONSTANTS.KIT_EVENT_REGISTER_EVENT] || {};
1221				var evRegFn = evReg[me.CONSTANTS.KIT_EVENT_REGISTER_FUNCTION] = evReg[me.CONSTANTS.KIT_EVENT_REGISTER_FUNCTION] || {};
1222				evRegEv[config.ev] = evRegEv[config.ev] || [];
1223				evRegFn[config.ev] = evRegFn[config.ev] || (function() {
1224					/*try {*/
1225					// stop global event on-off
1226					if(window[me.CONSTANTS.KIT_EVENT_STOPALLEVENT]) {
1227						return;
1228					}
1229					var EV = arguments[0] || window.event;
1230
1231					me.mergeIf(EV, {
1232						target : EV.target || EV.srcElement,
1233						currentTarget : config.el,
1234						relatedTarget : EV.relatedTarget ? EV.relatedTarget : EV.toElement || EV.fromElement
1235					});
1236					//add dragElement temp reg
1237					if(!$kit.isEmpty($kit.event) && $kit.isEmpty(EV.relatedTarget) && !$kit.isEmpty($kit.event.dragElement) && (EV.type.indexOf('drag') == 0 || EV.type.indexOf('drop') == 0)) {
1238						EV.dragElement = $kit.event.dragElement;
1239					}
1240					me.mergeIf(EV, {
1241						stopNow : function() {
1242							EV.stopPropagation && EV.stopPropagation();
1243							EV.preventDefault && EV.preventDefault();
1244							//
1245							EV.cancelBubble = true;
1246							EV.returnValue = false;
1247							//
1248							window[me.CONSTANTS.KIT_EVENT_STOPIMMEDIATEPROPAGATION] = true;
1249						},
1250						stopDefault : function() {
1251							EV.preventDefault && EV.preventDefault();
1252							EV.returnValue = false;
1253						},
1254						stopGoOn : function() {
1255							//EV.preventDefault && EV.preventDefault();
1256							EV.stopPropagation && EV.stopPropagation();
1257							//
1258							EV.cancelBubble = true;
1259							//EV.returnValue = false;
1260						}
1261					}, me.evExtra(EV));
1262					var target = config.el;
1263					var evQueue = target[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_EVENT][config.ev];
1264					var returnValue;
1265					for(var i = 0; i < evQueue.length; i++) {
1266						if(window[me.CONSTANTS.KIT_EVENT_STOPIMMEDIATEPROPAGATION]) {
1267							break;
1268						}
1269						var _evConfig = evQueue[i];
1270						returnValue = _evConfig.fn.apply(_evConfig.scope || _evConfig.el, [EV, _evConfig]);
1271					}
1272					window[me.CONSTANTS.KIT_EVENT_STOPIMMEDIATEPROPAGATION] = false;
1273					/*
1274					 } catch(e) {
1275					 alert(e);
1276					 throw e;
1277					 };*/
1278					if(returnValue != null) {
1279						return returnValue;
1280					}
1281				});
1282				if(document.attachEvent) {
1283					config.el.attachEvent('on' + config.ev, config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_FUNCTION][config.ev]);
1284				} else {
1285					config.el.addEventListener(config.ev, config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_FUNCTION][config.ev], false);
1286				}
1287				evRegEv[config.ev].push(config);
1288			} else {
1289				if(!me.isEmpty(config.el) && !me.isEmpty(config.ev) && me.isEmpty(config.fn)) {
1290					if(window[me.CONSTANTS.KIT_EVENT_STOPALLEVENT]) {
1291						return;
1292					}
1293					// var evt = document.createEvent('Event');
1294					// evt.initEvent(config.ev, true, true);
1295					// config.el.dispatchEvent(evt);
1296					me.newEv({
1297						el : config.el,
1298						type : 'Events',
1299						ev : config.ev,
1300						bubbles : true,
1301						cancelable : true
1302					});
1303				}
1304			}
1305		}
1306	},
1307	/**
1308	 * kit事件注销方法
1309	 * @param {Object} config
1310	 * @param {Selector|Element|NodeList} config.el 触发事件的元素,等于event.currentTarget
1311	 * @param {String} [config.ev] 事件type,如无,则注销该元素下所有类型的事件
1312	 * @param {Function} [config.fn] 事件方法,如有,则根据toString对比,找到后注销,如无,则注销该事件下所有的方法
1313	 */
1314	delEv : function(config) {
1315		var me = this, defaultConfig = {
1316			el : window,
1317			ev : null,
1318			fn : null
1319		}
1320		config = me.join(defaultConfig, config);
1321		if(me.isAry(config.el)) {
1322			for(var i = 0; i < config.el.length; i++) {
1323				me.delEv(me.join(config, {
1324					el : config.el[i]
1325				}));
1326			}
1327		} else if(me.isCanSplit2Ary(config.el)) {
1328			var a = config.el.split(me.CONSTANTS.REGEXP_SPACE)
1329			for(var i = 0; i < a.length; i++) {
1330				var _el = me.el8id(a[i]);
1331				if(!me.isEmpty(_el)) {
1332					me.delEv(me.join(config, {
1333						el : _el
1334					}));
1335				}
1336			}
1337		} else if(me.isStr(config.el)) {
1338			var _el = me.el8id(config.el);
1339			if(me.isEmpty(_el)) {
1340				_el = me.el("#" + config.el);
1341			}
1342			if(!me.isEmpty(_el)) {
1343				me.delEv(me.join(config, {
1344					el : _el
1345				}));
1346			}
1347		} else if(me.isAry(config.ev)) {
1348			for(var i = 0; i < config.ev.length; i++) {
1349				me.delEv(me.join(config, {
1350					ev : config.ev[i]
1351				}));
1352			}
1353		} else if(me.isCanSplit2Ary(config.ev)) {
1354			var a = config.ev.split(me.CONSTANTS.REGEXP_SPACE)
1355			for(var i = 0; i < a.length; i++) {
1356				me.delEv(me.join(config, {
1357					ev : a[i]
1358				}));
1359			}
1360		} else if(!me.isEmpty(config.el)) {
1361			if(!me.isEmpty(config.ev)) {
1362				config.ev = config.ev.toString().trim();
1363				if(!me.isEmpty(config.fn)) {
1364					var evQueue = config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_EVENT][config.ev];
1365					for(var i = 0; i < evQueue.length; i++) {
1366						var _config = evQueue[i];
1367						if(_config.fn == config.fn || _config.fn.toString() == config.fn.toString() || me.trimAll(_config.fn.toString()) == me.trimAll(config.fn.toString())) {
1368							evQueue.splice(i, 1);
1369						}
1370					}
1371					if(evQueue.length == 0) {
1372						delete config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_EVENT][config.ev];
1373						rmEv(config.el, config.ev, config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_FUNCTION][config.ev]);
1374						delete config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_FUNCTION][config.ev];
1375					}
1376				} else {
1377					delete config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_EVENT][config.ev];
1378					rmEv(config.el, config.ev, config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_FUNCTION][config.ev]);
1379					delete config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_FUNCTION][config.ev];
1380				}
1381			} else {
1382				if($kit.isEmpty(config.el[me.CONSTANTS.KIT_EVENT_REGISTER]) || $kit.isEmpty(config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_EVENT])) {
1383					return;
1384				}
1385				for(var _ev in config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_EVENT]) {
1386					rmEv(config.el, _ev, config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_FUNCTION][_ev]);
1387				}
1388				delete config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_EVENT];
1389				delete config.el[me.CONSTANTS.KIT_EVENT_REGISTER][me.CONSTANTS.KIT_EVENT_REGISTER_FUNCTION];
1390			}
1391		}
1392		function rmEv(el, e, fn) {
1393			if(document.attachEvent) {
1394				el.detachEvent('on' + e, fn);
1395			} else {
1396				el.removeEventListener(e, fn, false);
1397			}
1398		}
1399
1400	},
1401	/**
1402	 * 触发事件
1403	 * @param {Object} config
1404	 * @param {Element} config.el 触发元素
1405	 * @param {String} [config.ev] 事件类型
1406	 */
1407	newEv : function(config) {
1408		var me = this, defaultConfig = {
1409			el : window,
1410			type : 'Events',
1411			ev : null,
1412			bubbles : false,
1413			cancelable : false
1414		}
1415		config = me.join(defaultConfig, config);
1416		if(!$kit.isEmpty(config.ev)) {
1417			if(document.createEvent) {
1418				var e = document.createEvent(config.type);
1419				e.initEvent(config.ev, config.bubbles, config.cancelable);
1420				config.el.dispatchEvent(e);
1421			} else {
1422				config.el.fireEvent('on' + config.ev);
1423			}
1424		}
1425	},
1426	/**
1427	 * set event extra info
1428	 * @param {Event}
1429	 * @private
1430	 */
1431	evExtra : function(ev) {
1432		var me = this;
1433		var pageX = ev.pageX || ev.clientX + me.viewport().scrollLeft;
1434		var pageY = ev.pageY || ev.clientY + me.viewport().scrollTop;
1435		var offsetX = ev.offsetY || ev.layerX;
1436		var offsetY = ev.offsetY || ev.layerY;
1437		return me.merge({
1438			pageX : pageX,
1439			pageY : pageY,
1440			offsetX : offsetX,
1441			offsetY : offsetY
1442		}, me.evPos(ev))
1443	},
1444	/**
1445	 * get event coordinate info
1446	 * @param {Event}
1447	 * @private
1448	 */
1449	evPos : function(ev) {
1450		if(ev.type.indexOf("touch") == 0 && ev.targetTouches && ev.targetTouches.length) {
1451			return {
1452				firstFingerClientX : ev.targetTouches[0].clientX,
1453				firstFingerClientY : ev.targetTouches[0].clientY,
1454				firstFingerPageX : ev.targetTouches[0].pageX,
1455				firstFingerPageY : ev.targetTouches[0].pageY
1456			}
1457		}
1458		return {
1459			firstFingerClientX : ev.clientX,
1460			firstFingerClientY : ev.clientY,
1461			firstFingerPageX : ev.pageX,
1462			firstFingerPageY : ev.pageY
1463		}
1464	},
1465	// -----------------------------------object manipulate-----------------------------------
1466	/**
1467	 * 合并对象,生成一个新的对象
1468	 * @param {Object ...}
1469	 * @return {Object}
1470	 */
1471	join : function() {
1472		var a = arguments, b = {};
1473		if(a.length == 0) {
1474			return;
1475		}
1476		for(var i = 0; i < a.length; i++) {
1477			for(var r in a[i]) {
1478				if(!$kit.isEmpty(a[i][r])) {
1479					b[r] = a[i][r];
1480				}
1481			}
1482		}
1483		return b;
1484	},
1485	/**
1486	 * 合并对象,后面所有的对象的属性都加到第一个身上
1487	 * @param {Object ...}
1488	 * @return {Object}
1489	 */
1490	merge : function() {
1491		var a = arguments;
1492		if(a.length < 2) {
1493			return;
1494		}
1495		if(a[0] != null) {
1496			for(var i = 1; i < a.length; i++) {
1497				for(var r in a[i]) {
1498					a[0][r] = a[i][r];
1499				}
1500			}
1501		}
1502		return a[0];
1503	},
1504	/**
1505	 * 合并对象,后面所有的对象的属性都加到第一个身上,注意,如果第一个有了,则不覆盖
1506	 * @param {Object ...}
1507	 * @return {Object}
1508	 */
1509	mergeIf : function() {
1510		var a = arguments;
1511		if(a.length < 2) {
1512			return;
1513		}
1514		for(var i = 1; i < a.length; i++) {
1515			for(var r in a[i]) {
1516				if(a[0][r] == null) {
1517					a[0][r] = a[i][r];
1518				}
1519			}
1520		}
1521		return a[0];
1522	},
1523	/**
1524	 * is collection include object
1525	 */
1526	/*
1527	has : function(collection, object, ignoreCase) {
1528	if( typeof (collection) == "undefined" || typeof (object) == "undefined") {
1529	return false;
1530	}
1531	var me = this, flag = false, ignoreCase = (ignoreCase == true ? ignoreCase : false);
1532	if(me.isAry(collection)) {
1533	for(var i = 0; i < collection.length; i++) {
1534	if(collection[i] == object || (ignoreCase && collection[i].toLowerCase() == object.toLowerCase())) {
1535	flag = true;
1536	break;
1537	}
1538	}
1539	} else {
1540	if(collection != null) {
1541	if( object in collection) {
1542	flag = true;
1543	} else if(ignoreCase) {
1544	for(var p in collection) {
1545	if(p.toString().toLowerCase() == object.toString().toLowerCase()) {
1546	flag = true;
1547	break;
1548	}
1549	}
1550	}
1551	}
1552	}
1553	return flag;
1554	},*/
1555
1556	// -----------------------------------log-----------------------------------
1557	/**
1558	 * 简单的log
1559	 * @param {String} info
1560	 * @param {Object} config
1561	 */
1562	log : function(info, config) {
1563		try {
1564			var me = this;
1565			config = me.merge({
1566				borderColor : "#000",
1567				container : null
1568			}, config);
1569			if(me.isAry(info)) {
1570				info = info.join("");
1571			}
1572			if(document.body) {
1573				var div;
1574				if(config.container == null) {
1575					div = document.body.appendChild(document.createElement("div"));
1576				} else {
1577					div = config.container.appendChild(document.createElement("div"));
1578				}
1579				div.className = "J_Debug_Info";
1580				div.style.borderBottom = "1px solid " + config.borderColor || "#000";
1581				try {
1582					div.innerHTML += info;
1583				} catch (e) {
1584					div.innerHTML += e.toString();
1585				}
1586			} else {
1587				alert(info);
1588			}
1589		} catch(e) {
1590			alert("error!" + e);
1591			throw e;
1592		}
1593	},
1594	/**
1595	 * 清空log
1596	 */
1597	clsLog : function() {
1598		var me = this;
1599		var a = me.els8cls("J_Debug_Info");
1600		while(a.length) {
1601			a[0].parentNode.removeChild(a[0]);
1602		}
1603	},
1604	// -----------------------------------else-----------------------------------
1605	/**
1606	 * 返回随机数
1607	 * @private
1608	 */
1609	only : function() {
1610		var rnd = Math.random(10000);
1611		return new Date().getTime().toString() + '_' + rnd.toString().substr(2, 10);
1612	},
1613	/**
1614	 * generate unique DOM id
1615	 * @return {String}
1616	 */
1617	onlyId : function() {
1618		var me = this;
1619		var id = me.CONSTANTS.KIT_DOM_ID_PREFIX + me.only();
1620		var count;
1621		if(arguments.length == 1) {
1622			count = arguments[0];
1623		} else {
1624			count = 0;
1625		}
1626		count++;
1627		if(count > me.CONSTANTS.MAX_CYCLE_COUNT) {
1628			throw "error!";
1629		}
1630		if(!me.isEmpty(me.el8id(id))) {
1631			return me.onlyId(count);
1632		}
1633		return id
1634	},
1635	/**
1636	 * 判断iOS版本信息
1637	 * @return {Object}
1638	 */
1639	iOSInfo : function() {
1640		var me = this, regExp_appleDevice = /\(([a-z; ]+)CPU ([a-z ]*)OS ([\d_]+) like Mac OS X/i;
1641		var ver, device, re;
1642		if(regExp_appleDevice.test(navigator.userAgent)) {
1643			var a = navigator.userAgent.match(regExp_appleDevice);
1644			ver = a[3].toString().trim();
1645			ver = ver.replace(/_/g, ".");
1646			device = a[1].toString().trim();
1647			device = device.substring(0, device.indexOf(";"));
1648			re = {
1649				device : device,
1650				ver : ver
1651			}
1652		}
1653		return re;
1654	},
1655	// each : function(config) {
1656	// var me = this;
1657	// var a = config.array;
1658	// for(var i = 0; i < a.length; i++) {
1659	// if(me.inAry(config.exclude, a[i])) {
1660	// continue;
1661	// } else {
1662	// config.fn.call(config.scope || this, a[i], i, a);
1663	// }
1664	// }
1665	// },
1666	/**
1667	 * 数组遍历
1668	 * @param {Array|NodeList}
1669	 * @param {Function} fn 遍历执行方法,执行方法中返回false值,则停止继续遍历
1670	 * @param {Object} [scope] 执行方法的this指针
1671	 */
1672	each : function(ary, fn, scope) {
1673		if(ary == null) {
1674			return;
1675		}
1676		var me = this;
1677		if(me.isFn(fn)) {
1678			if(me.isAry(ary)) {
1679				for(var i = 0; i < ary.length; i++) {
1680					var re = fn.call(scope || window, ary[i], i, ary);
1681					if(re == false) {
1682						break;
1683					}
1684				}
1685			} else if(me.isObj(ary)) {
1686				var i = 0;
1687				for(var k in ary) {
1688					i++;
1689					var re = fn.call(scope || window, ary[k], k, ary, i);
1690					if(re == false) {
1691						break;
1692					}
1693				}
1694			}
1695		}
1696	},
1697	/**
1698	 * 合并字符串
1699	 * @param {Array|Map}
1700	 * @param {String} connectStr 链接每个属性的字符
1701	 * @param {String} 遍历Map的时候,链接key与value的字符
1702	 * @return {String}
1703	 */
1704	concat : function(o, connectStr, connectOper) {
1705		if($kit.isStr(o)) {
1706			return o;
1707		}
1708		var connectStr = '&' || connectStr;
1709		var connectOper = '=' || connectOper;
1710		if($kit.isAry(o)) {
1711			return o.join(connectStr);
1712		}
1713		var reStr = [];
1714		this.each(o, function(v, k) {
1715			reStr.push(k + connectOper + v);
1716		});
1717		return reStr.join(connectStr);
1718	},
1719	/**
1720	 * 简单继承subClass inherit superClass
1721	 * @param {Object} config
1722	 * @param {Object} config.child 子类
1723	 * @param {Object} config.father 父类
1724	 */
1725	inherit : function(config) {
1726		var me = this, child = config.child, father = config.father;
1727		
1728		var _arguments = undefined || config.arguments;
1729		try {
1730			_arguments = arguments.callee.caller.arguments;
1731		} catch(e) {
1732			//don`t pass arguments of constructor
1733		}
1734		me.mergeIf(child.prototype, new father(_arguments));
1735		child.prototype.constructor = child;
1736		child.superClass = father;
1737	},
1738	/**
1739	 * 模板的简单实现
1740	 * @param {String} templ 模板文本
1741	 * @param {Map} data 替换对象
1742	 * <pre>
1743	 * render('this is ${obj}', {
1744	 * 	obj : 'car'
1745	 * });
1746	 * 结果:this is car
1747	 * </pre>
1748	 */
1749	tpl : function(templ, data) {
1750		// 充分利用变量,为单个节点提速
1751		// 正则尽快匹配失败
1752		// 理论上可以作为JSON的key,支持很多字符
1753		return templ.replace(/(\$)(\{([^}]*)\})/gm, function(value, clear, origin, key) {
1754			key = key.split('.');
1755			value = data[key.shift()];
1756			for(var i = 0; i < key.length; i++) {
1757				value = value[key[i]];
1758			}
1759			return (value === null || value === undefined) ? (!!clear ? '' : origin) : value;
1760		});
1761	}
1762}
1763/**
1764 * $Kit的实例,直接通过这个实例访问$Kit所有方法
1765 * @type $Kit
1766 */
1767$kit = new $Kit();
1768/**
1769 * dom ready event
1770 * @memberOf $Kit
1771 * @member $
1772 * @function
1773 * @instance
1774 * @param {Function}
1775 */
1776$kit.$ = function(fn) {
1777	document.addEventListener('DOMContentLoaded', fn, false);
1778}