Spaces:
Running
Running
File size: 3,708 Bytes
6918275 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | import { createStore } from "/js/AlpineStore.js";
let bootstrapTooltipObserver = null;
function ensureBootstrapTooltip(element) {
if (!element || !(element instanceof Element)) return;
const bs = globalThis.bootstrap;
if (!bs?.Tooltip) return;
const existing = bs.Tooltip.getInstance(element);
const title = element.getAttribute("title") || element.getAttribute("data-bs-original-title");
if (!title) return;
if (existing) {
if (element.getAttribute("title")) {
element.setAttribute("data-bs-original-title", title);
element.removeAttribute("title");
}
existing.setContent({ ".tooltip-inner": title });
return;
}
if (element.getAttribute("title")) {
element.setAttribute("data-bs-original-title", title);
element.removeAttribute("title");
}
element.setAttribute("data-bs-toggle", "tooltip");
element.setAttribute("data-bs-trigger", "hover");
element.setAttribute("data-bs-tooltip-initialized", "true");
new bs.Tooltip(element, {
delay: { show: 0, hide: 0 },
trigger: "hover",
});
}
function initBootstrapTooltips(root = document) {
if (!globalThis.bootstrap?.Tooltip) return;
const selector = "[title], [data-bs-original-title]";
const rootIsElement = root instanceof Element;
const tooltipTargets = [
...(rootIsElement && root.matches(selector) ? [root] : []),
...Array.from(root.querySelectorAll(selector)),
];
tooltipTargets.forEach((element) => ensureBootstrapTooltip(element));
}
function disposeBootstrapTooltip(element) {
const instance = globalThis.bootstrap?.Tooltip?.getInstance(element);
if (!instance) return;
try {
instance.dispose();
} catch {
// Bootstrap 5 can throw while disposing an already-torn-down tooltip node.
}
}
function observeBootstrapTooltips() {
if (!globalThis.bootstrap?.Tooltip) return;
// Prevent multiple observers
if (bootstrapTooltipObserver) return;
bootstrapTooltipObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (
mutation.type === "attributes" &&
(mutation.attributeName === "title" ||
mutation.attributeName === "data-bs-original-title")
) {
ensureBootstrapTooltip(mutation.target);
return;
}
if (mutation.type === "childList") {
// Check removed nodes for tooltip cleanup
mutation.removedNodes.forEach((node) => {
if (!(node instanceof Element)) return;
const tooltipElements = node.matches?.("[data-bs-tooltip-initialized]")
? [node]
: Array.from(
node.querySelectorAll?.("[data-bs-tooltip-initialized]") || []
);
tooltipElements.forEach((el) => {
if (el.isConnected) return;
disposeBootstrapTooltip(el);
});
});
mutation.addedNodes.forEach((node) => {
if (!(node instanceof Element)) return;
if (
node.matches("[title], [data-bs-original-title]") ||
node.querySelector("[title], [data-bs-original-title]")
) {
initBootstrapTooltips(node);
}
});
}
});
});
bootstrapTooltipObserver.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ["title", "data-bs-original-title"],
});
}
function cleanupTooltipObserver() {
if (bootstrapTooltipObserver) {
bootstrapTooltipObserver.disconnect();
bootstrapTooltipObserver = null;
}
}
export const store = createStore("tooltips", {
init() {
initBootstrapTooltips();
observeBootstrapTooltips();
},
cleanup: cleanupTooltipObserver,
});
|