msgbox.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. 'use strict';
  2. function messageBox({
  3. title, // [mandatory] the title string for innerHTML
  4. contents, // [mandatory] 1) DOM element 2) string for innerHTML
  5. className = '', // string, CSS class name of the message box element
  6. buttons = [], // array of strings used as labels
  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. resolveWith(keyCode == 13 ? {enter: true} : {esc: true});
  34. }
  35. },
  36. scroll() {
  37. scrollTo(blockScroll.x, blockScroll.y);
  38. }
  39. };
  40. }
  41. function resolveWith(value) {
  42. setTimeout(messageBox.resolve, 0, value);
  43. animateElement(messageBox.element, {className: 'fadeout', remove: true})
  44. .then(unbindAndRemoveSelf);
  45. }
  46. function createElement() {
  47. if (messageBox.element) {
  48. unbindAndRemoveSelf();
  49. }
  50. const id = 'message-box';
  51. const putAs = typeof contents == 'string' ? 'innerHTML' : 'appendChild';
  52. messageBox.element = $element({id, className, appendChild: [
  53. $element({appendChild: [
  54. $element({id: `${id}-title`, innerHTML: title}),
  55. $element({id: `${id}-close-icon`, appendChild:
  56. $element({tag: 'SVG#svg', class: 'svg-icon', viewBox: '0 0 20 20', appendChild:
  57. $element({tag: 'SVG#path', d: 'M11.69,10l4.55,4.55-1.69,1.69L10,11.69,' +
  58. '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',
  59. })
  60. }),
  61. onclick: messageBox.listeners.closeIcon}),
  62. $element({id: `${id}-contents`, [putAs]: contents}),
  63. $element({id: `${id}-buttons`, appendChild:
  64. buttons.map((textContent, buttonIndex) => textContent &&
  65. $element({
  66. tag: 'button',
  67. buttonIndex,
  68. textContent,
  69. onclick: messageBox.listeners.button,
  70. })
  71. )
  72. }),
  73. ]}),
  74. ]});
  75. }
  76. function bindGlobalListeners() {
  77. blockScroll = blockScroll && {x: scrollX, y: scrollY};
  78. if (blockScroll) {
  79. window.addEventListener('scroll', messageBox.listeners.scroll);
  80. }
  81. window.addEventListener('keydown', messageBox.listeners.key);
  82. }
  83. function unbindAndRemoveSelf() {
  84. document.removeEventListener('keydown', messageBox.listeners.key);
  85. window.removeEventListener('scroll', messageBox.listeners.scroll);
  86. messageBox.element.remove();
  87. messageBox.element = null;
  88. messageBox.resolve = null;
  89. }
  90. }