My goal with this was to wrap the terrible YouTube Embed API in a Stimulus controller that would allow me to access the underlying API while providing some convenience methods. One key outcome is that the controller emits youtube
events which contain the current position in the video. This means that other code can now respond to the position you are at in the video.
<div data-controller="youtube" data-youtube-code-value="Lo_1pyQ7xvc">
<button data-action="youtube#play">Play</button>
<button data-action="youtube#pause">Pause</button>
<button data-action="youtube#stop">Stop</button>
<br>
<div data-youtube-target="frame"></div>
</div>
The button
s and br
are not neccessary, they just help show off the functionality.
When the controller connects, data-duration
, data-time
and data-state
attributes will appear on the controller element. This is really handy if you're using this element to initiate a Reflex, as all of the attributes will be automatically sent to the server as part of the Reflex.
If you want to send the YouTube instance commands, you'll need a DOM element reference to the container div
. I'm going to assume that you have that, and that it's available to you as $0
.
$0.addEventListener('youtube', e => console.log(e.detail.time))
$0.youtube.player.mute()
The controller element emits one non-bubbling youtube
event every second that the video is playing.
The controller element has a youtube
accessor which is a reference to the internal state of the Stimulus controller.
I did not want to attempt to exhaustively replicate the functionality of every getter and setter offered by the YouTube API. If you want to mute()
or unMute()
you can access the underlying YouTube API via the player
accessor.
You must specify a data-youtube-code-value
attribute. data-youtube-width-value
and data-youtube-height-value
are optional.
- play()
- pause()
- stop()
- seek(seconds)
- player // reference to wrapped YouTube API instance
- time // current position in the video, as an integer representing seconds
- duration // number of seconds total in the video
- state // see states below
- loaded // percentage of video that has been downloaded / buffered, expressed as a float from 0 to 1
If you want to convert loaded
to a percentage, multiply it by 100 and parseInt()
.
-1 (unstarted) 0 (ended) 1 (playing) 2 (paused) 3 (buffering) 5 (video cued)
The only difference with my setup is that I use importmap so I type
➜ CAMPANAZZO git:(homev5) ✗ ./bin/importmap pin youtube-player
Pinning "youtube-player" to https://ga.jspm.io/npm:[email protected]/dist/index.js
Pinning "debug" to https://ga.jspm.io/npm:[email protected]/src/browser.js
Pinning "load-script" to https://ga.jspm.io/npm:[email protected]/index.js
Pinning "ms" to https://ga.jspm.io/npm:[email protected]/index.js
Pinning "process" to https://ga.jspm.io/npm:@jspm/[email protected]/nodelibs/browser/process-production.js
Pinning "sister" to https://ga.jspm.io/npm:[email protected]/src/sister.js