Aller au contenu

MediaWiki:Minerva.js

De Wikidébats, l'encyclopédie des débats et des arguments « pour » et « contre »

Note : après avoir publié 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 appuyez sur Ctrl + F5 ou Ctrl + R (⌘ + R sur un Mac).
  • Google Chrome : appuyez sur Ctrl + Maj + R (⌘ + Shift + R sur un Mac).
  •  Edge : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl + F5.
$(function() {
	argumentMapContentCall();
	argumentMapColor();
	argumentContentCall();
	argumentContentDrop();
	closeArgument();
	moreContentCall();
	latestChangesCall();
	breadcrumbButton();
	breadcrumbContentCall();
	insertScrollToRootButton();
	fillEditSummary();
	fillEditSummaryForCheckbox();
});

/* <Dynamic API call> */

/* Pour afficher le contenu d'un argument ouvert */
function argumentContentCall() {
  $(document).on('click', '.argument-expandable-title:not(.expanded)', function() {
	var level = $(this).data('level');
	var clickedElement= true;
	closeArgument(level, clickedElement);

	// Appeler les fonctions supplémentaires
	var scrollTop = $(this).offset().top - 5;
	$('html, body').animate({ scrollTop: scrollTop }, 'slow');
	loadContentFromTitle($(this));
  });
}

// Annule le script si clic sur le bouton modifier-argument
$(document).on('click', '.ns-0 .modifier-argument a', function(event) {
	event.stopPropagation();
});

/* Pour charger le contenu d'un argument */
function loadContentFromTitle(titleElement){
	titleElement.addClass('expanded').removeClass('open');
	var template = titleElement.data('template');
	var argument = titleElement.data('argument');
	var type = titleElement.data('type');
	var level = titleElement.data('level');
	var root = titleElement.data('root');
	var path = titleElement.data('path');
	var warnings = titleElement.data('warnings');
	var page = titleElement.data('page');
	var wrapper = titleElement.parent().find('.argument-content-wrapper');
	var query = '{{' + template + '|argument=' + argument + '|type=' + type + '|niveau=' + level + '|racine=' + root + '|chemin=' + path + '|avertissements=' + warnings + '|page=' + page + '}}';
	new mw.Api().post({
			action: "parse",
				contentmodel: "wikitext",
				text: query
			}).done( function( data ) {
		var text = data.parse.text['*'].replace(/<!--[\S\s]*?-->/gm, '' );
		wrapper.append(text);
	});
	
	breadcrumbButton(titleElement);
	insertScrollToRootButton($(titleElement));
}

/* Pour supprimer le contenu d'un argument fermé manuellement */
function argumentContentDrop(){
	$(document).on('click', '.argument-expandable-title.expanded', function(){
		// Vérifiez si #bouton-fil existe et supprimez-le s'il existe
		if ($('#bouton-fil').length) {
			$('#bouton-fil').remove();
		}
		
		$(this).removeClass('expanded').addClass('open');
		var wrapper = $(this).parent().find('.argument-content-wrapper');
		wrapper.empty();
	});
}

/* Pour afficher un argument de la carte des arguments sur lequel on clique */
function argumentMapContentCall(){
	$('.ns-0').on('click', '#Argument_map .titre-argument-carte', function(){
		$('.argument-expandable-title.expanded').each(function() {
			if ($(this).data('level') === 1) {
				// Supprimer la classe "expanded" et ajouter la classe "open"
				$(this).removeClass('expanded').addClass('open');
				// Supprimer le contenu de l'élément suivant avec la classe "argument-content-wrapper"
				$(this).next('.argument-content-wrapper').empty();
			}
		});
		$(this).addClass('visited');
		var title = $(this).text().replace(/\./g,'\\.').replace(/ /g,"_").replace(/'/g,"\\'").replace(/"/g,'\\"').replace(/,/g,'\\,').replace(/\(/g,'\\(').replace(/\)/g,'\\)');
		var sectionContent = $('#' + title).closest('.collapsible-block');
		if (!sectionContent.attr('class').split(/\s+/).includes('open-block')) {
			$(sectionContent).addClass('open-block').removeAttr('hidden');
		}
		var sectionTitle = $(sectionContent).prev();
		if (!sectionTitle.attr('class').split(/\s+/).includes('open-block')) {
			$(sectionTitle).addClass('open-block');
		}
		var sectionArrow = $(sectionTitle).children(":first");
		if (!sectionArrow.attr('class').split(/\s+/).includes('mf-icon-rotate-flip')) {
			$(sectionArrow).addClass('mf-icon-rotate-flip');
		}
		var scrollTop = $('#' + title).offset().top - 5;
		$('html, body').animate({ scrollTop: scrollTop }, 'slow');
		var argumentTitle = $('#' + title);
		// Ajoute le lien "modifier" s'il n'existe pas déjà
		if (argumentTitle.find('.modifier-argument').length === 0) {
			argumentTitle.append('<span class="modifier-argument"><a href="#" title="Modifier cet argument">modifier</a></span>');
		}
		if (!argumentTitle.attr('class').split(/\s+/).includes('expanded')) {
			argumentTitle.addClass('expanded open-block');
			loadContentFromTitle(argumentTitle);
		}
	});
}

/* Pour colorer dans la carte des arguments les arguments ouverts */
function argumentMapColor(){
	$('.ns-0').on('click', '.root-argument:not(.expanded)', function(){
		var id = $(this).attr('id');
		var element = $('#' + id + '_map');
		element.addClass('visited');
	});
}

/* Pour fermer automatiquement un argument et retirer le gras pour indiquer qu'il a été ouvert */
function closeArgument(level, clickedElement) {
	// Si clickedElement n'est pas défini, on l'assigne à null
	clickedElement = clickedElement || null;

	// Sélectionner tous les éléments qui ont la classe "argument-expandable-title" et la classe "expanded"
	$('.argument-expandable-title.expanded').each(function() {
		// Vérifier si l'élément a le même niveau (data-level égal) et que ce n'est pas l'élément cliqué (si fourni)
		if ($(this).data('level') === level && (!clickedElement || !$(this).is(clickedElement))) {
			// Supprimer la classe "expanded" et ajouter la classe "open"
			$(this).removeClass('expanded').addClass('open');
			
			// Supprimer le contenu de l'élément suivant avec la classe "argument-content-wrapper"
			$(this).next('.argument-content-wrapper').empty();
		}
	});
}

/*	Cache en mémoire pour les fils d'Ariane déjà générés	*/
var breadcrumbCache = new Map();			// key => html
var breadcrumbRequests = new Map();		// key => jqXHR (promesse en cours)

/*	Rendu de la modale à partir d'un HTML déjà prêt	*/
function renderBreadcrumbModal(html) {
	// Si une modale existe déjà (mais masquée), on la supprime pour repartir propre
	if ($('#modal').length) {
		$('#modal').remove();
	}
	var modal = $('<div>', { id: 'modal' });
	var modalContent = $('<div>', { id: 'fil-ariane' });
	modalContent.html(html);
	modal.append(modalContent);
	$('body').append(modal);

	// Fermer la modale au clic n'importe où dans la modale en la masquant
	modal.on('click', function() {
		modal.hide();
	});
}

