PageSourceSearch

https://mcalesterradio.com/live-now-button.js?v=20260916c

js mcalesterradio.com collected 2026-10-08 09:09:24 UTC 3,163 bytes, 86 lines download raw bytes

1/**
2 * LIVE NOW button state
3 * ---------------------
4 * The header LIVE NOW button has two resting states:
5 *
6 *   • something is live  → the box fills solid red
7 *   • nothing is live    → an empty box with a white outline
8 *
9 * It is never disabled. With nothing live it still leads to the watch section,
10 * where visitors find highlights and previous live streams.
11 *
12 * Live items are published by admins and moderators into the shared "live now"
13 * list, mirrored into localStorage by shared-data.js. This script only reads
14 * that list, so it is safe to load on every page, with or without main.js.
15 */
16(function () {
17    'use strict';
18
19    if (typeof window === 'undefined' || !window.document) return;
20
21    // Loading the script twice must not install two sets of listeners.
22    if (window.MSTLiveNowButton) return;
23
24    var STORAGE_KEY = 'mstLiveNow';
25    var BUTTON_SELECTOR = '.live-now-btn';
26
27    function hasLiveItems() {
28        try {
29            var raw = window.localStorage ? window.localStorage.getItem(STORAGE_KEY) : null;
30            var parsed = JSON.parse(raw || '[]');
31            return Array.isArray(parsed) && parsed.length > 0;
32        } catch (error) {
33            // Unreadable or malformed storage means we cannot claim anything is live.
34            return false;
35        }
36    }
37
38    function refresh() {
39        var buttons = document.querySelectorAll(BUTTON_SELECTOR);
40        if (!buttons.length) return false;
41
42        var isLive = hasLiveItems();
43
44        Array.prototype.forEach.call(buttons, function (button) {
45            if (button.classList.contains('is-live') !== isLive) {
46                button.classList.toggle('is-live', isLive);
47            }
48            button.setAttribute('data-live-state', isLive ? 'live' : 'offline');
49            button.setAttribute('aria-label', isLive
50                ? 'Live now - watch the live stream'
51                : 'Live now - see highlights and past live streams');
52            button.setAttribute('title', isLive
53                ? 'Live right now'
54                : 'Nothing live right now - see highlights and past live streams');
55            // The button is always actionable, whichever state it is in.
56            button.removeAttribute('aria-disabled');
57        });
58
59        return isLive;
60    }
61
62    window.MSTLiveNowButton = {
63        refresh: refresh,
64        isLive: hasLiveItems
65    };
66
67    if (document.readyState === 'loading') {
68        document.addEventListener('DOMContentLoaded', refresh, { once: true });
69    } else {
70        refresh();
71    }
72
73    // shared-data.js announces every list it pulls from the shared store, which is
74    // how a live item published on another device reaches this page.
75    window.addEventListener('mst:shared-data-updated', function (event) {
76        var keys = event && event.detail && event.detail.keys;
77        if (Array.isArray(keys) && keys.indexOf(STORAGE_KEY) === -1) return;
78        refresh();
79    });
80
81    // Another tab on this browser changing the list.
82    window.addEventListener('storage', function (event) {
83        if (event && event.key && event.key !== STORAGE_KEY) return;
84        refresh();
85    });
86})();

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.