MediaWiki:Gadget-Evaluation.js

Note : après avoir enregistré la page, vous devrez forcer le rechargement complet du cache de votre navigateur pour voir les changements.

Mozilla / Firefox / Konqueror / Safari : maintenez la touche Majuscule (Shift) en cliquant sur le bouton Actualiser (Reload) ou pressez Maj-Ctrl-R (Cmd-R sur Apple Mac) ;

Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5.
/* adapté de [[MediaWiki:Gadget-Evaluation.js]] (version du 12 septembre 2008) par Chphe
* {{Projet:JavaScript/Script|Evaluation}}
*/

//<source lang="javascript">//<pre><nowiki>

/* eslint-env browser */
/* jshint esversion: 6, laxbreak: true */
/* globals mw, $ */

if ( mw.config.get( 'wgNamespaceNumber' ) === 0 && mw.config.get( 'wgAction' ) === 'view' ) {
	mw.loader.using( [ 'mediawiki.util', 'mediawiki.api', 'user' ], function () {
		$( ev_addEvalTab );
	} );
}

function ev_addEvalTab( $ ) {
	var portletLink = mw.util.addPortletLink( 'p-cactions', '#', 'Évaluer', 'ca-evaluer' );

	$( portletLink ).click( function ( e ) {
		e.preventDefault();
		ev_launchEval();
	} );

	if ( window.alwaysEval ) {
		ev_launchEval();
	}
}

function ev_launchEval() {
	if ( mw.util.getParamValue( 'printable' ) === 'yes' ) {
		/* version imprimable */
		return;
	}

	var EvalDiv = $('#EvalDiv');
	if (!EvalDiv.length) {
		EvalDiv = $('<div>').attr({
			id: 'EvalDiv',
			class: 'center'
		});
		$('#mw-content-text').prepend(EvalDiv);
	}

	// Initialisation des variables
	if ( typeof window.initEvalProjectNames !== "undefined" ) {
		window.initEvalProjectNames();
	} else {
		window.evalProjectNames = [];
	}

	window.evaluation_portails = [];

	window.evaluation_multiprojets = {};
	window.evaluation_multiprojets.project = [];
	window.evaluation_multiprojets.portailPresent = [];
	window.evaluation_multiprojets.importance = [];
	window.evaluation_multiprojets.state = [];
	window.evaluation_multiprojets.avancement_global = "?";
	window.evaluation_multiprojets.autres = {}; // pour ramasser le reste (WP1.0, todo, wikiconcours, ...)

	window.estHomonymie = false;

	// 1 - Détermination du statut ou non d'homonymie
	EvalDiv.html("Détermination du statut d'homonymie...");
	new mw.Api()
	.get({
		action: 'query',
		format: 'json' ,
		titles: mw.config.get( 'wgPageName' ),
		prop: 'pageprops',
		ppprop: 'disambiguation',
		formatversion: 2
	})
	.done( function ( results ) {
		window.estHomonymie = 'pageprops' in results.query.pages[0];
		ev_ExtractPortail();
	});
}

function ev_ExtractPortail() {
	// 2 - Détermination de la liste des portails liés par les catégories
	$('#EvalDiv').html("Détermination des portails liés...");

	var liste_remplacements = {
		"Allemagne": "Monde germanique", "Autriche": "Monde germanique", "Liechtenstein": "Monde germanique",
		"Révolution française": "Révolution et Empire", "Premier Empire": "Révolution et Empire",
		"Arts martiaux et sports de combat": "Arts martiaux",
		"Monde celtique": "Celtes",
		"Lacs et cours d'eau": "Cours d'eau",
		"Canidés": "Cynophilie",
		"Vexillologie": "Drapeaux",
		"Égypte antique": "Egyptopedia",
		"Grèce antique": "Hellenopedia",
		"Intercommunalités de France": "Intercommunalités françaises",
		"Iran et monde iranien": "Iran",
		"Arménie/Monastères arméniens": "Monastères arméniens",
		"Motocyclette": "Moto",
		"Bois et forêt": "Sylvipédia"
	};
	var reg_portail = /^Catégorie:Portail:([^\/]*)/; // eslint-disable-line no-useless-escape

	new mw.Api()
	.get({
		action: 'query',
		format: 'json',
		prop: 'categories',
		titles: mw.config.get( 'wgPageName' ),
		clshow: "hidden",
		cllimit: 500,
		formatversion: 2
	})
	.done( function ( results ) {
		var categories = results.query.pages[0].categories;
		if (categories) {
			for (var i = 0; i < categories.length; i++) {
				var m = reg_portail.exec( categories[i].title );
				if (m !== null && m[1] && !window.evaluation_portails.includes(m[1])){
					if (m[1] in liste_remplacements) {
						window.evaluation_portails.push(liste_remplacements[m[1]]);
					} else {
						window.evaluation_portails.push(m[1]);
					}
				}
			}
		}
		if (window.evaluation_portails.length !== 0) {
			ev_ExtractPortailSansProjet ();
		} else if (window.estHomonymie) {
				$('#EvalDiv').html("Les pages d'homonymie sans portail associé ne doivent pas être évaluées.");
		} else {
			ev_ExtractEvaluation();
		}
	});
}

