UNPKG

gun

Version:

A realtime, decentralized, offline-first, graph data synchronization engine.

183 lines (176 loc) 6.47 kB
<!DOCTYPE html> <html> <head> <title>Where</title> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport" /> <meta charset="utf-8"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.0.3/dist/leaflet.css"/> <script src="https://cdn.jsdelivr.net/npm/leaflet@1.0.3/dist/leaflet.js"></script> </head> <body> <div id="map"></div> <a id="share" class="hide"><div class="stick button">Share</div></a> <div id="link" class="hide"> <p>Copy and Paste this URL to your friends to share your location:</p> <center> <p id="follow">Location sharing not available!</p> </center> <p><b>Note</b>: Location may not sync when your device's screen is off or the tab is out of focus. You'd need to install this as an app for that to work.</p> <center> <a id="close"><div class="button">Close</div></a> </center> </div> <textarea style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 5em;" id="debug"></textarea> <style> html, body, #map { margin: 0; padding: 0; width: 100%; height: 100%; font-family: Arial; font-size: 16pt; z-index: 1; } .stick { position: absolute; bottom: 1em; right: 1em; } .button { display: inline-block; padding: 1em; opacity: .5; background: blue; color: white; z-index: 7; transition: .25s all; } .button:hover { opacity: 1; } .hide { display: none; } #link { position: absolute; padding: 1em; top: 2em; left: 2em; right: 2em; bottom: 2em; background: white; overflow: scroll; z-index: 9; } #follow { background: #EEE; padding: .5em; word-wrap: break-word; } </style> <script src="/jquery.js"></script> <script src="/gun.js"></script> <script> function Where(opt, cb){ // a small wrapper around Leaflet for map tracking. var where = {}; where.opt = opt || {}; where.opt.zoom = where.opt.zoom || {}; where.opt.err = where.opt.err || function(){}; where.map = L.map('map', { zoom: where.opt.zoom.level }); where.opt.tile = where.opt.tile || L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { maxZoom: where.opt.zoom.max, minZoom: where.opt.zoom.min, detectRetina: true, attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' }); where.map.addLayer(where.opt.tile); where.opt.zoom.ing = where.opt.zoom.ing || function(){ where.opt.zoom.level = where.map.getZoom(); } where.map.on('zoomstart', where.opt.zoom.ing, where.opt.err); where.map.on('zoomend', where.opt.zoom.ing, where.opt.err); where.map.on('zoomlevelschange', where.opt.zoom.ing, where.opt.err); where.update = function(latlng){ if((+new Date) - where.update.last < 400){ clearTimeout(where.update.to); where.update.to = setTimeout(function(){ where.update(latlng); }); return; } where.map.setView(latlng, where.opt.zoom.level, {animate: true}); where.marker = where.marker || L.marker().setLatLng(latlng).addTo(where.map); where.marker.setLatLng(latlng).update(); where.update.last = (+new Date); } if(where.opt.track){ where.map.on('locationfound', function(pos){ where.update(pos.latlng); where.opt.track(pos); }); where.map.locate({ setView: true, zoom: where.opt.zoom.level, watch: where.opt.continuous || true, timeout: where.opt.timeout || 10000, maximumAge: where.opt.maximumAge || 0, enableHighAccuracy: where.opt.enableHighAccuracy || false }); } return where; } </script> <script> ;(function(){ // the actual GPS tracking app! var gun = Gun(location.origin + '/gun'); var gps = {}; gps.opt = { continuous: true, // get location just once uses `getCurrentPosition()` while continuously uses `watchPosition()` enableHighAccuracy: true, // HighAccuracy uses more resources, https://developer.mozilla.org/en-US/docs/Web/API/PositionOptions timeout: 5000, // have this long to get data before erring. maximumAge: 0, // set to 0 to actually track. zoom: {max: 18, level: 13, min: 12} } function start(){ gps.follow = (window.location.hash || '').slice(1); if(gps.follow){ gps.where = gps.where || Where(gps.opt); gps.ref = gun.get('gps/' + gps.follow); gps.ref.on(function(latlng){ //$('#debug').value = 'track ' + JSON.stringify(latlng); gps.where.update(latlng); }); $('#share').addClass("hide"); } else { document.cookie = 'gps=' + (gps.track = (document.cookie.match(/gps\=(.*?)(\&|$|\;)/i)||[])[1] || Gun.text.random(5)); // trick with cookies! gps.ref = gun.get('gps/' + gps.track); gps.opt.track = function(pos){ pos = pos.latlng; if(gps.follow || Gun.time.is() - gps.when < 1000 || gps.last && gps.last.lat == pos.lat && gps.last.lng == pos.lng){ return; // throttle! } gps.when = Gun.time.is(); gps.ref.put(gps.last = pos); //$('#debug').value = JSON.stringify(gps.last); } gps.where = gps.where || Where(gps.opt); $('#follow').text(("where.gunDB.io/" || (location.origin + location.pathname)) + '#' + gps.track); $('#share').removeClass("hide"); $('#share').on('click', function(){ $('#link').toggleClass("hide"); }); $('#close').on('click', function(){ $('#link').toggleClass("hide"); }); } } start(); window.onhashchange = start; }()); </script> </body> </html>