const loading = document.getElementById('loading');
var map = L.map('map');
let marker = null;
let userMarker = null;
const popup = document.getElementById('popup')
let viewAll = false;
//var är vi?
map.locate({
setView: true,
maxZoom: 12,
enableHighAccuracy: true,
});
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
/**
* hittat vart avnänderan befinner sig, sätt ut markör för var vi är, kalla fornlämnings findern och hämtar adressinformation
* @param {*} e.latlng - användarens latitude och longitude
*/
map.on('locationfound', function (e) {
const latlng = e.latlng;
const userIcon = L.icon({
iconUrl: '/here.png',
iconSize: [38, 38]
})
userMarker = L.marker(latlng, { icon: userIcon })
.addTo(map)
findFL(latlng.lat, latlng.lng);
findUserLocation(latlng.lat, latlng.lng);
});
/**
* userLocation knappen, gröna knappen längst upp till höger. Ladda, tar bort sök/klickmarkörer, dölj popup, Hitta användarens position och centrera där
*
*/
document.getElementById('userLocation').addEventListener('click', () => {
loading.style.display = 'flex';
//rensa marker från sökt plats
if (marker) {
map.removeLayer(marker);
marker = null;
}
popup.classList.remove('visible');
map.locate({
setView: true,
maxZoom: 19,
enableHighAccuracy: true,
});
});
/**
* ViewAll knappen, ögon knappen längst upp till höger. Toggle visa fornlämningar eller inte, uppdatera ikonen, laddar om fornlämningar, rensar markörer och döljer popup
*/
document.getElementById('viewAll').addEventListener('click', () => {
if (viewAll) {
loading.style.display = 'flex';
viewAll = false
document.getElementById('viewAllWebp').srcset = "./eyeopen.webp";
document.getElementById('viewAllImg').src = "./eyeopen.png";
if (!marker) {
findFL(userMarker._latlng.lat, userMarker._latlng.lng)
} else {
findFL(marker._latlng.lat, marker._latlng.lng);
}
} else {
viewAll = true
document.getElementById('viewAllWebp').srcset = "./eyeclosed.webp";
document.getElementById('viewAllImg').src = "./eyeclosed.png";
if (window.flMarkers) {
window.flMarkers.forEach(m => map.removeLayer(m));
}
window.flMarkers = [];
}
popup.classList.remove('visible');
});
/**
* tar vad användaren sökt på, kör nominatim med flNameet för att hitta platsen - använder nomanitams angivna latitude och longitude för att ställa kartan på den platsen, visar popup med infon och startar sökning efter fornlämningar.
* @param {*} location - användarens sökning
*/
async function findLocation(location) {
try {
const response = await fetch(`https://nominatim.openstreetmap.org/search?q=${location}&format=json`);
const data = await response.json();
if (data) {
const latitude = parseFloat(data[0].lat);
const longitude = parseFloat(data[0].lon);
const markIcon = L.icon({
iconUrl: '/here2.png',
iconSize: [38, 38]
})
map.setView([latitude, longitude], 12);
marker = L.marker([latitude, longitude], { icon: markIcon })
.addTo(map)
//.bindPopup(`<b>${data[0].display_name}</b>`)
//.openPopup();
console.log(data[0])
console.log(marker)
popup.classList.add('visible');;
popup.innerHTML = `
<button id="closePopup" onclick="closePopup()"><b>✖</b></button>
<h1>${data[0].name}</h1>
<ul>
<li>${data[0].display_name} - ${data[0].addresstype}</li>
</ul>
`
findFL(latitude, longitude)
} else {
alert('Hittade inte platsen, var mer specifik!');
}
} catch (error) {
console.error('Error fetching location:', error);
loading.style.display = 'none';
}
}
/**
* enter för sökfältet, tar input värdet och kallar findlocation med den angivna platsen
*/
document.getElementById('inputLocation').addEventListener('keypress', function (e) {
if (e.key === 'Enter') {
e.preventDefault();
const location = this.value;
findLocation(location);
}
});
/**
* Placera en markör där man klickar på kartan. Laddar, tar bort markörer, skapar ny markör, söker fornlämningar nära den platsen
*
*/
map.on("click", function (e) {
loading.style.display = 'flex';
if (marker) {
map.removeLayer(marker);
marker = null;
}
const markIcon = L.icon({
iconUrl: '/here2.png',
iconSize: [38, 38]
})
marker = L.marker([e.latlng.lat, e.latlng.lng], { icon: markIcon })
.addTo(map)
findFL(e.latlng.lat, e.latlng.lng);
findUserLocation(e.latlng.lat, e.latlng.lng);
});
/**
* Hämtar information för angivna platsen, och visar den i popup
* @param {*} lat - latitude
* @param {*} lng - longitude
*/
async function findUserLocation(lat, lng) {
try {
const response = await fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${lat}&lon=${lng}`);
const data = await response.json();
popup.classList.add('visible');;
popup.innerHTML = `
<button id="closePopup" onclick="closePopup()"><b>✖</b></button>
<h1>${data.name}</h1>
<ul>
<li>${data.display_name} - ${data.addresstype}</li>
</ul>
`
} catch (error) {
console.error('Error fetching location:', error);
loading.style.display = 'none';
}
}
/**
* Hämtar fornlämningar i ett område runt positionen, tar ut koordinater, namn, beskrivning och länk, skapar markörer baserat på vad det är.
* @param {*} lat -latitude
* @param {*} lng -longitude
*/
function findFL(lat, lng) {
//definiera området runt (boundingbox)
const north = lat + 0.025;
const west = lng - 0.05;
const south = lat - 0.025;
const east = lng + 0.05;
const boundingbox = `"${west} ${south} ${east} ${north}"`;
const boundingboxEncoded = encodeURIComponent(`/WGS84 ${boundingbox}`);
fetch(`https://kulturarvsdata.se/ksamsok/api?method=search&hitsPerPage=10000&query=boundingBox=${boundingboxEncoded} AND text=fornlämning`, {
headers: { 'Accept': 'application/json' }
})
.then(resp => resp.json())
.then(data => {
console.log(data)
if (window.flMarkers) {
window.flMarkers.forEach(m => map.removeLayer(m));
}
window.flMarkers = [];
let records = data.result.records || [];
//https://www.w3.org/TR/json-ld11/
//https://www.youtube.com/watch?v=0YgJLXgZCj4
records.forEach((rec, i) => {
let graph = rec.record["@graph"] || [];
// leta efter koordinater och om det är synligt ovan jord
let coordsValue;
for (let node of graph) {
if (node["ksam:coordinates"]) {
coordsValue = node["ksam:coordinates"];
}
if (node["ksam:desc"]) {
let descValue = node["ksam:desc"];
// Se till att det är strings alltid så att includes fungerar
let descText = descValue;
if (descValue != null && typeof descValue === "object") {
descText = descValue["@value"];
}
}
}
if (!coordsValue) {
return;
} // hoppa över fornlämningen om det saknas coordinater
// ta strängen
let xml = coordsValue["@value"];
// plocka ut alla nummer-par med regex (lon,lat)
let coords = [];
let regex = /([\d.]+),([\d.]+)/g;
let match;
while (match = regex.exec(xml)) {
let lon = parseFloat(match[1]);
let lat = parseFloat(match[2]);
coords.push([lat, lon]);
}
//https://stackoverflow.com/questions/23636870/javascript-extract-coordinates-from-a-string
//https://stackoverflow.com/questions/5004913/parse-out-all-long-lat-from-a-string
//https://stackoverflow.com/questions/52595325/javascript-split-coordinates-from-a-string
// medelpunkt
let sumLat = 0, sumLon = 0;
coords.forEach(c => {
sumLat += c[0];
sumLon += c[1];
});
let center = [sumLat / coords.length, sumLon / coords.length];
// namnet på fornlämningen
let flName = ""
for (let node of graph) {
if (node["ksam:name"]) {
flName = node["ksam:name"]["@value"]
break;
}
}
//console.log(flName)
//beskrivning av fornlämningen
let flDesc = "";
for (let node of graph) {
if (node["ksam:desc"]) {
let tempDesc = node["ksam:desc"]["@value"] || node["ksam:desc"] || "";
flDesc += "<li>" + tempDesc + "</li>"
}
}
let flUrl = ""
for (let node of graph) {
if (node["ksam:url"]) {
flUrl = node["ksam:url"]
break;
}
}
// fallback om ingen bra beskrivning hittades
if (flDesc === "<li></li>" || flDesc === "<li>Synlig ovan mark</li>") {
flDesc = "Platsen är ej undersökt eller saknar beskrivning.";
}
//console.log(flDesc)
let icon = "?"
if (flDesc != "Platsen är ej undersökt eller saknar beskrivning.") {
if (flName === "Stensättning" || flName === "Hägnad" || flName === "Röjningsröse" || flName === "Röse") {
icon = "🪨"
}
else if (flName === "Gravfält" || flName === "Grav" || flName === "Grav markerad av sten/block") {
icon = "💀"
}
else if (flName === "Hög") {
icon = "⛰️"
}
else if (flName === "Boplats" || flName === "Lägenhetsbebyggelse" || flName === "Bytomt/gårdstomt" || flName === "Grav- och boplatsområde" || flName === "Boplatsområde" || flName === "Hammare/smedja") {
icon = "🛖"
}
else if (flName === "Fossil åker" || flName === "Fossilåker") {
icon = "🦴"
}
else if (flName === "Gränsmärke") {
icon = "🔺"
}
else if (flName === "Färdväg") {
icon = "🛣️"
}
else if (flName === "Hällristning" || flName === "Runristning") {
icon = "🎨"
}
else if (flName === "Fartygs-/båtlämning" || flName === "") {
icon = "🛥️"
}
else if (flName === "Kyrka" || flName === "Kyrka/kapell") {
icon = "⛪"
}
else {
icon = "❗"
}
}
// gör flMarker
let flMarker = L.marker(center, {
icon: L.divIcon({
html: icon,
className: 'flmarker',
iconSize: [26, 26]
})
}).addTo(map);
flMarker.on('click', function () {
popup.classList.add('visible');
popup.innerHTML = `
<button id="closePopup" onclick="closePopup()"><b>✖</b></button>
<h1>${flName}</h1>
<ul>${flDesc}</ul>
<a href="${flUrl}" target="_blank">länk</a>
<p id="coordinater">${center[0]}, ${center[1]}</p>
`;
});
window.flMarkers = window.flMarkers || [];
window.flMarkers.push(flMarker);
loading.style.display = 'none';
});
})
.catch(error => console.log(error));
loading.style.display = 'none';
}