msgbox.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. messageBox.element.focus();
  18. return new Promise(_resolve => {
  19. messageBox.resolve = _resolve;
  20. });
  21. function initOwnListeners() {
  22. messageBox.listeners = messageBox.listeners || {
  23. closeIcon() {
  24. resolveWith({button: -1});
  25. },
  26. button() {
  27. resolveWith({button: this.buttonIndex});
  28. },
  29. key(event) {
  30. const keyCode = event.keyCode || event.which;
  31. if (!event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey
  32. && (keyCode === 13 || keyCode === 27)) {
  33. event.preventDefault();
  34. event.stopPropagation();
  35. resolveWith(keyCode === 13 ? {enter: true} : {esc: true});
  36. }
  37. },
  38. scroll() {
  39. scrollTo(blockScroll.x, blockScroll.y);
  40. }
  41. };
  42. }
  43. function resolveWith(value) {
  44. unbindGlobalListeners();
  45. setTimeout(messageBox.resolve, 0, value);
  46. animateElement(messageBox.element, {
  47. className: 'fadeout',
  48. onComplete: removeSelf,
  49. });
  50. }
  51. function createElement() {
  52. if (messageBox.element) {
  53. unbindGlobalListeners();
  54. removeSelf();
  55. }
  56. const id = 'message-box';
  57. messageBox.element =
  58. $create({id, className}, [
  59. $create([
  60. $create(`#${id}-title`, title),
  61. $create(`#${id}-close-icon`, {onclick: messageBox.listeners.closeIcon},
  62. $create('SVG:svg.svg-icon', {viewBox: '0 0 20 20'},
  63. $create('SVG:path', {d: 'M11.69,10l4.55,4.55-1.69,1.69L10,11.69,' +
  64. '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',
  65. }))),
  66. $create(`#${id}-contents`, tHTML(contents)),
  67. $create(`#${id}-buttons`,
  68. buttons.map((content, buttonIndex) => content &&
  69. $create('button', Object.assign({
  70. buttonIndex,
  71. textContent: typeof content === 'object' ? '' : content,
  72. onclick: messageBox.listeners.button,
  73. }, typeof content === 'object' && content)))),
  74. ]),
  75. ]);
  76. }
  77. function bindGlobalListeners() {
  78. blockScroll = blockScroll && {x: scrollX, y: scrollY};
  79. if (blockScroll) {
  80. window.addEventListener('scroll', messageBox.listeners.scroll);
  81. }
  82. window.addEventListener('keydown', messageBox.listeners.key, true);
  83. }
  84. function unbindGlobalListeners() {
  85. window.removeEventListener('keydown', messageBox.listeners.key, true);
  86. window.removeEventListener('scroll', messageBox.listeners.scroll);
  87. }
  88. function removeSelf() {
  89. messageBox.element.remove();
  90. messageBox.element = null;
  91. messageBox.resolve = null;
  92. }
  93. }
  94. messageBox.alert = text =>
  95. messageBox({
  96. contents: text,
  97. className: 'pre center',
  98. buttons: [t('confirmClose')]
  99. });
  100. messageBox.confirm = text =>
  101. messageBox({
  102. contents: text,
  103. className: 'pre center',
  104. buttons: [t('confirmYes'), t('confirmNo')]
  105. }).then(result => result.button === 0 || result.enter);