MediaWiki:Common.js

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Hinweis: Leeren Sie nach dem Speichern 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: Strg+F5 drücken oder Strg drücken und gleichzeitig Aktualisieren anklicken
  • Opera: Extras → Internetspuren löschen … → Individuelle Auswahl → Den kompletten Cache löschen
if (localStorage && localStorage.getItem('common.js.debugger')) { /* sorry, sonst peil ich gar nichts mehr */
  debugger;
}
/* Link zu utrace für Bürokraten */

if (mw.config.exists('wgUserGroups') && mw.config.get('wgUserGroups').indexOf('bureaucrat') > -1) {
  $('.mw-anonuserlink').each(function() {
    $(this).after(" [<a href='http://www.utrace.de/?query=" + $( this ).text() + "'>utrace</a>] ");
  });
}

/* Links neben Überschriften.
 * Ein <span id=...> in der Überschrift überschreibt die Mediawiki-ID!
*/
if(location.pathname != '/index.php' && location.pathname != '/wiki/Startseite') {
  $(".mw-headline").each(function(){
    var $explicitId = $("span[id]", this);
    var href = location.pathname + "#" + ($explicitId.length > 0 ? $explicitId[0].id : this.id);
    $(this).after("<a href='" + href +"' class='locale-anchor'><span>" + href + "</span></a>");
  })
  $("#firstHeading").append("<a href='" + location.pathname +"' class='locale-anchor'><span>" + location.pathname + "</span></a>");
}

/* Links zum Forum */
var  returnto = window.location.href,
     headingelement = $('#firstHeading'), 
     heading =  $('#firstHeading > .locale-anchor > span').text(),
     allowedtags = ["css", "html", "javascript", "php", "webserver"],
     url = "https://forum.selfhtml.org/self/new",
     parameters = {};

if(heading) {
   heading = heading.trim();
   var headingparts = heading.split("/");
   var prob_url = "https://wiki.selfhtml.org" + heading;

   // for(var i = 0; i < headingparts.length; ++i) {
   //   prob_url += "/" + encodeURIComponent(headingparts[i]);
   // }

   parameters['message[problematic_site]'] = prob_url;

   if(headingparts.length > 2) {
     var subject = "Frage zum Wiki-Artikel „" + headingparts[headingparts.length-1] + "“";
     var tag = headingparts[2].toLowerCase();

     parameters['message[tags][]'] = ['frage zum wiki'];

     if(allowedtags.indexOf(tag) != -1) {
       parameters['message[tags][]'].push(tag);
     }

     parameters['message[subject]'] = subject;

     url += "?" + $.param(parameters);
   }

   headingelement.append("<div id='dokuwiki__pagetools'><div class='tools'><ul><li class='forum'><a href='" + url + "' title='Frage im SELFHTML-Forum stellen‽'>Frage im SELFHTML-<br>Forum stellen‽</a></li><li class='top'><a title='nach oben' href='#'>nach oben</href></li><li class='last_changes'><a title='Liste der letzten Änderungen' href='/wiki/Spezial:Letzte_%C3%84nderungen'>letzte Änderungen</a></li></ul></div></div>");

if ($("#pt-anonlogin, #pt-login").length == 1 && $("#dokuwiki__pagetools").length == 1) 
{
  if (returnto.indexOf("/wiki/") > -1) {
    returnto = returnto.replace(window.location.protocol+"//"+window.location.host+"/wiki/","");
  }
  else {
    returnto = returnto.replace(window.location.protocol+"//"+window.location.host+"/index.php?title=","");
  }

  $("#dokuwiki__pagetools ul").append("<li class='anmelden' title='anmelden'><a href='/index.php?title=Spezial:Anmelden&returnto=" + returnto + "'>anmelden</a></li>");
}


$('.top > a').click(function(ev) { 

  $('html, body').animate({
      scrollTop: $('html').offset().top
  }, 100);
  
  ev.preventDefault();

  $(this).blur();

});


}
/* Umsortieren der Navigation */
$('#ca-edit').appendTo('#p-namespaces > ul');

if (document.URL.indexOf('Spezial:') == -1) {

   $('#p-namespaces > ul').append("<li><span><a href='" + url + "' title='Frage im SELFHTML-Forum stellen‽'>Fragen</a></span></li>");

}
/* Umbennenen der Linktexte */
$('#ca-nstab-main a').text('Lesen');
$('#ca-talk a').text('Diskutieren');
$('#ca-edit a').text('Bearbeiten');

/* redundantes Lesen ausblenden */
$('#ca-view').css('display','none');

/* Placeholder im Suchfeld */
document.getElementById('searchInput').setAttribute('placeholder', 'Suchbegriff');

