PageSourceSearch

https://thepatentprofessor.com/wp-content/plugins/ele-custom-skin/…/assets/js/ecs-color-switcher.js?ver=4.3.1

js thepatentprofessor.com collected 2026-09-24 12:48:44 UTC 4,591 bytes, 161 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	}
38
39	/**
40	 * Persist the choice as a cookie so both PHP (server-side, for cache-aware
41	 * pages) and the inline anti-FOUC script can read it before first paint.
42	 */
43	function persistScheme(scheme) {
44		if (scheme === ALT_VALUE) {
45			document.cookie = COOKIE_NAME + '=alt; path=/; max-age=31536000; SameSite=Lax';
46		} else {
47			document.cookie = COOKIE_NAME + '=; path=/; max-age=0; SameSite=Lax';
48		}
49	}
50
51	/**
52	 * Return true if the user has a manually stored scheme preference.
53	 */
54	function hasCookie() {
55		return /(?:^|;\s*)ecs_color_scheme=/.test( document.cookie );
56	}
57
58	/**
59	 * Sync every widget on the page to the current scheme.
60	 * Handles toggle, dual, and dropdown display types.
61	 */
62	function syncAllWidgets() {
63		var isAlt = getCurrentScheme() === ALT_VALUE;
64
65		document.querySelectorAll('.ecs-dms-wrap').forEach(function (wrap) {
66			// Wrapper gets .is-alt for CSS toggle state switching
67			wrap.classList.toggle('is-alt', isAlt);
68
69			var display = wrap.dataset.display;
70
71			if (display === 'toggle') {
72				var btn = wrap.querySelector('.ecs-dms-btn');
73				if (btn) {
74					btn.classList.toggle('is-active', isAlt);
75				}
76
77			} else if (display === 'dual') {
78				wrap.querySelectorAll('.ecs-dms-btn').forEach(function (btn) {
79					var isActive = btn.dataset.scheme === ALT_VALUE ? isAlt : !isAlt;
80					btn.classList.toggle('is-active', isActive);
81					btn.setAttribute('aria-pressed', isActive ? 'true' : 'false');
82				});
83
84			} else if (display === 'dropdown') {
85				var select = wrap.querySelector('.ecs-dms-select');
86				if (select) {
87					select.value = isAlt ? ALT_VALUE : 'default';
88				}
89			}
90		});
91	}
92
93	/**
94	 * Click handler — handles toggle and dual buttons.
95	 */
96	function handleClick(event) {
97		var btn = event.target.closest('.ecs-dms-btn');
98		if (!btn) { return; }
99
100		var wrap = btn.closest('.ecs-dms-wrap');
101		if (!wrap) { return; }
102
103		var newScheme;
104
105		if (wrap.dataset.display === 'dual') {
106			// Each dual button carries its target scheme explicitly
107			newScheme = btn.dataset.scheme;
108		} else {
109			// Toggle: flip the current scheme
110			newScheme = getCurrentScheme() === ALT_VALUE ? 'default' : ALT_VALUE;
111		}
112
113		applyScheme(newScheme);
114		persistScheme(newScheme);
115		syncAllWidgets();
116	}
117
118	/**
119	 * Change handler — handles dropdown.
120	 */
121	function handleDropdownChange(event) {
122		var select = event.target;
123		if (!select.classList.contains('ecs-dms-select')) { return; }
124
125		applyScheme(select.value);
126		persistScheme(select.value);
127		syncAllWidgets();
128	}
129
130	// ── Init ─────────────────────────────────────────────────────────────────
131
132	function init() {
133		// Sync widgets to whatever the anti-FOUC script already set on <html>
134		syncAllWidgets();
135
136		// System Auto: if enabled and no manual preference stored,
137		// follow live OS theme changes.
138		var cfg = window.ecsSchemeConfig || {};
139		if ( cfg.systemAuto ) {
140			var mq = window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' );
141			if ( mq ) {
142				mq.addEventListener( 'change', function ( e ) {
143					if ( ! hasCookie() ) {
144						applyScheme( e.matches ? ALT_VALUE : 'default' );
145						syncAllWidgets();
146					}
147				} );
148			}
149		}
150
151		// Delegate on document so Elementor re-renders don't require re-binding
152		document.addEventListener('click', handleClick);
153		document.addEventListener('change', handleDropdownChange);
154	}
155
156	if (document.readyState === 'loading') {
157		document.addEventListener('DOMContentLoaded', init);
158	} else {
159		init();
160	}
161})();

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.