MediaWiki:Minerva.js
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)); }); })();