/* Das folgende JavaScript wird für alle Benutzer geladen. */

/* Edittools-Erweiterung auf mehrere Seiten mit Tabs / mw.util braucht Dependency */
mw.loader.using(["mediawiki.util"], function() {
  mw.loader.load(
    mw.util.getUrl( 'MediaWiki:Edittools.js', { action:'raw', ctype:'text/javascript' } ),
    'text/javascript'
  );
});

/* Overlay für Frickl-Funktionalität einrichten - IIFE
 * - Erzeugt Links zum Beispiel in einem Fiddle-ähnlichen Setup.
 * - Erzeugt Tabs für Quelltext und Vorschau (mit Beispielseite in einem iFrame).
 * - Erzeugt "Bearbeiten" Link für BeispielAdministratoren 
 */
(function setUpFrickl() {
  // IIFE in IIFE, um handleTabChange keinerlei Daten für eine Closure-Bildung anzubieten!
  (function capsulatedInit() {
    // Instrumentierung durch selfhtml.js.setupFrickl
    // - kein localStorage oder Schalter fehlt: 'true' setzen
    // - Wert ist 'false': Gar kein Setup
    // - Wert ist 'noadmin': BeispielAdmin deaktivieren
    // - Wert ist 'true': Normalverhalten
    const enableSwitch = ((localStorage && localStorage.getItem('selfhtml.js.setupFrickl')) || 'true').toLowerCase();
    if (enableSwitch == 'false') return;

    const isBeispielAdmin = checkIfBeispielAdmin();

    // Finde Ergebnisse der Vorlage Beispiel mit BeispielCode und hinterlegter zeige-URL
    if (Array.prototype.reduce.call(
                document.querySelectorAll('.vorlage_beispiel'),
                function(hasExample, beispiel, index) {
                   const tabList = attachFricklToExample(beispiel, (index+1).toString().padStart(4,'0'));
                   if (tabList === false) return hasExample;
                   if (tabList === true) return true;
    
                   // Click-Handler für die Tabs HIER einrichten um keine Riesen-Closure zu erzeugen
                   tabList.addEventListener("click", handleTabChange);
                   return true;
                },
                false)) {
      // Stylesheet für Frickl-Overlay nur ergänzen wenn auch nötig
      addFricklStyles();
    }

    function checkIfBeispielAdmin() {
      if (enableSwitch == 'noadmin') return false;
      const userGroups = mw.config.get('wgUserGroups');
      return userGroups && userGroups.includes('exampleadmin');
    }

    // Output der Beispiel-Vorlage für Frickl umbauen
    function attachFricklToExample(exampleBox, beispielNummer) {
   
      const exampleHeader = exampleBox.querySelector(".note-box-title"),
            exampleContent = exampleBox.querySelectorAll(".note-box-example-comment, .note-box-example-code, .note-box-example-wiki"),
            exampleLink   = exampleHeader && exampleHeader.querySelector(".beispiel_url");
      var   liveBox = exampleBox.querySelector(".live-view"),
            attachResult;
      
      // Wenn der Link existiert, existiert auch der Headerbereich
      if (!exampleLink)
        return false;
   
      const parsedUrl  = /^(?<path>.*\/)example.php(?<sample>\/.*)$/.exec(exampleLink.href);
      if (!parsedUrl)
        return false;
   
      exampleHeader.append(
        createLink("Ausprobieren", parsedUrl.groups.path + "frickl.php" + parsedUrl.groups.sample)
      );
      if (isBeispielAdmin) {
        exampleHeader.append(
          createLink("Bearbeiten", "/wiki" + parsedUrl.groups.sample + "?action=edit")
        );
      }
   
      // Example Link kann schon mal weg
      exampleLink.remove();
   
      if (exampleContent.length > 0 && !liveBox) {
        return createExampleWithSourceAndPreview(exampleBox, exampleHeader, exampleContent, parsedUrl);
      }
      if (liveBox) {  // .tabbed und .live-box vorbelegt
        createExamplePreview(exampleBox, liveBox, parsedUrl);
        return true;
      }
      return false;
    }

    function createExampleWithSourceAndPreview(exampleBox, exampleHeader, exampleContent, parsedUrl, beispielNummer) {
      // prepare heading for tabs
      exampleBox.classList.add("tabbed");
   
      const tabList = document.createElement("ul");
      tabList.setAttribute('role', 'tablist');
   
      const liveID = "Beispiel_" + beispielNummer,
            codeID = "Code-" + liveID,
            sourceTab = createTab('Quelltext', codeID, '/wiki' + parsedUrl.groups.sample),
            liveTab   = createTab('Vorschau' , liveID, parsedUrl[0]);
   
      tabList.append(sourceTab, liveTab);
      exampleHeader.append(tabList);
   
      const codeBox = createPanel(codeID),
            liveFrame = document.createElement("iframe"),
            liveBox = createPanel(liveID, liveFrame);
   
      liveBox.className = 'live-view';
      liveFrame.dataset.src = parsedUrl[0];
   
      exampleBox.append(codeBox, liveBox);
      // Example-Inhalt in den Example-Container verlegen
      exampleContent.forEach(function(ex) { codeBox.appendChild(ex); });
   
      // Quellcode-Tab aktivieren
      activateTab(exampleHeader.querySelector("#"+codeID));
   
      return tabList;
    }

    function createExamplePreview(exampleBox, liveBox, parsedUrl) {
      exampleBox.classList.add("tabbed");
      const liveFrame = document.createElement("iframe");
      liveFrame.src = parsedUrl[0];
      liveBox.append(liveFrame);
   
      if (exampleBox.dataset.vorschauHoehe && exampleBox.dataset.vorschauHoehe.trim()) {
        liveBox.style.setProperty('height', exampleBox.dataset.vorschauHoehe);
      }
    }

    function createTab(text, id, url) {
      const link = createLink(text, url);
      link.id = id;
      link.setAttribute('role', 'tab');
      const li = document.createElement("li");
      li.setAttribute('role', 'presentation');
      li.appendChild(link);
      return li;
    }

    function createPanel(refId, content) {
      const panel = document.createElement("div");
      panel.setAttribute('aria-labelledby', refId);
      if (content)
        panel.append(content)
      return panel;
    }

    function createLink(text, url) {
      const link = document.createElement("a");
      link.textContent = text;
      link.href = url;
      return link;
    }
  })();
  
  function handleTabChange(clickEvent) {
    const clickedLink = clickEvent.target;
    const clickedId = clickedLink && clickedLink.id;
    if (!clickedId || clickedLink.tagName != 'A') return;

    activateTab(clickedLink);

    if (clickEvent.detail < 2) {
      // single click: deactivate standard click behaviour for links
      clickEvent.preventDefault();
      clickEvent.stopPropagation();
      return false;
    }
  }

  function activateTab(tabLink) {
    const tabList = tabLink.closest("ul");
    const exampleBox = tabList.closest(".vorlage_beispiel");
      
    tabList
      .querySelectorAll("a[role=tab]")
      .forEach(function(link) { 
        const panel = exampleBox.querySelector('div[aria-labelledby='+link.id+']');
        panel.hidden = (link != tabLink);
        if (panel.hidden) {
          link.removeAttribute('aria-selected');
        }
        else {
          link.setAttribute('aria-selected', 'true');
          if (panel.classList.contains('live-view')) {
            const iframe = panel.querySelector("iframe");
            if (!iframe.src) {
              iframe.src = iframe.dataset.src;
            }
            if (exampleBox.dataset.vorschauHoehe) {
              panel.style.setProperty('height', exampleBox.dataset.vorschauHoehe);
            }
          }
        }
      });
  }

  function addFricklStyles() {
    // CSS nicht doppelt anhängen!
    if (document.querySelector("#frickl-styles")) return;

    const l = document.createElement("link");
    l.rel = "stylesheet";
    l.id = "frickl-styles";
    l.href = "/extensions/Selfhtml/css/frickl-overlay.css";

    document.head.appendChild(l);
  }
})();  /* Ende setupFrickl() IIFE */

