PageSourceSearch

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

js buffer.com collected 2026-09-24 06:40:03 UTC 9,078 bytes, 286 lines download raw bytes

1setTimeout(function () {
2  ;(function () {
3    const handleVideoPlayer = function (videoElementContainer) {
4      const videoPlayer =
5        videoElementContainer.querySelector('.kg-video-player')
6      const videoPlayerContainer = videoElementContainer.querySelector(
7        '.kg-video-player-container',
8      )
9      const playIconContainer = videoElementContainer.querySelector(
10        '.kg-video-play-icon',
11      )
12      const pauseIconContainer = videoElementContainer.querySelector(
13        '.kg-video-pause-icon',
14      )
15      const seekSlider = videoElementContainer.querySelector(
16        '.kg-video-seek-slider',
17      )
18      const playbackRateContainer = videoElementContainer.querySelector(
19        '.kg-video-playback-rate',
20      )
21      const muteIconContainer = videoElementContainer.querySelector(
22        '.kg-video-mute-icon',
23      )
24      const unmuteIconContainer = videoElementContainer.querySelector(
25        '.kg-video-unmute-icon',
26      )
27      const volumeSlider = videoElementContainer.querySelector(
28        '.kg-video-volume-slider',
29      )
30      const videoEl = videoElementContainer.querySelector('video')
31      const durationContainer =
32        videoElementContainer.querySelector('.kg-video-duration')
33      const currentTimeContainer = videoElementContainer.querySelector(
34        '.kg-video-current-time',
35      )
36      const largePlayIcon = videoElementContainer.querySelector(
37        '.kg-video-large-play-icon',
38      )
39      const videoOverlay =
40        videoElementContainer.querySelector('.kg-video-overlay')
41      let playbackRates = [
42        {
43          rate: 0.75,
44          label: '0.7×',
45        },
46        {
47          rate: 1.0,
48          label: '1×',
49        },
50        {
51          rate: 1.25,
52          label: '1.2×',
53        },
54        {
55          rate: 1.75,
56          label: '1.7×',
57        },
58        {
59          rate: 2.0,
60          label: '2×',
61        },
62      ]
63
64      let raf = null
65      let currentPlaybackRateIdx = 1
66      if (!!videoEl.loop) {
67        largePlayIcon.classList.add('kg-video-hide-animated')
68        videoOverlay.classList.add('kg-video-hide-animated')
69      }
70      const whilePlaying = () => {
71        seekSlider.value = Math.floor(videoEl.currentTime)
72        currentTimeContainer.textContent = calculateTime(seekSlider.value)
73        videoPlayer.style.setProperty(
74          '--seek-before-width',
75          `${(seekSlider.value / seekSlider.max) * 100}%`,
76        )
77        raf = requestAnimationFrame(whilePlaying)
78      }
79
80      const showRangeProgress = (rangeInput) => {
81        if (rangeInput === seekSlider) {
82          videoPlayer.style.setProperty(
83            '--seek-before-width',
84            (rangeInput.value / rangeInput.max) * 100 + '%',
85          )
86        } else {
87          videoPlayer.style.setProperty(
88            '--volume-before-width',
89            (rangeInput.value / rangeInput.max) * 100 + '%',
90          )
91        }
92      }
93
94      const calculateTime = (secs) => {
95        const minutes = Math.floor(secs / 60)
96        const seconds = Math.floor(secs % 60)
97        const returnedSeconds = seconds < 10 ? `0${seconds}` : `${seconds}`
98        return `${minutes}:${returnedSeconds}`
99      }
100
101      const displayDuration = () => {
102        durationContainer.textContent = calculateTime(videoEl.duration)
103      }
104
105      const setSliderMax = () => {
106        seekSlider.max = Math.floor(videoEl.duration)
107      }
108
109      const displayBufferedAmount = () => {
110        if (videoEl.buffered.length > 0) {
111          const bufferedAmount = Math.floor(
112            videoEl.buffered.end(videoEl.buffered.length - 1),
113          )
114          videoPlayer.style.setProperty(
115            '--buffered-width',
116            `${(bufferedAmount / seekSlider.max) * 100}%`,
117          )
118        }
119      }
120
121      if (videoEl.readyState > 0) {
122        displayDuration()
123        setSliderMax()
124        displayBufferedAmount()
125        if (videoEl.autoplay) {
126          raf = requestAnimationFrame(whilePlaying)
127          playIconContainer.classList.add('kg-video-hide')
128          pauseIconContainer.classList.remove('kg-video-hide')
129        }
130        if (videoEl.muted) {
131          unmuteIconContainer.classList.add('kg-video-hide')
132          muteIconContainer.classList.remove('kg-video-hide')
133        }
134      } else {
135        videoEl.addEventListener('loadedmetadata', () => {
136          displayDuration()
137          setSliderMax()
138          displayBufferedAmount()
139          if (videoEl.autoplay) {
140            raf = requestAnimationFrame(whilePlaying)
141            playIconContainer.classList.add('kg-video-hide')
142            pauseIconContainer.classList.remove('kg-video-hide')
143          }
144          if (videoEl.muted) {
145            unmuteIconContainer.classList.add('kg-video-hide')
146            muteIconContainer.classList.remove('kg-video-hide')
147          }
148        })
149      }
150
151      videoElementContainer.onmouseover = () => {
152        if (!videoEl.loop) {
153          videoPlayerContainer.classList.remove('kg-video-hide-animated')
154        }
155      }
156
157      videoElementContainer.onmouseleave = () => {
158        const isPlaying = !!(
159          videoEl.currentTime > 0 &&
160          !videoEl.paused &&
161          !videoEl.ended &&
162          videoEl.readyState > 2
163        )
164        if (isPlaying) {
165          videoPlayerContainer.classList.add('kg-video-hide-animated')
166        }
167      }
168
169      videoElementContainer.addEventListener('click', () => {
170        if (!videoEl.loop) {
171          const isPlaying = !!(
172            videoEl.currentTime > 0 &&
173            !videoEl.paused &&
174            !videoEl.ended &&
175            videoEl.readyState > 2
176          )
177          if (isPlaying) {
178            handleOnPause()
179          } else {
180            handleOnPlay()
181          }
182        }
183      })
184
185      videoEl.onplay = () => {
186        largePlayIcon.classList.add('kg-video-hide-animated')
187        videoOverlay.classList.add('kg-video-hide-animated')
188        playIconContainer.classList.add('kg-video-hide')
189        pauseIconContainer.classList.remove('kg-video-hide')
190      }
191
192      const handleOnPlay = () => {
193        largePlayIcon.classList.add('kg-video-hide-animated')
194        videoOverlay.classList.add('kg-video-hide-animated')
195        playIconContainer.classList.add('kg-video-hide')
196        pauseIconContainer.classList.remove('kg-video-hide')
197        videoEl.play()
198        raf = requestAnimationFrame(whilePlaying)
199      }
200
201      const handleOnPause = () => {
202        pauseIconContainer.classList.add('kg-video-hide')
203        playIconContainer.classList.remove('kg-video-hide')
204        videoEl.pause()
205        cancelAnimationFrame(raf)
206      }
207
208      largePlayIcon.addEventListener('click', (event) => {
209        event.stopPropagation()
210        handleOnPlay()
211      })
212
213      playIconContainer.addEventListener('click', (event) => {
214        event.stopPropagation()
215        handleOnPlay()
216      })
217
218      pauseIconContainer.addEventListener('click', (event) => {
219        event.stopPropagation()
220        handleOnPause()
221      })
222
223      muteIconContainer.addEventListener('click', (event) => {
224        event.stopPropagation()
225        muteIconContainer.classList.add('kg-video-hide')
226        unmuteIconContainer.classList.remove('kg-video-hide')
227        videoEl.muted = false
228      })
229
230      unmuteIconContainer.addEventListener('click', (event) => {
231        event.stopPropagation()
232        unmuteIconContainer.classList.add('kg-video-hide')
233        muteIconContainer.classList.remove('kg-video-hide')
234        videoEl.muted = true
235      })
236
237      playbackRateContainer.addEventListener('click', (event) => {
238        event.stopPropagation()
239        let nextPlaybackRate = playbackRates[(currentPlaybackRateIdx + 1) % 5]
240        currentPlaybackRateIdx = currentPlaybackRateIdx + 1
241        videoEl.playbackRate = nextPlaybackRate.rate
242        playbackRateContainer.textContent = nextPlaybackRate.label
243      })
244
245      videoEl.addEventListener('progress', displayBufferedAmount)
246
247      seekSlider.addEventListener('input', (e) => {
248        e.stopPropagation()
249        showRangeProgress(e.target)
250        currentTimeContainer.textContent = calculateTime(seekSlider.value)
251        if (!videoEl.paused) {
252          cancelAnimationFrame(raf)
253        }
254      })
255
256      seekSlider.addEventListener('change', (event) => {
257        event.stopPropagation()
258        videoEl.currentTime = seekSlider.value
259        if (!videoEl.paused) {
260          requestAnimationFrame(whilePlaying)
261        }
262      })
263
264      volumeSlider.addEventListener('click', (event) => {
265        event.stopPropagation()
266      })
267
268      seekSlider.addEventListener('click', (event) => {
269        event.stopPropagation()
270      })
271
272      volumeSlider.addEventListener('input', (e) => {
273        e.stopPropagation()
274        const value = e.target.value
275        showRangeProgress(e.target)
276        videoEl.volume = value / 100
277      })
278    }
279
280    const videoCardElements = document.querySelectorAll('.kg-video-card')
281
282    for (let i = 0; i < videoCardElements.length; i++) {
283      handleVideoPlayer(videoCardElements[i])
284    }
285  })()
286})

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.