magellan/magellan.js

152 lines
4.8 KiB
JavaScript

(function() {
const MIN_ZOOM = 6;
const MAX_ZOOM = 18;
const INITIAL_ZOOM = 14;
const TILE_URL = 'https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png';
const STATE = {
locations: new Map(),
};
let db = new Kinto({
bucket: "magellan"
});
let kintoLocations = db.collection("locations");
let syncOptions = {
remote: "https://kinto.b.delire.party/v1",
//headers: {Authorization: "Basic " + btoa('user:pass')}
};
async function sync() {
try {
await kintoLocations.sync(syncOptions);
} catch (err){
alert(err);
}
}
sync();
function addLocation(loc) {
if (!STATE.locations.has(loc.label)) {
let marker = L.marker(loc.coordinates)
.addTo(map)
.bindPopup(loc.label);
STATE.locations.set(loc.label, marker);
return true;
}
return false;
}
async function init() {
try {
let locations = await kintoLocations.list();
locations = locations.data;
console.log(locations)
locations.forEach(addLocation);
} catch (err) {
alert(`on init: ${err.toString()}`)
}
}
init();
async function addNewLocation(loc) {
if (addLocation(loc)) {
let marker = STATE.locations.get(loc.label);
marker.openPopup();
// Add it to kinto.
try {
await kintoLocations.create({
label: loc.label,
coordinates: loc.coordinates
});
} catch (err) {
alert(`Error when creating new location: ${err.toString()}`);
};
sync();
} else {
STATE.locations.get(loc.label).openPopup();
}
}
class Location {
constructor({ id, label, coordinates}) {
this.id = id || null;
this.label = label;
this.coordinates = coordinates;
}
}
async function fetchLocation(address) {
// Alternatively, search only for addresses (specialized for Lyon 7).
//const GEOCODING_URL = 'https://api-adresse.data.gouv.fr/search/?q={query}&postcode=69007';
const GEOCODING_URL = 'https://demo.addok.xyz/search/?q={query}&limit=20';
let resp = await fetch(GEOCODING_URL.replace('{query}', address));
let results = await resp.json();
results = results.features.map(feature => {
let { properties: {label: label}, geometry: { coordinates: coordinates }} = feature;
coordinates.unshift(coordinates.pop());
return new Location({label, coordinates});
});
console.log(results);
return results;
}
let map = L.map('the-map').setView([45.751591, 4.845695], INITIAL_ZOOM);
L.tileLayer(TILE_URL, {minZoom: MIN_ZOOM, maxZoom: MAX_ZOOM, attribution: 'Carte données &copy; <a href="https://osm.org/copyright/">OpenStreetMap (ODbL)</a> / fond OSM-FR (CC-by-SA), <a href="https://www.data.gouv.fr/fr/datasets/points-dinterets-openstreetmap/">POI: OpenStreetMap (ODbL)</a>, <a href="https://www.data.gouv.fr/fr/datasets/base-d-adresses-nationale-ouverte-bano/">adresses BANO (ODbL)</a>, <a href="https://github.com/addok/addok">geocodeur addok</a>'}).addTo(map);
let $ = document.querySelector.bind(document);
let $address = $('#address');
let $submit = $('#submit');
let $results = window.results = $('#results');
$('#form').onsubmit = function(event) {
event.preventDefault();
return false;
}
$submit.onclick = async function() {
let address = $address.value.trim();
$results.innerHTML = `searching for ${address}...`;
let firstResult = true;
let locations = await fetchLocation(address);
locations = locations.map(loc => {
let li = document.createElement('li');
let a = document.createElement('a');
a.href = '#';
a.onclick = function() {
L.popup()
.setLatLng(loc.coordinates)
.setContent(loc.label)
.openOn(map);
}
a.appendChild(document.createTextNode(loc.label))
li.appendChild(a);
li.appendChild(document.createTextNode(' '));
let button = document.createElement('button');
button.appendChild(document.createTextNode('Save'));
button.onclick = () => { addNewLocation(loc) };
li.appendChild(button);
if (firstResult) {
firstResult = false;
$results.innerHTML = '';
}
$results.appendChild(li);
return li;
});
}
})();