Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Join the Playtest on Steam Now: SpiritVale

MediaWiki:Common.js: Difference between revisions

MediaWiki interface page
No edit summary
Tags: Mobile edit Mobile web edit
No edit summary
Tags: Mobile edit Mobile web edit
 
(5 intermediate revisions by the same user not shown)
Line 17: Line 17:


   // Versioned init guard (allows safe updates without stale blocks)
   // Versioned init guard (allows safe updates without stale blocks)
   var LEVELS_VERSION = 2;
   var LEVELS_VERSION = 6; // neutral hooks + bubble styling owned by CSS + no tick/check row
 
   if (typeof COMMON.levelsInit === "number" && COMMON.levelsInit >= LEVELS_VERSION) return;
   if (typeof COMMON.levelsInit === "number" && COMMON.levelsInit >= LEVELS_VERSION) return;
   COMMON.levelsInit = LEVELS_VERSION;
   COMMON.levelsInit = LEVELS_VERSION;


   var CARD_SEL = ".sv-gi-card, .sv-skill-card, .sv-passive-card";
  // Prefer neutral shared hooks; keep legacy class fallbacks for compatibility.
   var CARD_SEL =
    "[data-sv-card='1'], .sv-gi-card, .sv-skill-card, .sv-passive-card";


   // Accept the native range input and the custom slider variants.
   // Accept the native range input and the custom slider variants.
Line 27: Line 30:
     "input.sv-level-range[type='range'], .sv-level-range--custom, .sv-level-range[data-sv-slider='1']";
     "input.sv-level-range[type='range'], .sv-level-range--custom, .sv-level-range[data-sv-slider='1']";


   var LEVEL_BOUNDARY_SEL = ".sv-skill-level, .sv-gi-level";
   var LEVEL_BOUNDARY_SEL =
   var LEVEL_SCOPE_SEL = ".sv-gi-bottom, .sv-skill-bottom";
    "[data-sv-level-boundary='1'], .sv-skill-level, .sv-gi-level";
 
   var LEVEL_SCOPE_SEL =
    "[data-sv-level-scope='1'], .sv-gi-bottom, .sv-skill-bottom";
 
   var SERIES_SEL = "[data-series]";
   var SERIES_SEL = "[data-series]";
   var LEVEL_INIT_ATTR = "data-gi-level-init";
   var LEVEL_INIT_ATTR = "data-sv-level-init";


   var _seriesCache = typeof WeakMap !== "undefined" ? new WeakMap() : null;
   var _seriesCache = typeof WeakMap !== "undefined" ? new WeakMap() : null;
Line 115: Line 122:
   }
   }


   function getCardLevel(card, maxLevel) {
  function getCardMinLevel(card, slider, maxLevel) {
    // Prefer explicit neutral hooks, then legacy attrs, then slider attrs.
    var raw =
      card.getAttribute("data-min-level") ||
      card.getAttribute("data-minLevel") ||
      card.getAttribute("data-level-min");
 
    if (raw == null || raw === "") {
      if (slider) {
        if (isRangeInput(slider)) raw = slider.getAttribute("min");
        else if (isCustomSlider(slider))
          raw = slider.getAttribute("aria-valuemin") || slider.getAttribute("data-min");
      }
    }
 
    var min = clampInt(raw, 1, maxLevel, 1);
    if (min > maxLevel) min = maxLevel;
    return min;
  }
 
   function getCardLevel(card, minLevel, maxLevel) {
     var raw =
     var raw =
       card.getAttribute("data-level") ||
       card.getAttribute("data-level") ||
Line 123: Line 150:
         : null);
         : null);


     return clampInt(raw, 1, maxLevel, 1);
     return clampInt(raw, minLevel, maxLevel, minLevel);
  }
 
  function getStep(slider) {
    // Default = 1. Support future: data-step, or <input step="">
    var raw = null;
    if (slider) raw = slider.getAttribute("data-step") || slider.getAttribute("step");
    var s = parseInt(raw, 10);
    if (!s || isNaN(s) || s < 1) s = 1;
    return s;
   }
   }


