1setTimeout(function () { 2 ;(function () { 3 const handleAudioPlayer = function (audioElementContainer) { 4 const audioPlayerContainer = audioElementContainer.querySelector( 5 '.kg-audio-player-container', 6 ) 7 const playIconContainer = audioElementContainer.querySelector( 8 '.kg-audio-play-icon', 9 ) 10 const pauseIconContainer = audioElementContainer.querySelector( 11 '.kg-audio-pause-icon', 12 ) 13 const seekSlider = audioElementContainer.querySelector( 14 '.kg-audio-seek-slider', 15 ) 16 const playbackRateContainer = audioElementContainer.querySelector( 17 '.kg-audio-playback-rate', 18 ) 19 const muteIconContainer = audioElementContainer.querySelector( 20 '.kg-audio-mute-icon', 21 ) 22 const unmuteIconContainer = audioElementContainer.querySelector( 23 '.kg-audio-unmute-icon', 24 ) 25 const volumeSlider = audioElementContainer.querySelector( 26 '.kg-audio-volume-slider', 27 ) 28 const audio = audioElementContainer.querySelector('audio') 29 const durationContainer = 30 audioElementContainer.querySelector('.kg-audio-duration') 31 const currentTimeContainer = audioElementContainer.querySelector( 32 '.kg-audio-current-time', 33 ) 34 let playbackRates = [ 35 { 36 rate: 0.75, 37 label: '0.7Ã', 38 }, 39 { 40 rate: 1.0, 41 label: '1Ã', 42 }, 43 { 44 rate: 1.25, 45 label: '1.2Ã', 46 }, 47 { 48 rate: 1.75, 49 label: '1.7Ã', 50 }, 51 { 52 rate: 2.0, 53 label: '2Ã', 54 }, 55 ] 56 57 let raf = null 58 let currentPlaybackRateIdx = 1 59 60 const whilePlaying = () => { 61 seekSlider.value = Math.floor(audio.currentTime) 62 currentTimeContainer.textContent = calculateTime(seekSlider.value) 63 audioPlayerContainer.style.setProperty( 64 '--seek-before-width', 65 `${(seekSlider.value / seekSlider.max) * 100}%`, 66 ) 67 raf = requestAnimationFrame(whilePlaying) 68 } 69 70 const showRangeProgress = (rangeInput) => { 71 if (rangeInput === seekSlider) { 72 audioPlayerContainer.style.setProperty( 73 '--seek-before-width', 74 (rangeInput.value / rangeInput.max) * 100 + '%', 75 ) 76 } else { 77 audioPlayerContainer.style.setProperty( 78 '--volume-before-width', 79 (rangeInput.value / rangeInput.max) * 100 + '%', 80 ) 81 } 82 } 83 84 const calculateTime = (secs) => { 85 const minutes = Math.floor(secs / 60) 86 const seconds = Math.floor(secs % 60) 87 const returnedSeconds = seconds < 10 ? `0${seconds}` : `${seconds}` 88 return `${minutes}:${returnedSeconds}` 89 } 90 91 const displayDuration = () => { 92 durationContainer.textContent = calculateTime(audio.duration) 93 } 94 95 const setSliderMax = () => { 96 seekSlider.max = Math.floor(audio.duration) 97 } 98 99 const displayBufferedAmount = () => { 100 if (audio.buffered.length > 0) { 101 const bufferedAmount = Math.floor( 102 audio.buffered.end(audio.buffered.length - 1), 103 ) 104 audioPlayerContainer.style.setProperty( 105 '--buffered-width', 106 `${(bufferedAmount / seekSlider.max) * 100}%`, 107 ) 108 } 109 } 110 111 if (audio.readyState > 0) { 112 displayDuration() 113 setSliderMax() 114 displayBufferedAmount() 115 } else { 116 audio.addEventListener('loadedmetadata', () => { 117 displayDuration() 118 setSliderMax() 119 displayBufferedAmount() 120 }) 121 } 122 123 playIconContainer.addEventListener('click', () => { 124 playIconContainer.classList.add('kg-audio-hide') 125 pauseIconContainer.classList.remove('kg-audio-hide') 126 audio.play() 127 requestAnimationFrame(whilePlaying) 128 }) 129 130 pauseIconContainer.addEventListener('click', () => { 131 pauseIconContainer.classList.add('kg-audio-hide') 132 playIconContainer.classList.remove('kg-audio-hide') 133 audio.pause() 134 cancelAnimationFrame(raf) 135 }) 136 137 muteIconContainer.addEventListener('click', () => { 138 muteIconContainer.classList.add('kg-audio-hide') 139 unmuteIconContainer.classList.remove('kg-audio-hide') 140 audio.muted = false 141 }) 142 143 unmuteIconContainer.addEventListener('click', () => { 144 unmuteIconContainer.classList.add('kg-audio-hide') 145 muteIconContainer.classList.remove('kg-audio-hide') 146 audio.muted = true 147 }) 148 149 playbackRateContainer.addEventListener('click', () => { 150 let nextPlaybackRate = playbackRates[(currentPlaybackRateIdx + 1) % 5] 151 currentPlaybackRateIdx = currentPlaybackRateIdx + 1 152 audio.playbackRate = nextPlaybackRate.rate 153 playbackRateContainer.textContent = nextPlaybackRate.label 154 }) 155 156 audio.addEventListener('progress', displayBufferedAmount) 157 158 seekSlider.addEventListener('input', (e) => { 159 showRangeProgress(e.target) 160 currentTimeContainer.textContent = calculateTime(seekSlider.value) 161 if (!audio.paused) { 162 cancelAnimationFrame(raf) 163 } 164 }) 165 166 seekSlider.addEventListener('change', () => { 167 audio.currentTime = seekSlider.value 168 if (!audio.paused) { 169 requestAnimationFrame(whilePlaying) 170 } 171 }) 172 173 volumeSlider.addEventListener('input', (e) => { 174 const value = e.target.value 175 showRangeProgress(e.target) 176 audio.volume = value / 100 177 }) 178 } 179 180 const audioCardElements = document.querySelectorAll('.kg-audio-card') 181 182 for (let i = 0; i < audioCardElements.length; i++) { 183 handleAudioPlayer(audioCardElements[i]) 184 } 185 })() 186})
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.