MediaWiki:Gadget-Common.js

Tủ sách mở Wikibooks

Chú ý: Sau khi lưu trang, có thể bạn sẽ phải xóa bộ nhớ đệm của trình duyệt để xem các thay đổi.

  • Firefox / Safari: Nhấn giữ phím Shift trong khi nhấn Tải lại (Reload), hoặc nhấn tổ hợp Ctrl-F5 hay Ctrl-R (⌘R trên Mac)
  • Google Chrome: Nhấn tổ hợp Ctrl-Shift-R (⇧⌘R trên Mac)
  • Internet Explorer / Edge: Nhấn giữ phím Ctrl trong khi nhấn Làm tươi (Refresh), hoặc nhấn tổ hợp Ctrl-F5
  • Opera: Nhấn tổ hợp Ctrl-F5.
wgGadget_CommonJsVersion = "20120613002";
// 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);
}
if (!String.prototype.trim) {
  String.prototype.trim = function() { return this.trimLeft().trimRight(); }
}
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);
}


/**
 * Écriture cookie : expire après 1 année par défaut
 *   name : nom du cookie
 *   value : valeur du cookie
 *   delay(entier) : delay d'expiration (1 an ou CookiesLifeTimeYears par défaut)
 *   delayunit(1 caractère) : unité utilisée pour delay :
 *     'a'/'y' années/years    'm' mois/months  'j'/'d' jours/days
 *     date au format GMT par défaut
 */
function SetVar(name,value,delay,delayunit)
{
    var expires=new Date();
    if (typeof(CookiesLifeTimeYears)=="undefined") CookiesLifeTimeYears=1;
    if (delay)
    {
        if (delayunit)
        {
            switch(delayunit)
            {
            case 'd': case 'j': default: expires.setTime(expires.getTime()+delay*86400000); break;
            case 'm':
                var enmois = delay%12;     // nombre de mois
                delay = (delay-enmois)/12; // nombre d'années entier
                var mois = expires.getMonth()+enmois;
                if (mois>11) // mois de 0 à 11 dans l'objet Date
                { mois -= 12; delay++; }   // -12 mois, +1 an
                expires.setMonth(mois);
                if (delay==0) break;
            case 'a': case 'y':
                expires.setFullYear(expires.getFullYear()+delay); break;
            }
        }
        else expires=new Date(delay);
    }
    else
    {
        expires.setFullYear(expires.getFullYear()+CookiesLifeTimeYears);
    }
    document.cookie=name+"="+escape(value)+
        ";expires="+expires.toGMTString()+";path=/";
}

/**
 * Lecture cookie, valeur par défaut : paramètre defvalue
 */
function GetVar(name,defvalue)
{
    var s=";"+document.cookie.replace(/ /g,"")+";";
    var i=s.indexOf(";"+name+"=");
    if (i<0) return defvalue;
    i+=name.length+2;
    return unescape(s.substring(i,s.indexOf(";",i)));
}

/**
 * Récupère la valeur du cookie
 */
function getCookieVal(name)
{
    return GetVar(name,false);
}

/**
 * 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.nodeValue.length)?v.nodeValue: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 wgTalkPageName = mw.config.get('wgPageName');
var wgMainPageName = mw.config.get('wgPageName');
if (mw.config.get('wgNamespaceNumber')>=0)
{
  var ns = mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceNumber')];
  var wgPage = (ns.length>0)?mw.config.get('wgPageName').substring(ns.length+1):mw.config.get('wgPageName');
  ns = mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceNumber')&-2];
  wgMainPageName = (ns==""?"":ns+":")+wgPage;
  ns = mw.config.get('wgFormattedNamespaces')[mw.config.get('wgNamespaceNumber')|1];
  wgTalkPageName = (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_wpvi=wgProtocol+'://upload.wikimedia.org/wikipedia/vi/';
url_wbfr=wgProtocol+'://upload.wikimedia.org/wikibooks/fr/';
url_wbvi=wgProtocol+'://upload.wikimedia.org/wikibooks/vi/';

if (typeof(onloadProtectedFunctsLast)=='undefined')
  var onloadProtectedFunctsLast = []; // fonctions exécutées en dernier

/**
    fr: Ajout de fonctions dans onloadProtectedFunctsLast
        Fonction à appeler en dernier (ex : correction de liens, boîtes latérales déroulantes, ...)
    en: Add functions in onloadProtectedFunctsLast
        Function to call last (ex: link corrections, drop-down sidebox, ...)
*/
addLastOnloadHook = function ( hookFunct )
{
    onloadProtectedFunctsLast[onloadProtectedFunctsLast.length] = hookFunct;
}