function ev_ExtractPortailSansProjet () {
	// 3 - Retrait des portails sans projet associé de la liste
	$('#EvalDiv').html("Recherche des projets d'évaluation associés aux portails liés...");

	var regex = /Catégorie:Évaluation des articles du projet (.*)/;

	new mw.Api()
	.get({
		action: 'query',
		format: 'json',
		prop: 'info',
		titles: window.evaluation_portails.map( portail => 'Catégorie:Évaluation des articles du projet ' + portail ),
		formatversion: 2
	})
	.done( function ( results ) {
		var pages = results.query.pages;
		if (pages !== undefined) {
			for (var j = 0; j < pages.length; j++) {
				var match = regex.exec(pages[j].title);
				if (match !== null && 'missing' in pages[j]) {
					var idx = window.evaluation_portails.indexOf( match[1] );
					if (idx !== -1) {
						window.evaluation_portails.splice(idx, 1);
					}
				}
			}
		}
		ev_ExtractEvaluation();
	});
}

function ev_ExtractEvaluation() {
	// 4 - Lecture du modèle Wikiprojet
	$('#EvalDiv').html("Interrogation de la page de discussion...");

	new mw.Api()
	.get({
		action: 'query',
		titles: mw.config.get( 'wgFormattedNamespaces' )[1] + ':' + mw.config.get( 'wgPageName' ),
		prop: 'revisions',
		rvprop: 'content',
		rvslots: 'main',
		formatversion: 2
	})
	.done( function ( results ) {
		var page = results.query.pages[0];
		window.evaluation_multiprojets.pdd_existe = !page.missing;
		if ( !page.missing ) {
			var pageContent = page.revisions[0].slots.main.content;

			var reg_modele_multiprojet = /{{[wW]ikiprojet\s*\|([^{]*(({{[^{}]+?}}[^{]*?)*?)?)}}/;
			var m = reg_modele_multiprojet.exec( pageContent );
			if ( m ) {
				var reg_pipe = /({{[^}]*}})/g;
				var n = m[1].replace( reg_pipe, function ( match ) { return match.replace( /\|/g, "{{subst:!}}" ); } );
				var tab = n.split( "|" );
				var i = 0;
				var ind = window.evaluation_multiprojets.project.length;
				while ( i < tab.length ) {
					var t = tab[i].split( "=" );
					if ( t.length === 2 ) {
						if ( t[0].trim() === "avancement" ) {

							var avanc = t[1].trim().toLowerCase();
							var clean_avancement = {
								"adq": "AdQ",
								"ba": "BA",
								"a": "A",
								"b": "B",
								"bd": "BD",
								"ébauche": "ébauche",
								"e": "ébauche",
								"homonymie": "homonymie"
							};
							window.evaluation_multiprojets.avancement_global = clean_avancement[avanc] || "?";

						} else {
							window.evaluation_multiprojets.autres[t[0]] = t[1].trim();
						}
					} else if ( t.length === 1 ) {
						var _proj = tab[i].trim();
						window.evaluation_multiprojets.project[ind] = _proj;
						if ( i === tab.length - 1 ) alert( "Erreur de lecture du modèle {{Wikiprojet}}" );
						var imp = tab[i + 1].trim().toLowerCase();
						if ( imp === "faible" || imp === "moyenne" || imp === "élevée" || imp === "maximum" ) {
							window.evaluation_multiprojets.importance[ind] = imp;
						} else {
							window.evaluation_multiprojets.importance[ind] = "?";
						}
						window.evaluation_multiprojets.state[ind] = true;
						window.evaluation_multiprojets.portailPresent[ind] = false;
						ind++;
						i++;
					}
					i++;
				}
			}
		}
		if (window.evaluation_multiprojets.project.length !== 0) {
			ev_ResolveAlias();
		} else {
			ev_drawEvaluation();
		}
	});
}

function ev_ResolveAlias() {
	// 5 - Résolution des alias via {{Wikiprojet/alias}}
	$('#EvalDiv').html("Résolution des alias de projet...");

	new mw.Api()
	.get({
		action: 'parse',
		format: 'json',
		text: window.evaluation_multiprojets.project.map( projet => '{{Wikiprojet/alias|projet=' + projet + '}}' ).join( ';' ),
		contentmodel: 'wikitext',
		rvslots: 'main'
	})
	.done( function ( results ) {
		var parsedContent = results.parse.text['*'];
		var match = parsedContent.match(/<p>((.|\n)*?)<\/p>/);
		if (match) {
			var projetsResolu = match[1].split(";");
			for (var i = 0; i < projetsResolu.length; i++) {
				window.evaluation_multiprojets.project[i] = projetsResolu[i].trim();
			}
		}
		ev_drawEvaluation();
	});
}

function ev_drawEvaluation() {
	// Ajout des portails présents à la liste des projets

	for ( var i = 0; i < window.evaluation_portails.length; i++ ) {
		if ( window.evaluation_multiprojets.project.indexOf( window.evaluation_portails[i] ) !== -1 ) {
			window.evaluation_multiprojets.portailPresent[window.evaluation_multiprojets.project.indexOf( window.evaluation_portails[i])] = true;
		} else if (typeof window.noPortalEvals === "undefined" || !window.noPortalEvals) {
			var t = window.evaluation_multiprojets.project.length;

			window.evaluation_multiprojets.project[t] = window.evaluation_portails[i];
			window.evaluation_multiprojets.importance[t] = "?";
			window.evaluation_multiprojets.state[t] = false;
			window.evaluation_multiprojets.portailPresent[t] = true;
		}
	}

	// Ajout des projets notés dans le common.js de l'utilisateur à la liste des projets à afficher

	for ( var j = 0; j < window.evalProjectNames.length; j++ ) {
		if ( window.evaluation_multiprojets.project.indexOf( window.evalProjectNames[j] ) === -1 ) {
			var u = window.evaluation_multiprojets.project.length;

			window.evaluation_multiprojets.project[u] = window.evalProjectNames[j];
			window.evaluation_multiprojets.importance[u] = "?";
			window.evaluation_multiprojets.state[u] = false;
			window.evaluation_multiprojets.portailPresent[u] = false;
		}
	}

	// Construction de l'outil d'évaluation

	var tab = $("<table>")
		.addClass('wikitable')
		.css({
			'text-align': 'center',
			'font-size': '90%'
		})
		.append(
			$('<tr>').append(
				$('<td>')
					.html('<b>Avancement commun</b>')
					.attr('rowSpan', 2),
				[
					{ titre: "AdQ", couleur: "6699FF" },
					{ titre: "BA", couleur: "66FF66" },
					{ titre: "A", couleur: "66FFFF" },
					{ titre: "B", couleur: "FFFF66" },
					{ titre: "BD", couleur: "FFAA66" },
					{ titre: "Ébauche", couleur: "FF6666" },
					{ titre: "?", couleur: "F8F8F8" },
					...(window.estHomonymie ? [{ titre: "Homonymie", couleur: "66FF66" }] : [])
				]
				.map(({ titre, couleur }) => {
					return $("<td>")
						.html('<b>' + titre + '</b>')
						.css('background-color', '#' + couleur);
					})
			),
			$('<tr>').append(
				[ "AdQ", "BA", "A", "B", "BD", "ébauche", "?", ...(window.estHomonymie ? ["homonymie"] : []) ].map( value => {
					return $("<td>").append(
						$("<input>")
							.attr("type", "radio")
							.attr("name", "ag_mp")
							.prop("checked", window.evaluation_multiprojets.avancement_global === value)
							.on("click", function () {
								window.evaluation_multiprojets.avancement_global = value;
							})
					);
				})
			)
	);

	var tab2 = $("<table>")
		.addClass('wikitable')
		.css({
			'text-align': 'center',
			'font-size': '90%'
		})
		.append(
			$('<tr>').append(
				[
					{ titre: "Projet", couleur: "F8F8F8" },
					{ titre: "Évaluation", couleur: "F8F8F8" },
					{ titre: "Portail présent", couleur: "F8F8F8" },
					{ titre: "Maximum", couleur: "FF00FF" },
					{ titre: "Élevée", couleur: "FF88FF" },
					{ titre: "Moyenne", couleur: "FFCCFF" },
					{ titre: "Faible", couleur: "FFEEFF" },
					{ titre: "?", couleur: "F8F8F8" }
				]
				.map(({ titre, couleur }) => {
					return $("<td>")
						.html('<b>' + titre + '</b>')
						.css('background-color', '#' + couleur);
					})
			)
		);

	// "k" doit être en block scope (i.e. let), car il est utilisé dans des event handlers définis dans la boucle
	for ( let k = 0; k < window.evaluation_multiprojets.project.length; k++ ) {
		var project = window.evaluation_multiprojets.project[k];
		tab2.append(
			$('<tr>').append(
				$('<td>').append(
					$('<a>')
						.attr('href', mw.util.getUrl('Projet:' + project))
						.attr('title', 'Projet:' + project)
						.text(project)
				),
				$('<td>').append(
					$('<input>').attr({
						id: 'evc_' + k,
						type: 'checkbox',
						checked: window.evaluation_multiprojets.state[k]
					}).on('click', function () {
						window.evaluation_multiprojets.state[k] = this.checked;
					})
				),
				$('<td>').append(
					$('<input>').attr({
						type: 'checkbox',
						checked: window.evaluation_multiprojets.portailPresent[k],
						disabled: true
					}).on('click', function () {
						window.evaluation_multiprojets.portailPresent[k] = this.checked;
					})
				),
				[ "maximum", "élevée", "moyenne", "faible", "?" ].map( value => {
					return $("<td>").append(
						$("<input>")
							.attr("type", "radio")
							.attr("name", k + "i")
							.prop("checked", window.evaluation_multiprojets.importance[k] === value)
							.on("click", function () {
								window.evaluation_multiprojets.importance[k] = value;
								window.evaluation_multiprojets.state[k] = true;
								$( "#evc_" + k).prop("checked", true);
							})
						);
					})
				)
		);
	}

	// Création du champ de recherche et du bouton pour ajouter un projet manuellement

	var cont_addProject = $("<div>").attr("id", "addProject");
	var lbl_addProject = $("<label>").text("Ajouter un projet : ");
	var input_addProject = $("<input>").attr({
		type: "text",
		id: "input_addProject",
//		size: "64"
	})
	.on('keyup', function (e) {
		if (e.key === 'Enter' || e.keyCode === 13) {
			ev_addProject();
		}
	});
	mw.loader.using( [ "jquery.ui" ], function () { input_addProject.autocomplete( { source: ev_autocomp } ); } );
	var btn_addProject = $( '<button>' )
		.text( 'Ajouter' )
		.attr( 'id', 'btn_addProject' )
		.click( ev_addProject );
	cont_addProject.append(lbl_addProject, input_addProject, btn_addProject);

	// Bouton de sauvegarde des modifications

	var btn_setEvaluation = $( '<button>' )
		.text( 'Exporter cette évaluation vers la page de discussion' )
		.attr( 'id', 'EvalButton' )
		.css( 'margin-top', '1em' )
		.click( ev_setEvaluation );

	// Ajout de tous les éléments à la page

	$( '#EvalDiv' )
		.empty()
		.append( tab, tab2, cont_addProject, btn_setEvaluation );
}

function ev_autocomp (request, response) {
	if (/[{}|<>\[\]]/.test(request.term)) { // eslint-disable-line no-useless-escape
		response([]);
		return;
	}
	var commonPrefix = 'Évaluation des articles du projet ';
	var prefix = commonPrefix + request.term.substr(0, 1).toUpperCase() + request.term.substr(1);
	var query = {format: 'json', action: 'query', list: 'allpages', apprefix: prefix, apnamespace: 14, rawcontinue: ''};
	$.getJSON(mw.util.wikiScript('api'), query, function (obj) {
		var projets = [];
		for (var i = 0; i < obj.query.allpages.length; i++) {
			var category = obj.query.allpages[i].title;
			projets.push(category.substr(category.indexOf(':') + 1 + commonPrefix.length));
		}
		if (projets.length == 1 && projets[0] == request.term) {
			response([]);
		} else {
			response(projets);
		}
	});
}

function ev_addProject() {
	var val = $( '#input_addProject' ).val();
	if (val && val !== "") {
		if ( window.evaluation_multiprojets.project.indexOf( val ) !== -1 ) {
			window.evaluation_multiprojets.state[window.evaluation_multiprojets.project.indexOf( val )] = true;
		} else {
			window.evaluation_multiprojets.project.push(val);
			window.evaluation_multiprojets.importance.push("?");
			window.evaluation_multiprojets.state.push(true);
			window.evaluation_multiprojets.portailPresent.push(false);
		}
		ev_drawEvaluation();
	}
}

function ev_setEvaluation() {
	$('#EvalButton').prop('disabled', true);
	var talkpage = mw.config.get( 'wgFormattedNamespaces' )[1] + ':' + mw.config.get( 'wgPageName' );
	var summary = "[[Projet:Scripts et gadgets/Notices/Evaluation|Évaluation]]\xA0: Multiprojet (" + window.evaluation_multiprojets.avancement_global + ")";
	for ( var i = 0; i < window.evaluation_multiprojets.project.length; i++ ) {
		if ( window.evaluation_multiprojets.state[i] ) {
			summary += " " + window.evaluation_multiprojets.project[i] + "|" + window.evaluation_multiprojets.importance[i];
		}
	}
	summary += ")";
	if ( window.evaluation_multiprojets.pdd_existe ) {
		new mw.Api()
			.edit( talkpage, function ( revision ) {
				return {
					text: ev_processText( revision.content ),
					summary: summary
				};
			} )
			.done( function ( ) {
				$('#EvalButton').prop('disabled', false);
				mw.notify('Évaluation mise à jour avec succès.', { type: 'success'});
			});
	} else {
		new mw.Api()
			.create( talkpage, { summary: summary }, ev_processText( '' ) )
			.done( function ( ) {
				$('#EvalButton').prop('disabled', false);
				mw.notify('Évaluation mise à jour avec succès.', { type: 'success'});
			});
	}
}

function ev_processText( text ) {

	// Mise à jour des paramètres du modèle

	var regtxt = /\{\{[wW]ikiprojet\s*\|[^}]*\}\}/;
	var newtxt = "{{Wikiprojet";
	var regtodo = /\{\{([tT]odo\|?\*?|[àÀ] faire\|?\*?)\}\}/;
	var ok = false;
	var i;
	for ( i = 0; i < window.evaluation_multiprojets.project.length; i++ ) {
		if ( window.evaluation_multiprojets.state[i] ) {
			newtxt += "\n|{{subst:Wikiprojet/alias|projet="
				+ window.evaluation_multiprojets.project[i]
				+ "}}|"
				+ window.evaluation_multiprojets.importance[i];
			ok = true;
		}
	}
	ok = ok || ( window.evaluation_multiprojets.avancement_global !== "?" );
	newtxt += "\n|avancement=" + window.evaluation_multiprojets.avancement_global;

	for ( const [ i, autre ] of Object.entries( window.evaluation_multiprojets.autres ) ) {
		newtxt += "\n|" + i + "=" + autre;
	}
	newtxt += "\n}}";

	if ( ok ) {
		if ( regtxt.test( text ) ) {
			text = text.replace( regtxt, newtxt );
		} else {
			text = newtxt + "\n" + text;
		}
		text = text.replace( regtodo, "" );
	}

	// Modèle {{Traduit de}} remis en tête de page de discussion

	var reg = /(\{\{[tT]raduit de\s*\|[^}]*\}\})/;
	var m = reg.exec( text );
	if ( m ) {
		var left = RegExp.leftContext;
		var right = RegExp.rightContext;
		text = m[1]
			+ "\n"
			+ left.trimEnd()
			+ "\n"
			+ right.trimStart();
	}
	return text;
}
//</nowiki></pre></source>