MediaWiki:Common.js: Unterschied zwischen den Versionen

Keine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
Zeile 394: Zeile 394:
   }
   }


});
/* Fireworks Popup (v1) – once per day, canvas fireworks, motion-safe */
mw.loader.using(['mediawiki.util','jquery']).then(function(){
  (function($, mw){
    'use strict';
    var CONFIG = {
      enabled: true,
      id: 'fireworks_popup_v1',                // bei Änderungen erhöhen
      title: 'Neu: Abfüllungen bewerten 🎉',
      messageHTML:
        '<p>Ab sofort kannst du im Wiki <strong>jede Abfüllung bewerten</strong> – ' +
        'teile deine Meinung und hilf anderen bei der Auswahl!</p>',
      cta: { text: 'Jetzt bewerten', url: 'https://ados-wiki.de/index.php?title=Test2' }, // URL anpassen
      showOnNamespaces: 'all',                  // oder z. B. [0,4]
      dailyLimit: 1,
      escToClose: true,
      clickBackdropToClose: true
    };
    if (!CONFIG.enabled) return;
    // Namespace-Filter
    var ns = mw.config.get('wgNamespaceNumber');
    if (CONFIG.showOnNamespaces !== 'all' &&
        $.isArray(CONFIG.showOnNamespaces) &&
        $.inArray(ns, CONFIG.showOnNamespaces) === -1) return;
    // Einmal pro Tag
    var isAnon = (mw.config.get('wgUserName') === null);
    function g(k){ try{return localStorage.getItem(k);}catch(e){return null;} }
    function s(k,v){ try{localStorage.setItem(k,v);}catch(e){} }
    var key = 'popup_' + CONFIG.id + (isAnon?':anon':':user');
    var today = (function(d){return d.getFullYear()+'-'+('0'+(d.getMonth()+1)).slice(-2)+'-'+('0'+d.getDate()).slice(-2);})(new Date());
    if (g(key) === today) return;
    function markSeen(){ s(key, today); }
    $(function(){
      // Grundgerüst
      var $overlay = $('<div>', {'class':'mw-popup-overlay'});
      var $modal = $('<div>', {'class':'mw-popup-modal','role':'dialog','aria-modal':'true','aria-labelledby':'mw-fw-title'});
      // Feuerwerk-Canvas (liegt oben im Modal, hinter Text reservierter Bereich)
      var $fwWrap = $('<div>', {'class':'mw-fw-canvas-wrap'});
      var $canvas = $('<canvas>', {'class':'mw-fw-canvas', 'aria-hidden':'true'});
      $fwWrap.append($canvas);
      var $title = $('<h2>', { id: 'mw-fw-title' }).text(CONFIG.title);
      var $content = $('<div>', {'class':'mw-popup-content'}).html(CONFIG.messageHTML);
      var $buttons = $('<div>', {'class':'mw-popup-button-row'});
      var $ok = $('<button>', {'class':'mw-popup-close', type:'button'}).text('OK');
      $buttons.append($ok);
      if (CONFIG.cta && CONFIG.cta.url) {
        $buttons.append($('<a>', {
          'class':'mw-popup-wiki-button',
          'href': CONFIG.cta.url,
          'target':'_blank',
          'rel':'noopener'
        }).text(CONFIG.cta.text || 'Mehr'));
      }
      $modal.append($fwWrap, $title, $content, $buttons);
      $('body').append($overlay, $modal);
      // Fokus
      setTimeout(function(){ try{$modal.attr('tabindex','-1').focus();}catch(e){} }, 0);
      function close(){
        stopFireworks();
        markSeen();
        $overlay.remove(); $modal.remove();
        $(document).off('keydown.mwfw');
      }
      $ok.on('click', close);
      if (CONFIG.clickBackdropToClose) $overlay.on('click', close);
      if (CONFIG.escToClose) {
        $(document).on('keydown.mwfw', function(e){
          var k = e.key || e.keyCode;
          if (k==='Escape' || k==='Esc' || k===27){ e.preventDefault(); close(); }
        });
      }
      // ==== Fireworks (Canvas) ====
      var canvas = $canvas[0], ctx = canvas.getContext('2d');
      var dpr = Math.max(1, window.devicePixelRatio || 1);
      var w=0,h=0, raf=null, particles=[], bursts=[];
      var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
      function resize(){
        var rect = $fwWrap[0].getBoundingClientRect();
        w = Math.floor(rect.width * dpr);
        h = Math.floor(rect.height * dpr);
        canvas.width = w; canvas.height = h;
        canvas.style.width = rect.width+'px';
        canvas.style.height = rect.height+'px';
      }
      function rand(min,max){ return Math.random()*(max-min)+min; }
      function hsla(h,s,l,a){ return 'hsla('+h+','+s+'%,'+l+'%,'+a+')'; }
      function spawnBurst(x,y){
        var hue = Math.floor(rand(0,360));
        for (var i=0;i<80;i++){
          var angle = rand(0, Math.PI*2);
          var speed = rand(1.2, 3.2);
          particles.push({
            x:x, y:y,
            vx: Math.cos(angle)*speed,
            vy: Math.sin(angle)*speed,
            life: rand(45, 80),
            age: 0,
            hue: hue + rand(-15,15),
          });
        }
      }
      function tick(){
        ctx.clearRect(0,0,w,h);
        // leichte Verdunkelung für Nachleuchten
        ctx.globalCompositeOperation = 'source-over';
        ctx.fillStyle = 'rgba(0,0,0,0.08)';
        ctx.fillRect(0,0,w,h);
        ctx.globalCompositeOperation = 'lighter';
        var next = [];
        for (var i=0;i<particles.length;i++){
          var p = particles[i];
          p.age++;
          // Schwerkraft + Dämpfung
          p.vy += 0.02;
          p.vx *= 0.99; p.vy *= 0.99;
          p.x += p.vx*dpr; p.y += p.vy*dpr;
          var alpha = Math.max(0, 1 - p.age/p.life);
          if (alpha > 0){
            ctx.beginPath();
            ctx.fillStyle = hsla(p.hue, 100, 60, alpha);
            ctx.arc(p.x, p.y, Math.max(0.5, 2*alpha), 0, Math.PI*2);
            ctx.fill();
            next.push(p);
          }
        }
        particles = next;
        // regelmäßig neue Bursts
        if (Math.random() < 0.08) {
          var bx = rand(w*0.15, w*0.85);
          var by = rand(h*0.2,  h*0.6);
          spawnBurst(bx, by);
        }
        raf = requestAnimationFrame(tick);
      }
      function startFireworks(){
        if (reduceMotion) return; // respektiert Nutzerpräferenz
        resize();
        // Initial 2 Bursts
        spawnBurst(w*0.3, h*0.45);
        spawnBurst(w*0.7, h*0.35);
        if (!raf) raf = requestAnimationFrame(tick);
        window.addEventListener('resize', resize);
      }
      function stopFireworks(){
        if (raf){ cancelAnimationFrame(raf); raf=null; }
        window.removeEventListener('resize', resize);
      }
      startFireworks();
      // Direkt als gesehen markieren, damit reload am selben Tag nicht neu zeigt
      markSeen();
    });
  })(jQuery, mw);
});
});