diff options
| author | Hsieh Chin Fan <pham@topo.tw> | 2024-10-02 17:43:02 +0800 |
|---|---|---|
| committer | Hsieh Chin Fan <pham@topo.tw> | 2024-10-02 19:03:10 +0800 |
| commit | 661b6c90ac12f8f43bdf935fe39811fee5dcffc7 (patch) | |
| tree | de9facd7e82d6aafbac393f6b51880b31b552419 /src | |
| parent | 045e55ce0547544e064f09f87bd1f75d7fa088b0 (diff) | |
feat: add checked/unchecked state for block menu item
also, prevent menu got erased by className
Diffstat (limited to 'src')
| -rw-r--r-- | src/MenuItem.mjs | 38 | ||||
| -rw-r--r-- | src/css/dumbymap.css | 14 | ||||
| -rw-r--r-- | src/dumbymap.mjs | 10 |
3 files changed, 47 insertions, 15 deletions
diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs index a7724d3..d485032 100644 --- a/src/MenuItem.mjs +++ b/src/MenuItem.mjs | |||
| @@ -1,12 +1,13 @@ | |||
| 1 | import { shiftByWindow } from './utils.mjs' | 1 | import { shiftByWindow } from './utils.mjs' |
| 2 | 2 | ||
| 3 | class Item extends window.HTMLDivElement { | 3 | class Item extends window.HTMLDivElement { |
| 4 | constructor ({ text, innerHTML, onclick, style }) { | 4 | constructor ({ text, innerHTML, onclick, style, className, onmouseover }) { |
| 5 | super() | 5 | super() |
| 6 | this.innerHTML = innerHTML ?? text | 6 | this.innerHTML = innerHTML ?? text |
| 7 | this.onclick = onclick | 7 | this.onclick = onclick |
| 8 | this.classList.add('menu-item') | ||
| 9 | this.style.cssText = style | 8 | this.style.cssText = style |
| 9 | this.classList.add('menu-item') | ||
| 10 | className?.forEach(c => this.classList.add(c)) | ||
| 10 | 11 | ||
| 11 | this.onmouseover = () => { | 12 | this.onmouseover = () => { |
| 12 | this.parentElement | 13 | this.parentElement |
| @@ -28,7 +29,7 @@ class Folder extends window.HTMLDivElement { | |||
| 28 | // Prepare submenu | 29 | // Prepare submenu |
| 29 | const submenu = document.createElement('div') | 30 | const submenu = document.createElement('div') |
| 30 | submenu.className = 'sub-menu' | 31 | submenu.className = 'sub-menu' |
| 31 | submenu.style.cssText = 'position: absolute; left: 105%; top: 0px;' | 32 | submenu.style.cssText = 'position: absolute; left: 105%; top: -20px;' |
| 32 | this.items.forEach(item => submenu.appendChild(item)) | 33 | this.items.forEach(item => submenu.appendChild(item)) |
| 33 | submenu.onmouseleave = () => submenu.remove() | 34 | submenu.onmouseleave = () => submenu.remove() |
| 34 | 35 | ||
| @@ -62,19 +63,28 @@ export const pickBlockItem = ({ blocks, utils }) => | |||
| 62 | new Folder({ | 63 | new Folder({ |
| 63 | innerHTML: '<span>Blocks<span><span class="info">(n/p)</span>', | 64 | innerHTML: '<span>Blocks<span><span class="info">(n/p)</span>', |
| 64 | items: blocks.map( | 65 | items: blocks.map( |
| 65 | (block, index) => | 66 | (block, index) => { |
| 66 | new Item({ | 67 | const focus = block.classList.contains('focus') |
| 67 | text: | 68 | const preview = block.querySelector('p') |
| 68 | `<strong style="display: inline-block; width: 2.5em;">(${index})</strong>` + | 69 | ?.textContent.substring(0, 15) |
| 69 | block | 70 | ?.concat(' ', '... ') ?? '' |
| 70 | .querySelector('p') | 71 | const item = new Item({ |
| 71 | ?.textContent.substring(0, 15) | 72 | className: ['keep-menu', focus ? 'checked' : 'unchecked'], |
| 72 | .concat(' ...'), | 73 | innerHTML: |
| 73 | onclick: () => { | 74 | `<strong>(${index})</strong><span style='display: inline-block; margin-inline: 1.2em;'>${preview}</span>`, |
| 74 | block.classList.add('focus') | 75 | onclick: (e) => { |
| 75 | utils.scrollToBlock(block) | 76 | block.classList.toggle('focus') |
| 77 | |||
| 78 | const focus = block.classList.contains('focus') | ||
| 79 | if (focus) utils.scrollToBlock(block) | ||
| 80 | const item = e.target.closest('.menu-item.keep-menu') | ||
| 81 | item.classList.add(focus ? 'checked' : 'unchecked') | ||
| 82 | item.classList.remove(focus ? 'unchecked' : 'checked') | ||
| 76 | } | 83 | } |
| 77 | }) | 84 | }) |
| 85 | |||
| 86 | return item | ||
| 87 | } | ||
| 78 | ) | 88 | ) |
| 79 | }) | 89 | }) |
| 80 | 90 | ||
diff --git a/src/css/dumbymap.css b/src/css/dumbymap.css index b3ff877..3d07d45 100644 --- a/src/css/dumbymap.css +++ b/src/css/dumbymap.css | |||
| @@ -289,6 +289,18 @@ p a[href^='http']::after, | |||
| 289 | display: inline-block; | 289 | display: inline-block; |
| 290 | float: right; | 290 | float: right; |
| 291 | } | 291 | } |
| 292 | |||
| 293 | &.unchecked::before { | ||
| 294 | content: '\2610'; | ||
| 295 | float: right; | ||
| 296 | margin-left: 0.5em; | ||
| 297 | } | ||
| 298 | |||
| 299 | &.checked::before { | ||
| 300 | content: '\2611'; | ||
| 301 | float: right; | ||
| 302 | margin-left: 0.5em; | ||
| 303 | } | ||
| 292 | } | 304 | } |
| 293 | 305 | ||
| 294 | .sub-menu { | 306 | .sub-menu { |
| @@ -746,3 +758,5 @@ p a[href^='http']::after, | |||
| 746 | .bold-options { | 758 | .bold-options { |
| 747 | font-weight: bold; | 759 | font-weight: bold; |
| 748 | } | 760 | } |
| 761 | standard: Use JavaScript Standard Style (https://standardjs.com) | ||
| 762 | standard: <text>:1:6: Parsing error: Unexpected token { (null) | ||
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 7e04501..b909fe0 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
| @@ -461,7 +461,12 @@ export const generateMaps = (container, { delay, mapCallback }) => { | |||
| 461 | const menu = document.createElement('div') | 461 | const menu = document.createElement('div') |
| 462 | menu.className = 'menu' | 462 | menu.className = 'menu' |
| 463 | menu.style.display = 'none' | 463 | menu.style.display = 'none' |
| 464 | menu.onclick = () => (menu.style.display = 'none') | 464 | menu.onclick = (e) => { |
| 465 | const keepMenu = e.target.closest('.keep-menu') || e.target.classList.contains('.keep-menu') | ||
| 466 | if (keepMenu) return | ||
| 467 | |||
| 468 | menu.style.display = 'none' | ||
| 469 | } | ||
| 465 | container.appendChild(menu) | 470 | container.appendChild(menu) |
| 466 | 471 | ||
| 467 | // Menu Items | 472 | // Menu Items |
| @@ -505,6 +510,9 @@ export const generateMaps = (container, { delay, mapCallback }) => { | |||
| 505 | // Remove menu when click outside | 510 | // Remove menu when click outside |
| 506 | const actionOutsideMenu = e => { | 511 | const actionOutsideMenu = e => { |
| 507 | if (menu.style.display === 'none') return | 512 | if (menu.style.display === 'none') return |
| 513 | const keepMenu = e.target.closest('.keep-menu') || e.target.classList.contains('.keep-menu') | ||
| 514 | if (keepMenu) return | ||
| 515 | |||
| 508 | const rect = menu.getBoundingClientRect() | 516 | const rect = menu.getBoundingClientRect() |
| 509 | if ( | 517 | if ( |
| 510 | e.clientX < rect.left || | 518 | e.clientX < rect.left || |