diff options
-rw-r--r-- | src/dumbymap.mjs | 110 | ||||
-rw-r--r-- | src/editor.mjs | 21 |
2 files changed, 66 insertions, 65 deletions
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 7408529..a563c88 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
@@ -21,70 +21,69 @@ const mapCache = {} | |||
21 | 21 | ||
22 | // FUNCTION: Get DocLinks from special anchor element {{{ | 22 | // FUNCTION: Get DocLinks from special anchor element {{{ |
23 | /** | 23 | /** |
24 | * CreateDocLinks. | 24 | * CreateDocLink. |
25 | * | 25 | * |
26 | * @param {HTMLElement} Elements contains anchor elements for doclinks | 26 | * @param {HTMLElement} Elements contains anchor elements for doclinks |
27 | * @returns {Array} List of doclinks just created | ||
28 | */ | 27 | */ |
29 | export const createDocLinks = (container) => Array.from(container.querySelectorAll(docLinkSelector)) | 28 | export const createDocLink = (link) => { |
30 | .map(link => { | 29 | link.classList.add('with-leader-line', 'doclink') |
31 | link.classList.add('with-leader-line', 'doclink') | 30 | link.lines = [] |
32 | link.lines = [] | ||
33 | 31 | ||
34 | link.onmouseover = () => { | 32 | link.onmouseover = () => { |
35 | const label = decodeURIComponent(link.href.split('#')[1]) | 33 | const label = decodeURIComponent(link.href.split('#')[1]) |
36 | const selector = link.title.split('=>')[1] ?? '#' + label | 34 | const selector = link.title.split('=>')[1] ?? '#' + label |
37 | const target = document.querySelector(selector) | 35 | const target = document.querySelector(selector) |
38 | if (!target?.checkVisibility()) return | 36 | if (!target?.checkVisibility()) return |
39 | |||
40 | const line = new LeaderLine({ | ||
41 | start: link, | ||
42 | end: target, | ||
43 | middleLabel: LeaderLine.pathLabel({ | ||
44 | text: label, | ||
45 | fontWeight: 'bold', | ||
46 | }), | ||
47 | hide: true, | ||
48 | path: "magnet" | ||
49 | }) | ||
50 | link.lines.push(line) | ||
51 | line.show('draw', { duration: 300, }) | ||
52 | } | ||
53 | link.onmouseout = () => { | ||
54 | link.lines.forEach(line => line.remove()) | ||
55 | link.lines.length = 0 | ||
56 | } | ||
57 | 37 | ||
58 | return link | 38 | const line = new LeaderLine({ |
59 | }) | 39 | start: link, |
40 | end: target, | ||
41 | middleLabel: LeaderLine.pathLabel({ | ||
42 | text: label, | ||
43 | fontWeight: 'bold', | ||
44 | }), | ||
45 | hide: true, | ||
46 | path: "magnet" | ||
47 | }) | ||
48 | link.lines.push(line) | ||
49 | line.show('draw', { duration: 300, }) | ||
50 | } | ||
51 | link.onmouseout = () => { | ||
52 | link.lines.forEach(line => line.remove()) | ||
53 | link.lines.length = 0 | ||
54 | } | ||
55 | } | ||
60 | // }}} | 56 | // }}} |
61 | // FUNCTION: Get GeoLinks from special anchor element {{{ | 57 | // FUNCTION: Get GeoLinks from special anchor element {{{ |
62 | /** | 58 | /** |
63 | * Create geolinks, which points to map by geo schema and id | 59 | * Create geolinks, which points to map by geo schema and id |
64 | * | 60 | * |
65 | * @param {HTMLElement} Elements contains anchor elements for doclinks | 61 | * @param {HTMLElement} Elements contains anchor elements for doclinks |
66 | * @returns {Array} List of doclinks just created | 62 | * @returns {Boolean} ture is link is created, false if coordinates are invalid |
67 | */ | 63 | */ |
68 | export const createGeoLinks = (container, callback) => Array.from(container.querySelectorAll(geoLinkSelector)) | 64 | export const createGeoLink = (link, callback = null) => { |
69 | .filter(link => { | 65 | const url = new URL(link.href) |
70 | const url = new URL(link.href) | 66 | const xyInParams = url.searchParams.get('xy') |
71 | const xy = url?.href?.match(/^geo:([0-9.,]+)/)?.at(1)?.split(',')?.reverse()?.map(Number) | 67 | const xy = xyInParams |
72 | 68 | ? xyInParams.split(',')?.map(Number) | |
73 | if (!xy || isNaN(xy[0]) || isNaN(xy[1])) return false | 69 | : url?.href?.match(/^geo:([0-9.,]+)/)?.at(1)?.split(',')?.reverse()?.map(Number) |
74 | 70 | ||
75 | // Geo information in link | 71 | if (!xy || isNaN(xy[0]) || isNaN(xy[1])) return false |
76 | link.url = url | 72 | |
77 | link.xy = xy | 73 | // Geo information in link |
78 | link.classList.add('with-leader-line', 'geolink') | 74 | link.url = url |
79 | link.targets = link.url.searchParams.get('id')?.split(',') ?? null | 75 | link.xy = xy |
80 | 76 | link.classList.add('with-leader-line', 'geolink') | |
81 | // LeaderLine | 77 | link.targets = link.url.searchParams.get('id')?.split(',') ?? null |
82 | link.lines = [] | 78 | |
83 | callback(link) | 79 | // LeaderLine |
84 | 80 | link.lines = [] | |
85 | return true | 81 | callback?.call(this, link) |
86 | }) | 82 | |
83 | return true | ||
84 | } | ||
87 | // }}} | 85 | // }}} |
86 | |||
88 | export const markdown2HTML = (container, mdContent) => { | 87 | export const markdown2HTML = (container, mdContent) => { |
89 | // Render: Markdown -> HTML {{{ | 88 | // Render: Markdown -> HTML {{{ |
90 | Array.from(container.children).map(e => e.remove()) | 89 | Array.from(container.children).map(e => e.remove()) |
@@ -171,9 +170,12 @@ export const generateMaps = (container, callback) => { | |||
171 | 170 | ||
172 | // LeaderLine {{{ | 171 | // LeaderLine {{{ |
173 | 172 | ||
173 | Array.from(container.querySelectorAll(docLinkSelector)) | ||
174 | .filter(createDocLink) | ||
175 | |||
174 | // Get anchors with "geo:" scheme | 176 | // Get anchors with "geo:" scheme |
175 | htmlHolder.anchors = [] | 177 | htmlHolder.anchors = [] |
176 | const geoLinks = createGeoLinks(htmlHolder, (link) => { | 178 | const geoLinkCallback = (link) => { |
177 | link.onmouseover = () => addLeaderLines(link) | 179 | link.onmouseover = () => addLeaderLines(link) |
178 | link.onmouseout = () => removeLeaderLines(link) | 180 | link.onmouseout = () => removeLeaderLines(link) |
179 | link.onclick = (event) => { | 181 | link.onclick = (event) => { |
@@ -184,7 +186,9 @@ export const generateMaps = (container, callback) => { | |||
184 | // TODO Just hide leader line and show it again | 186 | // TODO Just hide leader line and show it again |
185 | removeLeaderLines(link) | 187 | removeLeaderLines(link) |
186 | } | 188 | } |
187 | }) | 189 | } |
190 | const geoLinks = Array.from(container.querySelectorAll(geoLinkSelector)) | ||
191 | .filter(l => createGeoLink(l, geoLinkCallback)) | ||
188 | 192 | ||
189 | const isAnchorPointedBy = (link) => (anchor) => { | 193 | const isAnchorPointedBy = (link) => (anchor) => { |
190 | const mapContainer = anchor.closest('.map-container') | 194 | const mapContainer = anchor.closest('.map-container') |
diff --git a/src/editor.mjs b/src/editor.mjs index 539a770..ab5db42 100644 --- a/src/editor.mjs +++ b/src/editor.mjs | |||
@@ -1,6 +1,6 @@ | |||
1 | /*global EasyMDE*/ | 1 | /*global EasyMDE*/ |
2 | /*eslint no-undef: "error"*/ | 2 | /*eslint no-undef: "error"*/ |
3 | import { markdown2HTML, generateMaps, createDocLinks } from './dumbymap' | 3 | import { markdown2HTML, generateMaps } from './dumbymap' |
4 | import { defaultAliases, parseConfigsFromYaml } from 'mapclay' | 4 | import { defaultAliases, parseConfigsFromYaml } from 'mapclay' |
5 | import { Suggestion } from './MenuItem' | 5 | import { Suggestion } from './MenuItem' |
6 | 6 | ||
@@ -88,11 +88,17 @@ if (contentFromHash) { | |||
88 | editor.cleanup() | 88 | editor.cleanup() |
89 | editor.value(contentFromHash) | 89 | editor.value(contentFromHash) |
90 | } | 90 | } |
91 | |||
92 | // }}} | 91 | // }}} |
93 | // Set up logic about editor content {{{ | 92 | // Set up logic about editor content {{{ |
93 | const afterMapRendered = (_) => { | ||
94 | // mapHolder.oncontextmenu = (event) => { | ||
95 | // event.preventDefault() | ||
96 | // const lonLat = mapHolder.renderer.unproject([event.x, event.y]) | ||
97 | // // TODO... | ||
98 | // } | ||
99 | } | ||
94 | markdown2HTML(HtmlContainer, editor.value()) | 100 | markdown2HTML(HtmlContainer, editor.value()) |
95 | createDocLinks(HtmlContainer) | 101 | dumbymap = generateMaps(HtmlContainer, afterMapRendered) |
96 | 102 | ||
97 | // Quick hack to style lines inside code block | 103 | // Quick hack to style lines inside code block |
98 | const addClassToCodeLines = () => { | 104 | const addClassToCodeLines = () => { |
@@ -159,17 +165,8 @@ const debounceForMap = (() => { | |||
159 | } | 165 | } |
160 | })() | 166 | })() |
161 | 167 | ||
162 | const afterMapRendered = (_) => { | ||
163 | // mapHolder.oncontextmenu = (event) => { | ||
164 | // event.preventDefault() | ||
165 | // const lonLat = mapHolder.renderer.unproject([event.x, event.y]) | ||
166 | // // TODO... | ||
167 | // } | ||
168 | } | ||
169 | |||
170 | const updateDumbyMap = () => { | 168 | const updateDumbyMap = () => { |
171 | markdown2HTML(HtmlContainer, editor.value()) | 169 | markdown2HTML(HtmlContainer, editor.value()) |
172 | createDocLinks(HtmlContainer) | ||
173 | // TODO Test if generate maps intantly is OK with map cache | 170 | // TODO Test if generate maps intantly is OK with map cache |
174 | // debounceForMap(HtmlContainer, afterMapRendered) | 171 | // debounceForMap(HtmlContainer, afterMapRendered) |
175 | dumbymap = generateMaps(HtmlContainer, afterMapRendered) | 172 | dumbymap = generateMaps(HtmlContainer, afterMapRendered) |