MediaWiki Diskussion:GeoHack.js

Letzter Kommentar: vor 3 Jahren von Wurgl in Abschnitt Koordinaten von Sternen

OSM map Bearbeiten

/* Embed an OSM map on div id="osmEmbed" exists */
var OSM_class_R = /\bOSM:([\d.+-]+)_([\d.+-]+)_([\d.+-]+)_(\w+)/;
function embedOpenStreetMap() {
    clearInterval(osmtimer);
    var osmTarget = document.getElementById('osmEmbed');
    if(osmTarget && OSM_class_R.exec(osmTarget.className)){
        var lat=1.0*RegExp.$1, lon=1.0*RegExp.$2, zoom=RegExp.$3;
        var span = 360.0/(512.0*Math.pow(2,zoom))*720/2;  //WTF?
        iframe = document.createElement('iframe');
        iframe.frameBorder = 0; // IE 6
        iframe.scrolling = 'no';
        iframe.src = "http://www.openstreetmap.org/export/embed.html?layer="+RegExp.$4+"&bbox=" + 
            (lon-span*Math.cos(lat*.0175))+','+(lat-span/2)+','+(lon+span*Math.cos(lat*.0175))+','+(lat+span/2)+
            "&marker="+lat+','+lon;
        iframe.height = osmTarget.clientHeight+'px';
        iframe.width = osmTarget.clientWidth+'px';
        iframe.style.position = "absolute";
        osmTarget.appendChild(iframe);
    }
}
osmtimer = setInterval("if(document.getElementById('osmEmbed'))embedOpenStreetMap()", 200)
setTimeout('clearInterval(osmtimer)', 5000)

Adding the above code will enable a single OSM map to be embedded into the German GeoHack page. Use <div id="osmEmbed" class="OSM:{latdegdec}_{londegdec}_{osmzoom}_mapnik" style="position:relative; width:720px; height:360px;"></div> on Template:GeoTemplate. Dispenser 06:44, 17. Jan. 2010 (CET)Beantworten

Skript umleiten um Traffic zu sparen Bearbeiten

Könnte ein Admin das Skript http://www.openstreetmap.org/export/embed.html bitte umbiegen auf: http://toolserver.org/~kolossos/openlayers/embed.html

Hintergründe finden sich in der OSM-Mailingliste[1] und liegt darin, dass auch Kacheln außerhalb des Blickbereiches geladen werden. Das nun optimierte Skript lädt statt 42 tiles erstmal nur 6, also statt 1.2 Megabyte nur ein siebentel. Erst nach dem ersten Schieben wird der sogenannte Buffer auf 2 hochgesetzt. Danke. --Kolossos 17:44, 7. Aug. 2010 (CEST)Beantworten

Codeverbesserung Bearbeiten

Hier folgt eine Überarbeitung des JavaScript-Codes:

/* Embed an OSM map on div id="osmEmbed" exists
 * This script is loaded by https://geohack.toolforge.org/geohack.php, see also [[Vorlage:GeoTemplate]]
 */
( function () {
	'use strict';

	function embedOpenStreetMap() {
		var matches;
		var OSM_class_R = /\bOSM:([\d.+-]+)_([\d.+-]+)_([\d.+-]+)_(\w+)/;
		var osmTarget = document.getElementById( 'osmEmbed' );
		if ( osmTarget && ( matches = OSM_class_R.exec( osmTarget.className ) ) ) {
			var lat = parseFloat( matches[ 1 ] );
			var lon = parseFloat( matches[ 2 ] );
			var zoom = parseFloat( matches[ 3 ] );
			var layer = matches[ 4 ];
			var span = 360 / ( 512 * Math.pow( 2, zoom ) ) * 360;  //WTF?
			var lonSpan = span * Math.cos( lat / 180 * Math.PI );
			var bbox = [
				lon - lonSpan,
				lat - span / 2,
				lon + lonSpan,
				lat + span / 2
			];
			var iframe = document.createElement( 'iframe' );
			iframe.frameBorder = 0; // IE 6
			iframe.scrolling = 'no';
			iframe.src = 'https://wiwosm.toolforge.org/osm-on-ol/embed-labs.html' +
				'?layer=' + layer +
				'&bbox=' + bbox.join( ',' ) +
				'&marker=' + lat + ',' + lon;
			iframe.height = osmTarget.clientHeight;
			iframe.width = osmTarget.clientWidth;
			iframe.style.position = 'relative';
			osmTarget.appendChild( iframe );
		}
	}

	if ( document.readyState === 'loading' ) {
		document.addEventListener( 'DOMContentLoaded', embedOpenStreetMap );
	} else {
		embedOpenStreetMap();
	}
}() );

Es beinhaltet folgende Änderungen:

