NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Geocache Height // @namespace http://inge.org.uk/userscripts // @description Works out the height of a geocache in metres above sea level and adds it alongside the coordinates on the geocache listing. // @include https://www.geocaching.com/geocache/GC* // @author JRI // @oujs:author JRI // @copyright 2010-20, James Inge (http://geo.inge.org.uk/) // @license MIT; http://www.opensource.org/licenses/mit-license.php // @version 1.2.0 // @grant GM_xmlhttpRequest // @grant GM.xmlHttpRequest // @grant unsafeWindow // @connect api.geonames.org // @icon https://geo.inge.org.uk/userscripts/height48.png // @icon64 https://geo.inge.org.uk/userscripts/height64.png // @updateURL https://geo.inge.org.uk/userscripts/Geocache_Height.meta.js // @downloadURL https://openuserjs.org/install/JRI/Geocache_Height.user.js // ==/UserScript== // // Works out the height of a geocache. // // v0.0.1 First attempt! // v0.0.2 Updated for changes to geocaching.com layout. // v0.0.3 Updated for more changes to geocaching.com layout. // v1.0.4 Updated for changes to geocaching.com cache page URLs. // v1.1.0 Update and re-write for changes to geocaching.com. // v1.1.1 Add @connect metadata to request permission to connect to Google, avoiding security pop-ups in Tampermonkey. // v1.1.2 Added compatibility with Greasemonkey 4 // v1.1.3 Switched from Google Elevation API to Geonames // v1.1.4 Fixed for geocaching.com page change // v1.2.0 Fixed to wait for web page to load all variables before running. // /*jslint browser, devel */ /*global window, GM, GM_xmlhttpRequest */ (function () { "use strict"; function formatHeight(height) { var heightElement = document.createElement("span"); heightElement.id = "jriCacheHeight"; heightElement.innerHTML = (height >= 0) ? " +" : " "; heightElement.innerHTML += Math.round(height) + "m"; return heightElement; } const scriptId = "Geocache Height v1.2.0 "; const target = document.getElementById("uxLatLon"); function getCoords() { /* Looks for coordinates in global content variables lat and lng, and returns them as a LatLng object * Returns undefined on failure */ return (typeof unsafeWindow.lat === "number" && typeof unsafeWindow.lng === "number" ? {lat: unsafeWindow.lat, lng: unsafeWindow.lng} : undefined ); } function isPMOnly() { const form = document.getElementById("aspnetForm"); return (form && (/cache_pmo\.aspx/).test(form.action)); } function parseHeight(jsonString) { /* Extracts height information from JSON response. Returns a number * in metres on success, null for no data or undefined on failure. */ try { const json = JSON.parse(jsonString); return ( typeof json.astergdem === "number" ? ( json.astergdem > -9999 ? json.astergdem : (console.debug(`${scriptId}received no height data for this location.`), null)) : (console.error(`${scriptId}didn't get the data format it expected from Geonames`), null) ); } catch (e) { console.error(`${e}: ${scriptId}didn't get valid JSON data from Geonames`); } } async function load(id, delayedFn, requiredVars = []) { //don't run on frames or iframes if (window.top !== window.self) { return; } if (isPMOnly()) { console.warn(id + "run on Premium Member cache - coordinates not available"); return; } if (target === null) { console.error(id + "couldn't find where to display height on the cache page"); return; } console.log(`${id}initializing: waiting for variables: ${requiredVars.join()}`); while(!requiredVars.every((v) => unsafeWindow.hasOwnProperty(v))) { await new Promise(resolve => setTimeout(resolve, 500)); } console.log(`${id}running`); delayedFn(id); } function main(id) { const coords = getCoords(); if (!coords) { console.error(scriptId + "couldn't work out coordinates for cache"); return; } const xhr = (typeof GM_xmlhttpRequest === "function") ? GM_xmlhttpRequest : ((typeof GM === "object" && typeof GM.xmlHttpRequest === "function") ? GM.xmlHttpRequest : undefined); if (xhr) { xhr({ method: "GET", url: `http://api.geonames.org/astergdemJSON?lat=${coords.lat}&lng=${coords.lng}&username=gme_h`, onload: function (responseDetails) { var height = parseHeight(responseDetails.responseText); if (height != null) { target.parentElement.appendChild(formatHeight(height)); } } }); } else { console.error(scriptId + "needs a userscript manager that supports cross-site XHR"); } } load(scriptId, main, ["lat", "lng"]); }());