Utilisateur:Seudo/sd renommage.js

La bibliothèque libre.

Note : après avoir enregistré vos modifications, il se peut que vous deviez forcer le rechargement complet du cache de votre navigateur pour voir les changements.

  • Firefox / Safari : Maintenez la touche Maj (Shift) en cliquant sur le bouton Actualiser ou pressez Ctrl-F5 ou Ctrl-R (⌘-R sur un Mac) ;
  • Google Chrome : Appuyez sur Ctrl-Maj-R (⌘-Shift-R sur un Mac) ;
  • Internet Explorer : Maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5 ;
  • Opera : Allez dans Menu → Settings (Opera → Préférences sur un Mac) et ensuite à Confidentialité & sécurité → Effacer les données d'exploration → Images et fichiers en cache.
/* Script de renommage de page. EXPÉRIMENTAL (pas encore utilisé sur un exemple réel).

Décale (positivement ou négativement) une plage de pages appartenant à un même livre et peut être utilisé lorsque des pages ont été ajoutées ou supprimées dans un fac similé. Par exemple, il renommera les pages Page:Mon livre.djvu/100 à Page:Mon livre.djvu/120 en pages Page:Mon livre.djvu/105 à Page:Mon livre.djvu/125.

Pour utiliser ce script, ajouter la ligne suivante dans votre fichier common.js :
  importScript('Utilisateur:Seudo/sd_renommage.js')

Le script apparaît alors sous le nom « Sd renommage » dans le menu « Plus » (ou ailleurs). Il demande le nom du livre (exemple : Livre:Mon livre.djvu), le numéro de la première et de la dernière page (exemple : 100 et 120) à décaler ainsi que l’ampleur du décalage (exemple : 5).

Pour l’instant, il demande une confirmation à chaque page et peut donc être long à utiliser sur un gros livre. Une fois stabilisé, on pourra réduire le nombre de confirmations.
*/

const API_USER_AGENT = "User:Seudo/sd_renommage.js";

function get_token() {
    let promise = getAjax('https://fr.wikisource.org/w/api.php', {
        data: {
            "action": "query",
            "format": "json",
            "meta": "tokens"
        },
        headers: { 'Api-User-Agent': API_USER_AGENT },
        xhrFields: {
            withCredentials: true
        },
        datatype: "json"
    }).then(function(json) {
        if(json.query && json.query.tokens && json.query.tokens.csrftoken) {
            let token = json.query.tokens.csrftoken;
            console.log("Récupéré de l'API le token : " + token);
            return token; 
        }
        else {
            console.log(json);
            throw "Token non renvoyé";
        }
    }).fail(function(jqXHR, textStatus, errorThrown) {
        console.log("" + textStatus + ", " + errorThrown);
        alert("Erreur lors de la récupération du token : " + textStatus);
    });
    return promise;
}

