MediaWiki:Common.js
/* jshint esversion: 6, scripturl: true */
/* globals window, document, URL, setTimeout, console */
/* globals mw, $, importScript, MonobookToolbar */
/* exported obtenir, addSpecialCharset, addSpecialCharsetHTML, addCustomButton */
/**
* N'importe quel JavaScript ici sera chargé pour n'importe quel utilisateur et pour chaque page accédée.
*
* ATTENTION : Avant de modifier cette page, veuillez tester vos changements avec votre propre
* vector.js. Une erreur sur cette page peut faire bugger le site entier (et gêner l'ensemble des
* visiteurs), même plusieurs heures après la modification !
*
* Prière de ranger les nouvelles fonctions dans les sections adaptées :
* - Fonctions JavaScript
* - Fonctions spécifiques pour MediaWiki
* - Applications spécifiques à la fenêtre d'édition
* - Applications qui peuvent être utilisées sur toute page
* - Applications spécifiques à un espace de nom ou une page
*
* <nowiki> /!\ Ne pas retirer cette balise
*/
// Encapsulation de tout le code dans une IIFE globale
// (le code doit être exécuté immédiatement, donc ne pas mettre ici de mw.loader.using(), etc.)
( function () {
'use strict';
/*
* Les fonctions appliquées au contenu de page sont ajoutées à cet array,
* et à la fin du script ces fonctions sont exécutées dans un hook "wikipage.content",
* mais avec l'élément approprié pour le contenu de page.
*/
const pageContentHooks = [];
/***********************/
/* Fonctions générales */
/***********************/
/**
* Projet JavaScript
*/
window.obtenir = function ( name ) {
if ( mw.loader.getState( 'ext.gadget.' + name ) !== null ) {
mw.loader.load( 'ext.gadget.' + name );
} else {
importScript( 'MediaWiki:Gadget-' + name + '.js' );
}
};
/****************************************/
/* Applications pour l'ensemble du site */
/****************************************/
/**
* Appliquer le CSS des pages de discussion aux pages du Bistro, du BA et aux pages spécifiées
* Ne suffit pas à l'activation des outils de discussion améliorés
*/
if ( mw.config.get( 'wgNamespaceNumber' ) >= 2 && mw.config.get( 'wgNamespaceNumber' ) % 2 === 0 ) {
$( function ( $ ) { // eslint-disable-line no-unused-vars
const alwaysTransform = ( function () {
if ( ![ 4, 102 ].includes( mw.config.get( 'wgNamespaceNumber' ) ) ) {
return false;
}
// voir [[phab:T351243]] et par ailleurs [[Spécial:Diff/219320914]]
const pageName = mw.config.get( 'wgPageName' ).replace( /_/g, ' ' );
const basePages = [
"Wikipédia:Le Bistro",
"Wikipédia:Le Jardin",
"Wikipédia:Bulletin des administrateurs",
"Wikipédia:Bulletin des bureaucrates",
"Wikipédia:Bulletin des patrouilleurs",
"Wikipédia:Demande d'intervention sur une page protégée",
"Wikipédia:Demande d'intervention sur un message système",
"Wikipédia:Demande de protection de page",
"Wikipédia:Demande de fusion d'historiques",
"Wikipédia:Demande de purge d'historique",
"Wikipédia:Demande de renommage",
"Wikipédia:Demande de suppression immédiate",
"Wikipédia:Demande de restauration de page",
"Wikipédia:Bot/Requêtes",
"Wikipédia:Forum de relecture",
"Wikipédia:Forum des nouveaux",
"Wikipédia:Le salon de médiation",
"Wikipédia:Legifer",
"Wikipédia:Pages à fusionner",
"Wikipédia:Pages à scinder",
"Wikipédia:Questions techniques",
"Wikipédia:Requête aux administrateurs",
"Wikipédia:Sondage",
"Wikipédia:Vandalisme en cours",
"Wikipédia:Bulletin du filtrage",
"Wikipédia:AbuseFilter/Requêtes",
"Wikipédia:AbuseFilter/Faux positifs",
"Wikipédia:Oracle",
"Projet:Modèle/Demandes",
"Projet:Infobox/Demandes",
];
return basePages.some( function ( basePage ) {
return pageName === basePage || pageName.startsWith( basePage + '/' );
} );
} )();
if ( alwaysTransform ) {
document.body.classList.replace( 'ns-subject', 'ns-talk' );
} else {
pageContentHooks.push( function ( $pageContent ) {
if ( $pageContent.find( '#transformeEnPageDeDiscussion' ).length ) {
document.body.classList.replace( 'ns-subject', 'ns-talk' );
} else {
// on repose sur le fait que le code est exécuté uniquement dans les namespaces pairs (subject),
// autrement la ligne suivante irait transformer à tort des pages "talk" en "subject"
document.body.classList.replace( 'ns-talk', 'ns-subject' );
}
} );
}
} );
}
/**
* Tout ce qui concerne la page d'édition
*/
if ( [ 'edit', 'submit' ].includes( mw.config.get( 'wgAction' ) ) ) {
// chargement de [[MediaWiki:Gadget-CommonEdit.js]]
mw.loader.load( 'ext.gadget.CommonEdit' );
// pour que les fonctions soient définies dès maintenant,
// mais l'exécution réelle ne se fait qu'une fois le module chargé
window.addSpecialCharset = function ( title, chars ) {
mw.hook( 'CommonEdit.charsetFunctions.ready' ).add( function ( charsetFunctions ) {
charsetFunctions.addSpecialCharset( title, chars );
} );
};
window.addSpecialCharsetHTML = function ( title, charsHTML ) {
mw.hook( 'CommonEdit.charsetFunctions.ready' ).add( function ( charsetFunctions ) {
charsetFunctions.addSpecialCharsetHTML( title, charsHTML );
} );
};
// fonction pour ajouter un bouton à la fin de la barre d'outils
// permet d'utiliser [[MediaWiki:Gadget-MonobookToolbar.js]] sans se préoccuper de son chargement
window.addCustomButton = ( function () {
let promise;
return function ( ...args ) {
if ( !promise ) {
promise = mw.loader.using( 'ext.gadget.MonobookToolbar' );
}
promise.done( function () {
MonobookToolbar.addButton( ...args );
} );
};
} )();
} else {
// pour que les fonctions soient toujours définies,
// afin d'éviter aux scripts utilisateur de planter
window.addSpecialCharset = function () {};
window.addSpecialCharsetHTML = function () {};
window.addCustomButton = function () {};
}
/**
* Réécriture des titres
*
* Fonction utilisée par [[Modèle:Titre incorrect]]
*
* La fonction cherche un bandeau de la forme
* <div id="RealTitleBanner">
* <span id="RealTitle">titre</span>
* </div>
*
* Un élément comportant id="DisableRealTitle" désactive la fonction
*/
function rewritePageTitle( $ ) {
const $realTitleBanner = $( '#RealTitleBanner' );
if ( $realTitleBanner.length && !$( '#DisableRealTitle' ).length ) {
const $realTitle = $( '#RealTitle' );
const $h1 = $( '.mw-first-heading' );
const $header = ( mw.config.get( 'skin' ) === 'vector-2022' ) ? $( '.mw-body-header' ) : $h1;
if ( $realTitle.length && $h1.length && $header.length ) {
const titleHtml = $realTitle.html();
if ( titleHtml === '' ) {
$h1.hide();
} else {
$h1.html( titleHtml );
if ( mw.config.get( 'wgAction' ) === 'view' && !mw.config.get( 'wgDiffNewId' ) ) { // page views, exclude diff pages
// using a callback for replacement, to prevent interpreting "$" characters that realTitle might contain
document.title = document.title.replace( /^.+( [—–-] Wikipédia)$/, function ( match, p1 ) {
return $realTitle.text() + p1;
} );
}
}
$realTitleBanner.hide();
// voir [[phab:T351243]] et par ailleurs [[Spécial:Diff/219320914]]
$( '<p>' ).css( 'font-size', '80%' )
.append( 'Titre à utiliser pour créer un lien interne : ', $( '<b>' ).text( mw.config.get( 'wgPageName' ).replace( /_/g, ' ' ) ) )
.insertAfter( $header );
}
}
}
$( rewritePageTitle ); // TODO: éventuellement, compatibilité avec l'aperçu rapide
/**
* Ajout d'un sous-titre
*
* Fonction utilisée par [[Modèle:Sous-titre]] et quelques modules de taxobox
*
* La fonction cherche un élément de la forme
* <span id="sous_titre_h1">Sous-titre</span>
*/
function sousTitreH1( $pageContent ) {
$( '#sous_titre_h1_moved' ).remove();
const $span = $pageContent.find( '#sous_titre_h1' );
if ( $span.length ) {
$span.attr( 'id', 'sous_titre_h1_moved' );
$span.prepend( ' ' );
$( '.mw-first-heading' ).append( $span );
}
}
pageContentHooks.push( sousTitreH1 );
/**
* permet d'ajouter un petit lien (par exemple d'aide) à la fin du titre d'une page.
* utilisé par [[Modèle:Aide contextuelle]]
* known bug : conflit avec le changement de titre classique.
* Pour les commentaires, merci de contacter [[user:Plyd|Plyd]].
*/
function rewritePageH1bis( $ ) { // eslint-disable-line no-unused-vars
const helpPage = document.getElementById( 'helpPage' );
if ( helpPage ) {
const h1 = document.getElementsByClassName( 'mw-first-heading' )[ 0 ];
if ( h1 ) {
h1.insertAdjacentHTML( 'beforeend', `<span id="h1-helpPage">${ helpPage.innerHTML }</span>` );
}
}
}
$( rewritePageH1bis ); // TODO: éventuellement, compatibilité avec l'aperçu rapide
/**
* Boîtes déroulantes
*
* Pour [[Modèle:Méta palette de navigation]]
*/
// attention : ces deux variables sont aussi utilisées
// dans le code « Tout développer/réduire », plus bas dans cette page
const Palette_Derouler = '[afficher]';
const Palette_Enrouler = '[masquer]';
const Palette_max = 1;
function Palette_toggleContent( $table ) {
/*
direct children, car il ne faut pas prendre les lignes des éventuelles tables imbriquées
table > tbody (peut-être aussi thead à l'avenir) > tr
ensuite, on applique à toutes les lignes sauf la première
*/
$table.children().children( 'tr' ).slice( 1 ).toggleClass( 'navboxHidden' );
}
function Palette_onTogglerClick( e ) {
e.preventDefault();
if ( this.textContent === Palette_Enrouler ) {
this.textContent = Palette_Derouler;
} else {
this.textContent = Palette_Enrouler;
}
Palette_toggleContent( $( e.currentTarget.closest( '.collapsible' ) ) );
}
function Palette_onTitleClick( e ) {
if ( e.target.closest( 'a' ) ) {
return;
}
const toggler = this.querySelector( '.navboxToggle a' );
if ( toggler ) {
toggler.click(); // .click() natif du DOM, celui de jQuery ne fonctionne pas ici
}
}
function Palette( $pageContent ) {
const tableToGroup = new WeakMap();
const groupLengths = new WeakMap();
const $tables = $pageContent.find( '.collapsible' );
$tables.each( function ( _, table ) {
const group = table.parentNode.closest( '.navbox-container, .collapsible' );
if ( group ) {
tableToGroup.set( table, group );
groupLengths.set( group, ( groupLengths.get( group ) || 0 ) + 1 );
}
} );
$tables.each( function ( _, table ) {
const $table = $( table );
let collapsed = false;
if ( table.classList.contains( 'autocollapse' ) ) {
const group = tableToGroup.get( table );
if ( group && groupLengths.get( group ) > Palette_max ) {
collapsed = true;
}
} else if ( table.classList.contains( 'collapsed' ) ) {
collapsed = true;
}
const toggler = document.createElement( 'a' );
toggler.href = 'javascript:';
toggler.textContent = ( collapsed ? Palette_Derouler : Palette_Enrouler );
toggler.addEventListener( 'click', Palette_onTogglerClick );
const togglerContainer = document.createElement( 'span' );
togglerContainer.className = 'navboxToggle';
togglerContainer.append( '\xA0', toggler );
// le modèle dispose d'une classe "navbox-title",
// sauf que les palettes "inlinées" (e.g. « class="navbox collapsible collapsed" ») n'ont pas cette classe
$table.find( 'tr' ).eq( 0 ).find( 'th' ).eq( 0 ).prepend( togglerContainer );
if ( collapsed ) {
Palette_toggleContent( $table );
}
} );
// permet de dérouler/enrouler les palettes en cliquant n'importe où sur l'entête
// (utilisation de la classe "navbox-title", comme ça seules les vraies palettes utilisant le modèle sont ciblées)
$pageContent.find( '.navbox-title' )
.click( Palette_onTitleClick )
.css( 'cursor', 'pointer' );
}
pageContentHooks.push( Palette );
/**
* Pour [[Modèle:Boîte déroulante]]
*/
const BoiteDeroulante_Derouler = '[afficher]';
const BoiteDeroulante_Enrouler = '[masquer]';
function BoiteDeroulante_toggle( NavToggle ) {
const NavFrame = NavToggle.parentNode;
const caption = [];
caption[ 0 ] = NavFrame.dataset.boiteDeroulanteDerouler;
caption[ 1 ] = NavFrame.dataset.boiteDeroulanteEnrouler;
const hide = NavToggle.textContent === caption[ 1 ];
NavToggle.textContent = caption[ hide ? 0 : 1 ];
const NavContent = NavFrame.querySelector( '.NavContent' );
if ( hide ) {
NavContent.setAttribute( 'hidden', 'onbeforematch' in document.body ? 'until-found' : 'hidden' );
} else {
NavContent.removeAttribute( 'hidden' );
}
}
function BoiteDeroulante( $pageContent ) {
$pageContent.find( '.NavFrame' ).each( function ( _, NavFrame ) {
let Derouler;
let Enrouler;
if ( NavFrame.title && NavFrame.title.includes( '/' ) ) {
const CustomTexts = NavFrame.title.split( '/' );
Derouler = CustomTexts[ 0 ];
Enrouler = CustomTexts[ 1 ];
} else {
Derouler = BoiteDeroulante_Derouler;
Enrouler = BoiteDeroulante_Enrouler;
}
NavFrame.title = '';
NavFrame.dataset.boiteDeroulanteDerouler = Derouler;
NavFrame.dataset.boiteDeroulanteEnrouler = Enrouler;
const NavToggle = document.createElement( 'a' );
NavToggle.className = 'NavToggle';
NavToggle.href = 'javascript:';
NavToggle.addEventListener( 'click', function ( e ) {
e.preventDefault();
BoiteDeroulante_toggle( e.target );
} );
NavToggle.textContent = Enrouler;
NavFrame.prepend( NavToggle );
BoiteDeroulante_toggle( NavToggle );
const NavContent = NavFrame.querySelector( '.NavContent' );
NavContent.addEventListener( 'beforematch', () => {
NavToggle.textContent = NavFrame.dataset.boiteDeroulanteEnrouler;
NavContent.removeAttribute( 'hidden' );
} );
} );
// permet de dérouler/enrouler les boîtes en cliquant n'importe où sur l'entête
$pageContent.find( '.NavHead' )
.click( function ( e ) {
if ( e.target.closest( 'a' ) ) {
return;
}
const toggle = $( this ).siblings( 'a.NavToggle' )[ 0 ];
if ( toggle ) {
toggle.click(); // .click() natif du DOM, celui de jQuery ne fonctionne pas ici
}
} )
.css( 'cursor', 'pointer' );
}
pageContentHooks.push( BoiteDeroulante );
/**
* Script pour alterner entre plusieurs cartes de géolocalisation
*/
function GeoBox_Init( $pageContent ) {
// noter qu'une classe "imgtoggle" (sans l'underscore) est aussi présente sur le wiki, sans rapport avec celle-ci
$pageContent.find( '.img_toggle' ).each( function ( i, Container ) {
Container.id = 'img_toggle_' + i;
const Boxes = $( Container ).find( '.geobox' );
if ( Boxes.length < 2 ) {
return;
}
const ToggleLinksDiv = document.createElement( 'ul' );
ToggleLinksDiv.id = 'geoboxToggleLinks_' + i;
Boxes.each( function ( a, ThisBox ) {
ThisBox.id = 'geobox_' + i + '_' + a;
let ThisAlt;
const ThisImg = ThisBox.getElementsByTagName( 'img' )[ 0 ];
if ( ThisImg ) {
ThisAlt = ThisImg.alt;
}
if ( !ThisAlt ) {
ThisAlt = 'erreur : description non trouvée';
}
const toggle = document.createElement( 'a' );
toggle.id = 'geoboxToggle_' + i + '_' + a;
toggle.textContent = ThisAlt;
toggle.href = 'javascript:';
toggle.addEventListener( 'click', function ( e ) {
e.preventDefault();
GeoBox_Toggle( this );
} );
const Li = document.createElement( 'li' );
Li.append( toggle );
ToggleLinksDiv.append( Li );
if ( a === 0 ) {
toggle.style.color = '#888';
toggle.style.pointerEvents = 'none';
} else {
ThisBox.style.display = 'none';
}
} );
Container.append( ToggleLinksDiv );
} );
}
function GeoBox_Toggle( link ) {
const matches = link.id.match( /^geoboxToggle_(\d+)_(\d+)$/ );
if ( !matches ) {
return;
}
const ImgToggleIndex = matches[ 1 ];
const GeoBoxIndex = matches[ 2 ];
const ImageToggle = document.getElementById( 'img_toggle_' + ImgToggleIndex );
const Links = document.getElementById( 'geoboxToggleLinks_' + ImgToggleIndex );
const Geobox = document.getElementById( 'geobox_' + ImgToggleIndex + '_' + GeoBoxIndex );
const Link = document.getElementById( 'geoboxToggle_' + ImgToggleIndex + '_' + GeoBoxIndex );
if ( !ImageToggle || !Links || !Geobox || !Link ) {
return;
}
$( ImageToggle ).find( '.geobox' ).each( function ( _, ThisgeoBox ) {
if ( ThisgeoBox === Geobox ) {
ThisgeoBox.style.display = '';
} else {
ThisgeoBox.style.display = 'none';
}
} );
$( Links ).find( 'a' ).each( function ( _, thisToggleLink ) {
if ( thisToggleLink === Link ) {
thisToggleLink.style.color = '#888';
thisToggleLink.style.pointerEvents = 'none';
} else {
thisToggleLink.style.color = '';
thisToggleLink.style.pointerEvents = '';
}
} );
}
pageContentHooks.push( GeoBox_Init );
/**
* Configuration du tri des diacritique dans les tables de class "sortable"
*/
mw.config.set( 'tableSorterCollation', {'à':'a', 'â':'a', 'æ':'ae', 'é':'e', 'è':'e', 'ê':'e', 'î':'i', 'ï':'i', 'ô':'o', 'œ':'oe', 'û':'u', 'ç':'c', } );
/**
* Direct imagelinks to Commons
*
* Required modules: mediawiki.util, user.options
*
* @source www.mediawiki.org/wiki/Snippets/Direct_imagelinks_to_Commons
* @author Krinkle
* @version 2025-10-09
* Ajouté le 'uselang' ce 18 janvier 2016 — Ltrlg
*/
if ( mw.config.get( 'wgNamespaceNumber' ) >= 0 ) {
mw.loader.using( [ 'mediawiki.util', 'user.options' ], function () {
pageContentHooks.push( function ( $pageContent ) {
const uploadBaseRe = /^(https:)?\/\/upload\.wikimedia\.org\/wikipedia\/commons/;
const localFileNSString = mw.config.get( 'wgFormattedNamespaces' )[ '6' ] + ':';
const server = '(https:)?' + mw.util.escapeRegExp( mw.config.get( 'wgServer' ) );
const localBasePath = new RegExp( '^(?:' + server + ')?' + mw.util.escapeRegExp(
mw.util.getUrl( localFileNSString ) )
);
const localBaseScript = new RegExp( '^(?:' + server + ')?' + mw.util.escapeRegExp(
mw.util.wikiScript() + '?title=' + mw.util.wikiUrlencode( localFileNSString )
) );
const commonsBasePath = 'https://commons.wikimedia.org/wiki/File:';
const commonsBaseScript = 'https://commons.wikimedia.org/w/index.php?title=File:';
const lang = mw.user.options.get( 'language' );
$pageContent.find( '.mw-file-description' ).each( function ( i, link ) {
if ( link.tagName !== 'A' ) {
return;
}
const img = link.querySelector( 'img' );
// attention : on lit l'attribut, et non la propriété (elle contient en plus le protocole)
// (en prime, il est plus performant dans ce cas de lire l'attribut)
if ( img && uploadBaseRe.test( img.getAttribute( 'src' ) ) ) {
const currVal = link.getAttribute( 'href' );
if ( localBasePath.test( currVal ) ) {
link.setAttribute( 'href', currVal.replace( localBasePath, commonsBasePath ) + '?uselang=' + lang );
} else if ( localBaseScript.test( currVal ) ) {
link.setAttribute( 'href', currVal.replace( localBaseScript, commonsBaseScript ) + '&uselang=' + lang );
}
}
} );
} );
} );
}
/**
* Ajout d'un lien « Ajouter un sujet » en bas de page
*/
if ( mw.config.get( 'wgAction' ) === 'view' ) {
$( function ( $ ) {
if (
// onglet sticky « Ajouter un sujet » des outils de discussion sur Vector 2022
document.getElementById( 'ca-addsection-sticky-header' )
// élément « Démarrer une discussion » sur les pdd vides
|| document.body.classList.contains( 'ext-discussiontools-emptystate-shown' )
) {
return;
}
const addSectionLink = $( '#ca-addsection' ).find( 'a' )[ 0 ];
if ( !addSectionLink ) { // pas d'onglet « Ajouter un sujet »
return;
}
const $container = $( '<div style="clear:both; text-align:right; font-size:0.9em; margin:1em 0 -0.5em;" class="noprint">' );
const link = document.createElement( 'a' );
link.href = addSectionLink.href; // ce href sert encore, pour les middle-click, Ctrl+click... (ouverture dans un nouvel onglet)
link.title = addSectionLink.title;
link.textContent = addSectionLink.textContent;
// compatibilité avec DiscussionTools, voir [[mw:Extension:DiscussionTools]]
link.addEventListener( 'click', function ( e ) {
if ( !e.ctrlKey ) {
e.preventDefault();
addSectionLink.click(); // .click() natif du DOM, celui de jQuery ne fonctionne pas ici
}
} );
$container.append( link );
$( '#mw-content-text' ).append( $container );
} );
}
/**
* Permet d'afficher les catégories cachées sur bureau, en ajoutant un (+) à la manière des boîtes déroulantes
*/
function addHiddenCatsToggler( $catlinks ) {
if ( new URL( document.URL ).searchParams.get( 'printable' ) === 'yes' ) {
return;
}
const cl = $catlinks[ 0 ];
if ( !cl || cl.id !== 'catlinks' ) {
mw.log.warn( 'wikipage.categories hook did not receive the #catlinks element' );
return;
}
const hc = cl.querySelector( '#mw-hidden-catlinks' );
if ( !hc ) {
return;
}
if ( hc.classList.contains( 'mw-hidden-cats-user-shown' ) ) {
return;
}
if ( hc.classList.contains( 'mw-hidden-cats-ns-shown' ) ) {
hc.classList.add( 'mw-hidden-cats-hidden' );
}
let nc = cl.querySelector( '#mw-normal-catlinks' );
if ( !nc ) {
nc = document.createElement( 'div' );
nc.id = 'mw-normal-catlinks';
nc.className = 'mw-normal-catlinks';
const a = document.createElement( 'a' );
a.href = '/wiki/Catégorie:Accueil';
a.title = 'Catégorie:Accueil';
a.textContent = 'Catégories';
nc.append( a, ' : ' );
cl.prepend( nc );
cl.classList.remove( 'catlinks-allhidden' );
}
const lnk = document.createElement( 'a' );
lnk.id = 'mw-hidden-cats-link';
lnk.title = 'Cet article contient des catégories cachées';
lnk.style.cursor = 'pointer';
lnk.style.color = 'var(--color-emphasized, black)';
lnk.style.marginLeft = '0.3em';
lnk.addEventListener( 'click', toggleHiddenCats );
lnk.textContent = '[+]';
nc.append( lnk );
}
function toggleHiddenCats( e ) {
const hc = document.getElementById( 'mw-hidden-catlinks' );
if ( hc.classList.contains( 'mw-hidden-cats-hidden' ) ) {
hc.classList.remove( 'mw-hidden-cats-hidden' );
hc.classList.add( 'mw-hidden-cat-user-shown' );
e.target.textContent = '[–]';
} else {
hc.classList.remove( 'mw-hidden-cat-user-shown' );
hc.classList.add( 'mw-hidden-cats-hidden' );
e.target.textContent = '[+]';
}
}
mw.hook( 'wikipage.categories' ).add( addHiddenCatsToggler );
/**
* Repositionnement de la page sur l'ancre avec laquelle elle a été appelée
* après le repli des boîtes déroulantes, entre autres.
*/
if ( window.location.hash ) {
$( function ( $ ) { // eslint-disable-line no-unused-vars
setTimeout( function () {
try {
const anchorId = decodeURIComponent( window.location.hash.substring( 1 ) );
const anchorElement = document.getElementById( anchorId );
if ( anchorElement ) {
anchorElement.scrollIntoView();
}
} catch ( e ) {
console.warn( 'Invalid URI fragment:', e );
}
}, 1 );
} );
}
/*********************************************************************/
/* Fonctions strictement spécifiques à un espace de nom ou à une page */
/*********************************************************************/
// ESPACE DE NOM 'SPECIAL'
if ( mw.config.get( 'wgNamespaceNumber' ) === -1 ) {
/**
* Ajoute le namespace et l'éventuelle limite de pagination en cours aux filtres personnalisés sur [[Spécial:Pages liées]]
* Voir aussi [[MediaWiki:Linkshere]]
*/
if ( mw.config.get( 'wgCanonicalSpecialPageName' ) === 'Whatlinkshere' ) {
const query = new URL( document.URL ).searchParams;
let append = '';
for ( const name of [ 'namespace', 'invert', 'limit' ] ) {
const value = query.getAll( name ).pop();
if ( value ) {
append += '&' + name + '=' + encodeURIComponent( value );
}
}
if ( append !== '' ) {
$( function ( $ ) {
$( '#whatlinkshere-customfilters' ).find( 'a' ).each( function () {
this.href += append;
} );
} );
}
}
/**
* Affiche un modèle Information sur la page de téléchargement de fichiers [[Spécial:Téléchargement]]
* Voir aussi [[MediaWiki:Onlyifuploading.js]]
*/
if ( mw.config.get( 'wgCanonicalSpecialPageName' ) === 'Upload' ) {
importScript( 'MediaWiki:Onlyifuploading.js' );
}
} // Fin du code concernant l'espace de nom 'Special'
/*********************************************************************/
/* Modification du comportement d'un bouton du menu */
/*********************************************************************/
/**
* Ajout d'écouteurs d'événement au bouton Développer / Réduire pour qu'il affecte également les éléments déroulants définis sur cette page :
* - les palettes
* - les boîtes déroulantes
* - les catégories cachées (le bouton ne sera pas ajouté s'il n'y a que des catégories cachées à dérouler)
*/
mw.loader.using( [ 'mediawiki.util', 'mediawiki.page.ready' ], function () {
const expand_text = 'Tout développer';
const collapse_text = 'Tout réduire';
const expand_tooltip = 'Développer tous les éléments réductibles de la page actuelle';
const collapse_tooltip = 'Réduire tous les éléments réductibles de la page actuelle';
let allExpanded = false;
let toggleAll = document.querySelector( '#t-collapsible-toggle-all a' );
if ( !toggleAll && $( '.mw-body-content .collapsible, .mw-body-content .NavToggle' ).length ) {
// Si présence d'éléments déroulants et bouton absent, on ajoute le bouton nous-même.
const portletLink = mw.util.addPortletLink(
'p-tb',
'#',
expand_text,
't-collapsible-toggle-all',
expand_tooltip
);
if ( portletLink ) {
// set up the toggle link
toggleAll = portletLink.querySelector( 'a' );
toggleAll.setAttribute( 'role', 'button' );
toggleAll.setAttribute( 'aria-expanded', 'false' );
}
}
if ( toggleAll ) {
toggleAll.addEventListener( 'click', ( e ) => {
e.preventDefault();
if ( !allExpanded ) { /* Tout est réduit ou dans son état initial -> on déroule */
/* Palettes */
$( '.navboxToggle a' ).each( function () {
if ( this.textContent === Palette_Derouler ) {
this.click(); // .click() natif du DOM, celui de jQuery ne fonctionne pas ici
}
} );
/* Boîtes déroulantes */
$( 'a.NavToggle' ).each( function () {
const NavFrame = this.parentNode;
if ( this.textContent === NavFrame.dataset.boiteDeroulanteDerouler ) {
this.click(); // .click() natif du DOM, celui de jQuery ne fonctionne pas ici
}
} );
/* Catégories cachées */
const cl = $( '#mw-hidden-catlinks' );
if ( cl.hasClass( 'mw-hidden-cats-hidden' ) ) {
cl.removeClass( 'mw-hidden-cats-hidden' );
cl.addClass( 'mw-hidden-cat-user-shown' );
$( '#mw-hidden-cats-link' ).text( '[-]' );
}
/* Mise à jour des propriétés du bouton pour le cas où on l'a ajouté nous-mêmes */
toggleAll.textContent = collapse_text;
toggleAll.title = collapse_tooltip;
toggleAll.setAttribute( 'aria-expanded', 'true' );
allExpanded = true;
} else { /* Tout est déplié -> on réduit */
/* Palettes */
$( '.navboxToggle a' ).each( function () {
if ( this.textContent === Palette_Enrouler ) {
this.click(); // .click() natif du DOM, celui de jQuery ne fonctionne pas ici
}
} );
/* Boîtes déroulantes */
$( 'a.NavToggle' ).each( function () {
const NavFrame = this.parentNode;
if ( this.textContent === NavFrame.dataset.boiteDeroulanteEnrouler ) {
this.click(); // .click() natif du DOM, celui de jQuery ne fonctionne pas ici
}
} );
/* Catégories cachées */
const cl = $( '#mw-hidden-catlinks' );
if ( !cl.hasClass( 'mw-hidden-cats-hidden' ) ) {
cl.removeClass( 'mw-hidden-cat-user-shown' );
cl.addClass( 'mw-hidden-cats-hidden' );
$( '#mw-hidden-cats-link' ).text( '[+]' );
}
/* Mise à jour des propriétés du bouton pour le cas où on l'a ajouté nous-mêmes */
toggleAll.textContent = expand_text;
toggleAll.title = expand_tooltip;
toggleAll.setAttribute( 'aria-expanded', 'false' );
allExpanded = false;
}
} );
}
} );
/*
* Exécution des fonctions ajoutées à l'array "pageContentHooks"
*
* Pour info : nous sommes sûrs que $content est déjà inséré dans la page, cf. [[phab:T341349]]
* Edit : pas confiance. Par exemple, avec l'éditeur visuel c'est détaché malgré le warning, cf. [[phab:T341349#10163990]]
* Par conséquent, considérer que l'élément peut aussi être détaché.
*/
mw.hook( 'wikipage.content' ).add( function ( $content ) {
/*
* Désactivation de toutes les fonctions en "pageContentHooks" de cette page
* avec les (nombreuses) prévisualisations de DiscussionTools (voir [[mw:Help:DiscussionTools]]) :
* - soit ça bugue parce que ça agit sur du contenu en dehors de $content (c'était le cas de "addHiddenCatsToggler")
* - soit ça fonctionne quand même, mais ça serait gênant (exemple : "transformeEnPageDeDiscussion")
* - soit il est peu probable que cela soit utilisé dans un message (exemples : palettes, boîtes déroulantes, etc.)
*/
if ( $content[ 0 ].matches( '.ext-discussiontools-ui-replyWidget-preview' ) ) {
return;
}
/*
* Sélection plus précise de l'élément avec le contenu de page,
* pour éviter l'interface de diff, l'interface de modification, le print footer...
* ainsi que les pages qui n'ont pas de contenu (historiques, pages spéciales, etc.)
*/
let $pageContent;
const $parserOutput = $content.find( '.mw-parser-output' );
if ( $parserOutput.length ) { // élément avec le contenu de page
$pageContent = $parserOutput;
} else if ( $content.hasClass( 'mw-parser-output' ) ) { // [[phab:T349298]]
$pageContent = $content;
} else { // pas de contenu de page (historiques, pages spéciales, etc.)
return;
}
for ( const hook of pageContentHooks ) {
hook( $pageContent );
}
} );
} )(); // Fermeture de la IIFE globale
// </nowiki> /!\ Ne pas retirer cette balise
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.