diff options
author | Hsieh Chin Fan <pham@topo.tw> | 2024-09-30 17:59:05 +0800 |
---|---|---|
committer | Hsieh Chin Fan <pham@topo.tw> | 2024-10-01 11:35:11 +0800 |
commit | f4fe9ff6c1ce2811fe9aa0272333b4732a6ebcdc (patch) | |
tree | 6bde54a5c2afe37fb4bea6a00b492e74a0720e16 /src/dumbymap.mjs | |
parent | 193ba872c455296bff55e5f6a7d6dbbbb85c265e (diff) |
refactor: move menu feature from editor to dumbymap
Diffstat (limited to 'src/dumbymap.mjs')
-rw-r--r-- | src/dumbymap.mjs | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 67376c7..d365712 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
@@ -8,6 +8,7 @@ import { renderWith, defaultAliases, parseConfigsFromYaml } from 'mapclay'; | |||
8 | import { onRemove, animateRectTransition, throttle } from './utils'; | 8 | import { onRemove, animateRectTransition, throttle } from './utils'; |
9 | import { Layout, SideBySide, Overlay } from './Layout'; | 9 | import { Layout, SideBySide, Overlay } from './Layout'; |
10 | import * as utils from './dumbyUtils'; | 10 | import * as utils from './dumbyUtils'; |
11 | import * as menuItem from './MenuItem'; | ||
11 | 12 | ||
12 | const docLinkSelector = 'a[href^="#"][title^="=>"]'; | 13 | const docLinkSelector = 'a[href^="#"][title^="=>"]'; |
13 | const geoLinkSelector = 'a[href^="geo:"]'; | 14 | const geoLinkSelector = 'a[href^="geo:"]'; |
@@ -520,7 +521,57 @@ export const generateMaps = (container, { delay, mapCallback }) => { | |||
520 | clearTimeout(timer); | 521 | clearTimeout(timer); |
521 | }); | 522 | }); |
522 | }); | 523 | }); |
524 | // }}} | ||
525 | |||
526 | // Menu {{{ | ||
527 | const menu = document.createElement('div'); | ||
528 | menu.className = 'menu'; | ||
529 | menu.onclick = () => (menu.style.display = 'none'); | ||
530 | new MutationObserver(() => { | ||
531 | if (menu.style.display === 'none') { | ||
532 | menu.style.cssText = ''; | ||
533 | menu.replaceChildren(); | ||
534 | } | ||
535 | }).observe(menu, { | ||
536 | attributes: true, | ||
537 | attributeFilter: ['style'], | ||
538 | }); | ||
539 | container.appendChild(menu); | ||
540 | |||
541 | // Menu Items | ||
542 | container.oncontextmenu = e => { | ||
543 | const selection = document.getSelection(); | ||
544 | const range = selection.getRangeAt(0); | ||
545 | if (selection) { | ||
546 | e.preventDefault(); | ||
547 | menu.innerHTML = ''; | ||
548 | const addGeoLink = new menuItem.GeoLink({ range }); | ||
549 | menu.appendChild(addGeoLink.createElement()); | ||
550 | } | ||
551 | menu.style.cssText = `overflow: visible; display: block; left: ${e.clientX + 10}px; top: ${e.clientY + 5}px;`; | ||
552 | menu.appendChild(menuItem.modal); | ||
553 | menu.appendChild(menuItem.pickMapItem(dumbymap)); | ||
554 | menu.appendChild(menuItem.pickBlockItem(dumbymap)); | ||
555 | menu.appendChild(menuItem.pickLayoutItem(dumbymap)); | ||
556 | }; | ||
523 | 557 | ||
558 | // Remove menu when click outside | ||
559 | const actionOutsideMenu = e => { | ||
560 | if (menu.style.display === 'none') return; | ||
561 | const rect = menu.getBoundingClientRect(); | ||
562 | if ( | ||
563 | e.clientX < rect.left || | ||
564 | e.clientX > rect.left + rect.width || | ||
565 | e.clientY < rect.top || | ||
566 | e.clientY > rect.top + rect.height | ||
567 | ) { | ||
568 | menu.style.display = 'none'; | ||
569 | } | ||
570 | }; | ||
571 | document.addEventListener('click', actionOutsideMenu); | ||
572 | onRemove(htmlHolder, () => | ||
573 | document.removeEventListener('click', actionOutsideMenu), | ||
574 | ); | ||
524 | //}}} | 575 | //}}} |
525 | return Object.seal(dumbymap); | 576 | return Object.seal(dumbymap); |
526 | }; | 577 | }; |