From 661b6c90ac12f8f43bdf935fe39811fee5dcffc7 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Wed, 2 Oct 2024 17:43:02 +0800 Subject: feat: add checked/unchecked state for block menu item also, prevent menu got erased by className --- src/MenuItem.mjs | 38 ++++++++++++++++++++++++-------------- src/css/dumbymap.css | 14 ++++++++++++++ src/dumbymap.mjs | 10 +++++++++- 3 files changed, 47 insertions(+), 15 deletions(-) (limited to 'src') 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 @@ import { shiftByWindow } from './utils.mjs' class Item extends window.HTMLDivElement { - constructor ({ text, innerHTML, onclick, style }) { + constructor ({ text, innerHTML, onclick, style, className, onmouseover }) { super() this.innerHTML = innerHTML ?? text this.onclick = onclick - this.classList.add('menu-item') this.style.cssText = style + this.classList.add('menu-item') + className?.forEach(c => this.classList.add(c)) this.onmouseover = () => { this.parentElement @@ -28,7 +29,7 @@ class Folder extends window.HTMLDivElement { // Prepare submenu const submenu = document.createElement('div') submenu.className = 'sub-menu' - submenu.style.cssText = 'position: absolute; left: 105%; top: 0px;' + submenu.style.cssText = 'position: absolute; left: 105%; top: -20px;' this.items.forEach(item => submenu.appendChild(item)) submenu.onmouseleave = () => submenu.remove() @@ -62,19 +63,28 @@ export const pickBlockItem = ({ blocks, utils }) => new Folder({ innerHTML: 'Blocks(n/p)', items: blocks.map( - (block, index) => - new Item({ - text: - `(${index})` + - block - .querySelector('p') - ?.textContent.substring(0, 15) - .concat(' ...'), - onclick: () => { - block.classList.add('focus') - utils.scrollToBlock(block) + (block, index) => { + const focus = block.classList.contains('focus') + const preview = block.querySelector('p') + ?.textContent.substring(0, 15) + ?.concat(' ', '... ') ?? '' + const item = new Item({ + className: ['keep-menu', focus ? 'checked' : 'unchecked'], + innerHTML: + `(${index})${preview}`, + onclick: (e) => { + block.classList.toggle('focus') + + const focus = block.classList.contains('focus') + if (focus) utils.scrollToBlock(block) + const item = e.target.closest('.menu-item.keep-menu') + item.classList.add(focus ? 'checked' : 'unchecked') + item.classList.remove(focus ? 'unchecked' : 'checked') } }) + + return item + } ) }) 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, display: inline-block; float: right; } + + &.unchecked::before { + content: '\2610'; + float: right; + margin-left: 0.5em; + } + + &.checked::before { + content: '\2611'; + float: right; + margin-left: 0.5em; + } } .sub-menu { @@ -746,3 +758,5 @@ p a[href^='http']::after, .bold-options { font-weight: bold; } +standard: Use JavaScript Standard Style (https://standardjs.com) +standard: :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 }) => { const menu = document.createElement('div') menu.className = 'menu' menu.style.display = 'none' - menu.onclick = () => (menu.style.display = 'none') + menu.onclick = (e) => { + const keepMenu = e.target.closest('.keep-menu') || e.target.classList.contains('.keep-menu') + if (keepMenu) return + + menu.style.display = 'none' + } container.appendChild(menu) // Menu Items @@ -505,6 +510,9 @@ export const generateMaps = (container, { delay, mapCallback }) => { // Remove menu when click outside const actionOutsideMenu = e => { if (menu.style.display === 'none') return + const keepMenu = e.target.closest('.keep-menu') || e.target.classList.contains('.keep-menu') + if (keepMenu) return + const rect = menu.getBoundingClientRect() if ( e.clientX < rect.left || -- cgit v1.2.3-70-g09d2