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) { |