diff options
author | Hsieh Chin Fan <pham@topo.tw> | 2024-10-31 11:27:20 +0800 |
---|---|---|
committer | Hsieh Chin Fan <pham@topo.tw> | 2024-10-31 12:01:51 +0800 |
commit | 7ee1ad61627f9a2af04f080cfa95a30f3c8e4525 (patch) | |
tree | cff733c310788f802fe00fbcdd8f4054a3ef4075 | |
parent | 2bcad7ff9a42ad39a4b2f24c4af9b6a5578ba1fd (diff) |
feat: add menu-item for Geocoding
* Use nominatim for API calls
* Create multiple GeoLinks for each results in response
* Also add menu-item DELETE to remove duplicated GeoLinks from one
Geocoding
-rw-r--r-- | src/MenuItem.mjs | 23 | ||||
-rw-r--r-- | src/dumbyUtils.mjs | 2 | ||||
-rw-r--r-- | src/dumbymap.mjs | 33 | ||||
-rw-r--r-- | src/utils.mjs | 2 |
4 files changed, 57 insertions, 3 deletions
diff --git a/src/MenuItem.mjs b/src/MenuItem.mjs index 103f43e..13dbc44 100644 --- a/src/MenuItem.mjs +++ b/src/MenuItem.mjs | |||
@@ -586,3 +586,26 @@ export const editMap = (map, dumbymap) => { | |||
586 | ], | 586 | ], |
587 | }) | 587 | }) |
588 | } | 588 | } |
589 | |||
590 | export const addLinkbyNominatim = (range) => { | ||
591 | return Item({ | ||
592 | text: 'Add Link by Geocoding', | ||
593 | onclick: () => { | ||
594 | const place = range.toString() | ||
595 | fetch(`https://nominatim.openstreetmap.org/search?q=${place.toString()}&format=json`) | ||
596 | .then(res => res.json()) | ||
597 | .then(places => { | ||
598 | if (places.length === 0) return | ||
599 | console.log('nomiatim', places) | ||
600 | range.deleteContents() | ||
601 | places.forEach(p => { | ||
602 | const a = document.createElement('a') | ||
603 | a.className = 'not-geolink from-geocoding' | ||
604 | a.href = `geo:${p.lat},${p.lon}?name=${p.name}&osm=${p.osm_type}/${p.osm_id}` | ||
605 | a.textContent = place | ||
606 | range.insertNode(a) | ||
607 | }) | ||
608 | }) | ||
609 | }, | ||
610 | }) | ||
611 | } | ||
diff --git a/src/dumbyUtils.mjs b/src/dumbyUtils.mjs index 975833b..8110e82 100644 --- a/src/dumbyUtils.mjs +++ b/src/dumbyUtils.mjs | |||
@@ -144,7 +144,7 @@ export const addGeoSchemeByText = async (node) => { | |||
144 | 144 | ||
145 | // Return anchor element with Geo Scheme | 145 | // Return anchor element with Geo Scheme |
146 | const a = document.createElement('a') | 146 | const a = document.createElement('a') |
147 | a.className = 'not-geolink from-text' | 147 | a.className = 'not-geolink from-geocoding' |
148 | a.href = `geo:0,0?xy=${x},${y}` | 148 | a.href = `geo:0,0?xy=${x},${y}` |
149 | a.textContent = match.at(0) | 149 | a.textContent = match.at(0) |
150 | return a | 150 | return a |
diff --git a/src/dumbymap.mjs b/src/dumbymap.mjs index 4562612..9bc1da7 100644 --- a/src/dumbymap.mjs +++ b/src/dumbymap.mjs | |||
@@ -540,7 +540,8 @@ export const generateMaps = (container, { | |||
540 | const map = e.target.closest('.mapclay') | 540 | const map = e.target.closest('.mapclay') |
541 | const block = e.target.closest('.dumby-block') | 541 | const block = e.target.closest('.dumby-block') |
542 | const linkWithLine = e.target.closest('.with-leader-line') | 542 | const linkWithLine = e.target.closest('.with-leader-line') |
543 | if (!block && !map && !linkWithLine) return | 543 | const rangeSelected = document.getSelection().type === 'Range' |
544 | if (!block && !map && !linkWithLine && !rangeSelected) return | ||
544 | e.preventDefault() | 545 | e.preventDefault() |
545 | 546 | ||
546 | /** Add HTMLElement for menu */ | 547 | /** Add HTMLElement for menu */ |
@@ -560,6 +561,12 @@ export const generateMaps = (container, { | |||
560 | }).observe(menu, { childList: true }) | 561 | }).observe(menu, { childList: true }) |
561 | menu.timer = setTimeout(() => menu.remove(), 100) | 562 | menu.timer = setTimeout(() => menu.remove(), 100) |
562 | 563 | ||
564 | /** Menu Item for Geocoding */ | ||
565 | if (rangeSelected) { | ||
566 | // TODO check click is inside selection | ||
567 | const range = document.getSelection().getRangeAt(0) | ||
568 | menu.appendChild(menuItem.addLinkbyNominatim(range)) | ||
569 | } | ||
563 | /** Menu Item for editing map */ | 570 | /** Menu Item for editing map */ |
564 | const mapEditor = e.target.closest('.edit-map') | 571 | const mapEditor = e.target.closest('.edit-map') |
565 | if (mapEditor) { | 572 | if (mapEditor) { |
@@ -584,6 +591,30 @@ export const generateMaps = (container, { | |||
584 | ) | 591 | ) |
585 | }, | 592 | }, |
586 | })) | 593 | })) |
594 | } else if (geoLink.classList.contains('from-geocoding')) { | ||
595 | menu.appendChild(menuItem.Item({ | ||
596 | innerHTML: '<strong style="color: red;">DELETE</strong>', | ||
597 | onclick: () => { | ||
598 | getMarkersFromMaps(geoLink) | ||
599 | .forEach(m => m.remove()) | ||
600 | |||
601 | const sibling = [ | ||
602 | geoLink.previousElementSibling, | ||
603 | geoLink.nextElementSibling, | ||
604 | ] | ||
605 | .find(a => | ||
606 | a.classList.contains('from-geocoding') && a.textContent === geoLink.textContent, | ||
607 | ) | ||
608 | |||
609 | if (sibling) { | ||
610 | geoLink.remove() | ||
611 | } else { | ||
612 | geoLink.replaceWith( | ||
613 | document.createTextNode(geoLink.textContent), | ||
614 | ) | ||
615 | } | ||
616 | }, | ||
617 | })) | ||
587 | } | 618 | } |
588 | menu.appendChild(menuItem.setGeoLinkType(geoLink)) | 619 | menu.appendChild(menuItem.setGeoLinkType(geoLink)) |
589 | } | 620 | } |
diff --git a/src/utils.mjs b/src/utils.mjs index d2c5d8f..c0da23a 100644 --- a/src/utils.mjs +++ b/src/utils.mjs | |||
@@ -173,7 +173,7 @@ export const replaceTextNodes = ( | |||
173 | const nodeIterator = document.createNodeIterator( | 173 | const nodeIterator = document.createNodeIterator( |
174 | rootNode, | 174 | rootNode, |
175 | window.NodeFilter.SHOW_TEXT, | 175 | window.NodeFilter.SHOW_TEXT, |
176 | node => node.textContent.match(pattern) && !node.parentElement.closest('pre,code,a') | 176 | node => node.textContent.match(pattern) && node.parentElement && !node.parentElement.closest('pre,code,a') |
177 | ? window.NodeFilter.FILTER_ACCEPT | 177 | ? window.NodeFilter.FILTER_ACCEPT |
178 | : window.NodeFilter.FILTER_REJECT, | 178 | : window.NodeFilter.FILTER_REJECT, |
179 | ) | 179 | ) |