From 405cc77d0b8e7e864137ba9f485c47e4f1fb07af Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Thu, 24 Oct 2024 01:02:45 +0800 Subject: feat: improve menu element * add observer for display and position, in case no menu item inside * remove all existing menus when oncontextmenu --- src/css/dumbymap.css | 2 +- src/dumbymap.mjs | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/css/dumbymap.css b/src/css/dumbymap.css index 8dfe90d..8ba0887 100644 --- a/src/css/dumbymap.css +++ b/src/css/dumbymap.css @@ -171,7 +171,7 @@ pre:has(.mapclay) { } .menu { - display: block; + display: none; overflow: visible; width: fit-content; min-width: 10rem; diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 8b9a2a6..2f2b67f 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs @@ -527,25 +527,27 @@ export const generateMaps = (container, { /** MENU: Menu Items for Context Menu */ container.oncontextmenu = e => { + container.querySelectorAll('.dumby-menu').forEach(m => m.remove()) const map = e.target.closest('.mapclay') const block = e.target.closest('.dumby-block') if (!block && !map) return e.preventDefault() - /** MENU: Prepare Context Menu */ + // Add menu element const menu = document.createElement('div') menu.classList.add('menu', 'dumby-menu') menu.onclick = (e) => { - const keepMenu = e.target.closest('.keep-menu') || e.target.classList.contains('.keep-menu') - if (keepMenu) return - + if (e.target.closest('.keep-menu')) return menu.remove() } - container.body.appendChild(menu) - - menu.replaceChildren() - menu.style.display = 'block' - menu.style.cssText = `left: ${e.clientX - menu.offsetParent.offsetLeft + 10}px; top: ${e.clientY - menu.offsetParent.offsetTop + 5}px;` + container.appendChild(menu) + new MutationObserver(() => { + menu.style.display = 'block' + menu.style.left = (e.clientX - menu.offsetParent.offsetLeft + 10) + 'px' + menu.style.top = (e.clientY - menu.offsetParent.offsetTop + 5) + 'px' + clearTimeout(menu.timer) + }).observe(menu, { childList: true }) + menu.timer = setTimeout(() => menu.remove(), 100) // Menu Items for map if (map?.renderer?.results) { -- cgit v1.2.3-70-g09d2 From 6d7da75bdcca544ac40ad1d93e8da1a4fee8d4f2 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Thu, 24 Oct 2024 10:38:30 +0800 Subject: feat: add menu item for deleting GeoLink from raw text --- src/dumbyUtils.mjs | 9 +++++++-- src/dumbymap.mjs | 14 +++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/dumbyUtils.mjs b/src/dumbyUtils.mjs index 214e44f..42a51bc 100644 --- a/src/dumbyUtils.mjs +++ b/src/dumbyUtils.mjs @@ -385,7 +385,7 @@ export const dragForAnchor = (container, range, endOfLeaderLine) => { container.classList.add('dragging-geolink') const geoLink = document.createElement('a') geoLink.textContent = range.toString() - geoLink.classList.add('with-leader-line', 'geolink', 'drag') + geoLink.classList.add('with-leader-line', 'geolink', 'drag', 'from-text') // Replace current content with link const originContent = range.cloneContents() @@ -439,6 +439,11 @@ export const dragForAnchor = (container, range, endOfLeaderLine) => { } } +/** + * addGeoSchemeByText. + * + * @param {Node} node + */ export const addGeoSchemeByText = async (node) => { const digit = '[\\d\\uFF10-\\uFF19]' const decimal = '[.\\uFF0E]' @@ -451,7 +456,7 @@ export const addGeoSchemeByText = async (node) => { if (Date.parse(match.at(0) + ' 1990')) return null const a = document.createElement('a') - a.className = 'not-geolink' + a.className = 'not-geolink from-text' a.href = `geo:0,0?xy=${x},${y}` a.textContent = match.at(0) return a diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 2f2b67f..6e5bc38 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs @@ -530,7 +530,8 @@ export const generateMaps = (container, { container.querySelectorAll('.dumby-menu').forEach(m => m.remove()) const map = e.target.closest('.mapclay') const block = e.target.closest('.dumby-block') - if (!block && !map) return + const geoLink = e.target.closest('.geolink') + if (!block && !map && !geoLink) return e.preventDefault() // Add menu element @@ -549,6 +550,17 @@ export const generateMaps = (container, { }).observe(menu, { childList: true }) menu.timer = setTimeout(() => menu.remove(), 100) + // Menu Items for GeoLink + if (geoLink) { + if (geoLink.classList.contains('from-text')) { + menu.appendChild(new menuItem.Item({ + text: 'Delete', + onclick: () => geoLink.replaceWith(document.createTextNode(geoLink.textContent)), + })) + } + return + } + // Menu Items for map if (map?.renderer?.results) { const rect = map.getBoundingClientRect() -- cgit v1.2.3-70-g09d2 From 14f13987693ff3733bf6167fbfc3c70f1b6864bf Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Thu, 24 Oct 2024 12:14:50 +0800 Subject: feat: add menu items for setting marker type --- src/MenuItem.mjs | 36 ++++++++++++++++++++++++++++++++++++ src/dumbyUtils.mjs | 6 +++--- src/dumbymap.mjs | 9 ++++++++- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs index 74b01d5..874c829 100644 --- a/src/MenuItem.mjs +++ b/src/MenuItem.mjs @@ -1,4 +1,5 @@ import { shiftByWindow } from './utils.mjs' +import * as utils from './dumbyUtils.mjs' /** * @typedef {Object} RefLink @@ -426,3 +427,38 @@ export const addRefLink = (cm, refLinks) => }) }), }) + +/** + * setGeoLinkTypeItem. + * + * @param {HTMLAnchorElement} link + * @param {String} text + * @param {String} type + */ +export const setGeoLinkTypeItem = ({ link, text, type }) => { + const params = new URLSearchParams(link.search) + return new Item({ + text, + onclick: () => { + params.set('type', type) + link.search = params + utils.removeLeaderLines(link) + utils.getMarkersFromMaps(link) + .forEach(marker => marker.remove()) + utils.getMarkersFromMaps(link) + }, + }) +} + +/** + * setGeoLinkType. + * + * @param {HTMLAnchorElement} link + */ +export const setGeoLinkType = (link) => new Folder({ + text: 'Marker Type', + items: [ + setGeoLinkTypeItem({ link, text: 'Pin', type: 'pin' }), + setGeoLinkTypeItem({ link, text: 'Circle', type: 'circle' }), + ], +}) diff --git a/src/dumbyUtils.mjs b/src/dumbyUtils.mjs index 42a51bc..8fe23eb 100644 --- a/src/dumbyUtils.mjs +++ b/src/dumbyUtils.mjs @@ -93,7 +93,8 @@ export function removeBlockFocus () { * @param {HTMLAnchorElement} link * @return {HTMLElement[]} markers */ -const getMarkersFromMaps = link => { +export const getMarkersFromMaps = link => { + const params = new URLSearchParams(link.search) const maps = Array.from( link.closest('.Dumby') .querySelectorAll('.mapclay[data-render="fulfilled"]'), @@ -107,7 +108,7 @@ const getMarkersFromMaps = link => { const marker = map.querySelector(`.marker[data-xy="${lonLat}"]`) ?? renderer.addMarker({ xy: lonLat, - type: link.type, + type: params.get('type') ?? null, }) marker.dataset.xy = lonLat marker.title = new URLSearchParams(link.search).get('xy') ?? lonLat @@ -167,7 +168,6 @@ export const createGeoLink = (link) => { link.classList.remove('not-geolink') // TODO refactor as data attribute link.targets = params.get('id')?.split(',') ?? null - link.type = params.get('type') ?? null link.title = 'Left-Click to move Camera, Middle-Click to clean anchor' link.lines = [] diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 6e5bc38..4d6657f 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs @@ -555,9 +555,16 @@ export const generateMaps = (container, { if (geoLink.classList.contains('from-text')) { menu.appendChild(new menuItem.Item({ text: 'Delete', - onclick: () => geoLink.replaceWith(document.createTextNode(geoLink.textContent)), + onclick: () => { + utils.getMarkersFromMaps(geoLink) + .forEach(m => m.remove()) + geoLink.replaceWith( + document.createTextNode(geoLink.textContent), + ) + }, })) } + menu.appendChild(menuItem.setGeoLinkType(geoLink)) return } -- cgit v1.2.3-70-g09d2