Closed RoofTurkey closed 3 years ago
I'm not exactly sure how that patch works for you; passing the frame id out of the component won't allow you to access it with the JS API. The iframe is within the shadow dom.
To resolve this, I patched the event in the above PR and if you pass the iframe ref from the shadow to the YT.Player()
method, you'll end up with a working solution (full example in demo/index.html):
<lite-youtube
id="test-jsapi"
videoid="guJLfqTFfIw"
params="enablejsapi=1">
</lite-youtube>
<script>
let player;
// do stuff with the callbacks and what not
document.addEventListener('liteYoutubeIframeLoaded', () => {
// There is only ever one iframe, and you know it's in the ShadowRoot once the event is thrown
const iframe = document.querySelector('#test-jsapi').shadowRoot.querySelector('iframe');
player = new YT.Player(iframe, {
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}, false);
</script>
Ah, the reason I also added in a (unique) id was to be able to load multiple videos on one page. With the event I can easily add the YouTube JS api once an iframe has loaded. My JS code handling this looks like this (and is currently running in our production environment):
let youTubeIframeScriptLoaded = false;
let youTubePlayerLoaded = false;
document.addEventListener('youTubeIframeLoaded', function (event) {
if (!youTubeIframeScriptLoaded) {
// See: https://developers.google.com/youtube/iframe_api_reference
const tag = document.createElement('script');
tag.id = 'youtube-iframe-api';
tag.src = 'https://www.youtube.com/iframe_api';
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
youTubeIframeScriptLoaded = true;
}
let player;
function onYouTubeIframeAPIReady() {
let youTubeIframe = document.getElementById(event.detail.id + '-root').shadowRoot.getElementById(event.detail.id);
player = new YT.Player(youTubeIframe, {
events: {}
});
youTubePlayerLoaded = true;
}
if (!youTubePlayerLoaded) {
window.onYouTubeIframeAPIReady = onYouTubeIframeAPIReady;
} else {
onYouTubeIframeAPIReady();
}
const photoGalleryModal = $('#photogallery');
photoGalleryModal.on('hide.bs.modal', function () {
pausePlayerIfPlaying(player);
});
photoGalleryModal.on('show.bs.modal', function () {
pausePlayerIfPlaying(player);
});
$('#carouselBig').on('slide.bs.carousel', function () {
pausePlayerIfPlaying(player);
});
$('#carouselSmall').on('slide.bs.carousel', function () {
pausePlayerIfPlaying(player);
});
function pausePlayerIfPlaying(player) {
if (player === undefined) {
return;
}
if (player.getPlayerState() === YT.PlayerState.PLAYING) {
player.pauseVideo();
}
}
});
With your solution multiple videos on one page would not be supported, while (as you can see here) it could be done using the frame id.
@justinribeiro+lite-youtube+0.9.1.patch.zip
When using this package I was missing events, therefore I wrote this patch that adds event dispatching when a YouTube iframe has finished loading (then you can start using the YouTube JS API for example)
Would be nice if you could add this to the codebase so I no longer need this patch and other developers can also use this functionality.