diff options
author | Hsieh Chin Fan <pham@topo.tw> | 2024-09-29 21:01:03 +0800 |
---|---|---|
committer | Hsieh Chin Fan <pham@topo.tw> | 2024-09-29 21:19:07 +0800 |
commit | 27feb1302304eede3cdc58ffde5ce8e0f0019da4 (patch) | |
tree | 0db88a3c17f4761470d0b3e39b3ad16e36fbe2c5 /src/MenuItem.mjs | |
parent | 110d8890e171573adad1fe171a122dfbc89f6faa (diff) |
feat: add submenu for map/block/layout switching
* Add general classes into MenuItem
* Use MutationObserver for data-mode
* Automatically unfocus other maps when one is focused
TODO:
* hover effect on submenu item doesn't work, why?
* shorcuts hint in selector ".folder.menu-item" not looks great
Diffstat (limited to 'src/MenuItem.mjs')
-rw-r--r-- | src/MenuItem.mjs | 101 |
1 files changed, 82 insertions, 19 deletions
diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs index 734c313..e974f9e 100644 --- a/src/MenuItem.mjs +++ b/src/MenuItem.mjs | |||
@@ -1,31 +1,94 @@ | |||
1 | import { createGeoLink } from './dumbymap'; | 1 | import { createGeoLink } from './dumbymap'; |
2 | 2 | ||
3 | export function nextMap() { | 3 | class Item { |
4 | const element = document.createElement('div'); | 4 | constructor({ text, innerHTML, onclick }) { |
5 | element.className = 'menu-item'; | 5 | this.text = text; |
6 | element.innerHTML = 'Next Map <span class="info">(Tab)</span>'; | 6 | this.innerHTML = innerHTML; |
7 | element.onclick = () => this.utils.focusNextMap(); | 7 | this.onclick = onclick; |
8 | } | ||
8 | 9 | ||
9 | return element; | 10 | get element() { |
11 | const element = document.createElement('div'); | ||
12 | element.innerHTML = this.innerHTML ? this.innerHTML : this.text; | ||
13 | element.classList.add('menu-item'); | ||
14 | element.onclick = this.onclick; | ||
15 | return element; | ||
16 | } | ||
10 | } | 17 | } |
11 | 18 | ||
12 | export function nextBlock() { | 19 | class Folder { |
13 | const element = document.createElement('div'); | 20 | constructor({ text, innerHTML, items }) { |
14 | element.className = 'menu-item'; | 21 | this.text = text; |
15 | element.innerHTML = 'Next Block <span class="info">(n)</span>'; | 22 | this.innerHTML = innerHTML; |
16 | element.onclick = () => this.utils.focusNextBlock(); | 23 | this.items = items; |
24 | this.utils; | ||
25 | } | ||
26 | |||
27 | get element() { | ||
28 | const element = document.createElement('div'); | ||
29 | element.classList.add(this.className); | ||
30 | element.className = 'menu-item folder'; | ||
31 | element.innerHTML = this.innerHTML; | ||
32 | element.style.cssText = 'position: relative; overflow: visible;'; | ||
33 | element.onmouseover = () => { | ||
34 | // Prepare submenu | ||
35 | this.submenu = document.createElement('div'); | ||
36 | this.submenu.className = 'sub-menu'; | ||
37 | this.submenu.style.cssText = `position: absolute; left: 105%; top: 0px;`; | ||
38 | this.items.forEach(item => this.submenu.appendChild(item)); | ||
17 | 39 | ||
18 | return element; | 40 | // hover effect |
41 | element.parentElement | ||
42 | .querySelectorAll('.sub-menu') | ||
43 | .forEach(sub => sub.remove()); | ||
44 | element.appendChild(this.submenu); | ||
45 | }; | ||
46 | return element; | ||
47 | } | ||
19 | } | 48 | } |
20 | 49 | ||
21 | export function nextLayout() { | 50 | export const pickMapItem = dumbymap => |
22 | const element = document.createElement('div'); | 51 | new Folder({ |
23 | element.className = 'menu-item'; | 52 | innerHTML: '<span>Focus a Map<span><span class="info">(Tab)</span>', |
24 | element.innerHTML = 'Next Layout <span class="info">(x)</span>'; | 53 | items: dumbymap.utils.renderedMaps().map( |
25 | element.onclick = () => this.utils.switchToNextLayout(); | 54 | map => |
55 | new Item({ | ||
56 | text: map.id, | ||
57 | onclick: () => map.classList.add('focus'), | ||
58 | }).element, | ||
59 | ), | ||
60 | }).element; | ||
26 | 61 | ||
27 | return element; | 62 | export const pickBlockItem = dumbymap => |
28 | } | 63 | new Folder({ |
64 | innerHTML: '<span>Focus Block<span><span class="info">(n/p)</span>', | ||
65 | items: dumbymap.blocks.map( | ||
66 | (block, index) => | ||
67 | new Item({ | ||
68 | text: `Block ${index}`, | ||
69 | onclick: () => block.classList.add('focus'), | ||
70 | }).element, | ||
71 | ), | ||
72 | }).element; | ||
73 | |||
74 | export const pickLayoutItem = dumbymap => | ||
75 | new Folder({ | ||
76 | innerHTML: '<span>Switch Layout<span><span class="info">(x)</span>', | ||
77 | items: [ | ||
78 | new Item({ | ||
79 | text: 'EDIT', | ||
80 | onclick: () => document.body.setAttribute('data-mode', 'editing'), | ||
81 | }).element, | ||
82 | ...dumbymap.layouts.map( | ||
83 | layout => | ||
84 | new Item({ | ||
85 | text: layout.name, | ||
86 | onclick: () => | ||
87 | dumbymap.container.setAttribute('data-layout', layout.name), | ||
88 | }).element, | ||
89 | ), | ||
90 | ], | ||
91 | }).element; | ||
29 | 92 | ||
30 | export class GeoLink { | 93 | export class GeoLink { |
31 | constructor({ range }) { | 94 | constructor({ range }) { |