PageSourceSearch

https://www.mix969huntsville.com/wp-content/plugins/ele-custom-ski…/assets/js/ecs-color-switcher.js?ver=4.3.4

js mix969huntsville.com collected 2026-09-29 09:37:57 UTC 5,526 bytes, 193 lines download raw bytes

1/**
2 * ECS Dark Mode Switcher
3 *
4 * Handles three display modes (toggle, dual, dropdown) for the
5 * ECS Dark Mode Switcher widget.  Persists the user's choice via
6 * a cookie so PHP can add data-ecs-scheme="alt" to <html> before
7 * first paint — cache-safe.
8 *
9 * No dependencies — vanilla JS, loaded in the footer.
10 */
11(function () {
12	'use strict';
13
14	// Guard against double-init when loaded more than once.
15	if ( window.__ecsDmsReady ) { return; }
16	window.__ecsDmsReady = true;
17
18	var COOKIE_NAME = 'ecs_color_scheme';
19	var ALT_VALUE   = 'alt';
20
21	/**
22	 * Get the current active scheme ('alt' or null).
23	 */
24	function getCurrentScheme() {
25		return document.documentElement.getAttribute('data-ecs-scheme');
26	}
27
28	/**
29	 * Apply a scheme by setting / removing the attribute on <html>.
30	 */
31	function applyScheme(scheme) {
32		if (scheme === ALT_VALUE) {
33			document.documentElement.setAttribute('data-ecs-scheme', ALT_VALUE);
34		} else {
35			document.documentElement.removeAttribute('data-ecs-scheme');
36		}
37		swapLogos(scheme === ALT_VALUE);
38	}
39
40	/**
41	 * Swap site logo src when dark mode is active.
42	 * Targets the Elementor Site Logo widget and the standard WP custom logo.
43	 * Stores the original src in data-ecs-logo-default so it can be restored.
44	 */
45	function swapLogos(isAlt) {
46		var cfg     = window.ecsSchemeConfig || {};
47		var darkUrl = cfg.darkLogoUrl;
48		if (!darkUrl) { return; }
49
50		document.querySelectorAll(
51			'.elementor-widget-theme-site-logo img, .elementor-widget-site-logo img, a.custom-logo-link img'
52		).forEach(function(img) {
53			if (isAlt) {
54				if (!img.dataset.ecsLogoDefault) {
55					img.dataset.ecsLogoDefault = img.src;
56				}
57				if (img.src !== darkUrl) {
58					img.src = darkUrl;
59					img.srcset = '';
60				}
61			} else {
62				if (img.dataset.ecsLogoDefault) {
63					img.src = img.dataset.ecsLogoDefault;
64					img.dataset.ecsLogoDefault = '';
65				}
66			}
67		});
68	}
69
70	/**
71	 * Persist the choice as a cookie so both PHP (server-side, for cache-aware
72	 * pages) and the inline anti-FOUC script can read it before first paint.
73	 */
74	function persistScheme(scheme) {
75		if (scheme === ALT_VALUE) {
76			document.cookie = COOKIE_NAME + '=alt; path=/; max-age=31536000; SameSite=Lax';
77		} else {
78			document.cookie = COOKIE_NAME + '=; path=/; max-age=0; SameSite=Lax';
79		}
80	}
81
82	/**
83	 * Return true if the user has a manually stored scheme preference.
84	 */
85	function hasCookie() {
86		return /(?:^|;\s*)ecs_color_scheme=/.test( document.cookie );
87	}
88
89	/**
90	 * Sync every widget on the page to the current scheme.
91	 * Handles toggle, dual, and dropdown display types.
92	 */
93	function syncAllWidgets() {
94		var isAlt = getCurrentScheme() === ALT_VALUE;
95
96		document.querySelectorAll('.ecs-dms-wrap').forEach(function (wrap) {
97			// Wrapper gets .is-alt for CSS toggle state switching
98			wrap.classList.toggle('is-alt', isAlt);
99
100			var display = wrap.dataset.display;
101
102			if (display === 'toggle') {
103				var btn = wrap.querySelector('.ecs-dms-btn');
104				if (btn) {
105					btn.classList.toggle('is-active', isAlt);
106				}
107
108			} else if (display === 'dual') {
109				wrap.querySelectorAll('.ecs-dms-btn').forEach(function (btn) {
110					var isActive = btn.dataset.scheme === ALT_VALUE ? isAlt : !isAlt;
111					btn.classList.toggle('is-active', isActive);
112					btn.setAttribute('aria-pressed', isActive ? 'true' : 'false');
113				});
114
115			} else if (display === 'dropdown') {
116				var select = wrap.querySelector('.ecs-dms-select');
117				if (select) {
118					select.value = isAlt ? ALT_VALUE : 'default';
119				}
120			}
121		});
122	}
123
124	/**
125	 * Click handler — handles toggle and dual buttons.
126	 */
127	function handleClick(event) {
128		var btn = event.target.closest('.ecs-dms-btn');
129		if (!btn) { return; }
130
131		var wrap = btn.closest('.ecs-dms-wrap');
132		if (!wrap) { return; }
133
134		var newScheme;
135
136		if (wrap.dataset.display === 'dual') {
137			// Each dual button carries its target scheme explicitly
138			newScheme = btn.dataset.scheme;
139		} else {
140			// Toggle: flip the current scheme
141			newScheme = getCurrentScheme() === ALT_VALUE ? 'default' : ALT_VALUE;
142		}
143
144		applyScheme(newScheme);
145		persistScheme(newScheme);
146		syncAllWidgets();
147	}
148
149	/**
150	 * Change handler — handles dropdown.
151	 */
152	function handleDropdownChange(event) {
153		var select = event.target;
154		if (!select.classList.contains('ecs-dms-select')) { return; }
155
156		applyScheme(select.value);
157		persistScheme(select.value);
158		syncAllWidgets();
159	}
160
161	// ── Init ─────────────────────────────────────────────────────────────────
162
163	function init() {
164		// Sync widgets and logo to whatever the anti-FOUC script already set on <html>
165		syncAllWidgets();
166		swapLogos(getCurrentScheme() === ALT_VALUE);
167
168		// System Auto: if enabled and no manual preference stored,
169		// follow live OS theme changes.
170		var cfg = window.ecsSchemeConfig || {};
171		if ( cfg.systemAuto ) {
172			var mq = window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' );
173			if ( mq ) {
174				mq.addEventListener( 'change', function ( e ) {
175					if ( ! hasCookie() ) {
176						applyScheme( e.matches ? ALT_VALUE : 'default' );
177						syncAllWidgets();
178					}
179				} );
180			}
181		}
182
183		// Delegate on document so Elementor re-renders don't require re-binding
184		document.addEventListener('click', handleClick);
185		document.addEventListener('change', handleDropdownChange);
186	}
187
188	if (document.readyState === 'loading') {
189		document.addEventListener('DOMContentLoaded', init);
190	} else {
191		init();
192	}
193})();

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.