Line 144: Line 180:
     var span = card.querySelector(".sv-level-num");
     var span = card.querySelector(".sv-level-num");
     if (span) span.textContent = String(level);
     if (span) span.textContent = String(level);
  }
  function setLevelMax(card, maxLevel) {
    var span = card.querySelector(".sv-level-max");
    if (span) span.textContent = String(maxLevel);
   }
   }


Line 149: Line 190:
     if (!scope) return;
     if (!scope) return;


    // JS arrays are 0-based; Lua uses 1-based "level".
     var index = level - 1;
     var index = level - 1;
     var nodes = scope.querySelectorAll(SERIES_SEL);
     var nodes = scope.querySelectorAll(SERIES_SEL);
Line 170: Line 212:
   }
   }


   function getCustomMin(slider) {
  function unhide(el) {
    if (!el) return;
    if (el.classList) el.classList.remove("sv-hidden");
    if (el.removeAttribute) el.removeAttribute("hidden");
    if (el.style && el.style.display === "none") el.style.display = "";
  }
 
  function hide(el) {
    if (!el) return;
    if (el.classList) el.classList.add("sv-hidden");
    if (el.setAttribute) el.setAttribute("hidden", "hidden");
  }
 
  /* ================================================================== */
  /* Custom slider helpers (bounds/percent)                              */
  /* ================================================================== */
 
   function getCustomMin(slider, fallback) {
     return clampInt(
     return clampInt(
       slider.getAttribute("aria-valuemin") || slider.getAttribute("data-min"),
       slider.getAttribute("aria-valuemin") || slider.getAttribute("data-min"),
       1,
       1,
       999,
       999,
       1
       fallback != null ? fallback : 1
     );
     );
   }
   }


   function getCustomMax(slider) {
   function getCustomMax(slider, fallback) {
     return clampInt(
     return clampInt(
       slider.getAttribute("aria-valuemax") || slider.getAttribute("data-max"),
       slider.getAttribute("aria-valuemax") || slider.getAttribute("data-max"),
       1,
       1,
       999,
       999,
       1
       fallback != null ? fallback : 1
     );
     );
   }
   }


   function getCustomValue(slider, fallback) {
  function getCustomBounds(slider, fallbackMin) {
    var min = getCustomMin(slider, fallbackMin != null ? fallbackMin : 1);
    var max = getCustomMax(slider, min);
    if (max < min) max = min;
    return { min: min, max: max };
  }
 
   function getCustomValue(slider, min, max, fallback) {
     return clampInt(
     return clampInt(
       slider.getAttribute("aria-valuenow") || slider.getAttribute("data-value"),
       slider.getAttribute("aria-valuenow") || slider.getAttribute("data-value"),
       1,
       min,
       999,
       max,
       fallback != null ? fallback : 1
       fallback != null ? fallback : min
     );
     );
  }
  function pctFromValue(min, max, value) {
    if (max === min) return 0;
    var pct = (value - min) / (max - min);
    if (pct < 0) pct = 0;
    if (pct > 1) pct = 1;
    return pct;
   }
   }


