-
Notifications
You must be signed in to change notification settings - Fork 278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
use YT player API to force autoplay, resolving double-tap bug #109
Changes from 6 commits
a652608
b5575bc
4667952
0461e74
62724cd
53b22c6
f3b132e
185af94
1fa89dd
1f885c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,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); | ||
|
||
|
||
// Chrome & Edge have no problem with the basic YouTube Embed with ?autoplay=1 | ||
// However Safari and Firefox 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 300KB (ungz) of JS for the YT Player API | ||
// TODO: chrome android seems to also need this | ||
this.needsYTApiForAutoplay = navigator.vendor.includes('Apple') || navigator.userAgent.includes('Firefox'); | ||
} | ||
|
||
// // TODO: Support the the user changing the [videoid] attribute | ||
|
@@ -95,12 +102,53 @@ class LiteYTEmbed extends HTMLElement { | |
LiteYTEmbed.preconnected = true; | ||
} | ||
|
||
addIframe() { | ||
fetchYTPlayerApi() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. alsoo wondering if there's a lazy way to attach... #82 hmmm! EDIT: see also #146 (comment) |
||
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()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. im a little scared this newish feature will pose problems with various people's tsc/acorn/estree versions, if they're too old. but hopefully its fine. |
||
|
||
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; | ||
this.classList.add('lyt-activated'); | ||
|
||
const params = new URLSearchParams(this.getAttribute('params') || []); | ||
params.append('autoplay', '1'); | ||
params.append('playsinline', '1'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
if (this.needsYTApiForAutoplay) { | ||
return this.addYTPlayerIframe(params); | ||
} | ||
|
||
const iframeEl = document.createElement('iframe'); | ||
iframeEl.width = 560; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<title>lite-youtube-embed</title> | ||
<meta charset="utf-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
<link rel="stylesheet" href="../src/lite-yt-embed.css" /> | ||
</head> | ||
<body> | ||
<h1>multiple embeds</h1> | ||
|
||
<lite-youtube videoid="ogfYd705cRs" playlabel="Play: Keynote (Google I/O '18)"></lite-youtube> | ||
|
||
|
||
<lite-youtube videoid="n57U2_-3NLQ" playlabel="Play: Chrome Dev Summit 2021 recap"></lite-youtube> | ||
|
||
|
||
<script src="../src/lite-yt-embed.js"></script> | ||
|
||
<!-- <script> | ||
// Simulate duplicate iframe problem. https://github.com/paulirish/lite-youtube-embed/issues/92 | ||
document.body.addEventListener('click', e => e.target.click()); | ||
</script> --> | ||
</body> | ||
</html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i figure ill have to change this to be some other sniff. don't think there's a good "feature detect" that's equivalent to failing to successfully autoplay. so yeah.. we'll do a UA sniff of some sort.
but this'll need to also include chrome android as well. and perhaps more.
some testing required:
has problems with autoplay on https://lite-youtube-embed-git-master-paulirish.vercel.app/
ios safari
desktop safari
firefox android
chrome android
edge mobile (probably.. untested)
no problems
desktop chrome
desktop firefox
desktop edge (on mac)