MediaWiki:Gadget-Common.js

Un livre de Wikilivres.

Attention : Depuis MediaWiki 1.18 les pages se terminant avec l'extension .js ou .css sont interprétées comme des pages wiki ! En particulier les modèles (subst ou non) et les liens. Vous devez donc migrer le code source et effectuer vos changements en évitant ces éléments de syntaxe wiki (peu importe leurs emplacements dans le code source : commentaire, chaine) :

  • Double accolades ouvrantes (en particulier avec subst:) : séparer les deux accolades "{"+"{" du reste de la chaine
  • Double crochets ouvrants : même technique de séparation.
  • Signature (tildes ~ multiples) : même technique de séparation.

Note : après avoir enregistré vos préférences, vous devrez attendre que le serveur mette à jour la feuille de style globale avant de forcer le rechargement complet du cache de votre navigateur pour voir les changements.

  • Firefox / Safari : Maintenez la touche Maj (Shift) en cliquant sur le bouton Actualiser ou pressez Ctrl-F5 ou Ctrl-R (⌘-R sur un Mac) ;
  • Google Chrome : Appuyez sur Ctrl-Maj-R (⌘-Shift-R sur un Mac) ;
  • Internet Explorer : Maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5 ;
  • Konqueror : Cliquez sur Actualiser ou pressez F5 ;
  • Opera : Videz le cache dans Outils → Préférences.
wgfrwikibooks_Gadget_CommonJsVersion = "20201007002";
// Script contenant les fonctions utilisées par d'autres gadgets
// Ces fonctions ne peuvent être placées dans MediaWiki:Common.js
// qui est inclus après les gadgets.

/************************************************************/
/* Fonctions générales (pallient les limites de javascript) */
/************************************************************/


/**
 * Traitement des classes 
 * Javascript ne fournit actuellement que .className qui est extrêmement limité
 * surveiller l'implémentation de .classList http://www.w3.org/TR/2008/WD-html5-diff-20080122/#htmlelement-extensions
 */

function whichClass(element, classes) {
    var s=" "+element.className+" ";
    for (var i=0; i<classes.length; i++)
        if (s.indexOf(" "+classes[i]+" ")>=0) return i;
    return -1;
}

function hasClass(node, classe) {
    var s=" "+node.className+" ";
    return s.indexOf(" "+classe+" ") >= 0;
}

function addClass(node, className) {
    if (hasClass(node, className)) return false;
    node.className += ' '+ className;
    return true;
}

function removeClass(node, className) {
    if (!hasClass(node, className)) return false;
    node.className = eregReplace('(^|\\s+)'+ className +'($|\\s+)', ' ', node.className);
    return true;
}
 
function eregReplace(search, replace, subject)
{ return subject.replace(new RegExp(search,'g'), replace); }

/**
 * rechercher les éléments de la page dont le paramètre "class" est celui recherché
 * http://developer.mozilla.org/en/docs/DOM:document.getElementsByClassName
 */
function getElementsByClass(searchClass,node,tag) {
    if ( node == null ) node = document;
    if ( tag == null ) tag = '*';
    return getElementsByClassName(node, tag, searchClass);
}

/**
 * Fonctions de traitement de chaînes
 */
function equalsAa(str1, str2) {
    return str1.toUpperCase() == str2.toUpperCase();
}

function startsWithAa(string, prefix) {
    return equalsAa(string.substring(0, prefix.length), prefix);
}

function substractPrefixAa(string, prefix) {
    return startsWithAa(string, prefix) ? string.substring(prefix.length) : string;
}

function endsWithAa(string, prefix) {
    return (string.length>=prefix.length) &&
        equalsAa(string.substring(string.length-prefix.length), prefix);
}

function substractSuffixAa(string, prefix) {
    return endsWithAa(string, prefix) ? string.substring(0,string.length-prefix.length) : string;
}

function startsWith(string, prefix) {
    return string.substring(0, prefix.length) == prefix;
}