Line 204: Line 278:
   }
   }


   function updateCustomVisual(slider, value) {
  /* ================================================================== */
     var min = getCustomMin(slider);
  /* Custom slider value bubble                                          */
     var max = getCustomMax(slider);
  /* - JS owns structure + text/position only                            */
     if (max < min) max = min;
  /* - CSS owns visuals                                                  */
  /* ================================================================== */
 
   function ensureValueLabel(slider) {
    if (!slider || !slider.querySelector || !isCustomSlider(slider)) return null;
 
    var bubble = slider.querySelector(".sv-level-bubble");
    if (bubble) return bubble;
 
    bubble = document.createElement("span");
    bubble.className = "sv-level-bubble sv-hidden";
    bubble.setAttribute("hidden", "hidden");
    bubble.setAttribute("aria-hidden", "true");
 
    slider.appendChild(bubble);
    return bubble;
  }
 
  function setValueLabel(slider, value) {
     var bubble = ensureValueLabel(slider);
    if (!bubble) return;
 
     var b = getCustomBounds(slider, 1);
    bubble.textContent = String(value);
    bubble.style.left = pctFromValue(b.min, b.max, value) * 100 + "%";
  }
 
  function showValueLabel(slider) {
    if (!slider) return;
    var bubble = ensureValueLabel(slider);
     if (!bubble) return;
 
    if (slider._svBubbleTimer) {
      clearTimeout(slider._svBubbleTimer);
      slider._svBubbleTimer = null;
    }
 
    unhide(bubble);
  }
 
  function hideValueLabelSoon(slider, delayMs) {
    if (!slider) return;
    var bubble = slider.querySelector ? slider.querySelector(".sv-level-bubble") : null;
    if (!bubble) return;


     var pct = max === min ? 0 : (value - min) / (max - min);
     if (slider._svBubbleTimer) clearTimeout(slider._svBubbleTimer);
     if (pct < 0) pct = 0;
     slider._svBubbleTimer = setTimeout(function () {
     if (pct > 1) pct = 1;
      hide(bubble);
      slider._svBubbleTimer = null;
     }, delayMs != null ? delayMs : 450);
  }


     var left = pct * 100;
  function updateCustomVisual(slider, value) {
    var b = getCustomBounds(slider, 1);
     var left = pctFromValue(b.min, b.max, value) * 100;


     var thumb = slider.querySelector(".sv-level-thumb");
     var thumb = slider.querySelector(".sv-level-thumb");
Line 220: Line 342:
     if (thumb && thumb.style) thumb.style.left = left + "%";
     if (thumb && thumb.style) thumb.style.left = left + "%";
     if (fill && fill.style) fill.style.width = left + "%";
     if (fill && fill.style) fill.style.width = left + "%";
    setValueLabel(slider, value);
   }
   }


   function setCustomValue(slider, value) {
   function setCustomValue(slider, value, min, max) {
     slider.setAttribute("aria-valuenow", String(value));
     slider.setAttribute("aria-valuenow", String(value));
     slider.setAttribute("data-value", String(value));
     slider.setAttribute("data-value", String(value));
    // Helpful SR text (doesn't affect visuals)
    slider.setAttribute("aria-valuetext", "Level " + String(value) + " of " + String(max));
     updateCustomVisual(slider, value);
     updateCustomVisual(slider, value);
  }
  function snapToStep(raw, min, max, step) {
    if (step < 1) step = 1;
    var x = raw;
    if (x < min) x = min;
    if (x > max) x = max;
    var snapped = min + Math.round((x - min) / step) * step;
    if (snapped < min) snapped = min;
    if (snapped > max) snapped = max;
    return snapped;
   }
   }


   function valueFromClientX(slider, clientX) {
   function valueFromClientX(slider, clientX) {
     var rect = slider.getBoundingClientRect();
     var rect = slider.getBoundingClientRect();
     var min = getCustomMin(slider);
     var b = getCustomBounds(slider, 1);
    var max = getCustomMax(slider);
    if (max < min) max = min;


     var w = rect.width || 1;
     var w = rect.width || 1;
Line 239: Line 377:
     if (x > 1) x = 1;
     if (x > 1) x = 1;


     var raw = min + x * (max - min);
     var raw = b.min + x * (b.max - b.min);
     var rounded = Math.round(raw);
    return snapToStep(raw, b.min, b.max, getStep(slider));
     return clampInt(rounded, min, max, min);
  }
 
  /* ================================================================== */
  /* End-of-bar value label (right-side value)                          */
  /* ================================================================== */
 
  function ensureEndValueLabel(card, slider) {
     var wrap = null;
    if (slider) wrap = closest(slider, ".sv-level-slider");
    if (!wrap && card && card.querySelector) wrap = card.querySelector(".sv-level-slider");
    if (!wrap) return null;
 
    var out = wrap.querySelector(".sv-level-endvalue");
     if (out) return out;
 
    out = document.createElement("span");
    out.className = "sv-level-endvalue";
    out.setAttribute("aria-hidden", "true"); // slider already exposes aria-valuetext
    wrap.appendChild(out);
    return out;
   }
   }


   function unhide(el) {
   function setEndValueLabel(card, slider, value) {
     if (!el) return;
     var out = ensureEndValueLabel(card, slider);
     if (el.classList) el.classList.remove("sv-hidden");
     if (out) out.textContent = String(value);
     if (el.removeAttribute) el.removeAttribute("hidden");
  }
     if (el.style && el.style.display === "none") el.style.display = "";
 
  /* ================================================================== */
  /* Core apply / init                                                    */
  /* ================================================================== */
 
  function scheduleApply(card, rawLevel) {
     if (!card) return;
 
    card._svLevelNext = rawLevel;
    if (card._svLevelRaf) return;
 
     if (window.requestAnimationFrame) {
      card._svLevelRaf = requestAnimationFrame(function () {
        card._svLevelRaf = null;
        var v = card._svLevelNext;
        card._svLevelNext = null;
        applyLevelToCard(card, v);
      });
      return;
    }
 
    card._svLevelRaf = setTimeout(function () {
      card._svLevelRaf = null;
      var v = card._svLevelNext;
      card._svLevelNext = null;
      applyLevelToCard(card, v);
    }, 0);
   }
   }


