Eventform
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.phpnö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-APImediawiki.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
- Eingeloggt die Seite Veranstaltungen aufrufen
- Hard-Reload durchführen (Strg+Shift+R), da der ResourceLoader aggressiv cacht
- 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:
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_PAGEist eine Konstante am Dateianfang (aktuell'Veranstaltungen'). Achtung:wgPageNameverwendet Unterstriche statt Leerzeichen.!mw.config.get( 'wgUserName' )— anonyme Benutzer (Wertnull) 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(Aktionsavemit Flagsprimary, progressivesowie eine Abbrechen-Aktion mit Flagsafe) - In
initialize()werden die Eingabefelder alsOO.ui.TextInputWidgeterzeugt und überOO.ui.FieldLayoutin dreiOO.ui.FieldsetLayout-Gruppen gegliedert: Pflichtfelder, Event, Location getBodyHeight()gibt eine feste Höhe (600px) zurück- Der Dialog wird über einen
OO.ui.WindowManagergeöffnet, der andocument.bodyhä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:
- Alle Feldwerte ausliest und trimmt
- Pflichtfelder prüft (Titel, Datum); bei Fehlern wird ein
OO.ui.Errormitrecoverable: truezurückgegeben — der Dialog zeigt die Meldung an und bleibt offen - Koordinaten parst (siehe unten) und leere Karten-URL-Felder automatisch befüllt
- Den Wikitext generiert (siehe unten)
- Per
api.get( { action: 'query', titles: titel } )prüft, ob die Seite existiert (page.missingim Ergebnis); wenn ja → Fehler „existiert bereits" - Per
api.postWithToken( 'csrf', { action: 'edit', title, text, createonly: true, summary } )die Seite anlegt.createonlyist eine zweite Absicherung gegen Überschreiben (Race Condition zwischen Prüfung und Anlage) - 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:
- 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. VorparseFloatwird das Komma durch einen Punkt ersetzt. - Internationales Dezimalformat:
48.0542, 15.4276, auch ohne Leerzeichen, mit Semikolon oder nur Leerzeichen, negative Werte erlaubt - Dezimal mit Himmelsrichtungen:
47.75N 15.68Eoder47,75°N, 15,68°E— S und W negieren den Wert - 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 - Grad-Dezimalminuten (DM):
47°45.000'N 15°40.800'E— Umrechnung: Grad + Minuten/60
Automatische Kartenlink-Generierung
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
addLocLinemit einemlocFirst-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(analogCoMaps.png,GoogleMaps.png) — die Icon-Dateien müssen im Wiki hochgeladen sein
Manual: Benutzung
- Auf der Seite Veranstaltungen den Button Neue Veranstaltung anlegen klicken (nur sichtbar, wenn eingeloggt)
- Pflichtfelder ausfüllen: Seitentitel (wird der Name der Wiki-Seite, muss eindeutig sein) und Datum
- Optional: Uhrzeit (Vorbelegung 17:00, kann geleert werden), Bild-Dateiname, Website, Adresse, Kartenlinks, GPS-Koordinaten
- 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. - 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. - 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_PAGEam Anfang vonMediaWiki:Gadget-eventform.jsanpassen. Leerzeichen im Seitennamen als Unterstrich schreiben. - Felder hinzufügen: (1)
TextInputWidgetininitialize()anlegen, (2)FieldLayoutim passenden Fieldset ergänzen, (3) Wert ingetActionProcessinsfields-Objekt aufnehmen, (4) Ausgabe inbuildWikitextergänzen. - Seitenstruktur ändern: Nur
buildWikitextanpassen. - Berechtigungen: Über das Flag
rights=…inMediaWiki:Gadgets-definitionsteuerbar (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 desmw.loader.using().then()-Callbacks kann dazu führen, dass der Handler nie feuert. Der UI-Code gehört direkt in denthen()-Callback. wgPageNameexakt treffen: Groß-/Kleinschreibung und Unterstriche müssen exakt stimmen, sonst beendet sich das Gadget kommentarlos.- Icon-Dateien:
osm.png,CoMaps.png,GoogleMaps.pngmü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.