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.

116 lines
2.4 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. this.mounted = false
  43. this.opened = false
  44. }
  45. /**
  46. *
  47. * @param {KeyboardEvent} ev
  48. */
  49. onPress(ev) {
  50. if (ev.key === "Escape" && ev.ctrlKey ) {
  51. this.closeModal()
  52. }
  53. }
  54. getValues() {
  55. /** @type {HTMLElement[]} */
  56. const elems = this.findInputs()
  57. const map = {}
  58. for (const component of this.getComponents()) {
  59. if (component.getFormData != null) {
  60. Object.assign(map, component.getFormData() || {})
  61. }
  62. }
  63. return elems.reduce((map, elem) => {
  64. let path = elem.getAttribute("name").split(".")
  65. let node = map
  66. for (const part of path.slice(0, -1)) {
  67. if (node[part] == null) {
  68. node[part] = {}
  69. }
  70. node = node[part]
  71. }
  72. node[path[path.length - 1]] = elem.value;
  73. return map
  74. }, map)
  75. }
  76. /**
  77. * @param {HTMLElement} elem
  78. */
  79. findInputs(elem = this.getEl()) {
  80. let results = []
  81. if (elem.childNodes.length === 0) {
  82. return []
  83. }
  84. for (let i = 0; i < elem.children.length; ++i) {
  85. const child = elem.children.item(i)
  86. if (child.dataset.formboundary != null) {
  87. continue
  88. }
  89. if (child.nodeName === "INPUT" || child.nodeName === "TEXTAREA") {
  90. results.push(child)
  91. } else {
  92. results = results.concat(this.findInputs(child))
  93. }
  94. }
  95. return results
  96. }
  97. }