Hauptseite > Schwarzatal.org


Diese Seite dokumentiert das Eventform-Gadget, mit dem eingeloggte Benutzer über ein Formular neue Veranstaltungsseiten anlegen können. Die Dokumentation ist so gehalten, dass das Gadget damit vollständig nachgebaut werden kann.

Überblick

Das Eventform-Gadget blendet auf der Seite Veranstaltungen einen Button „Neue Veranstaltung anlegen" ein. Ein Klick öffnet einen Formular-Dialog. Nach dem Ausfüllen erzeugt das Gadget eine neue Wiki-Seite mit standardisierter Struktur (Abschnitte Zeit, Event, Location, Photos & Videos) und leitet den Benutzer direkt dorthin weiter.

Eigenschaften:

  • Reines JavaScript-Gadget — keine Server-Extension, keine Änderung an LocalSettings.php nötig (außer der einmaligen Aktivierung der Gadgets-Extension)
  • Läuft nur auf einer konfigurierbaren Trigger-Seite und nur für eingeloggte Benutzer
  • Prüft vor dem Anlegen, ob der Seitentitel bereits existiert (kein Überschreiben möglich)
  • Erkennt GPS-Koordinaten in mehreren Formaten und generiert daraus automatisch Kartenlinks (OpenStreetMap, CoMaps, Google Maps), sofern die jeweiligen URL-Felder leer sind

Architektur

Das Gadget besteht aus drei Wiki-Seiten und einer normalen Inhaltsseite:

Seite Zweck
MediaWiki:Gadgets-definition Registriert das Gadget beim ResourceLoader
MediaWiki:Gadget-eventform.js Gesamte Logik: Formular-Dialog, Koordinaten-Parser, Wikitext-Generator, API-Aufrufe
MediaWiki:Gadget-eventform.css Styling des Button-Containers
Veranstaltungen (Trigger-Seite) Enthält den Anker <div id="event-form-container"></div>, in den der Button gerendert wird

Verwendete MediaWiki-Bausteine:

  • Extension:Gadgets — Auslieferung des Codes an die Browser
  • OOUI (oojs-ui-core, oojs-ui-windows) — Formular-Dialog und Button, in MediaWiki eingebaut
  • mediawiki.api (mw.Api) — Seitenexistenz-Prüfung und Seitenerstellung über die Action-API
  • mediawiki.util — URL-Erzeugung für die Weiterleitung

Installation

Schritt 1: Gadgets-Extension aktivieren

Die Gadgets-Extension liegt MediaWiki bei, muss aber ggf. aktiviert werden. In LocalSettings.php (per FTP):

wfLoadExtension( 'Gadgets' );

Kontrolle: Auf Spezial:Version muss unter „Installierte Erweiterungen" der Eintrag Gadgets erscheinen.

Schritt 2: Gadget registrieren

Auf der Seite MediaWiki:Gadgets-definition folgenden Block eintragen:

== Werkzeuge ==
* eventform[ResourceLoader|default|rights=edit]|eventform.js|eventform.css

Bedeutung der Flags:

  • ResourceLoader — Auslieferung über den ResourceLoader (Caching, Minifizierung)
  • default — für alle Benutzer standardmäßig aktiv (abwählbar unter Einstellungen → Gadgets)
  • rights=edit — nur Benutzer mit Bearbeitungsrecht erhalten das Gadget

Kontrolle: Auf Spezial:Gadgets muss „eventform" gelistet sein.

Schritt 3: JavaScript anlegen

Die Seite MediaWiki:Gadget-eventform.js mit dem vollständigen Gadget-Code anlegen (siehe Funktionsweise im Detail für die Logik; der aktuelle Code steht in der Versionsgeschichte der Seite selbst).

Schritt 4: CSS anlegen

Die Seite MediaWiki:Gadget-eventform.css anlegen:

#event-form-container {
	margin: 1.5em 0;
	padding: 1em;
	background: #f8f9fa;
	border: 1px solid #c8ccd1;
	border-radius: 4px;
	text-align: center;
}

Schritt 5: Trigger-Seite vorbereiten

Auf der Seite Veranstaltungen an gewünschter Stelle den Anker einfügen:

