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