diff options
-rw-r--r-- | src/MenuItem.mjs | 36 | ||||
-rw-r--r-- | src/css/dumbymap.css | 2 | ||||
-rw-r--r-- | src/dumbyUtils.mjs | 15 | ||||
-rw-r--r-- | src/dumbymap.mjs | 41 |
4 files changed, 78 insertions, 16 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 @@ | |||
1 | import { shiftByWindow } from './utils.mjs' | 1 | import { shiftByWindow } from './utils.mjs' |
2 | import * as utils from './dumbyUtils.mjs' | ||
2 | 3 | ||
3 | /** | 4 | /** |
4 | * @typedef {Object} RefLink | 5 | * @typedef {Object} RefLink |
@@ -426,3 +427,38 @@ export const addRefLink = (cm, refLinks) => | |||
426 | }) | 427 | }) |
427 | }), | 428 | }), |
428 | }) | 429 | }) |
430 | |||
431 | /** | ||
432 | * setGeoLinkTypeItem. | ||
433 | * | ||
434 | * @param {HTMLAnchorElement} link | ||
435 | * @param {String} text | ||
436 | * @param {String} type | ||
437 | */ | ||
438 | export const setGeoLinkTypeItem = ({ link, text, type }) => { | ||
439 | const params = new URLSearchParams(link.search) | ||
440 | return new Item({ | ||
441 | text, | ||
442 | onclick: () => { | ||
443 | params.set('type', type) | ||
444 | link.search = params | ||
445 | utils.removeLeaderLines(link) | ||
446 | utils.getMarkersFromMaps(link) | ||
447 | .forEach(marker => marker.remove()) | ||
448 | utils.getMarkersFromMaps(link) | ||
449 | }, | ||
450 | }) | ||
451 | } | ||
452 | |||
453 | /** | ||
454 | * setGeoLinkType. | ||
455 | * | ||
456 | * @param {HTMLAnchorElement} link | ||
457 | */ | ||
458 | export const setGeoLinkType = (link) => new Folder({ | ||
459 | text: 'Marker Type', | ||
460 | items: [ | ||
461 | setGeoLinkTypeItem({ link, text: 'Pin', type: 'pin' }), | ||
462 | setGeoLinkTypeItem({ link, text: 'Circle', type: 'circle' }), | ||
463 | ], | ||
464 | }) | ||
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) { | |||
171 | } | 171 | } |
172 | 172 | ||
173 | .menu { | 173 | .menu { |
174 | display: block; | 174 | display: none; |
175 | overflow: visible; | 175 | overflow: visible; |
176 | width: fit-content; | 176 | width: fit-content; |
177 | min-width: 10rem; | 177 | min-width: 10rem; |
diff --git a/src/dumbyUtils.mjs b/src/dumbyUtils.mjs index 214e44f..8fe23eb 100644 --- a/src/dumbyUtils.mjs +++ b/src/dumbyUtils.mjs | |||
@@ -93,7 +93,8 @@ export function removeBlockFocus () { | |||
93 | * @param {HTMLAnchorElement} link | 93 | * @param {HTMLAnchorElement} link |
94 | * @return {HTMLElement[]} markers | 94 | * @return {HTMLElement[]} markers |
95 | */ | 95 | */ |
96 | const getMarkersFromMaps = link => { | 96 | export const getMarkersFromMaps = link => { |
97 | const params = new URLSearchParams(link.search) | ||
97 | const maps = Array.from( | 98 | const maps = Array.from( |
98 | link.closest('.Dumby') | 99 | link.closest('.Dumby') |
99 | .querySelectorAll('.mapclay[data-render="fulfilled"]'), | 100 | .querySelectorAll('.mapclay[data-render="fulfilled"]'), |
@@ -107,7 +108,7 @@ const getMarkersFromMaps = link => { | |||
107 | const marker = map.querySelector(`.marker[data-xy="${lonLat}"]`) ?? | 108 | const marker = map.querySelector(`.marker[data-xy="${lonLat}"]`) ?? |
108 | renderer.addMarker({ | 109 | renderer.addMarker({ |
109 | xy: lonLat, | 110 | xy: lonLat, |
110 | type: link.type, | 111 | type: params.get('type') ?? null, |
111 | }) | 112 | }) |
112 | marker.dataset.xy = lonLat | 113 | marker.dataset.xy = lonLat |
113 | marker.title = new URLSearchParams(link.search).get('xy') ?? lonLat | 114 | marker.title = new URLSearchParams(link.search).get('xy') ?? lonLat |
@@ -167,7 +168,6 @@ export const createGeoLink = (link) => { | |||
167 | link.classList.remove('not-geolink') | 168 | link.classList.remove('not-geolink') |
168 | // TODO refactor as data attribute | 169 | // TODO refactor as data attribute |
169 | link.targets = params.get('id')?.split(',') ?? null | 170 | link.targets = params.get('id')?.split(',') ?? null |
170 | link.type = params.get('type') ?? null | ||
171 | link.title = 'Left-Click to move Camera, Middle-Click to clean anchor' | 171 | link.title = 'Left-Click to move Camera, Middle-Click to clean anchor' |
172 | 172 | ||
173 | link.lines = [] | 173 | link.lines = [] |
@@ -385,7 +385,7 @@ export const dragForAnchor = (container, range, endOfLeaderLine) => { | |||
385 | container.classList.add('dragging-geolink') | 385 | container.classList.add('dragging-geolink') |
386 | const geoLink = document.createElement('a') | 386 | const geoLink = document.createElement('a') |
387 | geoLink.textContent = range.toString() | 387 | geoLink.textContent = range.toString() |
388 | geoLink.classList.add('with-leader-line', 'geolink', 'drag') | 388 | geoLink.classList.add('with-leader-line', 'geolink', 'drag', 'from-text') |
389 | 389 | ||
390 | // Replace current content with link | 390 | // Replace current content with link |
391 | const originContent = range.cloneContents() | 391 | const originContent = range.cloneContents() |
@@ -439,6 +439,11 @@ export const dragForAnchor = (container, range, endOfLeaderLine) => { | |||
439 | } | 439 | } |
440 | } | 440 | } |
441 | 441 | ||
442 | /** | ||
443 | * addGeoSchemeByText. | ||
444 | * | ||
445 | * @param {Node} node | ||
446 | */ | ||
442 | export const addGeoSchemeByText = async (node) => { | 447 | export const addGeoSchemeByText = async (node) => { |
443 | const digit = '[\\d\\uFF10-\\uFF19]' | 448 | const digit = '[\\d\\uFF10-\\uFF19]' |
444 | const decimal = '[.\\uFF0E]' | 449 | const decimal = '[.\\uFF0E]' |
@@ -451,7 +456,7 @@ export const addGeoSchemeByText = async (node) => { | |||
451 | if (Date.parse(match.at(0) + ' 1990')) return null | 456 | if (Date.parse(match.at(0) + ' 1990')) return null |
452 | 457 | ||
453 | const a = document.createElement('a') | 458 | const a = document.createElement('a') |
454 | a.className = 'not-geolink' | 459 | a.className = 'not-geolink from-text' |
455 | a.href = `geo:0,0?xy=${x},${y}` | 460 | a.href = `geo:0,0?xy=${x},${y}` |
456 | a.textContent = match.at(0) | 461 | a.textContent = match.at(0) |
457 | return a | 462 | return a |
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 8b9a2a6..4d6657f 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
@@ -527,25 +527,46 @@ export const generateMaps = (container, { | |||
527 | 527 | ||
528 | /** MENU: Menu Items for Context Menu */ | 528 | /** MENU: Menu Items for Context Menu */ |
529 | container.oncontextmenu = e => { | 529 | container.oncontextmenu = e => { |
530 | container.querySelectorAll('.dumby-menu').forEach(m => m.remove()) | ||
530 | const map = e.target.closest('.mapclay') | 531 | const map = e.target.closest('.mapclay') |
531 | const block = e.target.closest('.dumby-block') | 532 | const block = e.target.closest('.dumby-block') |
532 | if (!block && !map) return | 533 | const geoLink = e.target.closest('.geolink') |
534 | if (!block && !map && !geoLink) return | ||
533 | e.preventDefault() | 535 | e.preventDefault() |
534 | 536 | ||
535 | /** MENU: Prepare Context Menu */ | 537 | // Add menu element |
536 | const menu = document.createElement('div') | 538 | const menu = document.createElement('div') |
537 | menu.classList.add('menu', 'dumby-menu') | 539 | menu.classList.add('menu', 'dumby-menu') |
538 | menu.onclick = (e) => { | 540 | menu.onclick = (e) => { |
539 | const keepMenu = e.target.closest('.keep-menu') || e.target.classList.contains('.keep-menu') | 541 | if (e.target.closest('.keep-menu')) return |
540 | if (keepMenu) return | ||
541 | |||
542 | menu.remove() | 542 | menu.remove() |
543 | } | 543 | } |
544 | container.body.appendChild(menu) | 544 | container.appendChild(menu) |
545 | 545 | new MutationObserver(() => { | |
546 | menu.replaceChildren() | 546 | menu.style.display = 'block' |
547 | menu.style.display = 'block' | 547 | menu.style.left = (e.clientX - menu.offsetParent.offsetLeft + 10) + 'px' |
548 | menu.style.cssText = `left: ${e.clientX - menu.offsetParent.offsetLeft + 10}px; top: ${e.clientY - menu.offsetParent.offsetTop + 5}px;` | 548 | menu.style.top = (e.clientY - menu.offsetParent.offsetTop + 5) + 'px' |
549 | clearTimeout(menu.timer) | ||
550 | }).observe(menu, { childList: true }) | ||
551 | menu.timer = setTimeout(() => menu.remove(), 100) | ||
552 | |||
553 | // Menu Items for GeoLink | ||
554 | if (geoLink) { | ||
555 | if (geoLink.classList.contains('from-text')) { | ||
556 | menu.appendChild(new menuItem.Item({ | ||
557 | text: 'Delete', | ||
558 | onclick: () => { | ||
559 | utils.getMarkersFromMaps(geoLink) | ||
560 | .forEach(m => m.remove()) | ||
561 | geoLink.replaceWith( | ||
562 | document.createTextNode(geoLink.textContent), | ||
563 | ) | ||
564 | }, | ||
565 | })) | ||
566 | } | ||
567 | menu.appendChild(menuItem.setGeoLinkType(geoLink)) | ||
568 | return | ||
569 | } | ||
549 | 570 | ||
550 | // Menu Items for map | 571 | // Menu Items for map |
551 | if (map?.renderer?.results) { | 572 | if (map?.renderer?.results) { |