function substractPrefix(string, prefix) {
    return startsWith(string, prefix) ? string.substring(prefix.length) : string;
}

function endsWith(string, prefix) {
    return (string.length>=prefix.length) &&
        (string.substring(string.length-prefix.length) == prefix);
}

function substractSuffix(string, prefix) {
    return endsWith(string, prefix) ? string.substring(0,string.length-prefix.length) : string;
}

// Extension de la classe String :
String.prototype.trimLeft = function() { return this.replace(/^\s\s*/, ''); }
String.prototype.trimRight = function() {
    var str = this,
        ws = /\s/,
        i = str.length;
    while (ws.test(str.charAt(--i)));
    return str.slice(0, i + 1);
}

String.prototype.equalAa = function(other) { return equalsAa(this,other); };
String.prototype.startsAa = function(prefix) { return startsWithAa(this,prefix); };
String.prototype.endsAa = function(prefix) { return endsWithAa(this,prefix); };
String.prototype.popAa = function(prefix,suffix) {
    var s = this;
    if (prefix) s=substractPrefixAa(s,prefix);
    if (suffix) s=substractSuffixAa(s,suffix);
    return s;
};
String.prototype.starts = function(prefix) { return startsWith(this,prefix); };
String.prototype.ends = function(prefix) { return endsWith(this,prefix); };
String.prototype.pop = function(prefix,suffix) {
    var s = this;
    if (prefix) s=substractPrefix(s,prefix);
    if (suffix) s=substractSuffix(s,suffix);
    return s;
};
String.prototype.ucFirst = function () {
   return this.substr(0,1).toUpperCase() + this.substr(1,this.length);
};


/**
 * Déterminer l'adresse du serveur à utiliser dans les liens quand fullurl:page n'est pas utilisable.
 */

var wgProtocol = '';
if (mw.config.get('wgServer').starts('//')) // Nouveau type d'URL relative gérée par MediaWiki
{
    var url = document.location.toString();
    var i = url.indexOf('://'); // position of first ://
    wgProtocol = url.substring(0, i);
}
else
{
    var i = mw.config.get('wgServer').indexOf('://'); // position of first ://
    wgProtocol = mw.config.get('wgServer').substring(0, i);
}

/**
 * Teste le groupe de l'utilisateur
 */
function usergroup(groupname)
{
    if (!mw.config.get('wgUserGroups')) return false;
    for(var i in mw.config.get('wgUserGroups'))
        if (mw.config.get('wgUserGroups')[i]==groupname) return true;
    return false;
}

/**
 * Moyen efficace de connaitre tous les droits de l'utilisateur
 * en une variable (filtrage selon les droits plus simple).
 */
var wgUserLevel =
    (usergroup("user")?1:0) |
    (usergroup("autoconfirmed")?2:0) |
    (usergroup("sysop")?4:0) |
    (usergroup("bureaucrat")?8:0) ;

/**
 * Tester le niveau utilisateur
 * levelmask :
 *   bits 7-4 = masque de bits
 *   bits 3-0 = valeur de wgUserLevel à obtenir après masquage (et binaire).
 * ex: 0x40 pour les non sysops
 * Retourne true si la valeur correspond, false sinon.
 */
function userHasLevel(levelmask)
{ return (wgUserLevel & (levelmask>>>4)) == (wgUserLevel & 0xF); }

/**
 * retourne la valeur d'un attribut html, sinon une valeur par défaut
 */
function getAttr(node, name, defvalue)
{
    if (!node.attributes) return defvalue;
    var v=node.attributes.getNamedItem(name);
    return (v&&v.value.length)?v.value:defvalue;
}

/**
 * Teste si la page fait partie d'un livre donné
 * Ne pas oublier d'ajouter le séparateur utilisé à la fin de title
 * (en général / , : ou (espace))
 */
function inBook(title)
{
    if (mw.config.get('wgTitle')==title.substring(0,title.length-1)) return true;
    return mw.config.get('wgTitle').substr(0, title.length) == title;
}

/**
 * Tester si une chaine est une adresse IP.
 */
