MediaWiki:Gadget-Common.js
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;
}