/*	Pour générer le bouton du fil d'Ariane	*/
function breadcrumbButton(titleElement) {
	if ($('#bouton-fil').length) {
		$('#bouton-fil').remove();
	}
	if ($('#modal').length) {
		$('#modal').remove();
	}

	var image = $('<img>', {
		src: '/w/images/fr/4/4d/Bouton-fil-Ariane.svg',
		alt: 'Fil d\'Ariane',
		id: 'bouton-fil',
		style: 'position: fixed; bottom: 1em; right: 2em; width: 50px; height: 50px; cursor: pointer; z-index: 9999;'
	});

	image.insertBefore($(titleElement));
}

/*	Pour afficher le fil d'Ariane d'un argument (avec cache)	*/
function breadcrumbContentCall() {
	$(document).on('click', '#bouton-fil', function(event) {
		event.stopPropagation();

		// Si la modale existe déjà, on la réaffiche simplement
		if ($('#modal').length) {
			$('#modal').show();
			return;
		}

		// Récupérer path/page depuis l'argument courant
		var argument = this.closest('.argument-expandable');
		if (!argument) {
			return;
		}
		var argumentTitle = argument.querySelector('.argument-expandable-title');
		if (!argumentTitle) {
			return;
		}
		var path = argumentTitle.dataset.path || '';
		var page = argumentTitle.dataset.page || '';
		var key = path + '|' + page;

		// Si on a déjà le HTML en cache, on réutilise sans régénérer
		if (breadcrumbCache.has(key)) {
			renderBreadcrumbModal(breadcrumbCache.get(key));
			return;
		}

		// Si une requête est déjà en cours pour cette clé, on s'y abonne
		if (breadcrumbRequests.has(key)) {
			breadcrumbRequests.get(key).done(function(data) {
				var text = (data && data.parse && data.parse.text && data.parse.text['*']) ? data.parse.text['*'] : '';
				text = text.replace(/<!--[\S\s]*?-->/gm, '');
				// S'assurer que le cache est rempli (au cas où)
				if (!breadcrumbCache.has(key)) {
					breadcrumbCache.set(key, text);
				}
				renderBreadcrumbModal(text);
			});
			return;
		}

		// Sinon, on crée la requête, on la mémorise, puis on remplit le cache
		var query = '{{Fil d\'Ariane | chemin = ' + path + ' | page = ' + page + ' }}';

		var req = new mw.Api().post({
			action: 'parse',
			contentmodel: 'wikitext',
			text: query
		});

		breadcrumbRequests.set(key, req);

		req.done(function(data) {
			var text = (data && data.parse && data.parse.text && data.parse.text['*']) ? data.parse.text['*'] : '';
			text = text.replace(/<!--[\S\s]*?-->/gm, '');
			breadcrumbCache.set(key, text);
			renderBreadcrumbModal(text);
		}).always(function() {
			// Quelle que soit l'issue, on nettoie le registre des requêtes en cours
			breadcrumbRequests.delete(key);
		});
	});
}

/* Pour remonter à l'argument parent */
function insertScrollToRootButton($title) {
	if ($('#bouton-remonter').length) {
		$('#bouton-remonter').remove();
	}

	var image = $('<img>', {
		src: '/w/images/fr/1/16/Remonter-page.svg',
		alt: 'Remonter à l\'argument parent',
		id: 'bouton-remonter',
		style: 'position: fixed; bottom: 5em; right: 2em; width: 50px; height: 25px; cursor: pointer; z-index: 9999;'
	});

	image.insertBefore($title);
}

$(document).on('click', '#bouton-remonter', function(event) {
	event.stopPropagation();
	var level = $(this).next('.argument-expandable-title').data('level');
	var rootEnc = $(this).next('.argument-expandable-title').data('root');
	rootEnc = rootEnc.replace(/\+/g, '_');
	var txt = document.createElement("textarea");
	txt.innerHTML = decodeURIComponent(rootEnc);
	var root = txt.value;
	var cible = document.getElementById(root);
	if(level === 1) {
		$('#bouton-remonter').remove();
		$('#bouton-fil').remove();
	} else {
		breadcrumbButton($(cible));
		insertScrollToRootButton($(cible));
	}
	var scrollTop = cible ? $(cible).offset().top - 5 : 0;
	$('html, body').animate({ scrollTop: scrollTop }, 'slow');

	closeArgument(level);
});

/* Pour remonter à l'argument parent au clic sur la flèche */
$(document).on('click', '.remonter-argument, .remonter-fil', function(event) {
	event.preventDefault();
	var level = $(this).data('level');
	closeArgument(level);
	var titleElement = $(this).find('a');
	var href = titleElement.attr('href');
	var anchorName = href.split('#')[1]; // On extrait le nom de l'ancre de l'attribut href
	var escapedTitleElement = document.getElementById(anchorName);
	var scrollTop = $(escapedTitleElement).offset().top - 5;
	$('html, body').animate({ scrollTop: scrollTop }, 'slow');
	breadcrumbButton(escapedTitleElement);
	insertScrollToRootButton(escapedTitleElement);
});

/* Pour remonter à la carte des arguments au clic sur le titre du débat dans le fil d'Ariane */
$(document).on('click', '.remonter-carte, .remonter-haut', function(event) {
	closeArgument(1);
	var target = $('#Argument_map');
	if (!target.length) {
		target = $('#mw-mf-viewport'); // Cas d'une page d'argument
	}
	if (target.length) {
		$('html, body').animate({ scrollTop: target.offset().top }, 'slow');
	}
	if ($('#bouton-fil').length) {
		$('#bouton-fil').remove(); // Supprimez-le s'il existe déjà
	}
	if ($('#bouton-remonter').length) {
		$('#bouton-remonter').remove(); // Supprimez-le s'il existe déjà
	}
});

/* Code spécifique aux autoévaluations */
$(document).ready(function() {
	if ($('.ns-3100').length > 0) {
		/* Pour remonter en tête de page dans les autoévaluations */
		$(document).on('click', '.remonter-autoevaluation, .remonter-haut, .titre-ariane', function(event) {
			event.preventDefault();
			$('html, body').animate({ scrollTop: 0 }, 'slow');
			$('#bouton-fil').remove();
			closeArgument(2);
		});
		$(document).on('click', '.remonter-fil.level-2', function(event) {
			$('#bouton-fil').remove();
		});
		/* Pour remonter en début de page après chaque évaluation d'un argument */
		$(document).on('click', '.bouton-argument-suivant', function() {
			$('html, body').animate({ scrollTop: 0 }, 'slow'); // Fait défiler en douceur
		});
	}
});

/* Pour afficher un contenu supplémentaire */
function moreContentCall(){
$(document).on('click', '.more-content-button', function(){
	$(this).hide();
	var page = $(this).data('page');
	var wrapper = $(this).parent().find('.more-content-wrapper');
	var query = '{{Contenu supplémentaire | page = ' + page + '}}';
	new mw.Api().post({
			action: "parse",
				contentmodel: "wikitext",
				text: query
			}).done( function( data ) {
		var text = data.parse.text['*'].replace(/<!--[\S\s]*?-->/gm, '' );
		wrapper.replaceWith('<div class="more-content-wrapper"><div class="more-content-drop show"></div>' + text + '</div>');
	});
});
}

/* Pour afficher les dernières modifications d'un débat */
function latestChangesCall(){
$('.ns-0').on('click', '.latest-changes-button', function(){
	var button = $(this).parent().find('.latest-changes-button.mw-ui-button');
	var page = button.data('page');
	button.hide();
	var wrapper = $(this).parent().find('.latest-changes-wrapper');
	var query = '{{Dernières modifications | page = ' + page + '}}';
	new mw.Api().post({
			action: "parse",
				contentmodel: "wikitext",
				text: query
			}).done( function( data ) {
		var text = data.parse.text['*'].replace(/<!--[\S\s]*?-->/gm, '' );
		wrapper.replaceWith('<div class="latest-changes-wrapper"><div class="latest-changes-drop show"></div>' + text + '</div>');
	});
});
}