<div id="event-form-container"></div>

Fehlt der Anker, hängt das Gadget den Button automatisch ans Ende des Seiteninhalts.

Schritt 6: Testen

  1. Eingeloggt die Seite Veranstaltungen aufrufen
  2. Hard-Reload durchführen (Strg+Shift+R), da der ResourceLoader aggressiv cacht
  3. Button „Neue Veranstaltung anlegen" muss erscheinen

Funktionsweise im Detail

Dieser Abschnitt beschreibt die Logik so, dass das Gadget nachprogrammiert werden kann.

Grundgerüst

Der gesamte Code liegt in einer IIFE (( function () { ... }() );) mit 'use strict'. Am Anfang stehen zwei Guards, die das Skript sofort beenden, wenn es nicht greifen soll:

  1. mw.config.get( 'wgPageName' ) !== TRIGGER_PAGE — das Gadget wird zwar auf jeder Seite geladen (Gadgets sind global), rendert aber nur auf der konfigurierten Trigger-Seite. TRIGGER_PAGE ist eine Konstante am Dateianfang (aktuell 'Veranstaltungen'). Achtung: wgPageName verwendet Unterstriche statt Leerzeichen.
  2. !mw.config.get( 'wgUserName' ) — anonyme Benutzer (Wert null) werden ausgeschlossen.

Danach lädt mw.loader.using( [...] ) asynchron die benötigten Module. Erst im .then()-Callback wird die UI aufgebaut — zu diesem Zeitpunkt ist das DOM garantiert bereit, ein zusätzlicher DOM-Ready-Wrapper ist nicht nötig (und führte in der Entwicklung zu Problemen, siehe Stolpersteine).

Benötigte Module:

oojs-ui-core, oojs-ui-windows, oojs-ui.styles.icons-interactions,
mediawiki.api, mediawiki.util

Formular-Dialog (OOUI)

Der Dialog ist eine Subklasse von OO.ui.ProcessDialog:

  • OO.inheritClass( EventDialog, OO.ui.ProcessDialog )
  • Statische Eigenschaften: name, title, actions (Aktion save mit Flags primary, progressive sowie eine Abbrechen-Aktion mit Flag safe)
  • In initialize() werden die Eingabefelder als OO.ui.TextInputWidget erzeugt und über OO.ui.FieldLayout in drei OO.ui.FieldsetLayout-Gruppen gegliedert: Pflichtfelder, Event, Location
  • getBodyHeight() gibt eine feste Höhe (600px) zurück
  • Der Dialog wird über einen OO.ui.WindowManager geöffnet, der an document.body hängt

Felder (alle TextInputWidget; Datum mit type: 'date', Uhrzeit mit type: 'time' und Vorbelegung 17:00):

Feld Pflicht Verwendung im Wikitext
Seitentitel ja Name der neuen Wiki-Seite
Datum ja Zeile 🗓️ … (wird unverändert als String übernommen)
Uhrzeit nein Zeile ⏰ …; bei leerem Feld entfällt die Zeile komplett
Bild (Dateiname) nein Datei:…; Rotlink erlaubt nachträglichen Upload per Klick
Website URL nein Zeile 🌐 …
Adresse nein Zeile 📍 …
OpenStreetMap URL nein Zeile mit OSM-Icon; wird ggf. automatisch generiert
GPS-Koordinaten nein Zeile 🧭 … (Originaleingabe); Quelle der Auto-Generierung
CoMaps URL nein Zeile mit CoMaps-Icon; wird ggf. automatisch generiert
Google Maps URL nein Zeile mit Google-Maps-Icon; wird ggf. automatisch generiert

Speicher-Ablauf

