diff options
Diffstat (limited to 'src/lib/Utility/html.ts')
| -rw-r--r-- | src/lib/Utility/html.ts | 132 |
1 files changed, 94 insertions, 38 deletions
diff --git a/src/lib/Utility/html.ts b/src/lib/Utility/html.ts index 8d60d3b6..10d52971 100644 --- a/src/lib/Utility/html.ts +++ b/src/lib/Utility/html.ts @@ -1,42 +1,98 @@ -import settings from '$stores/settings'; -import { get } from 'svelte/store'; +import settings from "$stores/settings"; +import { get } from "svelte/store"; -export const nbsp = (str: string) => str.replace(/ /g, ' '); +export const nbsp = (str: string) => str.replace(/ /g, " "); export const createHeightObserver = (details = true) => { - document.querySelectorAll('.list').forEach((element) => { - if ( - !( - element as unknown as { - dataset: { observed: string }; - } - ).dataset.observed - ) { - new ResizeObserver((entries) => { - entries.forEach((entry) => { - const element = entry.target as HTMLElement; - - if (get(settings).displayLimitListHeight) { - element.style.height = 'auto'; - - const elementBound = element.getBoundingClientRect(); - const height = window.innerHeight - elementBound.top - 2.5 * 16; - - if (elementBound.height > height) element.style.height = `${height}px`; - } - }); - }).observe(element); - - if (details) - new MutationObserver((mutations) => { - mutations.forEach((mutation) => { - const element = mutation.target as HTMLDetailsElement; - - if (element.tagName === 'DETAILS' && !element.open) element.style.height = 'auto'; - }); - }).observe(element, { attributes: true }); - - element.setAttribute('data-observed', 'true'); - } - }); + const observedElements = new Set<HTMLElement>(); + const resizeObservers = new Map<HTMLElement, ResizeObserver>(); + const detailObservers = new Map<HTMLElement, MutationObserver>(); + + const applyHeightLimit = (target: HTMLElement) => { + if (!get(settings).displayLimitListHeight) { + target.style.height = "auto"; + + return; + } + + target.style.height = "auto"; + + const elementBound = target.getBoundingClientRect(); + const height = window.innerHeight - elementBound.top - 2.5 * 16; + + if (elementBound.height > height) target.style.height = `${height}px`; + }; + + const observeElement = (element: HTMLElement) => { + if (element.dataset.observed) return; + + const resizeObserver = new ResizeObserver((entries) => { + entries.forEach((entry) => { + const target = entry.target as HTMLElement; + + applyHeightLimit(target); + }); + }); + + resizeObserver.observe(element); + resizeObservers.set(element, resizeObserver); + + if (details) { + const detailsObserver = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + const target = mutation.target as HTMLDetailsElement; + + if (target.tagName === "DETAILS" && !target.open) + target.style.height = "auto"; + }); + }); + + detailsObserver.observe(element, { attributes: true }); + detailObservers.set(element, detailsObserver); + } + + element.dataset.observed = "true"; + + observedElements.add(element); + applyHeightLimit(element); + }; + + document.querySelectorAll<HTMLElement>(".list").forEach(observeElement); + + const mutationObserver = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + mutation.addedNodes.forEach((node) => { + if (!(node instanceof HTMLElement)) return; + + if (node.matches(".list")) observeElement(node); + + node.querySelectorAll<HTMLElement>(".list").forEach(observeElement); + }); + }); + }); + + mutationObserver.observe(document.body, { childList: true, subtree: true }); + + const unsubscribeSettings = settings.subscribe(() => { + observedElements.forEach((element) => { + applyHeightLimit(element); + }); + }); + + return () => { + unsubscribeSettings(); + mutationObserver.disconnect(); + resizeObservers.forEach((observer) => { + observer.disconnect(); + }); + detailObservers.forEach((observer) => { + observer.disconnect(); + }); + + observedElements.forEach((element) => { + element.style.height = "auto"; + + delete element.dataset.observed; + }); + }; }; |