Line 256: Line 439:
     var maxLevel = getCardMaxLevel(card);
     var maxLevel = getCardMaxLevel(card);
     var slider = getLevelSlider(card);
     var slider = getLevelSlider(card);
     var level = clampInt(rawLevel, 1, maxLevel, getCardLevel(card, maxLevel));
    var minLevel = getCardMinLevel(card, slider, maxLevel);
 
     var level = clampInt(rawLevel, minLevel, maxLevel, getCardLevel(card, minLevel, maxLevel));


     card.setAttribute("data-level", String(level));
     card.setAttribute("data-level", String(level));
     setLevelNumber(card, level);
     setLevelNumber(card, level);
    setLevelMax(card, maxLevel);


     if (slider) {
     if (slider) {
Line 267: Line 453:
     }
     }


     if (slider && maxLevel > 1) {
     if (slider) {
       if (isRangeInput(slider)) {
       if (isRangeInput(slider)) {
         slider.setAttribute("min", "1");
         slider.setAttribute("min", String(minLevel));
         slider.setAttribute("max", String(maxLevel));
         slider.setAttribute("max", String(maxLevel));
        slider.setAttribute("step", String(getStep(slider)));
        slider.setAttribute("aria-valuetext", "Level " + String(level) + " of " + String(maxLevel));
         if (String(slider.value) !== String(level)) slider.value = String(level);
         if (String(slider.value) !== String(level)) slider.value = String(level);
       } else if (isCustomSlider(slider)) {
       } else if (isCustomSlider(slider)) {
         setCustomBounds(slider, 1, maxLevel);
         setCustomBounds(slider, minLevel, maxLevel);
         setCustomValue(slider, level);
         setCustomValue(slider, level, minLevel, maxLevel);
       }
       }
    } else if (slider && isCustomSlider(slider)) {
      setCustomBounds(slider, 1, maxLevel);
      setCustomValue(slider, level);
     }
     }
    setEndValueLabel(card, slider, level);


     var boundary = getLevelBoundary(slider);
     var boundary = getLevelBoundary(slider);
Line 298: Line 485:
       var maxLevel = getCardMaxLevel(card);
       var maxLevel = getCardMaxLevel(card);
       var slider = getLevelSlider(card);
       var slider = getLevelSlider(card);
      var minLevel = getCardMinLevel(card, slider, maxLevel);
      var start = getCardLevel(card, minLevel, maxLevel);


      var start = getCardLevel(card, maxLevel);
       if (slider && maxLevel > minLevel) {
       if (slider && maxLevel > 1) {
         if (isRangeInput(slider)) start = clampInt(slider.value, minLevel, maxLevel, start);
         if (isRangeInput(slider)) start = slider.value;
         else if (isCustomSlider(slider)) start = getCustomValue(slider, minLevel, maxLevel, start);
         else if (isCustomSlider(slider)) start = getCustomValue(slider, start);
       }
       }


