Mudanças entre as edições de "Widget:Item"

De Wiki Gla
Ir para navegação Ir para pesquisar
m
m
Linha 1: Linha 1:
<includeonly>
<includeonly>
     <!--
     <!--
       Tooltip: HTML vem do Módulo:Item.renderTooltip via renderOne (Scribunto).
       Tooltip: payload codificado em data-tip (Módulo:Item). Corpo vazio no HTML.
       Este widget aplica estilos e posiciona .item-tooltip no hover.
      JS decodifica no hover (rápido, sem API) e limpa no mouseout.
       Defesa leve: hover real + rate limit de decodes para automação.
     -->
     -->
     <style>
     <style>
Linha 266: Linha 267:
             var MARGIN = 8;
             var MARGIN = 8;
             var GAP = 6;
             var GAP = 6;
            var XOR_KEY = 0x5A;
             var activeTip = null;
             var activeTip = null;
             var activeWrapper = null;
             var activeWrapper = null;
            var decodeCache = Object.create(null);
            var decodeLog = [];
            var untrustedStrikes = 0;
            var decodeBlocked = false;
            var RATE_WINDOW = 120000;
            var RATE_MAX = 120;


             function showTooltip(wrapper) {
             function isStaff() {
                 hideTooltip();
                 try {
                    if (!window.mw || !mw.config) return false;
                    var groups = mw.config.get("wgUserGroups") || [];
                    for (var i = 0; i < groups.length; i++) {
                        var g = groups[i];
                        if (g === "sysop" || g === "bureaucrat" || g === "editor" || g === "staff") {
                            return true;
                        }
                    }
                } catch (e) { /* ignore */ }
                return false;
            }
 
            function allowDecode() {
                if (decodeBlocked || !isStaff() && untrustedStrikes >= 4) {
                    decodeBlocked = true;
                    return false;
                }
                if (isStaff()) return true;
                var now = Date.now();
                while (decodeLog.length && now - decodeLog[0] > RATE_WINDOW) {
                    decodeLog.shift();
                }
                if (decodeLog.length >= RATE_MAX) {
                    decodeBlocked = true;
                    return false;
                }
                decodeLog.push(now);
                return true;
            }
 
            function decodePayload(hex) {
                if (!hex) return null;
                if (decodeCache[hex]) return decodeCache[hex];
                try {
                    var json = "";
                    for (var i = 0; i < hex.length; i += 2) {
                        json += String.fromCharCode(parseInt(hex.substr(i, 2), 16) ^ XOR_KEY);
                    }
                    var obj = JSON.parse(json);
                    decodeCache[hex] = obj;
                    return obj;
                } catch (e) {
                    return null;
                }
            }
 
            function appendText(el, text) {
                if (!text) return;
                el.appendChild(document.createTextNode(text));
            }
 
            function fillTooltipBody(tip) {
                if (tip.querySelector(".item-tooltip-name")) return true;
 
                var hex = tip.getAttribute("data-tip");
                if (!hex) return true;
 
                if (!allowDecode()) return false;
 
                var p = decodePayload(hex);
                if (!p) return false;
 
                var body = tip.querySelector(".item-tooltip-body");
                if (!body) return false;
 
                var nameEl = document.createElement("div");
                nameEl.className = "item-tooltip-name";
                appendText(nameEl, p.n);
                body.appendChild(nameEl);
 
                if (p.c) {
                    var catEl = document.createElement("div");
                    catEl.className = "item-tooltip-cat";
                    appendText(catEl, p.c);
                    body.appendChild(catEl);
                }
 
                var hasDetails = p.lv || p.sp || p.d || p.p1 || p.p2 || p.v;
                if (hasDetails) {
                    var sep = document.createElement("div");
                    sep.className = "item-tooltip-sep";
                    body.appendChild(sep);
                }
 
                if (p.lv) {
                    var lvEl = document.createElement("div");
                    lvEl.className = "item-tooltip-level";
                    appendText(lvEl, p.lv);
                    body.appendChild(lvEl);
                }
 
                if (p.sp && (p.p1 || p.p2)) {
                    var passWrap = document.createElement("div");
                    passWrap.className = "item-tooltip-passives";
                    if (p.p1) {
                        var row1 = document.createElement("div");
                        row1.className = "item-tooltip-passive-row";
                        var b1 = document.createElement("span");
                        b1.className = "item-tooltip-passive-badge";
                        appendText(b1, "2");
                        var t1 = document.createElement("span");
                        t1.className = "item-tooltip-passive-text";
                        appendText(t1, p.p1);
                        row1.appendChild(b1);
                        row1.appendChild(t1);
                        passWrap.appendChild(row1);
                    }
                    if (p.p2) {
                        var row2 = document.createElement("div");
                        row2.className = "item-tooltip-passive-row";
                        var b2 = document.createElement("span");
                        b2.className = "item-tooltip-passive-badge";
                        appendText(b2, "5");
                        var t2 = document.createElement("span");
                        t2.className = "item-tooltip-passive-text";
                        appendText(t2, p.p2);
                        row2.appendChild(b2);
                        row2.appendChild(t2);
                        passWrap.appendChild(row2);
                    }
                    body.appendChild(passWrap);
                } else if (p.d) {
                    var descEl = document.createElement("div");
                    descEl.className = "item-tooltip-desc";
                    appendText(descEl, p.d);
                    body.appendChild(descEl);
                }
 
                if (p.v) {
                    var footer = document.createElement("div");
                    footer.className = "item-tooltip-footer";
                    var valEl = document.createElement("span");
                    valEl.className = "item-tooltip-val";
                    appendText(valEl, p.v);
                    footer.appendChild(valEl);
                    body.appendChild(footer);
                }


                 var tip = wrapper.querySelector(".item-tooltip");
                 return true;
                if (!tip) return;
            }


                 activeWrapper = wrapper;
            function wipeTooltipBody(tip) {
                 activeTip = tip;
                 if (!tip || !tip.getAttribute("data-tip")) return;
                var body = tip.querySelector(".item-tooltip-body");
                 if (body) body.innerHTML = "";
            }


            function positionTooltip(tip, wrapper) {
                 tip.classList.add("tooltip-visible");
                 tip.classList.add("tooltip-visible");
                tip.style.visibility = "hidden";
                 tip.classList.remove("tooltip-below", "tooltip-shift-right", "tooltip-shift-left");
                 tip.classList.remove("tooltip-below", "tooltip-shift-right", "tooltip-shift-left");
                 tip.style.removeProperty("--arrow-offset");
                 tip.style.removeProperty("--arrow-offset");


                 document.body.appendChild(tip);
                 tip.style.visibility = "hidden";
 
                 var rect = wrapper.getBoundingClientRect();
                 var rect = wrapper.getBoundingClientRect();
                 var tipH = tip.offsetHeight;
                 var tipH = tip.offsetHeight;
Linha 318: Linha 465:
                 tip.style.left = left + "px";
                 tip.style.left = left + "px";
                 tip.style.visibility = "";
                 tip.style.visibility = "";
            }
            function showTooltip(wrapper) {
                hideTooltip();
                var tip = wrapper.querySelector(".item-tooltip");
                if (!tip) return;
                if (tip.getAttribute("data-tip") && !fillTooltipBody(tip)) return;
                activeWrapper = wrapper;
                activeTip = tip;
                document.body.appendChild(tip);
                positionTooltip(tip, wrapper);
             }
             }


Linha 327: Linha 488:
                     activeTip.style.visibility = "";
                     activeTip.style.visibility = "";
                     activeTip.style.removeProperty("--arrow-offset");
                     activeTip.style.removeProperty("--arrow-offset");
                    wipeTooltipBody(activeTip);
                     activeWrapper.appendChild(activeTip);
                     activeWrapper.appendChild(activeTip);
                     activeTip = null;
                     activeTip = null;
Linha 334: Linha 496:


             document.addEventListener("mouseover", function (e) {
             document.addEventListener("mouseover", function (e) {
                if (e.isTrusted === false) {
                    untrustedStrikes++;
                    return;
                }
                 var wrapper = e.target.closest ? e.target.closest(".item-wrapper") : null;
                 var wrapper = e.target.closest ? e.target.closest(".item-wrapper") : null;
                 if (wrapper && wrapper !== activeWrapper) {
                 if (wrapper && wrapper !== activeWrapper) {

Edição das 19h40min de 28 de maio de 2026