/* Pour ouvrir certains liens dans un nouvel onglet */
$(document).on('click', '.onglet-externe a', function(event) {
	event.preventDefault();
	var url = $(this).attr('href');
	window.open(url, '_blank');
});


/* Pour compléter le résumé des modifications apportées selon la partie de la page modifiée */

function fillEditSummary(message) {
	if (typeof message === "undefined") {
		return;
	}
	var input = $('input[name=wpSummary], textarea[name=wpSummary]');
	var summary = input.val();

	if (summary) {
		var condition = summary.substr(-3);
		if (condition === '*/ ') {
			summary += message;
		} else {
			summary += ' + ' + message;
		}
	} else {
		summary = message;
	}

	input.val(summary);

	// Ajuster la hauteur si c’est un textarea avec auto-resize
	var textarea = input.get(0);
	if (textarea && textarea.tagName.toLowerCase() === 'textarea' && textarea.classList.contains('auto-resize-textarea')) {
		autoResize(textarea);
	}
}
function autoResize(el) {
	el.style.height = 'auto'; // Réinitialise d'abord
	el.style.height = el.scrollHeight + 'px'; // Ajuste à la hauteur du contenu
}

function fillEditSummaryForCheckbox(object, addingMessage, removingMessage){
	if (typeof object === "undefined") {
		return;
	}
	var input = $('input[name=wpSummary], textarea[name=wpSummary]');
	var summary = input.val();
	var checked = object.prop('checked');
	var bannerName = object.parent();
	var bannerName = $(bannerName).next();
	var bannerName = $(bannerName).text() + ' »';
	if (checked) {
		var actionDone = addingMessage + ' «';
	} else {
		var actionDone = removingMessage + ' «';
	}
	var message = actionDone + bannerName;
	fillEditSummary(message);
}

