1. /*!
  2. * artDialog 5
  3. * Date: 2012-03-21
  4. * http://code.google.com/p/artdialog/
  5. * (c) 2009-2012 TangBin, http://www.planeArt.cn
  6. *
  7. * This is licensed under the GNU LGPL, version 2.1 or later.
  8. * For details, see: http://creativecommons.org/licenses/LGPL/2.1/
  9. */
  10.  
  11. ;(function (window, undefined) {
  12.  
  13. var $ = window.art = function (selector, context) {
  14. return new $.fn.constructor(selector, context);
  15. },
  16. quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
  17. rclass = /[\n\t]/g;
  18.  
  19. if (window.$ === undefined) {
  20. window.$ = $;
  21. };
  22.  
  23. $.fn = $.prototype = {
  24.  
  25. constructor: function (selector, context) {
  26. var match, elem;
  27. context = context || document;
  28.  
  29. if (!selector) {
  30. return this;
  31. };
  32.  
  33. if (selector.nodeType) {
  34. this[0] = selector;
  35. return this;
  36. };
  37.  
  38. if (typeof selector === 'string') {
  39. match = quickExpr.exec(selector);
  40.  
  41. if (match && match[2]) {
  42. elem = context.getElementById(match[2]);
  43. if (elem && elem.parentNode) this[0] = elem;
  44. return this;
  45. };
  46. };
  47.  
  48. this[0] = selector;
  49. return this;
  50. },
  51.  
  52. /**
  53. * 判断样式类是否存在
  54. * @param {String} 名称
  55. * @return {Boolean}
  56. */
  57. hasClass: function (name) {
  58. var className = ' ' + name + ' ';
  59.  
  60. if ((' ' + this[0].className + ' ').replace(rclass, ' ').indexOf(className) > -1) {
  61. return true;
  62. };
  63.  
  64. return false;
  65. },
  66.  
  67. /**
  68. * 添加样式类
  69. * @param {String} 名称
  70. */
  71. addClass: function (name) {
  72. if (!this.hasClass(name)) {
  73. this[0].className += ' ' + name;
  74. };
  75.  
  76. return this;
  77. },
  78.  
  79. /**
  80. * 移除样式类
  81. * @param {String} 名称
  82. */
  83. removeClass: function (name) {
  84. var elem = this[0];
  85.  
  86. if (!name) {
  87. elem.className = '';
  88. } else
  89. if (this.hasClass(name)) {
  90. elem.className = elem.className.replace(name, ' ');
  91. };
  92.  
  93. return this;
  94. },
  95.  
  96. /**
  97. * 读写样式<br />
  98. * css(name) 访问第一个匹配元素的样式属性<br />
  99. * css(properties) 把一个"名/值对"对象设置为所有匹配元素的样式属性<br />
  100. * css(name, value) 在所有匹配的元素中,设置一个样式属性的值<br />
  101. */
  102. css: function (name, value) {
  103. var i, elem = this[0], obj = arguments[0];
  104.  
  105. if (typeof name === 'string') {
  106. if (value === undefined) {
  107. return $.css(elem, name);
  108. } else {
  109. elem.style[name] = value;
  110. };
  111. } else {
  112. for (i in obj) {
  113. elem.style[i] = obj[i];
  114. };
  115. };
  116.  
  117. return this;
  118. },
  119.  
  120. /** 显示元素 */
  121. show: function () {
  122. return this.css('display', 'block');
  123. },
  124.  
  125. /** 隐藏元素 */
  126. hide: function () {
  127. return this.css('display', 'none');
  128. },
  129.  
  130. /**
  131. * 获取相对文档的坐标
  132. * @return {Object} 返回left、top的数值
  133. */
  134. offset: function () {
  135. var elem = this[0],
  136. box = elem.getBoundingClientRect(),
  137. doc = elem.ownerDocument,
  138. body = doc.body,
  139. docElem = doc.documentElement,
  140. clientTop = docElem.clientTop || body.clientTop || 0,
  141. clientLeft = docElem.clientLeft || body.clientLeft || 0,
  142. top = box.top + (self.pageYOffset || docElem.scrollTop) - clientTop,
  143. left = box.left + (self.pageXOffset || docElem.scrollLeft) - clientLeft;
  144.  
  145. return {
  146. left: left,
  147. top: top
  148. };
  149. },
  150.  
  151. /**
  152. * 读写HTML - (不支持文本框)
  153. * @param {String} 内容
  154. */
  155. html: function (content) {
  156. var elem = this[0];
  157.  
  158. if (content === undefined) return elem.innerHTML;
  159. $.cleanData(elem.getElementsByTagName('*'));
  160. elem.innerHTML = content;
  161.  
  162. return this;
  163. },
  164.  
  165. /**
  166. * 移除节点
  167. */
  168. remove: function () {
  169. var elem = this[0];
  170.  
  171. $.cleanData(elem.getElementsByTagName('*'));
  172. $.cleanData([elem]);
  173. elem.parentNode.removeChild(elem);
  174.  
  175. return this;
  176. },
  177.  
  178. /**
  179. * 事件绑定
  180. * @param {String} 类型
  181. * @param {Function} 要绑定的函数
  182. */
  183. bind: function (type, callback) {
  184. $.event.add(this[0], type, callback);
  185. return this;
  186. },
  187.  
  188. /**
  189. * 移除事件
  190. * @param {String} 类型
  191. * @param {Function} 要卸载的函数
  192. */
  193. unbind: function(type, callback) {
  194. $.event.remove(this[0], type, callback);
  195. return this;
  196. }
  197.  
  198. };
  199.  
  200. $.fn.constructor.prototype = $.fn;
  201.  
  202. /** 检测window */
  203. $.isWindow = function (obj) {
  204. return obj && typeof obj === 'object' && 'setInterval' in obj;
  205. };
  206.  
  207. /**
  208. * 搜索子元素
  209. * 注意:只支持nodeName或.className的形式,并且只返回第一个元素
  210. * @param {String}
  211. */
  212. $.fn.find = function (expr) {
  213. var value, elem = this[0],
  214. className = expr.split('.')[1];
  215.  
  216. if (className) {
  217. if (document.getElementsByClassName) {
  218. value = elem.getElementsByClassName(className);
  219. } else {
  220. value = getElementsByClassName(className, elem);
  221. };
  222. } else {
  223. value = elem.getElementsByTagName(expr);
  224. };
  225.  
  226. return $(value[0]);
  227. };
  228. function getElementsByClassName (className, node, tag) {
  229. node = node || document;
  230. tag = tag || '*';
  231. var i = 0,
  232. j = 0,
  233. classElements = [],
  234. els = node.getElementsByTagName(tag),
  235. elsLen = els.length,
  236. pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");
  237.  
  238. for (; i < elsLen; i ++) {
  239. if (pattern.test(els[i].className)) {
  240. classElements[j] = els[i];
  241. j ++;
  242. };
  243. };
  244. return classElements;
  245. };
  246.  
  247. /**
  248. * 遍历
  249. * @param {Object}
  250. * @param {Function}
  251. */
  252. $.each = function (obj, callback) {
  253. var name, i = 0,
  254. length = obj.length,
  255. isObj = length === undefined;
  256.  
  257. if (isObj) {
  258. for (name in obj) {
  259. if (callback.call(obj[name], name, obj[name]) === false) {
  260. break;
  261. };
  262. };
  263. } else {
  264. for (
  265. var value = obj[0];
  266. i < length && callback.call(value, i, value) !== false;
  267. value = obj[++i]
  268. ) {};
  269. };
  270.  
  271. return obj;
  272. };
  273.  
  274. /**
  275. * 读写缓存
  276. * @param {HTMLElement} 元素
  277. * @param {String} 缓存名称
  278. * @param {Any} 数据
  279. * @return {Any} 如果无参数data则返回缓存数据
  280. */
  281. $.data = function (elem, name, data) {
  282. var cache = $.cache,
  283. id = uuid(elem);
  284.  
  285. if (name === undefined) {
  286. return cache[id];
  287. };
  288.  
  289. if (!cache[id]) {
  290. cache[id] = {};
  291. };
  292.  
  293. if (data !== undefined) {
  294. cache[id][name] = data;
  295. };
  296.  
  297. return cache[id][name];
  298. };
  299.  
  300. /**
  301. * 删除缓存
  302. * @param {HTMLElement} 元素
  303. * @param {String} 缓存名称
  304. */
  305. $.removeData = function (elem, name) {
  306. var empty = true,
  307. expando = $.expando,
  308. cache = $.cache,
  309. id = uuid(elem),
  310. thisCache = id && cache[id];
  311.  
  312. if (!thisCache) {
  313. return;
  314. };
  315.  
  316. if (name) {
  317.  
  318. delete thisCache[name];
  319. for (var n in thisCache) {
  320. empty = false;
  321. };
  322.  
  323. if (empty) {
  324. delete $.cache[id];
  325. };
  326.  
  327. } else {
  328.  
  329. delete cache[id];
  330.  
  331. if (elem.removeAttribute) {
  332. elem.removeAttribute(expando);
  333. } else {
  334. elem[expando] = null;
  335. };
  336.  
  337. };
  338. };
  339.  
  340. $.uuid = 0;
  341. $.cache = {};
  342. $.expando = '@cache' + + new Date;
  343.  
  344. // 标记元素唯一身份
  345. function uuid (elem) {
  346. var expando = $.expando,
  347. id = elem === window ? 0 : elem[expando];
  348. if (id === undefined) elem[expando] = id = ++ $.uuid;
  349. return id;
  350. };
  351.  
  352. /**
  353. * 事件机制
  354. * @namespace
  355. * @requires [$.data, $.removeData]
  356. */
  357. $.event = {
  358.  
  359. /**
  360. * 添加事件
  361. * @param {HTMLElement} 元素
  362. * @param {String} 事件类型
  363. * @param {Function} 要添加的函数
  364. */
  365. add: function (elem, type, callback) {
  366. var cache, listeners,
  367. that = $.event,
  368. data = $.data(elem, '@events') || $.data(elem, '@events', {});
  369.  
  370. cache = data[type] = data[type] || {};
  371. listeners = cache.listeners = cache.listeners || [];
  372. listeners.push(callback);
  373.  
  374. if (!cache.handler) {
  375. cache.elem = elem;
  376. cache.handler = that.handler(cache);
  377.  
  378. elem.addEventListener
  379. ? elem.addEventListener(type, cache.handler, false)
  380. : elem.attachEvent('on' + type, cache.handler);
  381. };
  382. },
  383.  
  384. /**
  385. * 卸载事件
  386. * @param {HTMLElement} 元素
  387. * @param {String} 事件类型
  388. * @param {Function} 要卸载的函数
  389. */
  390. remove: function (elem, type, callback) {
  391. var i, cache, listeners,
  392. that = $.event,
  393. empty = true,
  394. data = $.data(elem, '@events');
  395.  
  396. if (!data) {
  397. return;
  398. };
  399.  
  400. if (!type) {
  401. for (i in data) that.remove(elem, i);
  402. return;
  403. };
  404.  
  405. cache = data[type];
  406.  
  407. if (!cache) {
  408. return;
  409. };
  410.  
  411. listeners = cache.listeners;
  412. if (callback) {
  413. for (i = 0; i < listeners.length; i ++) {
  414. listeners[i] === callback && listeners.splice(i--, 1);
  415. };
  416. } else {
  417. cache.listeners = [];
  418. };
  419.  
  420. if (cache.listeners.length === 0) {
  421. elem.removeEventListener
  422. ? elem.removeEventListener(type, cache.handler, false)
  423. : elem.detachEvent('on' + type, cache.handler);
  424.  
  425. delete data[type];
  426. cache = $.data(elem, '@events');
  427.  
  428. for (var n in cache) {
  429. empty = false;
  430. };
  431.  
  432. if (empty) {
  433. $.removeData(elem, '@events');
  434. };
  435. };
  436. },
  437.  
  438. /** @inner 事件句柄 */
  439. handler: function (cache) {
  440. return function (event) {
  441. event = $.event.fix(event || window.event);
  442. for (var i = 0, list = cache.listeners, fn; fn = list[i++];) {
  443. if (fn.call(cache.elem, event) === false) {
  444. event.preventDefault();
  445. event.stopPropagation();
  446. };
  447. };
  448. };
  449. },
  450.  
  451. /** @inner Event对象兼容处理 */
  452. fix: function (event) {
  453. if (event.target) {
  454. return event;
  455. };
  456.  
  457. var eventObj = {
  458. target: event.srcElement || document,
  459. preventDefault: function () {event.returnValue = false},
  460. stopPropagation: function () {event.cancelBubble = true}
  461. };
  462.  
  463. // IE6/7/8 在原生window.event对象写入数据会导致内存无法回收,应当采用拷贝
  464. for (var i in event) {
  465. eventObj[i] = event[i];
  466. }
  467.  
  468. return eventObj;
  469. }
  470.  
  471. };
  472.  
  473. /**
  474. * 清理元素集的事件与缓存
  475. * @requires [$.removeData, $.event]
  476. * @param {HTMLCollection} 元素集
  477. */
  478. $.cleanData = function (elems) {
  479. var i = 0, elem,
  480. len = elems.length,
  481. removeEvent = $.event.remove,
  482. removeData = $.removeData;
  483.  
  484. for (; i < len; i ++) {
  485. elem = elems[i];
  486. removeEvent(elem);
  487. removeData(elem);
  488. };
  489. };
  490.  
  491. // 获取css
  492. $.css = 'defaultView' in document && 'getComputedStyle' in document.defaultView ?
  493. function (elem, name) {
  494. return document.defaultView.getComputedStyle(elem, false)[name];
  495. } :
  496. function (elem, name) {
  497. return elem.currentStyle[name] || '';
  498. };
  499.  
  500. /**
  501. * 获取滚动条位置 - [不支持写入]
  502. * $.fn.scrollLeft, $.fn.scrollTop
  503. * @example 获取文档垂直滚动条:$(document).scrollTop()
  504. * @return {Number} 返回滚动条位置
  505. */
  506. $.each(['Left', 'Top'], function (i, name) {
  507. var method = 'scroll' + name;
  508.  
  509. $.fn[method] = function () {
  510. var elem = this[0], win;
  511.  
  512. win = getWindow(elem);
  513. return win ?
  514. ('pageXOffset' in win) ?
  515. win[i ? 'pageYOffset' : 'pageXOffset'] :
  516. win.document.documentElement[method] || win.document.body[method] :
  517. elem[method];
  518. };
  519. });
  520.  
  521. function getWindow (elem) {
  522. return $.isWindow(elem) ?
  523. elem :
  524. elem.nodeType === 9 ?
  525. elem.defaultView || elem.parentWindow :
  526. false;
  527. };
  528.  
  529. /**
  530. * 获取窗口或文档尺寸 - [只支持window与document读取]
  531. * @example
  532. 获取文档宽度:$(document).width()
  533. 获取可视范围:$(window).width()
  534. * @return {Number}
  535. */
  536. $.each(['Height', 'Width'], function (i, name) {
  537. var type = name.toLowerCase();
  538.  
  539. $.fn[type] = function (size) {
  540. var elem = this[0];
  541. if (!elem) {
  542. return size == null ? null : this;
  543. };
  544.  
  545. return $.isWindow(elem) ?
  546. elem.document.documentElement['client' + name] || elem.document.body['client' + name] :
  547. (elem.nodeType === 9) ?
  548. Math.max(
  549. elem.documentElement['client' + name],
  550. elem.body['scroll' + name], elem.documentElement['scroll' + name],
  551. elem.body['offset' + name], elem.documentElement['offset' + name]
  552. ) : null;
  553. };
  554.  
  555. });
  556.  
  557. return $}(window));
  558.  
  559. ;(function ($, window, undefined) {
  560.  
  561. // artDialog 只支持 xhtml 1.0 或者以上的 DOCTYPE 声明
  562. if (document.compatMode === 'BackCompat') {
  563. throw new Error('artDialog: Document types require more than xhtml1.0');
  564. };
  565.  
  566. var _singleton,
  567. _count = 0,
  568. _expando = 'artDialog' + + new Date,
  569. _isIE6 = window.VBArray && !window.XMLHttpRequest,
  570. _isMobile = 'createTouch' in document && !('onmousemove' in document)
  571. || /(iPhone|iPad|iPod)/i.test(navigator.userAgent),
  572. _isFixed = !_isIE6 && !_isMobile;
  573.  
  574. var artDialog = function (config, ok, cancel) {
  575.  
  576. config = config || {};
  577.  
  578. if (typeof config === 'string' || config.nodeType === 1) {
  579.  
  580. config = {content: config, fixed: !_isMobile};
  581. };
  582.  
  583. var api, defaults = artDialog.defaults;
  584. var elem = config.follow = this.nodeType === 1 && this || config.follow;
  585.  
  586. // 合并默认配置
  587. for (var i in defaults) {
  588. if (config[i] === undefined) {
  589. config[i] = defaults[i];
  590. };
  591. };
  592.  
  593. config.id = elem && elem[_expando + 'follow'] || config.id || _expando + _count;
  594. api = artDialog.list[config.id];
  595.  
  596. if (api) {
  597. if (elem) {
  598. api.follow(elem)
  599. };
  600. api.zIndex().focus();
  601. return api;
  602. };
  603.  
  604. // 目前主流移动设备对fixed支持不好
  605. if (!_isFixed) {
  606. config.fixed = false;
  607. };
  608.  
  609. // !$.isArray(config.button)
  610. if (!config.button || !config.button.push) {
  611. config.button = [];
  612. };
  613.  
  614. // 确定按钮
  615. if (ok !== undefined) {
  616. config.ok = ok;
  617. };
  618.  
  619. if (config.ok) {
  620. config.button.push({
  621. id: 'ok',
  622. value: config.okValue,
  623. callback: config.ok,
  624. focus: true
  625. });
  626. };
  627.  
  628. // 取消按钮
  629. if (cancel !== undefined) {
  630. config.cancel = cancel;
  631. };
  632.  
  633. if (config.cancel) {
  634. config.button.push({
  635. id: 'cancel',
  636. value: config.cancelValue,
  637. callback: config.cancel
  638. });
  639. };
  640.  
  641. // 更新 zIndex 全局配置
  642. artDialog.defaults.zIndex = config.zIndex;
  643.  
  644. _count ++;
  645.  
  646. return artDialog.list[config.id] = _singleton ?
  647. _singleton.constructor(config) : new artDialog.fn.constructor(config);
  648. };
  649.  
  650. artDialog.version = '5.0';
  651.  
  652. artDialog.fn = artDialog.prototype = {
  653.  
  654. /** @inner */
  655. constructor: function (config) {
  656. var dom;
  657.  
  658. this.closed = false;
  659. this.config = config;
  660. this.dom = dom = this.dom || this._getDom();
  661.  
  662. config.skin && dom.wrap.addClass(config.skin);
  663.  
  664. dom.wrap.css('position', config.fixed ? 'fixed' : 'absolute');
  665. dom.close[config.cancel === false ? 'hide' : 'show']();
  666. dom.content.css('padding', config.padding);
  667.  
  668. this.button.apply(this, config.button);
  669.  
  670. this.title(config.title)
  671. .content(config.content)
  672. .size(config.width, config.height)
  673. .time(config.time);
  674.  
  675. config.follow
  676. ? this.follow(config.follow)
  677. : this.position();
  678.  
  679. this.zIndex();
  680. config.lock && this.lock();
  681.  
  682. this._addEvent();
  683. this[config.visible ? 'visible' : 'hidden']().focus();
  684.  
  685. _singleton = null;
  686.  
  687. config.initialize && config.initialize.call(this);
  688.  
  689. return this;
  690. },
  691.  
  692. /**
  693. * 设置内容
  694. * @param {String, HTMLElement, Object} 内容 (可选)
  695. */
  696. content: function (message) {
  697.  
  698. var prev, next, parent, display,
  699. that = this,
  700. $content = this.dom.content,
  701. content = $content[0];
  702.  
  703. if (this._elemBack) {
  704. this._elemBack();
  705. delete this._elemBack;
  706. };
  707.  
  708. if (typeof message === 'string') {
  709.  
  710. $content.html(message);
  711. } else
  712.  
  713. if (message && message.nodeType === 1) {
  714.  
  715. // 让传入的元素在对话框关闭后可以返回到原来的地方
  716. display = message.style.display;
  717. prev = message.previousSibling;
  718. next = message.nextSibling;
  719. parent = message.parentNode;
  720.  
  721. this._elemBack = function () {
  722. if (prev && prev.parentNode) {
  723. prev.parentNode.insertBefore(message, prev.nextSibling);
  724. } else if (next && next.parentNode) {
  725. next.parentNode.insertBefore(message, next);
  726. } else if (parent) {
  727. parent.appendChild(message);
  728. };
  729. message.style.display = display;
  730. that._elemBack = null;
  731. };
  732.  
  733. $content.html('');
  734. content.appendChild(message);
  735. $(message).show();
  736.  
  737. };
  738.  
  739. return this.position();
  740. },
  741.  
  742. /**
  743. * 设置标题
  744. * @param {String, Boolean} 标题内容. 为 false 则隐藏标题栏
  745. */
  746. title: function (content) {
  747.  
  748. var dom = this.dom,
  749. outer = dom.outer,
  750. $title = dom.title,
  751. className = 'd-state-noTitle';
  752.  
  753. if (content === false) {
  754. $title.hide().html('');
  755. outer.addClass(className);
  756. } else {
  757. $title.show().html(content);
  758. outer.removeClass(className);
  759. };
  760.  
  761. return this;
  762. },
  763. /** @inner 位置居中 */
  764. position: function () {
  765.  
  766. var dom = this.dom,
  767. wrap = dom.wrap[0],
  768. $window = dom.window,
  769. $document = dom.document,
  770. fixed = this.config.fixed,
  771. dl = fixed ? 0 : $document.scrollLeft(),
  772. dt = fixed ? 0 : $document.scrollTop(),
  773. ww = $window.width(),
  774. wh = $window.height(),
  775. ow = wrap.offsetWidth,
  776. oh = wrap.offsetHeight,
  777. left = (ww - ow) / 2 + dl,
  778. top = top = (oh < 4 * wh / 7 ? wh * 0.382 - oh / 2 : (wh - oh) / 2) + dt,
  779. style = wrap.style;
  780.  
  781. style.left = Math.max(left, dl) + 'px';
  782. style.top = Math.max(top, dt) + 'px';
  783.  
  784. return this;
  785. },
  786.  
  787. /**
  788. * 尺寸
  789. * @param {Number, String} 宽度
  790. * @param {Number, String} 高度
  791. */
  792. size: function (width, height) {
  793.  
  794. var style = this.dom.main[0].style;
  795.  
  796. if (typeof width === 'number') {
  797. width = width + 'px';
  798. };
  799.  
  800. if (typeof height === 'number') {
  801. height = height + 'px';
  802. };
  803.  
  804. style.width = width;
  805. style.height = height;
  806.  
  807. return this;
  808. },
  809.  
  810. /**
  811. * 跟随元素
  812. * @param {HTMLElement}
  813. */
  814. follow: function (elem) {
  815.  
  816. var $elem = $(elem),
  817. config = this.config;
  818.  
  819. // 隐藏元素不可用
  820. if (!elem || !elem.offsetWidth && !elem.offsetHeight) {
  821.  
  822. return this.position(this._left, this._top);
  823. };
  824.  
  825. var fixed = config.fixed,
  826. expando = _expando + 'follow',
  827. dom = this.dom,
  828. $window = dom.window,
  829. $document = dom.document,
  830. winWidth = $window.width(),
  831. winHeight = $window.height(),
  832. docLeft = $document.scrollLeft(),
  833. docTop = $document.scrollTop(),
  834. offset = $elem.offset(),
  835. width = elem.offsetWidth,
  836. height = elem.offsetHeight,
  837. left = fixed ? offset.left - docLeft : offset.left,
  838. top = fixed ? offset.top - docTop : offset.top,
  839. wrap = this.dom.wrap[0],
  840. style = wrap.style,
  841. wrapWidth = wrap.offsetWidth,
  842. wrapHeight = wrap.offsetHeight,
  843. setLeft = left - (wrapWidth - width) / 2,
  844. setTop = top + height,
  845. dl = fixed ? 0 : docLeft,
  846. dt = fixed ? 0 : docTop;
  847.  
  848. setLeft = setLeft < dl ? left :
  849. (setLeft + wrapWidth > winWidth) && (left - wrapWidth > dl)
  850. ? left - wrapWidth + width
  851. : setLeft;
  852.  
  853. setTop = (setTop + wrapHeight > winHeight + dt)
  854. && (top - wrapHeight > dt)
  855. ? top - wrapHeight
  856. : setTop;
  857.  
  858. style.left = setLeft + 'px';
  859. style.top = setTop + 'px';
  860.  
  861. this._follow && this._follow.removeAttribute(expando);
  862. this._follow = elem;
  863. elem[expando] = config.id;
  864.  
  865. return this;
  866. },
  867.  
  868. /**
  869. * 自定义按钮
  870. * @example
  871. button({
  872. value: 'login',
  873. callback: function () {},
  874. disabled: false,
  875. focus: true
  876. }, .., ..)
  877. */
  878. button: function () {
  879.  
  880. var dom = this.dom,
  881. $buttons = dom.buttons,
  882. elem = $buttons[0],
  883. strongButton = 'd-state-highlight',
  884. listeners = this._listeners = this._listeners || {},
  885. ags = [].slice.call(arguments);
  886.  
  887. var i = 0, val, value, id, isNewButton, button;
  888.  
  889. for (; i < ags.length; i ++) {
  890.  
  891. val = ags[i];
  892.  
  893. value = val.value;
  894. id = val.id || value;
  895. isNewButton = !listeners[id];
  896. button = !isNewButton ? listeners[id].elem : document.createElement('input');
  897.  
  898. button.type = 'button';
  899. button.className = 'd-button';
  900.  
  901. if (!listeners[id]) {
  902. listeners[id] = {};
  903. };
  904.  
  905. if (value) {
  906. button.value = value;
  907. };
  908.  
  909. if (val.width) {
  910. button.style.width = val.width;
  911. };
  912.  
  913. if (val.callback) {
  914. listeners[id].callback = val.callback;
  915. };
  916.  
  917. if (val.focus) {
  918. this._focus && this._focus.removeClass(strongButton);
  919. this._focus = $(button).addClass(strongButton);
  920. this.focus();
  921. };
  922.  
  923. button[_expando + 'callback'] = id;
  924. button.disabled = !!val.disabled;
  925. if (isNewButton) {
  926. listeners[id].elem = button;
  927. elem.appendChild(button);
  928. };
  929. };
  930.  
  931. $buttons[0].style.display = ags.length ? '' : 'none';
  932.  
  933. return this;
  934. },
  935.  
  936. /** 显示对话框 */
  937. visible: function () {
  938. //this.dom.wrap.show();
  939. this.dom.wrap.css('visibility', 'visible');
  940. this.dom.outer.addClass('d-state-visible');
  941.  
  942. if (this._isLock) {
  943. this._lockMask.show();
  944. };
  945.  
  946. return this;
  947. },
  948.  
  949. /** 隐藏对话框 */
  950. hidden: function () {
  951. //this.dom.wrap.hide();
  952. this.dom.wrap.css('visibility', 'hidden');
  953. this.dom.outer.removeClass('d-state-visible');
  954.  
  955. if (this._isLock) {
  956. this._lockMask.hide();
  957. };
  958.  
  959. return this;
  960. },
  961.  
  962. /** 关闭对话框 */
  963. close: function () {
  964.  
  965. if (this.closed) {
  966. return this;
  967. };
  968.  
  969. var dom = this.dom,
  970. $wrap = dom.wrap,
  971. list = artDialog.list,
  972. beforeunload = this.config.beforeunload,
  973. follow = this.config.follow;
  974.  
  975. if (beforeunload && beforeunload.call(this) === false) {
  976. return this;
  977. };
  978.  
  979. if (artDialog.focus === this) {
  980. artDialog.focus = null;
  981. };
  982.  
  983. if (follow) {
  984. follow.removeAttribute(_expando + 'follow');
  985. };
  986.  
  987. if (this._elemBack) {
  988. this._elemBack();
  989. };
  990.  
  991. this.time();
  992. this.unlock();
  993. this._removeEvent();
  994. delete list[this.config.id];
  995.  
  996. if (_singleton) {
  997.  
  998. $wrap.remove();
  999.  
  1000. // 使用单例模式
  1001. } else {
  1002.  
  1003. _singleton = this;
  1004.  
  1005. dom.title.html('');
  1006. dom.content.html('');
  1007. dom.buttons.html('');
  1008.  
  1009. $wrap[0].className = $wrap[0].style.cssText = '';
  1010. dom.outer[0].className = 'd-outer';
  1011.  
  1012. $wrap.css({
  1013. left: 0,
  1014. top: 0,
  1015. position: _isFixed ? 'fixed' : 'absolute'
  1016. });
  1017.  
  1018. for (var i in this) {
  1019. if (this.hasOwnProperty(i) && i !== 'dom') {
  1020. delete this[i];
  1021. };
  1022. };
  1023.  
  1024. this.hidden();
  1025.  
  1026. };
  1027.  
  1028. this.closed = true;
  1029. return this;
  1030. },
  1031.  
  1032. /**
  1033. * 定时关闭
  1034. * @param {Number} 单位毫秒, 无参数则停止计时器
  1035. */
  1036. time: function (time) {
  1037.  
  1038. var that = this,
  1039. timer = this._timer;
  1040.  
  1041. timer && clearTimeout(timer);
  1042.  
  1043. if (time) {
  1044. this._timer = setTimeout(function(){
  1045. that._click('cancel');
  1046. }, time);
  1047. };
  1048.  
  1049. return this;
  1050. },
  1051.  
  1052. /** @inner 设置焦点 */
  1053. focus: function () {
  1054.  
  1055. if (this.config.focus) {
  1056. //setTimeout(function () {
  1057. try {
  1058. var elem = this._focus && this._focus[0] || this.dom.close[0];
  1059. elem && elem.focus();
  1060. // IE对不可见元素设置焦点会报错
  1061. } catch (e) {};
  1062. //}, 0);
  1063. };
  1064.  
  1065. return this;
  1066. },
  1067.  
  1068. /** 置顶对话框 */
  1069. zIndex: function () {
  1070.  
  1071. var dom = this.dom,
  1072. top = artDialog.focus,
  1073. index = artDialog.defaults.zIndex ++;
  1074.  
  1075. // 设置叠加高度
  1076. dom.wrap.css('zIndex', index);
  1077. this._lockMask && this._lockMask.css('zIndex', index - 1);
  1078.  
  1079. // 设置最高层的样式
  1080. top && top.dom.outer.removeClass('d-state-focus');
  1081. artDialog.focus = this;
  1082. dom.outer.addClass('d-state-focus');
  1083.  
  1084. return this;
  1085. },
  1086.  
  1087. /** 设置屏锁 */
  1088. lock: function () {
  1089.  
  1090. if (this._isLock) {
  1091. return this;
  1092. };
  1093.  
  1094. var that = this,
  1095. config = this.config,
  1096. dom = this.dom,
  1097. div = document.createElement('div'),
  1098. $div = $(div),
  1099. index = artDialog.defaults.zIndex - 1;
  1100.  
  1101. this.zIndex();
  1102. dom.outer.addClass('d-state-lock');
  1103.  
  1104. $div.css({
  1105. zIndex: index,
  1106. position: 'fixed',
  1107. left: 0,
  1108. top: 0,
  1109. width: '100%',
  1110. height: '100%',
  1111. overflow: 'hidden'
  1112. }).addClass('d-mask');
  1113.  
  1114. if (!_isFixed) {
  1115. $div.css({
  1116. position: 'absolute',
  1117. width: $(window).width() + 'px',
  1118. height: $(document).height() + 'px'
  1119. });
  1120. };
  1121.  
  1122. $div.bind('click', function () {
  1123. that._reset();
  1124. }).bind('dblclick', function () {
  1125. that._click('cancel');
  1126. });
  1127.  
  1128. document.body.appendChild(div);
  1129.  
  1130. this._lockMask = $div;
  1131. this._isLock = true;
  1132.  
  1133. return this;
  1134. },
  1135.  
  1136. /** 解开屏锁 */
  1137. unlock: function () {
  1138.  
  1139. if (!this._isLock) {
  1140. return this;
  1141. };
  1142.  
  1143. this._lockMask.unbind();
  1144. this._lockMask.hide();
  1145. this._lockMask.remove();
  1146.  
  1147. this.dom.outer.removeClass('d-state-lock');
  1148. this._isLock = false;
  1149.  
  1150. return this;
  1151. },
  1152.  
  1153. // 获取元素
  1154. _getDom: function () {
  1155.  
  1156. var body = document.body;
  1157.  
  1158. if (!body) {
  1159. throw new Error('artDialog: "documents.body" not ready');
  1160. };
  1161.  
  1162. var wrap = document.createElement('div');
  1163.  
  1164. wrap.style.cssText = 'position:absolute;left:0;top:0';
  1165. wrap.innerHTML = artDialog._templates;
  1166. body.insertBefore(wrap, body.firstChild);
  1167.  
  1168. var name,
  1169. i = 0,
  1170. dom = {},
  1171. els = wrap.getElementsByTagName('*'),
  1172. elsLen = els.length;
  1173.  
  1174. for (; i < elsLen; i ++) {
  1175. name = els[i].className.split('d-')[1];
  1176. if (name) {
  1177. dom[name] = $(els[i]);
  1178. };
  1179. };
  1180.  
  1181. dom.window = $(window);
  1182. dom.document = $(document);
  1183. dom.wrap = $(wrap);
  1184.  
  1185. return dom;
  1186. },
  1187.  
  1188. // 按钮回调函数触发
  1189. _click: function (id) {
  1190.  
  1191. var fn = this._listeners[id] && this._listeners[id].callback;
  1192.  
  1193. return typeof fn !== 'function' || fn.call(this) !== false ?
  1194. this.close() : this;
  1195. },
  1196.  
  1197. // 重置位置
  1198. _reset: function () {
  1199. var elem = this.config.follow;
  1200. elem ? this.follow(elem) : this.position();
  1201. },
  1202.  
  1203. // 事件代理
  1204. _addEvent: function () {
  1205.  
  1206. var that = this,
  1207. dom = this.dom;
  1208.  
  1209. // 监听点击
  1210. dom.wrap
  1211. .bind('click', function (event) {
  1212.  
  1213. var target = event.target, callbackID;
  1214.  
  1215. // IE BUG
  1216. if (target.disabled) {
  1217. return false;
  1218. };
  1219.  
  1220. if (target === dom.close[0]) {
  1221. that._click('cancel');
  1222. return false;
  1223. } else {
  1224. callbackID = target[_expando + 'callback'];
  1225. callbackID && that._click(callbackID);
  1226. };
  1227.  
  1228. })
  1229. .bind('mousedown', function () {
  1230. that.zIndex();
  1231. });
  1232.  
  1233. },
  1234.  
  1235. // 卸载事件代理
  1236. _removeEvent: function () {
  1237. this.dom.wrap.unbind();
  1238. }
  1239.  
  1240. };
  1241.  
  1242. artDialog.fn.constructor.prototype = artDialog.fn;
  1243.  
  1244. $.fn.dialog = $.fn.artDialog = function () {
  1245. var config = arguments;
  1246. this[this.live ? 'live' : 'bind']('click', function () {
  1247. artDialog.apply(this, config);
  1248. return false;
  1249. });
  1250. return this;
  1251. };
  1252.  
  1253. /** 最顶层的对话框API */
  1254. artDialog.focus = null;
  1255.  
  1256. /**
  1257. * 根据 ID 获取某对话框 API
  1258. * @param {String} 对话框 ID
  1259. * @return {Object} 对话框 API (实例)
  1260. */
  1261. artDialog.get = function (id) {
  1262. return id === undefined
  1263. ? artDialog.list
  1264. : artDialog.list[id];
  1265. };
  1266.  
  1267. artDialog.list = {};
  1268.  
  1269. // 全局快捷键
  1270. $(document).bind('keydown', function (event) {
  1271. var target = event.target,
  1272. nodeName = target.nodeName,
  1273. rinput = /^input|textarea$/i,
  1274. api = artDialog.focus,
  1275. keyCode = event.keyCode;
  1276.  
  1277. if (!api || !api.config.esc || rinput.test(nodeName) && target.type !== 'button') {
  1278. return;
  1279. };
  1280.  
  1281. // ESC
  1282. keyCode === 27 && api._click('cancel');
  1283. });
  1284.  
  1285. // 浏览器窗口改变后重置对话框位置
  1286. $(window).bind('resize', function () {
  1287. var dialogs = artDialog.list;
  1288. for (var id in dialogs) {
  1289. dialogs[id]._reset();
  1290. };
  1291. });
  1292.  
  1293. // XHTML 模板
  1294. // 使用 uglifyjs 压缩能够预先处理"+"号合并字符串
  1295. // @see http://marijnhaverbeke.nl/uglifyjs
  1296. artDialog._templates =
  1297. '<div class="d-outer">'
  1298. + '<table class="d-border">'
  1299. + '<tbody>'
  1300. + '<tr>'
  1301. + '<td class="d-nw"></td>'
  1302. + '<td class="d-n"></td>'
  1303. + '<td class="d-ne"></td>'
  1304. + '</tr>'
  1305. + '<tr>'
  1306. + '<td class="d-w"></td>'
  1307. + '<td class="d-c">'
  1308. + '<div class="d-inner">'
  1309. + '<table class="d-dialog">'
  1310. + '<tbody>'
  1311. + '<tr>'
  1312. + '<td class="d-header">'
  1313. + '<div class="d-titleBar">'
  1314. + '<div class="d-title"></div>'
  1315. + '<a class="d-close" href="javascript:/*artDialog*/;">'
  1316. + '\xd7'
  1317. + '</a>'
  1318. + '</div>'
  1319. + '</td>'
  1320. + '</tr>'
  1321. + '<tr>'
  1322. + '<td class="d-main">'
  1323. + '<div class="d-content"></div>'
  1324. + '</td>'
  1325. + '</tr>'
  1326. + '<tr>'
  1327. + '<td class="d-footer">'
  1328. + '<div class="d-buttons"></div>'
  1329. + '</td>'
  1330. + '</tr>'
  1331. + '</tbody>'
  1332. + '</table>'
  1333. + '</div>'
  1334. + '</td>'
  1335. + '<td class="d-e"></td>'
  1336. + '</tr>'
  1337. + '<tr>'
  1338. + '<td class="d-sw"></td>'
  1339. + '<td class="d-s"></td>'
  1340. + '<td class="d-se"></td>'
  1341. + '</tr>'
  1342. + '</tbody>'
  1343. + '</table>'
  1344. +'</div>';
  1345.  
  1346. /**
  1347. * 默认配置
  1348. */
  1349. artDialog.defaults = {
  1350.  
  1351. // 消息内容
  1352. content: '<div class="d-loading"><span>loading..</span></div>',
  1353.  
  1354. // 标题
  1355. title: 'message',
  1356.  
  1357. // 自定义按钮
  1358. button: null,
  1359.  
  1360. // 确定按钮回调函数
  1361. ok: null,
  1362.  
  1363. // 取消按钮回调函数
  1364. cancel: null,
  1365.  
  1366. // 对话框初始化后执行的函数
  1367. initialize: null,
  1368.  
  1369. // 对话框关闭前执行的函数
  1370. beforeunload: null,
  1371.  
  1372. // 确定按钮文本
  1373. okValue: 'ok',
  1374.  
  1375. // 取消按钮文本
  1376. cancelValue: 'cancel',
  1377.  
  1378. // 内容宽度
  1379. width: 'auto',
  1380.  
  1381. // 内容高度
  1382. height: 'auto',
  1383.  
  1384. // 内容与边界填充距离
  1385. padding: '20px 25px',
  1386.  
  1387. // 皮肤名(多皮肤共存预留接口)
  1388. skin: null,
  1389.  
  1390. // 自动关闭时间
  1391. time: null,
  1392.  
  1393. // 是否支持Esc键关闭
  1394. esc: true,
  1395.  
  1396. // 是否支持对话框按钮自动聚焦
  1397. focus: true,
  1398.  
  1399. // 初始化后是否显示对话框
  1400. visible: true,
  1401.  
  1402. // 让对话框跟随某元素
  1403. follow: null,
  1404.  
  1405. // 是否锁屏
  1406. lock: false,
  1407.  
  1408. // 是否固定定位
  1409. fixed: false,
  1410.  
  1411. // 对话框叠加高度值(重要:此值不能超过浏览器最大限制)
  1412. zIndex: 1987
  1413.  
  1414. };
  1415.  
  1416. this.artDialog = $.dialog = $.artDialog = artDialog;
  1417. }(this.art || this.jQuery, this));