Line 310: Line 499:
   }
   }


  /* ================================================================== */
  /* Events                                                              */
  /* ================================================================== */
  // Native range inputs
   document.addEventListener(
   document.addEventListener(
     "input",
     "input",
Line 320: Line 514:
       if (!card) return;
       if (!card) return;


       applyLevelToCard(card, t.value);
       scheduleApply(card, t.value);
     },
     },
     true
     true
   );
   );


  // Custom slider pointer interaction (click anywhere + drag)
   document.addEventListener(
   document.addEventListener(
     "pointerdown",
     "pointerdown",
     function (e) {
     function (e) {
      if (e.button != null && e.button !== 0) return; // primary only
       var slider =
       var slider =
         e.target && e.target.closest
         e.target && e.target.closest
Line 348: Line 545:
       }
       }


       applyLevelToCard(card, valueFromClientX(slider, e.clientX));
       showValueLabel(slider);
      scheduleApply(card, valueFromClientX(slider, e.clientX));
     },
     },
     true
     true
Line 359: Line 557:
       if (e.pointerId !== _drag.pointerId) return;
       if (e.pointerId !== _drag.pointerId) return;
       e.preventDefault();
       e.preventDefault();
       applyLevelToCard(_drag.card, valueFromClientX(_drag.slider, e.clientX));
 
       showValueLabel(_drag.slider);
      scheduleApply(_drag.card, valueFromClientX(_drag.slider, e.clientX));
     },
     },
     true
     true
Line 373: Line 573:
       } catch (err) {}
       } catch (err) {}
     }
     }
    hideValueLabelSoon(_drag.slider, 650);
     _drag = null;
     _drag = null;
   }
   }
Line 378: Line 580:
   document.addEventListener("pointerup", endDrag, true);
   document.addEventListener("pointerup", endDrag, true);
   document.addEventListener("pointercancel", endDrag, true);
   document.addEventListener("pointercancel", endDrag, true);
  // Mouse-only slider interaction:
  // - Remove keyboard-driven adjustments on custom sliders
  // - Block native <input type="range"> from changing via keyboard (if present)
  var _SV_BLOCK_KEYS = {
    ArrowLeft: 1,
    ArrowRight: 1,
    ArrowUp: 1,
    ArrowDown: 1,
    Left: 1,
    Right: 1,
    Up: 1,
    Down: 1,
    Home: 1,
    End: 1,
    PageUp: 1,
    PageDown: 1
  };


   document.addEventListener(
   document.addEventListener(
     "keydown",
     "keydown",
     function (e) {
     function (e) {
      var key = e && e.key;
      if (!_SV_BLOCK_KEYS[key]) return;
      var el = document.activeElement;
      if (!el) return;
      // Native range inputs (keep mouse drag, disable keyboard nudges)
      if (isRangeInput(el) && el.classList && el.classList.contains("sv-level-range")) {
        e.preventDefault();
        return;
      }
      // Custom sliders (we keep focus behaviors, but no keyboard changes)
      var slider = closest(el, ".sv-level-range--custom, .sv-level-range[data-sv-slider='1']");
      if (slider) {
        e.preventDefault();
        return;
      }
    },
    true
  );
  // Show bubble on focus (discoverability), hide on blur
  document.addEventListener(
    "focusin",
    function () {
       var el = document.activeElement;
       var el = document.activeElement;
       if (!el || !el.closest) return;
       if (!el || !el.closest) return;
       var slider = el.closest(".sv-level-range--custom, .sv-level-range[data-sv-slider='1']");
       var slider = el.closest(".sv-level-range--custom, .sv-level-range[data-sv-slider='1']");
       if (!slider) return;
       if (!slider) return;


       var card = closest(slider, CARD_SEL);
       var b = getCustomBounds(slider, 1);
       if (!card) return;
       var v = getCustomValue(slider, b.min, b.max, b.min);


       var min = getCustomMin(slider);
       setValueLabel(slider, v);
       var max = getCustomMax(slider);
       showValueLabel(slider);
      if (max < min) max = min;
    },
    true
  );


       var cur = getCustomValue(slider, getCardLevel(card, max));
  document.addEventListener(
       var next = cur;
    "focusout",
    function (e) {
       var t = e.target;
      if (!t || !t.closest) return;
      var slider = t.closest(".sv-level-range--custom, .sv-level-range[data-sv-slider='1']");
       if (!slider) return;


       if (e.key === "ArrowLeft" || e.key === "Left" || e.key === "ArrowDown") {
       hideValueLabelSoon(slider, 300);
        next = cur - 1;
      } else if (e.key === "ArrowRight" || e.key === "Right" || e.key === "ArrowUp") {
        next = cur + 1;
      } else if (e.key === "Home") {
        next = min;
      } else if (e.key === "End") {
        next = max;
      } else if (e.key === "PageDown") {
        next = cur - 5;
      } else if (e.key === "PageUp") {
        next = cur + 5;
      } else {
        return;
      }
 
      e.preventDefault();
      next = clampInt(next, min, max, cur);
      applyLevelToCard(card, next);
     },
     },
     true
     true
Line 440: Line 674:
     initAllLevels(document);
     initAllLevels(document);
   }
   }
})();
/* ====================================================================== */
/* LEGACY POPUPS (disabled)                                              */
/*                                                                        */
/* This section is intentionally isolated so it can be deleted in one cut. */
/* To temporarily re-enable legacy behavior, set:                          */
/*  SV.common.enableLegacyPopups = true                                  */
/* ====================================================================== */
(function () {
  var SV = (window.SV = window.SV || {});
  var COMMON = (SV.common = SV.common || {});
  if (!COMMON.enableLegacyPopups) return;
  // Place any legacy popup code blocks here verbatim if needed during transition.
})();
})();


