diff --git a/index.html b/index.html index b51fd6c..4b07427 100644 --- a/index.html +++ b/index.html @@ -19,6 +19,7 @@

View isolated demos:

  • lite-youtube-embed - progressively enhanced
  • lite-youtube-embed - custom poster image
  • lite-youtube-embed - with parameters
  • +
  • lite-youtube-embed - multiple embeds on same page
  • normal youtube embed diff --git a/src/lite-yt-embed.js b/src/lite-yt-embed.js index e8183c1..43275cf 100644 --- a/src/lite-yt-embed.js +++ b/src/lite-yt-embed.js @@ -53,11 +53,13 @@ class LiteYTEmbed extends HTMLElement { // TODO: In the future we could be like amp-youtube and silently swap in the iframe during idle time // We'd want to only do this for in-viewport or near-viewport ones: https://github.com/ampproject/amphtml/pull/5003 this.addEventListener('click', this.addIframe); - } - // // TODO: Support the the user changing the [videoid] attribute - // attributeChangedCallback() { - // } + // Chrome & Edge desktop have no problem with the basic YouTube Embed with ?autoplay=1 + // However Safari desktop and most/all mobile browsers do not successfully track the user gesture of clicking through the creation/loading of the iframe, + // so they don't autoplay automatically. Instead we must load an additional 2 sequential JS files (1KB + 165KB) (un-br) for the YT Player API + // TODO: Try loading the the YT API in parallel with our iframe and then attaching/playing it. #82 + this.needsYTApiForAutoplay = navigator.vendor.includes('Apple') || navigator.userAgent.includes('Mobi'); + } /** * Add a to the head @@ -96,13 +98,53 @@ class LiteYTEmbed extends HTMLElement { LiteYTEmbed.preconnected = true; } - addIframe(e) { + fetchYTPlayerApi() { + if (window.YT || (window.YT && window.YT.Player)) return; + + this.ytApiPromise = new Promise((res, rej) => { + var el = document.createElement('script'); + el.src = 'https://www.youtube.com/iframe_api'; + el.async = true; + el.onload = _ => { + YT.ready(res); + }; + el.onerror = rej; + this.append(el); + }); + } + + async addYTPlayerIframe(params) { + this.fetchYTPlayerApi(); + await this.ytApiPromise; + + const videoPlaceholderEl = document.createElement('div') + this.append(videoPlaceholderEl); + + const paramsObj = Object.fromEntries(params.entries()); + + new YT.Player(videoPlaceholderEl, { + width: '100%', + videoId: this.videoId, + playerVars: paramsObj, + events: { + 'onReady': event => { + event.target.playVideo(); + } + } + }); + } + + async addIframe(){ if (this.classList.contains('lyt-activated')) return; - e.preventDefault(); this.classList.add('lyt-activated'); const params = new URLSearchParams(this.getAttribute('params') || []); params.append('autoplay', '1'); + params.append('playsinline', '1'); + + if (this.needsYTApiForAutoplay) { + return this.addYTPlayerIframe(params); + } const iframeEl = document.createElement('iframe'); iframeEl.width = 560; diff --git a/variants/multiple-embeds.html b/variants/multiple-embeds.html new file mode 100644 index 0000000..591f210 --- /dev/null +++ b/variants/multiple-embeds.html @@ -0,0 +1,25 @@ + + + + lite-youtube-embed + + + + + +

    multiple embeds

    + + + + + + + + + + + + diff --git a/variants/solo.html b/variants/solo.html index 5fcced6..fbd4154 100644 --- a/variants/solo.html +++ b/variants/solo.html @@ -13,9 +13,5 @@

    lite-youtube custom element

    - diff --git a/variants/yt.html b/variants/yt.html index ca1aaf9..e9260d4 100644 --- a/variants/yt.html +++ b/variants/yt.html @@ -7,10 +7,10 @@ -

    typical iframe embed

    +

    typical iframe embed