PageSourceSearch

https://insidetherink.com/wp-content/themes/inside-the-rink/assets/js/theme-toggle.js?ver=1.10.2

js insidetherink.com collected 2026-10-02 04:55:46 UTC 2,830 bytes, 102 lines download raw bytes

1/**
2 * Inside The Rink — light/dark toggle.
3 *
4 * The anti-flash half of this lives in an inline <head> script (functions.php),
5 * which must run before first paint. This file only handles interaction.
6 *
7 * Storage is localStorage, not a cookie or user meta, because the HTML is
8 * edge-cached — a server-rendered choice would be baked into the cached page
9 * and served to every visitor.
10 *
11 * Three states, matching the app's ThemeMode in src/context/theme-context.tsx:
12 *   no attribute          -> follow the OS (default)
13 *   data-itr-theme=light  -> forced light
14 *   data-itr-theme=dark   -> forced dark
15 *
16 * The button toggles between light and dark. Clearing site data returns the
17 * visitor to following the OS.
18 */
19( function () {
20	'use strict';
21
22	var STORAGE_KEY = 'itr-theme';
23	var root = document.documentElement;
24
25	function osPrefersDark() {
26		return window.matchMedia && window.matchMedia( '(prefers-color-scheme: dark)' ).matches;
27	}
28
29	/** What the visitor is actually looking at right now. */
30	function currentTheme() {
31		var forced = root.getAttribute( 'data-itr-theme' );
32
33		if ( 'light' === forced || 'dark' === forced ) {
34			return forced;
35		}
36
37		return osPrefersDark() ? 'dark' : 'light';
38	}
39
40	function store( mode ) {
41		try {
42			window.localStorage.setItem( STORAGE_KEY, mode );
43		} catch ( e ) {
44			// Private mode or storage disabled — the toggle still works for this
45			// page view, it just won't persist.
46		}
47	}
48
49	function apply( mode ) {
50		root.setAttribute( 'data-itr-theme', mode );
51		store( mode );
52		syncButtons( mode );
53	}
54
55	function syncButtons( mode ) {
56		var isDark = 'dark' === mode;
57		var label = isDark ? 'Switch to light mode' : 'Switch to dark mode';
58
59		document.querySelectorAll( '.itr-theme-toggle' ).forEach( function ( btn ) {
60			btn.setAttribute( 'aria-label', label );
61			btn.setAttribute( 'title', label );
62			btn.setAttribute( 'aria-pressed', isDark ? 'true' : 'false' );
63		} );
64	}
65
66	function init() {
67		syncButtons( currentTheme() );
68
69		document.addEventListener( 'click', function ( event ) {
70			var btn = event.target.closest( '.itr-theme-toggle' );
71
72			if ( ! btn ) {
73				return;
74			}
75
76			event.preventDefault();
77			apply( 'dark' === currentTheme() ? 'light' : 'dark' );
78		} );
79
80		// Keep following the OS until the visitor makes an explicit choice.
81		if ( window.matchMedia ) {
82			var mq = window.matchMedia( '(prefers-color-scheme: dark)' );
83			var onChange = function () {
84				if ( ! root.hasAttribute( 'data-itr-theme' ) ) {
85					syncButtons( currentTheme() );
86				}
87			};
88
89			if ( mq.addEventListener ) {
90				mq.addEventListener( 'change', onChange );
91			} else if ( mq.addListener ) {
92				mq.addListener( onChange );
93			}
94		}
95	}
96
97	if ( 'loading' === document.readyState ) {
98		document.addEventListener( 'DOMContentLoaded', init );
99	} else {
100		init();
101	}
102}() );

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.