diff options
author | Hsieh Chin Fan <pham@topo.tw> | 2024-10-01 16:31:39 +0800 |
---|---|---|
committer | Hsieh Chin Fan <pham@topo.tw> | 2024-10-01 20:07:06 +0800 |
commit | acad0593c6971a693078eeeb4fb15f278c427fa9 (patch) | |
tree | 11cff487265045c31d011170208cd9b366b26e5e /src | |
parent | 5c55ea01e1df826bf21f33c6ef067b0c7d60d4f8 (diff) |
fix: set menu position relative to click
need to calculate offset of parent element
Diffstat (limited to 'src')
-rw-r--r-- | src/MenuItem.mjs | 6 | ||||
-rw-r--r-- | src/css/dumbymap.css | 243 | ||||
-rw-r--r-- | src/dumbymap.mjs | 4 |
3 files changed, 134 insertions, 119 deletions
diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs index 6c2a1d9..8b812b1 100644 --- a/src/MenuItem.mjs +++ b/src/MenuItem.mjs | |||
@@ -4,6 +4,12 @@ class Item extends HTMLDivElement { | |||
4 | this.innerHTML = innerHTML ?? text; | 4 | this.innerHTML = innerHTML ?? text; |
5 | this.onclick = onclick; | 5 | this.onclick = onclick; |
6 | this.classList.add('menu-item'); | 6 | this.classList.add('menu-item'); |
7 | |||
8 | this.onmouseover = () => { | ||
9 | this.parentElement | ||
10 | .querySelectorAll('.sub-menu') | ||
11 | .forEach(sub => sub.remove()); | ||
12 | } | ||
7 | } | 13 | } |
8 | } | 14 | } |
9 | window.customElements.define('menu-item', Item, { extends: 'div' }); | 15 | window.customElements.define('menu-item', Item, { extends: 'div' }); |
diff --git a/src/css/dumbymap.css b/src/css/dumbymap.css index 7cb4d8c..4d0282b 100644 --- a/src/css/dumbymap.css +++ b/src/css/dumbymap.css | |||
@@ -219,6 +219,131 @@ root { | |||
219 | } | 219 | } |
220 | } | 220 | } |
221 | 221 | ||
222 | .menu { | ||
223 | display: block; | ||
224 | width: fit-content; | ||
225 | min-width: 10rem; | ||
226 | max-height: 40vh; | ||
227 | overflow-x: visible; | ||
228 | |||
229 | position: absolute; | ||
230 | z-index: 9999; | ||
231 | |||
232 | border: 2px solid gray; | ||
233 | border-radius: 6px; | ||
234 | |||
235 | background: white; | ||
236 | |||
237 | & > *:first-child { | ||
238 | border-top: 2px solid transparent; | ||
239 | border-radius: 5px 5px 0 0; | ||
240 | } | ||
241 | |||
242 | & > *:last-child { | ||
243 | border-bottom: 2px solid transparent; | ||
244 | border-radius: 0 0 5px 5px; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | .menu-item { | ||
249 | display: flex; | ||
250 | justify-content: space-between; | ||
251 | padding: 0.5rem; | ||
252 | position: relative; | ||
253 | |||
254 | z-index: 9999; | ||
255 | |||
256 | cursor: pointer; | ||
257 | text-wrap: nowrap; | ||
258 | |||
259 | &:hover { | ||
260 | background: rgb(226 232 240); | ||
261 | } | ||
262 | |||
263 | .info { | ||
264 | padding-inline: 1em; | ||
265 | |||
266 | color: steelblue; | ||
267 | font-weight: bold; | ||
268 | } | ||
269 | |||
270 | &.folder::after { | ||
271 | content: '⏵'; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | .sub-menu { | ||
276 | overflow: scroll; | ||
277 | width: fit-content; | ||
278 | min-width: 6rem; | ||
279 | max-height: 40vh; | ||
280 | |||
281 | position: absolute; | ||
282 | z-index: 100; | ||
283 | |||
284 | border: 2px solid gray; | ||
285 | border-radius: 6px; | ||
286 | |||
287 | background: white; | ||
288 | |||
289 | .menu-item { | ||
290 | min-width: 5em; | ||
291 | margin: 0 auto; | ||
292 | padding-inline: 0.5em; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | .plainoverlay-body { | ||
297 | position: absolute; | ||
298 | } | ||
299 | |||
300 | .plainmodal-content { | ||
301 | width: 700px; | ||
302 | height: 80%; | ||
303 | padding: 1em; | ||
304 | |||
305 | position: absolute; | ||
306 | left: 50vw; | ||
307 | top: 50vh; | ||
308 | |||
309 | background: white; | ||
310 | |||
311 | transform: translate(-50%, -50%); | ||
312 | overflow-y: scroll; | ||
313 | white-space: pre; | ||
314 | |||
315 | details { | ||
316 | margin-bottom: 0.5em; | ||
317 | } | ||
318 | |||
319 | summary { | ||
320 | max-width: 60%; | ||
321 | |||
322 | cursor: pointer; | ||
323 | } | ||
324 | |||
325 | details > :not(summary) { | ||
326 | padding-left: 2em; | ||
327 | } | ||
328 | |||
329 | p { | ||
330 | margin: 0.3em; | ||
331 | white-space: nowrap; | ||
332 | overflow-x: scroll; | ||
333 | } | ||
334 | |||
335 | pre { | ||
336 | padding: 0.5em; | ||
337 | |||
338 | background: #f0f0f0; | ||
339 | } | ||
340 | |||
341 | .align-right { | ||
342 | display: inline-block; | ||
343 | float: right; | ||
344 | } | ||
345 | } | ||
346 | |||
222 | .Dumby { | 347 | .Dumby { |
223 | overflow: visible; | 348 | overflow: visible; |
224 | width: 100%; | 349 | width: 100%; |
@@ -609,121 +734,3 @@ root { | |||
609 | .bold-options { | 734 | .bold-options { |
610 | font-weight: bold; | 735 | font-weight: bold; |
611 | } | 736 | } |
612 | |||
613 | .menu { | ||
614 | display: none; | ||
615 | width: fit-content; | ||
616 | min-width: 10rem; | ||
617 | max-height: 40vh; | ||
618 | |||
619 | position: absolute; | ||
620 | z-index: 9999; | ||
621 | |||
622 | border: 2px solid gray; | ||
623 | border-radius: 6px; | ||
624 | |||
625 | background: white; | ||
626 | overflow-y: scroll; | ||
627 | } | ||
628 | |||
629 | .menu-item { | ||
630 | display: flex; | ||
631 | box-sizing: border-box; | ||
632 | justify-content: space-between; | ||
633 | padding: 0.5rem; | ||
634 | |||
635 | z-index: 9999; | ||
636 | |||
637 | border: 2px solid transparent; | ||
638 | border-radius: 5px; | ||
639 | |||
640 | cursor: pointer; | ||
641 | text-wrap: nowrap; | ||
642 | |||
643 | &:hover { | ||
644 | background: rgb(226 232 240); | ||
645 | } | ||
646 | |||
647 | .info { | ||
648 | padding-inline: 1em; | ||
649 | |||
650 | color: steelblue; | ||
651 | font-weight: bold; | ||
652 | } | ||
653 | } | ||
654 | |||
655 | .folder::after { | ||
656 | content: '⏵'; | ||
657 | } | ||
658 | |||
659 | .sub-menu { | ||
660 | overflow: scroll; | ||
661 | width: fit-content; | ||
662 | min-width: 6rem; | ||
663 | max-height: 40vh; | ||
664 | |||
665 | position: absolute; | ||
666 | z-index: 100; | ||
667 | |||
668 | border: 2px solid gray; | ||
669 | border-radius: 6px; | ||
670 | |||
671 | background: white; | ||
672 | |||
673 | .menu-item { | ||
674 | min-width: 5em; | ||
675 | margin: 0 auto; | ||
676 | padding-inline: 0.5em; | ||
677 | } | ||
678 | } | ||
679 | |||
680 | .plainoverlay-body { | ||
681 | position: absolute; | ||
682 | } | ||
683 | |||
684 | .plainmodal-content { | ||
685 | width: 700px; | ||
686 | height: 80%; | ||
687 | padding: 1em; | ||
688 | |||
689 | position: absolute; | ||
690 | left: 50vw; | ||
691 | top: 50vh; | ||
692 | |||
693 | background: white; | ||
694 | |||
695 | transform: translate(-50%, -50%); | ||
696 | overflow-y: scroll; | ||
697 | white-space: pre; | ||
698 | |||
699 | details { | ||
700 | margin-bottom: 0.5em; | ||
701 | } | ||
702 | |||
703 | summary { | ||
704 | max-width: 60%; | ||
705 | |||
706 | cursor: pointer; | ||
707 | } | ||
708 | |||
709 | details > :not(summary) { | ||
710 | padding-left: 2em; | ||
711 | } | ||
712 | |||
713 | p { | ||
714 | margin: 0.3em; | ||
715 | white-space: nowrap; | ||
716 | overflow-x: scroll; | ||
717 | } | ||
718 | |||
719 | pre { | ||
720 | padding: 0.5em; | ||
721 | |||
722 | background: #f0f0f0; | ||
723 | } | ||
724 | |||
725 | .align-right { | ||
726 | display: inline-block; | ||
727 | float: right; | ||
728 | } | ||
729 | } | ||
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 2a6f332..cb528cd 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
@@ -462,12 +462,15 @@ export const generateMaps = (container, { delay, mapCallback }) => { | |||
462 | // Menu {{{ | 462 | // Menu {{{ |
463 | const menu = document.createElement('div'); | 463 | const menu = document.createElement('div'); |
464 | menu.className = 'menu'; | 464 | menu.className = 'menu'; |
465 | menu.style.display = 'none'; | ||
465 | menu.onclick = () => (menu.style.display = 'none'); | 466 | menu.onclick = () => (menu.style.display = 'none'); |
466 | container.appendChild(menu); | 467 | container.appendChild(menu); |
467 | 468 | ||
468 | // Menu Items | 469 | // Menu Items |
469 | container.oncontextmenu = e => { | 470 | container.oncontextmenu = e => { |
470 | menu.replaceChildren(); | 471 | menu.replaceChildren(); |
472 | menu.style.display = 'block'; | ||
473 | menu.style.cssText = `left: ${e.x - menu.offsetParent.offsetLeft + 10}px; top: ${e.y - menu.offsetParent.offsetTop + 5}px;`; | ||
471 | e.preventDefault(); | 474 | e.preventDefault(); |
472 | 475 | ||
473 | // GeoLinks | 476 | // GeoLinks |
@@ -476,7 +479,6 @@ export const generateMaps = (container, { delay, mapCallback }) => { | |||
476 | const range = selection.getRangeAt(0); | 479 | const range = selection.getRangeAt(0); |
477 | menu.appendChild(menuItem.addGeoLink(dumbymap, range)); | 480 | menu.appendChild(menuItem.addGeoLink(dumbymap, range)); |
478 | } | 481 | } |
479 | menu.style.cssText = `overflow: visible; display: block; left: ${e.clientX + 10}px; top: ${e.clientY + 5}px;`; | ||
480 | 482 | ||
481 | const map = e.target.closest('.mapclay'); | 483 | const map = e.target.closest('.mapclay'); |
482 | if (map?.renderer?.results) { | 484 | if (map?.renderer?.results) { |