MediaWiki:Gadget-RechercheDeCatégorie.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).
- Internet Explorer / Edge : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl + F5.
- Opera : appuyez sur Ctrl + F5.
function sanitize(word) { return word .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } function normalizeString(str) { return str.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase(); } $(document).ready(function() { // À afficher uniquement sur les pages du namespace "Catégorie" if (mw.config.get('wgNamespaceNumber') === 14) { // Sauvegarde le contenu original de la page var originalCategoryGenerated = $('#mw-category-media').html(); var originalCategoryMedia = $('#mw-category-media').html(); var originalPages = $('#mw-pages').html(); var originalParserOutput = $('.mw-parser-output').html(); var originalCatlinks = $('#catlinks').html(); var originalPageTitle = $('.mw-page-title-main').text(); var originalNamespace = $('.mw-page-title-namespace').text(); var originalSeparator = $('.mw-page-title-separator').text(); // Ajoute une barre de recherche en haut de la page var searchBar = '<div id="categorySearch" style="display: flex; margin-bottom: 5px">' + '<div id="categorySearchBar" class="vector-search-box-inner" data-search-loc="header-navigation">' + '<input class="vector-search-box-input" type="search" name="search" placeholder="Rechercher un média dans la catégorie" aria-label="Rechercher un média dans la catégorie" autocapitalize="sentences" title="Rechercher un média dans la catégorie [alt-shift-g]" accesskey="g" id="categorySearchInput">' + '<input id="mw-searchButton" class="searchButton mw-fallbackSearchButton" type="submit" name="fulltext" title="Rechercher les pages comportant ce texte." value="Rechercher" style="margin-right: 10px;">' + '<input id="searchButton" class="searchButton" type="submit" name="go" title="Rechercher les éléments de la catégorie qui correspondent à votre recherche" value="Lire">' + '</div>' + '<div style="display: flex; align-items: center; margin-left: 10px;" class="vector-body">' + '<input type="checkbox" id="caseSensitive" name="caseSensitive" style="margin-right: 5px;">' + '<label for="caseSensitive">Respecter la casse</label>' + '<div style="margin: 0px 5px">•</div>' + '<input type="checkbox" id="includeSubcategories" name="includeSubcategories" style="margin-right: 5px;">' + '<label for="includeSubcategories">Inclure les sous-catégories</label>' + '<div style="margin: 0px 5px">•</div>' + '<button id="closeCategorySearch" title="Annuler la recherche" style="background-color: #FAFBFC; border: 1px solid rgba(27, 31, 35, 0.3); border-radius: 6px; cursor: pointer; line-height: 20px">Annuler la recherche</button>' + '</div>' + '</div>'; // Vérifie si la barre de recherche existe déjà if (!$('#categorySearch').length) { $('#content').prepend(searchBar); } // Fonction de recherche et d'affichage function performSearch() { var searchTerm = $('#categorySearchInput').val(); var isCaseSensitive = $('#caseSensitive').is(':checked'); var includeSubcategories = $('#includeSubcategories').is(':checked'); var normalizedSearchTerm = isCaseSensitive ? searchTerm : normalizeString(searchTerm); var categoryName = mw.config.get('wgPageName').replace('Catégorie:', '').replace(/_/g, ' '); // Changer le titre de la page sans modifier le titre de l'onglet $('.mw-page-title-namespace').hide(); $('.mw-page-title-separator').hide(); $('.mw-page-title-main').text('Recherche dans « Catégorie:' + categoryName + ' »'); // Masquer le contenu original $('#mw-subcategories').hide(); $('#mw-category-media').hide(); $('#mw-pages').hide(); // Fonction pour récupérer les fichiers MediaWiki via l'API function fetchFiles(term, category) { return $.ajax({ url: mw.util.wikiScript('api'), data: { action: 'query', list: 'categorymembers', cmtitle: 'Catégorie:' + category, cmtype: 'file', cmlimit: 'max', cmprop: 'title', format: 'json' }, dataType: 'json' }); } // Fonction pour récupérer les sous-catégories via l'API function fetchSubcategories(category) { return $.ajax({ url: mw.util.wikiScript('api'), data: { action: 'query', list: 'categorymembers', cmtitle: 'Catégorie:' + category, cmtype: 'subcat', cmlimit: 'max', format: 'json' }, dataType: 'json' }); } // Fonction récursive pour récupérer les fichiers de toutes les sous-catégories function fetchAllFiles(category, visitedCategories) { if (visitedCategories[category]) { return $.Deferred().resolve([]).promise(); // Retourne une promesse résolue avec un tableau vide si déjà visité } visitedCategories[category] = true; var allFiles = []; return fetchFiles(normalizedSearchTerm, category).then(function(data) { allFiles = data.query.categorymembers; if (includeSubcategories) { return fetchSubcategories(category).then(function(subcatData) { var subcategories = subcatData.query.categorymembers; var subcatPromises = subcategories.map(function(subcategory) { var subcategoryName = subcategory.title.replace('Catégorie:', ''); return fetchAllFiles(subcategoryName, visitedCategories); }); return $.when.apply($, subcatPromises).then(function() { $.each(arguments, function(i, subFiles) { allFiles = allFiles.concat(subFiles); }); return allFiles; }); }); } else { return allFiles; } }); } // Fonction pour filtrer et afficher les fichiers function displayFiles(files) { var filteredFiles = files.filter(function(file) { var fileTitle = file.title.replace('Fichier:', ''); return isCaseSensitive ? fileTitle.includes(searchTerm) : normalizeString(fileTitle).includes(normalizedSearchTerm); }); // Tri des fichiers par ordre alphabétique du titre filteredFiles.sort(function(a, b) { return a.title.localeCompare(b.title); }); var resultsCount = filteredFiles.length; var resultsText = resultsCount < 2 ? 'résultat' : 'résultats'; var galleryHtml = '<h2 class="search-results-title">Média trouvés avec la recherche « ' + sanitize(searchTerm) + ' »</h2>' + '<p class="search-results-count">La recherche a donné ' + resultsCount + ' ' + resultsText + '.</p>' + '<div id="mw-category-media-search">' + '<div class="gallery mw-gallery-traditional" style="display: flex; flex-wrap: wrap; gap: 5px;">'; filteredFiles.forEach(function(file) { var fileName = file.title.toLowerCase(); var isMP4 = fileName.endsWith('.mp4'); var isOGG = fileName.endsWith('.ogg'); var fileUrl = mw.util.getUrl('Special:FilePath/' + file.title.replace('Fichier:', '')); var thumbHtml = ''; if (isMP4) { // Générer une vignette pour les fichiers MP4 thumbHtml = '<video width="150" height="150" controls>' + '<source src="' + fileUrl + '" type="video/mp4">' + 'Your browser does not support the video tag.' + '</video>'; } else if (isOGG) { // Générer une vignette pour les fichiers OGG thumbHtml = '<audio controls style="width: 150px;">' + '<source src="' + fileUrl + '" type="audio/ogg">' + 'Your browser does not support the audio element.' + '</audio>'; } else { thumbHtml = '<img src="' + fileUrl + '" alt="' + file.title + '" style="max-width: 100%; max-height: 100%; object-fit: contain; object-position: center;">'; } galleryHtml += '<div class="gallerybox" style="margin: 5px; width: 160px;">' + '<div class="thumb" style="width: 150px; height: 150px; overflow: hidden; border: 1px solid #ccc; background: #f7f7f7; display: flex; align-items: center; justify-content: center; padding: 5px;">' + '<a href="' + mw.util.getUrl(file.title) + '" class="image" style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">' + thumbHtml + '</a></div>' + '<div class="gallerytext" style="text-align: center; margin-top: 5px;">' + '<p class="galleryfilename" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0;">' + '<a href="' + mw.util.getUrl(file.title) + '">' + file.title.replace('Fichier:', '') + '</a></p>' + '</div></div>'; }); galleryHtml += '</div></div>'; $('#mw-category-media').before(galleryHtml); // Insère la galerie avant mw-category-media } // Efface les résultats précédents $('#mw-category-media-search').remove(); $('.search-results-title').remove(); // Supprime les titres précédents $('.search-results-count').remove(); // Supprime les compteurs précédents // Recherche les fichiers et les affiche fetchAllFiles(categoryName, {}).done(function(files) { displayFiles(files); }).fail(function() { alert('Une erreur est survenue lors de la recherche des fichiers.'); }); } // Ajoute un événement pour le bouton de recherche $('#searchButton').off('click').on('click', performSearch); $('#mw-searchButton').off('click').on('click', performSearch); // Ajoute un événement pour la touche Entrée dans la barre de recherche $('#categorySearchInput').off('keypress').on('keypress', function(event) { if (event.which === 13) { performSearch(); } }); // Ajoute un événement pour le bouton de fermeture $('#closeCategorySearch').off('click').on('click', function() { $('.mw-parser-output').html(originalParserOutput).show(); // Restaure le contenu original et l'affiche $('#mw-category-media').html(originalCategoryMedia).show(); $('#mw-pages').html(originalPages).show(); $('#mw-subcategories').show(); // Restaure le contenu original et l'affiche $('#catlinks').html(originalCatlinks).show(); // Restaure le contenu original et l'affiche $('.mw-page-title-main').text(originalPageTitle); // Restaure le titre principal original $('.mw-page-title-namespace').text(originalNamespace).show(); $('.mw-page-title-separator').text(originalSeparator).show(); $('#mw-category-media-search').remove(); // Supprime les résultats de recherche $('.search-results-title').remove(); // Supprime les titres de résultats de recherche $('.search-results-count').remove(); // Supprime les compteurs de résultats de recherche }); } });