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();
  }
})();