diff options
Diffstat (limited to 'src/assets/javascripts/maps.js')
| -rw-r--r-- | src/assets/javascripts/maps.js | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/assets/javascripts/maps.js b/src/assets/javascripts/maps.js new file mode 100644 index 00000000..3ab5e2b6 --- /dev/null +++ b/src/assets/javascripts/maps.js @@ -0,0 +1,212 @@ +"use strict"; + +window.browser = window.browser || window.chrome; +import utils from './utils.js' + +const targets = /^https?:\/{2}(((www|maps)\.)?(google\.).*(\/maps)|maps\.(google\.).*)/; + +let redirects = { + 'osm': { + "normal": [ + "https://openstreetmap.org" + ] + }, + 'facil': { + "normal": [ + "https://facilmap.org" + ] + } +}; + + +let + disableMaps, + mapsFrontend, + facilNormalRedirectsChecks, + facilNormalCustomRedirects; + +function init() { + browser.storage.local.get( + [ + "disableMaps", + "mapsFrontend", + "facilNormalRedirectsChecks", + "facilNormalCustomRedirects", + ], + r => { + disableMaps = r.disableMaps; + mapsFrontend = r.mapsFrontend; + facilNormalRedirectsChecks = r.facilNormalRedirectsChecks; + facilNormalCustomRedirects = r.facilNormalCustomRedirects; + } + ) +} + +init(); +browser.storage.onChanged.addListener(init) + +function redirect(url, initiator) { + const mapCentreRegex = /@(-?\d[0-9.]*),(-?\d[0-9.]*),(\d{1,2})[.z]/; + const dataLatLngRegex = /!3d(-?[0-9]{1,}.[0-9]{1,})!4d(-?[0-9]{1,}.[0-9]{1,})/; + const placeRegex = /\/place\/(.*)\//; + const travelModes = { + driving: "fossgis_osrm_car", + walking: "fossgis_osrm_foot", + bicycling: "fossgis_osrm_bike", + transit: "fossgis_osrm_car", // not implemented on OSM, default to car. + }; + const travelModesFacil = { + driving: "car", + walking: "pedestrian", + bicycling: "bicycle", + transit: "car", // not implemented on Facil, default to car. + }; + const osmLayers = { + none: "S", + transit: "T", + traffic: "S", // not implemented on OSM, default to standard. + bicycling: "C", + }; + + function addressToLatLng(address) { + const xmlhttp = new XMLHttpRequest(); + xmlhttp.open("GET", `https://nominatim.openstreetmap.org/search/${address}?format=json&limit=1`, false); + xmlhttp.send(); + if (xmlhttp.status === 200) { + const json = JSON.parse(xmlhttp.responseText)[0]; + if (json) { + console.log('json', json) + return [ + `${json.lat},${json.lon}`, + `${json.boundingbox[2]},${json.boundingbox[1]},${json.boundingbox[3]},${json.boundingbox[0]}`, + ]; + } + } + console.info("Error: Status is " + xmlhttp.status); + } + + if (disableMaps) return; + if (initiator && initiator.host === "earth.google.com") return; + if (!url.href.match(targets)) return; + + let randomInstance; + if (mapsFrontend == 'osm') randomInstance = utils.getRandomInstance(redirects.osm.normal); + if (mapsFrontend == 'facil') randomInstance = utils.getRandomInstance([...facilNormalRedirectsChecks, ...facilNormalCustomRedirects]); + + let mapCentre = "#"; + let prefs = {}; + + if (url.pathname.match(mapCentreRegex)) { // Set map centre if present + var [, lat, lon, zoom] = url.pathname.match(mapCentreRegex); + } else if (url.searchParams.has("center")) { + var [lat, lon] = url.searchParams.get("center").split(","); + var zoom = url.searchParams.get("zoom") ?? "17"; + } + + if (lat && lon && zoom) { + if (mapsFrontend == 'osm') mapCentre = `#map=${zoom}/${lat}/${lon}`; + if (mapsFrontend == 'facil') mapCentre = `#${zoom}/${lat}/${lon}`; + } + + if (url.searchParams.get("layer")) prefs.layers = osmLayers[url.searchParams.get("layer")]; + + if (url.pathname.includes("/embed")) { // Handle Google Maps Embed API + // https://www.google.com/maps/embed/v1/place?key=AIzaSyD4iE2xVSpkLLOXoyqT-RuPwURN3ddScAI&q=Eiffel+Tower,Paris+France + console.log("embed life"); + + let query = ""; + if (url.searchParams.has("q")) query = url.searchParams.get("q"); + else if (url.searchParams.has("query")) query = url.searchParams.has("query"); + + else if (url.searchParams.has("pb")) + try { query = url.searchParams.get("pb").split(/!2s(.*?)!/)[1]; } + catch (error) { console.error(error); } // Unable to find map marker in URL. + + let [coords, boundingbox] = addressToLatLng(query); + prefs.bbox = boundingbox; + prefs.marker = coords; + prefs.layer = "mapnik"; + let prefsEncoded = new URLSearchParams(prefs).toString(); + if (mapsFrontend == 'osm') { resolve(`${randomInstance}/export/embed.html?${prefsEncoded}`); return; } + + if (mapsFrontend == 'facil') { resolve(`${randomInstance}/#q=${query}`); return; } + + } else if (url.pathname.includes("/dir")) { // Handle Google Maps Directions + // https://www.google.com/maps/dir/?api=1&origin=Space+Needle+Seattle+WA&destination=Pike+Place+Market+Seattle+WA&travelmode=bicycling + + let travMod = url.searchParams.get("travelmode"); + if (url.searchParams.has("travelmode")) prefs.engine = travelModes[travMod]; + + let orgVal = url.searchParams.get("origin"); + let destVal = url.searchParams.get("destination"); + + let org; addressToLatLng(orgVal, a => org = a); + let dest; addressToLatLng(destVal, a => dest = a); + prefs.route = `${org};${dest}`; + + let prefsEncoded = new URLSearchParams(prefs).toString(); + if (mapsFrontend == 'osm') { resolve(`${randomInstance}/directions?${prefsEncoded}${mapCentre}`); return; } + if (mapsFrontend == 'facil') { resolve(`${randomInstance}/#q=${orgVal}%20to%20${destVal}%20by%20${travelModesFacil[travMod]}`); return; } + + } else if (url.pathname.includes("data=") && url.pathname.match(dataLatLngRegex)) { // Get marker from data attribute + // https://www.google.com/maps/place/41%C2%B001'58.2%22N+40%C2%B029'18.2%22E/@41.032833,40.4862063,17z/data=!3m1!4b1!4m6!3m5!1s0x0:0xf64286eaf72fc49d!7e2!8m2!3d41.0328329!4d40.4883948 + console.log("data life"); + + let [, mlat, mlon] = url.pathname.match(dataLatLngRegex); + + if (mapsFrontend == 'osm') { resolve(`${randomInstance}/search?query=${mlat}%2C${mlon}`); return; } + if (mapsFrontend == 'facil') { resolve(`${randomInstance}/#q=${mlat}%2C${mlon}`); return; } + + } else if (url.searchParams.has("ll")) { // Get marker from ll param + // https://maps.google.com/?ll=38.882147,-76.99017 + console.log("ll life"); + + const [mlat, mlon] = url.searchParams.get("ll").split(","); + + if (mapsFrontend == 'osm') { resolve(`${randomInstance}/search?query=${mlat}%2C${mlon}`); return; } + if (mapsFrontend == 'facil') { resolve(`${randomInstance}/#q=${mlat}%2C${mlon}`); return; } + } else if (url.searchParams.has("viewpoint")) { // Get marker from viewpoint param. + // https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=48.857832,2.295226&heading=-45&pitch=38&fov=80 + console.log("viewpoint life"); + + const [mlat, mlon] = url.searchParams.get("viewpoint").split(","); + + if (mapsFrontend == 'osm') { resolve(`${randomInstance}/search?query=${mlat}%2C${mlon}`); return; } + if (mapsFrontend == 'facil') { resolve(`${randomInstance}/#q=${mlat}%2C${mlon}`); return; } + } else { // Use query as search if present. + console.log("normal life"); + + let query; + if (url.searchParams.has("q")) query = url.searchParams.get("q"); + else if (url.searchParams.has("query")) query = url.searchParams.get("query"); + else if (url.pathname.match(placeRegex)) query = url.pathname.match(placeRegex)[1]; + + let prefsEncoded = new URLSearchParams(prefs).toString(); + if (query) { + if (mapsFrontend == 'osm') { resolve(`${randomInstance}/search?query="${query}${mapCentre}&${prefsEncoded}`); return; } + if (mapsFrontend == 'facil') { resolve(`${randomInstance}/${mapCentre}/Mpnk/${query}`); return; } + } + } + + let prefsEncoded = new URLSearchParams(prefs).toString(); + console.log("mapCentre", mapCentre); + console.log("prefs", prefs); + console.log("prefsEncoded", prefsEncoded); + if (mapsFrontend == 'osm') { resolve(`${randomInstance}/${mapCentre}&${prefsEncoded}`); return; } + if (mapsFrontend == 'facil') { resolve(`${randomInstance}/${mapCentre}/Mpnk`); return; } +} + +async function initDefaults() { + await browser.storage.local.set({ + disableMaps: false, + mapsFrontend: 'osm', + mapsRedirects: redirects, + facilNormalRedirectsChecks: [...redirects.facil.normal], + facilNormalCustomRedirects: [], + }) +} + +export default { + redirect, + initDefaults, +}; |
