diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/MenuItem.mjs | 5 | ||||
| -rw-r--r-- | src/css/dumbymap.css | 69 | ||||
| -rw-r--r-- | src/css/index.css | 67 | ||||
| -rw-r--r-- | src/dumbymap.mjs | 51 | ||||
| -rw-r--r-- | src/editor.mjs | 34 |
5 files changed, 123 insertions, 103 deletions
diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs index f4cd518..74138ec 100644 --- a/src/MenuItem.mjs +++ b/src/MenuItem.mjs | |||
| @@ -89,7 +89,10 @@ export const pickLayoutItem = dumbymap => | |||
| 89 | items: [ | 89 | items: [ |
| 90 | new Item({ | 90 | new Item({ |
| 91 | text: 'EDIT', | 91 | text: 'EDIT', |
| 92 | onclick: () => document.body.setAttribute('data-mode', 'editing'), | 92 | onclick: () => |
| 93 | dumbymap.container | ||
| 94 | .closest('.playground') | ||
| 95 | .setAttribute('data-mode', 'editing'), | ||
| 93 | }).element, | 96 | }).element, |
| 94 | ...dumbymap.layouts.map( | 97 | ...dumbymap.layouts.map( |
| 95 | layout => | 98 | layout => |
diff --git a/src/css/dumbymap.css b/src/css/dumbymap.css index f6275ab..822353f 100644 --- a/src/css/dumbymap.css +++ b/src/css/dumbymap.css | |||
| @@ -226,7 +226,7 @@ root { | |||
| 226 | padding: 0; | 226 | padding: 0; |
| 227 | 227 | ||
| 228 | position: relative; | 228 | position: relative; |
| 229 | overflow-x: auto; | 229 | overflow: visible; |
| 230 | 230 | ||
| 231 | &::after { | 231 | &::after { |
| 232 | content: 'Layout: ' attr(data-layout); | 232 | content: 'Layout: ' attr(data-layout); |
| @@ -609,3 +609,70 @@ root { | |||
| 609 | .bold-options { | 609 | .bold-options { |
| 610 | font-weight: bold; | 610 | font-weight: bold; |
| 611 | } | 611 | } |
| 612 | |||
| 613 | .menu { | ||
| 614 | display: none; | ||
| 615 | width: fit-content; | ||
| 616 | |||
| 617 | position: absolute; | ||
| 618 | z-index: 9999; | ||
| 619 | |||
| 620 | border: 2px solid gray; | ||
| 621 | border-radius: 6px; | ||
| 622 | |||
| 623 | background: white; | ||
| 624 | min-width: 10rem; | ||
| 625 | max-height: 40vh; | ||
| 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 | |||
| 663 | position: absolute; | ||
| 664 | z-index: 100; | ||
| 665 | |||
| 666 | border: 2px solid gray; | ||
| 667 | border-radius: 6px; | ||
| 668 | |||
| 669 | background: white; | ||
| 670 | min-width: 6rem; | ||
| 671 | max-height: 40vh; | ||
| 672 | |||
| 673 | .menu-item { | ||
| 674 | margin: 0 auto; | ||
| 675 | padding-inline: 0.5em; | ||
| 676 | min-width: 5em; | ||
| 677 | } | ||
| 678 | } | ||
diff --git a/src/css/index.css b/src/css/index.css index 069bf85..b13a45d 100644 --- a/src/css/index.css +++ b/src/css/index.css | |||
| @@ -104,22 +104,6 @@ body { | |||
| 104 | } | 104 | } |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | #menu { | ||
| 108 | display: none; | ||
| 109 | width: fit-content; | ||
| 110 | |||
| 111 | position: absolute; | ||
| 112 | z-index: 9999; | ||
| 113 | |||
| 114 | border: 2px solid gray; | ||
| 115 | border-radius: 6px; | ||
| 116 | |||
| 117 | background: white; | ||
| 118 | min-width: 10rem; | ||
| 119 | max-height: 40vh; | ||
| 120 | overflow-y: scroll; | ||
| 121 | } | ||
| 122 | |||
| 123 | .container__suggestion { | 107 | .container__suggestion { |
| 124 | display: flex; | 108 | display: flex; |
| 125 | overflow: hidden; | 109 | overflow: hidden; |
| @@ -161,54 +145,3 @@ body { | |||
| 161 | } | 145 | } |
| 162 | } | 146 | } |
| 163 | } | 147 | } |
| 164 | |||
| 165 | .menu-item { | ||
| 166 | display: flex; | ||
| 167 | box-sizing: border-box; | ||
| 168 | justify-content: space-between; | ||
| 169 | padding: 0.5rem; | ||
| 170 | |||
| 171 | z-index: 9999; | ||
| 172 | |||
| 173 | border: 2px solid transparent; | ||
| 174 | border-radius: 5px; | ||
| 175 | |||
| 176 | cursor: pointer; | ||
| 177 | text-wrap: nowrap; | ||
| 178 | |||
| 179 | &:hover { | ||
| 180 | background: rgb(226 232 240); | ||
| 181 | } | ||
| 182 | |||
| 183 | .info { | ||
| 184 | padding-inline: 1em; | ||
| 185 | |||
| 186 | color: steelblue; | ||
| 187 | font-weight: bold; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | .folder::after { | ||
| 192 | content: '⏵'; | ||
| 193 | } | ||
| 194 | |||
| 195 | .sub-menu { | ||
| 196 | overflow: scroll; | ||
| 197 | width: fit-content; | ||
| 198 | |||
| 199 | position: absolute; | ||
| 200 | z-index: 100; | ||
| 201 | |||
| 202 | border: 2px solid gray; | ||
| 203 | border-radius: 6px; | ||
| 204 | |||
| 205 | background: white; | ||
| 206 | min-width: 6rem; | ||
| 207 | max-height: 40vh; | ||
| 208 | |||
| 209 | .menu-item { | ||
| 210 | margin: 0 auto; | ||
| 211 | padding-inline: 0.5em; | ||
| 212 | min-width: 5em; | ||
| 213 | } | ||
| 214 | } | ||
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 | }; |
diff --git a/src/editor.mjs b/src/editor.mjs index 9946686..760e2e1 100644 --- a/src/editor.mjs +++ b/src/editor.mjs | |||
| @@ -661,39 +661,5 @@ layoutObserver.observe(HtmlContainer, { | |||
| 661 | attributeOldValue: true, | 661 | attributeOldValue: true, |
| 662 | }); | 662 | }); |
| 663 | // }}} | 663 | // }}} |
| 664 | // ContextMenu {{{ | ||
| 665 | document.oncontextmenu = e => { | ||
| 666 | if (cm.hasFocus()) return; | ||
| 667 | |||
| 668 | const selection = document.getSelection(); | ||
| 669 | const range = selection.getRangeAt(0); | ||
| 670 | if (selection) { | ||
| 671 | e.preventDefault(); | ||
| 672 | menu.innerHTML = ''; | ||
| 673 | const addGeoLink = new menuItem.GeoLink({ range }); | ||
| 674 | menu.appendChild(addGeoLink.createElement()); | ||
| 675 | } | ||
| 676 | menu.style.cssText = `overflow: visible; display: block; left: ${e.clientX + 10}px; top: ${e.clientY + 5}px;`; | ||
| 677 | menu.appendChild(menuItem.pickMapItem(dumbymap)); | ||
| 678 | menu.appendChild(menuItem.pickBlockItem(dumbymap)); | ||
| 679 | menu.appendChild(menuItem.pickLayoutItem(dumbymap)); | ||
| 680 | }; | ||
| 681 | |||
| 682 | const actionOutsideMenu = e => { | ||
| 683 | if (menu.style.display === 'none' || cm.hasFocus()) return; | ||
| 684 | const rect = menu.getBoundingClientRect(); | ||
| 685 | if ( | ||
| 686 | e.clientX < rect.left || | ||
| 687 | e.clientX > rect.left + rect.width || | ||
| 688 | e.clientY < rect.top || | ||
| 689 | e.clientY > rect.top + rect.height | ||
| 690 | ) { | ||
| 691 | menu.style.display = 'none'; | ||
| 692 | } | ||
| 693 | }; | ||
| 694 | |||
| 695 | document.addEventListener('click', actionOutsideMenu); | ||
| 696 | |||
| 697 | // }}} | ||
| 698 | 664 | ||
| 699 | // vim: sw=2 ts=2 foldmethod=marker foldmarker={{{,}}} | 665 | // vim: sw=2 ts=2 foldmethod=marker foldmarker={{{,}}} |