const LINKS = [ { label: 'Google Maps', url: 'https://www.google.com/maps/search/?api=1&query={lat},{lon}', }, { label: 'Apple Maps', url: 'https://maps.apple.com/?q={lat},{lon}&t=m', }, { label: 'Default app', url: 'geo:{lat},{lon}', }, { label: 'OpenStreetMap', url: 'https://www.openstreetmap.org/?mlat={lat}&mlon={lon}&zoom=15&layers=M', }, ]; const content = document.getElementById('content'); route(); window.addEventListener('hashchange', route); function route() { const latLon = parseLatLon(location.hash.slice(1)); content.innerHTML = ''; if (!latLon) { document.title = 'Share a location'; content.append(createEl('h1', {}, [document.title])); const input = createEl('input'); const button = createEl('button', {}, ['Share']); const inputGroup = createEl('div', { class: 'input-group' }, [input, button]); const errorDiv = createEl('div', { class: 'error' }); content.append(createEl('label', {}, ['Latitude, longitude', inputGroup])); content.append(errorDiv); function share() { if (!input.value.trim()) { return; } try { let [lat, lon] = parseLatLon(input.value); // TODO: use navigator.share if supported window.location = `#${lat},${lon}`; } catch (error) { errorDiv.textContent = error; } } input.addEventListener('keydown', (e) => { if (e.key == 'Enter') { share(); } }); button.addEventListener('click', share); // TODO: provide a button to share the current position via navigator.geolocation.getCurrentPosition if supported } else { document.title = 'Open location'; content.append(createEl('p', {}, ['Open in'])); const linkList = createEl('ul'); const [lat, lon] = latLon; for (const linkSpec of LINKS) { const url = linkSpec.url.replace('{lat}', lat).replace('{lon}', lon); const link = createEl('a', { href: url }, [linkSpec.label]); linkList.append(createEl('li', {}, [link])); } content.append(linkList); } } function parseLatLon(text) { if (text == '') { return null; } let [lat, lon] = text.split(','); lat = parseFloat(lat); lon = parseFloat(lon); if (Number.isNaN(lat) || Number.isNaN(lon)) { throw Error('failed to parse latitude or longitude'); } if (lat < -180 || lat > 180 || lon < -90 || lon > 90) { throw Error('latitude or longitude are out of range'); } return [lat, lon]; } function createEl(tag, attrs = {}, content = []) { const el = document.createElement(tag); for (const [name, value] of Object.entries(attrs)) { el.setAttribute(name, value); } for (const child of content) { el.append(child); } return el; }