aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorHsieh Chin Fan <pham@topo.tw>2024-10-02 17:43:02 +0800
committerHsieh Chin Fan <pham@topo.tw>2024-10-02 19:03:10 +0800
commit661b6c90ac12f8f43bdf935fe39811fee5dcffc7 (patch)
treede9facd7e82d6aafbac393f6b51880b31b552419
parent045e55ce0547544e064f09f87bd1f75d7fa088b0 (diff)
feat: add checked/unchecked state for block menu item
also, prevent menu got erased by className
-rw-r--r--src/MenuItem.mjs38
-rw-r--r--src/css/dumbymap.css14
-rw-r--r--src/dumbymap.mjs10
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 @@
1import { shiftByWindow } from './utils.mjs' 1import { shiftByWindow } from './utils.mjs'
2 2
3class Item extends window.HTMLDivElement { 3class 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}
761standard: Use JavaScript Standard Style (https://standardjs.com)
762standard: <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 ||