Mudanças entre as edições de "Módulo:Droflax"

De Wiki Gla
Ir para navegação Ir para pesquisar
(Limpou toda a página)
Etiquetas: Reversão manual anulando
Linha 1: Linha 1:
local p = {}


function p.main(frame)
    local args = frame:getParent().args
    return p._main(args)
end
function p._main(args)
    -- Validaciones básicas
    if not args.nome or args.nome == '' then
        return '<div style="color:red;">Error: Nome es requerido</div>'
    end
   
    -- Procesamiento de habilidades
    local habilidades = {}
    for i = 1, 21 do
        local nomeKey = 'hab' .. i .. '-nome'
        if args[nomeKey] and args[nomeKey] ~= '' then
            table.insert(habilidades, {
                nome = args[nomeKey] or '',
                icon = args['hab' .. i .. '-icon'] or '',
                level = tonumber(args['hab' .. i .. '-level']) or 1,
                desc = args['hab' .. i .. '-desc'] or '',
                atr = args['hab' .. i .. '-atr'] or '',
                video = args['hab' .. i .. '-video'] or ''
            })
        end
    end
   
    -- Procesamiento de skins
    local skins = {}
    for i = 1, 11 do
        local imageKey = 'skin' .. i .. '-image'
        if args[imageKey] and args[imageKey] ~= '' then
            table.insert(skins, {
                image = args[imageKey] or '',
                banner = args['skin' .. i .. '-banner'] or '',
                tooltip = args['skin' .. i .. '-tooltip'] or ''
            })
        end
    end
   
    -- Construcción del HTML usando mw.html (más eficiente)
    local root = mw.html.create('div')
        :addClass('personaje-box')
        :attr('data-tier', args.tier or '')
   
    -- Header
    local header = root:tag('div'):addClass('personaje-header')
   
    local topbar = header:tag('div'):addClass('personaje-topbar')
    local nomeBox = topbar:tag('div'):addClass('personaje-nome-box')
   
    nomeBox:tag('img')
        :attr('src', '/images/6/63/Franky_ts_medal.png')
        :addClass('topbar-icon')
   
    local nomeCategory = nomeBox:tag('div'):addClass('personaje-nome-category')
    nomeCategory:tag('div'):addClass('nome'):wikitext(args.nome)
    nomeCategory:tag('div'):addClass('classes'):wikitext(args.classe or '')
   
    -- Description
    header:tag('div')
        :addClass('topbar-description')
        :wikitext((args.nome or '') .. ' (' .. (args.tier or '') .. ') é um personagem do tier ' .. string.lower(args.tier or '') .. '.')
   
    -- Tabs
    local tabs = header:tag('div'):addClass('personaje-tabs')
    tabs:tag('button'):addClass('tab-btn'):attr('data-tab', 'arma'):wikitext('Arma')
    tabs:tag('button'):addClass('tab-btn active'):attr('data-tab', 'habilidades'):wikitext('Habilidades')
    tabs:tag('button'):addClass('tab-btn'):attr('data-tab', 'skins'):wikitext('Skins')
   
    -- Art image
    root:tag('img')
        :addClass('art-personaje')
        :attr('src', args.image or '')
        :attr('alt', 'Arte del personaje')
   
    -- Habilidades tab content
    local habTab = root:tag('div')
        :addClass('tab-content active')
        :attr('id', 'habilidades')
   
    -- Cuadros container (iconos de habilidades)
    local cuadrosContainer = habTab:tag('div'):addClass('cuadros-container')
    for i, hab in ipairs(habilidades) do
        local cuadro = cuadrosContainer:tag('div')
            :addClass('cuadro')
            :attr('data-hab-index', i)
            :attr('title', hab.nome)
       
        cuadro:tag('img')
            :attr('src', hab.icon)
            :attr('alt', hab.nome)
            :css('width', '100%')
            :css('height', '100%')
            :css('object-fit', 'cover')
    end
   
    -- Habilidades details container
    local habContainer = habTab:tag('div'):addClass('habilidades-container')
    local habDetails = habContainer:tag('div'):addClass('habilidades-details')
    local descripcionContainer = habDetails:tag('div')
        :addClass('descripcion-container')
        :attr('id', 'descripcion-container')
   
    local videoContainer = habContainer:tag('div')
        :addClass('video-container')
        :attr('id', 'video-container')
   
    -- Skins tab content
    local skinsTab = root:tag('div')
        :addClass('tab-content')
        :attr('id', 'skins')
   
    local cardSkins = skinsTab:tag('div'):addClass('card-skins')
    cardSkins:tag('span')
        :addClass('card-skins-title')
        :wikitext('SKINS & SPOTLIGHTS')
   
    local carouselWrapper = cardSkins:tag('div'):addClass('skins-carousel-wrapper')
    carouselWrapper:tag('button')
        :addClass('skins-arrow left')
        :wikitext('«')
   
    local carousel = carouselWrapper:tag('div'):addClass('skins-carousel')
    for _, skin in ipairs(skins) do
        local skinCard = carousel:tag('div'):addClass('skin-card')
        skinCard:tag('img')
            :addClass('skins--imageBanner')
            :attr('src', skin.banner)
            :attr('alt', 'banner')
       
        skinCard:tag('img')
            :addClass('skins--imageSkin')
            :attr('src', skin.image)
            :attr('alt', 'skin')
    end
   
    carouselWrapper:tag('button')
        :addClass('skins-arrow right')
        :wikitext('»')
   
    -- Datos JSON para JavaScript (más eficiente que data-attributes múltiples)
    local dataScript = mw.html.create('script')
        :attr('type', 'application/json')
        :attr('id', 'persona-data-json')
        :wikitext(mw.text.jsonEncode({
            nome = args.nome or '',
            tier = args.tier or '',
            classe = args.classe or '',
            image = args.image or '',
            habilidades = habilidades,
            skins = skins
        }))
   
    -- CSS (solo lo esencial, el resto en CSS común)
    local style = mw.html.create('style'):wikitext([[
        .personaje-box { padding: 16px; color: #000; font-family: 'Segoe UI', sans-serif; width: 90%; margin: auto; position: relative; user-select: none; }
        .personaje-topbar { display: flex; flex-direction: column; align-items: flex-start; padding: 8px 16px; }
        .personaje-nome-box { display: flex; align-items: center; gap: 8px; }
        .topbar-icon { width: 90px; height: 90px; object-fit: none; background: #60dae2; }
        .nome { font-size: 60px; font-family: 'Orbitron', sans-serif; font-weight: 900; }
        .topbar-description { font-size: 16px; margin-top: 6px; background: #6AF3FB; width: fit-content; padding-inline: 16px; border-radius: 0 10px 10px 0; }
        .personaje-header { display: flex; gap: 10px; flex-direction: column; }
        .art-personaje { width: 665px; position: absolute; right: 1rem; top: 0.4rem; z-index: 9; }
        /* ... resto del CSS optimizado ... */
    ]])
   
    -- JavaScript optimizado
    local script = mw.html.create('script'):wikitext([[
        (function() {
            'use strict';
           
            // Cargar datos JSON (más rápido que procesar data-attributes)
            const dataEl = document.getElementById('persona-data-json');
            if (!dataEl) return console.error('Persona: no se encontró JSON data');
           
            let data;
            try {
                data = JSON.parse(dataEl.textContent);
            } catch (e) {
                return console.error('Persona: error parsing JSON', e);
            }
           
            // Cache de elementos DOM
            const elements = {
                tabBtns: document.querySelectorAll('.tab-btn'),
                tabContents: document.querySelectorAll('.tab-content'),
                cuadros: document.querySelectorAll('.cuadro'),
                descripcionContainer: document.getElementById('descripcion-container'),
                videoContainer: document.getElementById('video-container'),
                personajeBox: document.querySelector('.personaje-box')
            };
           
            // Aplicar tier class
            const tierClass = {
                'bronze': 'tier-bronze', 'bronce': 'tier-bronze',
                'silver': 'tier-silver', 'prata': 'tier-silver',
                'gold': 'tier-gold', 'ouro': 'tier-gold',
                'diamond': 'tier-diamond', 'diamante': 'tier-diamond'
            }[data.tier.toLowerCase()];
           
            if (tierClass) elements.personajeBox.classList.add(tierClass);
           
            // Event listeners optimizados
            elements.tabBtns.forEach(btn => {
                btn.addEventListener('click', handleTabClick, false);
            });
           
            elements.cuadros.forEach((cuadro, index) => {
                cuadro.addEventListener('click', () => handleHabilidadClick(index), false);
            });
           
            // Funciones optimizadas
            function handleTabClick(e) {
                const target = e.target.dataset.tab;
                elements.tabBtns.forEach(b => b.classList.remove('active'));
                elements.tabContents.forEach(c => c.classList.remove('active'));
                e.target.classList.add('active');
                document.getElementById(target).classList.add('active');
            }
           
            function handleHabilidadClick(index) {
                const hab = data.habilidades[index];
                if (!hab) return;
               
                // Generar HTML de atributos
                const atributos = hab.atr.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'
                ];
               
                const atributosHTML = atributos.map((v, i) => {
                    let f = v === '-' ? '-' : parseInt(v);
                    if (i === 1 && !isNaN(f)) f = (f > 0 ? '+' : '') + f;
                    return `
                        <span class="simple-tooltip">
                            <div class="cardAttribute">
                                <img src="${icons[i]}" class="cardAttribute--icon">
                                <h2 class="cardAttribute--value">${f}${i === 0 && f !== '-' ? ' seg' : ''}</h2>
                            </div>
                        </span>`;
                }).join('');
               
                // Actualizar descripción
                elements.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.</span>
                        </div>
                    </div>
                    <div class="attribute--cardsContainer">${atributosHTML}</div>
                    <div class="desc">${hab.desc.replace(/'''(.*?)'''/g, '<b>$1</b>')}</div>
                `;
               
                // Actualizar video
                elements.videoContainer.innerHTML = hab.video ?
                    `<video width="100%" controls playsinline><source src="${hab.video}" type="video/webm"></video>` : '';
               
                // Actualizar clases activas
                elements.cuadros.forEach(c => c.classList.remove('activo'));
                elements.cuadros[index].classList.add('activo');
            }
           
            // Inicializar primera habilidad
            if (data.habilidades.length > 0) {
                handleHabilidadClick(0);
            }
           
            // Inicializar carrusel de skins
            initSkinsCarousel();
           
            function initSkinsCarousel() {
                const carousel = document.querySelector('.skins-carousel');
                if (!carousel) return;
               
                const wrapper = document.querySelector('.skins-carousel-wrapper');
                const leftBtn = document.querySelector('.skins-arrow.left');
                const rightBtn = document.querySelector('.skins-arrow.right');
               
                let isScrolling = false;
               
                function updateArrows() {
                    const maxScroll = carousel.scrollWidth - carousel.clientWidth;
                    const hasLeft = carousel.scrollLeft > 5;
                    const hasRight = carousel.scrollLeft < maxScroll - 5;
                   
                    leftBtn.style.display = hasLeft ? 'inline-block' : 'none';
                    rightBtn.style.display = hasRight ? 'inline-block' : 'none';
                   
                    wrapper.classList.toggle('has-left', hasLeft);
                    wrapper.classList.toggle('has-right', hasRight);
                }
               
                function scrollCarousel(direction) {
                    if (isScrolling) return;
                    isScrolling = true;
                   
                    const scrollAmount = carousel.clientWidth * 0.6;
                    const currentScroll = carousel.scrollLeft;
                    const maxScroll = carousel.scrollWidth - carousel.clientWidth;
                   
                    let nextScroll;
                    if (direction === 'left') {
                        nextScroll = Math.max(0, currentScroll - scrollAmount);
                    } else {
                        nextScroll = Math.min(maxScroll, currentScroll + scrollAmount);
                    }
                   
                    carousel.scrollTo({ left: nextScroll, behavior: 'smooth' });
                   
                    setTimeout(() => {
                        isScrolling = false;
                        updateArrows();
                    }, 300);
                }
               
                leftBtn.addEventListener('click', () => scrollCarousel('left'));
                rightBtn.addEventListener('click', () => scrollCarousel('right'));
                carousel.addEventListener('scroll', updateArrows, { passive: true });
               
                // Observer para cambios de tamaño
                new ResizeObserver(updateArrows).observe(carousel);
               
                // Inicializar
                updateArrows();
            }
           
            // Limpiar data element
            dataEl.remove();
        })();
    ]])
   
    return tostring(root) .. tostring(dataScript) .. tostring(style) .. tostring(script)
end
return p

Edição das 15h31min de 20 de julho de 2025

A documentação para este módulo pode ser criada em Módulo:Droflax/doc