From 7ee1ad61627f9a2af04f080cfa95a30f3c8e4525 Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Thu, 31 Oct 2024 11:27:20 +0800 Subject: 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 --- src/MenuItem.mjs | 23 +++++++++++++++++++++++ src/dumbyUtils.mjs | 2 +- src/dumbymap.mjs | 33 ++++++++++++++++++++++++++++++++- src/utils.mjs | 2 +- 4 files changed, 57 insertions(+), 3 deletions(-) (limited to 'src') 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) => { ], }) } + +export const addLinkbyNominatim = (range) => { + return Item({ + text: 'Add Link by Geocoding', + onclick: () => { + const place = range.toString() + fetch(`https://nominatim.openstreetmap.org/search?q=${place.toString()}&format=json`) + .then(res => res.json()) + .then(places => { + if (places.length === 0) return + console.log('nomiatim', places) + range.deleteContents() + places.forEach(p => { + const a = document.createElement('a') + a.className = 'not-geolink from-geocoding' + a.href = `geo:${p.lat},${p.lon}?name=${p.name}&osm=${p.osm_type}/${p.osm_id}` + a.textContent = place + range.insertNode(a) + }) + }) + }, + }) +} 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) => { // Return anchor element with Geo Scheme const a = document.createElement('a') - a.className = 'not-geolink from-text' + a.className = 'not-geolink from-geocoding' a.href = `geo:0,0?xy=${x},${y}` a.textContent = match.at(0) 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, { const map = e.target.closest('.mapclay') const block = e.target.closest('.dumby-block') const linkWithLine = e.target.closest('.with-leader-line') - if (!block && !map && !linkWithLine) return + const rangeSelected = document.getSelection().type === 'Range' + if (!block && !map && !linkWithLine && !rangeSelected) return e.preventDefault() /** Add HTMLElement for menu */ @@ -560,6 +561,12 @@ export const generateMaps = (container, { }).observe(menu, { childList: true }) menu.timer = setTimeout(() => menu.remove(), 100) + /** Menu Item for Geocoding */ + if (rangeSelected) { + // TODO check click is inside selection + const range = document.getSelection().getRangeAt(0) + menu.appendChild(menuItem.addLinkbyNominatim(range)) + } /** Menu Item for editing map */ const mapEditor = e.target.closest('.edit-map') if (mapEditor) { @@ -584,6 +591,30 @@ export const generateMaps = (container, { ) }, })) + } else if (geoLink.classList.contains('from-geocoding')) { + menu.appendChild(menuItem.Item({ + innerHTML: 'DELETE', + onclick: () => { + getMarkersFromMaps(geoLink) + .forEach(m => m.remove()) + + const sibling = [ + geoLink.previousElementSibling, + geoLink.nextElementSibling, + ] + .find(a => + a.classList.contains('from-geocoding') && a.textContent === geoLink.textContent, + ) + + if (sibling) { + geoLink.remove() + } else { + geoLink.replaceWith( + document.createTextNode(geoLink.textContent), + ) + } + }, + })) } menu.appendChild(menuItem.setGeoLinkType(geoLink)) } 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 = ( const nodeIterator = document.createNodeIterator( rootNode, window.NodeFilter.SHOW_TEXT, - node => node.textContent.match(pattern) && !node.parentElement.closest('pre,code,a') + node => node.textContent.match(pattern) && node.parentElement && !node.parentElement.closest('pre,code,a') ? window.NodeFilter.FILTER_ACCEPT : window.NodeFilter.FILTER_REJECT, ) -- cgit v1.2.3-70-g09d2