getActionProcess( 'save' ) gibt einen OO.ui.Process zurück, dessen Callback:

  1. Alle Feldwerte ausliest und trimmt
  2. Pflichtfelder prüft (Titel, Datum); bei Fehlern wird ein OO.ui.Error mit recoverable: true zurückgegeben — der Dialog zeigt die Meldung an und bleibt offen
  3. Koordinaten parst (siehe unten) und leere Karten-URL-Felder automatisch befüllt
  4. Den Wikitext generiert (siehe unten)
  5. Per api.get( { action: 'query', titles: titel } ) prüft, ob die Seite existiert (page.missing im Ergebnis); wenn ja → Fehler „existiert bereits"
  6. Per api.postWithToken( 'csrf', { action: 'edit', title, text, createonly: true, summary } ) die Seite anlegt. createonly ist eine zweite Absicherung gegen Überschreiben (Race Condition zwischen Prüfung und Anlage)
  7. Bei Erfolg per window.location.href = mw.util.getUrl( titel ) zur neuen Seite weiterleitet

Koordinaten-Parser

Die Funktion parseCoordinates( input ) gibt { lat, lng } oder null zurück. Sie probiert nacheinander mehrere reguläre Ausdrücke; der erste Treffer mit plausiblen Werten (|lat| ≤ 90, |lng| ≤ 180) gewinnt:

  1. Deutsches Dezimalformat (Komma als Dezimaltrenner): 47,7073132, 15,9934565 — auch mit Semikolon oder Leerzeichen als Koordinatentrenner. Wichtig, weil die Google-Maps-App auf deutschsprachigen Geräten dieses Format in die Zwischenablage kopiert. Erkennungslogik: zwei Zahlen mit Dezimal-Komma, getrennt durch ", " (Komma+Leerzeichen), Semikolon oder Leerzeichen. Vor parseFloat wird das Komma durch einen Punkt ersetzt.
  2. Internationales Dezimalformat: 48.0542, 15.4276, auch ohne Leerzeichen, mit Semikolon oder nur Leerzeichen, negative Werte erlaubt
  3. Dezimal mit Himmelsrichtungen: 47.75N 15.68E oder 47,75°N, 15,68°E — S und W negieren den Wert
  4. Grad-Minuten-Sekunden (DMS): 47°45'00.0"N 15°40'48.0"E — Umrechnung: Grad + Minuten/60 + Sekunden/3600. Akzeptiert sowohl gerade (' ") als auch typografische Zeichen ( ), da mobile Betriebssysteme beim Kopieren oft typografische Zeichen erzeugen
  5. Grad-Dezimalminuten (DM): 47°45.000'N 15°40.800'E — Umrechnung: Grad + Minuten/60

Wenn parseCoordinates erfolgreich war, werden für leere URL-Felder Links generiert (vom Benutzer ausgefüllte Felder haben immer Vorrang). Die Koordinaten werden mit toFixed( 7 ) formatiert:

Dienst URL-Schema
OpenStreetMap https://www.openstreetmap.org/?mlat=LAT&mlon=LNG#map=17/LAT/LNG (Pin + Zoomstufe 17)
CoMaps https://comaps.at/LAT,LNG (CoMaps ist ein Fork von Organic Maps und nutzt dessen URL-Schema)
Google Maps https://www.google.com/maps?q=LAT,LNG

Wikitext-Generator