Bitte den Code übernehmen. --Fomafix (Diskussion) 16:54, 13. Feb. 2021 (CET)Beantworten

Fehlerbericht:
  1. Die Variable iframe wurde nicht deklariert und verseucht derzeit den globalen Namensraum.
  2. Vom Funktionsnamen embedOpenStreetMap ist nicht ganz klar ob das global erreichbar sein muss oder nur lokal, intern wäre.
    • Wenn es global sein soll, dann muss window. vorangestellt werden, da zukünftig mit Kapselung gerechnet werden muss.
    • Wenn es nicht global erreichbar sein muss, dann ist diese gesamte Prozedur ordnungsgemäß zu kapseln.
Upstream wäre entsprechend zu benachrichtigen.
VG --PerfektesChaos 17:34, 13. Feb. 2021 (CET)Beantworten
Richtig. Ich habe nur die größten Schnitzer korrigiert. Im obigen Code habe ich nun die Punkte aus dem Fehlerbericht korrigiert. --Fomafix (Diskussion) 17:52, 13. Feb. 2021 (CET)Beantworten
Fein; meine obigen Beanstandungen beseitigt.
Upstream wäre das entsprechend beizubiegen.
Der Floh in meinem Ohr warnt noch davor, dass zweimal vorkommendes *.0175 gefahrengeneigt wäre, leicht zu Irrtümern führen könne, und empfiehlt sicherheitshalber noch eine Null vor den Punkt zu setzen.
Im jetzigen Zustand kann es auch noch mit dem Qualitätssiegel "use strict"; geadelt werden.
VG --PerfektesChaos 18:08, 13. Feb. 2021 (CET)Beantworten
@PerfektesChaos, Fomafix: Hallo, ihr beiden. Wird an dem Skript noch etwas geändert oder darf ich jetzt gleich die Esperantoversion danach aktualisieren? Gruß --Tlustulimu (Diskussion) 20:15, 13. Feb. 2021 (CET)Beantworten
Ich habe den Code oben noch etwas leserlicher umgeschrieben und den Legacy-Code ersetzt. --Fomafix (Diskussion) 20:22, 13. Feb. 2021 (CET)Beantworten
Das 'use strict' habe ich auch noch dazu genommen und dadurch gleich nochmal eine undefinierte Variable entdeckt.
Das iframe-Attribut height ist nur eine Zahl ohne px.
Sonst noch irgend etwas zu verbessern? --Fomafix (Diskussion) 20:38, 13. Feb. 2021 (CET)Beantworten
Die Formel für die Umrechnung auf Bogengrad für die Breitengradhöhe habe ich auf die Konstante Math.PI zurückgeführt. Die Anzahl der Nachkommastellen könnte bei der Ausgabe in die URL noch begrenzt werden. --Fomafix (Diskussion) 21:07, 13. Feb. 2021 (CET)Beantworten
  • Hmm, jetzt ist eine zwar in C sehr gebräuchliche Syntax reingekommen, die in JavaScript aber sehr verpönt ist; die Inline-Zuweisung:if ( osmTarget && ( matches = OSM_class_R.exec() ) ) {
    • Ich würde diesen Bereich anders schreiben:
function embedOpenStreetMap() {
   var osmTarget = document.getElementById( 'osmEmbed' ),
       bbox, iframe, layer, lat, lon, lonSpan, matches, OSM_class_R, span, zoom;
   if ( osmTarget ) {
      OSM_class_R = /\bOSM:([\d.+-]+)_([\d.+-]+)_([\d.+-]+)_(\w+)/;
      matches     = OSM_class_R.exec( osmTarget.className );
      if ( matches ) {
  • Meine numerisch-optimistische Grundausbildung sträubt sich gegen die nunmehr sichtbarer werdenden Rechenoperationen. Aus Effizienzgründen gilt, Divisionen möglichst zu vermeiden und durch Multiplikationen zu ersetzen, und Multiplikationen durch Additionen:
    • Statt / 2 besser: * 0.5
    • Statt / 180 * Math.PI besser: * 0.0017683882 // / 180 * PI
    • Statt 512 * pow( 2, zoom ) besser: pow( 2, zoom + 9 )
    • Statt 1 / pow( 2, zoom + 9 ) besser: pow( 2, - zoom - 9 )
  • 360 / * 360; //WTF? bzw. zuvor 360.0/*720/2;
    • Das ist ein verunglücktes Math.floor() oder sowas und wirkungslos, weil JavaScript anders als Fortran-mäßig da keine Integer rausbekäme.
    • Weil jedoch lonSpan wegen Multiplikation mit Kosinus nie Integer ist, sind auch zwei Komponenten von bbox schon mal Gleitkommazahlen. Dann müssen die anderen beiden auch nicht auf Integer getrimmt werden.
  • Damit wird aber aus der Berechnung span = pow( 2, - zoom - 9 );
  • Das müsste zusammengebaut werden, und dann an einem zufälligen Beispiel überprüft ob in etwa die gleiche URL herauskäme wie vorher, und abschließend die Gesamtfunktion erprobt werden.
  • @Tlu: Schau mal nächstes Wochenende nach, ob es bei uns schon als Systemnachricht hinterlegt wurde. Das entpuppt sich hier als Totalschaden.
  • Wobei sich mir die Frage stellt, was diese 512 sein sollen und ob sich dahinter vielleicht eine Pixelei verbirgt.
    • Das Teil ist ganz offensichtlich zu Zeiten der Desktop-PC geschrieben worden.
    • Vielleicht ist heutzutage besser, die Hardware-Auflösung zu berücksichtigen. Es gibt Breitbild-Monitore als Kinoleinwand, und es gibt Mini-Mobilgeräte als Armbanduhr.
    • Möglicherweise ist es schlauer, diese 512 bzw. 9 dreistufig in Abhängigkeit von der Viewport-Auflösung zu bestimmen.
    • Mir scheint, als ob der Plan gewesen war, links und rechts von einem Mittelpunkt eines eingebetteten Dingens je 512 Pixel zu sichern, was dann bei einem Monitor 1024 × 768 und einer Maximalgröße des Dingens auf Vollbild dann wenigstens ein Pixel Genauigkeit an Auflösung sichern solle, oder so.
    • Jedenfalls scheinen mir diese 512 unter heutigen Hardwarebedingungen überholt.
    • Ein Minatur-Screen bekommt vielleicht zu viele Pixel übers Netz übertragen, zu viel Grafik, die dann verkleinert eingepasst würde?
    • Ein Breitbild-Monitor eine zu grobe Grafik???
    • Was soll das alles??????

VG --PerfektesChaos 16:44, 14. Feb. 2021 (CET)Beantworten

Deine Überlegungen sind prinzipiell richtig. Die Performanceuptimierung des Codes ist aber marginal gegenüber der absichtlichen 200 ms Verzögerung beim Start und gegenüber der unnötigen Abfrage von https://tools.wmflabs.org/ (DNS-Auflösung, Drei-Wege-Handschlag, TLS-Handshake, Zertifikatsprüfung und HTTP-Anfrage mit Weiterleitung als Antwort).
Sauber wäre es den ganzen alten Code durch etwas Neues zu ersetzten. Mit mw:Extension:Kartographer gibt es dafür sogar eine passende Extension. --Fomafix (Diskussion) 19:34, 14. Feb. 2021 (CET)Beantworten
In etwa, so wie es in w:en:MediaWiki:GeoHack.js könnte man das machen. Als Bonus wäre dann die Lizenzangabe von OpenStreetMap wieder korrekt acht Jahre nach der Lizenzumstellung auf die ODbL. Es könnte evtl. so aussehen?
/* Embed an OSM map on div id="osmEmbed" exists
 * This script is loaded by https://geohack.toolforge.org/geohack.php, see also [[Vorlage:GeoTemplate]]
 */
(function () {
    'use strict';

    function loadLeaflet() {
        var style = document.createElement('link');
        style.rel = 'stylesheet';
        style.type = 'text/css';
        style.href = '//maps.wikimedia.org/leaflet/leaflet.css';
        style.addEventListener("load", assetLoaded.bind(this, "style"));
        document.head.appendChild(style);
    
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = '//maps.wikimedia.org/leaflet/leaflet.js';
        script.addEventListener("load", assetLoaded.bind(this, "script"));
        document.head.appendChild(script);
    }

    var loadedAssets = [];
    function assetLoaded(asset) {
        loadedAssets.push(asset);
        if (loadedAssets.indexOf("script") >= 0 && loadedAssets.indexOf("style") >= 0) {
            embedOpenStreetMap();
        }
    }

    function embedOpenStreetMap() {
        var osmTarget = document.getElementById('osmEmbed'),
            match = document.getElementById('osmEmbed').className.match(/\bOSM:([\d.+-]+)_([\d.+-]+)_([\d.+-]+)_(\w+)/);
        if (osmTarget !== null && match !== null) {
            var lat = parseFloat(match[1]),
        	    lon = parseFloat(match[2]),
        	    zoom = parseInt(match[3]);

	        var map = L.map('osmEmbed').setView([lat, lon], zoom);
	        map.attributionControl.setPrefix('');
		    L.tileLayer('//maps.wikimedia.org/osm-intl/{z}/{x}/{y}{r}.png', {
		        attribution: 'Wikimedia maps beta | Map data &copy; <a href="http://osm.org/copyright">OpenStreetMap contributors</a>'
		    }).addTo(map);

	        L.marker([lat, lon]).addTo(map);
        }
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', loadLeaflet);
    } else {
        loadLeaflet();
    }
}).call(window);

--CamelCaseNick (Diskussion) 02:06, 15. Feb. 2021 (CET)Beantworten

  1. @CamelCaseNick: Zu deinem Vorschlag direkt bleiben einige Kommentare nicht aus.
    • Es gibt in Zeilen 38, 40, 44 ein nicht deklariertes L – das müsste window.L heißen.
      • Bei einer globalen Variablen L und massiver Kollisionsgefahr kräuseln sich mir die Fußnägel.
      • Wird definiert im allerletzten Statement von: https://maps.wikimedia.org/leaflet/leaflet.js
      • Sowas hat window.Leafletjs zu heißen, Mr. and Ms. http://leafletjs.com
      • Ich könnte Leute auf meinen CPU-Lüfter schnallen und ein paar Jahre rotieren lassen, die einer globalen Variablen einen aus einem Buchstaben bestehenden Namen geben. Ich bin allein auf diesem Planeten. Es gibt keine Skripte außer meinem. Niemand könnte in einem anderen Skript auch eine global sichtbare Variable verwenden, die nur aus einem Buchstaben besteht und zufällig in Großschreibung. Ich ruiniere so nebenbei dessen Skript, wenn ich später komme. Ist jemand anders später dran, dann schießt er halt mein Skript ab, ist mir doch egal, ich bin ja nicht der dämliche Anwender. Und alle, die über mein L stolpern können erstmal raten wo das wohl herkommen mag.
    • Das this in Zeilen 12 und 18 ist problematisch (uneindeutig) definiert und könnte undefined werden, weil es nicht in einem Objekt-Kontext steht.
    • Ansonsten sieht das gut aus, könnte man dann syntaktisch so machen (wobei ich nicht die leiseste Ahnung habe, was das fachlich bewirkt).
    • Wobei ich die non-jQuery-non-MediaWiki-Konstrukte geflissentlich übersehe, damit das Ganze auch in Kontext außerhalb der WMF vereinheitlicht benutzt werden kann.
  2. @ Sharing
    • Warum zum Henker müssen wir hier eigentlich jedes Wiki einzeln an Systemnachrichten rumfrickeln?
    • SOP blockiert zwar ggf. bestimmte Fremdskripte, CORS könnte das für mediawiki.org oder wikimedia.org oder beide im Zuge der „globalen Skripte“ explizit zulassen.
    • Eigentlich betrifft das jedoch eher Ajax/API-Zugriffe; meine Benutzerskripte können meines Wissens alle Wikis ausführen.
  3. Eigentlich müsste es ausreichen, dieses ganze Zeugs als Option an den vermutlich auslösenden https://wikimap.toolforge.org/ per URL-Parameter dranzuhängen; &view=leaflet für enWP oder &view=geohack für unsere bisherige Methode oder was auch immer. Und diese Skript-Details kann dann eine für 1000 Wikis gepflegte Skriptsammlung dann selbst beschicken; pro Projekt damit sogar konfigurierbar, falls Optionen benötigt würden. Und diese seltsame Systemnachricht-Skripterei kann man sich schenken.
VG --PerfektesChaos 19:17, 15. Feb. 2021 (CET)Beantworten

Koordinaten von Sternen Bearbeiten

Hallo!

Bei Sternen wie Beteigeuze und KW Sagittarii oder anderen astronomischen Objekten wie 2MASS J00412179+3547133 wird offenbar durch diesen Code das grüne Icon mit der Lupe eingeblendet. Bei Klick darauf zeigt es den atlantischen Ozean mit den Koordinaten 0°W 0°N (rauszoomen, dann sieht man Afrika).

Indirekt kommt das durch die Vorlage:CoordinateSky die ein &div mit id=coordinates erzeugt und einem darin enthaltenen Link der den string "geokack" enthält.

Eine minimalistische Seite mit dem Inhalt <div id="coordinates">[http://geohack]</div> erzeugt ebenfalls dieses grüne Icon (so hab ich diese Seite gefunden).

Wäre ganz gut, wenn das Ding etwas restriktiver ist und bei Himmelskoordinaten nichts macht. --Wurgl (Diskussion) 17:51, 17. Feb. 2021 (CET)Beantworten

Denkste! Nicht hier ist das Problem, sondern in/um Zeile 64 von m:MediaWiki:OSM.js gehört wohl eine Abfrage rein, ob '/skyhack.php' in dem Link drinnen ist, wenn gefunden dann return true. --Wurgl (Diskussion) 21:38, 17. Feb. 2021 (CET)Beantworten