PageSourceSearch

https://buffer.com/resources/cards/audio.js/

js buffer.com collected 2026-09-24 06:39:59 UTC 5,798 bytes, 186 lines download raw bytes

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.