function isIP(s)
{ return /(([0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))){3}|[0-9A-Fa-f]{1,4}([:][0-9A-Fa-f]{1,4}){7}|[:]([:]|([:][0-9A-Fa-f]{1,4}){1,7})|[0-9A-Fa-f]{1,4}[:]([:]|([:][0-9A-Fa-f]{1,4}){1,6})|([0-9A-Fa-f]{1,4}[:]){2}([:]|([:][0-9A-Fa-f]{1,4}){1,5})|([0-9A-Fa-f]{1,4}[:]){3}([:]|([:][0-9A-Fa-f]{1,4}){1,4})|([0-9A-Fa-f]{1,4}[:]){4}([:]|([:][0-9A-Fa-f]{1,4}){1,3})|([0-9A-Fa-f]{1,4}[:]){5}([:]|([:][0-9A-Fa-f]{1,4}){1,2})|([0-9A-Fa-f]{1,4}[:]){6}([:]|([:][0-9A-Fa-f]{1,4}))|([0-9A-Fa-f]{1,4}[:]){7}[:]|(([0-9A-Fa-f]{1,4}[:]){6}|[:][:]([0-9A-Fa-f]{1,4}[:]){0,5}|[0-9A-Fa-f]{1,4}[:][:]([0-9A-Fa-f]{1,4}[:]){0,4}|([0-9A-Fa-f]{1,4}[:]){2}[:]([0-9A-Fa-f]{1,4}[:]){0,3}|([0-9A-Fa-f]{1,4}[:]){3}[:]([0-9A-Fa-f]{1,4}[:]){0,2}|([0-9A-Fa-f]{1,4}[:]){4}[:]([0-9A-Fa-f]{1,4}[:]){0,1}|([0-9A-Fa-f]{1,4}[:]){5}[:])([0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))){3})/.test(s); }

/**
 * Indicateur de page de discussion ou considérée comme telle
 */
var wgIsTalkPage =
   (((mw.config.get('wgNamespaceNumber')>0)&&(mw.config.get('wgNamespaceNumber')&1)) // Page de discussion
   ||(mw.config.get('wgTitle').ends("Livre d'or")) // ou livre d'or
   ||((mw.config.get('wgNamespaceNumber')==4)&&(inBook("Le Bistro/") // ou bistro
       ||inBook("Requêtes aux ") // ou page de requêtes
       ||inBook("Candidature ") // ou candidature
       ||inBook("Bureaucrate/") // ou candidature bureaucrate
       ||inBook("Prise de décision/") // ou prise de décision
       ||inBook("Pages à ") // ou votes
       ||inBook("Livre d'or/") // ou livre d'or
   )));

/**
 * Indicateurs de page utilisateur (page ou discussion)
 */
var wgIsUser = (mw.config.get('wgNamespaceNumber')>>1)==1 ;
var wgIsUserIP = wgIsUser && isIP(mw.config.get('wgTitle'));
var wgIsUserNotIP = wgIsUser && !wgIsUserIP;

/** Indicateur de page en cours d'édition */
var wgIsEditingPage = (mw.config.get('wgAction') == "edit") || (mw.config.get('wgAction') == "submit");

/** Indicateur de page de script (*.js, *.css) */
var wgIsScriptPage = !wgIsTalkPage && (mw.config.get('wgTitle').ends('.js') || mw.config.get('wgTitle').ends('.css'));