/* Pour compléter automatiquement les résumés de modification */
$(document).ready(function() {
	if ($('.mw-special-FormEdit').length > 0) {

		// Pour remplir automatiquement le résumé des modifications avec la section correspondante
		$(document).ready(function () {
			// Récupère la valeur de l'attribut data-section
			var sectionValue = $('#formName').data('section');
			// Cible maintenant le <textarea> au lieu de l'input
			var summaryField = $('input[name=wpSummary], textarea[name=wpSummary]');
			// Vérifie que le champ est vide et que sectionValue existe
			if (summaryField.val().trim() === '' && sectionValue) {
				var section = '/* ' + sectionValue + ' */ ';
				summaryField.val(section);
				// Ajuste aussi la hauteur si nécessaire
				if (typeof autoResize === 'function') {
					autoResize(summaryField[0]);
				}
			}
		});
		
		// Pour ajuster automatiquement la hauteur du résumé des modifications
		setTimeout(function () {
			var input = document.querySelector('#wpSummary input.oo-ui-inputWidget-input');
			if (input) {
				var textarea = document.createElement('textarea');
				// Copier les attributs
				textarea.name = input.name;
				textarea.id = input.id;
				textarea.title = input.title;
				textarea.accessKey = input.accessKey;
				textarea.className = input.className + ' auto-resize-textarea';
				textarea.tabIndex = input.tabIndex;
				textarea.placeholder = input.placeholder || '';
				textarea.value = input.value;
				// Remplacement
				input.parentNode.replaceChild(textarea, input);
				// Ajustement initial
				autoResize(textarea);
				// Réajustement dynamique
				textarea.addEventListener('input', function () {
					autoResize(this);
				});
			}
		}, 500);
		
		// Pour les instances multiples
		$(document).ready(function() {
			var zones = [
				{
					selector: '.zone-arguments-pour',
					labelReorg: 'Réorganisation des arguments',
					labelRenom: 'Renommage de l’argument : « ',
					labelSupp: 'Suppression de l’argument : « ',
					labelAjout: 'Ajout de l’argument existant : « '
				},
				{
					selector: '.zone-arguments-contre',
					labelReorg: 'Réorganisation des arguments',
					labelRenom: 'Renommage de l’argument : « ',
					labelSupp: 'Suppression de l’argument : « ',
					labelAjout: 'Ajout de l’argument existant : « '
				},
				{
					selector: '.zone-justifications',
					labelReorg: 'Réorganisation des arguments',
					labelRenom: 'Renommage de l’argument : « ',
					labelSupp: 'Suppression de l’argument : « ',
					labelAjout: 'Ajout de l’argument existant : « '
				},
				{
					selector: '.zone-objections',
					labelReorg: 'Réorganisation des arguments',
					labelRenom: 'Renommage de l’objection : « ',
					labelSupp: 'Suppression de l’objection : « ',
					labelAjout: 'Ajout de l’argument existant : « '
				},
				{
					selector: '.zone-introduction',
					labelReorg: 'Réorganisation des rubriques',
					labelRenom: 'Renommage de la rubrique : « ',
					labelSupp: 'Suppression de la rubrique : « ',
					labelSuppBis: 'Suppression d’une rubrique sans titre',
					labelAjout: 'Ajout d’une rubrique'
				},
				{
					selector: '.zone-voir-Wikipedia',
					labelReorg: 'Réorganisation des articles',
					labelRenom: 'Renommage de l’article « ',
					labelSupp: 'Suppression de l’article « ',
					labelAjout: 'Ajout de l’article Wikipédia « '
				},
				{
					selector: '.zone-debats-connexes',
					labelReorg: 'Réorganisation des débats',
					labelRenom: 'Renommage du débat : « ',
					labelSupp: 'Suppression du débat : « ',
					labelAjout: 'Ajout du débat : « '
				},
				{
					selector: '.zone-interlangue',
					labelReorg: 'Réorganisation des liens interlangues',
					labelSupp: 'Suppression du lien vers « ',
					labelAjout: 'Ajout du lien interlangue vers : « '
				},
				{
					selector: '.zone-citations',
					labelReorg: 'Réorganisation des citations',
					labelSupp: 'Suppression de la citation de ',
					labelSuppBis: 'Suppression d’une citation',
					labelAjout: 'Ajout d’une citation'
				},
				{
					selector: '.zone-references',
					labelReorg: 'Réorganisation des références',
					labelSupp: 'Suppression de la référence : « ',
					labelSuppBis: 'Suppression d’une référence',
					labelAjout: 'Ajout d’une référence'
				}
			];

			// Parcours des zones
			zones.forEach(function(zone) {
				// Suppression
				document.querySelectorAll(zone.selector + ' .instanceRemove a').forEach(function(element) {
					element.addEventListener('click', function(e) {
						e.preventDefault();

						var row = element.closest('tr');
						var titreInput = row ? row.querySelector('.parametre-important') : null;
						if (!titreInput) {
							titreInput = row ? row.querySelector('.parametre-important-bis') : null;
						}

						var titre = titreInput && titreInput.value ? titreInput.value : null;
						var message;

						if (titre) {
							if (zone.selector === '.zone-citations') {
								message = (titreInput ? zone.labelSupp : zone.labelSuppBis || zone.labelSupp) + titre;
							} else {
								message = (titreInput ? zone.labelSupp : zone.labelSuppBis || zone.labelSupp) + titre + ' »';
							}
						} else {
							message = zone.labelSuppBis || zone.labelSupp;
						}

						fillEditSummary(message);
					});
				});

				// Ajout
				window.ajoutInstance = false;
				document.querySelectorAll(zone.selector + ' .instanceAddAbove a' + ', ' + zone.selector + ' .multipleTemplateAdder').forEach(function(element) {
					element.addEventListener('click', function(e) {
						e.preventDefault();
						if (
							zone.selector === '.zone-introduction' ||
							zone.selector === '.zone-citations' ||
							zone.selector === '.zone-references'
						) {
							fillEditSummary(zone.labelAjout);
						} else {
							window.ajoutInstance = true;
							window.ajoutInstanceZone = zone.selector;
						}
					});
				});
				
				// Renommage
				var inputs = document.querySelectorAll(zone.selector + ' .parametre-important');
				for (var i = 0; i < inputs.length; i++) {
					inputs[i].addEventListener('blur', function(e) {
						var value = e.target.value;
						if (value && value.trim() !== '') {
							if (typeof fillEditSummary === 'function') {
								// On remplace totalement le résumé pour éviter les répétitions
								fillEditSummary(zone.labelRenom + value + ' »');
							}
						}
					});
				}

				// Réorganisation
				var ordreInitial = [];
				var reorganisationDejaFaite = false;
				var clicEnCours = false;

				function getOrdre() {
					return Array.from(document.querySelectorAll(zone.selector + ' .multipleTemplateInstance'))
						.map(function(el) {
							var input = el.querySelector('select, input');
							return input && input.value ? input.value : el.innerText.trim();
						});
				}

				function startInteraction() {
					ordreInitial = getOrdre();
					clicEnCours = true;
				}

				function endInteraction() {
					if (!clicEnCours || reorganisationDejaFaite) return;

					var ordreFinal = getOrdre();
					if (JSON.stringify(ordreInitial) !== JSON.stringify(ordreFinal)) {
						fillEditSummary(zone.labelReorg);
						reorganisationDejaFaite = true;
					}
					clicEnCours = false;
				}

				// Étape 1 : début interaction (clic ou toucher)
				document.querySelectorAll(zone.selector + ' .instanceRearranger').forEach(function(el) {
					el.addEventListener('mousedown', startInteraction);
					el.addEventListener('touchstart', startInteraction);
				});

				// Étape 2 : fin interaction (clic ou toucher)
				var zoneElement = document.querySelector(zone.selector);
				if (zoneElement) {
					zoneElement.addEventListener('mouseup', endInteraction);
					zoneElement.addEventListener('touchend', endInteraction);
				}
				
				// Ajout d'une instance de type token
				function attachHandler() {
					$('select').off('select2:select.fullListener').on('select2:select.fullListener', function (e) {
						var selectedId = e.params.data && e.params.data._resultId;
						var $option = selectedId ? $(document.getElementById(selectedId)) : null;

						// Texte de base depuis l'événement
						var match = e.params.data.text.trim();

						// Si possible, extraire la version enrichie du DOM
						if ($option && $option.find('.select2-match-entire').length) {
							match = $option.find('.select2-match-entire').text().trim();
						}

						var message;
						if (window.ajoutInstance && window.ajoutInstanceZone) {
							var matchedZone = zones.find(function(z) {
								return z.selector === window.ajoutInstanceZone;
							});
							if (matchedZone) {
								message = matchedZone.labelAjout + match + ' »';
							} else {
								message = 'Ajout de « ' + match + ' »';
							}
							window.ajoutInstance = false;
							window.ajoutInstanceZone = null;
						} else {
							message = 'Ajout de « ' + match + ' »';
						}

						fillEditSummary(message);
					});
				}

				// MutationObserver pour chaque zone
				zones.forEach(function(zone) {
					var observer = new MutationObserver(attachHandler);
					observer.observe(document.body, {
						childList: true,
						subtree: true
					});
				});
			});
		});

		// Pour les cases à cocher d'avertissements
		$(document).on('click', '.checkboxesSpan .oo-ui-inputWidget-input', function() {
			if ($(this).closest('.zone-rubriques').length === 0) {
				fillEditSummaryForCheckbox($(this), 'Ajout du bandeau d’avertissement', 'Retrait du bandeau d’avertissement');
			}
		});
	
		// Pour les cases à cocher de rubriques
		$(document).ready(function() {
			$(document).on('click', '.zone-rubriques' + ' .oo-ui-inputWidget-input', function() {
				fillEditSummaryForCheckbox($(this), 'Ajout de la rubrique', 'Retrait de la rubrique');
			});
		});
		
		// Pour le changement de l'état d'avancement du débat
		$(document).on('change', '.mw-special-FormEdit .zone-bandeaux .mandatoryField', function() {
			var input = $('input[name=wpSummary], textarea[name=wpSummary]');
			var summary = input.val();
			var bannerName = $('.zone-bandeaux select.mandatoryField option:selected').val() + ' »'; // Sélectionne le select dans la zone-bandeaux
			var actionDone = 'Niveau d’avancement du débat changé à « ';
			var message = actionDone + bannerName;
			fillEditSummary(message);
		});
		
		function ajusterLargeurChamp($champ) {
		var $select2 = $champ.next('.select2');
		if ($select2.length) {
			$champ.attr('style', 'width: 100% !important');
			$select2.attr('style', 'width: 100% !important');
			$select2.find('.select2-selection').attr('style', 'width: 100% !important');
		}
	}

		// Pour ajuster le champ input des tokens
		function corrigerChampsPfTokens() {
			$('.pfTokens').each(function () {
				var $champ = $(this);
				if ($champ.next('.select2').length) {
					ajusterLargeurChamp($champ);
				} else {
					var tentatives = 0;
					var interval = setInterval(function () {
						if ($champ.next('.select2').length || tentatives > 50) {
							clearInterval(interval);
							ajusterLargeurChamp($champ);
						}
						tentatives++;
					}, 200);
				}
			});
		}
		corrigerChampsPfTokens();
		
		// Pour ajuster le champ input des titres affichés
		mw.loader.using( [] ).then( function () {
			'use strict';

			function autoResize( el ) {
						// Reset puis ajuste sur le scrollHeight réel
						el.style.height = 'auto';
						el.style.height = el.scrollHeight + 'px';
			}

			function scheduleInitialResize( el ) {
						// Cache overflow et tente plusieurs fois (layout, polices, etc.)
						el.style.overflowY = 'hidden';
						autoResize( el );

						if ( window.requestAnimationFrame ) {
									requestAnimationFrame( function () { autoResize( el ); } );
									requestAnimationFrame( function () { autoResize( el ); } );
						}

						setTimeout( function () { autoResize( el ); }, 0 );
						setTimeout( function () { autoResize( el ); }, 50 );

						if ( document.fonts && document.fonts.ready && document.fonts.ready.then ) {
									document.fonts.ready.then( function () { autoResize( el ); } );
						}
			}

			// Observateurs partagés (visible + resize de fenêtre)
			var tracked = new Set();
			var io = null;

			if ( 'IntersectionObserver' in window ) {
						io = new IntersectionObserver( function ( entries ) {
									entries.forEach( function ( e ) {
												if ( e.isIntersecting ) { autoResize( e.target ); }
									} );
						}, { threshold: 0.01 } );
			}

			var pendingWinResize = false;
			window.addEventListener( 'resize', function () {
						if ( pendingWinResize ) return;
						pendingWinResize = true;
						setTimeout( function () {
									pendingWinResize = false;
									tracked.forEach( function ( el ) { autoResize( el ); } );
						}, 100 );
			} );

			function wireTextarea( $textarea ) {
						var el = $textarea.get( 0 );

						// 1 ligne par défaut
						$textarea.attr( 'rows', '1' );

						// Ajustements initiaux
						scheduleInitialResize( el );

						// Événements usuels
						el.addEventListener( 'input', function () { autoResize( el ); } );
						el.addEventListener( 'change', function () { autoResize( el ); } );
						el.addEventListener( 'transitionend', function () { autoResize( el ); } );

						// Suivi global (resize fenêtre) + visibilité
						tracked.add( el );
						if ( io ) { io.observe( el ); }
			}

			function transformInputs( $root ) {
						$root.find( 'input.parametre-important' ).each( function () {
									var $input = $( this );

									// Évite double-transformation
									if ( $input.attr( 'data-mw-textareaized' ) === '1' ) return;
									$input.attr( 'data-mw-textareaized', '1' );

									// Crée le textarea
									var $textarea = $( '<textarea>' );

									// Copie les attributs utiles
									$.each( this.attributes, function () {
												if ( !this || !this.specified ) return;
												var name = this.name.toLowerCase();
												if ( name === 'type' || name === 'size' ) return;
												$textarea.attr( this.name, this.value );
									} );

									// Valeur courante
									$textarea.val( $input.val() );

									// Remplacement
									$input.replaceWith( $textarea );

									// Brancher l'autosize (incl. initial)
									wireTextarea( $textarea );
						} );
			}

			// Exécution à chaque insertion de contenu de page (incl. rechargements AJAX)
			mw.hook( 'wikipage.content' ).add( function ( $content ) {
						transformInputs( $content );
			} );
		} );


	
		// Pour la suppression de mots-clés
		$(document).on('click', '.select2-selection__choice__remove', function() {
			var $li = $(this).closest('.select2-selection__choice');
			var keyword = $li.find('.select2-match-entire').text();
			var message = 'Suppression de « ' + keyword + ' »';
			fillEditSummary(message);
		});
		
		// Pour le sujet du débat
		var sujetCompletInitial = $('.zone-sujet-complet').val(); // Sauvegarder la valeur initiale au chargement

		$(document).on('change', '.zone-sujet-complet', function() {
			var sujetCompletActuel = $(this).val();
			var $summary = $('textarea[name=wpSummary], input[name=wpSummary]'); // Sélection dynamique ici
			var summary = $summary.val();
			var ajoutOuModification = '';

			if (sujetCompletInitial === '' && sujetCompletActuel !== '') {
				ajoutOuModification = 'Ajout du sujet : « ' + sujetCompletActuel + ' »';
			} else if (
				sujetCompletInitial !== '' &&
				sujetCompletActuel !== '' &&
				sujetCompletInitial !== sujetCompletActuel
			) {
				ajoutOuModification = 'Sujet modifié : « ' + sujetCompletActuel + ' »';
			}

			if (ajoutOuModification) {
				summary = '/* Sujet du débat */ ' + ajoutOuModification;
				$summary.val(summary);
			}
		});
		
		// Pour ajouter au résumé de modifications les opérations proposées
		$(document).on('click', '.resume-modifications', function() {
			var input = $('input[name=wpSummary], textarea[name=wpSummary]');
			var summary = input.val();
			var newSummary = $(this).text();
			if (summary) {
				var condition = summary.substr(-3);
				if (condition == '*/ ') {
					summary = summary + newSummary;
					input.val(summary);
				} else {
					summary = summary + ' + ' + newSummary;
					input.val(summary);
				}
			} else {
				$('input[name=wpSummary]').val(newSummary);
			}
		});
		
		// Pour copier automatiquement le titre de la page de l'argument dans le champ "Titre affiché"
		$(document).on('select2:select', '.zone-arguments .pfTokens', function (e) {
			// Récupérer le texte de l'option sélectionnée
			var selectedText = e.params.data.text;

			// Trouver l'élément d'entrée juste après le select2
			var inputField = $(this).closest('tr').next('tr').find('.createboxInput');
		
			// Copier le texte seulement si le champ est vide
			if (inputField.val() === '') {
				inputField.val(selectedText);
			}
		});
	}
});


