dialog.js 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273
  1. /*! artDialog v6.0.5 | https://github.com/aui/artDialog */
  2. !(function () {
  3. var __modules__ = {};
  4. function require (id) {
  5. var mod = __modules__[id];
  6. var exports = 'exports';
  7. if (typeof mod === 'object') {
  8. return mod;
  9. }
  10. if (!mod[exports]) {
  11. mod[exports] = {};
  12. mod[exports] = mod.call(mod[exports], require, mod[exports], mod) || mod[exports];
  13. }
  14. return mod[exports];
  15. }
  16. function define (path, fn) {
  17. __modules__[path] = fn;
  18. }
  19. define("jquery", function () {
  20. return jQuery;
  21. });
  22. /*!
  23. * PopupJS
  24. * Date: 2014-11-09
  25. * https://github.com/aui/popupjs
  26. * (c) 2009-2014 TangBin, http://www.planeArt.cn
  27. *
  28. * This is licensed under the GNU LGPL, version 2.1 or later.
  29. * For details, see: http://www.gnu.org/licenses/lgpl-2.1.html
  30. */
  31. define("popup", function (require) {
  32. var $ = require("jquery");
  33. var _count = 0;
  34. var _isIE6 = !('minWidth' in $('html')[0].style);
  35. var _isFixed = !_isIE6;
  36. function Popup () {
  37. this.destroyed = false;
  38. this.__popup = $('<div />')
  39. /*使用 <dialog /> 元素可能导致 z-index 永远置顶的问题(chrome)*/
  40. .css({
  41. display: 'none',
  42. position: 'absolute',
  43. /*
  44. left: 0,
  45. top: 0,
  46. bottom: 'auto',
  47. right: 'auto',
  48. margin: 0,
  49. padding: 0,
  50. border: '0 none',
  51. background: 'transparent'
  52. */
  53. outline: 0
  54. })
  55. .attr('tabindex', '-1')
  56. .html(this.innerHTML)
  57. .appendTo('body');
  58. this.__backdrop = this.__mask = $('<div />')
  59. .css({
  60. opacity: .7,
  61. background: '#000'
  62. });
  63. // 使用 HTMLElement 作为外部接口使用,而不是 jquery 对象
  64. // 统一的接口利于未来 Popup 移植到其他 DOM 库中
  65. this.node = this.__popup[0];
  66. this.backdrop = this.__backdrop[0];
  67. _count ++;
  68. }
  69. $.extend(Popup.prototype, {
  70. /**
  71. * 初始化完毕事件,在 show()、showModal() 执行
  72. * @name Popup.prototype.onshow
  73. * @event
  74. */
  75. /**
  76. * 关闭事件,在 close() 执行
  77. * @name Popup.prototype.onclose
  78. * @event
  79. */
  80. /**
  81. * 销毁前事件,在 remove() 前执行
  82. * @name Popup.prototype.onbeforeremove
  83. * @event
  84. */
  85. /**
  86. * 销毁事件,在 remove() 执行
  87. * @name Popup.prototype.onremove
  88. * @event
  89. */
  90. /**
  91. * 重置事件,在 reset() 执行
  92. * @name Popup.prototype.onreset
  93. * @event
  94. */
  95. /**
  96. * 焦点事件,在 foucs() 执行
  97. * @name Popup.prototype.onfocus
  98. * @event
  99. */
  100. /**
  101. * 失焦事件,在 blur() 执行
  102. * @name Popup.prototype.onblur
  103. * @event
  104. */
  105. /** 浮层 DOM 素节点[*] */
  106. node: null,
  107. /** 遮罩 DOM 节点[*] */
  108. backdrop: null,
  109. /** 是否开启固定定位[*] */
  110. fixed: false,
  111. /** 判断对话框是否删除[*] */
  112. destroyed: true,
  113. /** 判断对话框是否显示 */
  114. open: false,
  115. /** close 返回值 */
  116. returnValue: '',
  117. /** 是否自动聚焦 */
  118. autofocus: true,
  119. /** 对齐方式[*] */
  120. align: 'bottom left',
  121. /** 内部的 HTML 字符串 */
  122. innerHTML: '',
  123. /** CSS 类名 */
  124. className: 'ui-popup',
  125. /**
  126. * 显示浮层
  127. * @param {HTMLElement, Event} 指定位置(可选)
  128. */
  129. show: function (anchor) {
  130. if (this.destroyed) {
  131. return this;
  132. }
  133. var that = this;
  134. var popup = this.__popup;
  135. var backdrop = this.__backdrop;
  136. this.__activeElement = this.__getActive();
  137. this.open = true;
  138. this.follow = anchor || this.follow;
  139. // 初始化 show 方法
  140. if (!this.__ready) {
  141. popup
  142. .addClass(this.className)
  143. .attr('role', this.modal ? 'alertdialog' : 'dialog')
  144. .css('position', this.fixed ? 'fixed' : 'absolute');
  145. if (!_isIE6) {
  146. $(window).on('resize', $.proxy(this.reset, this));
  147. }
  148. // 模态浮层的遮罩
  149. if (this.modal) {
  150. var backdropCss = {
  151. position: 'fixed',
  152. left: 0,
  153. top: 0,
  154. width: '100%',
  155. height: '100%',
  156. overflow: 'hidden',
  157. userSelect: 'none',
  158. zIndex: this.zIndex || Popup.zIndex
  159. };
  160. popup.addClass(this.className + '-modal');
  161. if (!_isFixed) {
  162. $.extend(backdropCss, {
  163. position: 'absolute',
  164. width: $(window).width() + 'px',
  165. height: $(document).height() + 'px'
  166. });
  167. }
  168. backdrop
  169. .css(backdropCss)
  170. .attr({tabindex: '0'})
  171. .on('focus', $.proxy(this.focus, this));
  172. // 锁定 tab 的焦点操作
  173. this.__mask = backdrop
  174. .clone(true)
  175. .attr('style', '')
  176. .insertAfter(popup);
  177. backdrop
  178. .addClass(this.className + '-backdrop')
  179. .insertBefore(popup);
  180. this.__ready = true;
  181. }
  182. if (!popup.html()) {
  183. popup.html(this.innerHTML);
  184. }
  185. }
  186. popup
  187. .addClass(this.className + '-show')
  188. .show();
  189. backdrop.show();
  190. this.reset().focus();
  191. this.__dispatchEvent('show');
  192. return this;
  193. },
  194. /** 显示模态浮层。参数参见 show() */
  195. showModal: function () {
  196. this.modal = true;
  197. return this.show.apply(this, arguments);
  198. },
  199. /** 关闭浮层 */
  200. close: function (result) {
  201. if (!this.destroyed && this.open) {
  202. if (result !== undefined) {
  203. this.returnValue = result;
  204. }
  205. this.__popup.hide().removeClass(this.className + '-show');
  206. this.__backdrop.hide();
  207. this.open = false;
  208. this.blur();// 恢复焦点,照顾键盘操作的用户
  209. this.__dispatchEvent('close');
  210. }
  211. return this;
  212. },
  213. /** 销毁浮层 */
  214. remove: function () {
  215. if (this.destroyed) {
  216. return this;
  217. }
  218. this.__dispatchEvent('beforeremove');
  219. if (Popup.current === this) {
  220. Popup.current = null;
  221. }
  222. // 从 DOM 中移除节点
  223. this.__popup.remove();
  224. this.__backdrop.remove();
  225. this.__mask.remove();
  226. if (!_isIE6) {
  227. $(window).off('resize', this.reset);
  228. }
  229. this.__dispatchEvent('remove');
  230. for (var i in this) {
  231. delete this[i];
  232. }
  233. return this;
  234. },
  235. /** 重置位置 */
  236. reset: function () {
  237. var elem = this.follow;
  238. if (elem) {
  239. this.__follow(elem);
  240. } else {
  241. this.__center();
  242. }
  243. this.__dispatchEvent('reset');
  244. return this;
  245. },
  246. /** 让浮层获取焦点 */
  247. focus: function () {
  248. var node = this.node;
  249. var popup = this.__popup;
  250. var current = Popup.current;
  251. var index = this.zIndex = Popup.zIndex ++;
  252. if (current && current !== this) {
  253. current.blur(false);
  254. }
  255. // 检查焦点是否在浮层里面
  256. if (!$.contains(node, this.__getActive())) {
  257. var autofocus = popup.find('[autofocus]')[0];
  258. if (!this._autofocus && autofocus) {
  259. this._autofocus = true;
  260. } else {
  261. autofocus = node;
  262. }
  263. this.__focus(autofocus);
  264. }
  265. // 设置叠加高度
  266. popup.css('zIndex', index);
  267. //this.__backdrop.css('zIndex', index);
  268. Popup.current = this;
  269. popup.addClass(this.className + '-focus');
  270. this.__dispatchEvent('focus');
  271. return this;
  272. },
  273. /** 让浮层失去焦点。将焦点退还给之前的元素,照顾视力障碍用户 */
  274. blur: function () {
  275. var activeElement = this.__activeElement;
  276. var isBlur = arguments[0];
  277. if (isBlur !== false) {
  278. this.__focus(activeElement);
  279. }
  280. this._autofocus = false;
  281. this.__popup.removeClass(this.className + '-focus');
  282. this.__dispatchEvent('blur');
  283. return this;
  284. },
  285. /**
  286. * 添加事件
  287. * @param {String} 事件类型
  288. * @param {Function} 监听函数
  289. */
  290. addEventListener: function (type, callback) {
  291. this.__getEventListener(type).push(callback);
  292. return this;
  293. },
  294. /**
  295. * 删除事件
  296. * @param {String} 事件类型
  297. * @param {Function} 监听函数
  298. */
  299. removeEventListener: function (type, callback) {
  300. var listeners = this.__getEventListener(type);
  301. for (var i = 0; i < listeners.length; i ++) {
  302. if (callback === listeners[i]) {
  303. listeners.splice(i--, 1);
  304. }
  305. }
  306. return this;
  307. },
  308. // 获取事件缓存
  309. __getEventListener: function (type) {
  310. var listener = this.__listener;
  311. if (!listener) {
  312. listener = this.__listener = {};
  313. }
  314. if (!listener[type]) {
  315. listener[type] = [];
  316. }
  317. return listener[type];
  318. },
  319. // 派发事件
  320. __dispatchEvent: function (type) {
  321. var listeners = this.__getEventListener(type);
  322. if (this['on' + type]) {
  323. this['on' + type]();
  324. }
  325. for (var i = 0; i < listeners.length; i ++) {
  326. listeners[i].call(this);
  327. }
  328. },
  329. // 对元素安全聚焦
  330. __focus: function (elem) {
  331. // 防止 iframe 跨域无权限报错
  332. // 防止 IE 不可见元素报错
  333. try {
  334. // ie11 bug: iframe 页面点击会跳到顶部
  335. if (this.autofocus && !/^iframe$/i.test(elem.nodeName)) {
  336. elem.focus();
  337. }
  338. } catch (e) {}
  339. },
  340. // 获取当前焦点的元素
  341. __getActive: function () {
  342. try {// try: ie8~9, iframe #26
  343. var activeElement = document.activeElement;
  344. var contentDocument = activeElement.contentDocument;
  345. var elem = contentDocument && contentDocument.activeElement || activeElement;
  346. return elem;
  347. } catch (e) {}
  348. },
  349. // 居中浮层
  350. __center: function () {
  351. var popup = this.__popup;
  352. var $window = $(window);
  353. var $document = $(document);
  354. var fixed = this.fixed;
  355. var dl = fixed ? 0 : $document.scrollLeft();
  356. var dt = fixed ? 0 : $document.scrollTop();
  357. var ww = $window.width();
  358. var wh = $window.height();
  359. var ow = popup.width();
  360. var oh = popup.height();
  361. var left = (ww - ow) / 2 + dl;
  362. var top = (wh - oh) * 382 / 1000 + dt;// 黄金比例
  363. var style = popup[0].style;
  364. style.left = Math.max(parseInt(left), dl) + 'px';
  365. style.top = Math.max(parseInt(top), dt) + 'px';
  366. },
  367. // 指定位置 @param {HTMLElement, Event} anchor
  368. __follow: function (anchor) {
  369. var $elem = anchor.parentNode && $(anchor);
  370. var popup = this.__popup;
  371. if (this.__followSkin) {
  372. popup.removeClass(this.__followSkin);
  373. }
  374. // 隐藏元素不可用
  375. if ($elem) {
  376. var o = $elem.offset();
  377. if (o.left * o.top < 0) {
  378. return this.__center();
  379. }
  380. }
  381. var that = this;
  382. var fixed = this.fixed;
  383. var $window = $(window);
  384. var $document = $(document);
  385. var winWidth = $window.width();
  386. var winHeight = $window.height();
  387. var docLeft = $document.scrollLeft();
  388. var docTop = $document.scrollTop();
  389. var popupWidth = popup.width();
  390. var popupHeight = popup.height();
  391. var width = $elem ? $elem.outerWidth() : 0;
  392. var height = $elem ? $elem.outerHeight() : 0;
  393. var offset = this.__offset(anchor);
  394. var x = offset.left;
  395. var y = offset.top;
  396. var left = fixed ? x - docLeft : x;
  397. var top = fixed ? y - docTop : y;
  398. var minLeft = fixed ? 0 : docLeft;
  399. var minTop = fixed ? 0 : docTop;
  400. var maxLeft = minLeft + winWidth - popupWidth;
  401. var maxTop = minTop + winHeight - popupHeight;
  402. var css = {};
  403. var align = this.align.split(' ');
  404. var className = this.className + '-';
  405. var reverse = {top: 'bottom', bottom: 'top', left: 'right', right: 'left'};
  406. var name = {top: 'top', bottom: 'top', left: 'left', right: 'left'};
  407. var temp = [{
  408. top: top - popupHeight,
  409. bottom: top + height,
  410. left: left - popupWidth,
  411. right: left + width
  412. }, {
  413. top: top,
  414. bottom: top - popupHeight + height,
  415. left: left,
  416. right: left - popupWidth + width
  417. }];
  418. var center = {
  419. left: left + width / 2 - popupWidth / 2,
  420. top: top + height / 2 - popupHeight / 2
  421. };
  422. var range = {
  423. left: [minLeft, maxLeft],
  424. top: [minTop, maxTop]
  425. };
  426. // 超出可视区域重新适应位置
  427. $.each(align, function (i, val) {
  428. // 超出右或下边界:使用左或者上边对齐
  429. if (temp[i][val] > range[name[val]][1]) {
  430. val = align[i] = reverse[val];
  431. }
  432. // 超出左或右边界:使用右或者下边对齐
  433. if (temp[i][val] < range[name[val]][0]) {
  434. align[i] = reverse[val];
  435. }
  436. });
  437. // 一个参数的情况
  438. if (!align[1]) {
  439. name[align[1]] = name[align[0]] === 'left' ? 'top' : 'left';
  440. temp[1][align[1]] = center[name[align[1]]];
  441. }
  442. //添加follow的css, 为了给css使用
  443. className += align.join('-') + ' '+ this.className+ '-follow';
  444. that.__followSkin = className;
  445. if ($elem) {
  446. popup.addClass(className);
  447. }
  448. css[name[align[0]]] = parseInt(temp[0][align[0]]);
  449. css[name[align[1]]] = parseInt(temp[1][align[1]]);
  450. popup.css(css);
  451. },
  452. // 获取元素相对于页面的位置(包括iframe内的元素)
  453. // 暂时不支持两层以上的 iframe 套嵌
  454. __offset: function (anchor) {
  455. var isNode = anchor.parentNode;
  456. var offset = isNode ? $(anchor).offset() : {
  457. left: anchor.pageX,
  458. top: anchor.pageY
  459. };
  460. anchor = isNode ? anchor : anchor.target;
  461. var ownerDocument = anchor.ownerDocument;
  462. var defaultView = ownerDocument.defaultView || ownerDocument.parentWindow;
  463. if (defaultView == window) {// IE <= 8 只能使用两个等于号
  464. return offset;
  465. }
  466. // {Element: Ifarme}
  467. var frameElement = defaultView.frameElement;
  468. var $ownerDocument = $(ownerDocument);
  469. var docLeft = $ownerDocument.scrollLeft();
  470. var docTop = $ownerDocument.scrollTop();
  471. var frameOffset = $(frameElement).offset();
  472. var frameLeft = frameOffset.left;
  473. var frameTop = frameOffset.top;
  474. return {
  475. left: offset.left + frameLeft - docLeft,
  476. top: offset.top + frameTop - docTop
  477. };
  478. }
  479. });
  480. /** 当前叠加高度 */
  481. Popup.zIndex = 1024;
  482. /** 顶层浮层的实例 */
  483. Popup.current = null;
  484. return Popup;
  485. });
  486. // artDialog - 默认配置
  487. define("dialog-config", {
  488. /* -----已注释的配置继承自 popup.js,仍可以再这里重新定义它----- */
  489. // 对齐方式
  490. //align: 'bottom left',
  491. // 是否固定定位
  492. //fixed: false,
  493. // 对话框叠加高度值(重要:此值不能超过浏览器最大限制)
  494. //zIndex: 1024,
  495. // 设置遮罩背景颜色
  496. backdropBackground: '#000',
  497. // 设置遮罩透明度
  498. backdropOpacity: 0.7,
  499. // 消息内容
  500. content: '<span class="ui-dialog-loading">Loading..</span>',
  501. // 标题
  502. title: '',
  503. // 对话框状态栏区域 HTML 代码
  504. statusbar: '',
  505. // 自定义按钮
  506. button: null,
  507. // 确定按钮回调函数
  508. ok: null,
  509. // 取消按钮回调函数
  510. cancel: null,
  511. // 确定按钮文本
  512. okValue: 'ok',
  513. // 取消按钮文本
  514. cancelValue: 'cancel',
  515. cancelDisplay: true,
  516. // 内容宽度
  517. width: '',
  518. // 内容高度
  519. height: '',
  520. // 内容与边界填充距离
  521. padding: '',
  522. // 对话框自定义 className
  523. skin: '',
  524. // 是否支持快捷关闭(点击遮罩层自动关闭)
  525. quickClose: false,
  526. // css 文件路径,留空则不会使用 js 自动加载样式
  527. // 注意:css 只允许加载一个
  528. cssUri: '../css/ui-dialog.css',
  529. // 模板(使用 table 解决 IE7 宽度自适应的 BUG)
  530. // js 使用 i="***" 属性识别结构,其余的均可自定义
  531. innerHTML:
  532. '<div i="dialog" class="ui-dialog">'
  533. + '<div class="ui-dialog-arrow-a"></div>'
  534. + '<div class="ui-dialog-arrow-b"></div>'
  535. + '<table class="ui-dialog-grid">'
  536. + '<tr>'
  537. + '<td i="header" class="ui-dialog-header">'
  538. + '<button i="close" class="ui-dialog-close">&#215;</button>'
  539. + '<div i="title" class="ui-dialog-title"></div>'
  540. + '</td>'
  541. + '</tr>'
  542. + '<tr>'
  543. + '<td i="body" class="ui-dialog-body">'
  544. + '<div i="content" class="ui-dialog-content"></div>'
  545. + '</td>'
  546. + '</tr>'
  547. + '<tr>'
  548. + '<td i="footer" class="ui-dialog-footer">'
  549. + '<div i="statusbar" class="ui-dialog-statusbar"></div>'
  550. + '<div i="button" class="ui-dialog-button"></div>'
  551. + '</td>'
  552. + '</tr>'
  553. + '</table>'
  554. +'</div>'
  555. });
  556. /*!
  557. * artDialog
  558. * Date: 2014-11-09
  559. * https://github.com/aui/artDialog
  560. * (c) 2009-2014 TangBin, http://www.planeArt.cn
  561. *
  562. * This is licensed under the GNU LGPL, version 2.1 or later.
  563. * For details, see: http://www.gnu.org/licenses/lgpl-2.1.html
  564. */
  565. define("dialog", function (require) {
  566. var $ = require("jquery");
  567. var Popup = require("popup");
  568. var defaults = require("dialog-config");
  569. var css = defaults.cssUri;
  570. // css loader: RequireJS & SeaJS
  571. if (css) {
  572. var fn = require[require.toUrl ? 'toUrl' : 'resolve'];
  573. if (fn) {
  574. css = fn(css);
  575. css = '<link rel="stylesheet" href="' + css + '" />';
  576. if ($('base')[0]) {
  577. $('base').before(css);
  578. } else {
  579. $('head').append(css);
  580. }
  581. }
  582. }
  583. var _count = 0;
  584. var _expando = new Date() - 0; // Date.now()
  585. var _isIE6 = !('minWidth' in $('html')[0].style);
  586. var _isMobile = 'createTouch' in document && !('onmousemove' in document)
  587. || /(iPhone|iPad|iPod)/i.test(navigator.userAgent);
  588. var _isFixed = !_isIE6 && !_isMobile;
  589. var artDialog = function (options, ok, cancel) {
  590. var originalOptions = options = options || {};
  591. if (typeof options === 'string' || options.nodeType === 1) {
  592. options = {content: options, fixed: !_isMobile};
  593. }
  594. options = $.extend(true, {}, artDialog.defaults, options);
  595. options.original = originalOptions;
  596. var id = options.id = options.id || _expando + _count;
  597. var api = artDialog.get(id);
  598. // 如果存在同名的对话框对象,则直接返回
  599. if (api) {
  600. return api.focus();
  601. }
  602. // 目前主流移动设备对fixed支持不好,禁用此特性
  603. if (!_isFixed) {
  604. options.fixed = false;
  605. }
  606. // 快捷关闭支持:点击对话框外快速关闭对话框
  607. if (options.quickClose) {
  608. options.modal = true;
  609. options.backdropOpacity = 0;
  610. }
  611. // 按钮组
  612. if (!$.isArray(options.button)) {
  613. options.button = [];
  614. }
  615. // 取消按钮
  616. if (cancel !== undefined) {
  617. options.cancel = cancel;
  618. }
  619. if (options.cancel) {
  620. options.button.push({
  621. id: 'cancel',
  622. value: options.cancelValue,
  623. callback: options.cancel,
  624. display: options.cancelDisplay
  625. });
  626. }
  627. // 确定按钮
  628. if (ok !== undefined) {
  629. options.ok = ok;
  630. }
  631. if (options.ok) {
  632. options.button.push({
  633. id: 'ok',
  634. value: options.okValue,
  635. callback: options.ok,
  636. autofocus: true
  637. });
  638. }
  639. return artDialog.list[id] = new artDialog.create(options);
  640. };
  641. var popup = function () {};
  642. popup.prototype = Popup.prototype;
  643. var prototype = artDialog.prototype = new popup();
  644. artDialog.create = function (options) {
  645. var that = this;
  646. $.extend(this, new Popup());
  647. var originalOptions = options.original;
  648. var $popup = $(this.node).html(options.innerHTML);
  649. var $backdrop = $(this.backdrop);
  650. this.options = options;
  651. this._popup = $popup;
  652. $.each(options, function (name, value) {
  653. if (typeof that[name] === 'function') {
  654. that[name](value);
  655. } else {
  656. that[name] = value;
  657. }
  658. });
  659. // 更新 zIndex 全局配置
  660. if (options.zIndex) {
  661. Popup.zIndex = options.zIndex;
  662. }
  663. // 设置 ARIA 信息
  664. $popup.attr({
  665. 'aria-labelledby': this._$('title')
  666. .attr('id', 'title:' + this.id).attr('id'),
  667. 'aria-describedby': this._$('content')
  668. .attr('id', 'content:' + this.id).attr('id')
  669. });
  670. // 关闭按钮
  671. this._$('close')
  672. .css('display', this.cancel === false ? 'none' : '')
  673. .attr('title', this.cancelValue)
  674. .on('click', function (event) {
  675. that._trigger('cancel');
  676. event.preventDefault();
  677. });
  678. // 添加视觉参数
  679. this._$('dialog').addClass(this.skin);
  680. this._$('body').css('padding', this.padding);
  681. // 点击任意空白处关闭对话框
  682. if (options.quickClose) {
  683. $backdrop
  684. .on(
  685. 'onmousedown' in document ? 'mousedown' : 'click',
  686. function () {
  687. that._trigger('cancel');
  688. return false;// 阻止抢夺焦点
  689. });
  690. }
  691. // 遮罩设置
  692. this.addEventListener('show', function () {
  693. $backdrop.css({
  694. opacity: 0,
  695. background: options.backdropBackground
  696. }).animate(
  697. {opacity: options.backdropOpacity}
  698. , 150);
  699. });
  700. // ESC 快捷键关闭对话框
  701. this._esc = function (event) {
  702. var target = event.target;
  703. var nodeName = target.nodeName;
  704. var rinput = /^input|textarea$/i;
  705. var isTop = Popup.current === that;
  706. var keyCode = event.keyCode;
  707. // 避免输入状态中 ESC 误操作关闭
  708. if (!isTop || rinput.test(nodeName) && target.type !== 'button') {
  709. return;
  710. }
  711. if (keyCode === 27) {
  712. that._trigger('cancel');
  713. }
  714. };
  715. $(document).on('keydown', this._esc);
  716. this.addEventListener('remove', function () {
  717. $(document).off('keydown', this._esc);
  718. delete artDialog.list[this.id];
  719. });
  720. _count ++;
  721. artDialog.oncreate(this);
  722. return this;
  723. };
  724. artDialog.create.prototype = prototype;
  725. $.extend(prototype, {
  726. /**
  727. * 显示对话框
  728. * @name artDialog.prototype.show
  729. * @param {HTMLElement Object, Event Object} 指定位置(可选)
  730. */
  731. /**
  732. * 显示对话框(模态)
  733. * @name artDialog.prototype.showModal
  734. * @param {HTMLElement Object, Event Object} 指定位置(可选)
  735. */
  736. /**
  737. * 关闭对话框
  738. * @name artDialog.prototype.close
  739. * @param {String, Number} 返回值,可被 onclose 事件收取(可选)
  740. */
  741. /**
  742. * 销毁对话框
  743. * @name artDialog.prototype.remove
  744. */
  745. /**
  746. * 重置对话框位置
  747. * @name artDialog.prototype.reset
  748. */
  749. /**
  750. * 让对话框聚焦(同时置顶)
  751. * @name artDialog.prototype.focus
  752. */
  753. /**
  754. * 让对话框失焦(同时置顶)
  755. * @name artDialog.prototype.blur
  756. */
  757. /**
  758. * 添加事件
  759. * @param {String} 事件类型
  760. * @param {Function} 监听函数
  761. * @name artDialog.prototype.addEventListener
  762. */
  763. /**
  764. * 删除事件
  765. * @param {String} 事件类型
  766. * @param {Function} 监听函数
  767. * @name artDialog.prototype.removeEventListener
  768. */
  769. /**
  770. * 对话框显示事件,在 show()、showModal() 执行
  771. * @name artDialog.prototype.onshow
  772. * @event
  773. */
  774. /**
  775. * 关闭事件,在 close() 执行
  776. * @name artDialog.prototype.onclose
  777. * @event
  778. */
  779. /**
  780. * 销毁前事件,在 remove() 前执行
  781. * @name artDialog.prototype.onbeforeremove
  782. * @event
  783. */
  784. /**
  785. * 销毁事件,在 remove() 执行
  786. * @name artDialog.prototype.onremove
  787. * @event
  788. */
  789. /**
  790. * 重置事件,在 reset() 执行
  791. * @name artDialog.prototype.onreset
  792. * @event
  793. */
  794. /**
  795. * 焦点事件,在 foucs() 执行
  796. * @name artDialog.prototype.onfocus
  797. * @event
  798. */
  799. /**
  800. * 失焦事件,在 blur() 执行
  801. * @name artDialog.prototype.onblur
  802. * @event
  803. */
  804. /**
  805. * 设置内容
  806. * @param {String, HTMLElement} 内容
  807. */
  808. content: function (html) {
  809. var $content = this._$('content');
  810. // HTMLElement
  811. if (typeof html === 'object') {
  812. html = $(html);
  813. $content.empty('').append(html.show());
  814. this.addEventListener('beforeremove', function () {
  815. $('body').append(html.hide());
  816. });
  817. // String
  818. } else {
  819. $content.html(html);
  820. }
  821. return this.reset();
  822. },
  823. /**
  824. * 设置标题
  825. * @param {String} 标题内容
  826. */
  827. title: function (text) {
  828. this._$('title').text(text);
  829. this._$('header')[text ? 'show' : 'hide']();
  830. return this;
  831. },
  832. /** 设置宽度 */
  833. width: function (value) {
  834. this._$('content').css('width', value);
  835. return this.reset();
  836. },
  837. /** 设置高度 */
  838. height: function (value) {
  839. this._$('content').css('height', value);
  840. return this.reset();
  841. },
  842. /**
  843. * 设置按钮组
  844. * @param {Array, String}
  845. * Options: value, callback, autofocus, disabled
  846. */
  847. button: function (args) {
  848. args = args || [];
  849. var that = this;
  850. var html = '';
  851. var number = 0;
  852. this.callbacks = {};
  853. if (typeof args === 'string') {
  854. html = args;
  855. number ++;
  856. } else {
  857. $.each(args, function (i, val) {
  858. var id = val.id = val.id || val.value;
  859. var style = '';
  860. that.callbacks[id] = val.callback;
  861. if (val.display === false) {
  862. style = ' style="display:none"';
  863. } else {
  864. number ++;
  865. }
  866. html +=
  867. '<button'
  868. + ' type="button"'
  869. + ' i-id="' + id + '"'
  870. + style
  871. + (val.disabled ? ' disabled' : '')
  872. + (val.autofocus ? ' autofocus class="ui-dialog-autofocus"' : '')
  873. + '>'
  874. + val.value
  875. + '</button>';
  876. that._$('button')
  877. .on('click', '[i-id=' + id +']', function (event) {
  878. var $this = $(this);
  879. if (!$this.attr('disabled')) {// IE BUG
  880. that._trigger(id);
  881. }
  882. event.preventDefault();
  883. });
  884. });
  885. }
  886. this._$('button').html(html);
  887. this._$('footer')[number ? 'show' : 'hide']();
  888. return this;
  889. },
  890. statusbar: function (html) {
  891. this._$('statusbar')
  892. .html(html)[html ? 'show' : 'hide']();
  893. return this;
  894. },
  895. _$: function (i) {
  896. return this._popup.find('[i=' + i + ']');
  897. },
  898. // 触发按钮回调函数
  899. _trigger: function (id) {
  900. var fn = this.callbacks[id];
  901. return typeof fn !== 'function' || fn.call(this) !== false ?
  902. this.close().remove() : this;
  903. }
  904. });
  905. artDialog.oncreate = $.noop;
  906. /** 获取最顶层的对话框API */
  907. artDialog.getCurrent = function () {
  908. return Popup.current;
  909. };
  910. /**
  911. * 根据 ID 获取某对话框 API
  912. * @param {String} 对话框 ID
  913. * @return {Object} 对话框 API (实例)
  914. */
  915. artDialog.get = function (id) {
  916. return id === undefined
  917. ? artDialog.list
  918. : artDialog.list[id];
  919. };
  920. artDialog.list = {};
  921. /**
  922. * 默认配置
  923. */
  924. artDialog.defaults = defaults;
  925. return artDialog;
  926. });
  927. window.dialog = require("dialog");
  928. })();