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) => { |