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.