mirror of
https://github.com/owntracks/recorder.git
synced 2026-05-05 02:36:45 +00:00
214 lines
6.4 KiB
HTML
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>
|