aboutsummaryrefslogtreecommitdiff
path: root/src/lib/Utility/html.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/Utility/html.ts')
-rw-r--r--src/lib/Utility/html.ts132
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;
+ });
+ };
};