Line 467: Line 684:
   var COMMON = (SV.common = SV.common || {});
   var COMMON = (SV.common = SV.common || {});


   var UPOP_VERSION = 31; // Universal Popups v3.1
  // Bumped only because we changed positioning margins (safe cache-bust).
   var UPOP_VERSION = 32; // Universal Popups v3.2
   if (typeof COMMON.universalPopupsInit === "number" && COMMON.universalPopupsInit >= UPOP_VERSION) return;
   if (typeof COMMON.universalPopupsInit === "number" && COMMON.universalPopupsInit >= UPOP_VERSION) return;
   COMMON.universalPopupsInit = UPOP_VERSION;
   COMMON.universalPopupsInit = UPOP_VERSION;
Line 740: Line 958:


     if (opts.pinned) {
     if (opts.pinned) {
       head.addEventListener("click", function (e) {
       head.addEventListener(
        e.preventDefault();
        "click",
        hidePopup();
        function (e) {
      }, { once: true });
          e.preventDefault();
          hidePopup();
        },
        { once: true }
      );
     }
     }


Line 762: Line 984:
       var vw = window.innerWidth || document.documentElement.clientWidth || 0;
       var vw = window.innerWidth || document.documentElement.clientWidth || 0;
       var vh = window.innerHeight || document.documentElement.clientHeight || 0;
       var vh = window.innerHeight || document.documentElement.clientHeight || 0;
       var margin = 10;
 
       var gap = 12;
      var tight = vw <= 520;
       var margin = tight ? 18 : 10;
       var gap = tight ? 14 : 12;


       var pr = el.getBoundingClientRect();
       var pr = el.getBoundingClientRect();
Line 777: Line 1,001:
       } else if (state.anchorKind === "finger") {
       } else if (state.anchorKind === "finger") {
         left = (vw - w) / 2;
         left = (vw - w) / 2;
         var y = state.anchorY || (vh / 2);
         var y = state.anchorY || vh / 2;
         top = y - h - gap;
         top = y - h - gap;
         if (top < margin) top = y + gap;
         if (top < margin) top = y + gap;
Line 784: Line 1,008:
         var tr = trigger.getBoundingClientRect();
         var tr = trigger.getBoundingClientRect();
         var isIconish = (tr.width || 0) <= 40;
         var isIconish = (tr.width || 0) <= 40;
         left = isIconish ? (tr.right - w) : tr.left;
         left = isIconish ? tr.right - w : tr.left;
         top = tr.bottom + gap;
         top = tr.bottom + gap;
         left = clamp(left, margin, Math.max(margin, vw - w - margin));
         left = clamp(left, margin, Math.max(margin, vw - w - margin));
Line 871: Line 1,095:
     }
     }


     if (!attrSize) size = (mode === "click") ? "lg" : "sm";
     if (!attrSize) size = mode === "click" ? "lg" : "sm";


     if (!HOVER_CAPABLE && mode === "hover") {
     if (!HOVER_CAPABLE && mode === "hover") {
Line 878: Line 1,102:
     }
     }


