diff options
| author | Hsieh Chin Fan <pham@topo.tw> | 2024-09-25 16:56:43 +0800 |
|---|---|---|
| committer | Hsieh Chin Fan <pham@topo.tw> | 2024-09-26 19:40:48 +0800 |
| commit | 435a2fcae3416fc0f37bfbfa2f27d2ec6f909d83 (patch) | |
| tree | b6ed0ee29202f56577e86dae0de39ef69fffb150 /src | |
| parent | c02d1d0cbd6e0cf4d011a1d96d0433e609f799db (diff) | |
feat: add menu items for dumbymap.utils
Diffstat (limited to 'src')
| -rw-r--r-- | src/MenuItem.mjs | 29 | ||||
| -rw-r--r-- | src/css/index.css | 17 | ||||
| -rw-r--r-- | src/editor.mjs | 21 |
3 files changed, 56 insertions, 11 deletions
diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs index 1b04d1c..85ab1a2 100644 --- a/src/MenuItem.mjs +++ b/src/MenuItem.mjs | |||
| @@ -1,5 +1,32 @@ | |||
| 1 | import { createGeoLink } from './dumbymap' | 1 | import { createGeoLink } from './dumbymap' |
| 2 | 2 | ||
| 3 | export function nextMap() { | ||
| 4 | const element = document.createElement('div') | ||
| 5 | element.className = 'menu-item' | ||
| 6 | element.innerHTML = 'Next Map <span class="info">(Tab)</span>' | ||
| 7 | element.onclick = () => this.utils.focusNextMap() | ||
| 8 | |||
| 9 | return element | ||
| 10 | } | ||
| 11 | |||
| 12 | export function nextBlock() { | ||
| 13 | const element = document.createElement('div') | ||
| 14 | element.className = 'menu-item' | ||
| 15 | element.innerHTML = 'Next Block <span class="info">(n)</span>' | ||
| 16 | element.onclick = () => this.utils.focusNextBlock() | ||
| 17 | |||
| 18 | return element | ||
| 19 | } | ||
| 20 | |||
| 21 | export function nextLayout() { | ||
| 22 | const element = document.createElement('div') | ||
| 23 | element.className = 'menu-item' | ||
| 24 | element.innerHTML = 'Next Layout <span class="info">(x)</span>' | ||
| 25 | element.onclick = () => this.utils.switchToNextLayout() | ||
| 26 | |||
| 27 | return element | ||
| 28 | } | ||
| 29 | |||
| 3 | export class GeoLink { | 30 | export class GeoLink { |
| 4 | 31 | ||
| 5 | constructor({ range }) { | 32 | constructor({ range }) { |
| @@ -8,7 +35,7 @@ export class GeoLink { | |||
| 8 | 35 | ||
| 9 | createElement = () => { | 36 | createElement = () => { |
| 10 | const element = document.createElement('div') | 37 | const element = document.createElement('div') |
| 11 | element.className = 'menu-item-add-geolink' | 38 | element.className = 'menu-item' |
| 12 | element.innerText = "Add GeoLink" | 39 | element.innerText = "Add GeoLink" |
| 13 | element.onclick = this.addGeoLinkbyRange | 40 | element.onclick = this.addGeoLinkbyRange |
| 14 | 41 | ||
diff --git a/src/css/index.css b/src/css/index.css index a5fd37f..a84a029 100644 --- a/src/css/index.css +++ b/src/css/index.css | |||
| @@ -114,7 +114,7 @@ body { | |||
| 114 | z-index: 100; | 114 | z-index: 100; |
| 115 | 115 | ||
| 116 | border: 2px solid gray; | 116 | border: 2px solid gray; |
| 117 | border-radius: 0.5rem; | 117 | border-radius: 6px; |
| 118 | 118 | ||
| 119 | background: white; | 119 | background: white; |
| 120 | min-width: 10rem; | 120 | min-width: 10rem; |
| @@ -164,8 +164,21 @@ body { | |||
| 164 | } | 164 | } |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | .menu-item-add-geolink { | 167 | .menu-item { |
| 168 | display: flex; | ||
| 168 | padding: 0.5rem; | 169 | padding: 0.5rem; |
| 169 | 170 | ||
| 171 | z-index: 9999; | ||
| 172 | |||
| 170 | cursor: pointer; | 173 | cursor: pointer; |
| 174 | justify-content: space-between; | ||
| 175 | |||
| 176 | &:hover { | ||
| 177 | background: rgb(226 232 240); | ||
| 178 | } | ||
| 179 | |||
| 180 | .info { | ||
| 181 | color: steelblue; | ||
| 182 | font-weight: bold; | ||
| 183 | } | ||
| 171 | } | 184 | } |
diff --git a/src/editor.mjs b/src/editor.mjs index 297d75a..ea80a19 100644 --- a/src/editor.mjs +++ b/src/editor.mjs | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | /*eslint no-undef: "error"*/ | 2 | /*eslint no-undef: "error"*/ |
| 3 | import { markdown2HTML, generateMaps } from './dumbymap' | 3 | import { markdown2HTML, generateMaps } from './dumbymap' |
| 4 | import { defaultAliases, parseConfigsFromYaml } from 'mapclay' | 4 | import { defaultAliases, parseConfigsFromYaml } from 'mapclay' |
| 5 | import { GeoLink, Suggestion } from './MenuItem' | 5 | import * as menuItem from './MenuItem' |
| 6 | 6 | ||
| 7 | // Set up Containers {{{ | 7 | // Set up Containers {{{ |
| 8 | 8 | ||
| @@ -300,7 +300,7 @@ const getSuggestionsForOptions = (optionTyped, validOptions) => { | |||
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | return suggestOptions | 302 | return suggestOptions |
| 303 | .map(o => new Suggestion({ | 303 | .map(o => new menuItem.Suggestion({ |
| 304 | text: `<span>${o.valueOf()}</span><span class='info' title="${o.desc ?? ''}">ⓘ</span>`, | 304 | text: `<span>${o.valueOf()}</span><span class='info' title="${o.desc ?? ''}">ⓘ</span>`, |
| 305 | replace: `${o.valueOf()}: `, | 305 | replace: `${o.valueOf()}: `, |
| 306 | })) | 306 | })) |
| @@ -314,7 +314,7 @@ const getSuggestionFromMapOption = (option) => { | |||
| 314 | ? `<span>${option.example_desc}</span><span class="truncate"style="color: gray">${option.example}</span>` | 314 | ? `<span>${option.example_desc}</span><span class="truncate"style="color: gray">${option.example}</span>` |
| 315 | : `<span>${option.example}</span>` | 315 | : `<span>${option.example}</span>` |
| 316 | 316 | ||
| 317 | return new Suggestion({ | 317 | return new menuItem.Suggestion({ |
| 318 | text: text, | 318 | text: text, |
| 319 | replace: `${option.valueOf()}: ${option.example ?? ""}`, | 319 | replace: `${option.valueOf()}: ${option.example ?? ""}`, |
| 320 | }) | 320 | }) |
| @@ -325,7 +325,7 @@ const getSuggestionsFromAliases = (option) => Object.entries(aliasesForMapOption | |||
| 325 | ?.map(record => { | 325 | ?.map(record => { |
| 326 | const [alias, value] = record | 326 | const [alias, value] = record |
| 327 | const valueString = JSON.stringify(value).replaceAll('"', '') | 327 | const valueString = JSON.stringify(value).replaceAll('"', '') |
| 328 | return new Suggestion({ | 328 | return new menuItem.Suggestion({ |
| 329 | text: `<span>${alias}</span><span class="truncate" style="color: gray">${valueString}</span>`, | 329 | text: `<span>${alias}</span><span class="truncate" style="color: gray">${valueString}</span>`, |
| 330 | replace: `${option.valueOf()}: ${valueString}`, | 330 | replace: `${option.valueOf()}: ${valueString}`, |
| 331 | }) | 331 | }) |
| @@ -420,7 +420,7 @@ const getSuggestions = (anchor) => { | |||
| 420 | return [ | 420 | return [ |
| 421 | getSuggestionFromMapOption(matchedOption), | 421 | getSuggestionFromMapOption(matchedOption), |
| 422 | ...getSuggestionsFromAliases(matchedOption) | 422 | ...getSuggestionsFromAliases(matchedOption) |
| 423 | ].filter(s => s instanceof Suggestion) | 423 | ].filter(s => s instanceof menuItem.Suggestion) |
| 424 | } | 424 | } |
| 425 | if (valueTyped && !isValidValue) { | 425 | if (valueTyped && !isValidValue) { |
| 426 | markInputIsInvalid() | 426 | markInputIsInvalid() |
| @@ -439,7 +439,7 @@ const getSuggestions = (anchor) => { | |||
| 439 | (suggestionPattern.includes(textPattern)) | 439 | (suggestionPattern.includes(textPattern)) |
| 440 | }) | 440 | }) |
| 441 | .map(([renderer, info]) => | 441 | .map(([renderer, info]) => |
| 442 | new Suggestion({ | 442 | new menuItem.Suggestion({ |
| 443 | text: `<span>use: ${renderer}</span><span class='info' title="${info.desc}">ⓘ</span>`, | 443 | text: `<span>use: ${renderer}</span><span class='info' title="${info.desc}">ⓘ</span>`, |
| 444 | replace: `use: ${renderer}`, | 444 | replace: `use: ${renderer}`, |
| 445 | }) | 445 | }) |
| @@ -577,15 +577,20 @@ layoutObserver.observe(HtmlContainer, { | |||
| 577 | // }}} | 577 | // }}} |
| 578 | // ContextMenu {{{ | 578 | // ContextMenu {{{ |
| 579 | document.oncontextmenu = (e) => { | 579 | document.oncontextmenu = (e) => { |
| 580 | if (cm.hasFocus()) return | ||
| 581 | |||
| 580 | const selection = document.getSelection() | 582 | const selection = document.getSelection() |
| 581 | const range = selection.getRangeAt(0) | 583 | const range = selection.getRangeAt(0) |
| 582 | if (!cm.hasFocus() && selection) { | 584 | if (selection) { |
| 583 | e.preventDefault() | 585 | e.preventDefault() |
| 584 | menu.innerHTML = '' | 586 | menu.innerHTML = '' |
| 585 | menu.style.cssText = `display: block; left: ${e.clientX + 10}px; top: ${e.clientY + 5}px;` | 587 | menu.style.cssText = `display: block; left: ${e.clientX + 10}px; top: ${e.clientY + 5}px;` |
| 586 | const addGeoLink = new GeoLink({ range }) | 588 | const addGeoLink = new menuItem.GeoLink({ range }) |
| 587 | menu.appendChild(addGeoLink.createElement()) | 589 | menu.appendChild(addGeoLink.createElement()) |
| 588 | } | 590 | } |
| 591 | menu.appendChild(menuItem.nextMap.bind(dumbymap)()) | ||
| 592 | menu.appendChild(menuItem.nextBlock.bind(dumbymap)()) | ||
| 593 | menu.appendChild(menuItem.nextLayout.bind(dumbymap)()) | ||
| 589 | } | 594 | } |
| 590 | 595 | ||
| 591 | const actionOutsideMenu = (e) => { | 596 | const actionOutsideMenu = (e) => { |