$(document).ready(function () {
	if (!$("body").hasClass("ns-0") || !$("body").hasClass("action-view") || !$("body").hasClass("is-authenticated")) {
		return;
	}

	/* 1. Déplacer le bouton Renommer après le titre de la page */
	function renameButton($content) {
		var $span = $content.find('#bouton-renommer');
		if ($span.length) {
			$span.prepend(' ');
			$span.css({
				display: 'inline-flex'
			});
			$('#firstHeading').append($span);
		}
	}
	mw.hook('wikipage.content').add(renameButton);

	/* 2. Déplacer le bouton Modifier le sujet du débat */
	function moveButtonWhenReady() {
		var bouton = document.getElementById("bouton-modifier-sujet");
		var tagline = document.querySelector(".pre-content.heading-holder .tagline");

		if (bouton && tagline) {
			bouton.style.cssFloat = "right";
			bouton.style.display = "inline";
			tagline.appendChild(bouton);
			clearInterval(waitForElements);
		}
	}
	var waitForElements = setInterval(moveButtonWhenReady, 300);

	/* 3. Déplacer le bouton Modifier les rubriques */
	(function() {
		var boutonId = "bouton-modifier-categories";
		var catId = "mw-normal-catlinks";

		function tryMoveButton() {
			var bouton = document.getElementById(boutonId);
			var categories = document.getElementById(catId);
			if (!bouton || !categories) return false;

			var ul = categories.querySelector("ul");
			if (!ul) return false;

			var lastLi = ul.querySelector("li:last-child");
			if (!lastLi) return false;

			if (bouton.parentElement !== lastLi) {
				lastLi.appendChild(bouton);
			}
			bouton.style.display = "inline";
			return true;
		}

		// Essaye immédiatement
		if (tryMoveButton()) return;

		// Sinon observe le DOM pour agir dès qu’ils apparaissent
		var observer = new MutationObserver(function() {
			if (tryMoveButton()) {
				observer.disconnect(); // Stopper l’observation
			}
		});
		observer.observe(document.body, { childList: true, subtree: true });
	})();

	/* 4. Déplacer le bouton Interlangue dans la sidebar */
	function moveInterlanguage($content) {
		var body = document.body;

		if (body.classList.contains('ns-0') && body.classList.contains('is-authenticated')) {
			var bouton = document.getElementById('bouton-modifier-interlangue');

			if (bouton) {
				var lien = bouton.querySelector('a');

				if (lien && lien.href) {
					var href = lien.getAttribute('href');
					var ul = document.getElementById('p-tb');

					if (ul && ul.tagName === 'UL') {
						var li = document.createElement('li');
						li.className = 'toggle-list-item';
						li.innerHTML =
							'<a ' +
							'class="toggle-list-item__anchor mw-ui-icon mw-ui-icon-before mw-ui-icon-wikimedia-language-base20" ' +
							'href="' + href + '">' +
							'<span class="toggle-list-item__icon">' +
							'<span class="toggle-list-item__label">Interlangue</span>' +
							'</span>' +
							'</a>';
						ul.appendChild(li);
					}
				}
				// Supprime l'élément #bouton-modifier-interlangue
				bouton.remove();
			}
		}
	}
	mw.hook('wikipage.content').add(moveInterlanguage);

	/* 5. Modifie l'icône du bouton Wikicode dans la sidebar */
	function replaceEditIcon($content) {
		var body = document.body;

		if (body.classList.contains('is-authenticated')) {
			var editLink = document.querySelector('#p-tb li a.menu__item--page-actions-overflow-editfull');
			if (editLink) {
				var icon = editLink.querySelector('.minerva-icon');
				if (icon && icon.classList.contains('minerva-icon--edit')) {
					icon.classList.remove('minerva-icon--edit');
					icon.classList.add('minerva-icon--wikicode');
				}
			}
		}
	}
	mw.hook('wikipage.content').add(replaceEditIcon);
	
	/* 6. Remplace le bouton Modifier le wikicode par Modifer avec formulaire */
	var intervalId = setInterval(function () {
		var boutonModifier = document.querySelector("#bouton-modifier-sujet");
		var caEdit = document.querySelector("#ca-edit");

		if (boutonModifier && caEdit) {
			var lien = boutonModifier.querySelector("a");
			if (lien && lien.href) {
				var nouveauHref = lien.href.replace("Sujet_de_d", "D");
				caEdit.href = nouveauHref;
			}
			clearInterval(intervalId); // Stoppe le polling une fois terminé
		} else {
			var boutonModifier = document.querySelector("#bouton-modifier-categories");
			var lien = boutonModifier.querySelector("a");
			if (lien && lien.href) {
				var nouveauHref = lien.href.replace("Rubriques_d'a", "A");
				caEdit.href = nouveauHref;
			}
		}
	}, 300);
});

