MediaWiki:Common.js: mudanças entre as edições

De Farmland
Ir para navegação Ir para pesquisar
Sem resumo de edição
Etiqueta: Revertido
Sem resumo de edição
 
(37 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
/* =======================================================
/* =======================================================
   CARROSSEL UNIFICADO - WIKI EVERLIGHT
   ARVORE DE HABILIDADE
   ======================================================= */
   ======================================================= */
mw.loader.using(['jquery', 'mediawiki.util'], function () {
document.addEventListener('DOMContentLoaded', function () {
     $(function() {
     var cards = document.querySelectorAll('.skill-card');
        const $wrapper = $('.carousel-wrapper');
    cards.forEach(function (card) {
        const $items = $('.carousel-item');
        card.addEventListener('click', function () {
        const $next = $('.right-btn');
             card.style.filter = 'brightness(1.2)';
        const $prev = $('.left-btn');
             setTimeout(function () { card.style.filter = 'brightness(1)'; }, 150);
       
        if (!$wrapper.length) return; // Só executa se o carrossel existir na página
 
        let current = 0;
        let autoPlayTimer;
 
        function updateCarousel() {
            // Atualiza a classe ativa para o efeito visual de destaque
            $items.removeClass('active').eq(current).addClass('active');
 
             const activeItem = $items.get(current);
            const scrollPosition =  
                activeItem.offsetLeft -
                ($wrapper.width() / 2) +
                ($(activeItem).outerWidth() / 2);
 
             $wrapper.stop().animate({
                scrollLeft: scrollPosition
            }, 500);
        }
 
        // Funções de Navegação
        function moveNext() {
            current = (current + 1) % $items.length;
            updateCarousel();
        }
 
        function movePrev() {
            current = (current - 1 + $items.length) % $items.length;
            updateCarousel();
        }
 
        // Eventos de Clique
        $next.on('click', function() {
            stopAutoPlay();
            moveNext();
         });
         });
    });
});


        $prev.on('click', function() {
            stopAutoPlay();
            movePrev();
        });


        // Auto-Play (4 segundos)
/* =======================================================
        function startAutoPlay() {
  BOTAO VOLTAR AO TOPO
            autoPlayTimer = setInterval(moveNext, 4000);
  ======================================================= */
        }
$(function () {
    var $button = $('<button id="back-to-top" title="Voltar ao Topo">↑ Topo</button>');
    $('body').append($button);


         function stopAutoPlay() {
    $(window).scroll(function () {
             clearInterval(autoPlayTimer);
         if ($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
            $button.fadeIn();
        } else {
             $button.fadeOut();
         }
         }
    });


        // Inicialização
    $button.click(function () {
        updateCarousel();
         $('html, body').animate({ scrollTop: 0 }, 'slow');
         startAutoPlay();
        return false;
 
        // Pausa o carrossel se o mouse estiver em cima
        $wrapper.hover(stopAutoPlay, startAutoPlay);
     });
     });
});
});
Linha 71: Linha 36:


/* =======================================================
/* =======================================================
   ARVORE HABILIDADE - WIKI EVERLIGHT
   ARVORE DE CLASSES
   ======================================================= */
   ======================================================= */
document.addEventListener('DOMContentLoaded', function () {
    var cells = document.querySelectorAll('.ragnarok-tree td[class^="evo-"]');
    cells.forEach(function (cell) {
        var link = cell.querySelector('a');
        if (link) {
            cell.style.cursor = 'pointer';
            cell.addEventListener('click', function () { window.location.href = link.href; });
        }
        cell.addEventListener('mouseenter', function () {
            var familyClass = Array.from(this.classList).find(function (c) { return c.startsWith('evo-'); });
            if (!familyClass || familyClass === 'evo-all') return;


            var myPos    = this.getAttribute('data-pos');
            var prevEl  = this.closest('table').previousElementSibling;
            var isClass1 = prevEl && prevEl.innerText.includes('Classe 1');
            var isClass2 = prevEl && prevEl.innerText.includes('Classe 2');


document.addEventListener('DOMContentLoaded', () => {
            if (isClass1) {
    const cards = document.querySelectorAll('.skill-card');
                document.querySelectorAll('.' + familyClass).forEach(function (el) {
                    el.classList.add('highlight-active');
                });
            } else if (isClass2) {
                this.classList.add('highlight-active');
                var table3 = document.querySelector('table:nth-of-type(3)');
                if (table3) {
                    table3.querySelectorAll('.' + familyClass).forEach(function (el) {
                        if (el.getAttribute('data-pos') === myPos) el.classList.add('highlight-active');
                    });
                }
            } else {
                this.classList.add('highlight-active');
            }
        });


    cards.forEach(card => {
         cell.addEventListener('mouseleave', function () {
         card.addEventListener('click', () => {
             document.querySelectorAll('.highlight-active').forEach(function (el) {
             const skillName = card.querySelector('.skill-name').innerText;
                 el.classList.remove('highlight-active');
            console.log(`Habilidade clicada: ${skillName}`);
             });
           
            // Exemplo de efeito visual simples
            card.style.filter = "brightness(1.2)";
            setTimeout(() => {
                 card.style.filter = "brightness(1)";
             }, 150);
         });
         });
     });
     });
});
});


