diff options
author | Hsieh Chin Fan <pham@topo.tw> | 2024-10-28 19:32:23 +0800 |
---|---|---|
committer | Hsieh Chin Fan <pham@topo.tw> | 2024-10-28 20:11:22 +0800 |
commit | ce1f619b9a7a64100a0315330244a296c091bbc9 (patch) | |
tree | 0165d829a83abe6d59a2fb69fec48b31213178eb /src/MenuItem.mjs | |
parent | 92dc83240b31455b8282242fafb0471681538fbe (diff) |
feat: add menu-folder for editing map options
* add dumbymap.aliases for option aliases
* don't remove sub-menu when child sub-menu exists
* don't add render delay for config modification by menu-item
* TODO sub-menu placement
Diffstat (limited to 'src/MenuItem.mjs')
-rw-r--r-- | src/MenuItem.mjs | 60 |
1 files changed, 52 insertions, 8 deletions
diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs index 7e50991..e560b39 100644 --- a/src/MenuItem.mjs +++ b/src/MenuItem.mjs | |||
@@ -3,6 +3,7 @@ import { addMarkerByPoint } from './dumbyUtils.mjs' | |||
3 | /* eslint-disable-next-line no-unused-vars */ | 3 | /* eslint-disable-next-line no-unused-vars */ |
4 | import { GeoLink, getMarkersFromMaps, removeLeaderLines } from './Link.mjs' | 4 | import { GeoLink, getMarkersFromMaps, removeLeaderLines } from './Link.mjs' |
5 | import * as markers from './marker.mjs' | 5 | import * as markers from './marker.mjs' |
6 | import { parseConfigsFromYaml } from 'mapclay' | ||
6 | 7 | ||
7 | /** | 8 | /** |
8 | * @typedef {Object} RefLink | 9 | * @typedef {Object} RefLink |
@@ -77,7 +78,10 @@ export class Folder extends window.HTMLDivElement { | |||
77 | const offset = this.items.length > 1 ? '-20px' : '0px' | 78 | const offset = this.items.length > 1 ? '-20px' : '0px' |
78 | submenu.style.cssText = `${style ?? ''}position: absolute; left: 105%; top: ${offset};` | 79 | submenu.style.cssText = `${style ?? ''}position: absolute; left: 105%; top: ${offset};` |
79 | this.items.forEach(item => submenu.appendChild(item)) | 80 | this.items.forEach(item => submenu.appendChild(item)) |
80 | submenu.onmouseleave = () => submenu.remove() | 81 | submenu.onmouseleave = () => { |
82 | if (submenu.querySelectorAll('.sub-menu').length > 0) return | ||
83 | submenu.remove() | ||
84 | } | ||
81 | 85 | ||
82 | // hover effect | 86 | // hover effect |
83 | this.parentElement | 87 | this.parentElement |
@@ -98,7 +102,7 @@ export const simplePlaceholder = (text) => new Item({ | |||
98 | }) | 102 | }) |
99 | 103 | ||
100 | /** | 104 | /** |
101 | * Creates a menu item for picking a map | 105 | * Pick up a map |
102 | * | 106 | * |
103 | * @param {Object} options - The options object | 107 | * @param {Object} options - The options object |
104 | * @param {Object} options.utils - Utility functions | 108 | * @param {Object} options.utils - Utility functions |
@@ -532,20 +536,21 @@ export const addMarker = ({ | |||
532 | /** | 536 | /** |
533 | * editByRawText. | 537 | * editByRawText. |
534 | * | 538 | * |
535 | * @param {HTMLElement} ele | 539 | * @param {HTMLElement} map |
536 | */ | 540 | */ |
537 | export const editMapByRawText = (ele) => new Item({ | 541 | export const editMapByRawText = (map) => new Item({ |
538 | text: 'Edit by Raw Text', | 542 | text: 'Edit by Raw Text', |
539 | onclick: () => { | 543 | onclick: () => { |
540 | const maps = Array.from(ele.querySelectorAll('.mapclay')) | 544 | const container = map.closest('.map-container') |
545 | const maps = Array.from(container.querySelectorAll('.mapclay')) | ||
541 | if (!maps) return false | 546 | if (!maps) return false |
542 | 547 | ||
543 | const rect = ele.getBoundingClientRect() | 548 | const rect = map.getBoundingClientRect() |
544 | const textArea = document.createElement('textarea') | 549 | const textArea = document.createElement('textarea') |
545 | textArea.className = 'edit-map' | 550 | textArea.className = 'edit-map' |
546 | textArea.style.cssText = `width: ${rect.width}px; height: ${rect.height}px;` | 551 | textArea.style.cssText = `width: ${rect.width}px; height: ${rect.height}px;` |
547 | textArea.value = maps.map(map => map.dataset.mapclay ?? '') | 552 | textArea.value = maps.map(map => map.dataset.mapclay ?? '') |
548 | .join('---') | 553 | .join('\n---\n') |
549 | .replaceAll(',', '\n') | 554 | .replaceAll(',', '\n') |
550 | .replaceAll(/["{}]/g, '') | 555 | .replaceAll(/["{}]/g, '') |
551 | .replaceAll(/:(\w)/g, ': $1') | 556 | .replaceAll(/:(\w)/g, ': $1') |
@@ -554,10 +559,49 @@ export const editMapByRawText = (ele) => new Item({ | |||
554 | const code = document.createElement('code') | 559 | const code = document.createElement('code') |
555 | code.className = 'map' | 560 | code.className = 'map' |
556 | code.textContent = textArea.value | 561 | code.textContent = textArea.value |
562 | container.dataset.render = 'no-delay' | ||
557 | textArea.replaceWith(code) | 563 | textArea.replaceWith(code) |
558 | }) | 564 | }) |
559 | ele.replaceChildren(textArea) | 565 | container.replaceChildren(textArea) |
560 | 566 | ||
561 | return true | 567 | return true |
562 | }, | 568 | }, |
563 | }) | 569 | }) |
570 | |||
571 | export const editMap = (map, dumbymap) => { | ||
572 | const options = Object.entries(dumbymap.aliases) | ||
573 | .map(([option, aliases]) => | ||
574 | new Folder({ | ||
575 | text: option, | ||
576 | items: Object.entries(aliases) | ||
577 | .map(([alias, value]) => { | ||
578 | const aliasValue = value.value ?? value | ||
579 | return new Item({ | ||
580 | innerHTML: `<div>${alias}</div><div style="padding-left: 20px; color: gray; font-size: 1rem";">${aliasValue}</div>`, | ||
581 | style: 'display: flex; justify-content: space-between; max-width: 20rem;', | ||
582 | onclick: () => { | ||
583 | const container = map.closest('.map-container') | ||
584 | const configText = Array.from(container.querySelectorAll('.mapclay')) | ||
585 | .map(map => map.dataset.mapclay ?? '') | ||
586 | .join('\n---\n') | ||
587 | const configList = parseConfigsFromYaml(configText) | ||
588 | configList.find(config => config.id === map.id)[option] = aliasValue | ||
589 | const code = document.createElement('code') | ||
590 | code.className = 'map' | ||
591 | code.textContent = configList.map(JSON.stringify).join('\n---\n') | ||
592 | container.dataset.render = 'no-delay' | ||
593 | container.replaceChildren(code) | ||
594 | }, | ||
595 | }) | ||
596 | }), | ||
597 | }), | ||
598 | ) | ||
599 | return new Folder({ | ||
600 | text: 'Edit Map', | ||
601 | style: 'overflow: visible;', | ||
602 | items: [ | ||
603 | editMapByRawText(map), | ||
604 | ...options, | ||
605 | ], | ||
606 | }) | ||
607 | } | ||