/* Pour remplace le bouton Modifier le wikicode par Modifer avec formulaire dans les pages d'utilisateurs */
$(document).ready(function () {
	if (!$("body").hasClass("ns-2") || !$("body").hasClass("action-view") || !$("body").hasClass("is-authenticated")) {
		return;
	}
		var intervalId = setInterval(function () {
		var boutonModifier = document.querySelector("#bouton-modifier-page-utilisateur");
		var caEdit = document.querySelector("#ca-edit");

		if (boutonModifier && caEdit) {
			var lien = boutonModifier.querySelector("a");
			if (lien && lien.href) {
				caEdit.href = lien.href;
				clearInterval(intervalId); // Stoppe le polling une fois terminé
			}
		}
	}, 300);
});

/* Pour déplacer le bouton "Modifier le sujet du débat" à côté du sous-titre */
document.addEventListener("DOMContentLoaded", function() {
  var bouton = document.getElementById("bouton-modifier-sujet");
  var tagline = document.querySelector(".pre-content.heading-holder .tagline");
  if (bouton && tagline) {
    tagline.appendChild(bouton);
  }
});

/* Pour créer un menu déroulant de modification des arguments */
$('.ns-0').ready(function() {

	// Au clic sur un div.argument-expandable-title (pas encore expanded)
	$('.ns-0').on('click', 'div.argument-expandable-title:not(.expanded)', function() {
		var $argumentTitle = $(this);

		// Ajoute le lien "modifier" s'il n'existe pas déjà
		if ($argumentTitle.find('.modifier-argument').length === 0) {
			$argumentTitle.append('<span class="modifier-argument"><a href="#" title="Modifier cet argument">modifier</a></span>');
		}
	});

	// Au clic sur "modifier", afficher ou masquer le menu déroulant
	$('.ns-0').on('click', '.modifier-argument a', function(e) {
		e.preventDefault();

		var $boutonModifier = $(this);
		var $argumentTitle = $boutonModifier.closest('.argument-expandable-title');
		var identifiantEnc = $argumentTitle.attr('data-argument');
		var identifiant = encodeURIComponent(decodeURIComponent(identifiantEnc.replace(/\+/g, ' '))).replace(/%20/g, '_');

		// Vérifie si un menu pour CE bouton existe déjà
		var $existingMenu = $('.modifier-dropdown[data-parent="' + $argumentTitle.attr('id') + '"]');
		if ($existingMenu.length) {
			$existingMenu.remove();
			return; // Ferme simplement
		}

		// Ferme les autres dropdown existants
		$('.modifier-dropdown').remove();

		// Crée le menu déroulant
		var menu = $('<div class="modifier-dropdown"></div>').attr('data-parent', $argumentTitle.attr('id'));

		// Cherche le lien "Modifier le titre affiché"
		var lienModifierTitre = '#';

		// Premier cas : remonter jusqu'à .NavFramex
		var ancestor = $argumentTitle.closest('.NavFramex');
		if (ancestor.length) {
			var navHead = ancestor.find('.NavHead').first();
			if (navHead.length) {
				var modifierSection = navHead.find('.modifier-section').first();
				if (modifierSection.length) {
					var lienHref = modifierSection.find('a').attr('href');
					if (lienHref) {
						lienModifierTitre = lienHref;
					}
				}
			}
		} else {
			// Deuxième cas : remonter jusqu'à <h2.section-modifiable> au-dessus du <section> parent
			var section = $argumentTitle.closest('section');
			if (section.length) {
				var previousH2 = section.prev('h2.section-modifiable');
				if (previousH2.length) {
					var modifierSectionLink = previousH2.find('.modifier-section a').first();
					if (modifierSectionLink.length) {
						lienModifierTitre = modifierSectionLink.attr('href');
					}
				}
			}
		}

		// Ajoute le premier lien "Modifier le titre affiché"
		var lienTitre = $('<span><a></a></span>');
		var iconeTitre = $('<img>')
			.attr('src', '/w/images/fr/b/ba/Modifier.svg')
			.attr('alt', '')
			.attr('class', 'picto-dropdown');
		lienTitre.find('a')
			.attr('href', lienModifierTitre)
			.attr('target', '_self')
			.append(iconeTitre)
			.append('Modifier le titre affiché');
		menu.append(lienTitre);

		// Ajoute les trois boutons habituels
		var formulaireTexte = [
			{ formulaire: 'Résumé', texte: 'Modifier le résumé', icone: '/w/images/fr/c/c6/Contributions.svg' },
			{ formulaire: 'Citations', texte: 'Modifier les citations', icone: '/w/images/fr/6/6e/Citation.svg' },
			{ formulaire: 'Références', texte: 'Modifier les références', icone: '/w/images/fr/9/9e/Bibliographie.svg' }
		];
		$.each(formulaireTexte, function(index, item) {
			var lien = $('<span><a></a></span>');
			var icone = $('<img>')
				.attr('src', item.icone)
				.attr('alt', '')
				.attr('class', 'picto-dropdown');
			lien.find('a')
				.attr('href', '/wiki/Sp%C3%A9cial:AjouterDonn%C3%A9es/' + item.formulaire + '/' + identifiant)
				.attr('target', '_self')
				.append(icone)
				.append(item.texte);
			menu.append(lien);
		});

		// Ajoute le 4e lien "Voir la page détaillée"
		var lienExterne = $('<span class="onglet-externe"><a></a></span>');
		var iconeExterne = $('<img>')
			.attr('src', '/w/images/fr/7/74/Loupe-noire.svg')
			.attr('alt', '')
			.attr('class', 'picto-dropdown');
		lienExterne.find('a')
			.attr('href', '/wiki/' + identifiant)
			.attr('target', '_self')
			.append(iconeExterne)
			.append('Voir la page détaillée');
		menu.append(lienExterne);

		// Ajoute le menu déroulant à la fin de body
		$('body').append(menu);

		// Calcule et applique la position sous le bouton "modifier"
		var offset = $boutonModifier.offset();
		var height = $boutonModifier.outerHeight();
		var menuWidth = menu.outerWidth();

		var left = offset.left - menuWidth + $boutonModifier.outerWidth();
		if (left < 0) {
			left = $argumentTitle.offset().left;
		}

		menu.css({
			'top': offset.top + height,
			'left': left
		}).show();
	});

	// Ferme le menu si on clique ailleurs que sur le menu ou le bouton "modifier"
	$(document).on('click', function(e) {
		if (!$(e.target).closest('.modifier-dropdown, .modifier-argument').length) {
			$('.modifier-dropdown').remove();
		}
	});

});