document.querySelectorAll('.carousel-track').forEach(track => {
  track.addEventListener('mouseenter', () => {
    track.querySelectorAll('.carousel-item').forEach(item => {
      item.style.animationPlayState = 'paused';
    });
  });
  track.addEventListener('mouseleave', () => {
    track.querySelectorAll('.carousel-item').forEach(item => {
      item.style.animationPlayState = 'running';
    });
  });
});






/* =======================================================
  CARROSSEL FARMLAND
  ======================================================= */
mw.hook('wikipage.content').add(function () {
    var carousel = document.getElementById('farmlandCarousel');
    if (!carousel) return;
    var wrapper  = carousel.querySelector('.carousel-wrapper');
    var container = carousel.querySelector('.carousel-container');
    var slides  = carousel.querySelectorAll('.carousel-slide');
    var dotsWrap = carousel.querySelector('.carousel-dots');
    var progBar  = carousel.querySelector('.carousel-progress');
    var nextBtn  = carousel.querySelector('.carousel-arrow.right');
    var prevBtn  = carousel.querySelector('.carousel-arrow.left');


    if (!container || slides.length === 0) return;


    var DELAY = 3500;
    var total = slides.length;
    var idx  = 1;
    var timer, busy = false;


    /* Clones para loop infinito sem flash */
    var firstClone = slides[0].cloneNode(true);
    var lastClone  = slides[total - 1].cloneNode(true);
    firstClone.classList.add('clone');
    lastClone.classList.add('clone');
    container.appendChild(firstClone);
    container.insertBefore(lastClone, slides[0]);


    var allSlides = container.querySelectorAll('.carousel-slide');


    /* Força layout correto (crítico no MediaWiki) */
    container.style.display    = 'flex';
    container.style.transition = 'none';
    allSlides.forEach(function (s) {
        s.style.minWidth  = '100%';
        s.style.flexShrink = '0';
    });
    container.style.transform = 'translateX(-' + (idx * 100) + '%)';


// =========================
    /* Dots */
// INTERATIVIDADE DOS GUIAS
    dotsWrap.innerHTML = '';
// =========================
    var dots = [];
    for (var i = 0; i < total; i++) {
        var dot = document.createElement('span');
        dot.className = 'dot';
        dotsWrap.appendChild(dot);
        dots.push(dot);
        (function (n) {
            dot.onclick = function () { goTo(n + 1); resetAuto(); };
        })(i);
    }


document.addEventListener('DOMContentLoaded', function() {
    function updateDots() {
  const guidesWrapper = document.querySelector('.ragnarok-guides-wrapper');
        var ai = idx - 1;
  if (!guidesWrapper) return;
        if (ai < 0) ai = total - 1;
        if (ai >= total) ai = 0;
        dots.forEach(function (d, i) {
            d.classList.toggle('active', i === ai);
        });
    }


  // 1. Sistema de Busca em Tempo Real
    function goTo(i, animate) {
  const searchInput = document.querySelector('.guide-search-input');
        if (busy) return;
  const searchButton = document.querySelector('.search-button');
        busy = true;
  const guideCards = document.querySelectorAll('.ragnarok-guide-card');
        idx  = i;
        container.style.transition = (animate === false)
            ? 'none'
            : 'transform 0.5s cubic-bezier(.4,0,.2,1)';
        container.style.transform = 'translateX(-' + (idx * 100) + '%)';
        updateDots();
    }


  function filterGuides() {
    container.addEventListener('transitionend', function () {
    const searchTerm = searchInput.value.toLowerCase().trim();
        if (allSlides[idx] && allSlides[idx].classList.contains('clone')) {
   
            container.style.transition = 'none';
    guideCards.forEach(card => {
            idx = (idx === 0) ? total : 1;
      const title = card.querySelector('.card-title').textContent.toLowerCase();
            container.style.transform = 'translateX(-' + (idx * 100) + '%)';
      const desc = card.querySelector('.card-desc').textContent.toLowerCase();
            updateDots();
     
        }
      if (searchTerm === '' || title.includes(searchTerm) || desc.includes(searchTerm)) {
         busy = false;
        card.style.display = 'flex';
        card.style.animation = 'fadeInUp 0.3s ease';
      } else {
         card.style.display = 'none';
      }
     });
     });
  }


  searchInput.addEventListener('input', filterGuides);
    function next() { goTo(idx + 1); resetAuto(); }
  searchButton.addEventListener('click', filterGuides);
    function prev() { goTo(idx - 1); resetAuto(); }


  // 2. Efeito de Hover com Partículas
     if (nextBtn) nextBtn.onclick = next;
  guideCards.forEach(card => {
    if (prevBtn) prevBtn.onclick = prev;
     card.addEventListener('mouseenter', function(e) {
      // Adiciona partículas no hover
      for (let i = 0; i < 8; i++) {
        createParticle(e, this);
      }
     
      // Efeito de brilho
      const shine = document.createElement('div');
      shine.className = 'card-shine';
      shine.style.cssText = `
        position: absolute;
        top: ${e.offsetY}px;
        left: ${e.offsetX}px;
        width: 0;
        height: 0;
        background: radial-gradient(circle, rgba(139, 92, 246, 0.2) 0%, transparent 70%);
        transform: translate(-50%, -50%);
        pointer-events: none;
        animation: expandShine 0.6s forwards;
        z-index: 1;
      `;
     
      this.style.position = 'relative';
      this.appendChild(shine);
     
      setTimeout(() => {
        if (shine.parentNode) shine.parentNode.removeChild(shine);
      }, 600);
    });
  });


  // 3. Criar partículas decorativas
    /* Barra de progresso */
  function createParticles() {
    function startProg() {
    const particleCount = 15;
        if (!progBar) return;
    for (let i = 0; i < particleCount; i++) {
        progBar.style.transition = 'none';
      const particle = document.createElement('div');
        progBar.style.width = '0%';
      particle.className = 'guide-particle';
        setTimeout(function () {
     
            progBar.style.transition = 'width ' + DELAY + 'ms linear';
      // Posição aleatória
            progBar.style.width = '100%';
      const left = Math.random() * 100;
         }, 30);
      const delay = Math.random() * 15;
      const duration = 15 + Math.random() * 10;
     
      particle.style.cssText = `
        left: ${left}%;
        top: 100%;
         animation-delay: ${delay}s;
        animation-duration: ${duration}s;
      `;
     
      guidesWrapper.appendChild(particle);
     }
     }
  }


  // 4. Efeito de partícula no clique
    function startAuto() {
  function createParticle(e, parent) {
        timer = setInterval(function () { goTo(idx + 1); startProg(); }, DELAY);
    const particle = document.createElement('div');
         startProg();
    particle.className = 'click-particle';
   
    const colors = ['#8B5CF6', '#3B82F6', '#EC4899', '#10B981'];
    const color = colors[Math.floor(Math.random() * colors.length)];
   
    particle.style.cssText = `
      position: absolute;
      width: 8px;
      height: 8px;
      background: ${color};
      border-radius: 50%;
      pointer-events: none;
      z-index: 100;
      left: ${e.offsetX}px;
      top: ${e.offsetY}px;
    `;
   
    parent.appendChild(particle);
   
    // Animação da partícula
    const angle = Math.random() * Math.PI * 2;
    const speed = 2 + Math.random() * 3;
    const vx = Math.cos(angle) * speed;
    const vy = Math.sin(angle) * speed;
   
    let x = e.offsetX;
    let y = e.offsetY;
    let opacity = 1;
   
    function animate() {
      x += vx;
      y += vy;
      opacity -= 0.02;
     
      particle.style.left = x + 'px';
      particle.style.top = y + 'px';
      particle.style.opacity = opacity;
     
      if (opacity > 0) {
        requestAnimationFrame(animate);
      } else {
         particle.remove();
      }
     }
     }
   
    animate();
  }


  // 5. Adicionar estilo CSS dinâmico para animações
    function stopAuto() {
  const style = document.createElement('style');
        clearInterval(timer);
  style.textContent = `
        if (progBar) { progBar.style.transition = 'none'; progBar.style.width = '0%'; }
    @keyframes expandShine {
      0% {
        width: 0;
        height: 0;
        opacity: 0.6;
      }
      100% {
        width: 300px;
        height: 300px;
        opacity: 0;
      }
     }
     }
   
 
     @keyframes fadeInUp {
     function resetAuto() { clearInterval(timer); startAuto(); }
      from {
 
        opacity: 0;
    /* Pausa no hover */
        transform: translateY(10px);
    if (wrapper) {
      }
         wrapper.addEventListener('mouseenter', stopAuto);
      to {
         wrapper.addEventListener('mouseleave', startAuto);
         opacity: 1;
         transform: translateY(0);
      }
     }
     }
  `;
  document.head.appendChild(style);


  // 6. Inicializar partículas
    /* Swipe mobile */
  createParticles();
    var startX = 0;
    if (wrapper) {
        wrapper.addEventListener('touchstart', function (e) { startX = e.touches[0].clientX; });
        wrapper.addEventListener('touchend', function (e) {
            var diff = startX - e.changedTouches[0].clientX;
            if (Math.abs(diff) > 40) { diff > 0 ? next() : prev(); }
        });
    }


  // 7. Contador de guias (opcional)
     updateDots();
  const guideCount = guideCards.length;
     startAuto();
  const countElement = document.createElement('div');
  countElement.className = 'guide-count';
  countElement.innerHTML = `
     <div style="
      text-align: center;
      margin-top: 20px;
      padding: 10px;
      background: rgba(139, 92, 246, 0.1);
      border-radius: 10px;
      color: #8B5CF6;
      font-weight: 600;
    ">
      🎮 Total de ${guideCount} guias disponíveis
    </div>
  `;
 
  const searchBox = document.querySelector('.ragnarok-search-box');
  if (searchBox) {
     searchBox.parentNode.insertBefore(countElement, searchBox.nextSibling);
  }
});
});

Edição atual tal como às 21h15min de 16 de maio de 2026

/* =======================================================
   ARVORE DE HABILIDADE
   ======================================================= */
document.addEventListener('DOMContentLoaded', function () {
    var cards = document.querySelectorAll('.skill-card');
    cards.forEach(function (card) {
        card.addEventListener('click', function () {
            card.style.filter = 'brightness(1.2)';
            setTimeout(function () { card.style.filter = 'brightness(1)'; }, 150);
        });
    });
});


/* =======================================================
   BOTAO VOLTAR AO TOPO
   ======================================================= */
$(function () {
    var $button = $('<button id="back-to-top" title="Voltar ao Topo">↑ Topo</button>');
    $('body').append($button);

    $(window).scroll(function () {
        if ($(window).scrollTop() + $(window).height() > $(document).height() - 100) {
            $button.fadeIn();
        } else {
            $button.fadeOut();
        }
    });

    $button.click(function () {
        $('html, body').animate({ scrollTop: 0 }, 'slow');
        return false;
    });
});


/* =======================================================
   ARVORE DE CLASSES
   ======================================================= */
document.addEventListener('DOMContentLoaded', function () {
    var cells = document.querySelectorAll('.ragnarok-tree td[class^="evo-"]');

    cells.forEach(function (cell) {
        var link = cell.querySelector('a');
        if (link) {
            cell.style.cursor = 'pointer';
            cell.addEventListener('click', function () { window.location.href = link.href; });
        }

        cell.addEventListener('mouseenter', function () {
            var familyClass = Array.from(this.classList).find(function (c) { return c.startsWith('evo-'); });
            if (!familyClass || familyClass === 'evo-all') return;

            var myPos    = this.getAttribute('data-pos');
            var prevEl   = this.closest('table').previousElementSibling;
            var isClass1 = prevEl && prevEl.innerText.includes('Classe 1');
            var isClass2 = prevEl && prevEl.innerText.includes('Classe 2');

            if (isClass1) {
                document.querySelectorAll('.' + familyClass).forEach(function (el) {
                    el.classList.add('highlight-active');
                });
            } else if (isClass2) {
                this.classList.add('highlight-active');
                var table3 = document.querySelector('table:nth-of-type(3)');
                if (table3) {
                    table3.querySelectorAll('.' + familyClass).forEach(function (el) {
                        if (el.getAttribute('data-pos') === myPos) el.classList.add('highlight-active');
                    });
                }
            } else {
                this.classList.add('highlight-active');
            }
        });

        cell.addEventListener('mouseleave', function () {
            document.querySelectorAll('.highlight-active').forEach(function (el) {
                el.classList.remove('highlight-active');
            });
        });
    });
});




/* =======================================================
   CARROSSEL FARMLAND
   ======================================================= */
mw.hook('wikipage.content').add(function () {

    var carousel = document.getElementById('farmlandCarousel');
    if (!carousel) return;

    var wrapper  = carousel.querySelector('.carousel-wrapper');
    var container = carousel.querySelector('.carousel-container');
    var slides   = carousel.querySelectorAll('.carousel-slide');
    var dotsWrap = carousel.querySelector('.carousel-dots');
    var progBar  = carousel.querySelector('.carousel-progress');
    var nextBtn  = carousel.querySelector('.carousel-arrow.right');
    var prevBtn  = carousel.querySelector('.carousel-arrow.left');

    if (!container || slides.length === 0) return;

    var DELAY = 3500;
    var total = slides.length;
    var idx   = 1;
    var timer, busy = false;

    /* Clones para loop infinito sem flash */
    var firstClone = slides[0].cloneNode(true);
    var lastClone  = slides[total - 1].cloneNode(true);
    firstClone.classList.add('clone');
    lastClone.classList.add('clone');
    container.appendChild(firstClone);
    container.insertBefore(lastClone, slides[0]);

    var allSlides = container.querySelectorAll('.carousel-slide');

    /* Força layout correto (crítico no MediaWiki) */
    container.style.display    = 'flex';
    container.style.transition = 'none';
    allSlides.forEach(function (s) {
        s.style.minWidth   = '100%';
        s.style.flexShrink = '0';
    });
    container.style.transform = 'translateX(-' + (idx * 100) + '%)';

    /* Dots */
    dotsWrap.innerHTML = '';
    var dots = [];
    for (var i = 0; i < total; i++) {
        var dot = document.createElement('span');
        dot.className = 'dot';
        dotsWrap.appendChild(dot);
        dots.push(dot);
        (function (n) {
            dot.onclick = function () { goTo(n + 1); resetAuto(); };
        })(i);
    }

    function updateDots() {
        var ai = idx - 1;
        if (ai < 0) ai = total - 1;
        if (ai >= total) ai = 0;
        dots.forEach(function (d, i) {
            d.classList.toggle('active', i === ai);
        });
    }

    function goTo(i, animate) {
        if (busy) return;
        busy = true;
        idx  = i;
        container.style.transition = (animate === false)
            ? 'none'
            : 'transform 0.5s cubic-bezier(.4,0,.2,1)';
        container.style.transform = 'translateX(-' + (idx * 100) + '%)';
        updateDots();
    }

    container.addEventListener('transitionend', function () {
        if (allSlides[idx] && allSlides[idx].classList.contains('clone')) {
            container.style.transition = 'none';
            idx = (idx === 0) ? total : 1;
            container.style.transform = 'translateX(-' + (idx * 100) + '%)';
            updateDots();
        }
        busy = false;
    });

    function next() { goTo(idx + 1); resetAuto(); }
    function prev() { goTo(idx - 1); resetAuto(); }

    if (nextBtn) nextBtn.onclick = next;
    if (prevBtn) prevBtn.onclick = prev;

    /* Barra de progresso */
    function startProg() {
        if (!progBar) return;
        progBar.style.transition = 'none';
        progBar.style.width = '0%';
        setTimeout(function () {
            progBar.style.transition = 'width ' + DELAY + 'ms linear';
            progBar.style.width = '100%';
        }, 30);
    }

    function startAuto() {
        timer = setInterval(function () { goTo(idx + 1); startProg(); }, DELAY);
        startProg();
    }

    function stopAuto() {
        clearInterval(timer);
        if (progBar) { progBar.style.transition = 'none'; progBar.style.width = '0%'; }
    }

    function resetAuto() { clearInterval(timer); startAuto(); }

    /* Pausa no hover */
    if (wrapper) {
        wrapper.addEventListener('mouseenter', stopAuto);
        wrapper.addEventListener('mouseleave', startAuto);
    }

    /* Swipe mobile */
    var startX = 0;
    if (wrapper) {
        wrapper.addEventListener('touchstart', function (e) { startX = e.touches[0].clientX; });
        wrapper.addEventListener('touchend', function (e) {
            var diff = startX - e.changedTouches[0].clientX;
            if (Math.abs(diff) > 40) { diff > 0 ? next() : prev(); }
        });
    }

    updateDots();
    startAuto();
});