Diferencia entre revisiones de «MediaWiki:Common.js»
Apariencia
Sin resumen de edición |
Sin resumen de edición |
||
| (No se muestran 4 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]; | ||
} | } | ||
| Línea 183: | Línea 188: | ||
var escapedTerm = term.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); | var escapedTerm = term.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); | ||
//usa una expresion regular que buscar un matcheo parcial, es decir el termino buscado | //usa una expresion regular que buscar un matcheo parcial, es decir el termino buscado | ||
//puede estar contenido en una palabra con diferente significado | //puede estar contenido en una palabra con diferente significado | ||
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();
}
})();