view assets/trackme.html @ 74:ebbecfa4231f

Refine behavior of livemap UI
author Lewin Bormann <lbo@spheniscida.de>
date Sat, 05 Dec 2020 11:43:38 +0100
parents 4249238c40c8
children afefa4d60653
line wrap: on
line source

<html>
    <head>
        <title>GeoHub :: Track me!</title>

        <style>
        table, th, td {
          border: 1px solid black;
        }
        </style>

    </head>

    <body>
    <!-- My name: assets/trackme.html -->

    <p style='color: red;'>Warning: This website sends your current location to its server (<span id="uiHost">unknown</span>)</p>

    <input type="button" value="Start logging!" onclick="startLogging()" id='uiStartButton' />

    <table>
        <tr>
            <th>Property</th>
            <th>Value</th>
        </tr>
        <tr>
            <td>Client</td>
            <td id="tblClient"><input type="text" id="inputClient" value="" /></td>
        </tr>
        <tr>
            <td>Secret</td>
            <td id="tblSecret"><input type="text" id="inputSecret" value="" /></td>
        </tr>
        <tr>
            <td>LiveMap</td>
            <td id="tblLiveMap"><a href="" id="hrefLiveMap">LiveMap</a></td>
        </tr>
        <tr>
            <td>Status</td>
            <td id="tblStatus">?</td>
        </tr>
        <tr>
            <td>Last time</td>
            <td id="tblTime">?</td>
        </tr>
        <tr>
            <td>Latitude</td>
            <td id="tblLat">?</td>
        </tr>
        <tr>
            <td>Longitude</td>
            <td id="tblLong">?</td>
        </tr>
    </table>

    <script>

    var urlParams = new URLSearchParams(window.location.search);
    var thisUrl = new URL(window.location);
    // Tell the user where their data is going.
    document.getElementById('uiHost').textContent = thisUrl.hostname;

    // Figure out the client: Try to get it from the user entry field, if it is empty
    // try the URL parameter, in that case fill in the field.
    function getClient() {
        var inputClient = document.getElementById('inputClient');
        var userClient = inputClient.value;
        var urlClient = urlParams.get('client');

        if (userClient.length == 0) {
            inputClient.value = urlClient;
            return urlClient;
        }
        return userClient;
    }
    // Figure out the secret.
    function getSecret() {
        var inputSecret = document.getElementById('inputSecret');
        var userSecret = inputSecret.value;
        var urlSecret = urlParams.get('secret');

        if (userSecret.length == 0) {
            inputSecret.value = urlSecret;
            return urlSecret;
        }
        return userSecret;
    }
    // Update URL from client/secret.
    function updateURL(client, secret) {
        var url = window.location.toString();
        
        if (url.search('\\?') < 0) {
            url += '?';
        }

        if (url.search('secret=') > 0) {
            url = url.replace(/secret=[a-zA-Z0-9]*/, `secret=${secret}`);
        } else {
            url += `&secret=${secret}`;
        }

        if (url.search('client=') > 0) {
            url = url.replace(/client=[a-zA-Z0-9]*/, `client=${client}`);
        } else {
            url += `&client=${client}`;
        }

        window.history.pushState({}, "", url);
    }
    // Update the link to the livemap if the user has changed client/secret.
    function updateLiveMap() {
        var secret = getSecret();
        var client = getClient();
        var url = `livemap.html?secret=${secret}&client=${client}`;
        document.getElementById('hrefLiveMap').href = url;
    }
    // Update the table to the newly aquired point.
    function updateUITable(pos) {
        var coord = pos.coords;
        var lastTime = new Date(pos.timestamp);

        document.getElementById('tblTime').textContent = lastTime.toTimeString();
        document.getElementById('tblLat').textContent = coord.latitude.toString();
        document.getElementById('tblLong').textContent = coord.longitude.toString();
        document.getElementById('tblStatus').textContent = 'Acquired';
    }
    // Show that the current point has been logged.
    function updateUITableSetLogged() {
        document.getElementById('tblStatus').textContent = 'Logged';
    }

    // Called once the `POST .../log` request has finished.
    function xhrLogCallback(xhr, readyStateChange) {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            if (xhr.status == 200) {
                console.log('Location update successful.');
                updateUITableSetLogged();
            } else if (xhr.status == 400) {
                console.log('Location update unsuccessful! Status:', xhr.responseText);
            }
        }
    }

    // Returns closure f(GeolocationCoordinates) logging to this Geohub.
    // The returned function accepts a GeoLocation position and sends an XHR request
    // to this GeoHub instance.
    function getLoggingHandler() {
        var lastLat = 0;
        var lastLong = 0;

        return function(glp) {
            var glc = glp.coords;
            var client = getClient();
            if (client == null) {
                console.log('Not logging: Client is null!');
                return;
            }
            if (glc.latitude == lastLat && glc.longitude == lastLong) {
                console.log('Not logging: Position has not changed');
                return;
            }

            // Show new data in UI.
            updateUITable(glp);

            lastLat = glc.latitude;
            lastLong = glc.longitude;

            const speedorempty = glc.speed ? `s=${glc.speed}` : '';
            const elevationorempty = glc.altitude ? `ele=${glc.altitude}` : '';
            const accorempty = glc.accuracy ? `accuracy=${glc.accuracy}` : '';
            var querystring = `&lat=${glc.latitude}&longitude=${glc.longitude}&${speedorempty}&${elevationorempty}&${accorempty}`;

            var trackUrl = thisUrl.origin + thisUrl.pathname;
            // Maybe just use relative path?
            trackUrl = trackUrl.replace('assets/trackme.html', `${client}/log?secret=${getSecret()}`);
            var url = trackUrl+querystring;

            var xhr = new XMLHttpRequest();
            xhr.responseType = 'json';
            xhr.open('POST', url, true);
            xhr.onreadystatechange = function(result) { xhrLogCallback(xhr, result); };
            xhr.send();
        };
    }

    // Main execution starts here.

    // loggingHandler is a closure produced above.
    const loggingHandler = getLoggingHandler();

    // Handles new events from the GeoLocation API.
    function locationUpdate(pos) {
        console.log('new location:', pos);
        loggingHandler(pos);
    }

    function startLogging() {
        var geo = navigator.geolocation;
        var watchId = geo.watchPosition(locationUpdate);

        var startStopButton = document.getElementById('uiStartButton');
        var inputClient = document.getElementById('inputClient');
        var inputSecret = document.getElementById('inputSecret');

        // Transition UI into active mode.
        startStopButton.value = 'Stop logging!';
        inputClient.disabled = true;
        inputSecret.disabled = true;
        // On Stop Logging clicked
        startStopButton.onclick = function() {
            geo.clearWatch(watchId);
            startStopButton.value = 'Start logging!';
            startStopButton.onclick = startLogging;
            inputClient.disabled = false;
            inputSecret.disabled = false;
        };
        updateLiveMap();
        updateURL();
    }

    // Pre-fill client/secret.
    getClient();
    getSecret();
    updateLiveMap();

    </script>

    </body>
</html>