封装方法到对象(javascript)的更多相关文章

  1. 使用DOM的方法获取所有li元素,然后使用jQuery()构造函数把它封装为jQuery对象

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. Javascript 封装方法

    基本封装方法 请看下面的例子: var Person = function(name,age){ this.name = name; this.age = age || "未填写" ...

  3. JavaScript Number 对象 Javascript Array对象 Location 对象方法 String对象方法

    JavaScript Number 对象 Number 对象属性 属性 描述 constructor 返回对创建此对象的 Number 函数的引用. MAX_VALUE 可表示的最大的数. MIN_V ...

  4. 分享几个Javascript 封装方法

    基本封装方法 请看下面的例子: var Person = function(name,age){ this.name = name; this.age = age || "未填写" ...

  5. JSON.stringify()方法是将一个javascript值(对象或者数组)转换成为一个JSON字符串;JSON.parse()解析JSON字符串,构造由字符串描述的javascript值或对象

    JSON.stringify()方法是将一个javascript值(对象或者数组)转换成为一个JSON字符串:JSON.parse()解析JSON字符串,构造由字符串描述的javascript值或对象

  6. 面向对象银角大王补充2-self就是调用当前方法的对象-静态字段,公有属性-封装的理解-继承的理解,普通方法,静态方法

    self是什么,就是一个函数,就是一个形式参数 4.self就是调用当前方法的对象 静态字段,公有属性 静态字段使用场景,每个对象中保存相同的东西时,可以使用静态字段,公有属性 5.封装的理解 类中封 ...

  7. JS对象 JavaScript 中的所有事物都是对象,如:字符串、数值、数组、函数等,每个对象带有属性和方法。

    什么是对象 JavaScript 中的所有事物都是对象,如:字符串.数值.数组.函数等,每个对象带有属性和方法. 对象的属性:反映该对象某些特定的性质的,如:字符串的长度.图像的长宽等: 对象的方法: ...

  8. DBUtils封装数据库返回对象的各种方法

    ①ArrayHandler:     将查询结果的第一行数据,保存到Object数组中       ②ArrayListHandler     将查询的结果,每一行先封装到Object数组中,然后将数 ...

  9. JavaScript RegExp ——对象,语法,修饰符,方括号,元字符,量词,对象方法,对象属性

    ㈠RegExp 对象 正则表达式是描述字符模式的对象. 正则表达式用于对字符串模式匹配及检索替换,是对字符串执行模式匹配的强大工具. ㈡语法 var patt=new RegExp(pattern,m ...

随机推荐

  1. elasticsearch清空type下的所有数据

    DELETE /twitter/tweet/_query{"query": { "match_all": {} }} 注:twitter为index,tweet ...

  2. 学习安卓开发过程中遇到关于R.Java文件的问题

    在学习安卓开发过程时,遇到R.java生成问题,总结几个方法解决. 1.首先必须做的就是检查代码的正确性,存在错误的代码,不编译生成R.java 2.右键点项目,选择 Android Tools -& ...

  3. jeecg308 <t:authFilter />标签失效的问题

    <%--该标签放到body末尾会无效,估计是js冲突,放到body前好用--%><t:authFilter /> <body></body>

  4. CSP学习之CryptoAPI初识

    Crypto API目的就是提供开发者在windows下使用PKI的编程接口. Crypto 提供了很多的加解密相关函数,如编码.解码.加密解密,哈希,数字证书.证书管理证书存储等.       有关 ...

  5. 9th week -the history of program 1950~2020

    We already know that programming language is a formal language designed to communicate instructions ...

  6. numpy中一些常用函数的用法总结

    先简单记录一下,后续补充详细的例子   1. strip()函数 s.strip(rm):s为字符串,rm为要删除的字符序列 只能删除开头或是结尾的字符或者字符串.不能删除中间的字符或是字符串 当rm ...

  7. ArcGIS Enterprise 10.5.1 静默安装部署记录(Centos 7.2 minimal)- 5、安装Datastore

    安装Datastore 解压datastore安装包,tar -xzvf ArcGIS_DataStore_Linux_1051_156441.tar.gz 切换到arcgis账户静默安装server ...

  8. 《ArcGIS Runtime SDK for Android开发笔记》——离在线一体化技术:概述

    1.前言 数据生产和数据展示是常见的两大专业级移动GIS应用场景,这里我们针对数据生产环节的ArcGIS的离在线一体化技术给大家做一个基本的介绍和梳理. 使用ArcGIS离在线一体化技术首先需要以下基 ...

  9. 《ArcGIS Runtime SDK for Android开发笔记》——(12)、自定义方式加载Bundle格式缓存数据

    随着ArcGIS 10.3的正式发布,Esri推出了新的紧凑型缓存格式以增强用户的访问体验.新的缓存格式下,Esri将缓存的索引信息.bundlx包含在了缓存的切片文件.bundle中.具体如下图所示 ...

  10. wxpyhon 对话框

    Python内置了好多定义好了的对话框供我们使用,这里先介绍三个最常用的: 1 Message dialog 2 Text entry 3 Choosing from a list 当然python还 ...