/** Information sur la page : page de discussion et page principale */
var wgPageNameSpace = mw.config.get('wgPageName').replaceAll('_',' ');
var wgTalkPageName = wgPageNameSpace;
var wgMainPageName = wgPageNameSpace;
if (mw.config.get('wgNamespaceNumber')>=0)
{
  var all_ns = mw.config.get('wgFormattedNamespaces');
  var ns = all_ns[mw.config.get('wgNamespaceNumber')].replaceAll('_',' ');
  var k = wgPageNameSpace .indexOf(':'),
      pns = (ns.length>0)?wgPageNameSpace .substring(0,k):"";
  var wgPage = (ns.length>0)?wgPageNameSpace .substring(k+1):wgPageNameSpace; /* Premier ':' si espace de nom. */
  if ((mw.config.get('wgNamespaceNumber')&-2)==2 && pns != ns)
    all_ns = [null,null,"Utilisatrice", "Discussion utilisatrice"];
  if ((mw.config.get('wgNamespaceNumber')&1)==0)
  {
    ns = all_ns[mw.config.get('wgNamespaceNumber')|1];
    wgTalkPageName = (ns==""?"":ns+":")+wgPage;
  }
  else
  {
    ns = all_ns[mw.config.get('wgNamespaceNumber')&-2];
    wgMainPageName = (ns==""?"":ns+":")+wgPage;
  }
}

function devdebug(msg) {
    if (typeof(_devdebug)=="function") _devdebug(msg);
}

/** Nom de page -> URL */
function urlOfWikiPage(pagename, server)
{
    if (typeof(server) == "undefined") server = ""; // relative URL
    else server=wgProtocol+"://"+server; // same protocol
    pagename = pagename.replace("?", "%3F");
    return server + mw.config.get('wgArticlePath').replace("$1", pagename);
}

function encodeParameter(parameter)
{
    var i = parameter.indexOf('=');
    return parameter.substring(0,i+1) + encodeURIComponent(parameter.substring(i+1));
}

// -2 Média, -1 Spécial, 0 (principal), 1 Discussion, 2 Utilisateur, 3 Discussion utilisateur
// 4 Wikilivres, 5 Discussion Wikilivres, 6 Fichier, 7 Discussion fichier,
// 8 MediaWiki, 9 Discussion MediaWiki, 10 Modèle, 11 Discussion modèle,
// 12 Aide, 13 Discussion aide, 14 Catégorie, 15 Discussion catégorie, 100 Transwiki, 101 Discussion Transwiki

// Pour des scripts internationaux :
function getpagename(ns_index, pagename)
{
    return mw.config.get('wgFormattedNamespaces')[""+ns_index]+":"+pagename;
}

function localurl(pagename /*, parameters... */)
{
    // If there is no more parameter than the pagename, use wiki/...
    if (arguments.length==1) return mw.config.get('wgArticlePath').replace("$1", pagename.replace("?", "%3F"));
    // Otherwise use /w/index.php?...
    var url = mw.config.get('wgScript') + '?title=' + encodeURIComponent(pagename);
    for( var i = 1; i < arguments.length; i++ )
        url = url + '&' + encodeParameter(arguments[i]);
    return url;
}


// Get the ISO lang code (2 or 3 characters) preceeding the pagename
// only lowercase, otherwise might be short namespace name
// (no such short namespace currently but maybe in the future...)

// defcode (optionnal): generally wgContentLanguage
// return [newpagename, langcode]
function getLangCode(pagename, defcode)
{
    var i = pagename.indexOf(':');
    if (i<2 || i>3) return [pagename, defcode];   // no lang code
    var code = pagename.substring(0,i);
    return (code == code.toLowerCase()) ? [pagename.substring(i+1), code] : [pagename, defcode];
}