if (isDef) {
    if (isDef) {
  var tipText = getDefTipText(trigger);
      var tipText = getDefTipText(trigger);
  if (!tipText) return null;
      if (!tipText) return null;


  var linkTitle = getDefLinkTitle(trigger);
      var linkTitle = getDefLinkTitle(trigger);


  var label = trigger.querySelector ? trigger.querySelector(".sv-def-text") : null;
      var label = trigger.querySelector ? trigger.querySelector(".sv-def-text") : null;
  var titleText = label ? String(label.textContent || "").trim()
      var titleText = label ? String(label.textContent || "").trim() : String(trigger.textContent || "").trim();
                        : String(trigger.textContent || "").trim();
      if (!titleText) titleText = "Definition";
  if (!titleText) titleText = "Definition";


  return {
      return {
    pinned: (mode === "click"),
        pinned: mode === "click",
    size: size,
        size: size,
    title: titleText,
        title: titleText,
    titleLink: linkTitle ? buildHeaderLink(linkTitle, titleText) : null,
        titleLink: linkTitle ? buildHeaderLink(linkTitle, titleText) : null,
    bodyText: tipText,
        bodyText: tipText,
    bodyPre: true,
        bodyPre: true,
    bodyNode: null
        bodyNode: null
  };
      };
}
    }


     var source = getContentNodeFromTrigger(trigger);
     var source = getContentNodeFromTrigger(trigger);