/* SVG Preview PNGs durch ihre Originale ersetzen */
(function() {
  /* SVG Preview-PNGs lassen sich durch die Endung .svg.png im src Attribut erkennen */
  var i, source, thumbPos, svgPos,
      images = document.querySelectorAll("img[src$='.svg.png'][srcset]"),
      thumbPart = "/thumb/",
      svgPart = ".svg/";
  /*
   * Bild-URLs sehen aus wie https://.../images/thumb/5/53/Client_Server.svg/600px-Client_Server.svg.png
   * Daraus muss /thumb entfernt werden und alles hinter dem ersten ".svg/", inclusive des '/'.
   * Darüber hinaus muss dem img Element das srcset Attribut entnommen werden, das ist bei SVG nicht mehr nötig.
   */
  for (i=0; i<images.length; i++) {
    source    = images[i].src;
    thumbPos  = source.indexOf(thumbPart);
    svgPos    = source.indexOf(svgPart, thumbPos);
   
    if (thumbPos >= 0 && svgPos > thumbPos) {
      images[i].src = source.substring(0, thumbPos) 
                    + source.substring(thumbPos + thumbPart.length - 1, svgPos + svgPart.length - 1);
      images[i].removeAttribute("srcset");
    }
  }
})();

/* Vorlage:Verbergen */
   
