diff options
| author | Hsieh Chin Fan <pham@topo.tw> | 2024-10-08 16:47:29 +0800 |
|---|---|---|
| committer | Hsieh Chin Fan <pham@topo.tw> | 2024-10-08 17:31:36 +0800 |
| commit | af4831dd8ad2df0b25a64ae3529a20b921e26c7c (patch) | |
| tree | dd7688074b123f8ebe7943bf1885b54ec35f1855 /src | |
| parent | 3685a63346f776044c74df767a88137a19b2643c (diff) | |
refactor: move addAnchorByEvent into dumbyUtils
Diffstat (limited to 'src')
| -rw-r--r-- | src/dumbyUtils.mjs | 40 | ||||
| -rw-r--r-- | src/editor.mjs | 53 |
2 files changed, 58 insertions, 35 deletions
diff --git a/src/dumbyUtils.mjs b/src/dumbyUtils.mjs index 95bb3dd..be45139 100644 --- a/src/dumbyUtils.mjs +++ b/src/dumbyUtils.mjs | |||
| @@ -6,7 +6,7 @@ import { insideWindow, insideParent } from './utils' | |||
| 6 | * | 6 | * |
| 7 | * @param {Boolean} reverse -- focus previous map | 7 | * @param {Boolean} reverse -- focus previous map |
| 8 | */ | 8 | */ |
| 9 | export function focusNextMap (reverse = false) { | 9 | export function focusNextMap(reverse = false) { |
| 10 | const renderedList = this.utils.renderedMaps() | 10 | const renderedList = this.utils.renderedMaps() |
| 11 | const index = renderedList.findIndex(e => e.classList.contains('focus')) | 11 | const index = renderedList.findIndex(e => e.classList.contains('focus')) |
| 12 | const nextIndex = (index + (reverse ? -1 : 1)) % renderedList.length | 12 | const nextIndex = (index + (reverse ? -1 : 1)) % renderedList.length |
| @@ -21,7 +21,7 @@ export function focusNextMap (reverse = false) { | |||
| 21 | * | 21 | * |
| 22 | * @param {Boolean} reverse -- focus previous block | 22 | * @param {Boolean} reverse -- focus previous block |
| 23 | */ | 23 | */ |
| 24 | export function focusNextBlock (reverse = false) { | 24 | export function focusNextBlock(reverse = false) { |
| 25 | const blocks = this.blocks.filter(b => | 25 | const blocks = this.blocks.filter(b => |
| 26 | b.checkVisibility({ | 26 | b.checkVisibility({ |
| 27 | contentVisibilityAuto: true, | 27 | contentVisibilityAuto: true, |
| @@ -56,7 +56,7 @@ export const scrollToBlock = block => { | |||
| 56 | /** | 56 | /** |
| 57 | * focusDelay. Delay of throttle, value changes by cases | 57 | * focusDelay. Delay of throttle, value changes by cases |
| 58 | */ | 58 | */ |
| 59 | export function focusDelay () { | 59 | export function focusDelay() { |
| 60 | return window.window.getComputedStyle(this.showcase).display === 'none' ? 50 : 300 | 60 | return window.window.getComputedStyle(this.showcase).display === 'none' ? 50 : 300 |
| 61 | } | 61 | } |
| 62 | 62 | ||
| @@ -65,7 +65,7 @@ export function focusDelay () { | |||
| 65 | * | 65 | * |
| 66 | * @param {Boolean} reverse -- Switch to previous one | 66 | * @param {Boolean} reverse -- Switch to previous one |
| 67 | */ | 67 | */ |
| 68 | export function switchToNextLayout (reverse = false) { | 68 | export function switchToNextLayout(reverse = false) { |
| 69 | const layouts = this.layouts | 69 | const layouts = this.layouts |
| 70 | const currentLayoutName = this.container.getAttribute('data-layout') | 70 | const currentLayoutName = this.container.getAttribute('data-layout') |
| 71 | const currentIndex = layouts.map(l => l.name).indexOf(currentLayoutName) | 71 | const currentIndex = layouts.map(l => l.name).indexOf(currentLayoutName) |
| @@ -81,7 +81,7 @@ export function switchToNextLayout (reverse = false) { | |||
| 81 | /** | 81 | /** |
| 82 | * removeBlockFocus. | 82 | * removeBlockFocus. |
| 83 | */ | 83 | */ |
| 84 | export function removeBlockFocus () { | 84 | export function removeBlockFocus() { |
| 85 | this.blocks.forEach(b => b.classList.remove('focus')) | 85 | this.blocks.forEach(b => b.classList.remove('focus')) |
| 86 | } | 86 | } |
| 87 | 87 | ||
| @@ -243,3 +243,33 @@ const isAnchorVisible = anchor => { | |||
| 243 | const mapContainer = anchor.closest('.mapclay') | 243 | const mapContainer = anchor.closest('.mapclay') |
| 244 | return insideWindow(anchor) && insideParent(anchor, mapContainer) | 244 | return insideWindow(anchor) && insideParent(anchor, mapContainer) |
| 245 | } | 245 | } |
| 246 | |||
| 247 | export const addAnchorByEvent = ({ | ||
| 248 | event, | ||
| 249 | map, | ||
| 250 | validateAnchorName = () => true | ||
| 251 | }) => { | ||
| 252 | const rect = map.getBoundingClientRect() | ||
| 253 | const [x, y] = map.renderer | ||
| 254 | .unproject([event.x - rect.left, event.y - rect.top]) | ||
| 255 | .map(coord => Number(coord.toFixed(7))) | ||
| 256 | |||
| 257 | let prompt | ||
| 258 | let anchorName | ||
| 259 | |||
| 260 | do { | ||
| 261 | prompt = prompt ? 'Anchor name exists' : 'Name this anchor' | ||
| 262 | anchorName = window.prompt(prompt, `${x}, ${y}`) | ||
| 263 | } | ||
| 264 | while (anchorName !== null && !validateAnchorName(anchorName)) | ||
| 265 | if (anchorName === null) return | ||
| 266 | |||
| 267 | const link = `geo:${y},${x}?xy=${x},${y}&id=${map.id} "${anchorName}"` | ||
| 268 | map.renderer.addMarker({ | ||
| 269 | xy: [x, y], | ||
| 270 | title: `${map.id}@${x}, ${y}`, | ||
| 271 | type: 'circle', | ||
| 272 | }) | ||
| 273 | |||
| 274 | return { ref: anchorName, link } | ||
| 275 | } | ||
diff --git a/src/editor.mjs b/src/editor.mjs index 499d42b..1c444eb 100644 --- a/src/editor.mjs +++ b/src/editor.mjs | |||
| @@ -4,6 +4,7 @@ import { markdown2HTML, generateMaps } from './dumbymap' | |||
| 4 | import { defaultAliases, parseConfigsFromYaml } from 'mapclay' | 4 | import { defaultAliases, parseConfigsFromYaml } from 'mapclay' |
| 5 | import * as menuItem from './MenuItem' | 5 | import * as menuItem from './MenuItem' |
| 6 | import { shiftByWindow } from './utils.mjs' | 6 | import { shiftByWindow } from './utils.mjs' |
| 7 | import { addAnchorByEvent } from './dumbyUtils.mjs' | ||
| 7 | 8 | ||
| 8 | // Set up Containers {{{ | 9 | // Set up Containers {{{ |
| 9 | 10 | ||
| @@ -47,7 +48,7 @@ const toggleEditing = () => { | |||
| 47 | // Content values for editor | 48 | // Content values for editor |
| 48 | 49 | ||
| 49 | const defaultContent = | 50 | const defaultContent = |
| 50 | `<br> | 51 | `<br> |
| 51 | 52 | ||
| 52 | > <big>Hello My Friend! This is DumbyMap!</big> | 53 | > <big>Hello My Friend! This is DumbyMap!</big> |
| 53 | 54 | ||
| @@ -441,30 +442,21 @@ const menuForEditor = (event, menu) => { | |||
| 441 | if (map) { | 442 | if (map) { |
| 442 | const item = new menuItem.Item({ | 443 | const item = new menuItem.Item({ |
| 443 | text: 'Add Anchor', | 444 | text: 'Add Anchor', |
| 444 | onclick: () => { | 445 | onclick: (event) => { |
| 445 | const rect = map.getBoundingClientRect() | 446 | const validateAnchorName = anchorName => |
| 446 | const [x, y] = map.renderer | 447 | !refLinks.find(obj => obj.ref === anchorName) |
| 447 | .unproject([event.x - rect.left, event.y - rect.top]) | 448 | const { ref, link } = addAnchorByEvent({ |
| 448 | .map(coord => coord.toFixed(7)) | 449 | event, |
| 449 | 450 | map, | |
| 450 | let prompt | 451 | validateAnchorName |
| 451 | let anchorName | 452 | }) |
| 452 | |||
| 453 | do { | ||
| 454 | prompt = prompt ? 'Anchor name exists' : 'Name this anchor' | ||
| 455 | anchorName = window.prompt(prompt, `${x}, ${y}`) | ||
| 456 | } | ||
| 457 | while (anchorName !== null && refLinks.find(({ ref }) => ref === anchorName)) | ||
| 458 | if (anchorName === null) return | ||
| 459 | 453 | ||
| 460 | const link = `geo:${y},${x}?xy=${x},${y}&id=${map.id} "${anchorName}"` | 454 | let refLinkString = `\n[${ref}]: ${link}` |
| 461 | const lastLineIsRefLink = cm.getLine(cm.lastLine()).match(refLinkPattern) | 455 | const lastLineIsRefLink = cm.getLine(cm.lastLine()).match(refLinkPattern) |
| 462 | cm.replaceRange( | 456 | if (lastLineIsRefLink) refLinkString = '\n' + refLinkString |
| 463 | `${lastLineIsRefLink ? '' : '\n'}\n[${anchorName}]: ${link}`, | 457 | cm.replaceRange(refLinkString, { line: Infinity }) |
| 464 | { line: Infinity } | 458 | |
| 465 | ) | 459 | refLinks.push({ ref, link }) |
| 466 | refLinks = getRefLinks() | ||
| 467 | map.renderer.addMarker({ xy: [Number(x), Number(y)], title: `${map.id}@${x},${y}`, type: 'circle' }) | ||
| 468 | } | 460 | } |
| 469 | }) | 461 | }) |
| 470 | menu.insertBefore(item, menu.firstChild) | 462 | menu.insertBefore(item, menu.firstChild) |
| @@ -802,13 +794,13 @@ const getSuggestions = anchor => { | |||
| 802 | return rendererSuggestions.length === 0 | 794 | return rendererSuggestions.length === 0 |
| 803 | ? [] | 795 | ? [] |
| 804 | : [ | 796 | : [ |
| 805 | ...rendererSuggestions, | 797 | ...rendererSuggestions, |
| 806 | new menuItem.Item({ | 798 | new menuItem.Item({ |
| 807 | innerHTML: '<a href="https://github.com/outdoorsafetylab/mapclay#renderer" class="external" style="display: block;">More...</a>', | 799 | innerHTML: '<a href="https://github.com/outdoorsafetylab/mapclay#renderer" class="external" style="display: block;">More...</a>', |
| 808 | className: ['suggestion'], | 800 | className: ['suggestion'], |
| 809 | onclick: () => window.open('https://github.com/outdoorsafetylab/mapclay#renderer', '_blank') | 801 | onclick: () => window.open('https://github.com/outdoorsafetylab/mapclay#renderer', '_blank') |
| 810 | }) | 802 | }) |
| 811 | ] | 803 | ] |
| 812 | } | 804 | } |
| 813 | return [] | 805 | return [] |
| 814 | } | 806 | } |
| @@ -1076,4 +1068,5 @@ document.addEventListener('selectionchange', () => { | |||
| 1076 | cm.setSelection({ ...anchor, ch: anchor.ch - content.length }, anchor) | 1068 | cm.setSelection({ ...anchor, ch: anchor.ch - content.length }, anchor) |
| 1077 | } | 1069 | } |
| 1078 | }) | 1070 | }) |
| 1071 | |||
| 1079 | // vim: sw=2 ts=2 foldmethod=marker foldmarker={{{,}}} | 1072 | // vim: sw=2 ts=2 foldmethod=marker foldmarker={{{,}}} |