Mudanças entre as edições de "Widget:Droflax"
Ir para navegação
Ir para pesquisar
| Linha 1: | Linha 1: | ||
(function() { | (function() { | ||
const | 'use strict'; | ||
if (! | |||
// Buscar todos los contenedores de personaje | |||
const personajeBoxes = document.querySelectorAll('.personaje-box'); | |||
personajeBoxes.forEach(initPersonaje); | |||
function initPersonaje(personajeBox) { | |||
// Obtener el nombre del personaje del ID | |||
const personajeId = personajeBox.id; | |||
if (!personajeId) return; | |||
const nome = personajeId.replace('personaje-', ''); | |||
const dataScript = document.getElementById(`personaje-data-${nome}`); | |||
if (!dataScript) { | |||
console.error(`No se encontraron datos para el personaje: ${nome}`); | |||
return; | |||
} | |||
let data; | |||
try { | |||
data = JSON.parse(dataScript.textContent); | |||
} catch (e) { | |||
console.error('Error al parsear datos del personaje:', e); | |||
return; | |||
} | |||
// Inicializar tabs | |||
initTabs(personajeBox); | |||
// Inicializar habilidades | |||
initHabilidades(personajeBox, data.habilidades); | |||
// Inicializar skins carousel | |||
initSkinsCarousel(personajeBox); | |||
// Remover el script de datos | |||
dataScript.remove(); | |||
} | |||
function initTabs(container) { | |||
const buttons = container.querySelectorAll('.tab-btn'); | |||
const contents = container.querySelectorAll('.tab-content'); | |||
buttons.forEach(btn => { | |||
btn.addEventListener('click', () => { | |||
buttons.forEach(b => b.classList.remove('active')); | |||
contents.forEach(c => c.classList.remove('active')); | |||
btn.classList.add('active'); | |||
const tabId = btn.dataset.tab; | |||
const targetContent = container.querySelector(`#${tabId}`); | |||
if (targetContent) { | |||
targetContent.classList.add('active'); | |||
} | |||
}); | |||
}); | }); | ||
} | } | ||
const | function initHabilidades(container, habilidades) { | ||
const cuadrosContainer = container.querySelector('.cuadros-container'); | |||
const descripcionContainer = container.querySelector('.descripcion-container'); | |||
const videoContainer = container.querySelector('.video-container'); | |||
if (!cuadrosContainer || !descripcionContainer || !videoContainer) return; | |||
const cuadros = cuadrosContainer.querySelectorAll('.cuadro'); | |||
cuadros.forEach((cuadro, index) => { | |||
cuadro.addEventListener('click', () => { | |||
const hab = habilidades[index]; | |||
if (!hab) return; | |||
// Formatear descripción | |||
const descripcionFormateada = hab.desc.replace(/'''(.*?)'''/g, '<b>$1</b>'); | |||
// Generar HTML de la descripción | |||
descripcionContainer.innerHTML = ` | |||
<div class="titulo-habilidad"> | |||
<h3>${hab.nome}</h3> | |||
<div class="tooltip-container"> | |||
<button class="info-btn">i</button> | |||
<span class="tooltip-text"> | |||
Información adicional sobre la habilidad, consejos o efectos especiales. | |||
</span> | |||
</div> | |||
</div> | |||
${generarHTMLAtributos(hab.atr)} | |||
<div class="desc">${descripcionFormateada}</div> | |||
`; | |||
// Mostrar video si existe | |||
videoContainer.innerHTML = hab.video ? ` | |||
<video width="100%" controls playsinline> | |||
<source src="${hab.video}" type="video/webm"> | |||
Tu navegador no soporta el elemento video. | |||
</video> | |||
` : ''; | |||
// Actualizar estado activo | |||
cuadros.forEach(c => c.classList.remove('activo')); | |||
cuadro.classList.add('activo'); | |||
}); | |||
}); | |||
// Scroll horizontal con rueda del mouse | |||
cuadrosContainer.addEventListener('wheel', e => { | |||
if (e.deltaY) { | |||
e.preventDefault(); | |||
cuadrosContainer.scrollLeft += e.deltaY; | |||
} | |||
}); | }); | ||
// Activar primera habilidad por defecto | |||
if (cuadros.length > 0) { | |||
cuadros[0].click(); | |||
} | |||
} | } | ||
function generarHTMLAtributos(atributos) { | |||
if (!atributos) return ''; | |||
const vals = atributos.split(',').map(v => v.trim()); | |||
const labels = ['Poder PVE', 'Poder PVP', 'Energía', 'Recarga']; | |||
const icons = [ | |||
'/images/7/7a/Icon-pve.png', | |||
'/images/5/5f/Icon-pvp.png', | |||
'/images/3/38/Icon-energy.png', | |||
'/images/b/b1/Icon-cooldown.png' | |||
]; | |||
return ` | |||
<div class="attribute--cardsContainer"> | |||
${vals.map((v, i) => { | |||
let valor = v === '-' ? '-' : parseInt(v); | |||
if (i === 1 && !isNaN(valor)) { | |||
valor = (valor > 0 ? '+' : '') + valor; | |||
} | |||
return ` | |||
<span class="simple-tooltip simple-tooltip-inline" data-tooltip="${labels[i]}"> | |||
<div class="cardAttribute"> | |||
<img src="${icons[i]}" class="cardAttribute--icon"> | |||
<h2 class="cardAttribute--value">${valor}${i === 0 && valor !== '-' ? ' seg' : ''}</h2> | |||
</div> | |||
</span> | |||
`; | |||
}).join('')} | |||
</div> | </div> | ||
`; | |||
} | |||
function initSkinsCarousel(container) { | |||
const carousel = container.querySelector('.skins-carousel'); | |||
const wrapper = container.querySelector('.skins-carousel-wrapper'); | |||
const leftBtn = container.querySelector('.skins-arrow.left'); | |||
const rightBtn = container.querySelector('.skins-arrow.right'); | |||
const | |||
if (!carousel || !wrapper || !leftBtn || !rightBtn) return; | |||
let isPredictingScroll = false; | |||
const getScrollAmount = () => carousel.clientWidth * 0.6; | const getScrollAmount = () => carousel.clientWidth * 0.6; | ||
const hideArrow = btn => { | const hideArrow = btn => { | ||
if (!btn.classList.contains('desapareciendo') && btn.style.display !== 'none') { | if (!btn.classList.contains('desapareciendo') && btn.style.display !== 'none') { | ||
| Linha 162: | Linha 173: | ||
} | } | ||
}; | }; | ||
const showArrow = btn => { | const showArrow = btn => { | ||
if (btn.style.display === 'none') { | if (btn.style.display === 'none') { | ||
btn.style.display = 'inline-block'; | btn.style.display = 'inline-block'; | ||
void btn.offsetWidth; | void btn.offsetWidth; // Force reflow | ||
} | } | ||
btn.classList.remove('desapareciendo'); | btn.classList.remove('desapareciendo'); | ||
}; | }; | ||
const setArrowsState = scrollLeft => { | const setArrowsState = scrollLeft => { | ||
const maxScroll = carousel.scrollWidth - carousel.clientWidth; | const maxScroll = carousel.scrollWidth - carousel.clientWidth; | ||
const hasLeft = scrollLeft > 5 | const hasLeft = scrollLeft > 5; | ||
hasLeft | const hasRight = scrollLeft < maxScroll - 5; | ||
hasRight | |||
if (hasLeft) showArrow(leftBtn); | |||
else hideArrow(leftBtn); | |||
if (hasRight) showArrow(rightBtn); | |||
else hideArrow(rightBtn); | |||
wrapper.classList.toggle('has-left', hasLeft); | wrapper.classList.toggle('has-left', hasLeft); | ||
wrapper.classList.toggle('has-right', hasRight); | wrapper.classList.toggle('has-right', hasRight); | ||
}; | }; | ||
const handleArrowClick = | const handleArrowClick = direction => { | ||
isPredictingScroll = true; | isPredictingScroll = true; | ||
const scrollLeft = carousel.scrollLeft | const scrollLeft = carousel.scrollLeft; | ||
const nextScroll = | const maxScroll = carousel.scrollWidth - carousel.clientWidth; | ||
const nextScroll = direction === 'left' | |||
? Math.max(0, scrollLeft - getScrollAmount()) | |||
: Math.min(maxScroll, scrollLeft + getScrollAmount()); | |||
setArrowsState(nextScroll); | setArrowsState(nextScroll); | ||
carousel.scrollTo({ left: nextScroll, behavior: 'smooth' }); | carousel.scrollTo({ left: nextScroll, behavior: 'smooth' }); | ||
let | // Esperar a que termine el scroll | ||
const | let lastPosition = -1; | ||
const | let stillCount = 0; | ||
if ( | const checkScroll = setInterval(() => { | ||
if (++ | const currentPosition = Math.round(carousel.scrollLeft); | ||
clearInterval( | if (currentPosition === lastPosition) { | ||
if (++stillCount >= 2) { | |||
clearInterval(checkScroll); | |||
isPredictingScroll = false; | isPredictingScroll = false; | ||
setArrowsState( | setArrowsState(currentPosition); | ||
} | } | ||
} else { | } else { | ||
lastPosition = currentPosition; | |||
stillCount = 0; | |||
} | } | ||
}, 50); | }, 50); | ||
}; | }; | ||
// Event listeners | |||
carousel.addEventListener('scroll', () => { | carousel.addEventListener('scroll', () => { | ||
if (!isPredictingScroll) setArrowsState(carousel.scrollLeft); | if (!isPredictingScroll) { | ||
setArrowsState(carousel.scrollLeft); | |||
} | |||
}); | }); | ||
new ResizeObserver(() => { | // Resize observer para recalcular cuando cambie el tamaño | ||
if (window.ResizeObserver) { | |||
new ResizeObserver(() => { | |||
if (!isPredictingScroll) { | |||
setArrowsState(carousel.scrollLeft); | |||
} | |||
}).observe(carousel); | |||
} | |||
leftBtn.addEventListener('click', () => handleArrowClick('left')); | leftBtn.addEventListener('click', () => handleArrowClick('left')); | ||
rightBtn.addEventListener('click', () => handleArrowClick('right')); | rightBtn.addEventListener('click', () => handleArrowClick('right')); | ||
// Estado inicial | |||
setArrowsState(carousel.scrollLeft); | setArrowsState(carousel.scrollLeft); | ||
} | } | ||
// Inicializar tooltips simples | |||
function | function initSimpleTooltips() { | ||
const | const tooltipElements = document.querySelectorAll('[data-tooltip]'); | ||
tooltipElements.forEach(element => { | |||
element.addEventListener('mouseenter', (e) => { | |||
const tooltip = document.createElement('div'); | |||
tooltip.className = 'simple-tooltip-popup'; | |||
tooltip.innerHTML = e.target.dataset.tooltip; | |||
document.body.appendChild(tooltip); | |||
const rect = e.target.getBoundingClientRect(); | |||
tooltip.style.position = 'absolute'; | |||
tooltip.style.left = rect.left + (rect.width / 2) - (tooltip.offsetWidth / 2) + 'px'; | |||
tooltip.style.top = rect.top - tooltip.offsetHeight - 8 + 'px'; | |||
tooltip.style.zIndex = '9999'; | |||
tooltip.style.background = '#222'; | |||
tooltip.style.color = '#fff'; | |||
tooltip.style.padding = '8px 10px'; | |||
tooltip.style.borderRadius = '4px'; | |||
tooltip.style.fontSize = '12px'; | |||
tooltip.style.whiteSpace = 'nowrap'; | |||
tooltip.style.boxShadow = '0 2px 10px rgba(0,0,0,0.5)'; | |||
tooltip.style.pointerEvents = 'none'; | |||
}); | |||
element.addEventListener('mouseleave', () => { | |||
const tooltips = document.querySelectorAll('.simple-tooltip-popup'); | |||
tooltips.forEach(tooltip => tooltip.remove()); | |||
}); | |||
}); | |||
} | } | ||
// Inicializar tooltips después de que se cargue el contenido | |||
setTimeout(initSimpleTooltips, 100); | |||
})(); | })(); | ||
Edição das 15h46min de 20 de julho de 2025
(function() {
'use strict';
// Buscar todos los contenedores de personaje
const personajeBoxes = document.querySelectorAll('.personaje-box');
personajeBoxes.forEach(initPersonaje);
function initPersonaje(personajeBox) {
// Obtener el nombre del personaje del ID
const personajeId = personajeBox.id;
if (!personajeId) return;
const nome = personajeId.replace('personaje-', );
const dataScript = document.getElementById(`personaje-data-${nome}`);
if (!dataScript) {
console.error(`No se encontraron datos para el personaje: ${nome}`);
return;
}
let data;
try {
data = JSON.parse(dataScript.textContent);
} catch (e) {
console.error('Error al parsear datos del personaje:', e);
return;
}
// Inicializar tabs
initTabs(personajeBox);
// Inicializar habilidades
initHabilidades(personajeBox, data.habilidades);
// Inicializar skins carousel
initSkinsCarousel(personajeBox);
// Remover el script de datos
dataScript.remove();
}
function initTabs(container) {
const buttons = container.querySelectorAll('.tab-btn');
const contents = container.querySelectorAll('.tab-content');
buttons.forEach(btn => {
btn.addEventListener('click', () => {
buttons.forEach(b => b.classList.remove('active'));
contents.forEach(c => c.classList.remove('active'));
btn.classList.add('active');
const tabId = btn.dataset.tab;
const targetContent = container.querySelector(`#${tabId}`);
if (targetContent) {
targetContent.classList.add('active');
}
});
});
}
function initHabilidades(container, habilidades) {
const cuadrosContainer = container.querySelector('.cuadros-container');
const descripcionContainer = container.querySelector('.descripcion-container');
const videoContainer = container.querySelector('.video-container');
if (!cuadrosContainer || !descripcionContainer || !videoContainer) return;
const cuadros = cuadrosContainer.querySelectorAll('.cuadro');
cuadros.forEach((cuadro, index) => {
cuadro.addEventListener('click', () => {
const hab = habilidades[index];
if (!hab) return;
// Formatear descripción
const descripcionFormateada = hab.desc.replace(/(.*?)/g, '$1');
// Generar HTML de la descripción
descripcionContainer.innerHTML = `
${hab.nome}
<button class="info-btn">i</button>
Información adicional sobre la habilidad, consejos o efectos especiales.
${generarHTMLAtributos(hab.atr)}
${descripcionFormateada}
`;
// Mostrar video si existe
videoContainer.innerHTML = hab.video ? `
<video width="100%" controls playsinline>
<source src="${hab.video}" type="video/webm">
Tu navegador no soporta el elemento video.
</video>
` : ;
// Actualizar estado activo
cuadros.forEach(c => c.classList.remove('activo'));
cuadro.classList.add('activo');
});
});
// Scroll horizontal con rueda del mouse
cuadrosContainer.addEventListener('wheel', e => {
if (e.deltaY) {
e.preventDefault();
cuadrosContainer.scrollLeft += e.deltaY;
}
});
// Activar primera habilidad por defecto
if (cuadros.length > 0) {
cuadros[0].click();
}
}
function generarHTMLAtributos(atributos) {
if (!atributos) return ;
const vals = atributos.split(',').map(v => v.trim());
const labels = ['Poder PVE', 'Poder PVP', 'Energía', 'Recarga'];
const icons = [
'/images/7/7a/Icon-pve.png',
'/images/5/5f/Icon-pvp.png',
'/images/3/38/Icon-energy.png',
'/images/b/b1/Icon-cooldown.png'
];
return `
${vals.map((v, i) => {
let valor = v === '-' ? '-' : parseInt(v);
if (i === 1 && !isNaN(valor)) {
valor = (valor > 0 ? '+' : ) + valor;
}
return `
<img src="${icons[i]}" class="cardAttribute--icon">
${valor}${i === 0 && valor !== '-' ? ' seg' : }
`;
}).join()}
`;
}
function initSkinsCarousel(container) {
const carousel = container.querySelector('.skins-carousel');
const wrapper = container.querySelector('.skins-carousel-wrapper');
const leftBtn = container.querySelector('.skins-arrow.left');
const rightBtn = container.querySelector('.skins-arrow.right');
if (!carousel || !wrapper || !leftBtn || !rightBtn) return;
let isPredictingScroll = false;
const getScrollAmount = () => carousel.clientWidth * 0.6;
const hideArrow = btn => {
if (!btn.classList.contains('desapareciendo') && btn.style.display !== 'none') {
btn.classList.add('desapareciendo');
setTimeout(() => {
btn.style.display = 'none';
btn.classList.remove('desapareciendo');
}, 300);
}
};
const showArrow = btn => {
if (btn.style.display === 'none') {
btn.style.display = 'inline-block';
void btn.offsetWidth; // Force reflow
}
btn.classList.remove('desapareciendo');
};
const setArrowsState = scrollLeft => {
const maxScroll = carousel.scrollWidth - carousel.clientWidth;
const hasLeft = scrollLeft > 5;
const hasRight = scrollLeft < maxScroll - 5;
if (hasLeft) showArrow(leftBtn);
else hideArrow(leftBtn);
if (hasRight) showArrow(rightBtn);
else hideArrow(rightBtn);
wrapper.classList.toggle('has-left', hasLeft);
wrapper.classList.toggle('has-right', hasRight);
};
const handleArrowClick = direction => {
isPredictingScroll = true;
const scrollLeft = carousel.scrollLeft;
const maxScroll = carousel.scrollWidth - carousel.clientWidth;
const nextScroll = direction === 'left'
? Math.max(0, scrollLeft - getScrollAmount())
: Math.min(maxScroll, scrollLeft + getScrollAmount());
setArrowsState(nextScroll);
carousel.scrollTo({ left: nextScroll, behavior: 'smooth' });
// Esperar a que termine el scroll
let lastPosition = -1;
let stillCount = 0;
const checkScroll = setInterval(() => {
const currentPosition = Math.round(carousel.scrollLeft);
if (currentPosition === lastPosition) {
if (++stillCount >= 2) {
clearInterval(checkScroll);
isPredictingScroll = false;
setArrowsState(currentPosition);
}
} else {
lastPosition = currentPosition;
stillCount = 0;
}
}, 50);
};
// Event listeners
carousel.addEventListener('scroll', () => {
if (!isPredictingScroll) {
setArrowsState(carousel.scrollLeft);
}
});
// Resize observer para recalcular cuando cambie el tamaño
if (window.ResizeObserver) {
new ResizeObserver(() => {
if (!isPredictingScroll) {
setArrowsState(carousel.scrollLeft);
}
}).observe(carousel);
}
leftBtn.addEventListener('click', () => handleArrowClick('left'));
rightBtn.addEventListener('click', () => handleArrowClick('right'));
// Estado inicial
setArrowsState(carousel.scrollLeft);
}
// Inicializar tooltips simples
function initSimpleTooltips() {
const tooltipElements = document.querySelectorAll('[data-tooltip]');
tooltipElements.forEach(element => {
element.addEventListener('mouseenter', (e) => {
const tooltip = document.createElement('div');
tooltip.className = 'simple-tooltip-popup';
tooltip.innerHTML = e.target.dataset.tooltip;
document.body.appendChild(tooltip);
const rect = e.target.getBoundingClientRect();
tooltip.style.position = 'absolute';
tooltip.style.left = rect.left + (rect.width / 2) - (tooltip.offsetWidth / 2) + 'px';
tooltip.style.top = rect.top - tooltip.offsetHeight - 8 + 'px';
tooltip.style.zIndex = '9999';
tooltip.style.background = '#222';
tooltip.style.color = '#fff';
tooltip.style.padding = '8px 10px';
tooltip.style.borderRadius = '4px';
tooltip.style.fontSize = '12px';
tooltip.style.whiteSpace = 'nowrap';
tooltip.style.boxShadow = '0 2px 10px rgba(0,0,0,0.5)';
tooltip.style.pointerEvents = 'none';
});
element.addEventListener('mouseleave', () => {
const tooltips = document.querySelectorAll('.simple-tooltip-popup');
tooltips.forEach(tooltip => tooltip.remove());
});
});
}
// Inicializar tooltips después de que se cargue el contenido
setTimeout(initSimpleTooltips, 100);
})();