MediaWiki:Common.js

Aus Rettungsdienst-Wiki
Zur Navigation springen Zur Suche springen

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
  • Internet Explorer/Edge: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
  • Opera: Strg+F5
/* global mw, $ */
(function () {
  'use strict';

  $.when( mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ] ), $.ready ).then( function () {

    // 1) Referenz-Portlet finden (Werkzeuge = p-tb). Daran hängen wir unseren Block direkt DARUNTER an.
    var tools = document.getElementById('p-tb') || document.getElementById('p-navigation');
    if ( !tools ) {
      console.warn('[NewPages] Referenz-Portlet nicht gefunden.');
      return;
    }

    // 2) Eigenen Portlet-Block erstellen – Klassen/Struktur von bestehendem Portlet ableiten
    var block = document.createElement('div');
    block.id = 'p-newpages';
    // Klassen vom Werkzeuge-Portlet übernehmen (wirkt in Timeless/Vector/MonoBook sauber)
    block.className = tools.className || 'mw-portlet';

    // passende Überschrift (h3 oder h2 – je nach Skin) ermitteln
    var headingTag = (tools.querySelector('h3,h2') || { tagName: 'H3' }).tagName;
    var heading = document.createElement(headingTag);
    heading.textContent = 'Neueste Beiträge';

    // Body + UL wie bei anderen Portlets
    var body = document.createElement('div');
    body.className = 'body';

    var list = document.createElement('ul');

    body.appendChild(list);
    block.appendChild(heading);
    block.appendChild(body);

    // Block direkt UNTERHALB von "Werkzeuge" einfügen
    if (tools.insertAdjacentElement) {
      tools.insertAdjacentElement('afterend', block);
    } else if (tools.parentNode) {
      tools.parentNode.insertBefore(block, tools.nextSibling);
    }

    // 3) Einträge via API laden
    var api = new mw.Api();
    api.get({
      action: 'query',
      list: 'recentchanges',
      rctype: 'new',
      rcprop: 'title|timestamp',
      rcnamespace: 0,            // nur Artikel
      rcshow: '!bot|!redirect',  // Bots & Weiterleitungen ausblenden
      rclimit: 3,
      format: 'json'
    }).done(function (data) {
      var items = (data.query && data.query.recentchanges) || [];

      // Helper: <li><a/></li> hinzufügen
      function addItem(href, text, title) {
        var li = document.createElement('li');
        var a = document.createElement('a');
        a.href = href;
        a.textContent = text;
        if (title) a.title = title;
        li.appendChild(a);
        list.appendChild(li);
      }

      if (!items.length) {
        addItem(mw.util.getUrl('Special:NewPages'), 'Keine neuen Seiten', 'Zur vollständigen Liste');
        return;
      }

      for (var i = 0; i < items.length; i++) {
        var rc = items[i];
        var href = mw.util.getUrl(rc.title);
        var tip  = new Date(rc.timestamp).toLocaleString('de-DE', { dateStyle: 'medium', timeStyle: 'short' });
        addItem(href, rc.title, tip);
      }

      // Abschluss-Link
      addItem(mw.util.getUrl('Special:NewPages'), 'Alle neuen Seiten →', 'Zur vollständigen Liste');
    }).fail(function (err) {
      console.error('[NewPages] API-Fehler:', err);
      var li = document.createElement('li');
      li.textContent = 'Fehler beim Laden';
      list.appendChild(li);
    });
  });
})();
/* global mw, $ */
(function () {
  'use strict';
  $.when( $.ready ).then(function () {

    // 1) Mögliche Einfügepunkte (Timeless/Vector/MonoBook)
    var content =
      document.getElementById('mw-content-text') ||
      document.getElementById('mw-content') ||
      document.getElementById('bodyContent') ||
      document.getElementById('content');

    if (!content) {
      console.warn('[ad-box] Kein Content-Container gefunden.');
      return;
    }

    // Doppelt vermeiden
    if (document.getElementById('ad-box')) {
      console.log('[ad-box] existiert bereits');
      return;
    }

    // 2) Box bauen
    var box = document.createElement('aside');
    box.id = 'ad-box';
    box.setAttribute('role','complementary');
    box.setAttribute('aria-label','Werbung');

    // Notfall-Styles, falls Common.css noch nicht greift (damit du es SOFORT siehst)
    box.style.cssText = 'float:right;width:300px;margin:0 0 1rem 1rem;background:#fffef7;border:1px solid #e5dfb3;border-radius:6px;box-shadow:0 1px 3px rgba(0,0,0,.06);font-size:90%;';

    var header = document.createElement('div');
    header.className = 'ad-header';
    header.innerHTML = '<span class="ad-badge" style="background:#ffea9e;border:1px solid #e0c200;padding:2px 6px;border-radius:4px;font-weight:700;text-transform:uppercase;">Anzeige</span> <span style="font-weight:700;margin-left:.5em;">Unterstütze dieses Wiki</span>';

    var body = document.createElement('div');
    body.className = 'ad-body';
    body.style.padding = '.6em .8em';

    // 3) Amazon-URL dynamisch (Spamfilter umgehen)
    var amazonHost  = 'amazon.' + 'de';
    var amazonBase  = 'https://www.' + amazonHost + '/';
    var partnerTag  = 'rettungsdie00-21'; // <-- anpassen

    var u = new URL(amazonBase);
    u.searchParams.set('tag', partnerTag);
    var amazonUrl = u.toString();

    // 4) Inhalt
    var html = '' +
      '<ul style="list-style:none;margin:.2em 0;padding:0">' +
      '  <li style="margin:.35em 0"><a href="' + amazonUrl + '" target="_blank" rel="nofollow sponsored noopener noreferrer">Bei Amazon einkaufen (Affiliate)</a></li>' +
      '  <li style="margin:.35em 0"><a href="https://www.paypal.me/rettungsdienstblog" target="_blank" rel="nofollow noopener noreferrer">PayPal – jetzt unterstützen</a></li>' +
      '  <li style="margin:.35em 0"><a href="/index.php?title=Spezial:Zufällige_Seite">Zufälliger Artikel →</a></li>' +
      '</ul>' +
      '<div style="font-size:85%; color:#555; margin-top:.5em;">' +
      '  * Als Amazon-Partner verdienen wir an qualifizierten Verkäufen.' +
      '</div>';

    body.innerHTML = html;
    box.appendChild(header);
    box.appendChild(body);

    // 5) Einfügen – zuerst im Content oben
    try {
      content.insertBefore(box, content.firstChild);
      console.log('[ad-box] eingefügt in', content.id || content.className);
    } catch (e) {
      console.warn('[ad-box] insertBefore fehlgeschlagen, versuche Fallback:', e);
      (content.appendChild || function(){ })(box);
    }

    // 6) Hard-Check: Wenn du ihn immer noch nicht siehst, als Test FIXIERT rechts oben einblenden
    //    Kommentiere die nächsten 5 Zeilen EIN, um zu testen:
    /*
    box.style.position = 'fixed';
    box.style.right = '1rem';
    box.style.top = '6rem';
    box.style.zIndex = 1000;
    console.log('[ad-box] testweise fixed positioniert');
    */
  });
})();
/* global mw, $ */
(function () {
  'use strict';
  $.when($.ready).then(function () {

    // Funktion, um festzustellen, ob Adblocker aktiv ist
    function detectAdblocker(callback) {
      var bait = document.createElement('div');
      bait.className = 'adsbox ad-banner ad-unit text-ad'; // typische Adblocker-Keywords
      bait.style.cssText = 'height:1px; width:1px; position:absolute; left:-9999px;';
      document.body.appendChild(bait);
      window.setTimeout(function () {
        var blocked = !bait.offsetHeight || !bait.clientHeight;
        document.body.removeChild(bait);
        callback(blocked);
      }, 300);
    }

    function showAdblockNotice() {
      if (document.getElementById('adblock-hinweis')) return;

      var div = document.createElement('div');
      div.id = 'adblock-hinweis';
      div.innerHTML =
        '<button id="adblock-close">×</button>' +
        '<strong>Hinweis:</strong> Wir finanzieren dieses Wiki durch Affiliate-Links und freiwillige Unterstützung. ' +
        'Bitte deaktiviere deinen Adblocker für <b>' + window.location.hostname + '</b>, um uns zu unterstützen. ❤️';

      document.body.appendChild(div);
      div.style.display = 'block';

      document.getElementById('adblock-close').onclick = function () {
        div.remove();
      };
    }

    // Nur zeigen, wenn Adblocker erkannt wird
    detectAdblocker(function (isBlocked) {
      if (isBlocked) {
        // Optional: Nur einmal pro Nutzer (mit LocalStorage)
        if (!localStorage.getItem('adblock_notice_shown')) {
          showAdblockNotice();
          localStorage.setItem('adblock_notice_shown', 'yes');
        }
      }
    });
  });
})();
/* global mw, $ */
(function () {
  'use strict';
  $.when($.ready).then(function () {

    var STORAGE_KEY = 'wiki_consent_v1';
    var defaults = {
      functional: true,   // technisch notwendig (immer an, gesperrt)
      analytics: false,   // z.B. Matomo/GA – optional
      media: false,       // z.B. YouTube/Maps – optional
      marketing: false    // z.B. Ads/Remarketing – optional
    };

    // ---- Helpers ----
    function loadState() {
      try {
        var raw = localStorage.getItem(STORAGE_KEY);
        if (!raw) return null;
        var obj = JSON.parse(raw);
        // safety: ensure all keys exist
        for (var k in defaults) if (!(k in obj)) obj[k] = defaults[k];
        return obj;
      } catch(e) { return null; }
    }
    function saveState(state) {
      localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
      window.wikiConsent = state; // global verfügbar
    }
    function ensureState() {
      var s = loadState();
      if (!s) { window.wikiConsent = defaults; return null; }
      window.wikiConsent = s;
      return s;
    }
    function createEl(tag, attrs, html) {
      var el = document.createElement(tag);
      if (attrs) for (var k in attrs) el.setAttribute(k, attrs[k]);
      if (html != null) el.innerHTML = html;
      return el;
    }

    // ---- UI: Banner ----
    function showBar() {
      if (document.getElementById('consent-bar')) return;
      var bar = createEl('div', { id: 'consent-bar' },
        '<div class="inner">' +
          '<div class="text">Wir verwenden <b>technisch notwendige Cookies</b> und – nach deiner Zustimmung – ' +
          'optional <b>Analyse</b> und <b>externe Medien</b>. ' +
          '<a href="/index.php?title=Datenschutz">Mehr erfahren</a></div>' +
          '<div class="btn-group">' +
            '<button class="btn secondary" id="consent-customize">Auswahl</button>' +
            '<button class="btn" id="consent-accept">Alle akzeptieren</button>' +
          '</div>' +
        '</div>'
      );
      document.body.appendChild(bar);
      bar.style.display = 'block';
      document.getElementById('consent-customize').onclick = openModal;
      document.getElementById('consent-accept').onclick = function () {
        var all = { functional: true, analytics: true, media: true, marketing: true };
        saveState(all);
        bar.remove();
        applyConsent(all);
      };
    }

    // ---- UI: Modal ----
    function openModal() {
      if (document.getElementById('consent-modal')) return;
      var s = loadState() || defaults;

      var modal = createEl('div', { id: 'consent-modal' });
      var html =
        '<div class="dialog">' +
          '<div class="head"><div><b>Datenschutz-Einstellungen</b></div>' +
          '<div><span class="badge">DSGVO</span></div></div>' +
          '<div class="body">' +
            row('Funktional', 'functional', s.functional, 'Erforderlich für Login, Sitzung, Seitendarstellung. (immer aktiv)', true) +
            row('Analyse', 'analytics', s.analytics, 'Anonyme Statistiken zur Verbesserung (z. B. Matomo/GA).') +
            row('Externe Medien', 'media', s.media, 'Einbettungen wie YouTube, Karten, Social-Posts.') +
            row('Marketing', 'marketing', s.marketing, 'Optionale Marketing-/Affiliate-Skripte.') +
          '</div>' +
          '<div class="foot">' +
            '<button class="btn secondary" id="consent-cancel">Abbrechen</button>' +
            '<button class="btn" id="consent-save">Auswahl speichern</button>' +
          '</div>' +
        '</div>';
      modal.innerHTML = html;
      document.body.appendChild(modal);
      modal.style.display = 'flex';

      document.getElementById('consent-cancel').onclick = function () { modal.remove(); };

      document.getElementById('consent-save').onclick = function () {
        var state = {
          functional: true,
          analytics: !!document.getElementById('consent-analytics').checked,
          media: !!document.getElementById('consent-media').checked,
          marketing: !!document.getElementById('consent-marketing').checked
        };
        saveState(state);
        modal.remove();
        var bar = document.getElementById('consent-bar'); if (bar) bar.remove();
        applyConsent(state);
      };

      function row(label, key, checked, hint, locked) {
        var disabled = locked ? ' disabled' : '';
        var isChecked = checked ? ' checked' : '';
        var id = 'consent-' + key;
        return '' +
          '<div class="row">' +
            '<div>' +
              '<div class="name">' + label + (locked ? ' <span class="badge">immer aktiv</span>' : '') + '</div>' +
              '<div class="hint">' + hint + '</div>' +
            '</div>' +
            '<label class="switch" for="' + id + '">' +
              '<input type="checkbox" id="' + id + '"' + isChecked + disabled + '>' +
              '<span class="slider"></span>' +
            '</label>' +
          '</div>';
      }
    }

    // ---- Hooks: Lade nur, wenn erlaubt ----
    function applyConsent(state) {
      // Beispiel: Analytics (Matomo/GA) – lade NUR bei Zustimmung
      if (state.analytics) {
        // loadAnalytics(); // hier deine Analytics-Init-Funktion aufrufen
      }
      // Beispiel: Externe Medien – ersetze Platzhalter durch Iframes
      if (state.media) {
        enableEmbeds();
      }
      // Beispiel: Marketing (derzeit nicht genutzt)
      if (state.marketing) {
        // loadMarketing(); // falls ihr mal was braucht
      }
    }

    // ---- Externe Einbettungen on-demand (Platzhalter -> echte Iframes) ----
    function enableEmbeds() {
      var placeholders = document.querySelectorAll('[data-embed-src]');
      for (var i = 0; i < placeholders.length; i++) {
        var ph = placeholders[i];
        var src = ph.getAttribute('data-embed-src');
        var iframe = document.createElement('iframe');
        iframe.src = src; iframe.width = ph.getAttribute('data-embed-width') || '560';
        iframe.height = ph.getAttribute('data-embed-height') || '315';
        iframe.allowFullscreen = true;
        iframe.loading = 'lazy';
        ph.parentNode.replaceChild(iframe, ph);
      }
    }

    // ---- Footer-Link „Cookie-Einstellungen“ (optional) ----
    // Füge irgendwo auf einer Seite <span class="cookie-settings-link" id="cookie-settings-open">Cookie-Einstellungen</span> ein
    var settingsLink = document.getElementById('cookie-settings-open');
    if (settingsLink) settingsLink.addEventListener('click', function () { openModal(); });

    // ---- Init: Zustand laden/anzeigen ----
    var current = ensureState();
    if (!current) {
      // keine Entscheidung -> Banner zeigen
      showBar();
    } else {
      applyConsent(current);
    }
  });
})();