The frontend/UI server, written in JS using the MarkoJS library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
2.3 KiB

  1. module.exports = class {
  2. onCreate() {
  3. this.mounted = false
  4. this.opened = false
  5. }
  6. closeModal() {
  7. this.emit("close")
  8. this.opened = false
  9. if (this.mounted) {
  10. window.removeEventListener("keydown", this.onPress)
  11. }
  12. }
  13. onInput(input) {
  14. if (!this.mounted) {
  15. return
  16. }
  17. if (input) {
  18. if (input.enabled && !this.opened) {
  19. this.emit("open")
  20. this.opened = true
  21. }
  22. if (input.closable) {
  23. if (input.enabled && (!this.input || !this.input.enabled)) {
  24. window.addEventListener("keydown", this.onPress)
  25. } else if (!input.enabled && (this.input && this.input.enabled)) {
  26. window.removeEventListener("keydown", this.onPress)
  27. }
  28. }
  29. }
  30. }
  31. onMount() {
  32. this.onPress = this.onPress.bind(this)
  33. this.mounted = true
  34. if (this.input.enabled && this.input.closable) {
  35. window.addEventListener("keydown", this.onPress)
  36. }
  37. }
  38. onUnmount() {
  39. if (this.input.enabled) {
  40. window.removeEventListener("keydown", this.onPress)
  41. }
  42. }
  43. /**
  44. *
  45. * @param {KeyboardEvent} ev
  46. */
  47. onPress(ev) {
  48. if (ev.key === "Escape" && ev.ctrlKey ) {
  49. this.closeModal()
  50. }
  51. }
  52. getValues() {
  53. /** @type {HTMLElement[]} */
  54. const elems = this.findInputs()
  55. const map = {}
  56. for (const component of this.getComponents()) {
  57. if (component.getFormData != null) {
  58. Object.assign(map, component.getFormData() || {})
  59. }
  60. }
  61. return elems.reduce((map, elem) => {
  62. let path = elem.getAttribute("name").split(".")
  63. let node = map
  64. for (const part of path.slice(0, -1)) {
  65. if (node[part] == null) {
  66. node[part] = {}
  67. }
  68. node = node[part]
  69. }
  70. node[path[path.length - 1]] = elem.value;
  71. return map
  72. }, map)
  73. }
  74. /**
  75. * @param {HTMLElement} elem
  76. */
  77. findInputs(elem = this.getEl()) {
  78. let results = []
  79. if (elem.childNodes.length === 0) {
  80. return []
  81. }
  82. for (let i = 0; i < elem.children.length; ++i) {
  83. const child = elem.children.item(i)
  84. if (child.dataset.formboundary != null) {
  85. continue
  86. }
  87. if (child.nodeName === "INPUT" || child.nodeName === "TEXTAREA") {
  88. results.push(child)
  89. } else {
  90. results = results.concat(this.findInputs(child))
  91. }
  92. }
  93. return results
  94. }
  95. }