Die Funktion buildWikitext( fields ) baut die Seite als Array von Zeilen auf und verbindet sie mit \n. Regeln:

  • Erste Zeile ist die Breadcrumb-Navigation: [[Hauptseite]] > [[Hauptseite#Kultur & Events|Kultur & Events]] > [[Veranstaltungen]]
  • Abschnitte in fester Reihenfolge: ==Zeit==, ==Event==, ==Location==, ==Photos & Videos==
  • Optionale Zeilen (Uhrzeit, Bild, Website, alle Location-Zeilen) werden bei leerem Feld komplett weggelassen — es entstehen keine leeren Zeilen oder verwaisten Symbole
  • Im Location-Abschnitt wird zwischen den vorhandenen Zeilen jeweils eine Leerzeile eingefügt (jede Zeile wird ein eigener Absatz); Hilfskonstruktion: eine Funktion addLocLine mit einem locFirst-Flag, das vor jeder Zeile außer der ersten eine Leerzeile einschiebt
  • URLs werden als Klartext eingefügt — MediaWiki wandelt https://… automatisch in klickbare Links um
  • Jeder Abschnitt endet mit vier <br>-Zeilen (Layout-Vorgabe der Event-Seiten)
  • Karten-Zeilen mit Icons: [[file:osm.png|24px|link=]] URL (analog CoMaps.png, GoogleMaps.png) — die Icon-Dateien müssen im Wiki hochgeladen sein

Manual: Benutzung

  1. Auf der Seite Veranstaltungen den Button Neue Veranstaltung anlegen klicken (nur sichtbar, wenn eingeloggt)
  2. Pflichtfelder ausfüllen: Seitentitel (wird der Name der Wiki-Seite, muss eindeutig sein) und Datum
  3. Optional: Uhrzeit (Vorbelegung 17:00, kann geleert werden), Bild-Dateiname, Website, Adresse, Kartenlinks, GPS-Koordinaten
  4. Tipp Bild: Einen sinnvollen Dateinamen mit Endung vergeben (z.B. Sommerfest2026.jpg). Auf der fertigen Seite erscheint ein Rotlink, über den das Bild direkt hochgeladen werden kann. Alternativ vorher unter Spezial:Hochladen hochladen.
  5. Tipp Koordinaten: Aus einer Karten-App kopieren und einfügen — deutsche Schreibweise mit Komma (47,7073132, 15,9934565) wird erkannt. Bei eingetragenen Koordinaten werden fehlende Links zu OpenStreetMap, CoMaps und Google Maps automatisch ergänzt.
  6. Seite anlegen klicken. Bei Erfolg erfolgt die Weiterleitung auf die neue Seite. Existiert der Titel bereits, erscheint eine Fehlermeldung und das Formular bleibt offen.

Konfiguration und Anpassung

  • Trigger-Seite ändern: Konstante TRIGGER_PAGE am Anfang von MediaWiki:Gadget-eventform.js anpassen. Leerzeichen im Seitennamen als Unterstrich schreiben.
  • Felder hinzufügen: (1) TextInputWidget in initialize() anlegen, (2) FieldLayout im passenden Fieldset ergänzen, (3) Wert in getActionProcess ins fields-Objekt aufnehmen, (4) Ausgabe in buildWikitext ergänzen.
  • Seitenstruktur ändern: Nur buildWikitext anpassen.
  • Berechtigungen: Über das Flag rights=… in MediaWiki:Gadgets-definition steuerbar (z.B. rights=edit).

Bekannte Stolpersteine

  • ResourceLoader-Cache: Nach jeder Änderung an Gadget-JS/CSS ist im Browser ein Hard-Reload nötig (Strg+Shift+R), teils dauert es zusätzlich bis zu ~5 Minuten, bis der ResourceLoader serverseitig neu ausliefert. Bei „Änderung wirkt nicht"-Symptomen zuerst immer an den Cache denken — auch am Handy.
  • Kein DOM-Ready-Wrapper im then(): Ein $( function () { … } ) innerhalb des mw.loader.using().then()-Callbacks kann dazu führen, dass der Handler nie feuert. Der UI-Code gehört direkt in den then()-Callback.
  • wgPageName exakt treffen: Groß-/Kleinschreibung und Unterstriche müssen exakt stimmen, sonst beendet sich das Gadget kommentarlos.
  • Icon-Dateien: osm.png, CoMaps.png, GoogleMaps.png müssen im Wiki existieren, sonst erscheinen Rotlinks in den Location-Zeilen.
  • Debugging: In der Browser-Konsole prüfen: mw.loader.getState('ext.gadget.eventform') muss "ready" liefern; mw.config.get('wgPageName') muss der Trigger-Seite entsprechen. Für Debugging über Seitenwechsel hinweg in den DevTools „Persistente Logs" aktivieren.

Grenzen der Lösung

  • Keine serverseitige Validierung — das Gadget läuft vollständig im Browser. Die Rechte-Durchsetzung übernimmt die MediaWiki-API (ein Benutzer kann nur anlegen, was er auch manuell anlegen dürfte).
  • Das Datum wird als freier String übernommen, ohne Plausibilitätsprüfung.
  • Keine Vorschau vor dem Anlegen (Erweiterung möglich).
  • Für strukturierte Abfragen über Events (z.B. „alle Veranstaltungen im Mai") wäre langfristig eine Lösung mit Page Forms und Cargo geeigneter.