MediaWiki:Common.js: Difference between revisions
MediaWiki interface page
More actions
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 = | 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- | 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, | 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"), | ||
min, | |||
max, | |||
fallback != null ? fallback : | 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 | /* ================================================================== */ | ||
var | /* Custom slider value bubble */ | ||
var max = | /* - JS owns structure + text/position only */ | ||
if ( | /* - 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; | |||
if (slider._svBubbleTimer) clearTimeout(slider._svBubbleTimer); | |||
slider._svBubbleTimer = setTimeout(function () { | |||
hide(bubble); | |||
slider._svBubbleTimer = null; | |||
}, delayMs != null ? delayMs : 450); | |||
} | |||
var left = | 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 | var b = getCustomBounds(slider, 1); | ||
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 | return snapToStep(raw, b.min, b.max, getStep(slider)); | ||
return | } | ||
/* ================================================================== */ | |||
/* 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 | function setEndValueLabel(card, slider, value) { | ||
var out = ensureEndValueLabel(card, slider); | |||
if ( | if (out) out.textContent = String(value); | ||
if ( | } | ||
if ( | |||
/* ================================================================== */ | |||
/* 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, | 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 | if (slider) { | ||
if (isRangeInput(slider)) { | if (isRangeInput(slider)) { | ||
slider.setAttribute("min", | 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, | setCustomBounds(slider, minLevel, maxLevel); | ||
setCustomValue(slider, level); | setCustomValue(slider, level, minLevel, maxLevel); | ||
} | } | ||
} | } | ||
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); | |||
if (slider && maxLevel > minLevel) { | |||
if (slider && maxLevel > | 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; | ||
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: | ||
} | } | ||
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(); | ||
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 | var b = getCustomBounds(slider, 1); | ||
var v = getCustomValue(slider, b.min, b.max, b.min); | |||
setValueLabel(slider, v); | |||
showValueLabel(slider); | |||
}, | |||
true | |||
); | |||
var | document.addEventListener( | ||
"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; | |||
hideValueLabelSoon(slider, 300); | |||
}, | }, | ||
true | true | ||
| Line 440: | Line 674: | ||
initAllLevels(document); | initAllLevels(document); | ||
} | } | ||
})(); | })(); | ||
| Line 467: | Line 684: | ||
var COMMON = (SV.common = SV.common || {}); | var COMMON = (SV.common = SV.common || {}); | ||
var UPOP_VERSION = | // 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( | ||
"click", | |||
function (e) { | |||
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 || | 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 ? | 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 = | 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); | |||
if (!tipText) return null; | |||
var linkTitle = getDefLinkTitle(trigger); | |||
var label = trigger.querySelector ? trigger.querySelector(".sv-def-text") : null; | |||
var titleText = label ? String(label.textContent || "").trim() : String(trigger.textContent || "").trim(); | |||
if (!titleText) titleText = "Definition"; | |||
return { | |||
pinned: mode === "click", | |||
size: size, | |||
title: titleText, | |||
titleLink: linkTitle ? buildHeaderLink(linkTitle, titleText) : null, | |||
bodyText: tipText, | |||
bodyPre: true, | |||
bodyNode: null | |||
}; | |||
} | } | ||
var source = getContentNodeFromTrigger(trigger); | var source = getContentNodeFromTrigger(trigger); | ||
| Line 904: | Line 1,127: | ||
return { | return { | ||
pinned: | 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( | ||
"pointerdown", | |||
function (e) { | |||
if (!e) return; | |||
if (isInsidePopup(e.target)) return; | |||
var trigger = findTrigger(e.target); | |||
if (!trigger) return; | |||
var opts = resolveOpts(trigger); | |||
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; | |||
if (HOVER_CAPABLE && !opts.pinned && (e.pointerType === "mouse" || !e.pointerType)) { | |||
e.stopPropagation(); | |||
return; | |||
} | |||
e.preventDefault(); | |||
e.stopPropagation(); | e.stopPropagation(); | ||
if (state.open && state.pinned && state.trigger === trigger) { | |||
hidePopup(); | |||
return; | |||
} | |||
openPopup(trigger, opts); | |||
}, | |||
true | |||
); | |||
window.addEventListener( | |||
"mouseover", | |||
function (e) { | |||
if (!HOVER_CAPABLE) return; | |||
if (isInsidePopup(e.target)) return; | |||
var trigger = findTrigger(e.target); | |||
if (!trigger) { | |||
if (state.open && !state.pinned) hidePopup(); | |||
return; | |||
} | |||
var opts = resolveOpts(trigger); | |||
if (!opts || opts.pinned) return; | |||
if ( | |||
state.anchorKind = "trigger"; | |||
e.stopPropagation(); | |||
clearTimeout(state.hideTimer); | |||
state.hideTimer = 0; | |||
openPopup(trigger, opts); | |||
}, | |||
true | |||
); | |||
window.addEventListener( | |||
"mouseout", | |||
function (e) { | |||
if (!HOVER_CAPABLE) return; | |||
if (!state.open || state.pinned) return; | |||
var trigger = findTrigger(e.target); | |||
if (!trigger || trigger !== state.trigger) return; | |||
e.stopPropagation(); | |||
clearTimeout(state.hideTimer); | |||
state.hideTimer = setTimeout(function () { | |||
if (state.open && !state.pinned) hidePopup(); | |||
}, 80); | |||
}, | |||
true | |||
); | |||
window.addEventListener( | |||
"click", | |||
if (state.open | function (e) { | ||
if (!state.open) return; | |||
if (isInsidePopup(e.target)) return; | |||
var trigger = findTrigger(e.target); | |||
if (trigger) { | |||
e.stopPropagation(); | |||
return; | |||
} | |||
if (state.pinned || !HOVER_CAPABLE) { | |||
hidePopup(); | |||
e.stopPropagation(); | |||
} | |||
} | }, | ||
true | |||
); | |||
if (state. | window.addEventListener( | ||
"keydown", | |||
function (e) { | |||
if (e.key !== "Escape") return; | |||
if (state.open) { | |||
hidePopup(); | |||
e.stopPropagation(); | |||
} | |||
}, | |||
true | |||
); | |||
window.addEventListener(" | window.addEventListener( | ||
"scroll", | |||
function () { | |||
if (!state.open || !state.trigger) return; | |||
positionPopup(state.trigger); | |||
}, | |||
true | |||
); | |||
window.addEventListener(" | window.addEventListener( | ||
"resize", | |||
function () { | |||
if (!state.open || !state.trigger) return; | |||
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); | ||