1class AudioStreamHandler_bf1e7435 extends elementorModules.frontend.handlers.Base { 2 getDefaultSettings() { 3 return { 4 selectors: { 5 playBtn: '.as-bf1e7435-play-btn', 6 playIcon: '.as-bf1e7435-play-icon', 7 pauseIcon: '.as-bf1e7435-pause-icon', 8 volumeInput: '.as-bf1e7435-volume-input', 9 trackTitle: '.as-bf1e7435-track-title', 10 artistName: '.as-bf1e7435-artist-name', 11 albumName: '.as-bf1e7435-album-name', 12 albumArt: '.as-bf1e7435-album-art' 13 } 14 }; 15 } 16 17 getDefaultElements() { 18 const selectors = this.getSettings('selectors'); 19 return { 20 $playBtn: this.$element.find(selectors.playBtn), 21 $playIcon: this.$element.find(selectors.playIcon), 22 $pauseIcon: this.$element.find(selectors.pauseIcon), 23 $volumeInput: this.$element.find(selectors.volumeInput), 24 $trackTitle: this.$element.find(selectors.trackTitle), 25 $artistName: this.$element.find(selectors.artistName), 26 $albumName: this.$element.find(selectors.albumName), 27 $albumArt: this.$element.find(selectors.albumArt) 28 }; 29 } 30 31 bindEvents() { 32 this.streamUrl = this.$element.find('.as-bf1e7435-player').data('stream-url'); 33 this.xmlUrl = this.$element.find('.as-bf1e7435-player').data('xml-url'); 34 this.interval = parseInt(this.$element.find('.as-bf1e7435-player').data('interval'), 10) * 1000 || 15000; 35 this.ajaxUrl = this.$element.find('.as-bf1e7435-player').data('ajax-url'); 36 this.nonce = this.$element.find('.as-bf1e7435-player').data('nonce'); 37 38 this.audio = null; 39 this.isPlaying = false; 40 this.metaTimer = null; 41 42 this.elements.$playBtn.on('click', this.togglePlayback.bind(this)); 43 this.elements.$volumeInput.on('input', this.handleVolumeChange.bind(this)); 44 45 // Start pulling metadata immediately if an XML URL is defined 46 if (this.xmlUrl) { 47 this.fetchMetadata(); 48 this.metaTimer = setInterval(this.fetchMetadata.bind(this), this.interval); 49 } else { 50 this.elements.$trackTitle.text('Live Broadcast'); 51 this.elements.$artistName.text('Ready to Play'); 52 } 53 } 54 55 initAudio() { 56 if (!this.audio) { 57 this.audio = new Audio(this.streamUrl); 58 this.audio.volume = parseFloat(this.elements.$volumeInput.val()); 59 } 60 } 61 62 togglePlayback() { 63 this.initAudio(); 64 65 if (this.isPlaying) { 66 this.audio.pause(); 67 // Force stream reload upon re-play to stay live and free up browser memory 68 this.audio.src = ''; 69 this.audio.load(); 70 this.audio = null; 71 72 this.elements.$playIcon.show(); 73 this.elements.$pauseIcon.hide(); 74 this.isPlaying = false; 75 } else { 76 this.initAudio(); 77 this.audio.src = this.streamUrl; 78 this.audio.play().catch(err => console.error("Audio stream playback failed:", err)); 79 80 this.elements.$playIcon.hide(); 81 this.elements.$pauseIcon.show(); 82 this.isPlaying = true; 83 } 84 } 85 86 handleVolumeChange(e) { 87 const vol = parseFloat(e.target.value); 88 if (this.audio) { 89 this.audio.volume = vol; 90 } 91 } 92 93 fetchMetadata() { 94 if (!this.xmlUrl || !this.ajaxUrl) return; 95 96 jQuery.ajax({ 97 url: this.ajaxUrl, 98 type: 'GET', 99 data: { 100 action: 'audio_stream_get_meta_bf1e7435', 101 xml_url: this.xmlUrl, 102 nonce: this.nonce 103 }, 104 success: (response) => { 105 if (response.success && response.data) { 106 const data = response.data; 107 this.elements.$trackTitle.text(data.title || 'Live Stream'); 108 this.elements.$artistName.text(data.artist || 'Radio Broadcast'); 109 110 if (data.album) { 111 this.elements.$albumName.text(data.album).show(); 112 } else { 113 this.elements.$albumName.hide(); 114 } 115 116 // Dynamically update Cover Art / Fallback 117 if (data.cover) { 118 this.elements.$albumArt.attr('src', data.cover); 119 } else { 120 const fallback = this.elements.$albumArt.data('fallback-logo'); 121 if (fallback) { 122 this.elements.$albumArt.attr('src', fallback); 123 } 124 } 125 } 126 }, 127 error: () => { 128 console.log('Failed to pull custom stream metadata'); 129 } 130 }); 131 } 132 133 onDestroy() { 134 if (this.audio) { 135 this.audio.pause(); 136 this.audio = null; 137 } 138 if (this.metaTimer) { 139 clearInterval(this.metaTimer); 140 } 141 } 142} 143 144jQuery(window).on('elementor/frontend/init', () => { 145 const addHandler = ($element) => { 146 elementorFrontend.elementsHandler.addHandler(AudioStreamHandler_bf1e7435, { $element }); 147 }; 148 elementorFrontend.hooks.addAction('frontend/element_ready/audio_stream_bf1e7435.default', addHandler); 149});
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.