Files
recorder/docroot/views/vmap.html
2022-04-17 19:41:44 +02:00

214 lines
6.4 KiB
HTML

<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>OwnTracks View</title>
<meta name="viewport" content="width=device-width, height=device-height, user-scalable=no, initial-scale=1.0">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="icon" sizes="192x192" href="../static/recorder.png">
<link rel="apple-touch-icon" href="../static/recorder.png">
<link rel="stylesheet" href="../utils/map.css">
<script src="../static/apikey.js"></script>
<script type="module">
import { debug } from "../utils/debug.js";
import { getCosmeticName, getCosmeticLocation } from "../utils/misc.js";
import { generatePopupHTML } from "../utils/map.js";
import { fetchApiData } from "../utils/network.js";
import { openSingularMarker, fitBounds, markerStyle, strokeStyle, clog } from "../utils/map_google.js";
debug("API Key:", apiKey);
let map;
let do_fit = false;
let devices = [];
const markers = {};
const refresh = 60000;
const livemarkers = true;
function setmarkers() {
for (const device of devices) {
map_marker(device);
}
}
function reload() {
importData();
setmarkers();
setTimeout(reload, refresh);
}
async function importData() {
const data = await fetchApiData({url: '@@@LASTPOS@@@'});
devices = data.data;
}
/**
* The TrackControl adds a control to the map that loads the GeoJSON track.
* This constructor takes the track DIV as an argument.
*/
function TrackControl(controlDiv, map) {
// Set CSS for the control border
const controlUI = document.createElement('div');
controlUI.style.backgroundColor = '#fff';
controlUI.style.border = '2px solid #fff';
controlUI.style.borderRadius = '3px';
controlUI.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
controlUI.style.cursor = 'pointer';
controlUI.style.marginBottom = '22px';
controlUI.style.textAlign = 'center';
controlUI.title = 'Click to load the track onto the map';
controlDiv.appendChild(controlUI);
// Set CSS for the control interior
const controlText = document.createElement('div');
controlText.style.color = 'rgb(25,25,25)';
controlText.style.fontFamily = 'Roboto,Arial,sans-serif';
controlText.style.fontSize = '16px';
controlText.style.lineHeight = '38px';
controlText.style.paddingLeft = '5px';
controlText.style.paddingRight = '5px';
controlText.innerHTML = 'Load track';
controlUI.appendChild(controlText);
// Setup the click event listeners: simply set the map to
// Chicago
google.maps.event.addDomListener(controlUI, 'click', function() {
map.data.loadGeoJson('@@@GEO@@@');
// Set the stroke style for each polygon
map.data.setStyle(strokeStyle);
});
}
async function initialize() {
let lat;
let lon;
await importData();
if (!Array.isArray(devices)) {
debug("Imported data is malformed:", devices);
document.write("Imported data is malformed");
return;
}
if (devices.length < 1) {
document.write("NO data");
}
try {
lat = devices[0].lat;
lon = devices[0].lon;
} catch (err) {
document.write("NO data");
return;
}
// FIXME: we can use "center" from VIEW to nail the map
const center = new google.maps.LatLng(lat, lon);
const mapOptions = {
center,
zoom: devices[0].zoom || 9,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scrollwheel: false,
disableDefaultUI: false,
panControl: false,
scaleControl: false,
streetViewControl: true,
overviewMapControl: true,
};
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
// Create the DIV to hold the control and call the TrackControl()
// constructor passing in this DIV.
const trackControlDiv = document.createElement('div');
const trackControl = new TrackControl(trackControlDiv, map);
trackControlDiv.index = 1;
map.controls[google.maps.ControlPosition.BOTTOM_LEFT].push(trackControlDiv);
setmarkers();
setTimeout(reload, refresh);
}
/*
* `loc' is a location object obtained from the Recorder, with some extra bits
* included from the view's configuration
*/
function map_marker(loc){
debug("Format marker:", loc);
const id = loc.tid;
const title = `${ getCosmeticName(loc) } ${ getCosmeticLocation(loc) }`;
const htmldesc = generatePopupHTML(loc);
const LatLng = new google.maps.LatLng(loc.lat, loc.lon);
if (markers.hasOwnProperty(id)) {
clog("UPD", id, loc);
const m = markers[id];
m.setPosition(LatLng);
m.setTitle(title);
/* Grab the InfoWindow of this marker and change content */
m.infowindow.setContent(htmldesc);
if (livemarkers) {
openSingularMarker(map, markers, m);
}
} else {
clog("NEW", id, loc);
const m = new google.maps.Marker({
position: LatLng,
map,
title,
icon: markerStyle,
});
/* Create a new InfoWindow for this marker, and add listener */
m.infowindow = new google.maps.InfoWindow({
content: htmldesc,
});
google.maps.event.addListener(m, "click", function() {
this['infowindow'].open(map, this);
});
if (livemarkers) {
openSingularMarker(map, markers, m);
}
markers[id] = m;
}
if (do_fit) {
fitBounds(map, markers);
}
}
// Load maps API:
const script = document.createElement('script');
script.src = `https://maps.googleapis.com/maps/api/js?v=3&key=${ apiKey }`;
script.addEventListener("load", () => {initialize();});
document.querySelector("head").appendChild(script);
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>