MediaWiki:Common.js: Difference between revisions
MediaWiki interface page
More actions
No edit summary |
No edit summary |
||
| Line 352: | Line 352: | ||
function initAllDefs(root) { | function initAllDefs(root) { | ||
var container = root || document; | var container = root || document; | ||
var defs = container.querySelectorAll(DEF_SEL + "[title]"); | var defs = container.querySelectorAll(DEF_SEL + "[title]"); | ||
| Line 384: | Line 381: | ||
var SV = (window.SV = window.SV || {}); | var SV = (window.SV = window.SV || {}); | ||
var COMMON = (SV.common = SV.common || {}); | var COMMON = (SV.common = SV.common || {}); | ||
if (COMMON.levelsInit) return; | |||
COMMON.levelsInit = | // --------- VERSIONED INIT (fixes "old script blocks new script") ----- | ||
var LEVELS_VERSION = 2; | |||
// If an older Common.js set levelsInit=1, we still want THIS one to run. | |||
if (typeof COMMON.levelsInit === "number" && COMMON.levelsInit >= LEVELS_VERSION) return; | |||
COMMON.levelsInit = LEVELS_VERSION; | |||
var CARD_SEL = ".sv-gi-card, .sv-skill-card, .sv-passive-card"; | var CARD_SEL = ".sv-gi-card, .sv-skill-card, .sv-passive-card"; | ||
// Be a bit forgiving: accept the custom slider even if the data attr changes. | |||
var LEVEL_RANGE_SEL = | var LEVEL_RANGE_SEL = | ||
"input.sv-level-range[type='range'], .sv-level-range--custom[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 = ".sv-skill-level, .sv-gi-level"; | ||
var LEVEL_SCOPE_SEL = ".sv-gi-bottom, .sv-skill-bottom"; | var LEVEL_SCOPE_SEL = ".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 _seriesCache = typeof WeakMap !== "undefined" ? new WeakMap() : null; | var _seriesCache = typeof WeakMap !== "undefined" ? new WeakMap() : null; | ||
| Line 454: | Line 459: | ||
function isCustomSlider(el) { | function isCustomSlider(el) { | ||
if (!el || !el.getAttribute) return false; | |||
if (el.getAttribute("data-sv-slider") === "1") return true; | |||
// fallback: class-based detection | |||
return !!(el.classList && el.classList.contains("sv-level-range--custom")); | |||
} | |||
function parseMaxFromUi(card) { | |||
// fallback if attributes drift: parse "... / 10" out of the UI text | |||
var ui = card && card.querySelector ? card.querySelector(".sv-level-ui") : null; | |||
if (!ui) return null; | |||
var m = String(ui.textContent || "").match(/\/\s*(\d+)/); | |||
return m ? m[1] : null; | |||
} | } | ||
function getCardMaxLevel(card) { | function getCardMaxLevel(card) { | ||
var raw = | |||
card.getAttribute("data-max-level") || | |||
card.getAttribute("data-maxLevel") || | |||
card.getAttribute("data-max") || | |||
card.getAttribute("data-level-max") || | |||
parseMaxFromUi(card); | |||
return clampInt(raw, 1, 999, 1); | |||
} | } | ||
function getCardLevel(card, maxLevel) { | function getCardLevel(card, maxLevel) { | ||
var raw = | |||
card.getAttribute("data-level") || | |||
card.getAttribute("data-gi-level") || | |||
(card.querySelector && card.querySelector(".sv-level-num") | |||
? card.querySelector(".sv-level-num").textContent | |||
: null); | |||
return clampInt(raw, 1, maxLevel, 1); | |||
} | } | ||
| Line 581: | Line 611: | ||
var rounded = Math.round(raw); | var rounded = Math.round(raw); | ||
return clampInt(rounded, min, max, min); | return clampInt(rounded, min, max, min); | ||
} | |||
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 = ""; | |||
} | } | ||
| Line 592: | Line 629: | ||
card.setAttribute("data-level", String(level)); | card.setAttribute("data-level", String(level)); | ||
setLevelNumber(card, level); | setLevelNumber(card, level); | ||
if (slider) { | |||
unhide(slider); | |||
var wrap = closest(slider, ".sv-level-slider"); | |||
if (wrap) unhide(wrap); | |||
} | |||
if (slider && maxLevel > 1) { | if (slider && maxLevel > 1) { | ||
| Line 602: | Line 645: | ||
setCustomValue(slider, level); | setCustomValue(slider, level); | ||
} | } | ||
} else if (slider && isCustomSlider(slider)) { | |||
// Even if max==1, keep the visual consistent | |||
setCustomBounds(slider, 1, maxLevel); | |||
setCustomValue(slider, level); | |||
} | } | ||
| Line 615: | Line 662: | ||
for (var i = 0; i < cards.length; i++) { | for (var i = 0; i < cards.length; i++) { | ||
var card = cards[i]; | var card = cards[i]; | ||
// Versioned per-card init (fixes "old init stamp blocks new logic") | |||
var stamped = clampInt(card.getAttribute(LEVEL_INIT_ATTR), 0, 999, 0); | |||
if (stamped >= LEVELS_VERSION) continue; | |||
var maxLevel = getCardMaxLevel(card); | var maxLevel = getCardMaxLevel(card); | ||
| Line 627: | Line 677: | ||
applyLevelToCard(card, start); | applyLevelToCard(card, start); | ||
card.setAttribute( | card.setAttribute(LEVEL_INIT_ATTR, String(LEVELS_VERSION)); | ||
} | } | ||
} | } | ||
| Line 651: | Line 701: | ||
var slider = | var slider = | ||
e.target && e.target.closest | e.target && e.target.closest | ||
? e.target.closest(".sv-level-range--custom[data-sv-slider='1']") | ? e.target.closest(".sv-level-range--custom, .sv-level-range[data-sv-slider='1']") | ||
: null; | : null; | ||
if (!slider) return; | if (!slider) return; | ||
| Line 706: | Line 756: | ||
if (!el || !el.closest) return; | if (!el || !el.closest) return; | ||
var slider = el.closest(".sv-level-range--custom[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; | ||
| Line 749: | Line 799: | ||
initLevels(root); | initLevels(root); | ||
} | } | ||
// Expose for debugging / manual re-init if needed | |||
COMMON.initAllLevels = initAllLevels; | |||
if (window.mw && mw.hook) { | if (window.mw && mw.hook) { | ||
| Line 780: | Line 833: | ||
var CARD_SEL = ".sv-gi-card, .sv-skill-card, .sv-passive-card"; | var CARD_SEL = ".sv-gi-card, .sv-skill-card, .sv-passive-card"; | ||
var POPUP_BTN_SEL = | var POPUP_BTN_SEL = | ||
".sv-tip-btn[data-sv-toggle='1'], .sv-disclose-btn[data-sv-toggle='1']"; | ".sv-tip-btn[data-sv-toggle='1'], .sv-disclose-btn[data-sv-toggle='1']"; | ||
var POPUP_DETAILS_SEL = "details.sv-tip, details.sv-disclose"; | var POPUP_DETAILS_SEL = "details.sv-tip, details.sv-disclose"; | ||
var POPUP_SUMMARY_SEL = "details.sv-tip > summary, details.sv-disclose > summary"; | var POPUP_SUMMARY_SEL = "details.sv-tip > summary, details.sv-disclose > summary"; | ||
var POPUP_WRAP_SEL = ".sv-tip, .sv-disclose"; | var POPUP_WRAP_SEL = ".sv-tip, .sv-disclose"; | ||
var POPUP_POP_SEL = ".sv-tip-pop, .sv-disclose-pop"; | var POPUP_POP_SEL = ".sv-tip-pop, .sv-disclose-pop"; | ||
| Line 807: | Line 857: | ||
visible: false, | visible: false, | ||
pinned: false, | pinned: false, | ||
anchor: null, | anchor: null, | ||
lastX: 0, | lastX: 0, | ||
lastY: 0, | lastY: 0, | ||
| Line 882: | Line 932: | ||
function safeIdSelector(id) { | function safeIdSelector(id) { | ||
return "#" + String(id).replace(/([ !"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~])/g, "\\$1"); | return "#" + String(id).replace(/([ !"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~])/g, "\\$1"); | ||
} | } | ||
| Line 890: | Line 938: | ||
if (!trigger) return null; | if (!trigger) return null; | ||
if (trigger.tagName === "SUMMARY") { | if (trigger.tagName === "SUMMARY") { | ||
var det = closest(trigger, POPUP_DETAILS_SEL); | var det = closest(trigger, POPUP_DETAILS_SEL); | ||
| Line 902: | Line 949: | ||
} | } | ||
var id = trigger.getAttribute ? trigger.getAttribute("aria-controls") : ""; | var id = trigger.getAttribute ? trigger.getAttribute("aria-controls") : ""; | ||
if (id) { | if (id) { | ||
| Line 923: | Line 969: | ||
} | } | ||
var w = closest(trigger, POPUP_WRAP_SEL); | var w = closest(trigger, POPUP_WRAP_SEL); | ||
if (w) { | if (w) { | ||
| Line 939: | Line 984: | ||
if (!node) return true; | if (!node) return true; | ||
var t = node.textContent; | var t = node.textContent; | ||
if (t == null) return true; | if (t == null) return true; | ||
| Line 964: | Line 1,008: | ||
if (root.classList) root.classList.remove("sv-hidden"); | if (root.classList) root.classList.remove("sv-hidden"); | ||
if (root.style && root.style.display === "none") root.style.display = ""; | if (root.style && root.style.display === "none") root.style.display = ""; | ||
| Line 975: | Line 1,018: | ||
if (!el) return; | if (!el) return; | ||
while (el.firstChild) el.removeChild(el.firstChild); | while (el.firstChild) el.removeChild(el.firstChild); | ||
var clone = sourceNode.cloneNode(true); | var clone = sourceNode.cloneNode(true); | ||
stripIds(clone); | stripIds(clone); | ||
unhideTree(clone); | unhideTree(clone); | ||
var isBody = | var isBody = | ||
clone.classList && | clone.classList && | ||
| Line 1,034: | Line 1,073: | ||
setExpanded(state.anchor, false); | setExpanded(state.anchor, false); | ||
if (state.anchor && state.anchor.tagName === "SUMMARY") { | if (state.anchor && state.anchor.tagName === "SUMMARY") { | ||
var det = closest(state.anchor, POPUP_DETAILS_SEL); | var det = closest(state.anchor, POPUP_DETAILS_SEL); | ||
| Line 1,051: | Line 1,089: | ||
if (!el) return; | if (!el) return; | ||
if (state.visible && state.anchor && state.anchor !== trigger) hidePop(); | if (state.visible && state.anchor && state.anchor !== trigger) hidePop(); | ||
| Line 1,062: | Line 1,099: | ||
setPopContentFromNode(sourceNode); | setPopContentFromNode(sourceNode); | ||
el.style.pointerEvents = state.pinned ? "auto" : "none"; | el.style.pointerEvents = state.pinned ? "auto" : "none"; | ||
el.classList.toggle("sv-pop-tip--pinned", state.pinned); | el.classList.toggle("sv-pop-tip--pinned", state.pinned); | ||
| Line 1,068: | Line 1,104: | ||
setExpanded(trigger, true); | setExpanded(trigger, true); | ||
if (trigger && trigger.tagName === "SUMMARY") { | if (trigger && trigger.tagName === "SUMMARY") { | ||
var det = closest(trigger, POPUP_DETAILS_SEL); | var det = closest(trigger, POPUP_DETAILS_SEL); | ||
| Line 1,086: | Line 1,121: | ||
return !!(e && e.pointerType && e.pointerType !== "mouse"); | return !!(e && e.pointerType && e.pointerType !== "mouse"); | ||
} | } | ||
if (HOVER_CAPABLE) { | if (HOVER_CAPABLE) { | ||
| Line 1,146: | Line 1,179: | ||
); | ); | ||
} | } | ||
document.addEventListener( | document.addEventListener( | ||
| Line 1,163: | Line 1,194: | ||
if (!isTouchLikeEvent(e)) return; | if (!isTouchLikeEvent(e)) return; | ||
e.preventDefault(); | e.preventDefault(); | ||
| Line 1,171: | Line 1,201: | ||
true | true | ||
); | ); | ||
document.addEventListener( | document.addEventListener( | ||
| Line 1,188: | Line 1,216: | ||
} | } | ||
e.preventDefault(); | e.preventDefault(); | ||
| Line 1,196: | Line 1,223: | ||
true | true | ||
); | ); | ||
document.addEventListener( | document.addEventListener( | ||
| Line 1,216: | Line 1,241: | ||
e.preventDefault(); | e.preventDefault(); | ||
if (state.pinned && sameAnchor(trigger)) hidePop(); | if (state.pinned && sameAnchor(trigger)) hidePop(); | ||
else showPop(trigger, source, state.lastX || 0, state.lastY || 0, true); | else showPop(trigger, source, state.lastX || 0, state.lastY || 0, true); | ||
| Line 1,222: | Line 1,246: | ||
true | true | ||
); | ); | ||
document.addEventListener( | document.addEventListener( | ||
| Line 1,230: | Line 1,252: | ||
if (!state.visible || !state.pinned) return; | if (!state.visible || !state.pinned) return; | ||
if (popEl && (e.target === popEl || (popEl.contains && popEl.contains(e.target)))) | if (popEl && (e.target === popEl || (popEl.contains && popEl.contains(e.target)))) | ||
return; | return; | ||
if (findTriggerFromEventTarget(e.target)) return; | if (findTriggerFromEventTarget(e.target)) return; | ||
| Line 1,268: | Line 1,288: | ||
true | true | ||
); | ); | ||
function hideTrigger(el) { | function hideTrigger(el) { | ||
| Line 1,281: | Line 1,299: | ||
var container = root || document; | var container = root || document; | ||
var btns = container.querySelectorAll(POPUP_BTN_SEL); | var btns = container.querySelectorAll(POPUP_BTN_SEL); | ||
for (var i = 0; i < btns.length; i++) { | for (var i = 0; i < btns.length; i++) { | ||
| Line 1,290: | Line 1,307: | ||
} | } | ||
var ds = container.querySelectorAll(POPUP_DETAILS_SEL); | var ds = container.querySelectorAll(POPUP_DETAILS_SEL); | ||
for (var j = 0; j < ds.length; j++) { | for (var j = 0; j < ds.length; j++) { | ||
| Line 1,300: | Line 1,316: | ||
if (isBlankContent(node2)) { | if (isBlankContent(node2)) { | ||
hideTrigger(d); | hideTrigger(d); | ||
} else { | } else { | ||
if (d.open) d.open = false; | if (d.open) d.open = false; | ||
if (s) setExpanded(s, false); | if (s) setExpanded(s, false); | ||