diff options
-rw-r--r-- | package.json | 4 | ||||
-rw-r--r-- | src/MenuItem.mjs | 35 | ||||
-rw-r--r-- | src/dumbymap.mjs | 25 | ||||
-rw-r--r-- | src/editor.mjs | 18 |
4 files changed, 53 insertions, 29 deletions
diff --git a/package.json b/package.json index 9ee1a77..3af08b8 100644 --- a/package.json +++ b/package.json | |||
@@ -50,6 +50,7 @@ | |||
50 | "stylelint-order": "^6.0.4" | 50 | "stylelint-order": "^6.0.4" |
51 | }, | 51 | }, |
52 | "dependencies": { | 52 | "dependencies": { |
53 | "cssprefix": "^2.0.17", | ||
53 | "easymde": "^2.18.0", | 54 | "easymde": "^2.18.0", |
54 | "leader-line": "^1.0.7", | 55 | "leader-line": "^1.0.7", |
55 | "mapclay": "^0.8.3", | 56 | "mapclay": "^0.8.3", |
@@ -58,7 +59,8 @@ | |||
58 | "markdown-it-footnote": "^4.0.0", | 59 | "markdown-it-footnote": "^4.0.0", |
59 | "markdown-it-front-matter": "^0.2.4", | 60 | "markdown-it-front-matter": "^0.2.4", |
60 | "markdown-it-toc-done-right": "^4.2.0", | 61 | "markdown-it-toc-done-right": "^4.2.0", |
61 | "plain-draggable": "^2.5.14" | 62 | "plain-draggable": "^2.5.14", |
63 | "plain-modal": "^1.0.34" | ||
62 | }, | 64 | }, |
63 | "author": "Hsiehg Chin Fan <pham@topo.tw>", | 65 | "author": "Hsiehg Chin Fan <pham@topo.tw>", |
64 | "homepage": "https://outdoorsafetylab.github.io/dumbymap", | 66 | "homepage": "https://outdoorsafetylab.github.io/dumbymap", |
diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs index 98f3bae..5604ef1 100644 --- a/src/MenuItem.mjs +++ b/src/MenuItem.mjs | |||
@@ -1,6 +1,5 @@ | |||
1 | import { createGeoLink } from './dumbymap'; | 1 | import { createGeoLink } from './dumbymap'; |
2 | import { scrollToBlock } from './dumbyUtils'; | 2 | import { scrollToBlock } from './dumbyUtils'; |
3 | import { default as PlainModal } from 'plain-modal'; | ||
4 | 3 | ||
5 | class Item extends HTMLDivElement { | 4 | class Item extends HTMLDivElement { |
6 | constructor({ text, innerHTML, onclick }) { | 5 | constructor({ text, innerHTML, onclick }) { |
@@ -38,7 +37,7 @@ window.customElements.define('menu-folder', Folder, { extends: 'div' }); | |||
38 | 37 | ||
39 | export const pickMapItem = dumbymap => | 38 | export const pickMapItem = dumbymap => |
40 | new Folder({ | 39 | new Folder({ |
41 | innerHTML: '<span>Focus a Map<span><span class="info">(Tab)</span>', | 40 | innerHTML: '<span>Maps<span><span class="info">(Tab)</span>', |
42 | items: dumbymap.utils.renderedMaps().map( | 41 | items: dumbymap.utils.renderedMaps().map( |
43 | map => | 42 | map => |
44 | new Item({ | 43 | new Item({ |
@@ -53,15 +52,16 @@ export const pickMapItem = dumbymap => | |||
53 | 52 | ||
54 | export const pickBlockItem = dumbymap => | 53 | export const pickBlockItem = dumbymap => |
55 | new Folder({ | 54 | new Folder({ |
56 | innerHTML: '<span>Focus Block<span><span class="info">(n/p)</span>', | 55 | innerHTML: '<span>Blocks<span><span class="info">(n/p)</span>', |
57 | items: dumbymap.blocks.map( | 56 | items: dumbymap.blocks.map( |
58 | (block, index) => | 57 | (block, index) => |
59 | new Item({ | 58 | new Item({ |
60 | text: | 59 | text: |
60 | `<strong>(${index})</strong>` + | ||
61 | block | 61 | block |
62 | .querySelector('p') | 62 | .querySelector('p') |
63 | ?.textContent.substring(0, 20) | 63 | ?.textContent.substring(0, 15) |
64 | .concat(' ...') ?? `Block ${index}`, | 64 | .concat(' ...'), |
65 | onclick: () => { | 65 | onclick: () => { |
66 | block.classList.add('focus'); | 66 | block.classList.add('focus'); |
67 | scrollToBlock(block); | 67 | scrollToBlock(block); |
@@ -72,13 +72,13 @@ export const pickBlockItem = dumbymap => | |||
72 | 72 | ||
73 | export const pickLayoutItem = dumbymap => | 73 | export const pickLayoutItem = dumbymap => |
74 | new Folder({ | 74 | new Folder({ |
75 | innerHTML: '<span>Switch Layout<span><span class="info">(x)</span>', | 75 | innerHTML: '<span>Layouts<span><span class="info">(x)</span>', |
76 | items: [ | 76 | items: [ |
77 | new Item({ | 77 | new Item({ |
78 | text: 'EDIT', | 78 | text: 'EDIT', |
79 | onclick: () => | 79 | onclick: () => |
80 | dumbymap.container | 80 | dumbymap.container |
81 | .closest('.playground') | 81 | .closest('[data-mode]') |
82 | .setAttribute('data-mode', 'editing'), | 82 | .setAttribute('data-mode', 'editing'), |
83 | }), | 83 | }), |
84 | ...dumbymap.layouts.map( | 84 | ...dumbymap.layouts.map( |
@@ -161,10 +161,17 @@ export class Suggestion { | |||
161 | } | 161 | } |
162 | } | 162 | } |
163 | 163 | ||
164 | export const modal = new Item({ | 164 | export const renderResults = (dumbymap, map) => |
165 | text: 'Render Results', | 165 | new Item({ |
166 | onclick: () => { | 166 | text: 'Render Results', |
167 | const modal = new PlainModal(); | 167 | onclick: e => { |
168 | modal.open(); | 168 | const modal = dumbymap.modal; |
169 | }, | 169 | modal.open(); |
170 | }); | 170 | modal.overlayBlur = 3; |
171 | modal.closeByEscKey = false; | ||
172 | // HACK find another way to override inline style | ||
173 | document.querySelector('.plainmodal-overlay-force').style.position = | ||
174 | 'static'; | ||
175 | console.log(map.renderer.results) | ||
176 | }, | ||
177 | }); | ||
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index d365712..b9b9fa2 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
@@ -9,6 +9,7 @@ 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 | import * as menuItem from './MenuItem'; |
12 | import { default as PlainModal } from 'plain-modal'; | ||
12 | 13 | ||
13 | const docLinkSelector = 'a[href^="#"][title^="=>"]'; | 14 | const docLinkSelector = 'a[href^="#"][title^="=>"]'; |
14 | const geoLinkSelector = 'a[href^="geo:"]'; | 15 | const geoLinkSelector = 'a[href^="geo:"]'; |
@@ -155,6 +156,9 @@ export const generateMaps = (container, { delay, mapCallback }) => { | |||
155 | container.appendChild(showcase); | 156 | container.appendChild(showcase); |
156 | showcase.classList.add('Showcase'); | 157 | showcase.classList.add('Showcase'); |
157 | const renderPromises = []; | 158 | const renderPromises = []; |
159 | const modalContent = document.createElement('div'); | ||
160 | container.appendChild(modalContent); | ||
161 | const modal = new PlainModal(modalContent); | ||
158 | 162 | ||
159 | const dumbymap = { | 163 | const dumbymap = { |
160 | layouts, | 164 | layouts, |
@@ -162,15 +166,15 @@ export const generateMaps = (container, { delay, mapCallback }) => { | |||
162 | htmlHolder, | 166 | htmlHolder, |
163 | showcase, | 167 | showcase, |
164 | blocks, | 168 | blocks, |
169 | modal, | ||
165 | utils: { | 170 | utils: { |
171 | ...utils, | ||
166 | renderedMaps: () => | 172 | renderedMaps: () => |
167 | Array.from( | 173 | Array.from( |
168 | container.querySelectorAll('.mapclay[data-render=fulfilled]'), | 174 | container.querySelectorAll('.mapclay[data-render=fulfilled]'), |
169 | ), | 175 | ), |
170 | focusNextMap: throttle(utils.focusNextMap, utils.focusDelay), | 176 | focusNextMap: throttle(utils.focusNextMap, utils.focusDelay), |
171 | switchToNextLayout: throttle(utils.switchToNextLayout, 300), | 177 | switchToNextLayout: throttle(utils.switchToNextLayout, 300), |
172 | focusNextBlock: utils.focusNextBlock, | ||
173 | removeBlockFocus: utils.removeBlockFocus, | ||
174 | }, | 178 | }, |
175 | }; | 179 | }; |
176 | Object.entries(dumbymap.utils).forEach(([util, func]) => { | 180 | Object.entries(dumbymap.utils).forEach(([util, func]) => { |
@@ -540,16 +544,25 @@ export const generateMaps = (container, { delay, mapCallback }) => { | |||
540 | 544 | ||
541 | // Menu Items | 545 | // Menu Items |
542 | container.oncontextmenu = e => { | 546 | container.oncontextmenu = e => { |
547 | e.preventDefault(); | ||
548 | |||
549 | // GeoLinks | ||
543 | const selection = document.getSelection(); | 550 | const selection = document.getSelection(); |
544 | const range = selection.getRangeAt(0); | 551 | if (selection.type === 'Range') { |
545 | if (selection) { | 552 | const range = selection.getRangeAt(0); |
546 | e.preventDefault(); | ||
547 | menu.innerHTML = ''; | 553 | menu.innerHTML = ''; |
548 | const addGeoLink = new menuItem.GeoLink({ range }); | 554 | const addGeoLink = new menuItem.GeoLink({ range }); |
549 | menu.appendChild(addGeoLink.createElement()); | 555 | menu.appendChild(addGeoLink.createElement()); |
550 | } | 556 | } |
551 | menu.style.cssText = `overflow: visible; display: block; left: ${e.clientX + 10}px; top: ${e.clientY + 5}px;`; | 557 | menu.style.cssText = `overflow: visible; display: block; left: ${e.clientX + 10}px; top: ${e.clientY + 5}px;`; |
552 | menu.appendChild(menuItem.modal); | 558 | |
559 | // Print Map Results | ||
560 | const map = e.target.closest('.mapclay'); | ||
561 | if (map) { | ||
562 | menu.appendChild(menuItem.renderResults(dumbymap, map)); | ||
563 | } | ||
564 | |||
565 | // Dumby Utils | ||
553 | menu.appendChild(menuItem.pickMapItem(dumbymap)); | 566 | menu.appendChild(menuItem.pickMapItem(dumbymap)); |
554 | menu.appendChild(menuItem.pickBlockItem(dumbymap)); | 567 | menu.appendChild(menuItem.pickBlockItem(dumbymap)); |
555 | menu.appendChild(menuItem.pickLayoutItem(dumbymap)); | 568 | menu.appendChild(menuItem.pickLayoutItem(dumbymap)); |
diff --git a/src/editor.mjs b/src/editor.mjs index 760e2e1..a7bdd77 100644 --- a/src/editor.mjs +++ b/src/editor.mjs | |||
@@ -11,7 +11,10 @@ const textArea = document.querySelector('.editor textarea'); | |||
11 | let dumbymap; | 11 | let dumbymap; |
12 | 12 | ||
13 | new MutationObserver(() => { | 13 | new MutationObserver(() => { |
14 | if (document.body.getAttribute('data-mode') === 'editing') { | 14 | if ( |
15 | document.body.getAttribute('data-mode') === 'editing' && | ||
16 | HtmlContainer.getAttribute('data-layout') !== 'normal' | ||
17 | ) { | ||
15 | HtmlContainer.setAttribute('data-layout', 'normal'); | 18 | HtmlContainer.setAttribute('data-layout', 'normal'); |
16 | } | 19 | } |
17 | }).observe(document.body, { | 20 | }).observe(document.body, { |
@@ -276,7 +279,7 @@ window.onhashchange = () => { | |||
276 | // Completion in Code Blok {{{ | 279 | // Completion in Code Blok {{{ |
277 | // Elements about suggestions {{{ | 280 | // Elements about suggestions {{{ |
278 | const menu = document.createElement('div'); | 281 | const menu = document.createElement('div'); |
279 | menu.id = 'menu'; | 282 | menu.className = 'menu'; |
280 | menu.onclick = () => (menu.style.display = 'none'); | 283 | menu.onclick = () => (menu.style.display = 'none'); |
281 | new MutationObserver(() => { | 284 | new MutationObserver(() => { |
282 | if (menu.style.display === 'none') { | 285 | if (menu.style.display === 'none') { |
@@ -648,14 +651,13 @@ document.onkeydown = e => { | |||
648 | // }}} | 651 | // }}} |
649 | // }}} | 652 | // }}} |
650 | // Layout Switch {{{ | 653 | // Layout Switch {{{ |
651 | const layoutObserver = new MutationObserver(() => { | 654 | new MutationObserver(mutaions => { |
655 | const mutation = mutaions.at(-1); | ||
652 | const layout = HtmlContainer.getAttribute('data-layout'); | 656 | const layout = HtmlContainer.getAttribute('data-layout'); |
653 | if (layout !== 'normal') { | 657 | if (layout !== 'normal' || mutation.oldValue === 'normal') { |
654 | document.body.removeAttribute('data-mode'); | 658 | document.body.setAttribute('data-mode', ''); |
655 | } | 659 | } |
656 | }); | 660 | }).observe(HtmlContainer, { |
657 | |||
658 | layoutObserver.observe(HtmlContainer, { | ||
659 | attributes: true, | 661 | attributes: true, |
660 | attributeFilter: ['data-layout'], | 662 | attributeFilter: ['data-layout'], |
661 | attributeOldValue: true, | 663 | attributeOldValue: true, |