« MediaWiki:Common.js » : différence entre les versions
Page de l’interface de MediaWiki
Autres actions
Aucun résumé des modifications |
Aucun résumé des modifications |
||
| (5 versions intermédiaires par le même utilisateur non affichées) | |||
| Ligne 1 : | Ligne 1 : | ||
/* Tout JavaScript | /* Tout JavaScript present ici sera execute par tous les utilisateurs a chaque chargement de page. */ | ||
/* ===== Fil d'Ariane des tuiles dans l'en-tete (skin Citizen) ===== | /* ===== Fil d'Ariane des tuiles dans l'en-tete (skin Citizen) ===== | ||
Affiche entre Accueil et Recherche la | Affiche entre Accueil et Recherche UN rectangle noir avec le titre | ||
la page | de la tuile la plus pertinente pour la page courante : | ||
0) page de provenance : chaque clic interne memorise la page ou l'on | |||
etait (sessionStorage) ; si c'est la cible d'une tuile (ex. on | |||
arrive de RetroGaming), c'est CETTE tuile qui est affichee. | |||
Le referrer sert de secours (bouton precedent, URL saisie). | |||
1) sinon si la page est elle-meme cible d'une tuile : sa tuile | |||
2) sinon (sous-article) : parmi les hubs qui pointent vers la page, | |||
le seul dont le nom ressemble le plus a celui de la page. | |||
MediaWiki 1.45 : le module mediawiki.title n'existe plus, | |||
mw.Title est fourni par mediawiki.api. | |||
Un MutationObserver re-insere la pastille si le skin reconstruit | |||
l'en-tete apres l'insertion. */ | |||
( function () { | ( function () { | ||
'use strict'; | 'use strict'; | ||
if ( mw.config.get( 'wgNamespaceNumber' ) !== 0 ) return; | if ( mw.config.get( 'wgNamespaceNumber' ) !== 0 ) return; | ||
// Memorise la page de provenance a chaque clic sur un lien interne. | |||
document.addEventListener( 'click', function ( e ) { | |||
var a = e.target && e.target.closest ? e.target.closest( 'a[href]' ) : null; | |||
if ( !a ) return; | |||
try { | |||
var u = new URL( a.href, location.href ); | |||
if ( u.hostname === location.hostname ) { | |||
sessionStorage.setItem( 'fil-ariane-precedente', | |||
location.pathname + location.search ); | |||
} | |||
} catch ( err ) {} | |||
} ); | |||
var current = mw.config.get( 'wgPageName' ); | var current = mw.config.get( 'wgPageName' ); | ||
if ( current === 'Accueil' ) return; | if ( current === 'Accueil' ) return; | ||
function titreNormalise( nom ) { | |||
try { return new mw.Title( nom ).toText(); } | |||
catch ( e ) { return nom; } | |||
} | |||
function similarite( a, b ) { | |||
var na = a.toLowerCase().replace( /_/g, ' ' ).split( /[^a-z0-9]+/ ).filter( Boolean ); | |||
var nb = b.toLowerCase().replace( /_/g, ' ' ).split( /[^a-z0-9]+/ ).filter( Boolean ); | |||
if ( !na.length || !nb.length ) return 0; | |||
var setB = {}; | |||
nb.forEach( function ( t ) { setB[ t ] = 1; } ); | |||
var commun = 0; | |||
na.forEach( function ( t ) { if ( setB[ t ] ) commun++; } ); | |||
return commun / Math.max( na.length, nb.length ); | |||
} | |||
function titreDepuisUrl( url ) { | |||
if ( !url ) return null; | |||
try { | |||
var u = new URL( url, location.origin ); | |||
var t = u.searchParams.get( 'title' ); | |||
if ( !t ) { | |||
var m = u.pathname.match( /\/index\.php\/(.+)$/ ); | |||
if ( m ) t = decodeURIComponent( m[ 1 ] ); | |||
} | |||
if ( !t ) return null; | |||
return titreNormalise( t.replace( /#.*/, '' ) ); | |||
} catch ( e ) { return null; } | |||
} | |||
function pastilles( tuiles ) { | function pastilles( tuiles ) { | ||
function construire() { | |||
var zone = document.createElement( 'div' ); | |||
zone.className = 'tuile-fil-ariane citizen-header__item'; | |||
tuiles.forEach( function ( t ) { | |||
var a = document.createElement( 'a' ); | |||
a.href = mw.util.getUrl( t.cible ); | |||
a.className = 'tuile-pastille'; | |||
a.title = 'Retour a la tuile : ' + t.titre; | |||
var span = document.createElement( 'span' ); | |||
span.textContent = t.titre; | |||
a.appendChild( span ); | |||
zone.appendChild( a ); | |||
} ); | |||
return zone; | |||
} | |||
var | |||
function verifier() { | |||
var header = document.querySelector( '.citizen-header' ); | |||
if ( !header ) return; | |||
if ( header.querySelector( '.tuile-fil-ariane' ) ) return; | |||
} ); | var logo = header.querySelector( '.citizen-header__logo' ); | ||
if ( !logo ) return; | |||
logo.insertAdjacentElement( 'afterend', construire() ); | |||
} | |||
verifier(); | |||
// Le skin peut reconstruire l'en-tete apres insertion : re-insere si besoin. | |||
var observer = new MutationObserver( verifier ); | |||
observer.observe( document.body, { childList: true, subtree: true } ); | |||
window.addEventListener( 'load', verifier ); | |||
} | } | ||
function lancer() { | function lancer() { | ||
var api = new mw.Api(); | var api = new mw.Api(); | ||
var norm = | var norm = titreNormalise( current ); | ||
api.get( { action: 'parse', page: 'Accueil', prop: 'text', formatversion: 2 } ) | api.get( { action: 'parse', page: 'Accueil', prop: 'text', formatversion: 2 } ) | ||
.then( function ( data ) { | .then( function ( data ) { | ||
| Ligne 53 : | Ligne 116 : | ||
} | } | ||
} ); | } ); | ||
var trouvees = tuiles.filter( function ( t ) { | function tuileDe( titreCible ) { | ||
return | var trouvees = tuiles.filter( function ( t ) { | ||
} ); | return titreNormalise( t.cible ) === titreCible; | ||
} ); | |||
return trouvees.length ? trouvees[ 0 ] : null; | |||
} | |||
// 0) page de provenance (clic memorise, puis referrer en secours) | |||
var provenances = [ | |||
titreDepuisUrl( sessionStorage.getItem( 'fil-ariane-precedente' ) ), | |||
titreDepuisUrl( document.referrer ) | |||
]; | |||
for ( var i = 0; i < provenances.length; i++ ) { | |||
var ref = provenances[ i ]; | |||
if ( ref && ref !== norm ) { | |||
var tuileRef = tuileDe( ref ); | |||
if ( tuileRef ) { pastilles( [ tuileRef ] ); return; } | |||
} | |||
} | |||
// 1) la page courante EST la cible d'une tuile | |||
var directe = tuileDe( norm ); | |||
if ( directe ) { pastilles( [ directe ] ); return; } | |||
// 2) sous-article : hubs qui pointent vers la page courante | |||
return api.get( { action: 'query', list: 'backlinks', bltitle: norm, | return api.get( { action: 'query', list: 'backlinks', bltitle: norm, | ||
bllimit: 500, blnamespace: 0, formatversion: 2 } ) | bllimit: 500, blnamespace: 0, formatversion: 2 } ) | ||
.then( function ( bd ) { | .then( function ( bd ) { | ||
var liens = ( bd.query.backlinks || [] ). | var liens = {}; | ||
( bd.query.backlinks || [] ).forEach( function ( p ) { | |||
liens[ titreNormalise( p.title ) ] = 1; | |||
} ); | } ); | ||
if ( | var candidats = tuiles.filter( function ( t ) { | ||
return liens[ titreNormalise( t.cible ) ]; | |||
} ); | |||
if ( !candidats.length ) return; | |||
// une seule pastille : le parent au nom le plus proche | |||
var best = candidats[ 0 ]; | |||
var bestScore = -1; | |||
candidats.forEach( function ( t ) { | |||
var s = similarite( t.cible, current ); | |||
if ( s > bestScore ) { bestScore = s; best = t; } | |||
} ); | |||
pastilles( [ best ] ); | |||
} ); | } ); | ||
} ); | } ); | ||
} | } | ||
function quandPret( fn ) { | |||
if ( document.readyState !== 'loading' ) { fn(); } | |||
else { document.addEventListener( 'DOMContentLoaded', fn ); } | |||
} | |||
quandPret( function () { | |||
mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ], lancer ); | |||
} ); | |||
}() ); | }() ); | ||
Dernière version du 24 octobre 2026 à 13:46
/* Tout JavaScript present ici sera execute par tous les utilisateurs a chaque chargement de page. */
/* ===== Fil d'Ariane des tuiles dans l'en-tete (skin Citizen) =====
Affiche entre Accueil et Recherche UN rectangle noir avec le titre
de la tuile la plus pertinente pour la page courante :
0) page de provenance : chaque clic interne memorise la page ou l'on
etait (sessionStorage) ; si c'est la cible d'une tuile (ex. on
arrive de RetroGaming), c'est CETTE tuile qui est affichee.
Le referrer sert de secours (bouton precedent, URL saisie).
1) sinon si la page est elle-meme cible d'une tuile : sa tuile
2) sinon (sous-article) : parmi les hubs qui pointent vers la page,
le seul dont le nom ressemble le plus a celui de la page.
MediaWiki 1.45 : le module mediawiki.title n'existe plus,
mw.Title est fourni par mediawiki.api.
Un MutationObserver re-insere la pastille si le skin reconstruit
l'en-tete apres l'insertion. */
( function () {
'use strict';
if ( mw.config.get( 'wgNamespaceNumber' ) !== 0 ) return;
// Memorise la page de provenance a chaque clic sur un lien interne.
document.addEventListener( 'click', function ( e ) {
var a = e.target && e.target.closest ? e.target.closest( 'a[href]' ) : null;
if ( !a ) return;
try {
var u = new URL( a.href, location.href );
if ( u.hostname === location.hostname ) {
sessionStorage.setItem( 'fil-ariane-precedente',
location.pathname + location.search );
}
} catch ( err ) {}
} );
var current = mw.config.get( 'wgPageName' );
if ( current === 'Accueil' ) return;
function titreNormalise( nom ) {
try { return new mw.Title( nom ).toText(); }
catch ( e ) { return nom; }
}
function similarite( a, b ) {
var na = a.toLowerCase().replace( /_/g, ' ' ).split( /[^a-z0-9]+/ ).filter( Boolean );
var nb = b.toLowerCase().replace( /_/g, ' ' ).split( /[^a-z0-9]+/ ).filter( Boolean );
if ( !na.length || !nb.length ) return 0;
var setB = {};
nb.forEach( function ( t ) { setB[ t ] = 1; } );
var commun = 0;
na.forEach( function ( t ) { if ( setB[ t ] ) commun++; } );
return commun / Math.max( na.length, nb.length );
}
function titreDepuisUrl( url ) {
if ( !url ) return null;
try {
var u = new URL( url, location.origin );
var t = u.searchParams.get( 'title' );
if ( !t ) {
var m = u.pathname.match( /\/index\.php\/(.+)$/ );
if ( m ) t = decodeURIComponent( m[ 1 ] );
}
if ( !t ) return null;
return titreNormalise( t.replace( /#.*/, '' ) );
} catch ( e ) { return null; }
}
function pastilles( tuiles ) {
function construire() {
var zone = document.createElement( 'div' );
zone.className = 'tuile-fil-ariane citizen-header__item';
tuiles.forEach( function ( t ) {
var a = document.createElement( 'a' );
a.href = mw.util.getUrl( t.cible );
a.className = 'tuile-pastille';
a.title = 'Retour a la tuile : ' + t.titre;
var span = document.createElement( 'span' );
span.textContent = t.titre;
a.appendChild( span );
zone.appendChild( a );
} );
return zone;
}
function verifier() {
var header = document.querySelector( '.citizen-header' );
if ( !header ) return;
if ( header.querySelector( '.tuile-fil-ariane' ) ) return;
var logo = header.querySelector( '.citizen-header__logo' );
if ( !logo ) return;
logo.insertAdjacentElement( 'afterend', construire() );
}
verifier();
// Le skin peut reconstruire l'en-tete apres insertion : re-insere si besoin.
var observer = new MutationObserver( verifier );
observer.observe( document.body, { childList: true, subtree: true } );
window.addEventListener( 'load', verifier );
}
function lancer() {
var api = new mw.Api();
var norm = titreNormalise( current );
api.get( { action: 'parse', page: 'Accueil', prop: 'text', formatversion: 2 } )
.then( function ( data ) {
var doc = new DOMParser().parseFromString( data.parse.text, 'text/html' );
var tuiles = [];
doc.querySelectorAll( '.accueil-tile' ).forEach( function ( el ) {
var cible = el.getAttribute( 'data-cible' );
var cle = el.getAttribute( 'data-tuile' );
var titre = el.querySelector( '.accueil-tile-title' );
if ( cible && cle ) {
tuiles.push( {
cible: cible, key: cle,
titre: titre ? titre.textContent.trim() : cle
} );
}
} );
function tuileDe( titreCible ) {
var trouvees = tuiles.filter( function ( t ) {
return titreNormalise( t.cible ) === titreCible;
} );
return trouvees.length ? trouvees[ 0 ] : null;
}
// 0) page de provenance (clic memorise, puis referrer en secours)
var provenances = [
titreDepuisUrl( sessionStorage.getItem( 'fil-ariane-precedente' ) ),
titreDepuisUrl( document.referrer )
];
for ( var i = 0; i < provenances.length; i++ ) {
var ref = provenances[ i ];
if ( ref && ref !== norm ) {
var tuileRef = tuileDe( ref );
if ( tuileRef ) { pastilles( [ tuileRef ] ); return; }
}
}
// 1) la page courante EST la cible d'une tuile
var directe = tuileDe( norm );
if ( directe ) { pastilles( [ directe ] ); return; }
// 2) sous-article : hubs qui pointent vers la page courante
return api.get( { action: 'query', list: 'backlinks', bltitle: norm,
bllimit: 500, blnamespace: 0, formatversion: 2 } )
.then( function ( bd ) {
var liens = {};
( bd.query.backlinks || [] ).forEach( function ( p ) {
liens[ titreNormalise( p.title ) ] = 1;
} );
var candidats = tuiles.filter( function ( t ) {
return liens[ titreNormalise( t.cible ) ];
} );
if ( !candidats.length ) return;
// une seule pastille : le parent au nom le plus proche
var best = candidats[ 0 ];
var bestScore = -1;
candidats.forEach( function ( t ) {
var s = similarite( t.cible, current );
if ( s > bestScore ) { bestScore = s; best = t; }
} );
pastilles( [ best ] );
} );
} );
}
function quandPret( fn ) {
if ( document.readyState !== 'loading' ) { fn(); }
else { document.addEventListener( 'DOMContentLoaded', fn ); }
}
quandPret( function () {
mw.loader.using( [ 'mediawiki.api', 'mediawiki.util' ], lancer );
} );
}() );