MediaWiki:Common.js: Unterschied zwischen den Versionen
Admin (Diskussion | Beiträge) Die Seite wurde neu angelegt: „→Das folgende JavaScript wird für alle Benutzer geladen.: →========================= Site Announcement Modal ========================= - Zeigt ein modales Popup einmal pro Tag pro Nutzer. - Mobilfreundlich (funktioniert mit Vector/Vector-2022/Minerva/Timeless). - Konfigurierbar über den CONFIG-Block. - Kein externes Framework nötig, nutzt jQuery (mit MediaWiki gebündelt).: (function ($, mw) { 'use strict'; // ---- CONFI…“ |
Admin (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
||
| Zeile 1: | Zeile 1: | ||
/* Das folgende JavaScript wird für alle Benutzer geladen. */ | /* Das folgende JavaScript wird für alle Benutzer geladen. */ | ||
/* ========================= | /* ========================= | ||
Site Announcement Modal | Site Announcement Modal + Image Preview | ||
========================= | ========================= */ | ||
*/ | |||
(function ($, mw) { | (function ($, mw) { | ||
'use strict'; | 'use strict'; | ||
var CONFIG = { | var CONFIG = { | ||
enabled: true, | enabled: true, | ||
id: ' | id: 'site_announcement_v2', // <- erhöht, damit die neue Version wieder angezeigt wird | ||
title: 'Ankündigung', | title: 'Ankündigung', | ||
html: | |||
html: '<p>🎉 Nächste Woche Wartungsfenster: <strong>Di, 10:00–11:00</strong>. | '<p>🎉 Nächste Woche Wartungsfenster: <strong>Di, 10:00–11:00</strong>. In dieser Zeit ist das Wiki nur eingeschränkt verfügbar.</p>' + | ||
'<div class="mw-site-announcement-actions">' + | |||
'<a href="https://s1.directupload.eu/images/250823/24cwslu3.png" target="_blank" rel="noopener" class="mw-ui-button">In neuem Tab öffnen</a>' + | |||
showOnNamespaces: 'all', | '<button type="button" class="mw-ui-button mw-ui-progressive" id="mw-site-announcement-more">Mehr Infos</button>' + | ||
onlyForLoggedOut: false, | '</div>', | ||
onlyForLoggedIn: false, | showOnNamespaces: 'all', | ||
startISO: null, | onlyForLoggedOut: false, | ||
endISO: null, | onlyForLoggedIn: false, | ||
dailyLimit: 1, | startISO: null, | ||
closeBehavesAsShown: true, | endISO: null, | ||
escToClose: true, | dailyLimit: 1, | ||
closeBehavesAsShown: true, | |||
escToClose: true, | |||
clickBackdropToClose: true, | |||
// Bildquelle für die Vorschau: | |||
imageSrc: 'https://s1.directupload.eu/images/250823/24cwslu3.png', | |||
imageAlt: 'Mehr Informationen' | |||
}; | }; | ||
if (!CONFIG.enabled) return; | if (!CONFIG.enabled) return; | ||
var isAnon = mw.config.get('wgUserName') === null; | var isAnon = mw.config.get('wgUserName') === null; | ||
if (CONFIG.onlyForLoggedOut && !isAnon) return; | if (CONFIG.onlyForLoggedOut && !isAnon) return; | ||
if (CONFIG.onlyForLoggedIn && isAnon) return; | if (CONFIG.onlyForLoggedIn && isAnon) return; | ||
var ns = mw.config.get('wgNamespaceNumber'); | var ns = mw.config.get('wgNamespaceNumber'); | ||
if (CONFIG.showOnNamespaces !== 'all' && Array.isArray(CONFIG.showOnNamespaces) && CONFIG.showOnNamespaces.indexOf(ns) === -1) { | if (CONFIG.showOnNamespaces !== 'all' && Array.isArray(CONFIG.showOnNamespaces) && CONFIG.showOnNamespaces.indexOf(ns) === -1) { | ||
| Zeile 49: | Zeile 43: | ||
} | } | ||
var now = new Date(); | var now = new Date(); | ||
if (CONFIG.startISO && now < new Date(CONFIG.startISO)) return; | if (CONFIG.startISO && now < new Date(CONFIG.startISO)) return; | ||
if (CONFIG.endISO && now > new Date(CONFIG.endISO)) return; | if (CONFIG.endISO && now > new Date(CONFIG.endISO)) return; | ||
var storage = (function () { | var storage = (function () { | ||
var prefix = 'mw_site_popup__'; | var prefix = 'mw_site_popup__'; | ||
function | function get(k){ try { return localStorage.getItem(prefix + k); } catch(e){ return null; } } | ||
function set(k,v){ try { localStorage.setItem(prefix + k, v); } catch(e){} } | |||
return { get:get, set:set }; | |||
function | |||
return { get: | |||
})(); | })(); | ||
var keyBase = CONFIG.id + (isAnon ? ':anon' : ':user'); | var keyBase = CONFIG.id + (isAnon ? ':anon' : ':user'); | ||
var lastShownKey = keyBase + ':lastShown'; | var lastShownKey = keyBase + ':lastShown'; | ||
var countKey = keyBase + ':count:'; | var countKey = keyBase + ':count:'; | ||
var todayStr = (function (d) { | var todayStr = (function (d){ return d.getFullYear() + '-' + String(d.getMonth()+1).padStart(2,'0') + '-' + String(d.getDate()).padStart(2,'0'); })(now); | ||
var lastShown = storage.get(lastShownKey); | var lastShown = storage.get(lastShownKey); | ||
var todayCount = parseInt(storage.get(countKey + todayStr) || '0', 10); | var todayCount = parseInt(storage.get(countKey + todayStr) || '0', 10); | ||
if (lastShown === todayStr && todayCount >= CONFIG.dailyLimit) return; | |||
function markShown(){ | |||
storage.set(lastShownKey, todayStr); | |||
storage.set(countKey + todayStr, String((todayCount || 0) + 1)); | |||
} | } | ||
function buildModal(bodyHtml, titleText){ | |||
function buildModal() { | var $overlay = $('<div>', { class: 'mw-site-announcement-overlay', tabindex: '-1', 'aria-hidden': 'true' }); | ||
var $overlay = $('<div>', { | var $dialog = $('<div>', { class: 'mw-site-announcement-modal', role: 'dialog', 'aria-modal': 'true', 'aria-labelledby': 'mw-site-announcement-title' }); | ||
var $dialog = $('<div>', { | |||
var $header = $('<div>', { class: 'mw-site-announcement-header' }) | var $header = $('<div>', { class: 'mw-site-announcement-header' }) | ||
.append($('<h2>', { id: 'mw-site-announcement-title', text: CONFIG.title })); | .append($('<h2>', { id: 'mw-site-announcement-title', text: titleText || CONFIG.title })); | ||
var $close = $('<button>', { type:'button', class:'mw-site-announcement-close', 'aria-label':'Schließen' }).text('×'); | |||
var $close = $('<button>', { | var $content = $('<div>', { class:'mw-site-announcement-content' }).html(bodyHtml); | ||
var $footer = $('<div>', { class:'mw-site-announcement-footer' }); | |||
var $ok = $('<button>', { type:'button', class:'mw-ui-button mw-ui-progressive' }).text('OK'); | |||
var $content = $('<div>', { class: 'mw-site-announcement-content' }).html( | |||
var $footer = $('<div>', { class: 'mw-site-announcement-footer' }); | |||
var $ok = $('<button>', { | |||
$header.append($close); | $header.append($close); | ||
$footer.append($ok); | $footer.append($ok); | ||
$dialog.append($header, $content, $footer); | $dialog.append($header, $content, $footer); | ||
return { | return { $overlay, $dialog, $close, $ok, $content }; | ||
} | } | ||
function | function openModal(bodyHtml, titleText, countAsShownOnOk = true, countAsShownOnClose = CONFIG.closeBehavesAsShown){ | ||
var parts = buildModal(bodyHtml, titleText); | |||
var $overlay = parts.$overlay, $dialog = parts.$dialog, $close = parts.$close, $ok = parts.$ok; | |||
var parts = buildModal(); | |||
var $overlay = parts.$overlay, $dialog = parts.$dialog, $ | |||
$('body').append($overlay, $dialog); | $('body').append($overlay, $dialog); | ||
var previouslyFocused = document.activeElement; | var previouslyFocused = document.activeElement; | ||
setTimeout(function () { | setTimeout(function(){ $dialog.attr('tabindex','-1').focus(); }, 0); | ||
function close() { | function close(count){ | ||
if ( | if (count) markShown(); | ||
$overlay.remove(); $dialog.remove(); | |||
$overlay.remove(); | |||
if (previouslyFocused && previouslyFocused.focus) previouslyFocused.focus(); | if (previouslyFocused && previouslyFocused.focus) previouslyFocused.focus(); | ||
$(document).off('keydown.mwSiteAnnouncement'); | $(document).off('keydown.mwSiteAnnouncement'); | ||
} | } | ||
$ok.on('click', function(){ close(countAsShownOnOk); }); | |||
$ok.on('click', function () { | $close.on('click', function(){ close(countAsShownOnClose); }); | ||
if (CONFIG.clickBackdropToClose) $overlay.on('click', function(){ close(countAsShownOnClose); }); | |||
$close.on('click', close); | |||
if (CONFIG.clickBackdropToClose) | |||
if (CONFIG.escToClose) { | if (CONFIG.escToClose) { | ||
$(document).on('keydown.mwSiteAnnouncement', function (e) { | $(document).on('keydown.mwSiteAnnouncement', function (e) { | ||
if (e.key === 'Escape') { | if (e.key === 'Escape') { e.preventDefault(); close(countAsShownOnClose); } | ||
}); | }); | ||
} | } | ||
return { $dialog, $overlay }; | |||
} | |||
function openImagePreview(){ | |||
var imgHtml = | |||
'<figure class="mw-site-announcement-figure">' + | |||
'<img src="'+ CONFIG.imageSrc +'" alt="'+ (CONFIG.imageAlt || '') +'" class="mw-site-announcement-img" loading="lazy">' + | |||
'<figcaption><a href="'+ CONFIG.imageSrc +'" target="_blank" rel="noopener">Bild in voller Größe öffnen</a></figcaption>' + | |||
'</figure>'; | |||
// Bildvorschau zählt nicht als "gesehen", damit man das Hauptmodal noch mit OK bestätigen kann: | |||
openModal(imgHtml, 'Mehr Infos', /*countAsShownOnOk*/ false, /*countAsShownOnClose*/ false); | |||
} | } | ||
$(function () { | $(function () { | ||
openModal(); | // Hauptmodal öffnen | ||
var main = openModal(CONFIG.html, CONFIG.title, /*countOnOk*/ true, /*countOnClose*/ CONFIG.closeBehavesAsShown); | |||
// „Mehr Infos“-Button (Bildvorschau) verdrahten | |||
main.$dialog.on('click', '#mw-site-announcement-more', function(){ | |||
openImagePreview(); | |||
}); | |||
}); | }); | ||
})(jQuery, mediaWiki); | })(jQuery, mediaWiki); | ||