PageSourceSearch

https://www.brookingsradio.com/wp-content/themes/fluid44/js/theme.js?ver=20261002_113303

js brookingsradio.com collected 2026-10-02 11:33:19 UTC 6,926 bytes, 204 lines download raw bytes

1jQuery(document).ready(function($) {
2
3  $('#listen-live').addClass('active');
4
5  // 1. Cross-Origin Safe Reference to Top Window Context
6  var safeTopWindow;
7  try {
8    var testTop = window.top.document; 
9    safeTopWindow = window.top;
10  } catch (e) {
11    safeTopWindow = window; 
12  }
13
14  // 2. Station Metadata Map (Uses PNG/JPG URLs strictly for iOS artwork compatibility)
15  var stationData = {
16    'persistent-KJJQ-AM-The-Ranch': {
17      url: 'https://live.amperwave.net/direct/brookings-kjjqammp3-imc',
18      title: 'AM 910 The Ranch',
19      artist: '910 AM - Brookings Radio',
20      logo: 'https://brookingsradio.com/wp-content/uploads/2026/07/cropped-Brookings-Radio-Favicon-192x192.png' // PNG Fallback for SVG
21    },
22    'persistent-KBRK-AM-1430': {
23      url: 'https://live.amperwave.net/direct/brookings-kbrkfmmp3-imc',
24      title: 'KBRK Traditional',
25      artist: '1430 AM - Brookings Radio',
26      logo: 'https://brookingsradio.com/wp-content/uploads/2026/07/cropped-Brookings-Radio-Favicon-192x192.png' // PNG Fallback for SVG
27    },
28    'persistent-B-93.7-FM': {
29        url: 'https://live.amperwave.net/direct/brookings-kbrkammp3-imc'
30      ,
31      title: 'KBRK B93.7',
32      artist: '93.7 FM - Brookings Radio',
33      logo: 'https://brookingsradio.com/wp-content/uploads/2026/07/new-b-logo.png'
34    },
35    'persistent-102.3-FM': {
36      url: 'https://live.amperwave.net/direct/brookings-kkqqfmmp3-imc',
37      title: 'KKQQ KCountry',
38      artist: '102.3 FM - Brookings Radio',
39      logo: 'https://brookingsradio.com/wp-content/uploads/2026/07/KKQQ-Logo.png'
40    },
41    'persistent-107.1-The-Hawk': {
42      url: 'https://live.amperwave.net/direct/brookings-kdbxfmmp3-imc',
43      title: 'KDBX The Hawk',
44      artist: '107.1 FM - Brookings Radio',
45      logo: 'https://brookingsradio.com/wp-content/uploads/2026/07/hawk-logo.jpg'
46    }
47  };
48
49  // 3. Global Audio State on safeTopWindow
50  safeTopWindow.RadioStations = safeTopWindow.RadioStations || {
51    activeStationKey: null,
52    audioInstance: null,
53    isBound: false
54  };
55
56  // Helper to sync UI icon states on the widget
57  function setCardUIState(container, isPlaying) {
58    if (!container) return;
59    
60    var $container = $(container);
61    if (isPlaying) {
62      $container.addClass('is-playing playing paused-state-off');
63      $container.find('.cp-play-button').addClass('cp-pause-button').removeClass('cp-play-button');
64    } else {
65      $container.removeClass('is-playing playing paused-state-off');
66      $container.find('.cp-pause-button').addClass('cp-play-button').removeClass('cp-pause-button');
67    }
68  }
69
70  // Helper to explicitly force iOS / Android Lock Screen Metadata
71  function updateLockScreenMetadata(station) {
72    if ('mediaSession' in navigator) {
73      try {
74        navigator.mediaSession.metadata = new MediaMetadata({
75          title: station.title,
76          artist: station.artist,
77          album: 'Brookings Radio Live',
78          artwork: [
79            { src: station.logo, sizes: '192x192', type: 'image/png' },
80            { src: station.logo, sizes: '512x512', type: 'image/png' }
81          ]
82        });
83
84        // Bind hardware play/pause actions on iOS lock screen
85        navigator.mediaSession.setActionHandler('play', function() {
86          if (safeTopWindow.RadioStations.audioInstance) {
87            safeTopWindow.RadioStations.audioInstance.play();
88          }
89        });
90        navigator.mediaSession.setActionHandler('pause', function() {
91          stopActiveStream();
92        });
93      } catch (err) {
94        console.warn('MediaSession initialization notice:', err);
95      }
96    }
97  }
98
99  // Helper to completely stop and destroy the current audio stream
100  function stopActiveStream() {
101    var state = safeTopWindow.RadioStations;
102    
103    if (state.audioInstance) {
104      state.audioInstance.pause();
105      state.audioInstance.removeAttribute('src'); // Drops network connection
106      if (typeof state.audioInstance.load === 'function') {
107        state.audioInstance.load();
108      }
109      state.audioInstance = null;
110    }
111
112    if (state.activeStationKey) {
113      var topDocNode = safeTopWindow.document;
114      var prevContainer = topDocNode.getElementById(state.activeStationKey);
115      if (prevContainer) {
116        setCardUIState(prevContainer, false);
117      }
118      state.activeStationKey = null;
119    }
120
121    // Clear lock screen metadata on stop
122    if ('mediaSession' in navigator) {
123      navigator.mediaSession.metadata = null;
124    }
125  }
126
127  // 4. Mobile & Desktop Unified Touch/Click Handler
128  function bindExclusivePlayback() {
129    var topDocNode = safeTopWindow.document;
130
131    function handleStationTap(e) {
132      var currentContainer = e.target.closest('#ajaxpress-persist div[id^="persistent-"]');
133      if (!currentContainer) return;
134
135      e.preventDefault();
136      e.stopPropagation();
137
138      var clickedStationId = currentContainer.id;
139      var station = stationData[clickedStationId];
140      var state = safeTopWindow.RadioStations;
141
142      if (!station) return;
143
144      // IF USER CLICKED THE CURRENTLY PLAYING STATION -> PAUSE IT
145      if (state.activeStationKey === clickedStationId) {
146        stopActiveStream();
147        return;
148      }
149
150      // IF A DIFFERENT STATION WAS PLAYING -> STOP IT FIRST
151      stopActiveStream();
152
153      // START THE NEW STREAM USING A CLEAN AUDIO INSTANCE
154      var newAudio = new Audio();
155      newAudio.preload = 'none';
156      newAudio.src = station.url;
157
158      // Bind metadata update to audio play event for iOS Safari
159      newAudio.addEventListener('play', function() {
160        updateLockScreenMetadata(station);
161      });
162
163      newAudio.play().then(function() {
164        state.audioInstance = newAudio;
165        state.activeStationKey = clickedStationId;
166        setCardUIState(currentContainer, true);
167        updateLockScreenMetadata(station);
168      }).catch(function(err) {
169        console.error('Stream playback error:', err);
170      });
171    }
172
173    var eventType = ('ontouchstart' in window) ? 'touchstart' : 'click';
174    topDocNode.addEventListener(eventType, handleStationTap, true); 
175  }
176
177  if (!safeTopWindow.RadioStations.isBound) {
178    bindExclusivePlayback();
179    safeTopWindow.RadioStations.isBound = true;
180  }
181
182  // 5. Persistent Drawer Toggle Handler
183  $(document).off('click.listenLiveToggle').on('click.listenLiveToggle', '#listen-live a.elementor-button, #listen-live', function(e) {
184    e.preventDefault();
185    e.stopPropagation();
186    
187    var topDoc = safeTopWindow.document;
188    var $persistEl = $(topDoc).find('#ajaxpress-persist');
189    
190    if ($persistEl.length) {
191      $(this).toggleClass('active');
192      if ($(this).hasClass('active')) {
193        $(this).find('span.elementor-button-text').html('Close Player');
194      } else {
195        $(this).find('span.elementor-button-text').html('Listen Live');
196      }
197      $persistEl.toggleClass('active');
198      topDoc.body.classList.toggle('player-active');
199    }
200  });
201
202});
203
204

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.