/* Pour modifier le menu latéral de gauche pour Wikidébats */
/* global mw, $ */
(function () {
	'use strict';

	// Ne rien faire si on n'est pas sur Minerva
	if (!mw || mw.config.get('skin') !== 'minerva') return;

	mw.loader.using(['mediawiki.util']).then(function () {

		var i18n = {
			"randomDebate": "Débat au hasard",
			"allDebates": "Tous les débats",
			"about": "À propos de Wikidébats",
			"contact": "Contact",
			"aboutUrl": "https://fr.wikidebates.org/wiki/Wikid%C3%A9bats:%C3%80_propos",
			"contactUrl": "https://fr.wikidebates.org/wiki/Sp%C3%A9cial:Contact",
			"randomCategory": "Débats",
			"allDebatesUrl": "Portail:Débats",
			"contributionsPortal": "Portail des contributions",
			"contributionsUrl": "https://fr.wikidebates.org/wiki/Portail:Contributions",
			"bistro": "Bistro",
			"bistroUrl": "https://fr.wikidebates.org/wiki/Wikid%C3%A9bats:Bistro"
		};

		function addMenuItem(parentUl, itemId, linkText, url, extraClass, insertAtStart) {
			if (!parentUl || document.getElementById(itemId)) return null;

			var li = document.createElement('li');
			li.className = 'toggle-list-item';
			li.id = itemId;

			var a = document.createElement('a');
			a.className = 'toggle-list-item__anchor ' + (extraClass || '');
			a.href = url;
			a.setAttribute('data-mw', 'interface');

			var label = document.createElement('span');
			label.className = 'toggle-list-item__label';
			label.textContent = linkText;

			a.appendChild(label);
			li.appendChild(a);

			if (insertAtStart && parentUl.firstChild) {
				parentUl.insertBefore(li, parentUl.firstChild);
			} else {
				parentUl.appendChild(li);
			}
			return li;
		}

		function ensureAboutContact() {
			if (document.getElementById('pt-wikidebates')) return;

			var menuLeft = document.getElementById('mw-mf-page-left');
			if (!menuLeft) return;

			// Point d’ancrage prioritaire : #pt-preferences (AMC activé)
			var anchor = document.getElementById('pt-preferences');

			// Fallback AMC désactivé : #p-personal -> #p-interaction -> #p-navigation
			if (!anchor) anchor = document.getElementById('p-personal');
			if (!anchor) anchor = document.getElementById('p-interaction');
			if (!anchor) anchor = document.getElementById('p-navigation');

			// Dernier <ul> à défaut
			if (!anchor) {
				var allUls = menuLeft.querySelectorAll('ul');
				if (allUls.length) anchor = allUls[allUls.length - 1];
			}
			if (!anchor) return;

			var wikiDebatesList = document.createElement('ul');
			wikiDebatesList.id = 'pt-wikidebates';
			wikiDebatesList.className = 'toggle-list__list';
			anchor.parentNode.insertBefore(wikiDebatesList, anchor.nextSibling);

			addMenuItem(wikiDebatesList, 'pt-about', i18n.about, i18n.aboutUrl, 'menu__item--pt-about');
			addMenuItem(wikiDebatesList, 'pt-contact', i18n.contact, i18n.contactUrl, 'menu__item--pt-contact');
		}

		function applyMenuPatches() {
			// 1) Navigation : "Débat au hasard" + "Tous les débats"
			var navigationMenu = document.querySelector('ul#p-navigation');
			if (navigationMenu) {
				var randomLink = navigationMenu.querySelector('a.menu__item--random');
				if (randomLink) {
					randomLink.href = '/wiki/Special:RandomInCategory/' + encodeURIComponent(i18n.randomCategory);
					var label = randomLink.querySelector('.toggle-list-item__label');
					if (label) label.textContent = i18n.randomDebate;
				}

				addMenuItem(
					navigationMenu,
					'pt-debates',
					i18n.allDebates,
					(mw.util ? mw.util.getUrl(i18n.allDebatesUrl) : '/wiki/' + encodeURIComponent(i18n.allDebatesUrl)),
					'menu__item--pt-debates'
				);
			}

			// 2) Supprimer un éventuel <ul class="hlist">
			var hlist = document.querySelector('div#mw-mf-page-left > ul.hlist');
			if (hlist) hlist.remove();

			// 3) Interaction : ordre RC -> Contributions -> Bistro (seulement si AMC activé)
			if (!document.body.classList.contains('mw-mf-amc-disabled')) {
				var interactionMenu = document.querySelector('ul#p-interaction');
				if (interactionMenu) {
					// Supprimer "Pages spéciales"
					var specialA = interactionMenu.querySelector('a.menu__item--specialPages');
					if (specialA) {
						var specialLi = specialA.closest ? specialA.closest('li') : null;
						if (!specialLi) {
							// Fallback si closest indispo
							var p = specialA.parentNode;
							while (p && p.nodeType === 1 && p.tagName.toLowerCase() !== 'li') p = p.parentNode;
							specialLi = p;
						}
						if (specialLi && specialLi.parentNode) specialLi.parentNode.removeChild(specialLi);
					}

					// Supprimer Bistro existant (version ancienne ou speechBubbles)
					var bistroLi = document.getElementById('pt-bistro');
					if (!bistroLi) {
						var speechA = interactionMenu.querySelector('a.menu__item--speechBubbles');
						if (speechA) {
							bistroLi = speechA.closest ? speechA.closest('li') : null;
							if (!bistroLi) {
								var p2 = speechA.parentNode;
								while (p2 && p2.nodeType === 1 && p2.tagName.toLowerCase() !== 'li') p2 = p2.parentNode;
								bistroLi = p2;
							}
						}
					}
					if (bistroLi && bistroLi.parentNode) bistroLi.parentNode.removeChild(bistroLi);

					// Supprimer ancienne entrée "Portail des contributions"
					var contribLi = document.getElementById('pt-contributions');
					if (contribLi && contribLi.parentNode) contribLi.parentNode.removeChild(contribLi);

					// Réordonner après "Modifications récentes"
					var rcA = interactionMenu.querySelector('a.menu__item--recentchanges');
					var recentChanges = null;
					if (rcA) {
						recentChanges = rcA.closest ? rcA.closest('li') : null;
						if (!recentChanges) {
							var p3 = rcA.parentNode;
							while (p3 && p3.nodeType === 1 && p3.tagName.toLowerCase() !== 'li') p3 = p3.parentNode;
							recentChanges = p3;
						}
					}
					if (recentChanges) {
						var contrib = addMenuItem(
							interactionMenu,
							'pt-contributions',
							i18n.contributionsPortal,
							i18n.contributionsUrl,
							'menu__item--pt-contributions'
						);
						if (contrib && recentChanges.parentNode) {
							recentChanges.parentNode.insertBefore(contrib, recentChanges.nextSibling);
						}

						var bistro = addMenuItem(
							interactionMenu,
							'pt-bistro',
							i18n.bistro,
							i18n.bistroUrl,
							'menu__item--pt-bistro'
						);
						if (bistro && contrib && contrib.parentNode) {
							contrib.parentNode.insertBefore(bistro, contrib.nextSibling);
						}
					}
				}
			}

			// 4) Dans tous les cas : ajouter "À propos" & "Contact"
			ensureAboutContact();
		}

		function softInit() {
			applyMenuPatches();
		}

		// A) Si le menu est déjà là
		if (document.getElementById('mw-mf-page-left')) {
			softInit();
		}

		// B) Au premier clic sur le bouton menu
		var menuBtn = document.getElementById('mw-mf-main-menu-button');
		if (menuBtn) {
			var handler = function () {
				softInit();
				menuBtn.removeEventListener('click', handler);
			};
			menuBtn.addEventListener('click', handler);
		}

		// C) Observer l’arrivée du menu dans le DOM
		if (!document.getElementById('mw-mf-page-left') && 'MutationObserver' in window) {
			var obs = new MutationObserver(function () {
				if (document.getElementById('mw-mf-page-left')) {
					try { softInit(); } finally { obs.disconnect(); }
				}
			});
			obs.observe(document.documentElement, { childList: true, subtree: true });
		}

		// D) À chaque navigation AJAX
		if (mw.hook && mw.hook('wikipage.content')) {
			mw.hook('wikipage.content').add(function () {
				softInit();
			});
		}

		// E) En dernier recours
		if (window.requestIdleCallback) {
			requestIdleCallback(softInit, { timeout: 2000 });
		} else {
			setTimeout(softInit, 1200);
		}
	});
})();

