Diferencia entre revisiones de «MediaWiki:Common.js»
Apariencia
Sin resumen de edición |
Sin resumen de edición |
||
(No se muestran 3 ediciones intermedias del mismo usuario) | |||
Línea 26: | Línea 26: | ||
function getSearchTerms() { | function getSearchTerms() { | ||
// Intenta obtener términos del parámetro highlight (usado por MediaWiki) | // Intenta obtener términos del parámetro highlight (usado por MediaWiki) | ||
var urlParams = new URLSearchParams(window.location.search); | var urlParams = new URLSearchParams(window.location.search); | ||
var highlight = urlParams.get('highlight'); | var highlight = urlParams.get('highlight'); | ||
Línea 31: | Línea 32: | ||
return [highlight]; | return [highlight]; | ||
} | } | ||
// Si no hay highlight, intenta obtener del referrer | // Si no hay highlight, intenta obtener del referrer | ||
var referrer = document.referrer; | var referrer = document.referrer; | ||
if (!referrer) return []; | if (!referrer) return []; | ||
var referrerUrl = new URL(referrer); | var referrerUrl = new URL(referrer); | ||
var search = referrerUrl.searchParams.get('search') || | var search = referrerUrl.searchParams.get('search') || | ||
referrerUrl.searchParams.get('query'); | referrerUrl.searchParams.get('query'); | ||
if (!search) return []; | if (!search) return []; | ||
// Limpia espacios extras y trata toda la búsqueda como un solo término | // Limpia espacios extras y trata toda la búsqueda como un solo término | ||
search = search.trim(); | search = search.trim(); | ||
return [search]; | return [search]; | ||
} | } |
Revisión actual - 16:22 31 mar 2025
/* Cualquier código JavaScript escrito aquí se cargará para todos los usuarios en cada carga de página */ // Este script resalta y permite navegar entre términos de búsqueda en el artículo destino (function() { // Variables globales para el seguimiento de la navegación var currentHighlightIndex = -1; // Índice del resaltado actual var highlightElements = []; // Array de todos los elementos resaltados /** * Verifica si llegamos desde una búsqueda * @returns {boolean} true si venimos de una búsqueda */ function isComingFromSearch() { var referrer = document.referrer; return referrer.includes('Special:Search') || referrer.includes('title=Special:Search') || referrer.includes('search=') || referrer.includes('Special:Buscar') || document.location.search.includes('highlight='); } /** * Obtiene los términos de búsqueda del referrer o parámetros de URL * @returns {Array} Array de términos de búsqueda */ function getSearchTerms() { // Intenta obtener términos del parámetro highlight (usado por MediaWiki) var urlParams = new URLSearchParams(window.location.search); var highlight = urlParams.get('highlight'); if (highlight) { return [highlight]; } // Si no hay highlight, intenta obtener del referrer var referrer = document.referrer; if (!referrer) return []; var referrerUrl = new URL(referrer); var search = referrerUrl.searchParams.get('search') || referrerUrl.searchParams.get('query'); if (!search) return []; // Limpia espacios extras y trata toda la búsqueda como un solo término search = search.trim(); return [search]; } /** * Crea y agrega los controles de navegación en la página */ function createNavigationControls() { var nav = document.createElement('div'); nav.className = 'search-navigation'; nav.innerHTML = [ '<div class="search-nav-controls">', '<button id="prevMatch">↑ Anterior</button>', '<span id="matchCounter">0 de 0</span>', '<button id="nextMatch">↓ Siguiente</button>', '</div>' ].join(''); document.body.appendChild(nav); // Estilos CSS para los controles de navegación var style = document.createElement('style'); style.textContent = [ '.search-navigation {', 'position: fixed;', 'bottom: 20px;', 'right: 20px;', 'z-index: 1000;', '}', '.search-nav-controls {', 'background: white;', 'padding: 10px;', 'border-radius: 8px;', 'box-shadow: 0 2px 10px rgba(0,0,0,0.1);', 'display: flex;', 'gap: 10px;', 'align-items: center;', '}', '.search-nav-controls button {', 'padding: 5px 10px;', 'border: 1px solid #ccc;', 'border-radius: 4px;', 'background: #f0f0f0;', 'cursor: pointer;', '}', '.search-nav-controls button:hover {', 'background: #e0e0e0;', '}', '.searchmatch {', 'background-color: #ffeb3b;', 'padding: 2px;', 'border-radius: 2px;', '}', '.searchmatch.current {', 'background-color: #ffa000;', 'color: white;', '}' ].join('\n'); document.head.appendChild(style); // Agregar listeners para los botones de navegación document.getElementById('prevMatch').addEventListener('click', navigateToPrevious); document.getElementById('nextMatch').addEventListener('click', navigateToNext); } /** * Actualiza el contador de coincidencias */ function updateMatchCounter() { var counter = document.getElementById('matchCounter'); if (counter && highlightElements.length > 0) { counter.textContent = (currentHighlightIndex + 1) + ' de ' + highlightElements.length; } } /** * Navega a una coincidencia específica * @param {number} index - Índice de la coincidencia */ function navigateToMatch(index) { if (highlightElements.length === 0) return; // Quita el resaltado especial del elemento actual if (currentHighlightIndex >= 0) { highlightElements[currentHighlightIndex].classList.remove('current'); } // Maneja el ciclo de navegación currentHighlightIndex = index; if (currentHighlightIndex >= highlightElements.length) { currentHighlightIndex = 0; } if (currentHighlightIndex < 0) { currentHighlightIndex = highlightElements.length - 1; } // Resalta y hace scroll al elemento actual var element = highlightElements[currentHighlightIndex]; element.classList.add('current'); element.scrollIntoView({ behavior: 'smooth', block: 'center' }); updateMatchCounter(); } /** * Navega a la siguiente coincidencia */ function navigateToNext() { navigateToMatch(currentHighlightIndex + 1); } /** * Navega a la coincidencia anterior */ function navigateToPrevious() { navigateToMatch(currentHighlightIndex - 1); } /** * Resalta los términos de búsqueda en el contenido del artículo */ function highlightSearchTerms() { // Solo procede si venimos de una búsqueda if (!isComingFromSearch()) return; var terms = getSearchTerms(); if (!terms.length) return; var content = document.getElementById('mw-content-text'); if (!content) return; terms.forEach(function(term) { // Ignora términos muy cortos if (term.length < 3) return; // Escapa caracteres especiales en el término de búsqueda var escapedTerm = term.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); //usa una expresion regular que buscar un matcheo parcial, es decir el termino buscado //puede estar contenido en una palabra con diferente significado var regex = new RegExp('\\b(' + escapedTerm + '\\w*)', 'gi'); // Crea un TreeWalker para recorrer todos los nodos de texto var walker = document.createTreeWalker( content, NodeFilter.SHOW_TEXT, null, false ); // Recolecta todos los nodos de texto var node; var nodes = []; while (node = walker.nextNode()) { nodes.push(node); } // Procesa cada nodo de texto nodes.forEach(function(node) { if (node.parentNode.nodeName !== 'SCRIPT' && node.parentNode.nodeName !== 'STYLE' && !node.parentNode.classList.contains('searchmatch')) { var text = node.textContent; if (regex.test(text)) { var span = document.createElement('span'); span.innerHTML = text.replace(regex, '<span class="searchmatch">$1</span>'); node.parentNode.replaceChild(span, node); } } }); }); // Recolecta todas las coincidencias resaltadas highlightElements = Array.from(document.getElementsByClassName('searchmatch')); // Si hay coincidencias, crea los controles y navega al primer resultado if (highlightElements.length > 0) { createNavigationControls(); navigateToMatch(0); } } // Agrega soporte para navegación con teclas document.addEventListener('keydown', function(e) { if (e.key === 'F3' || (e.ctrlKey && e.key === 'g')) { e.preventDefault(); navigateToNext(); } else if (e.shiftKey && e.key === 'F3' || (e.ctrlKey && e.shiftKey && e.key === 'g')) { e.preventDefault(); navigateToPrevious(); } }); // Inicia el script cuando la página esté lista if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', highlightSearchTerms); } else { highlightSearchTerms(); } })();