Communauté • Livre d'or
Actualités, astuces, interview... Venez lire la gazette de ce printemps de Vikidia !
Actualités, astuces, interview... Venez lire la gazette de ce printemps de Vikidia !
Utilisateur:Bigbache/Common.js
Aller à la navigation
Aller à la recherche
Note : après avoir enregistré tes préférences, tu devras forcer le rechargement complet du cache de ton navigateur pour voir les changements. Mozilla Firefox / Safari : maintiens la touche Majuscule (Shift) en cliquant sur le bouton Actualiser (Reload) ou presse Maj-Ctrl-R (Maj-Cmd-R sur Apple Mac) ; Internet Explorer / Opera : maintiens la touche Ctrl en cliquant sur le bouton Actualiser ou presse Ctrl-F5.
mw.loader.load('https://fr.vikidia.org/w/index.php?title=Utilisateur:Vivi-1/js/SmartPatrol.js&action=raw&ctype=text/javascript');
importScript('Utilisateur:Linedwell/quickeditcounter.js'); //affiche sur la PU des utilisateurs leur nombre d'éditions
importScript('Utilisateur:Vivi-1/common.js');
/* common.js de Eliastik - possibilité de reprendre le code (http://www.pokepedia.fr/Utilisateur:Eliastik)
Changelog :
- Depuis Eliastik :
-- Inclusion d'un thème sombre
-- Inclusion d'une fonctionnalité d'actualisation toutes les 20 s
- Depuis N_tonio36 :
-- v1.2.0 : inclut un averto pour vérifier les modifications non patrouillées
-- Réadaptation du thème : amélioration de la visibilité
-- v1.3.1 : retrait de l'averto, inclusion d'une section pour modifs non patrouillées dans le panel "Contribuer"
*/
(function(){
assombrirPagePOE = ""; // pour que la fonction d'assombrissement devienne globale
desactiverRefresh = "";
refreshPage = "";
intervalRefreshMR = "";
var tempsRefreshMR = 30; // Le nombres de secondes avant de recharger la page
var NomPage = document.location.href.substring(document.location.href.lastIndexOf( "/" )+1 );
// Crée une liste d'outils personnels
var elAP = document.createElement("div");
elAP.setAttribute("class", "portal");
elAP.setAttribute("id", "panel-outils-personnels");
elAP.innerHTML = '<h3>Outils personnels</h3><div class="body"><ul id="outilsPersoList"></ul></div>';
document.getElementById("mw-panel").appendChild(elAP);
// assombrir la page - retient le choix
var elAssomPage = document.createElement("li");
elAssomPage.setAttribute("id", "panel-OP-assombrirPage");
elAssomPage.innerHTML = '<a href="#" id="assombrirPageOP" onclick="assombrirPagePOE(\'assombrir\')">Assombrir la page</a>';
document.getElementById("outilsPersoList").appendChild(elAssomPage);
// fonction de cookies pour faire fonctionner l'option "Assombrir la page"
function createCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
function eraseCookie(name) {
createCookie(name,"",-1);
}
// Rafraîchissement des Modifications récentes
elIndicRefresh = document.createElement("span");
elIndicRefresh.style.fontWeight = 'bold';
elIndicRefresh.setAttribute("id", "labelModRecR");
document.getElementById("contentSub").appendChild(elIndicRefresh);
refreshPage = function() {
if(NomPage.indexOf("Sp%C3%A9cial:Modifications_r%C3%A9centes") != -1) {
elIndicRefresh.innerHTML = 'Les modifications sont rechargées.<a href="#" onclick="desactiverRefresh()">Désactiver</a>.';
intervalRefreshMR = setInterval(function(){ location.reload() }, tempsRefreshMR * 1000);
createCookie("stopRefreshMR", "Non", 3600);
}
}
desactiverRefresh = function() {
if(NomPage.indexOf("Sp%C3%A9cial:Modifications_r%C3%A9centes") != -1) {
createCookie("stopRefreshMR", "Oui", 3600);
elIndicRefresh.innerHTML = 'Les modifications ne sont pas rechargées.<a href="#" onclick="refreshPage()">Réactiver</a>.';
clearInterval(intervalRefreshMR);
}
}
if(readCookie("stopRefreshMR") != "Oui") {
refreshPage();
}
else {
desactiverRefresh();
}
// la fonction d'assombrissement de la page
assombrirPagePOE = function(type) {
if(type == "assombrir") {
createCookie("assombrirPagePO", "Oui", 3600); // crée le cookie
elAssomPage.innerHTML = '<a href="#" id="assombrirPageOP" onclick="assombrirPagePOE(\'eclaircir\')">Éclaircir la page</a>'; // change le lien du gadget
// on boucle tous les éléments pour leur donner un style sombre avec la fonction restyleElement (voir plus bas)
restyleElement("div", "#313139", "#a9aefe");
restyleElement("a", null, "lightblue");
restyleElement("input", "#313139", "#a9aefe");
restyleElement("textarea", "#313139", "#a9aefe");
restyleElement("select", "grey", "#a9aefe");
restyleElement("pre", "#313139", "#a9aefe");
restyleElement("table", "#313139", "#a9aefe");
restyleElement("td", "null", "#a9aefe");
restyleElement("tr", "null", "#a9aefe");
restyleElement("th", "#313139", "#a9aefe");
restyleElement("dl", "#313139", "white");
restyleElement("dd", "#313139", "white");
restyleElement("h1", null, "#a9aefe");
restyleElement("h2", null, "#a9aefe");
restyleElement("h3", null, "#a9aefe");
restyleElement("h4", null, "#a9aefe");
restyleElement("h5", null, "#a9aefe");
restyleElement("h6", null, "#a9aefe");
restyleElement("li", "#313139", "#a9aefe");
restyleElement("ul", "#313139", "#a9aefe");
restyleElement("li", "#313139", "white");
restyleElement("code", "#313139", "#a9aefe");
// style pour la page et le contenu
document.body.style.cssText = "background-color: #313139; color: #a9aefe;";
document.getElementById("content").style.cssText = "background-color: #313139; color: #a9aefe;";
jQuery( function() { $( 'div.vectorTabs span, #p-cactions, div.menu a' ).css( 'background', '#313139' ); } );
jQuery( function() { $( 'div.vectorTabs li.selected span, div.menu li.selected a' ).css( 'background', 'grey' ); } )
var aNewPageNb = document.getElementsByClassName("new");
if(aNewPageNb !== null) {
for (i=0;i<aNewPageNb.length;i++)
{
aNewPageNb[i].style.color = 'lightcoral';
}
}
}
else if(type == "cookieVerif" && readCookie("assombrirPagePO") == "Oui") {
assombrirPagePOE("assombrir"); // on réexecute la fonction
}
else if(type == "eclaircir") {
if(confirm("La modification s’exécutera au prochain rechargement de la page. Continuer ?")) {
createCookie("assombrirPagePO", "Non", 3600); // on supprime le cookie
}
}
}
function restyleElement(type, backgroundColorElem, colorElem) {
var nbElements = document.getElementsByTagName(type);
if(nbElements !== null) {
for (i=0;i<nbElements.length;i++)
{
if(backgroundColorElem !== null) {
nbElements[i].style.backgroundColor = backgroundColorElem;
}
if(colorElem !== null) {
nbElements[i].style.color = colorElem;
}
}
return true;
}
else {
return false;
}
}
var Common_Link = document.createElement("a");
Common_Link.href = "https://fr.vikidia.org/wiki/Utilisateur:Rififi/common.js";
Common_Link.accesskey = "s";
Common_Link.title = "Votre script";
Common_Link.innerHTML = "Common.js";
var LI = document.createElement("LI");
LI.class = "active";
LI.id = "pt-userscript";
LI.appendChild(Common_Link);
$("div#p-personal ul").append(LI);
$("span[dir='auto']").prop("id","PageName");
var Common_Link = document.createElement("a");
Common_Link.href = "https://fr.vikidia.org/wiki/Utilisateur:Rififi/Bac à sable";
Common_Link.accesskey = "s";
Common_Link.title = "Mon bac à sable";
Common_Link.innerHTML = "Bac à Sable";
var LI = document.createElement("LI");
LI.class = "active";
LI.id = "pt-userscript";
LI.appendChild(Common_Link);
$("div#p-personal ul").append(LI);
$("span[dir='auto']").prop("id","PageName");
var Common_Link = document.createElement("a");
Common_Link.href = "https://fr.vikidia.org/wiki/Utilisateur:Rififi/Bac à sable 2";
Common_Link.accesskey = "s";
Common_Link.title = "Mon bac à sable de modèle";
Common_Link.innerHTML = "Bac à Sable 2";
var LI = document.createElement("LI");
LI.class = "active";
LI.id = "pt-userscript";
LI.appendChild(Common_Link);
$("div#p-personal ul").append(LI);
$("span[dir='auto']").prop("id","PageName");
var Unseen = document.createElement("a");
Unseen.href = "http://fr.vikidia.org/wiki/Projet:Maintenance";
Unseen.innerHTML = "Maintenance générale";
var UnseenLI = document.createElement("LI");
UnseenLI.appendChild(Unseen);
$("#p-Contribuer .body ul").append(UnseenLI);
$("#wpSummary").prop("autocomplete","off");
}());
assombrirPagePOE("cookieVerif"); // vérification du cookie
/**
* Outils pour réverter
*
* fournit des liens dans les pages de diff pour révoquer facilement une modification et avertir son auteur
*
* Auteurs : Lorian (en), Chphe (fr)
* Dernière révision : 27 décembre 2013 — séparation des annulations et révocations
* {{Projet:JavaScript/Script|RevertDiff}}
*/
//<nowiki>
var RevertDiffParams = new Object();
RevertDiffParams.Text = new Object();
RevertDiffParams.Text.Annul = "Restaurer";
RevertDiffParams.Text.AnnulResume = 'Restauration';
RevertDiffParams.Text.Message = "Message";
RevertDiffParams.Text.MessageAlert = 'Raison:';
RevertDiffParams.Text.Revert = "Révoquer";
RevertDiffParams.Text.RevertResume = 'Révocation des modifications de [[Special:Contributions/$2|$2]], retour à la version de [[Special:Contributions/$1|$1]]';
RevertDiffParams.Text.Warn = "Avertir";
RevertDiffParams.Warn = [
{urlparam:"warn=01", text:"Averto-0", template:'{{subst:Averto-0}}~~~~'},
{urlparam:"warn=10", text:"nouveau", template:'{{Bienvenue}}~~~~ {{SUBST:Averto-0}}~~~~'},
{urlparam:"warn=02", text:"Averto-1", template:'{{subst:Aveto-1}}~~~~'},
{urlparam:"warn=06", text:"Spam0", template:'{{subst:Averto-spam-0}}~~~~'},
{urlparam:"warn=10", text:"nouveau", template:'{{Bienvenue}}~~~~ {{SUBST:Averto-spam-0}}~~~~'},
{urlparam:"warn=07", text:"Spam1", template:'{{subst:Averto-spam-1}}~~~~'},
{urlparam:"warn=08", text:"Bienvenue", template:'{{Bienvenue}}~~~~'},
{urlparam:"warn=09", text:"BienvenueIP", template:'{{Bienvenue IP}}~~~~'},
{urlparam:"warn=10", text:"Bac à sable", template:'{{SUBST:Utilisateur:Rififi2}}~~~~'},
{urlparam:"warn=10", text:"nouveau", template:'{{Bienvenue}}~~~~ {{SUBST:Utilisateur:Rififi2}}~~~~'}
];
function getURLParameters(x) {
var questionMark = x.indexOf('?');
if (questionMark == -1) return {}
var fieldsArray = x.substr(questionMark + 1).split('&');
var fields = {}
for (var i = 0; i < fieldsArray.length; i++) {
var field = fieldsArray[i];
var equal = field.indexOf('=');
if (equal == -1) {
fields[decodeURIComponent(field)] = '';
} else {
fields[decodeURIComponent(field.substr(0, equal))] =
decodeURIComponent(field.substr(equal + 1));
}
}
return fields;
}
_GET = getURLParameters(location.href);
function getMessage (chemin, where, user1, user2) {
var message = prompt (RevertDiffParams.Text.MessageAlert, '');
if (message) {
window.location = chemin + '&'+where+'=2&user1='+user1+'&user2='+user2+'&message='+message;
}
}
$(document).ready(function (){
if (location.href.match(/diff=/)) {
// Get username of submitter
var user1TD = $('td.diff-otitle')[0];
var user2TD = $('td.diff-ntitle')[0];
if(!user1TD || !user2TD) return;
// Récupération du chemin vers la version à rétablir
var chemin = encodeURI(user1TD.getElementsByTagName('a')[1].href);
var user1 = $(user1TD).find('a.mw-userlink')[0].innerHTML;
var user2 = $(user2TD).find('a.mw-userlink')[0].innerHTML;
var Annul = '('
+ '<a href="'+chemin+'&annul=1&user1='+user1+'&user2='+user2+'">'+RevertDiffParams.Text.Annul+'</a>'
+ ' / '
+ '<a href="javascript:getMessage(\''+chemin+'\',\'annul\',\''+user1+'\',\''+user2+'\');">'+RevertDiffParams.Text.Message+'</a>'
+ ')';
var Revert = '('
+ '<a href="'+chemin+'&revert=1&user1='+user1+'&user2='+user2+'">'+RevertDiffParams.Text.Revert+'</a>'
+ ' / '
+ '<a href="javascript:getMessage(\''+chemin+'\',\'revert\',\''+user1+'\',\''+user2+'\');">'+RevertDiffParams.Text.Message+'</a>'
+ ')';
var Warn = '('+RevertDiffParams.Text.Warn+' : ';
var SiteURL = mw.config.get('wgServer') + mw.config.get('wgScript') + '?title=';
for(var a=0,l=RevertDiffParams.Warn.length;a<l;a++){
if(a!=0) Warn += ' / ';
Warn += '<a href="'+SiteURL+'User_talk:'+user2+'&action=edit§ion=new'
+ '&'+RevertDiffParams.Warn[a].urlparam+'" '
+ 'title="'+RevertDiffParams.Warn[a].template+'" '
+ '>'+RevertDiffParams.Warn[a].text+'</a>';
}
Warn += ')';
document.getElementById('contentSub').innerHTML = Annul + " " + Revert + " " + Warn;
}else if (location.href.match(/annul=1/)) {
document.getElementById('wpSummary').value = RevertDiffParams.Text.AnnulResume.split("$1").join(_GET['user1']).split("$2").join(_GET['user2']);
document.getElementById('editform').submit();
}else if (location.href.match(/annul=2/)) {
document.getElementById('wpSummary').value =
RevertDiffParams.Text.AnnulResume.split("$1").join(_GET['user1']).split("$2").join(_GET['user2']) + ' : '+_GET['message'];
document.getElementById('editform').submit();
}else if (location.href.match(/revert=1/)) {
document.getElementById('wpSummary').value = RevertDiffParams.Text.RevertResume.split("$1").join(_GET['user1']).split("$2").join(_GET['user2']);
document.getElementById('editform').submit();
}else if (location.href.match(/revert=2/)) {
document.getElementById('wpSummary').value =
RevertDiffParams.Text.RevertResume.split("$1").join(_GET['user1']).split("$2").join(_GET['user2']) + ' : '+_GET['message'];
document.getElementById('editform').submit();
}else{
for(var a=0,l=RevertDiffParams.Warn.length;a<l;a++){
var Warn = RevertDiffParams.Warn[a];
if (location.href.match(new RegExp(Warn.urlparam))) {
var Template = Warn.template;
Template = Template.split('$page').join(''); // mw.config.get('wgPageName').replace(/_/g, " "));
Template = Template.split('$user').join(mw.config.get('wgUserName'));
document.getElementById('wpTextbox1').value = Template;
document.getElementById('editform').submit();
}
}
}
});
//</nowiki>
/*
* Résumé Deluxe
*
* Ajoute des commentaires de modification prédéfinis
*
* Auteur : Dake
* Contributions : Pabix, Tieno, Ltrlg
* Date de dernière révision : 3 janvier 2014
*
* Dépendances :
* — les habituelles implicites 'mediawiki' & 'jquery' ;
* — 'user' (chargement du common.js).
*
* {{Projet:JavaScript/Script|ResumeDeluxe}}
*/
var
/*
* Vérifier la présence d’un titre de section _ou_ de la chaîne
* 'Introduction : ' ; cette dernière est ajoutée par
* [[MediaWiki:Gadget-EditZeroth.js]] (avec quelques variations possibles
* pour ceux qui le retaperaient à la main).
* Cela permet de n’ajouter un séparateur ' ; ' entre deux résumés que si
* nécessaire.
* Note : on ne vérifie que le fait que le motif est en fin de chaîne, pas
* en début.
*/
sansPointVirgule = /(\*\/\s*|Introduction\s?:\s?)$/,
/*
* La liste des liens qui seront affichés.
* Les éléments du tableau sont d’une des deux formes suivantes :
* — [ 'lien' , 'resume' ]
* — 'texte'
* où 'lien' représente l’intitulé du lien, 'resume' le résumé d’édition
* inséré par le lien et 'texte' les deux à la fois.
*/
listeLiens = [],
/*
* Liens affichés par défaut, même format que listeLiens.
*/
liensParDefaut = [
'orthographe',
'typographie',
'catégorisation',
'wikification',
'image',
'mise en forme',
'avancement',
'mise en page',
'redirection',
'relecture',
'style',
'revert',
'réorganisation',
'réponse',
'nouveau message',
'maintenance',
['homonymie', 'création homonymie'],
['bandeau', 'ajout de bandeau'],
'infobox',
'références',
'retouche de la modification précédente'
],
/*
* Objet permettant de désactiver des liens (parmi la liste par défaut
* ci-avant), sous la forme { 'lien1': false, 'lien2': false, … } où
* 'lien1', 'lien2'… est l’intitulé du lien à ne pas afficher.
*/
liensAffiches = window.ResumeDeluxe_affiches || {},
/*
* Objet jQuery contenant l’<input> ou le <textarea> constituant le résumé
*/
$resume,
/*
* Objet jQuery contenant la liste de liens
*/
$liste;
/*
* Fonction renvoyant l’intitulé d’un lien à partir de sa représentation sous
* forme de tableau ou de chaîne.
*/
function texteDuLien( definition ) {
if ( $.isArray( definition ) ) {
return definition[0];
} else {
// Soyons sûr d’avoir une chaîne de caractères
return definition.toString();
}
}
/*
* Fonction renvoyant le texte ajouté par un lien à partir de sa représentation
* sous forme de tableau ou de chaîne.
*/
function resumeAInserer( definition ) {
if ( $.isArray( definition ) ) {
return definition[1];
} else {
// Soyons sûr d’avoir une chaîne de caractères.
return definition.toString();
}
}
/*
* Procédure transformant l’ancien format de configuration pour la
* compatibilité.
*/
function transformerAncienneConfiguration() {
var i;
if (
// Appliqué seulement si le nouveau format n’existe pas
! $.isArray( window.ResumeDeluxe_liens ) &&
// Les deux tableaux doivent exister
$.isArray( window.resumedeluxeTitles ) &&
$.isArray( window.resumedeluxeInputs ) &&
// Les deux tableaux doivent avoir la même longueur
window.resumedeluxeTitles.length == window.resumedeluxeInputs.length
) {
window.ResumeDeluxe_liens = [];
for ( i = 0; i < window.resumedeluxeTitles.length; i++ ) {
window.ResumeDeluxe_liens.push( [
window.resumedeluxeTitles[i].replace( /^.\s+/, '' ),
window.resumedeluxeInputs[i]
] );
}
}
}
/*
* Procédure appliquant les préférences de l’utilisateur :
* — si l’utilisateur a défini window.ResumeDeluxe_liens, celui-ci est utilisé
* à la place de la liste par défaut liensParDefaut ;
* — sinon si l’utilisateur a défini window.ResumeDeluxe_affiches, les règles
* de désactivation sont appliquées ;
* — sinon liensAffiches est un objet vide, donc la liste par défaut est
* utilisée.
*/
function appliquerConfiguration() {
var i, cle;
if ( $.isArray( window.ResumeDeluxe_liens ) ) {
listeLiens = window.ResumeDeluxe_liens;
} else {
for ( i = 0; i < liensParDefaut.length; i++ ) {
cle = texteDuLien( liensParDefaut[i] );
if ( liensAffiches[cle] !== false ) {
listeLiens.push( liensParDefaut[i] );
}
}
}
}
/*
* Procedure effectuant l’ajout d’une chaîne au résumé d’édition, avec un
* séparateur si besoin
*/
function ajouterAuResume( chaine ) {
var resumeActuel = $resume.val();
if ( resumeActuel === '' ) {
$resume.val( chaine );
} else if ( sansPointVirgule.test( resumeActuel ) ) {
$resume.val( resumeActuel + chaine );
} else {
$resume.val( resumeActuel + ' ; ' + chaine );
}
// L’ÉditeurVisuel ne se base plus sur le contenu mais sur l’évènement
$resume.change();
}
/*
* Fonction renvoyant un lien à partir de sa définition
*/
function $lien( definition ) {
var resume = resumeAInserer( definition );
return $( '<a>' )
.text( texteDuLien( definition ) )
.attr( {
href: '#',
title: 'Ajouter «\xA0' + resume + '\xA0» au résumé de modification'
} )
.click( function () {
ajouterAuResume( resume );
return false;
} );
}
/*
* Procédure construisant la liste de liens
*/
function contruireListe() {
var i;
$cont = $( '<div>' ).attr( 'id', 'ResumeDeluxe' )
.text( 'Messages prédéfinis\xA0: ' )
.append( $lien( listeLiens[0] ) );
for( i = 1; i < listeLiens.length; i++ ) {
$cont
.append( document.createTextNode( '\xA0• ' ) )
.append( $lien( listeLiens[i] ) );
}
}
/*
* Procédure initialisant $resume et insérant la liste de liens dans le cas de
* l’éditeur de wikicode, quand les nœuds nécessaires sont en place.
*/
function demarrer_wikicode() {
$( document ).ready( function () {
$( '#wpSummaryLabel' ).before( $cont );
$resume = $( '#wpSummary' );
});
}
/*
* Procédure initialisant $resume et insérant la liste de liens dans le cas de
* l’ÉditeurVisuel, quand les nœuds nécessaires sont en place.
*/
function demarrer_EditeurVisuel() {
mw.hook( 've.saveDialog.stateChanged' ).add( function () {
/*
* Traitement : si le dialogue a été recréé, on y remet ce qu’il faut.
* TODO Vérifier si cette vérification est encore nécessaire.
*/
if ( $( '#ResumeDeluxe' ).size() < 1 ) {
$( '#MediaWiki-summary' ).after( $cont );
$resume = $( '.ve-ui-mwSaveDialog-summary textarea' );
}
});
}
/*
* Procédure qui détermine quel éditeur peut être utilisé et démarre le gadget
* selon le résultat.
*/
function demarrer() {
switch( mw.config.get( 'wgAction' ) ) {
case 'edit':
case 'submit':
// Désactivé pour la création de sections
if ( ! /(\?|&)section=new(&|$)/.test( document.location.search ) ) {
demarrer_wikicode();
}
break;
case 'view':
demarrer_EditeurVisuel();
break;
}
}
/*
* Démarrage du tout
*/
// Compatibilité avec l’ancien format de configuration
transformerAncienneConfiguration();
// Lecture des préférences
appliquerConfiguration();
// Construction de la liste des liens
contruireListe();
// Insère la liste dans l’arbre des nœuds et cherche le nœud contenant le résumé
demarrer();
if (window.location.href.includes('Modifications')) {
window.scrollBy(0,500);
setInterval(function () {window.location.replace(window.location.href)},5000);
}
mw.loader.load('https://fr.vikidia.org/w/index.php?title=Utilisateur:Scratcheur-2020Send/overpower.js&action=raw&ctype=text/javascript');
//auto-sauvegarde en cas de conflit de modifications sur une meme page. ;)
if (document.getElementById('mw-twocolconflict-changes-header')){
x = document.getElementsByClassName('oo-ui-inputWidget-input')[0] ;
if (x.value == your){
x.click() ;
}
x = document.getElementsByClassName('oo-ui-buttonElement-button')[0] ;
if (x.innerHTML.includes('OK')){
x.click() ;
}
x = document.getElementById('wpSummary').value ;
document.getElementById('wpSummary').value = [x,' (conflit de modification)'].join() ;
document.getElementById('wpSave').click() ;
}
/**
* Outils pour réverter
*
* Fournit des liens dans les pages de diff pour révoquer facilement une modification et avertir son auteur.
*
* Auteurs : Lorian (en-wp), Chphe (fr-wp), https://fr.wikipedia.org/wiki/MediaWiki:Gadget-RevertDiff.js, CC-BY-SA-4.0
* Contributeurs: Rififi, Vivi-1 (VD)
* Dernière note de version : Transformation profonde (utilisation de l'API, adaptation pour le modèle Averto, utilisation des notifs, plus de vérifications).
* Dernière révision : 20/04/21
<nowiki>
**/
mw.loader.using( [ 'mediawiki.util', 'mediawiki.api', 'mediawiki.notify' ], function() {
if (typeof window.RevertDiff === 'undefined' && location.href.match(/diff=/)) { //We're not already launched AND we're on a diff
window.RevertDiff = true;//We're alive !
if(!window.RevertDiffUserSettings) //Some settings, you may add one.
window.RevertDiffUserSettings = {};
if(window.RevertDiffUserSettings.Confirm === undefined)//Default value
window.RevertDiffUserSettings.Confirm = true;
//Some params.
var RevertDiffParams = {
/**
* Defines the available warns, in the template Averto on the french Vikidia (https://fr.vikidia.org/wiki/Template:Averto).
* The type is the template's parameter type, the title is the title of the section, the MaxLevel is the maximum level ("niveau=") available for that type.
* The Page is the template's Page. Automatically put, it is set to true if available for all levels or set to the max level where it is allowed.
* UserTalkPage tells that we need to return in parameter Page, if we're on a talk page, the page owner's username.
*/
AvailableWarns:{
Global:{Type:"Global",Title:"Avertissement", MaxLevel:5, Page:1},
Copyvio:{Type:"Copyvio",Title:"Violation de Copyright", MaxLevel:2, Page:1},
Encyclo:{Type:"Encyclo",Title:"Vikidia est une encyclopédie !", MaxLevel:3},
Polite:{Type:"Politesse",Title:"Politesse", MaxLevel:3, UserTalkPage:true},
Preview:{Type:"Prévisualisation",Title:"Merci de [[Aide:Prévisualisation|prévisualiser]] !", MaxLevel:1, Page:true},
Deleted:{Type:"SI",Title:"Article supprimé", MaxLevel:1, Page:true},
Spam:{Type:"Spam",Title:"Spam", MaxLevel:2, Page:1}
},
BlockFrom:2,//From which level (NON included) the warn template alerts the user that he will be blocked. Will require block permissions to apply it.
GroupBlock:"sysop",//Who can block ? (put the minimum group, if there is more, you may need to edit userIs to allow arrays)
GroupNoLimitMsg:"sysop",//Who doesn't have any limit in posting messages ?
MaxMsgNonInGroup:2,//How many msgs a user not in GroupNoLimitMsg can post
MsgPosted:0, //How many messages were posted. Logically we start at 0.
/**
* The predevined warns available. Name will be displayed in the button, Type represents the index in AvailableWarns, Level the level of the warn used.
* If you wish to add a predefined warn which is uses a level superior than the block level, plese check whether the user can block (userIs(GroupBlock)) before generating the buttons.
* It can be a good idea to define a PredefinedWarnsThatBlock for example.
*/
PredefinedWarns:[
{Name:"Averto 0", Type:"Global", Level:0},
{Name:"Averto 1", Type:"Global", Level:1},
{Name:"Averto 2", Type:"Global", Level:2},
{Name:"Averto politesse 0", Type:"Polite", Level:0},
{Name:"Averto spam 0", Type:"Spam", Level:1},
{Name:"Averto spam 1", Type:"Spam", Level:2},
{Name:"Averto spam 2", Type:"Spam", Level:2},
{Name:"Averto copyvio 0", Type:"Copyvio",Level:0}
],
Texts:{
//Restore
NoRestore: "Vous ne pouvez pas restaurer.",
Restore: "Restaurer",
RestoreConfirm: 'Révoquer les modifications de (entre autres) $1 pour restaurer celles de $0 ?',
RestoreGGBtn: "C'est fait !",
RestoreGGNotif: "L'ancienne modification a été restaurée avec succès !",
RestoreNoChange: "Aucun changement effectué.",
RestorePutReason: "Raison",
RestoreReasonPrompt: 'Indiquez ici la raison :',
RestoreSummary: 'Restauration (retour à la version de [[Special:Contributions/$0|$0]]).',
Restoring: "Restauration...",
//Patrol
Patrolling: "Marquage de la révision comme relue...",
//Warn/Msg
BlockReminder: "Pensez à bloquer l'utilisateur ;-)",
MaxWarnTrig: "Vous avez déposé le nombre maximum de messages autorisés.",
MsgAlreadyPost : "Attention, vous avez déjà déposé $0 message(s) à $1. En déposer un autre ?",
MsgGGBtn: "Message déposé !",
MsgGGNotif: 'Message déposé avec succès !',
SendingMsg: "Envoi du message...",
Warn: "Déposer un avertissement",
WarnConfirm: "Déposer un message à l'utilisateur $0 ?",
WarnPredefined: "Déposer un avertisement prédéfinis : ",
WarnSubmit: "Avertir",
Welcome: "Bienvenuter",
//Misc
ItsYou: "C'est vous !",
OuchError: "Aïe aïe aïe... ",
//Errors
ErrorInternal: "erreur interne.",
ErrorEditFail: "échec de la modification.",
//EditFail
EditFailErrCode: "Code de l'erreur : ",
'EditFail-abusefilter-disallowed': "Un filtre anti-abus a empéché la modification.",
'EditFail-abusefilter-warning': "Un filtre anti-abus demande à ce que vous confirmiez votre action en la répétant.",
'EditFail-blocked': "Vous êtes bloqué !",
'EditFail-default':"La page n'est peut-être pas modifiable par vous.",
'EditFail-protectedpage': "La page est protégée.",
'EditFail-undofailure': "Quelqu'un a modifié lorsque vous étiez sur le diff."
},
//To put a welcome message. Title is section's, MsgUser/MsgIp msg for respectively a registred user and an IP.
Welcome:{
Title:"Bienvenue",
MsgUser:'{{subst:Bienvenue}}--~~~~',
MsgIP:'{{subst:Bienvenue IP}}--~~~~'
}
};
//Return a text to be shown, with the id and the vals (values to replace the $.. in txt). Vals are given in the order it appears in the text ($0, $1...)
function RDtxt(id, vals) {
var Txt = RevertDiffParams.Texts[id];
if(Txt) {
if(Array.isArray(vals))
for(var i = 0, l = vals.length; i < l; i++)
Txt = Txt.split("$"+i.toString()).join(vals[i]); //replaceAll isn't currently supported enough
return Txt;
}
}
//Is the user sysop, bureaucrat... uses wgUserGroups to konw it.
function userIs(group) {
return (mw.config.get("wgUserGroups").indexOf(group) !== -1);
}
//Simple function so as not to repeat a mw.notify().
function Notify(text,type) {
mw.notify(text, {title:"RevertDiff", type:(type === undefined ? "info" : type)});
}
function NotifyFail(text) {//Adds a txt before the actual error message.
mw.notify(RDtxt('OuchError')+text, {title:"RevertDiff", type:"error"});
}
//Will update the max level available, depending on the type and if the user can block.
function updateLevelList() {
var TypeSelected = $("#sel-RD-type").val(), //Which Type of warn is selected
$LevelNum = $("#num-RD-level")[0];
if(TypeSelected.length > 0){//We selected a warn
var WarnMaxLvl = RevertDiffParams.AvailableWarns[TypeSelected].MaxLevel, //First what's the max lvl of the warn ?
MaxLevel = userIs(RevertDiffParams.GroupBlock) ? WarnMaxLvl : (Math.min(WarnMaxLvl, RevertDiffParams.BlockFrom)); //Then we lower the max lvl to a non blocking lvl if the user can't block.
$LevelNum.max = MaxLevel;
}
$LevelNum.disabled = TypeSelected.length === 0; //Enable the field only if we've selected a type of warning.
}
//Function that edits the page with title title using params, and call successCaalback on success (passing response in arg).
//If there is a fail, call editFailed with the code for parameter.
//Do not mess this with mw.Api.edit, as this last returns the current revisions to make edits on it, here we just send parameters.
//And moreover Vikidia does not support mw.Api.edit (and not even mw.Api.newSection).
function editPage(title, params, successCallback) {
var Api = new mw.Api(),
Settings = {
action:"edit",
format:"json",
title:title
};
Object.assign(Settings,params);
Api.postWithToken('csrf', Settings).then(function(response) {//Let's go !
//We're sure of a success only if this is like this. Sometimes it fails (for example with AbuseFilter) but it doesn't send an "error" object.
if(response.edit.result === "Success") {
successCallback(response);
} else {
editFailed(response.edit.code);//If no success then fail.
}
}).fail(function(code) {
editFailed(code);//Same here
});
}
//Restore, but ask and check a given reason.
function restoreReason(oldId,user1,user2) {
var Reason = prompt(RDtxt("RestoreReasonPrompt"));
if(Reason) //putting a summary is mandatory (if you wanted to put a custom one)
restore(oldId,user1,user2,Reason); // We then just call the main function.
}
//Restore an older edit (oldId, made by user1) overriding the edit from user2 and other users above, perhaps using a customReason.
function restore(oldId,user1,user2,customReason){
//If customReason is defined, then the user already "confirmed" by putting a summary.
if(customReason === undefined && window.RevertDiffUserSettings.Confirm === true && !confirm( RDtxt('RestoreConfirm', [user1, user2]) ))
return;
Notify(RDtxt('Restoring'),"info");//So the users doesn't feel like waiting for nothing
var Summary = (customReason ? customReason + ' - ' : "") + RDtxt('RestoreSummary', [user1]); //We always put the RestoreSummary but we may add a customReason.
editPage(mw.config.get('wgPageName'), {
undo:oldId, //Undo until oldId
undoafter:mw.config.get('wgCurRevisionId'), //We need to tell mw from which edit to which edit we want to override
summary:Summary
}, function(response) {
if(response.edit.nochange !== undefined)//Not very useful, just to be more precise.
Notify(RDtxt('RestoreNoChange'),"info");
else
Notify(RDtxt('RestoreGGNotif'),'success');
$("#span-RD-restore").text(RDtxt('RestoreGGBtn')); //No need of it anymore
var PatrolLinkElt = $("#mw-diff-ntitle4 > .patrollink > a"); //Can we patrol = is the button-link "Mark as patrolled" present ?
if(PatrolLinkElt.length === 1) {
Notify(RDtxt('Patrolling'));
PatrolLinkElt[0].click();//The link already shows an animation and a notif when clicked.
}
});
}
//Warns user, with a warn of type type, at a level of level, and has been triggered by the element triggerer.
function warnUser(user, type, level, triggerer) {
var WarnObj = RevertDiffParams.AvailableWarns[type];//First let's fetch our warn.
if(!WarnObj) {//Uh oh
NotifyFail(RDtxt("ErrorInternal"));
return;
}
var Msg = '{{subst:Averto|type=';//The template starts by this, always. There are a type and a "niveau" parameter.
Msg += WarnObj.Type+
'|niveau='+
level; //The mandatory is down
if(WarnObj.Page === true || WarnObj.Page <= level) {//Do we want a Page argument ?
Msg += '|page=' + mw.config.get('wgPageName');
}
else if((WarnObj.UserTalkPage === true || WarnObj.UserTalkPage <= level) && //or a Page arguments that refers to a user talk page ?
mw.config.get("wgNamespaceNumber") === 3) {//But are we on a User talk: namespace ?
Msg += '|page=' + mw.config.get('wgRelevantUserName');//Using the name of the user who owns the talk page.
}
Msg += '}} ~~~~'; //We always finish by this.
//If we need to block, we remind the user by adding an additionnal sucess msg.
postMessage(Msg, WarnObj.Title, user, (level > RevertDiffParams.BlockFrom ? RDtxt('BlockReminder') : ''), triggerer);
}
//Welcomes user, using a message for IPs if the user isIP, and has been triggered by the elt $triggerer.
function welcomeUser(user, isIP, triggerer) {
var Welcome = RevertDiffParams.Welcome;
postMessage( (isIP ? Welcome.MsgIP : Welcome.MsgUser), RevertDiffParams.Welcome.Title, user, null, triggerer);
}
//Protection against accidental usages and usage of posting system. A non sysop user cannot post more than MaxMsgNonInGroup message(s).
function confirmPost(user) {
var UserCanPost = userIs(RevertDiffParams.GroupNoLimitMsg) || (RevertDiffParams.MsgPosted < RevertDiffParams.MaxMsgNonInGroup);
if(UserCanPost) {
var ConfirmMsg = "";
if(RevertDiffParams.MsgPosted > 0) {//Already posted a message = confirmation mandatory
ConfirmMsg = RDtxt("MsgAlreadyPost", [RevertDiffParams.MsgPosted,user]);
} else if(window.RevertDiffUserSettings.Confirm === true) { //Otherwise, did the user asked to confirm ?
ConfirmMsg = RDtxt('WarnConfirm', [user]);
} else { //Or else no confirmation
return true; //If he can post and there is no reason to ask for confirmation, then returns true.
}
return confirm(ConfirmMsg); //Ask for confirmation
}
alert(RDtxt('MaxWarnTrig'));
return false; //No way: the user can't post anymore
}
//Posts to user a message, that contains msg and has for title title. Will add additionnalSuccessMsg to the success notif if it's set.
//Triggered by elt $triggerer.
function postMessage(msg, title, user, additionnalSuccessMsg, triggerer) {
if (!confirmPost(user))//Can the user post ?
return;
Notify(RDtxt('SendingMsg'),"info"); //Wait little user, be patient !
editPage("User talk:"+user, {
section:"new",
sectiontitle:title,
text:msg
}, function() {
switch(triggerer.nodeName) {//The action we do on the elt depends of what is it
case "BUTTON": //We disable and change the txt
triggerer.disabled = true;
triggerer.textContent = RDtxt('MsgGGBtn');
break;
case "FORM": //We reset it
triggerer.reset();
break;
}
Notify(RDtxt('MsgGGNotif')+ (additionnalSuccessMsg ? ' '+additionnalSuccessMsg : ''), 'success');
RevertDiffParams.MsgPosted++;//To remind the user he already posted one !
});
}
//Function to tell that an edit failed and gives a clue about why.
function editFailed(code) {
var Msg = "";
switch (code) {
case "abusefilter-disallowed":
case "abusefilter-warning":
case "undofailure":
case "protectedpage":
case "blocked":
Msg = RDtxt("EditFail-"+code);//We defined the txt way earlier
break;
default:
Msg = RDtxt("EditFail-default") + (code ? (" "+RDtxt("EditFailErrCode")+code) : "");//If the code is defined then let's put it anyway.
}
NotifyFail(RDtxt("ErrorEditFail")+" "+Msg);
}
$(document).ready(function (){ //Aight, let's init
// Get username of submitter
var User1TD = $('td.diff-otitle');
var User2TD = $('td.diff-ntitle');
if (!User1TD.length || !User2TD.length){//Whoops
NotifyFail(RDtxt("ErrorInternal"));
return;
}
// Fetching the oldid
var OldId = mw.util.getParamValue("oldid", User1TD.find('span.mw-diff-edit a').attr('href')); //This is the link to edit the old version that we use ("(edit)" is displayed on the UI).
var User1A = User1TD.find('a.mw-userlink'),//This time the link to the user page...
User2A = User2TD.find('a.mw-userlink'),
User1Name = User1A.text(),// Finnally the text
User2Name = User2A.text(),
RestoreHTML, MessagesHTML;//And let's init.
//Can we edit the curr page ? This variable may do false-positive (that will be catched anyway by a nice failure notification) but no false negative.
if(mw.config.get("wgIsProbablyEditable")) {
RestoreHTML = '(<span id=span-RD-restore><button id=btn-RD-restore>'+RDtxt('Restore')+'</button>'//The span will permit the override of the button when we will finish the restoration.
+ '-'
+ '<button id=btn-RD-restore-sum>'+RDtxt('RestorePutReason')+'</button></span>)';//We can choose a custom reason or not.
} else {
RestoreHTML = "("+RDtxt("NoRestore")+")";//If we can't it's a little easier
}
//We're not going to warn ourselves !
if(mw.config.get("wgUserName") !== User2Name) {
var WarnsHTML = '('+RDtxt('Warn')+' : ';//First warning the user
//Showing a form to select any kind of warn we want that is usable in the template.
//We've a "no selection" option to prevent miss-clicks (amongst with the "required" option on the select).
WarnsHTML += '<form id=form-RD-warn><select id=sel-RD-type name=sel-RD-type required><option value="">---</option>';//Forms
for(var Warn in RevertDiffParams.AvailableWarns)
WarnsHTML += '<option value="'+Warn+'">'+RevertDiffParams.AvailableWarns[Warn].Type+'</option>';//Each of types available
WarnsHTML += '</select> <input id=num-RD-level name=num-RD-level min=0 value=0 step=1 type=number disabled required /> '+//the level selector (num)
'<input type=submit id=sub-RD-warn value="'+RDtxt("WarnSubmit")+'" /></form>) ';//The submit btn
WarnsHTML += '('+RDtxt("WarnPredefined");//Now the predefined warns :
for(var id=0,l=RevertDiffParams.PredefinedWarns.length; id<l; id++){
if(id!==0) WarnsHTML += '-';//If we aren't at the end of the list add a separator.
WarnsHTML += "<button id=btn-RD-predef-warn-"+id+">"+RevertDiffParams.PredefinedWarns[id].Name+'</button>';//A nice btn.
}
WarnsHTML += ')';//Finished with warns.
//Welcoming the user.
var WelcomeTxt = '(<button id=btn-RD-welcome>'+RDtxt('Welcome')+'</button>)';
MessagesHTML = WarnsHTML + " " + WelcomeTxt;//Now we have our html for the messages.
} else {
MessagesHTML = '('+RDtxt('ItsYou')+')';//Not gonna warn myself.
}
$("#contentSub").append("<div id=div-RD-main>"+RestoreHTML+" " +MessagesHTML+"</div>"); //Let's add ourself just below the title.
//Now let's bind some events.
if(mw.config.get("wgIsProbablyEditable")) //There is no btn if we can't edit.
$("button[id^=btn-RD-restore]").on("click", function(e) {
// If the id is btn-RD-restore-sum, we want to set a custom summarry.
var Func = (e.target.id === "btn-RD-restore-sum" ? restoreReason : restore);//Which fn to use ?
Func(OldId, User1Name, User2Name);
});
if(mw.config.get("wgUserName") !== User2Name) { //Same but it is because we don't warn ourselves.
$("button[id^=btn-RD-predef-warn-]").on("click", function(e) { //Predefined warns
var PredefinedWarn = RevertDiffParams.PredefinedWarns[e.target.id.slice(19,21)];
warnUser(User2Name, PredefinedWarn.Type, PredefinedWarn.Level, e.target);
});
$("#btn-RD-welcome").on("click", function(e) { //Welcome
var IsIP = User2A.hasClass("mw-anonuserlink"); //Is the link for an IP ?
welcomeUser(User2Name, IsIP, e.target);
});
$("#sel-RD-type").on("change", updateLevelList); //Change warn type = update the max lvl available
$("#form-RD-warn").on("submit", function(e){
warnUser(User2Name, $("#sel-RD-type").val(), $("#num-RD-level").val(),e.target);
e.returnValue = false;//We don't reload the page here !
e.preventDefault();
});
}
});
}//End of testing if we can use RevertDiff
});//End of closure
//</nowiki>