ملاحظة: بعد النشر، أنت قد تحتاج إلى إفراغ الكاش الخاص بمتصفحك لرؤية التغييرات.

  • فايرفوكس / سافاري: أمسك Shift أثناء ضغط Reload، أو اضغط على إما Ctrl-F5 أو Ctrl-R (⌘-R على ماك)
  • جوجل كروم: اضغط Ctrl-Shift-R (⌘-Shift-R على ماك)
  • إنترنت إكسبلورر/إيدج: أمسك Ctrl أثناء ضغط Refresh، أو اضغط Ctrl-F5
  • أوبرا: اضغط Ctrl-F5.
//Dokumentation auf [[Benutzer:Schnark/js/jsmodules]] <nowiki>

/*global mw: true */
/*global jsmodules_init: true *///Abwärtskompatibilität
(function($){

var jsmodules = {
    version: 1.11,
/* Registrierte Module, Aufbau:
  '[[Benutzer:Schnark/js/modul.js]]' : {
    desc:      'Beschreibung',                          //Beschreibung
    needed:    function (ns, action) { return true; },  //Funktion, die abh. von Namensraum und Aktion angibt, ob das Modul gebraucht wird
    cache:     {
               standard: 'latest',                      //Standard-Cache-Methode
               stable: '123456789',                     //letzte stabile Version
               latest: '987654321',                     //letzte Version (muss nur inkrementiert werden)
               days:   2 },                             //Anzahl der Tage, die gecachet werden soll
    dynamical: false,                                   //dynamisches Laden möglich?
    depends:   ['[[...]]', '[[...]]'],                  //Module, die vorher geladen werden müssen

    after:     function () {},                          //Funktion, die nach dem Laden ausgeführt werden soll
    status:    {
               called: false,                           //jsmodules.load aufgerufen?
               loaded: false,                           //geladen?
               disabled: false,                         //per Cookie deaktiviert?
               depend: false,                           //wegen Abhängigkeit aufgerufen?
               dynamical: true                          //per Cookie aktiviert?
               }
   }
*/
 modules: {},

 cookie_name: 'jsmodules',
 cookie_ttl: 60, //Haltbarkeit des Cookies (Tage)
 default_cookie: '', //Standardwert, falls kein Cookie vorhanden

 //Hilfsvariablen
 ns: 0, action: '', //Namensraum, Aktion
 async: false, //falls Skripte asynchron geladen werden (FF 4 und andere)
 server: '', server_save: '', //Pfad zu index.php
 mylocation: '', //Pfad zu index.php der Definitionen
 init: function() {
       jsmodules.ns = mw.config.get('wgNamespaceNumber');
       jsmodules.action = mw.config.get('wgAction');
       if (jsmodules.action === 'purge') jsmodules.action = 'view'; //überflüssig (?)
       if (jsmodules.action === 'submit') jsmodules.action = 'edit';
       if (jsmodules.action === 'historysubmit') jsmodules.action = 'diff'; //überflüssig (?)
       if (jsmodules.action === 'view' && location.search.search(/[?&]diff=/) > -1) jsmodules.action = 'diff';
       //kopiert von mw.util.getParamValue
       if (jsmodules.action === 'view' || jsmodules.action === 'nosuchaction') {
          var m = /^[^#]*[&?]action=([^&#]*)/.exec(document.location.href);
          if (m && m.length > 1) {
             jsmodules.action = decodeURIComponent(m[1].replace(/\+/g, '%20'));
          }
       }
       jsmodules.server = mw.config.get('wgServer') + mw.config.get('wgScript');
       jsmodules.server_save = jsmodules.server;
       if (mw.config.get('wgServer').indexOf('localhost') > -1) {
          jsmodules.mylocation = jsmodules.server;
       } else {
          jsmodules.mylocation = '//fa.wikipedia.org/w/index.php';
       }
       jsmodules.async = (document.createElement('script').async === true);
       if (!jsmodules.async) { //HACK für FF3.6
          var oldmwloaderusing = mw.loader.using;
          mw.loader.using = function (d, r, e) {
             $(function(){
              oldmwloaderusing(d, r, e);
             });
          };
       }
       $(document).on('loadWikiScript', function (e, name, object) {
           jsmodules.after('[[' + name + ']]', object);
       });
 },

//Funktionen für Anwender
//registriert ein Modul
 register: function(name, desc, needed, cache, dynamical, depends) {
           if (name in jsmodules.modules) return;
           if (typeof desc !== 'string') desc = '(keine Beschreibung verfügbar)';
           if (typeof needed !== 'function') needed = function (/*ns, action*/) {return true;};
           if (typeof cache !== 'object') cache = {};
           if (typeof dynamical !== 'boolean') dynamical = true;
           if (typeof depends !== 'object') depends = [];
           jsmodules.modules[name] = {desc: desc, needed: needed, cache: cache, dynamical: dynamical, depends: depends,
                                      status: {called: false, loaded: false, disabled: false, depend: false, depend_plus: false, dynamical: true}};
 },
//fügt eine Überschrift ein
 heading_count: 0,
 heading: function(name) {
          jsmodules.modules['#' + (jsmodules.heading_count++)] = {desc: name, dynamical: false};
 },
//fügt eine Abhängigkeit hinzu
 addDepend: function(name, dep) {
            jsmodules.register(name);
            jsmodules.modules[name].depends.push(dep);
 },
//ändert die URL für lokale Skripte
//server: true für Skripte dort, wo auch Definitionen liegen, string für Pfad zu index.php
 local: function (server) {
        if (server === true) server = jsmodules.mylocation;
        if (typeof server !== 'string' || server === '') {
           jsmodules.server = jsmodules.server_save;
        } else {
           jsmodules.server = server;
        }
 },

//lädt ein Modul
/* options = {
    before: '[[...]]' oder function () {...},   //Skript oder Funktion für vorher
    after:  '[[...]]' oder function () {...},   //Skript oder Funktion für hinterher
    cache: [...],

    depend: 'wegen XXX geladen',                //Beschreibung einer Abhängigkeit 
    needed: true/false,                         //nur interne Zwecke (abhängige Module, die eigentlich nicht gebraucht werden)
    dynamical: true/false,                      //dynamisch geladen?
    dontdoit: true/false                        //true: nicht laden, sondern alle URLs zurückgeben
   }
Werte für cache:
 '123456789': diese Version
 'stable':    stabile Version
 'latest':    letzte Version
 'none':      kein Cache
 'time':      nach Zeitablauf
 'x days':    nach x Tagen
 'standard':  Standard Cache-Verhalten
*/
 load: function(name, options) {
       if (typeof options !== 'object') options = {};
       if (typeof options.cache === 'string') options.cache = [options.cache];
       if (typeof options.cache !== 'object') options.cache = [];
       if (typeof options.needed !== 'boolean') options.needed = true;
       if (typeof options.dynamical !== 'boolean') options.dynamical = false;

       jsmodules.register(name);  //evt. registrieren

       if (typeof options.depend === 'string') {
          if (jsmodules.modules[name].status.called && //schon vorher aufgerufen
             !jsmodules.modules[name].status.depend) jsmodules.modules[name].status.depend_plus = true;
          jsmodules.modules[name].desc += '<br />' + options.depend;
          jsmodules.modules[name].status.depend = true;
       }

       jsmodules.modules[name].status.called = true;
       jsmodules.modules[name].status.dynamical = jsmodules.modules[name].status.dynamical && options.dynamical;
       if (jsmodules.modules[name].status.loaded) return;

       options.needed = options.needed && jsmodules.modules[name].needed(jsmodules.ns, jsmodules.action);
       jsmodules.modules[name].status.disabled = jsmodules.disabled(name);
       options.needed = options.needed && !jsmodules.modules[name].status.disabled;
       if (jsmodules.modules[name].status.disabled) return;

       var i, cache = [], script, scripts = [];
       for (i = 0; i < options.cache.length; i++)
           if (!options.cache[i].match(/\d$/)) cache.push(options.cache[i]); //alle Versionsnummern entfernen

       for (i = 0; i < jsmodules.modules[name].depends.length; i++) {//abhängige Module laden
           script = jsmodules.load(jsmodules.modules[name].depends[i],
                       {depend: '(wegen ' + name + ' geladen)', needed: options.needed, cache: cache, dontdoit: true});
           if (typeof script === 'object') scripts = scripts.concat(script);
       }

       if (!options.needed) return;
       jsmodules.modules[name].status.loaded = true;

       if (typeof options.before === 'function') options.before(); //vorher
       if (typeof options.before === 'string') {
          script = jsmodules.load(options.before, {depend: '(vor ' + name + ' geladen)', cache: cache, dontdoit: true});
          if (typeof script === 'object') scripts = scripts.concat(script);
       }

       if (!(mw.util.getParamValue('action') === 'submit' && //Skript in Vorschau wird direkt eingebunden, daher hier überspringen
           '[[' + mw.config.get('wgPageName').replace(/_/g, ' ') + ']]' === name.replace(/_/g, ' ')))
          scripts.push(jsmodules.fetch(name, options.cache, jsmodules.modules[name].cache));

       if (typeof options.after === 'function') jsmodules.modules[name].after = options.after; //hinterher
       if (typeof options.after === 'string') {
          script = jsmodules.load(options.after, {depend: '(nach ' + name + ' geladen)', cache: cache, dontdoit: true});
          if (typeof script === 'object') scripts = scripts.concat(script);
       }
       if (options.dontdoit) {
          return scripts;
       } else {
          jsmodules.really_load(scripts);
       }
 },

//interne Funktionen
//prüft, ob ein Modul per Cookie deaktiviert ist
 disabled: function(name) {
           var c = $.cookie(jsmodules.cookie_name) || jsmodules.default_cookie;
           return (c.indexOf(name + '0') !== -1);
 },
//ermittelt URL eines Skripts
 fetch: function(name, ucache, mcache) {
        var now = new Date(); var time = now.getTime();
        var cache = '';
        if (typeof mcache.standard !== 'string') mcache.standard = 'latest'; //Standard: latest
        ucache.push(mcache.standard);
        for (var i = 0; i < ucache.length; i++) {
            var c = ucache[i];
            if (c === 'stable' && typeof mcache.stable === 'string') {cache = 'oldid=' + mcache.stable; break;}
            if (c === 'latest' && typeof mcache.latest === 'string') {cache = mcache.latest; break;}
            if (c === 'none') {cache = String(time); break;}
            if (c === 'standard') {cache = ''; break;}
            if (c === 'time' && typeof mcache.days === 'number') {cache = String(Math.floor(time/(1000*60*60*24*mcache.days))); break;}
            if (c.indexOf('day') > 0) {cache = String(Math.floor(time/(1000*60*60*24*parseInt(c, 10)))); break;}
            if (c.match(/^\d+$/)) {cache = 'oldid=' + c; break;}
        }
        var url = '';
        if (name.indexOf('[[') === 0) {
           var re = /\[\[:([\-a-z:]*):/;
           url = jsmodules.path(re.exec(name)) + '?title=' +
                 encodeURIComponent(name.replace(re, '').replace(/[\[\]]/g, '').replace(/ /g,'_')).replace(/%2F/ig,'/').replace(/%3A/ig,':') +
                 '&action=raw&ctype=text/javascript';
        } else {
           url = name.replace(/[\[\]]/g, '');
        }
        if (cache !== '') url += (url.indexOf('?') > -1) ? '&' : '?';
        url += cache;
        return url;
        },
//lädt Skripte in richtiger Reihenfolge
  really_load: function(scripts) {
               if (scripts.length === 1) {
                  mw.loader.load(scripts[0]);
                  return;
               }
               if (!jsmodules.async) {
                  for (var i = 0; i < scripts.length; i++)
                      mw.loader.load(scripts[i]);
                  return;
               }

               var next = 0, all = scripts.length,
                   load_next = function () {
                               if (next === all) return;
                               var src = scripts[next++];

                               //aus mediawiki.js kopiert: addScript, siehe auch Kommentare dort
                               var done = false, script, head;
                               script = document.createElement('script');
                               script.setAttribute('src', src);
                               script.setAttribute('type', 'text/javascript');
                               script.onload = script.onreadystatechange = function() {
                                  if (!done && (!script.readyState || /loaded|complete/.test(script.readyState))) {
                                     done = true;
                                     load_next();
                                  try {
                                      script.onload = script.onreadystatechange = null;
                                      if (script.parentNode) {
                                         script.parentNode.removeChild(script);
                                      }
                                      script = undefined;
                                  } catch (e) { }
                                  }
                               };
                               if (window.opera) {
                                  $(function() { document.body.appendChild(script); });
                               } else {
                                  head = document.getElementsByTagName('head')[0];
                                  (document.body || head).appendChild(script);
                               }
                               //$.ajax({type: 'get', url: url, data: undefined, success: load_next, dataType: 'script', cache: true});
                   };
               load_next();
               },
//bestimmt einen Pfad mittels Interwikilinks interwiki: null oder ['x:y:z']
  path: function(interwiki) {
        if (interwiki === null) return jsmodules.server;
        var iw = interwiki[1].split(':');
        var projects = {'b': 'wikibooks', 'commons': '', 'meta': '', 'n': 'wikinews', 'q': 'wikiquote', 's': 'wikisource', 'v': 'wikiversity', 'w': 'wikipedia', 'wikt': 'wiktionary'};
        var lang = 'en', project = 'wikipedia';
        var treffer = /([^\/.]*)\.[^.]*\.org/.exec(jsmodules.server);
        if (treffer) {
           lang = treffer[1] || 'en'; project = treffer[2] || 'wikipedia';
        }
        if (project === 'wikimedia') {
           lang = 'en'; project = 'wikipedia';
        }
        for (var i = 0; i < iw.length; i++) {
            if (iw[i] in projects) {
               project = iw[i];
            } else {
               lang = iw[i];
            }
        }
        if (project in projects) {
           if (projects[project] === '') {
              lang = project;
              project = 'wikimedia';
           } else {
              project = projects[project];
           }
        }
        return '//' + lang + '.' + project + '.org/w/index.php';
 },
//lädt automatisch
 auto: function() {
       jsmodules.local(true); //lokale URL
       var c = $.cookie(jsmodules.cookie_name) || jsmodules.default_cookie;
       $.cookie(jsmodules.cookie_name, c, { expires: jsmodules.cookie_ttl, path: '/' });
       for (var name in jsmodules.modules) {
           if (jsmodules.modules[name].dynamical && !jsmodules.modules[name].status.loaded && c.indexOf(name + '1') > -1)
              jsmodules.load(name, {dynamical: true});
       }
       jsmodules.local();
 },
 run: function() {
      $(document).trigger('jsmodulesRun', [jsmodules]);
      if (typeof jsmodules_init === 'function') jsmodules_init(); //Abwärtskompatibilität
      jsmodules.auto();
      if (!jsmodules.modulverwaltung.disabled) $(jsmodules.modulverwaltung.init);
 },
//lädt die Definitionen
 importdef: function() {
            var now = new Date(); var time = now.getTime();
            var url = jsmodules.mylocation + '?title=Benutzer:Schnark/js/modules.js&action=raw&ctype=text/javascript&' +
                       String(Math.floor(time/(1000*60*60*24)));
            $(document).on('jsmodulesDef', function (e, f) {
                f(jsmodules);
            });
            mw.loader.load(url);
 },
//führt eine Funktion nach dem Laden des Skripts aus
 after: function(name, object) {
        if (typeof jsmodules.modules[name] === 'object' && typeof jsmodules.modules[name].after === 'function') jsmodules.modules[name].after(object);
 },

//Modulverwaltung per Cookie
modulverwaltung: {
//Symbole
 img_ja: '<img src="//upload.wikimedia.org/wikipedia/commons/thumb/8/80/Symbol_OK.svg/16px-Symbol_OK.svg.png" width="16" height="16" alt="Ja" title="Ja" />',
 img_nein: '<img src="//upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Red_x.svg/16px-Red_x.svg.png" width="16" height="16" alt="Nein" title="Nein" />',
 disabled: false,
 reload: true,

 getTabelle: function() {
    var tabelle = '<table class="wikitable"><tr><th>Name</th><th>Beschreibung</th><th>aktiv?</th><th>Bemerkung</th><th>Ändern</th></tr>';
    for (var name in jsmodules.modules) {
        if (jsmodules.modules.hasOwnProperty(name)) {
           var mod = jsmodules.modules[name];

           if (name.indexOf('#') === 0) { //Überschrift
              tabelle += '<tr><th colspan="5">' + mod.desc + '</th></tr>';
              continue;
           }

           var url = name.replace(/[\[\]]/g, '');
           if (name.indexOf('[[') === 0) url = mw.util.getUrl(url);
           url = '<a href="' + url + '"><code>' + name + '</code></a>';

           var aktiv = (mod.status.called && !mod.status.disabled) ? jsmodules.modulverwaltung.img_ja : jsmodules.modulverwaltung.img_nein;

           var bemerkung = [];
           if (mod.status.depend) {
              if (mod.status.depend_plus) {
                 bemerkung.push('Dieses Skript wird auch von anderen aktivierten Skripten benötigt.');
              } else {
                 bemerkung.push('Das Skript wurde wegen einer Abhängigkeit aktiviert.');
              }
           }
           if (mod.status.called && mod.status.dynamical) bemerkung.push('Das Skript wurde per Cookie aktiviert.');
           if (mod.status.disabled) bemerkung.push('Das Skript wurde per Cookie deaktiviert.');
           if (mod.status.called && !mod.status.disabled && !mod.status.loaded) bemerkung.push('Das Skript ist auf dieser Seite nicht aktiv.');
           bemerkung = bemerkung.join('<br />');

           var aendern = '';
           if (!mod.status.called) {
              if (!mod.dynamical) {
                 aendern = '-';
              } else {
                 aendern = mw.html.element('a', {rel: name, 'class': 'jsmodules-setze1', href: '#'}, 'aktivieren');
              }
           } else {
              if (mod.status.dynamical) {
                 aendern = mw.html.element('a', {rel: name, 'class': 'jsmodules-loesche', href: '#'}, 'deaktivieren');
              } else if (mod.status.disabled) {
                 aendern = mw.html.element('a', {rel: name, 'class': 'jsmodules-loesche', href: '#'}, 'aktivieren');
              } else {
                 aendern = mw.html.element('a', {rel: name, 'class': 'jsmodules-setze0', href: '#'}, 'deaktivieren');
              }
           }
           tabelle += '<tr><td>' + url + '</td><td>' + mod.desc + '</td><td>' + aktiv + '</td><td>' + bemerkung + '</td><td>' + aendern + '</td></tr>';
        }
    }
    tabelle += '</table>';
    tabelle = $(tabelle);
    tabelle.find('.jsmodules-loesche').click(function(){
            jsmodules.modulverwaltung.loesche($(this).attr('rel'));
            return false;
    });
    tabelle.find('.jsmodules-setze0').click(function(){
            jsmodules.modulverwaltung.setze($(this).attr('rel'), 0);
            return false;
    });
    tabelle.find('.jsmodules-setze1').click(function(){
            jsmodules.modulverwaltung.setze($(this).attr('rel'), 1);
            return false;
    });
    return tabelle;
 },

 init: function() {
    if (mw.config.get('wgCanonicalSpecialPageName') === 'Blankpage' && mw.util.getParamValue( 'action' ) === 'schnark-config') {
       document.title = 'Konfiguration deiner Skripte';
       $('#firstHeading').text('Konfiguration deiner Skripte');
       $('#mw-content-text').html(jsmodules.modulverwaltung.getTabelle());
    }
    var $tabelle = $('#konfigurationstabelle');
    if ($tabelle.length === 0) return;
    $tabelle.html(jsmodules.modulverwaltung.getTabelle());
 },

 setze: function(name, wert) {
       var c = $.cookie(jsmodules.cookie_name) || '';
       var i = c.indexOf(name);
       if (i === -1) {
          c += name + wert;
       } else {
          c = c.substr(0, i) + name + wert + c.substr(i + name.length + 1);
       }
       $.cookie(jsmodules.cookie_name, c, { expires: jsmodules.cookie_ttl, path: '/' });
       if (jsmodules.modulverwaltung.reload) jsmodules.modulverwaltung.do_reload();
 },
 loesche: function(name) {
         var c = $.cookie(jsmodules.cookie_name) || '';
         var i = c.indexOf(name);
         if (i !== -1)
            c = c.substr(0, i) + c.substr(i + name.length + 1);
         $.cookie(jsmodules.cookie_name, c, { expires: jsmodules.cookie_ttl, path: '/' });
         if (jsmodules.modulverwaltung.reload) jsmodules.modulverwaltung.do_reload();
 },
 //lädt Seite neu
 do_reload: function() {
   location.reload(false);
 }
}
};

$(document).trigger('loadWikiScript', ['Benutzer:Schnark/js/jsmodules.js', jsmodules]);

window.jsmodules = jsmodules; //Abwärtskompatibilität
mw.libs.jsmodules = jsmodules;

jsmodules.init();
mw.loader.using(['mediawiki.util', 'jquery.cookie'], jsmodules.importdef);

})(jQuery);
//</nowiki>