Line 904: Line 1,127:


     return {
     return {
       pinned: (mode === "click"),
       pinned: mode === "click",
       size: size,
       size: size,
       title: guessTitle(trigger, source),
       title: guessTitle(trigger, source),
Line 914: Line 1,137:
   }
   }


   window.addEventListener("pointerdown", function (e) {
   window.addEventListener(
    if (!e) return;
    "pointerdown",
    function (e) {
      if (!e) return;
 
      if (isInsidePopup(e.target)) return;


    if (isInsidePopup(e.target)) return;
      var trigger = findTrigger(e.target);
      if (!trigger) return;


    var trigger = findTrigger(e.target);
      var opts = resolveOpts(trigger);
    if (!trigger) return;
      if (!opts) return;


    var opts = resolveOpts(trigger);
      if (isSummaryTrigger(trigger)) e.preventDefault();
    if (!opts) return;


    if (isSummaryTrigger(trigger)) e.preventDefault();
      state.anchorKind = !HOVER_CAPABLE || (e.pointerType && e.pointerType !== "mouse") ? "finger" : "trigger";
      state.anchorX = typeof e.clientX === "number" ? e.clientX : 0;
      state.anchorY = typeof e.clientY === "number" ? e.clientY : 0;


    state.anchorKind = (!HOVER_CAPABLE || (e.pointerType && e.pointerType !== "mouse")) ? "finger" : "trigger";
      if (HOVER_CAPABLE && !opts.pinned && (e.pointerType === "mouse" || !e.pointerType)) {
    state.anchorX = (typeof e.clientX === "number") ? e.clientX : 0;
        e.stopPropagation();
    state.anchorY = (typeof e.clientY === "number") ? e.clientY : 0;
        return;
      }


    if (HOVER_CAPABLE && !opts.pinned && (e.pointerType === "mouse" || !e.pointerType)) {
      e.preventDefault();
       e.stopPropagation();
       e.stopPropagation();
      return;
    }


    e.preventDefault();
      if (state.open && state.pinned && state.trigger === trigger) {
    e.stopPropagation();
        hidePopup();
        return;
      }


    if (state.open && state.pinned && state.trigger === trigger) {
      openPopup(trigger, opts);
      hidePopup();
    },
      return;
     true
     }
  );


     openPopup(trigger, opts);
  window.addEventListener(
  }, true);
    "mouseover",
     function (e) {
      if (!HOVER_CAPABLE) return;
      if (isInsidePopup(e.target)) return;


  window.addEventListener("mouseover", function (e) {
      var trigger = findTrigger(e.target);
    if (!HOVER_CAPABLE) return;
      if (!trigger) {
    if (isInsidePopup(e.target)) return;
        if (state.open && !state.pinned) hidePopup();
        return;
      }


    var trigger = findTrigger(e.target);
      var opts = resolveOpts(trigger);
    if (!trigger) {
       if (!opts || opts.pinned) return;
       if (state.open && !state.pinned) hidePopup();
      return;
    }


    var opts = resolveOpts(trigger);
      state.anchorKind = "trigger";
    if (!opts || opts.pinned) return;


    state.anchorKind = "trigger";
      e.stopPropagation();
      clearTimeout(state.hideTimer);
      state.hideTimer = 0;


    e.stopPropagation();
      openPopup(trigger, opts);
     clearTimeout(state.hideTimer);
     },
     state.hideTimer = 0;
     true
  );


     openPopup(trigger, opts);
  window.addEventListener(
  }, true);
     "mouseout",
    function (e) {
      if (!HOVER_CAPABLE) return;
      if (!state.open || state.pinned) return;


  window.addEventListener("mouseout", function (e) {
      var trigger = findTrigger(e.target);
    if (!HOVER_CAPABLE) return;
      if (!trigger || trigger !== state.trigger) return;
    if (!state.open || state.pinned) return;


    var trigger = findTrigger(e.target);
      e.stopPropagation();
    if (!trigger || trigger !== state.trigger) return;


    e.stopPropagation();
      clearTimeout(state.hideTimer);
      state.hideTimer = setTimeout(function () {
        if (state.open && !state.pinned) hidePopup();
      }, 80);
    },
    true
  );


     clearTimeout(state.hideTimer);
  window.addEventListener(
     state.hideTimer = setTimeout(function () {
     "click",
       if (state.open && !state.pinned) hidePopup();
     function (e) {
    }, 80);
       if (!state.open) return;
  }, true);
      if (isInsidePopup(e.target)) return;


  window.addEventListener("click", function (e) {
      var trigger = findTrigger(e.target);
    if (!state.open) return;
      if (trigger) {
    if (isInsidePopup(e.target)) return;
        e.stopPropagation();
        return;
      }


    var trigger = findTrigger(e.target);
      if (state.pinned || !HOVER_CAPABLE) {
    if (trigger) {
        hidePopup();
      e.stopPropagation();
        e.stopPropagation();
       return;
       }
     }
     },
    true
  );


     if (state.pinned || !HOVER_CAPABLE) {
  window.addEventListener(
      hidePopup();
     "keydown",
      e.stopPropagation();
    function (e) {
    }
      if (e.key !== "Escape") return;
  }, true);
      if (state.open) {
        hidePopup();
        e.stopPropagation();
      }
    },
    true
  );


   window.addEventListener("keydown", function (e) {
   window.addEventListener(
    if (e.key !== "Escape") return;
    "scroll",
    if (state.open) {
    function () {
      hidePopup();
      if (!state.open || !state.trigger) return;
      e.stopPropagation();
      positionPopup(state.trigger);
     }
    },
   }, true);
     true
   );


   window.addEventListener("scroll", function () {
   window.addEventListener(
    if (!state.open || !state.trigger) return;
    "resize",
    positionPopup(state.trigger);
    function () {
  }, true);
      if (!state.open || !state.trigger) return;
 
      positionPopup(state.trigger);
  window.addEventListener("resize", function () {
    },
     if (!state.open || !state.trigger) return;
     true
    positionPopup(state.trigger);
   );
   }, true);


   function stripDefTitles(root) {
   function stripDefTitles(root) {
Line 1,031: Line 1,282:


   if (document.readyState === "loading") {
   if (document.readyState === "loading") {
     document.addEventListener("DOMContentLoaded", function () { stripDefTitles(document); });
     document.addEventListener("DOMContentLoaded", function () {
      stripDefTitles(document);
    });
   } else {
   } else {
     stripDefTitles(document);
     stripDefTitles(document);