Utilisateur:Athozus/Gadgets/BandeauxEbauches-Fork.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) ;

Firefox (sur GNU/Linux) / Chrome / Internet Explorer / Opera : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl-F5.
//<noinclude>{{Catégorisation JS|BandeauxEbauches}}</noinclude>
//
// Documentation : [[Projet:JavaScript/Notices/BandeauxEbauches]]
//<source lang=javascript>
//<pre><nowiki>

/* jshint esversion: 6 */
/* globals mw, $ */

( function () {
'use strict';

/***
 * VARIABLES PERSONNALISABLES
 */

// Publication automatique
if ( window.BandeauxEbauches_AutoEdit === undefined ) {
	window.BandeauxEbauches_AutoEdit = true;
}
// Modification mineure
if ( window.BandeauxEbauches_MinorEdit === undefined ) {
	window.BandeauxEbauches_MinorEdit = true;
}
// Délai (en secondes ) lors de la sélection d'une suggestion au clavier
if ( window.BandeauxEbauches_KeyboardDelay === undefined ) {
	window.BandeauxEbauches_KeyboardDelay = 0.2;
}
// Balise à appliquer aux modifs
if ( window.BandeauxEbauches_Tag === undefined ) {
	window.BandeauxEbauches_Tag = '';
	if ( mw.config.get( 'wgWikiID' ) === 'frwiki' ) {
		window.BandeauxEbauches_Tag = 'BandeauxEbauches';
	}
}

/***
 * VARIABLES INTERNES
 */

var maxStubTypes = 6;  // Nombre maximum de paramètres pour le modèle {{Ébauche}}
var editSummary = 'Changement [[Modèle:Ébauche|{{Ébauche}}]]';
var editSummaryNoTag = '\xA0' + '; avec [[MediaWiki:Gadget-BandeauxEbauches.js|BandeauxEbauches]]';

var allStubTypes;
var parserCache = {};
var editRunning = false;
var textChangedTimeouts = [];

/***
 * RECHERCHE DES PARAMÈTRES DU BANDEAU ACTUEL
 */

function parseSection0( callback ) {
	var api = new mw.Api();
	api.get( {
		'action': 'query',
		'prop': 'revisions',
		'titles': mw.config.get( 'wgPageName' ),
		'rvprop': 'content|timestamp',
		rvsection: 0,
		formatversion: 2
	} ).done( function ( data ) {
		var page = data.query.pages[0];
		var revision = page.revisions ? page.revisions[0] : {};
		var content = revision.content || '';
		var match = /\{\{\s*[ÉéEe]bauche\s*(\|([^{}]*))?\}\} *\n?/m.exec( content );
		var parsedPage = { timestamp: revision.timestamp || '' };
		if ( match ) {
			// Un bandeau d'ébauche a été trouvé dans le wikicode.
			parsedPage.codeBeforeTemplate = content.substr( 0, match.index );
			parsedPage.codeAfterTemplate = content.substr( match.index + match[0].length );
			parsedPage.stubTemplateCode = match[0];
			var parameters = match[2] ? match[2] : '';
			parsedPage.stubTypes = parameters.split( '|' ).map( param => param.trim() );
		} else {
			// Pas encore de bandeau d'ébauche. Calcule la meilleure place pour un nouveau bandeau,
			// après les éventuels bandeaux de renvoi vers un autre article.
			var disambigMatch = /^(\{\{\s*([Aa]rticle|[0-9]?[Aa]utres?[0-9]?|[Cc]onfusion|[Hh]omonymie|[Rr]edirect|[Tt]itre|[Vv]oir)\b.*\}\}\s*\n)*/m.exec( content );
			parsedPage.codeBeforeTemplate = disambigMatch[0];
			parsedPage.codeAfterTemplate = content.substr( disambigMatch[0].length );
			parsedPage.stubTemplateCode = '';
			parsedPage.stubTypes = [];
		}
		callback( parsedPage );
	} );
}

/***
 * ÉDITION
 */

function notify( message, type ) {
	mw.notify( message, { type: type || 'info', tag: 'StubGadget' } );
}

function generateCode( allowStubWithoutType ) {
	var stubTypes = $.map( $( 'input.StubGadget-Input' ), function ( i ) {
		return i.value ? '|' + i.value : '';
	} ).join( '' );
	return stubTypes !== '' || allowStubWithoutType ? '{{Ébauche' + stubTypes + '}}\n' : '';
}

function setEditRunning( value ) {
	editRunning = value;
	$( '#StubGadget-Publish, #StubGadget-Cancel' ).prop( 'disabled', value );
}

function publish( parsedPage, oldStubTemplateCode, newStubTemplateCode ) {
	if ( parsedPage.stubTemplateCode === newStubTemplateCode ) {
		cancelEdit();
		notify( 'Modification non enregistrée : changements déjà effectués indépendamment.' );
		setEditRunning( false );
		return;
	} else if ( parsedPage.stubTemplateCode !== oldStubTemplateCode ) {
		var confirmMessage = 'Le bandeau d\'ébauche a été modifié depuis le chargement de la page.\n' +
			'Ancienne version : « ' + oldStubTemplateCode + ' »\n' +
			 'Version actuelle : « ' + parsedPage.stubTemplateCode + ' »\n' +
			 'Votre version : « ' + newStubTemplateCode + ' »\n' +
			 'Voulez-vous enregistrer votre version en ignorant les modifications faites indépendamment ?';
		if ( !window.confirm( confirmMessage ) ) {
			setEditRunning( false );
			return;
		}
	}
	var editRequest = {
		action       : 'edit',
		title        : mw.config.get( 'wgPageName' ),
		section      : 0,
		text         : parsedPage.codeBeforeTemplate + newStubTemplateCode + parsedPage.codeAfterTemplate,
		summary      : editSummary,
		watchlist    : 'nochange',
		basetimestamp: parsedPage.timestamp
	};
	if ( window.BandeauxEbauches_MinorEdit ) {
		editRequest.minor = 1;
	}
	if ( window.BandeauxEbauches_Tag ) {
		editRequest.tags = window.BandeauxEbauches_Tag;
	} else {
		editRequest.summary += editSummaryNoTag;
	}
	var api = new mw.Api();
	api.postWithEditToken( editRequest ).done( function () {
		window.location.reload();
	} ).fail( function ( e ) {
		notify( 'Erreur lors de l\'enregistrement (code : ' + e + ')', 'error' );
		setEditRunning( false );
	} );
}

function openEditWindow( parsedPage, newStubTemplateCode ) {
	$.get(
		mw.config.get( 'wgScript' ),
		{title: mw.config.get( 'wgPageName' ), action: 'edit', section: 0}
	).done( function ( data ) {
		document.body.innerHTML = data;
		$( '#wpTextbox1' ).val( parsedPage.codeBeforeTemplate + newStubTemplateCode + parsedPage.codeAfterTemplate );
		$( '#wpSummary' ).val( editSummary + editSummaryNoTag );
		$( '#wpMinoredit' ).prop( 'checked', window.BandeauxEbauches_MinorEdit );
	} );
}

function confirmAndPublish( oldStubTemplateCode ) {
	if ( editRunning ) {
		return;
	}
	var newStubTemplateCode = generateCode( false );
	if ( newStubTemplateCode === oldStubTemplateCode ) {
		cancelEdit();
		notify( 'Modification non enregistrée : aucun changement effectué.' );
		return;
	}
	var confirmMessage = (oldStubTemplateCode.trim() || '(pas de bandeau)') + ' → ' +
		(newStubTemplateCode.trim() || '(pas de bandeau)') + '\n\nOK ?';
	if ( window.BandeauxEbauches_AutoEdit && !window.confirm( confirmMessage ) ) {
		return;
	}
	setEditRunning( true );
	parseSection0( function( parsedPage ) {
		if ( window.BandeauxEbauches_AutoEdit ) {
			publish( parsedPage, oldStubTemplateCode, newStubTemplateCode );
		} else {
			openEditWindow( parsedPage, newStubTemplateCode );
		}
	} );
}

/***
 * SUGGESTIONS
 */

function getAllStubTypes() {
	function initDataList() {
		var docfrag = document.createDocumentFragment();
		for ( var i = 0; i < allStubTypes.length; i++ ) {
			var option = document.createElement( 'option' );
			option.value = allStubTypes[i];
			docfrag.appendChild( option );
		}
		var dataList = document.getElementById( 'OptionsBandeauEbauche' );
		dataList.appendChild( docfrag );
	}
	if ( allStubTypes ) {
		initDataList();
	} else {
		var api = new mw.Api();
		api.get( {
			format: 'json',
			action: 'expandtemplates',
			text: '{{#invoke:Bandeau|listeEbauches}}',
			prop: 'wikitext',
			utf8: true
		} ).done( function ( data ) {
			var rawList = data.expandtemplates.wikitext;
			if ( rawList ) {
				allStubTypes = rawList.split( '\n' );
				initDataList();
			}
		} );
	}
}

/***
 * PRÉVISUALISATION
 */

function preview( callback ) {
	function updatePreview( bannerHtml ) {
		$( '#StubGadget-Preview' ).html( bannerHtml );
		if ( callback ) {
			callback();
		}
	}
	var templateCode = generateCode( true );
	if ( parserCache[templateCode] ) {
		updatePreview( parserCache[templateCode] );
	} else {
		var api = new mw.Api();
		api.get( {
			format: 'json',
			action: 'parse',
			title: mw.config.get( 'wgPageName' ),
			text: templateCode,
			prop: 'text',
			disablelimitreport: true
		} ).done( function ( data ) {
			var tempDiv = $( '<div>' + data.parse.text['*'] + '</div>' );
			var bannerHtml = $( tempDiv ).find( '.bandeau-niveau-ebauche' ).html();
			parserCache[templateCode] = bannerHtml;
			updatePreview( bannerHtml );
		} );
	}
}

function inputTextChanged() {
	var id2 = parseInt( this.id.substr( 'StubGadget-Input-'.length ), 10 );
	clearTimeout( textChangedTimeouts[id2] );
	textChangedTimeouts[id2] = setTimeout(
		function () {
			var idInput, Input;
			if ( editRunning ) {
				return;
			}
			idInput = 'StubGadget-Input-' + id2;
			Input = document.getElementById( idInput );
			if ( !Input ) {
				return;
			}
			var stubType = Input.value;
			if ( stubType === '' || allStubTypes.includes( stubType ) ) {
				Input.style.color = '';
				preview();
			} else {
				Input.style.color = 'red';
			}
		},
		window.BandeauxEbauches_KeyboardDelay * 1000
	);
}

/***
 * FORMULAIRE
 */

function cancelEdit() {
	$( '#StubGadget-InitialTemplate' ).css( 'display', 'block' );
	$( '#StubGadget-TempTemplate' ).remove();
}

function startEdit( parsedPage ) {
	$( '#StubGadget-TempTemplate' ).remove();
	var initialStubTemplate = $( '#StubGadget-InitialTemplate' );
	var previewDiv;
	if ( initialStubTemplate.length === 0 ) {
		previewDiv = $( '<div></div>' );
	} else {
		previewDiv = initialStubTemplate.clone();
		previewDiv.find( 'button' ).remove();
		previewDiv.removeAttr( 'class' );
	}
	previewDiv.attr( 'id', 'StubGadget-Preview' );
	var inputLine = $( '<p><datalist id="OptionsBandeauEbauche"></datalist>' +
		'<input type="button" class="cdx-button cdx-button--action-progressive cdx-button--weight-primary" id="StubGadget-Publish" value="Valider" style="float:right;">' +
		'<input type="button" class="cdx-button cdx-button--action-destructive cdx-button--weight-quiet" id="StubGadget-Cancel" value="Annuler" style="float:right;">' +
		'<input type="button" class="cdx-button cdx-button--action-destructive cdx-button--weight-primary" id="StubGadget-Erase" value="Tout supprimer" style="float:right;">' +
		'</p>' );
	for ( var a = 0; a < maxStubTypes || a < parsedPage.stubTypes.length; a++ ) {
		var input = $( '<input id="StubGadget-Input-' + a + '" type="text" list="OptionsBandeauEbauche" class="StubGadget-Input">' );
		input.val( parsedPage.stubTypes[a] || '' );
		inputLine.append( input );
	}
	var form = $(
		'<form id="StubGadget-Form" style="margin-top:1em;border-top:1px solid #aaa;"><p>' +
		'<label for="StubGadget-Form" style="font-weight:bold;padding-right:1em;">' +
		'Sélectionner les bandeaux d\'ébauche à apposer.</label>' +
		'</p></form>'
	);
	form.append( inputLine );
	var stubTemplate = $( '<div id="StubGadget-TempTemplate" class="plainlinks bandeau-niveau-ebauche bandeau-article"></div>' );
	stubTemplate.append( previewDiv, form );
	if ( initialStubTemplate.length === 0 ) {
		// Garde le bandeau masqué jusqu'à ce qu'une prévisualisation soit disponible.
		stubTemplate.css( 'display', 'none' );
		$( '#mw-content-text' ).prepend( stubTemplate );
		preview( function() {
			$( '#StubGadget-TempTemplate' ).css( 'display', 'block' );
			$( '#StubGadget-Input-0' ).focus();
		} );
	} else {
		initialStubTemplate.css( 'display', 'none' );
		initialStubTemplate.after( stubTemplate );
		$( '#StubGadget-Input-0' ).focus();
	}
	$( '#StubGadget-Publish' ).click( function() {
		confirmAndPublish( parsedPage.stubTemplateCode );
	} );
	$( '#StubGadget-Cancel' ).click( cancelEdit );
	$( '#StubGadget-Erase' ).click( function() {
		eraseTypes( parsedPage );
	} );
	$( '.StubGadget-Input' ).on( 'input', inputTextChanged );
	getAllStubTypes();
}

function eraseTypes( parsedPage ) {
	for ( var a = 0; a < maxStubTypes || a < parsedPage.stubTypes.length; a++ ) {
		$( '#StubGadget-Input-' + a ).val( '' );
	}
}

/***
 * LANCEMENT
 */

function initEditLink( $ ) {
	var stubTemplates = $( 'div.bandeau-niveau-ebauche.bandeau-article' ).first();
	if ( stubTemplates.length > 0 ) {
		// Il y a au moins un bandeau d'ébauche.
		// L'édition des thèmes d'ébauche se fait à partir d'un bouton "Modifier" ajouté dans le bandeau.
		stubTemplates.attr( 'id', 'StubGadget-InitialTemplate' );
		var editButton = $( '<button class="cdx-button" title="Modifier le bandeau d\'ébauche" style="float:right;">Modifier</button>' );
		editButton.click( function() {
			mw.loader.using( 'mediawiki.api', function () {
				parseSection0( startEdit );
			} );
		} );
		$( '#StubGadget-InitialTemplate' ).prepend( editButton );
	} else {
		// Il n'y a pas encore de bandeau d'ébauche.
		// Un bandeau d'ébauche peut être ajouté via un lien dans p-cactions (menu "Plus" sous Vector).
		var editStubLink = mw.util.addPortletLink( 'p-cactions', '#', 'Ébauche', 'ca-edit-stub', 'Ajouter un bandeau d\'ébauche' );
		$( editStubLink ).click( function ( e ) {
			e.preventDefault();
			mw.loader.using( 'mediawiki.api', function () {
				startEdit( {stubTemplateCode: '', stubTypes: []} );
			} );
		} );
	}
}

if ( mw.config.get( 'wgAction' ) === 'view' && mw.config.get( 'wgNamespaceNumber' ) > -1 ) {
	mw.loader.using( 'mediawiki.util', function () {
		$( initEditLink );
	} );
}

}() );

//</nowiki></pre></source>