MediaWiki:Common.js
De CK3 - FR
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() {
// Liste des IDs de menus à garder ouverts par défaut (ex: 'navigation', 'search')
// Laissez vide [] pour que tout soit fermé au chargement.
var showTheseMenus = [];
$('#mw-site-navigation .mw-portlet').each(function() {
var $portlet = $(this);
var $heading = $portlet.find('h3');
var $body = $portlet.find('.mw-portlet-body');
if ($heading.length && $body.length) {
// 1. Gestion de l'état initial
var portletId = $portlet.attr('id');
var isOpenByDefault = false;
// Vérifie si ce menu doit être ouvert par défaut
for (var i = 0; i < showTheseMenus.length; i++) {
if (portletId && portletId.indexOf(showTheseMenus[i]) !== -1) {
isOpenByDefault = true;
break;
}
}
// 2. Création de l'élément flèche
// Si ouvert par défaut : flèche HAUT (▲), sinon flèche BAS (▼)
var initialArrow = isOpenByDefault ? ' ▲' : ' ▼';
var $toggle = $('<span>')
.addClass('sidebar-toggle-arrow')
.text(initialArrow)
.css({
'float': 'right',
'cursor': 'pointer',
'font-size': '0.8em',
'color': '#72777d',
'user-select': 'none'
});
$heading.append($toggle);
// 3. Gestion de l'affichage initial du contenu
if (isOpenByDefault) {
$body.show();
} else {
$body.hide();
}
// 4. Gestion du clic
$heading.on('click', function(e) {
// Empêche l'action si on clique sur un lien éventuel dans le h3
if ($(e.target).is('a')) return;
var $icon = $(this).find('.sidebar-toggle-arrow');
if ($body.is(':visible')) {
// On ferme : slideUp + flèche vers le BAS (▼)
$body.slideUp(200);
$icon.text(' ▼');
} else {
// On ouvre : slideDown + flèche vers le HAUT (▲)
$body.slideDown(200);
$icon.text(' ▲');
}
});
}
});
});
mw.hook('wikipage.content').add(function($content) {
var $toc = $content.find('#toc');
// On vérifie que le sommaire existe et qu'on est sur un écran large
if ($toc.length && window.innerWidth > 850) {
var $targetCol = $('#mw-related-navigation');
if ($targetCol.length) {
// CORRECTION 1 : On supprime UNIQUEMENT la toolbox, pas tout le contenu
// Cela garde la structure HTML interne nécessaire au calcul de hauteur
$targetCol.find('#page-tools').remove();
// CORRECTION 2 : On insère le TOC tout en haut sans vider le reste
$targetCol.prepend($toc);
// Reset des styles inline pour éviter les conflits
$toc.css({
'float': 'none',
'margin': '0',
'width': '100%',
'background': 'transparent',
'border': 'none'
});
}
}
});
mw.hook('wikipage.content').add(function($content) {
// 1. Cibler le sommaire
var $toc = $content.find('#toc');
// 2. VÉRIFICATION CRUCIALE :
// On vérifie que le sommaire existe ET qu'il contient une liste <ul> non vide
// Cela évite d'afficher la barre si la page est trop courte pour avoir un sommaire
if ($toc.length && $toc.find('ul').length > 0 && window.innerWidth > 850) {
var $targetCol = $('#mw-related-navigation');
if ($targetCol.length) {
// Supprime uniquement la toolbox existante
$targetCol.find('#page-tools').remove();
// Insère le TOC tout en haut
$targetCol.prepend($toc);
// Ajuste le style pour qu'il s'intègre bien dans la colonne latérale
$toc.css({
'float': 'none',
'margin': '0',
'width': '100%',
'background': 'transparent',
'border': 'none',
'display': 'block' // Force l'affichage car il est parfois inline ou none par défaut
});
// Optionnel : Si la colonne est maintenant vide de tout autre contenu non désiré,
// vous pouvez aussi vérifier si $targetCol ne contient QUE le toc pour la masquer,
// mais généralement, Timeless y met d'autres choses (liens de langue, etc.).
}
} else {
// 3. CAS SANS SOMMAIRE :
// Si pas de sommaire valide, on s'assure que la colonne liée ne montre pas de vide étrange
// ou on peut masquer spécifiquement la section si elle ne contient que ça.
// Dans votre cas, si le script précédent a échoué à remplir, la barre par défaut (toolbox)
// risque d'apparaître si elle n'a pas été supprimée par un autre processus.
// Pour être sûr, on peut forcer le masquage de la colonne si elle est vide de contenu utile :
var $targetCol = $('#mw-related-navigation');
// Si la colonne existe mais ne contient ni toc, ni autres éléments utiles (à adapter selon vos autres gadgets)
if ($targetCol.length && $targetCol.find('#toc').length === 0) {
// Décommentez la ligne suivante si vous voulez masquer toute la colonne droite quand il n'y a pas de sommaire
// $targetCol.hide();
// Ou simplement s'assurer que la toolbox (si elle a été réinjectée ailleurs) est retirée :
$targetCol.find('#page-tools').remove();
}
}
});
// Partie pour ajouter le lien "Haut de page" (inchangée, mais protégée par la présence de l'UL)
mw.hook('wikipage.content').add(function($content) {
var toc = document.getElementById('toc');
if (toc) {
var ul = toc.querySelector('ul');
// On vérifie encore une fois que ul existe avant d'insérer
if (ul) {
var li = document.createElement('li');
li.innerHTML = '<a href="#top">Haut de page</a>';
ul.insertBefore(li, ul.firstChild);
}
}
});
mw.loader.using(['mediawiki.util', 'jquery'], function() {
// ============================================================
// FONCTION 1 : GÉNÉRER LE TABLEAU
// ============================================================
function genererTableauGC() {
var $listContainer = $('.gc-page-list');
if ($listContainer.length === 0) return;
// Si c'est déjà un tableau, on ne fait rien
if ($listContainer.find('table.wikitable').length > 0) return;
var $links = $listContainer.find('a');
var pageTitles = [];
var linkMap = {};
$links.each(function() {
var title = $(this).attr('title');
if (title && title.indexOf(':') === -1) {
pageTitles.push(title);
linkMap[title] = $(this);
}
});
if (pageTitles.length === 0) {
$listContainer.html('<p style="font-style:italic; color:#666; padding:10px;">Aucune Grande Campagne ne correspond à ces critères.</p>');
return;
}
new mw.Api().get({
action: 'query',
prop: 'categories',
titles: pageTitles.join('|'),
cllimit: 'max'
}).done(function(data) {
if (!data.query || !data.query.pages) return;
var pages = data.query.pages;
var tableHtml = '<table class="wikitable" style="min-width:60%; text-align:center; margin:0;">';
tableHtml += '<thead><tr><th>Nom</th><th>Date</th><th>Rang</th><th>Gouvernement</th><th>Statut</th></tr></thead><tbody>';
$.each(pages, function(pageId, pageData) {
if (pageId === "-1") return;
var title = pageData.title;
var rowData = { nom: '', date: '-', rang: '-', gouvernement: '-', statut: '-' };
var $link = linkMap[title];
if ($link && $link.length) {
var href = $link.attr('href');
rowData.nom = '<a href="' + href + '">' + title + '</a>';
} else {
rowData.nom = '<a href="/index.php?title=' + encodeURIComponent(title) + '">' + title + '</a>';
}
if (pageData.categories) {
$.each(pageData.categories, function(i, cat) {
var rawName = cat.title;
var catName = rawName.replace(/^Category:/i, '').replace(/^Catégorie:/i, '').trim();
if (catName === 'GC') return;
var subCat = '';
if (catName.indexOf('GC ') !== -1) subCat = catName.split('GC ').pop();
else if (catName.indexOf('GC_') !== -1) subCat = catName.split('GC_').pop();
else return;
subCat = subCat.trim();
if (!subCat) return;
var key = subCat.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
if (/^\d+$/.test(subCat)) rowData.date = subCat;
else if (['comte', 'duc', 'roi', 'empereur', 'aventurier'].includes(key)) rowData.rang = subCat;
else if (['tribal', 'feodal', 'clanique', 'administratif', 'nomade'].includes(key)) rowData.gouvernement = subCat;
else if (['independant', 'vassal'].includes(key)) rowData.statut = subCat;
});
}
tableHtml += '<tr><td style="text-align:left; padding-left:0.5em;">' + rowData.nom + '</td><td>' + rowData.date + '</td><td>' + rowData.rang + '</td><td>' + rowData.gouvernement + '</td><td>' + rowData.statut + '</td></tr>';
});
tableHtml += '</tbody></table>';
$listContainer.html(tableHtml);
// RÉAFFICHER le conteneur une fois fini
$listContainer.css('visibility', 'visible');
}).fail(function() {
$listContainer.css('visibility', 'visible');
$listContainer.html('<p style="color:red;">Erreur de chargement.</p>');
});
}
// ============================================================
// FONCTION 2 : FILTRAGE (Avec masquage intelligent)
// ============================================================
function initFiltres() {
if (mw.config.get('wgPageName') !== 'Grandes_Campagnes') return;
function filtrer() {
var r = document.querySelector('input[name="rang"].filtre-radio:checked');
var s = document.querySelector('input[name="statut"].filtre-radio:checked');
var d = document.querySelector('input[name="date"].filtre-radio:checked');
var g = document.querySelector('input[name="gouvernement"].filtre-radio:checked');
if (!r || !s || !d || !g) return;
var vR = r.value, vS = s.value, vD = d.value, vG = g.value;
var div = document.getElementById('resultat-dpl');
if (!div) return;
var $listContainer = $(div).find('.gc-page-list');
// 1. MASQUER immédiatement le contenu actuel (liste ou tableau)
// On utilise visibility:hidden pour garder l'espace et éviter un saut de page
if ($listContainer.length) {
$listContainer.css('visibility', 'hidden');
} else {
// Si la div est vide (premier chargement), on met un placeholder invisible
div.innerHTML = '<div class="gc-page-list" style="visibility:hidden;"></div>';
}
var api = new mw.Api();
api.post({
action: 'parse',
format: 'json',
text: '{{Resultat_Recherche_GC|rang=' + vR + '|statut=' + vS + '|date=' + vD + '|gouvernement=' + vG + '}}',
contentmodel: 'wikitext',
disableeditsection: true,
disabletoc: true
}).done(function(data) {
if (data.parse && data.parse.text) {
div.innerHTML = data.parse.text['*'];
// 2. Lancer la conversion en tableau (qui réaffichera à la fin)
genererTableauGC();
var url = new URL(window.location);
if (vR === '') url.searchParams.delete('rang'); else url.searchParams.set('rang', vR);
if (vS === '') url.searchParams.delete('statut'); else url.searchParams.set('statut', vS);
if (vD === '') url.searchParams.delete('date'); else url.searchParams.set('date', vD);
if (vG === '') url.searchParams.delete('gouvernement'); else url.searchParams.set('gouvernement', vG);
window.history.pushState({}, '', url);
}
}).fail(function() {
$listContainer.css('visibility', 'visible');
div.innerHTML = '<p style="color:red;">Erreur.</p>';
});
}
var radios = document.querySelectorAll('input.filtre-radio');
if (radios.length > 0) {
radios.forEach(function(rad) {
rad.addEventListener('change', filtrer);
});
}
}
// ============================================================
// FONCTION : SYNCHRONISER LES BOUTONS AVEC L'URL
// ============================================================
function synchroniserBoutonsAvecURL() {
var urlParams = new URLSearchParams(window.location.search);
// Pour chaque type de filtre (date, gouvernement, rang, statut)
['date', 'gouvernement', 'rang', 'statut'].forEach(function(groupe) {
var valeur = urlParams.get(groupe);
if (valeur) {
// Cherche le bouton radio correspondant et le coche
var radio = document.querySelector('input[name="' + groupe + '"].filtre-radio[value="' + valeur + '"]');
if (radio) {
radio.checked = true;
}
} else {
// Si pas de paramètre, coche "Tous" (value="")
var radioTous = document.querySelector('input[name="' + groupe + '"].filtre-radio[value=""]');
if (radioTous) {
radioTous.checked = true;
}
}
});
}
// ============================================================
// INITIALISATION
// ============================================================
$(function() {
if (mw.config.get('wgPageName') === 'Grandes_Campagnes') {
// 1. D'abord, on synchronise les boutons avec l'URL (ex: ?date=867)
synchroniserBoutonsAvecURL();
// 2. Ensuite, on génère le tableau et on active les écouteurs
setTimeout(function() {
genererTableauGC();
initFiltres();
}, 100);
}
});
});
/* Script personnalisé pour permettre le toggle de lignes de tableau (tr) */
$(document).ready(function() {
var pagesAutorisees = ['Liste_des_cultures']; // Ajoutez vos pages ici
if (pagesAutorisees.indexOf(mw.config.get('wgPageName')) !== -1) {
// Gestion du clic sur les boutons de date
$('.date-btn').on('click', function(e) {
e.preventDefault();
var $btn = $(this);
var selectedYear = $btn.data('year'); // Récupère l'année (ex: "867")
var $row = $btn.closest('tr'); // Trouve la ligne du tableau
// 1. Mettre à jour le style des boutons (optionnel : mettre en gras celui sélectionné)
$row.find('.date-btn').css('font-weight', 'normal').css('text-decoration', 'none');
$btn.css('font-weight', 'bold').css('text-decoration', 'underline');
// 2. Cacher tous les contenus de cette ligne
$row.find('.year-content').hide();
// 3. Afficher uniquement le contenu correspondant à l'année cliquée
$row.find('.content-' + selectedYear).show();
});
}
});
(function() {
'use strict';
function initTOCHighlight() {
var toc = document.getElementById('toc');
if (!toc) return;
var links = toc.querySelectorAll('a[href^="#"]');
if (!links.length) return;
// Collecter les cibles (headings avec id)
var targets = [];
links.forEach(function(link) {
var id = decodeURIComponent(link.getAttribute('href').replace('#', ''));
var el = document.getElementById(id);
if (el) targets.push(el);
});
if (!targets.length) return;
var current = null;
function update() {
var scrollPos = window.scrollY + 100; // 100px de marge
var active = targets[0];
for (var i = 0; i < targets.length; i++) {
if (targets[i].offsetTop <= scrollPos) {
active = targets[i];
} else {
break;
}
}
if (active !== current) {
// Retirer la classe de tous
links.forEach(function(link) {
link.parentElement.classList.remove('toc-current');
});
// Ajouter à l'actif
var id = active.id;
var activeLink = toc.querySelector('a[href="#' + encodeURIComponent(id) + '"]');
if (!activeLink) {
// Fallback : chercher par id décodé
links.forEach(function(link) {
var href = decodeURIComponent(link.getAttribute('href').replace('#', ''));
if (href === id) activeLink = link;
});
}
if (activeLink) {
activeLink.parentElement.classList.add('toc-current');
}
current = active;
}
}
// Throttle pour performance
var ticking = false;
window.addEventListener('scroll', function() {
if (!ticking) {
requestAnimationFrame(function() {
update();
ticking = false;
});
ticking = true;
}
});
update(); // Appel initial
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initTOCHighlight);
} else {
initTOCHighlight();
}
})();
