PageSourceSearch

https://oldnorth.com/wp-content/themes/wp_old_north/assets/js/theme.js?ver=1.4.5

js oldnorth.com collected 2026-10-02 03:26:58 UTC 4,635 bytes, 170 lines download raw bytes

1/**
2 * Old North Church - Theme Scripts
3 *
4 * Main JavaScript file for theme functionality.
5 *
6 * @package Old_North
7 * @since 1.0.0
8 */
9
10(function() {
11	'use strict';
12
13	// =========================================================================
14	// Shared Height Animation Utilities
15	// CSS handles easing/duration, JS sets heights and toggles `is-animating`
16	// =========================================================================
17	const running = new WeakMap(); // panel -> cleanup
18
19	const naturalHeight = (panel) => {
20		const prevHeight = panel.style.height;
21		const prevDisplay = panel.style.display;
22
23		const wasHidden = getComputedStyle(panel).display === "none";
24		if (wasHidden) {
25			panel.style.display = "block";
26			panel.style.height = "auto";
27		} else {
28			panel.style.height = "auto";
29		}
30
31		const h = panel.scrollHeight;
32
33		panel.style.height = prevHeight;
34		panel.style.display = prevDisplay;
35
36		return h;
37	};
38
39	const stopRunning = (panel) => {
40		const cleanup = running.get(panel);
41		if (cleanup) cleanup();
42	};
43
44	function animateOpen(panel) {
45		stopRunning(panel);
46
47		// Measure target height before starting
48		const target = naturalHeight(panel);
49
50		// Set initial state
51		panel.style.display = "block";
52		panel.style.height = "0px";
53
54		// Force layout so 0px is committed
55		panel.getBoundingClientRect();
56
57		// Add transition class BEFORE changing height
58		panel.classList.add("is-animating");
59
60		// Force layout again so transition class is applied
61		panel.getBoundingClientRect();
62
63		const onEnd = (e) => {
64			if (e.target !== panel || e.propertyName !== "height") return;
65			panel.removeEventListener("transitionend", onEnd);
66
67			panel.classList.remove("is-animating");
68			panel.style.height = "auto";
69
70			running.delete(panel);
71		};
72
73		const cleanup = () => {
74			panel.removeEventListener("transitionend", onEnd);
75			panel.classList.remove("is-animating");
76			panel.style.height = "auto";
77			running.delete(panel);
78		};
79
80		running.set(panel, cleanup);
81		panel.addEventListener("transitionend", onEnd);
82
83		// Trigger the transition by setting explicit px height
84		panel.style.height = `${target}px`;
85	}
86
87	function animateClose(panel) {
88		stopRunning(panel);
89
90		const start = panel.getBoundingClientRect().height || naturalHeight(panel);
91		panel.style.height = `${start}px`;
92
93		// Force layout so start height is committed before collapsing
94		panel.getBoundingClientRect();
95
96		panel.classList.add("is-animating");
97
98		const onEnd = (e) => {
99			if (e.target !== panel || e.propertyName !== "height") return;
100			panel.removeEventListener("transitionend", onEnd);
101
102			panel.classList.remove("is-animating");
103			panel.style.height = "0px";
104
105			running.delete(panel);
106		};
107
108		const cleanup = () => {
109			panel.removeEventListener("transitionend", onEnd);
110			panel.classList.remove("is-animating");
111			panel.style.height = "0px";
112			running.delete(panel);
113		};
114
115		running.set(panel, cleanup);
116		panel.addEventListener("transitionend", onEnd);
117
118		// Trigger the transition to 0
119		panel.style.height = "0px";
120	}
121
122	// Export utilities to window for use by other scripts (e.g., oni-menu)
123	window.OniAnimations = { naturalHeight, animateOpen, animateClose };
124
125	// =========================================================================
126	// Accordion Panel Animation
127	// =========================================================================
128	const TOGGLE_SEL = ".wp-block-accordion-heading__toggle[aria-controls]";
129
130	const getPanel = (btn) => {
131		const id = btn.getAttribute("aria-controls");
132		return id ? document.getElementById(id) : null;
133	};
134
135	function syncInitial(panel, open) {
136		panel.style.display = "block";
137		panel.style.height = open ? "auto" : "0px";
138		panel.classList.remove("is-animating");
139	}
140
141	function initAccordionToggle(btn) {
142		const panel = getPanel(btn);
143		if (!panel) return;
144
145		syncInitial(panel, btn.getAttribute("aria-expanded") === "true");
146
147		// WordPress core toggles aria-expanded; observe that
148		const obs = new MutationObserver(() => {
149			const open = btn.getAttribute("aria-expanded") === "true";
150			if (open) animateOpen(panel);
151			else animateClose(panel);
152		});
153
154		obs.observe(btn, { attributes: true, attributeFilter: ["aria-expanded"] });
155	}
156
157	function initAccordions() {
158		document.querySelectorAll(TOGGLE_SEL).forEach(initAccordionToggle);
159	}
160
161	// =========================================================================
162	// Initialize on DOM Ready
163	// =========================================================================
164	if (document.readyState === "loading") {
165		document.addEventListener("DOMContentLoaded", initAccordions);
166	} else {
167		initAccordions();
168	}
169
170})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.