// All project configuration
var wm_projects_url_info =
{        // ..._p = prefix   ..._s = suffix
'http':  {'url_p':'http://', 'pagewiki_s':'/wiki/', 'pagescript_s':'/w/index.php?title=',
          'projects':{

              // [before language code, after language code]
              'w:' :       ['', '.wikipedia.org'],
              'b:' :       ['', '.wikibooks.org'],
              's:' :       ['', '.wikisource.org'],
              'q:' :       ['', '.wikiquote.org'],
              'v:' :       ['', '.wikiversity.org'],
              'wikt:' :    ['', '.wiktionary.org'],
              'n:' :       ['', '.wikinews.org'],

              // [without language code]
              'wmf:' :     ['wikimediafoundation.org'],
              'mw:' :      ['www.mediawiki.org'],
              'meta:' :    ['meta.wikimedia.org'],
              'm:' :       ['meta.wikimedia.org'],
              'commons:' : ['commons.wikimedia.org'],
              'species:' : ['species.wikimedia.org'],

              // fullurl specified
              'bugzilla:' : 'https://bugzilla.wikimedia.org/show_bug.cgi?id='
          }},

'https':  {'url_p':'https://', 'pagewiki_s':'/wiki/', 'pagescript_s':'/w/index.php?title=',
          'projects':{

              // [before language code, after language code]
              'w:' :       ['', '.wikipedia.org'],
              'b:' :       ['', '.wikibooks.org'],
              's:' :       ['', '.wikisource.org'],
              'q:' :       ['', '.wikiquote.org'],
              'v:' :       ['', '.wikiversity.org'],
              'wikt:' :    ['', '.wiktionary.org'],
              'n:' :       ['', '.wikinews.org'],

              // [without language code]
              'wmf:' :     ['wikimediafoundation.org'],
              'mw:' :      ['www.mediawiki.org'],
              'meta:' :    ['meta.wikimedia.org'],
              'm:' :       ['meta.wikimedia.org'],
              'commons:' : ['commons.wikimedia.org'],
              'species:' : ['species.wikimedia.org'],

              // fullurl specified
              'bugzilla:' : 'https://bugzilla.wikimedia.org/show_bug.cgi?id='
          }}
};

function fullurl(pagename /*, parameters... */)
{
    var url = undefined;
    if (pagename.starts('wm')) // special case
    {
        var i = pagename.indexOf(':');
        if (i>=0)
        {
            try{
                var year = parseInt(pagename.substring(2,i));
                if (year==pagename.substring(2,i) && year>=2005)
                {
                    pagename = pagename.substring(i+1);
                    url = 'http://wikimania'+year+'.wikimedia.org';
                    {
                        // If there is no more parameter than the pagename, use wiki/...
                        if (arguments.length==1) return url + '/wiki/' + pagename.replace("?", "%3F");
                        // Otherwise use /w/index.php?...
                        url += '/w/index.php?title=' + encodeURIComponent(pagename);
                    }
                }
            }catch(e){}
        }
    }
    if (typeof(url)=='undefined')
    {
        var info = wm_projects_url_info[wgProtocol];
        var projects = info.projects;
        for(var prefix in projects)
            if (pagename.starts(prefix))
            {
                pagename = pagename.substring(prefix.length);
                var project = projects[prefix];
                if (typeof(project)=='string') // full url with GET form
                    url = project + encodeURIComponent(pagename);
                else
                {
                    url = info.url_p + project[0];
                    if (project.length==2)
                    {
                        var pagecode = getLangCode(pagename, mw.config.get('wgContentLanguage'));
                        url += pagecode[1] + project[1]; pagename = pagecode[0];
                    }
                    if (arguments.length==1) url += info.pagewiki_s + pagename.replace("?", "%3F");
                    else url += info.pagescript_s + encodeURIComponent(pagename);
                }
                break;
            }
        if (typeof(url)=='undefined')
        {
            // If there is no more parameter than the pagename, use wiki/...
            if (arguments.length==1) return mw.config.get('wgServer') + mw.config.get('wgArticlePath').replace("$1", pagename.replace("?", "%3F"));
            // Otherwise use /w/index.php?...
            url = mw.config.get('wgServer') + mw.config.get('wgScript') + '?title=' + encodeURIComponent(pagename);
        }
    }
    for( var i = 1; i < arguments.length; i++ )
        url = url + '&' + encodeParameter(arguments[i]);
    return url;
}

// Emplacements classiques des images :
url_wpcm=wgProtocol+'://upload.wikimedia.org/wikipedia/commons/';
url_wpfr=wgProtocol+'://upload.wikimedia.org/wikipedia/fr/';
url_wpen=wgProtocol+'://upload.wikimedia.org/wikipedia/en/';
url_wbfr=wgProtocol+'://upload.wikimedia.org/wikibooks/fr/';