msgbox.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. 'use strict';
  2. function messageBox({
  3. title, // [mandatory] string
  4. contents, // [mandatory] 1) DOM element 2) string
  5. className = '', // string, CSS class name of the message box element
  6. buttons = [], // array of strings or objects like {textContent[string], onclick[function]}.
  7. onshow, // function(messageboxElement) invoked after the messagebox is shown
  8. blockScroll, // boolean, blocks the page scroll
  9. }) { // RETURNS: Promise resolved to {button[number], enter[boolean], esc[boolean]}
  10. initOwnListeners();
  11. bindGlobalListeners();
  12. createElement();
  13. document.body.appendChild(messageBox.element);
  14. if (onshow) {
  15. onshow(messageBox.element);
  16. }
  17. return new Promise(_resolve => {
  18. messageBox.resolve = _resolve;
  19. });
  20. function initOwnListeners() {
  21. messageBox.listeners = messageBox.listeners || {
  22. closeIcon() {
  23. resolveWith({button: -1});
  24. },
  25. button() {
  26. resolveWith({button: this.buttonIndex});
  27. },
  28. key(event) {
  29. const keyCode = event.keyCode || event.which;
  30. if (!event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey
  31. && (keyCode === 13 || keyCode === 27)) {
  32. event.preventDefault();
  33. event.stopPropagation();
  34. resolveWith(keyCode === 13 ? {enter: true} : {esc: true});
  35. }
  36. },
  37. scroll() {
  38. scrollTo(blockScroll.x, blockScroll.y);
  39. }
  40. };
  41. }
  42. function resolveWith(value) {
  43. unbindGlobalListeners();
  44. setTimeout(messageBox.resolve, 0, value);
  45. animateElement(messageBox.element, {
  46. className: 'fadeout',
  47. onComplete: removeSelf,
  48. });
  49. }
  50. function createElement() {
  51. if (messageBox.element) {
  52. unbindGlobalListeners();
  53. removeSelf();
  54. }
  55. const id = 'message-box';
  56. messageBox.element = $element({id, className, appendChild: [
  57. $element({appendChild: [
  58. $element({id: `${id}-title`, textContent: title}),
  59. $element({id: `${id}-close-icon`, appendChild:
  60. $element({tag: 'SVG#svg', class: 'svg-icon', viewBox: '0 0 20 20', appendChild:
  61. $element({tag: 'SVG#path', d: 'M11.69,10l4.55,4.55-1.69,1.69L10,11.69,' +
  62. '5.45,16.23,3.77,14.55,8.31,10,3.77,5.45,5.45,3.77,10,8.31l4.55-4.55,1.69,1.69Z',
  63. })
  64. }),
  65. onclick: messageBox.listeners.closeIcon}),
  66. $element({id: `${id}-contents`, appendChild: tHTML(contents)}),
  67. $element({id: `${id}-buttons`, appendChild:
  68. buttons.map((content, buttonIndex) => content && $element({
  69. tag: 'button',
  70. buttonIndex,
  71. textContent: content.textContent || content,
  72. onclick: content.onclick || messageBox.listeners.button,
  73. }))
  74. }),
  75. ]}),
  76. ]});
  77. }
  78. function bindGlobalListeners() {
  79. blockScroll = blockScroll && {x: scrollX, y: scrollY};
  80. if (blockScroll) {
  81. window.addEventListener('scroll', messageBox.listeners.scroll);
  82. }
  83. window.addEventListener('keydown', messageBox.listeners.key, true);
  84. }
  85. function unbindGlobalListeners() {
  86. window.removeEventListener('keydown', messageBox.listeners.key, true);
  87. window.removeEventListener('scroll', messageBox.listeners.scroll);
  88. }
  89. function removeSelf() {
  90. messageBox.element.remove();
  91. messageBox.element = null;
  92. messageBox.resolve = null;
  93. }
  94. }
  95. messageBox.alert = text =>
  96. messageBox({
  97. contents: text,
  98. className: 'pre center',
  99. buttons: [t('confirmClose')]
  100. });
  101. messageBox.confirm = text =>
  102. messageBox({
  103. contents: text,
  104. className: 'pre center',
  105. buttons: [t('confirmYes'), t('confirmNo')]
  106. }).then(result => result.button === 0 || result.enter);