Hinweis: Leere nach dem Veröffentlichen den Browser-Cache, um die Änderungen sehen zu können.

  • Firefox/Safari: Umschalttaste drücken und gleichzeitig Aktualisieren anklicken oder entweder Strg+F5 oder Strg+R (⌘+R auf dem Mac) drücken
  • Google Chrome: Umschalttaste+Strg+R (⌘+Umschalttaste+R auf dem Mac) drücken
  • Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
// popup for geohack
( function ( mw, $ ) {
   "use strict";
	var geohackRE = /https:\/\/geohack\.toolforge\.org\/geohack\.php\?.*params=([\d\.\-]+)_(N|S)_([\d\.\-]+)_(O|E|W).*/;
	// does not work for Wikidata
	// wikidata      https://geohack.toolforge.org/geohack.php?params=48.17586_N_16.2918_E_globe:earth&language=de
	// <a href="https://geohack.toolforge.org/geohack.php?params=48.17586_N_16.2918_E_globe:earth&amp;language=de" class="external">48°10'33"N, 16°17'30"E</a>
	// the structure of geohack links
	
	// <tr class="exif-gpslatitude"><th>Geografische Breite</th><td>47° 28′ 31,59″ N</td></tr>
	var exifRE = /(\d+)° (\d+)′ ([\d,\.]+)″ (O|E|W|S|N)/;

	// helper for setTimeout
	function autoFadeOutPopup (o) {
		o.fadeOut("slow");
	}
	
	function fadeInPopup (event) {
		var div = $(event.target).find('.DECpu');
		div.fadeIn("slow");
		setTimeout(autoFadeOutPopup,7000,div);
	    return false;
	}
	
	function fadeOutPopup(event) {
		var sel = document.getSelection().toString();
		if(!sel){ // only of no selection for copy
			$(event.target).closest('.DECpu').fadeOut("slow");
		}
	    return false;
	}
	  
	$(document).ready(function() {
	  var texts = (function texts() {
	    var translations = {
	        en: {
				copy: "copy to clipboard",
				logoTitle: "Geotools by Herzi Pinki",
				credits: " DEC-Coords:",
	        },
	        de: {
				copy: "In die Zwischenablage kopieren",
				logoTitle: "Geowerkzeuge von Herzi Pinki",
				credits: " DEC-Koordinaten:",
	        },
	      },
	      chain = mw.language.getFallbackLanguageChain(),
	      len = chain.length,
	      ret = {},
	      i = len - 1;
	
	    while (i >= 0) {
	      if (translations.hasOwnProperty(chain[i])) {
	        $.extend(ret, translations[chain[i]]);
	      }
	      i -= 1;
	    }
	    return ret;
	  }());
	
	function addPopup(parentNode, cval, id, widthFac=1) {
			var dynDiv = document.createElement("div");
			dynDiv.setAttribute("id", id);
			
			var header = document.createElement("div");
			header.style.fontSize = "small";
			header.style.whiteSpace = "nowrap";

			// copy to clipboard
			var copybutton = document.createElement("img");
			copybutton.style.width = "30px";
			copybutton.style.height = "30px";
			copybutton.style.float = "right";
			copybutton.style.padding = "5px 1px";
			copybutton.src = "//upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Edit-copy.svg/30px-Edit-copy.svg.png";
			copybutton.title = texts.copy;
			copybutton.decoding = "async";
			header.appendChild(copybutton);

			var logo = document.createElement("img");
			logo.style.width = "15px";
			logo.style.height = "15px";
			logo.src = "//upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Erioll_world.svg/15px-Erioll_world.svg.png";
			logo.title = texts.logoTitle;
			logo.decoding = "async";
			header.appendChild(logo);
			header.appendChild(document.createTextNode(texts.credits));
    		dynDiv.appendChild(header);
    		
    		var cvalNode = document.createElement("div");
    		cvalNode.appendChild(document.createTextNode(cval));
    		cvalNode.className = "DECpuCval";
			cvalNode.style.clear = "left";
			cvalNode.style.lineHeight = 1.5;
			//cvalNode.style.textAlign = "center";
			cvalNode.style.padding = "4px 0px";
			cvalNode.style.whiteSpace = "nowrap";

    		dynDiv.appendChild(cvalNode);
    		
    		dynDiv.className = "DECpu";
    		dynDiv.style.position = "absolute";
    		dynDiv.style.width = (180*widthFac).toString+'px';
    		dynDiv.style.border = "1px solid";
    		dynDiv.style.background = "#ddd";
    		dynDiv.style.padding = "2px 5px";
    		dynDiv.style.display="none";
    		dynDiv.style.left="20px";
    		dynDiv.style.top="20px";
    		dynDiv.style.textAlign="left";
    		dynDiv.style.zIndex = "200";
    		
    		// need intermediate parent for positioning
    		var relParent = document.createElement("div");
    		relParent.style.position = "relative";
    		//relParent.style.width = "210px";
    		relParent.style.width="0";
    		relParent.style.height="0";
    		relParent.style.display="inline";

    		relParent.append(dynDiv);
    		parentNode.prepend(relParent);
    		var rectDiv = relParent.getBoundingClientRect();
    		var bodyDiv = $("body")[0].getBoundingClientRect();
    		if (rectDiv.left + rectDiv.width + 210 > bodyDiv.right) {
    			dynDiv.style.left = (parseInt(dynDiv.style.left, 10) - (210-(Math.round (bodyDiv.right-rectDiv.right))))+"px";
    		}

    		parentNode.addEventListener("mouseenter", fadeInPopup); 

    		dynDiv.addEventListener("click", fadeOutPopup);
			
			// putting the function to outer scope creates an exception
			// uncaught (in promise) DOMException: clipboard write was blocked due to lack of user activation.
			copybutton.addEventListener("click", function(event) {
					var nodes = $(event.target).closest('.DECpu').find('.DECpuCval');
					if (nodes) {
						navigator.clipboard.writeText(nodes[0].childNodes[0].nodeValue);
					}
				    return false;
				});
		}
		
		var anchors = document.getElementsByTagName("a");
		var i; // declare i
		for (i = 0; i < anchors.length; i++) {
			var coords = anchors[i].href.match(geohackRE);
			if (coords) {
				var parentNode = anchors[i].parentNode; 
				// geohack link found
				// coords[0] is the whole line
				// var geohackRE = /https:\/\/geohack\.toolforge\.org\/geohack\.php\?.*params=([\d\.\-]+)_(N|S)_([\d\.\-]+)_(O|E|W).*/;
	            //                                                                            (1        ) (2  ) (3        ) (4    ) 
				var lat = (coords[2] == 'S')? -coords[1] : coords[1];
				var lon = (coords[4] == 'W')? -coords[3] : coords[3];
				lat = Math.round(lat * 1000000) / 1000000; // round to 6 digits
				lon = Math.round(lon * 1000000) / 1000000;
				
				var cval = lat.toString() + ', ' + lon.toString();
	
				var id = "DEC"+i.toString();
				addPopup(parentNode, cval, id);
	
			}
		}
		
		// <tr class="exif-gpslatitude"><th>Geografische Breite</th><td>47° 28′ 31,59″ N</td></tr>
		var latNodes = document.getElementsByClassName("exif-gpslatitude");
		var latNode = null;
		if (latNodes.length>0) {
			latNode = latNodes[0];
		}
		
		var longNodes = document.getElementsByClassName("exif-gpslongitude");
		var longNode = null;
		if (longNodes.length>0) {
			longNode = longNodes[0];
		}
		
		var dirNodes = document.getElementsByClassName("exif-gpsimgdirection");
		var dirNode = null;
		if (dirNodes.length>0) {
			dirNode = dirNodes[0];
		}
		
		var altNodes = document.getElementsByClassName("exif-gpsaltitude");
		var altNode = null;
		if (altNodes.length>0) {
			altNode = altNodes[0];
		}

		if (latNode && longNode) {
			var latVal  = latNode.firstChild.nextSibling.firstChild.nodeValue;
			var longVal = longNode.firstChild.nextSibling.firstChild.nodeValue;
			var hookNode = latNode.firstChild.nextSibling;
			var msgBoxNode = null;
			var images = $("table.messagebox img[src*='Gnome-edit-clear.svg']");
			if (images.length>0) {
				msgBoxNode = images[0].parentNode.parentNode.parentNode;
			}
			
			var exifLat;
			var exifLong;

			// <tr class="exif-gpslatitude"><th>Geografische Breite</th><td>47° 28′ 31,59″ N</td></tr>
			// var exifRE = /(\d+)° (\d+)′ ([\d,\.]+)″ (O|E|W|S|N)/;
			//               (1  )  (2  )  (3       )  (4        )

			var exifCoords = latVal.match(exifRE);
			if (exifCoords) {
				exifCoords[3] = exifCoords[3].replace(',', '.'); // uniform comma, if any
				exifLat = parseInt(exifCoords[1]) + parseFloat(exifCoords[2])/60 + parseFloat(exifCoords[3])/3600 ;
				exifLat = (exifCoords[4] == "S")? -exifLat : exifLat;
				exifLat = Math.round(exifLat * 1000000) / 1000000; // round to 6 digits
			}
			exifCoords = longVal.match(exifRE);
			if (exifCoords) {
				exifCoords[3] = exifCoords[3].replace(',', '.'); // uniform comma, if any
	        	exifLong = parseInt(exifCoords[1]) + parseFloat(exifCoords[2])/60 + parseFloat(exifCoords[3])/3600 ;
				exifLong = (exifCoords[4] == "W")? -exifLong : exifLong;
				exifLong = Math.round(exifLong * 1000000) / 1000000; // round to 6 digits
			}
			
			var exifAlt = '';
			var exifDir = '';
			var altVal = '';
			var dirVal = '';
			if (altNode) {
				altVal  = altNode.firstChild.nextSibling.firstChild.nodeValue;
				// 633,7 Meter über dem Meeresspiegel
				// 1.633,7 Meter über dem Meeresspiegel
				exifAlt = altVal.match(/^([\d,\.]+).*/);
				if (exifAlt) {
					exifAlt[1] = exifAlt[1].replace(/\.(\d+,)/, '$1'); // uniform comma, if any; 1.633,7 case -> 1633,7
					exifAlt[1] = exifAlt[1].replace(/^(\d)\.(\d{3,3})/, '$1$2'); // remove 1000 sep, if any; 1.633 case -> 1633
					exifAlt[1] = exifAlt[1].replace(',', '.'); // uniform comma, if any
					altVal = parseFloat(exifAlt[1]);
				}
			}
			if (dirNode) {
				dirVal  = dirNode.firstChild.nextSibling.firstChild.nodeValue;
				// 123,7
				exifDir = dirVal.match(/^([\d,\.]+).*/);
				if (exifDir) {
					exifDir[1] = exifDir[1].replace(',', '.'); // uniform comma, if any
					dirVal = parseFloat(exifDir[1]);
				}
			}

			
			if (exifLat != 0 || exifLong != 0) {
				var cval2 = '{{Location|' + exifLat.toString() + '|' + exifLong.toString();
				// alt:633.7_source:exif_heading:149.25
				var par = '|source:exif';
				if (altVal) {
					par += '_alt:' + altVal;
				}
				if (dirVal) {
					par += '_heading:' + dirVal;
				}
				cval2 += par + '}}';
		
				addPopup(hookNode, cval2, "DECexif",3);
				if (msgBoxNode) {
					addPopup(msgBoxNode, cval2, "DECmsgExif",3);
				}
			}
		}

	});
}( window.mediaWiki, window.jQuery ) );