/* Réactive les infobulles dans les formulaires après chargement de la page */
mw.loader.using( 'ext.smw.tooltip' ).then( function () {
	function reinitSMWTooltips( $root ) {
		if ( window.smw && smw.tooltip && smw.tooltip.init ) {
			smw.tooltip.init( $root || $( document ) );
		}
	}
	// 1) au premier affichage du formulaire
	reinitSMWTooltips( $( document ) );
	// 2) après ajouts dynamiques (multi-instance, etc.)
	$( document ).on( 'pfaddinstance pfafterrebuild pfcreateinput', function ( e ) {
		reinitSMWTooltips( $( e.target ) );
	} );
} );

//	Préchargement VE mobile pour Minerva (MW 1.43+)
$( function () {
	//	Ne faire ça que sur Minerva (mobile)
	if ( mw.config.get( 'skin' ) !== 'minerva' ) return;

	//	Modules VE à charger (noms actuels)
	const modules = [
		'ext.visualEditor.targetLoader',
		'ext.visualEditor.core',
		'ext.visualEditor.core.mobile',		//	classes UI mobiles (dont MobileWindowManager)
		'ext.visualEditor.mediawiki',
		'ext.visualEditor.mwcore',
		'ext.visualEditor.base',
		'ext.visualEditor.mobileArticleTarget'	//	cible mobile de VE
	];

	//	Ne demander que ceux qui existent (évite "Skipped unavailable module")
	const available = modules.filter( m => mw.loader.getState( m ) !== null );
	if ( available.length ) {
		mw.loader.load( available );
	}

	//	Fallback de sécurité si, malgré tout, la classe mobile manque
	mw.loader.using( [ 'ext.visualEditor.core' ].concat( available ) ).then( function () {
		if ( window.ve && !ve.ui.MobileWindowManager && ve.ui.SurfaceWindowManager ) {
			ve.ui.MobileWindowManager = ve.ui.SurfaceWindowManager;
		}
	} );
} );

/*\
* * SECTIONS DÉROULANTES
*	Attendu : 
*	<div class="fr-collapsible fr-collapsed">
*		<h3 class="fr-collapsible-toggle">…</h3>
*		<div class="fr-collapsible-content">…</div>
*	</div>
\*/
(function(){
	function bindFrCollapsible($root){
		$root.find('.fr-collapsible').each(function(){
			var $box = $(this);
			if($box.data('fr-collapsible-bound')) return;
			$box.data('fr-collapsible-bound', true);

			var $toggle = $box.children('.fr-collapsible-toggle').first();
			var $content = $box.children('.fr-collapsible-content').first();
			if(!$toggle.length || !$content.length) return;

			/* a11y + base (jamais display:none) */
			$toggle.attr({role:'button', tabindex:0});
			$content.removeAttr('hidden')[0].style.display = 'block';

			var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

			function openPanel(instant){
				$box.removeClass('fr-collapsed').addClass('fr-expanded');
				$toggle.attr('aria-expanded','true')
					.removeClass('fr-collapsible-toggle-collapsed')
					.addClass('fr-collapsible-toggle-expanded');
				$content.attr('aria-hidden','false');

				if(instant || reduce){
					$content.stop(true,true);
					$content[0].style.transition = 'none';
					$content[0].style.height = 'auto';
					$content[0].style.opacity = '1';
					void $content[0].offsetHeight;
					$content[0].style.transition = '';
					return;
				}

				$content.stop(true,true);
				$content[0].style.display = 'block';
				$content[0].style.height = '0px';
				$content[0].style.opacity = '0';
				requestAnimationFrame(function(){
					var h = $content[0].scrollHeight;
					$content[0].style.height = h+'px';
					$content[0].style.opacity = '1';
				});
				$content.one('transitionend', function(e){
					if(e.target !== $content[0]) return;
					$content[0].style.height = 'auto';
				});
			}

			function closePanel(instant){
				$box.removeClass('fr-expanded').addClass('fr-collapsed');
				$toggle.attr('aria-expanded','false')
					.removeClass('fr-collapsible-toggle-expanded')
					.addClass('fr-collapsible-toggle-collapsed');
				$content.attr('aria-hidden','true');

				if(instant || reduce){
					$content.stop(true,true);
					$content[0].style.transition = 'none';
					$content[0].style.height = '0px';
					$content[0].style.opacity = '0';
					void $content[0].offsetHeight;
					$content[0].style.transition = '';
					return;
				}

				$content.stop(true,true);
				$content[0].style.display = 'block';
				$content[0].style.height = $content[0].scrollHeight+'px';
				$content[0].style.opacity = '1';
				requestAnimationFrame(function(){
					$content[0].style.height = '0px';
					$content[0].style.opacity = '0';
				});
			}

			function toggle(){
				var willOpen = $box.hasClass('fr-collapsed');
				willOpen ? openPanel(false) : closePanel(false);
			}

			/* Mobile-first : pointer (tactile/souris/stylet) + clavier */
			$toggle.on('pointerup', function(e){
				/* laisser passer les contrôles internes */
				if($(e.target).closest('a,button,input,select,textarea,label').length) return;
				e.preventDefault();
				toggle();
			});
			$toggle.on('keydown', function(e){
				if(e.key === 'Enter' || e.key === ' ' || e.keyCode === 13 || e.keyCode === 32){
					e.preventDefault();
					toggle();
				}
			});

			/* État initial instantané */
			($box.hasClass('fr-collapsed') ? closePanel : openPanel)(true);
		});
	}

	/* MediaWiki */
	mw.hook('wikipage.content').add(function($content){ bindFrCollapsible($content); });
	$(function(){ bindFrCollapsible($(document)); });
})();