var Verbergen = {
  toggle: function(what) {
    if (!$(what).hasClass('verbergen_schalter') || what.id.substr(0, 'verbergen_'.length) != 'verbergen_')
      return;
    var id = what.id.substr('verbergen_'.length);
    $('.verbergen_id_' + id).toggle();
  },
  showAll: function() {
    $('.verbergen_verborgen').show();
    $('.verbergen_gezeigt').hide();
  },
  hideAll: function() {
    $('.verbergen_verborgen').hide();
    $('.verbergen_gezeigt').show();
  },
  toggleAll: function() {
    $('.verbergen_verborgen').toggle();
    $('.verbergen_gezeigt').toggle();
  },
  span2a: function(toggle, onclickHandler) {
    var toggleLink = document.createElement('a');
    toggleLink.href = "?schalte";
    toggleLink.onclick = onclickHandler;
    toggleLink.className = toggle.className;
    if (toggle.id)
      toggleLink.id = toggle.id;
    toggleLink.innerHTML = toggle.innerHTML;
    if (toggle.style.cssText) toggleLink.style.cssText = toggle.style.cssText;
    else toggleLink.setAttribute('style', toggle.getAttribute('style'));
    toggle.parentNode.replaceChild(toggleLink, toggle);
  },
  setup: function() {
    $('.verbergen_schalter').each(function () {
      Verbergen.span2a(this, function() {Verbergen.toggle(this); return false;});
    });
    $('.verbergen_verborgen').hide();
    $('.verbergen_zeige_alles').each(function() {
      Verbergen.span2a(this, function() {Verbergen.showAll(); return false;});
    });
    $('.verbergen_verberge_alles').each(function () {
      Verbergen.span2a(this, function() {Verbergen.hideAll(); return false;});
    });
    $('.verbergen_schalte_alles').each(function () {
      Verbergen.span2a(this, function() {Verbergen.toggleAll(); return false;});
    });
  }
}; 
$(Verbergen.setup);

// Überschrift in Startseite ausblenden 

if (document.URL.indexOf('Startseite') > 0) {
  document.getElementById('firstHeading').style.display = 'none';
  document.getElementById('content').style.borderTop = 'none';
}

/* Helferlein einbinden, nur wenn 
 * - code mit class="helferlein" gesetzt ist
 * - kein IE vorliegt (der kennt .closest nicht)
 */
if (document.querySelector("code.helferlein") && HTMLElement.prototype.closest) {
  mw.loader.using(["mediawiki.util"], function() {
    mw.loader.load(
      mw.util.getUrl( 'MediaWiki:Helferlein.css', { action:'raw', ctype:'text/css' } ),
      'text/css'
    );
    mw.loader.load(
      mw.util.getUrl( 'MediaWiki:Helferlein.js', { action:'raw', ctype:'text/javascript' } ),
      'text/javascript'
    );
  });
}

(function() {
// Advent-Helper
   if (mw.config.get("wgAction").includes("protect")) return;  // Nicht für Lock/Unlock Seite!

   var seitenname = mw.config.get('wgPageName');      // Nur für Advent/yyyy/dd Seiten!
   var match = /^Advent\/(\d\d\d\d)\/(\d\d)$/i.exec(seitenname);
   if (!match) return;   // Kein relevanter page title

   var inhalt = document.getElementById("mw-content-text");        // Erwartete Seitenstruktur?
   var heading = inhalt.querySelector("h2");  
   if (inhalt == null || heading == null) return;

   var pageYear = parseInt(match[1]), pageDay = parseInt(match[2]),
       heute = new Date(), jahr = heute.getFullYear(), monat = heute.getMonth(), tag = heute.getDate();

   if (pageYear < jahr) return;                      // Älterer Kalender
   if (pageYear == jahr                              // Aktueller Kalender, Tag erreicht, nichts tun
       && monat == 11 && pageDay <= tag) return;

   // Benutzergruppen ermitteln - Sysop ist kein Weihnachtsmäuschen!
   mw.user.getGroups().then(function(groups) {
      if (groups.includes("sysop")) {
         heading.innerHTML += " - Pssst!";
         return;
      }
      // Kalender für Folgejahr oder Tag im akt. Kalender noch nicht erreicht
      inhalt.innerHTML = heading.outerHTML + "<p>Sei nicht so ein neugieriges <b>Weihnachtsmäuschen</b>!</p>";
   });
})();