$( function($) {
	nom_script = "Utilisateur:Seudo/sd_renommage.js";
	
	mw.util.addPortletLink('p-cactions',
		'#',
		'Sd renommage',
		'sd-renommage',
		'Renommage');

	// Fonction de renommage (récursive, s'arrête à la première erreur)
	function movePages(args) {
		// On renomme la page correspondant à args.premier, puis on passe à la suivante par récursion
		frompage = args.page_base + "/" + args.premier;
		topage = args.page_base + "/" + (args.premier + args.nbdecal);
		if(! confirm("Déplacement de " + frompage + " vers " + topage + "...")) {
			pluriel = (args.nbdone >= 2 ? "s" : "");
			alert("Arrêt : " + args.nbdone + " page" + pluriel + " renommée" + pluriel + ".");
			return;
		}

		// Renommage effectif...
        get_token()
        .then(function(token) {
		    return $.ajax({
    			url: mw.util.wikiScript('api'),
	 		    type: 'POST',
			    dataType: 'json',
    			data: {
	    			format: 'json',
    				action: 'move',
    				from: frompage,
    				to: topage,
    				reason: args.reason,
    				movetalk: true,
    				noredirect: 1,
    				token: token
    			}
            })
		})
		.done(function(data) {
			if (data && data["move"]) {
				// Le renommage a réussi
				args.nbdone += 1;
				next_premier = (args.nbdecal > 0 ? args.premier - 1 : args.premier + 1);
				if((args.nbdecal > 0 && next_premier < args.dernier) || (args.nbdecal < 0 && next_premier > args.dernier)) {
					// On a fini de tout renommer
					pluriel = (args.nbdone >= 2 ? "s" : "");
					alert("Succès : " + args.nbdone + " page" + pluriel + " renommée" + pluriel + ".");
				}
				else {
					args.premier = next_premier;
					movePages(args); // Appel récursif pour le suivant
				}
			} 
			else {
				pluriel = (args.nbdone >= 2 ? "s" : "");
				errmsg = "La requête a renvoyé une erreur : " 
					+ (data.error && data.error.info ? data.error.info : JSON.stringify(data)) 
					+ " (" + args.nbdone + " page" + pluriel + " renommée" + pluriel + ").";
				alert(errmsg);
			}
		})
		.fail(function(data) {
			pluriel = (args.nbdone >= 2 ? "s" : "");
			errmsg = "La requête Ajax a échoué : " + JSON.stringify(data)
				+ " (" + args.nbdone + " page" + pluriel + " renommée" + pluriel + ").";
			alert(errmsg);
		});
	}
	
	// Vérification des choix entrés par l'utilisateur et envoi
	function doit(form_dialog, document, from, to, nbdecal) {
		try {
			if(document.length == 0)
				throw "Vous n'avez pas entré le nom d'un document";
			document = document.trim();
			prefixe_livre = "Livre:";
			prefixe_user = "Utilisateur:";
			if(document.startsWith(prefixe_livre))
				page_base = "Page:" + document.substring(prefixe_livre.length);
			else if(document.startsWith(prefixe_user))
				page_base = document;
			else
				throw "Vous devez préciser un nom de livre (Livre:....djvu) ou une page de l'espace personnel (Utilisateur:...)";
			from = parseInt(from);
			to = parseInt(to);
			nbdecal = parseInt(nbdecal);
			if(from === NaN || to === NaN || nbdecal === NaN) 
				throw "Veuillez entrer des entiers dans tous les champs numériques";
			if(from <= 0 || to <= 0)
				throw "Veuillez entrer des entiers strictement positifs comme numéros de page";
			if(to < from)
				throw "La dernière page doit avoir un numéro supérieur ou égal à la première";
			pluriel = (nbdecal >= 2 ? "s" : "");
			question = "Êtes-vous sûr de vouloir décaler de " + nbdecal + " unité" + pluriel 
				+ " les pages " + from + " à " + to 
				+ " dans « " + document + " » ?";
			if(confirm(question)) {
				// Les données ont été validées, donc on peut fermer le formulaire
				form_dialog.close();

				// Le renommage va de la dernière à la première page si le décalage est positif,
				// et inversement
				premier = (nbdecal > 0 ? to : from);
				dernier = (nbdecal > 0 ? from : to);
				
				// Fonction asynchrone, rend la main tout de suite
				movePages({
					page_base: page_base,
					premier: premier,
					dernier: dernier,
					nbdecal: nbdecal,
					reason: 'Renommage semi-automatisé avec [[' + nom_script + ']]...',
					nbdone: 0
				});
			}
			else	
				alert("Ok, rien n'a été fait.");
		}
		catch(exc) {
			alert("Erreur : " + exc);
		}		
	}
	
	// Formulaire pour entrer les données
	function form() {
		function MyDialog( config ) {
			MyDialog.parent.call( this, config );
		}
		OO.inheritClass( MyDialog, OO.ui.Dialog );
		MyDialog.static.name = 'myDialog';
		MyDialog.prototype.initialize = function () {
			MyDialog.parent.prototype.initialize.call(this);
			this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );
			this.content.$element.append("<p>Cet outil permet de décaler d’un certain nombre d’unités "
				+ "un ensemble de pages d'un livre, afin d’associer la couche OCR "
				+ "ou le texte corrigé avec le fac similé.</p>");
			dialog = this;

			documentLabel = new OO.ui.LabelWidget({ label: 'Nom du document DjVu (ex. Livre:Mon livre.djvu)' });
			this.content.$element.append(documentLabel.$element);
			var livreInput = new OO.ui.TextInputWidget({ });
			this.content.$element.append(livreInput.$element);

			fromLabel = new OO.ui.LabelWidget({ label: 'Première page à décaler (entier > 0)' });
			this.content.$element.append(fromLabel.$element);
			var fromInput = new OO.ui.TextInputWidget({ validate:'integer' });
			this.content.$element.append(fromInput.$element);
			
			toLabel = new OO.ui.LabelWidget({ label: 'Dernière page à décaler (entier > 0)' });
			this.content.$element.append(toLabel.$element);
			var toInput = new OO.ui.TextInputWidget({ validate:'integer' });
			this.content.$element.append(toInput.$element);

			pasLabel = new OO.ui.LabelWidget({ label: 'Nombre d\'unités de décalage (entier positif ou négatif)' });
			this.content.$element.append(pasLabel.$element);
			var pasInput = new OO.ui.TextInputWidget({ });
			this.content.$element.append(pasInput.$element);

			var validerButton = new OO.ui.ButtonInputWidget({
				label: 'Valider',
				icon: 'check',
				value: 'check'
			});
			validerButton.on('click', function() {
				doit(dialog, livreInput.value.trim(), fromInput.value, toInput.value, pasInput.value);
			});
			this.content.$element.append(validerButton.$element);
			var cancelButton = new OO.ui.ButtonInputWidget({
				label: 'Annuler',
				icon: 'cancel',
				value: 'cancel'
			});
			cancelButton.on('click', function() {
				dialog.close();
			});
			this.content.$element.append(cancelButton.$element);
			this.$body.append(this.content.$element);
		};
		MyDialog.prototype.getBodyHeight = function () {
			return this.content.$element.outerHeight( true );
		};
		var myDialog = new MyDialog( {
			size: 'medium'
		} );
		var windowManager = new OO.ui.WindowManager();
		$( document.body ).append(windowManager.$element);
		windowManager.addWindows([myDialog]);
		windowManager.openWindow(myDialog);	
	}
	
	$('#sd-renommage').on('click', function(e) {
		// Code exécuté quand on clique sur la commande
		e.preventDefault();
		try {
			form();
		}
		catch(exc) {
			alert("Erreur : " + exc);
		}
	});
});