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
/**
 * Gadget-Pano360
 * Bindet 360-Grad-Panoramen (equirektangular) per Pannellum ein.
 * Verwendung im Wikitext:
 *   <div class="pano360" data-src="Datei:Beispiel.jpg">Fallback-Text</div>
 *
 * Unterstützte data-Attribute:
 *   data-src        Wiki-Dateiname ("Datei:X.jpg" oder "X.jpg") oder URL/Pfad (Pflicht)
 *   data-height     Höhe in Pixeln (Standard: per CSS, 400)
 *   data-yaw        Start-Blickrichtung horizontal in Grad (-180..180)
 *   data-pitch      Start-Blickrichtung vertikal in Grad (-90..90)
 *   data-hfov       Start-Blickwinkel/Zoom in Grad (Standard 100)
 *   data-autorotate Autorotation in Grad/Sekunde (z.B. 2, negativ = andersherum)
 *   data-preview    Vorschaubild, wird waehrend des Ladens angezeigt (Dateiname oder URL)
 *   data-title      Titel-Einblendung im Viewer
 *   data-author     Autor-Einblendung im Viewer
 *   data-compass    "1" = Kompass anzeigen
 *   data-north      Nordversatz in Grad (fuer Kompass), Blickrichtung von Norden
 */
(function () {
	'use strict';

	var LIB_PATH = mw.config.get('wgScriptPath') + '/resources/lib/pannellum/';
	var loadPromise = null;

	// Pannellum-Bibliothek (JS + CSS) genau einmal nachladen
	function loadPannellum() {
		if (loadPromise) {
			return loadPromise;
		}
		loadPromise = $.Deferred(function (deferred) {
			$('<link>', {
				rel: 'stylesheet',
				href: LIB_PATH + 'pannellum.css'
			}).appendTo('head');

			var script = document.createElement('script');
			script.src = LIB_PATH + 'pannellum.js';
			script.onload = function () {
				deferred.resolve();
			};
			script.onerror = function () {
				deferred.reject();
			};
			document.head.appendChild(script);
		}).promise();
		return loadPromise;
	}

	// Dateiname oder URL -> ladbare Bild-URL
	function resolveSrc(src) {
		src = String(src).trim();
		// Bereits URL oder absoluter Pfad? Unveraendert lassen.
		if (/^(https?:)?\/\//i.test(src) || src.charAt(0) === '/') {
			return src;
		}
		// Wiki-Datei: ueber Spezial:Weiterleitung zur Originaldatei
		var name = src.replace(/^(Datei|File):/i, '');
		return mw.util.getUrl('Special:Redirect/file/' + name);
	}

	// data-Attribut als Zahl lesen, sonst undefined
	function num($el, attr) {
		var v = $el.attr(attr);
		if (v === undefined || v === '' || isNaN(parseFloat(v))) {
			return undefined;
		}
		return parseFloat(v);
	}

	function initContainer(container) {
		var $c = $(container);
		var src = $c.attr('data-src');

		if (!src) {
			$c.text('Pano360: Attribut data-src fehlt.');
			return;
		}

		var config = {
			type: 'equirectangular',
			panorama: resolveSrc(src),
			autoLoad: true,
			showFullscreenCtrl: true,
			strings: {
				loadingLabel: 'Wird geladen …',
				bylineLabel: 'von %s',
				noPanoramaError: 'Kein Panoramabild angegeben.',
				fileAccessError: 'Die Datei %s konnte nicht geladen werden.',
				malformedURLError: 'Fehlerhafte Panorama-URL.'
			}
		};

		var yaw = num($c, 'data-yaw');
		var pitch = num($c, 'data-pitch');
		var hfov = num($c, 'data-hfov');
		var autorotate = num($c, 'data-autorotate');
		var north = num($c, 'data-north');

		if (yaw !== undefined) { config.yaw = yaw; }
		if (pitch !== undefined) { config.pitch = pitch; }
		if (hfov !== undefined) { config.hfov = hfov; }
		if (autorotate !== undefined) { config.autoRotate = autorotate; }
		if (north !== undefined) { config.northOffset = north; }
		if ($c.attr('data-compass') === '1') { config.compass = true; }
		if ($c.attr('data-title')) { config.title = $c.attr('data-title'); }
		if ($c.attr('data-author')) { config.author = $c.attr('data-author'); }
		if ($c.attr('data-preview')) {
			config.preview = resolveSrc($c.attr('data-preview'));
		}

		var height = num($c, 'data-height');
		if (height !== undefined) {
			container.style.height = height + 'px';
		}

		// Fallback-Inhalt entfernen, Viewer starten
		$c.empty();
		pannellum.viewer(container, config);
	}

	// Initialisierung bei Seitenladen und Vorschau
	mw.hook('wikipage.content').add(function ($content) {
		var $panos = $content.find('.pano360');
		if (!$panos.length) {
			return;
		}
		loadPannellum().then(function () {
			$panos.each(function () {
				if (this.getAttribute('data-pano360-init') !== '1') {
					this.setAttribute('data-pano360-init', '1');
					initContainer(this);
				}
			});
		}, function () {
			mw.log.warn('Pano360: Pannellum nicht ladbar unter ' + LIB_PATH);
			$panos.text('360°-Panorama-Viewer konnte nicht geladen werden.');
		});
	});
}());