generated from adobe/aem-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into 132-section-separator
- Loading branch information
Showing
21 changed files
with
404 additions
and
66 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* copied from https://github.com/paulirish/lite-youtube-embed/releases/tag/v0.2.0 */ | ||
/* stylelint-disable */ | ||
|
||
lite-youtube { | ||
background-color: #000; | ||
position: relative; | ||
display: block; | ||
contain: content; | ||
background-position: center center; | ||
background-size: cover; | ||
cursor: pointer; | ||
max-width: 720px; | ||
} | ||
|
||
/* gradient */ | ||
lite-youtube::before { | ||
content: ''; | ||
display: block; | ||
position: absolute; | ||
top: 0; | ||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAADGCAYAAAAT+OqFAAAAdklEQVQoz42QQQ7AIAgEF/T/D+kbq/RWAlnQyyazA4aoAB4FsBSA/bFjuF1EOL7VbrIrBuusmrt4ZZORfb6ehbWdnRHEIiITaEUKa5EJqUakRSaEYBJSCY2dEstQY7AuxahwXFrvZmWl2rh4JZ07z9dLtesfNj5q0FU3A5ObbwAAAABJRU5ErkJggg==); | ||
background-position: top; | ||
background-repeat: repeat-x; | ||
height: 60px; | ||
padding-bottom: 50px; | ||
width: 100%; | ||
transition: all 0.2s cubic-bezier(0, 0, 0.2, 1); | ||
} | ||
|
||
/* responsive iframe with a 16:9 aspect ratio | ||
thanks https://css-tricks.com/responsive-iframes/ | ||
*/ | ||
lite-youtube::after { | ||
content: ""; | ||
display: block; | ||
padding-bottom: calc(100% / (16 / 9)); | ||
} | ||
|
||
lite-youtube > iframe { | ||
width: 100%; | ||
height: 100%; | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
border: 0; | ||
} | ||
|
||
/* play button */ | ||
lite-youtube > .lty-playbtn { | ||
width: 68px; | ||
height: 48px; | ||
position: absolute; | ||
cursor: pointer; | ||
transform: translate3d(-50%, -50%, 0); | ||
top: 50%; | ||
left: 50%; | ||
z-index: 1; | ||
background-color: transparent; | ||
/* YT's actual play button svg */ | ||
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 68 48"><path fill="%23f00" fill-opacity="0.8" d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z"></path><path d="M 45,24 27,14 27,34" fill="%23fff"></path></svg>'); | ||
filter: grayscale(100%); | ||
transition: filter .1s cubic-bezier(0, 0, 0.2, 1); | ||
border: none; | ||
} | ||
|
||
lite-youtube:hover > .lty-playbtn, | ||
lite-youtube .lty-playbtn:focus { | ||
filter: none; | ||
} | ||
|
||
/* Post-click styles */ | ||
lite-youtube.lyt-activated { | ||
cursor: unset; | ||
} | ||
|
||
lite-youtube.lyt-activated::before, | ||
lite-youtube.lyt-activated > .lty-playbtn { | ||
opacity: 0; | ||
pointer-events: none; | ||
} | ||
|
||
.lyt-visually-hidden { | ||
clip: rect(0 0 0 0); | ||
clip-path: inset(50%); | ||
height: 1px; | ||
overflow: hidden; | ||
position: absolute; | ||
white-space: nowrap; | ||
width: 1px; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
// Copied from https://github.com/paulirish/lite-youtube-embed/releases/tag/v0.2.0 | ||
/* eslint-disable */ | ||
/** | ||
* A lightweight youtube embed. Still should feel the same to the user, just MUCH faster to initialize and paint. | ||
* | ||
* Thx to these as the inspiration | ||
* https://storage.googleapis.com/amp-vs-non-amp/youtube-lazy.html | ||
* https://autoplay-youtube-player.glitch.me/ | ||
* | ||
* Once built it, I also found these: | ||
* https://github.com/ampproject/amphtml/blob/master/extensions/amp-youtube (👍👍) | ||
* https://github.com/Daugilas/lazyYT | ||
* https://github.com/vb/lazyframe | ||
*/ | ||
class LiteYTEmbed extends HTMLElement { | ||
connectedCallback() { | ||
this.videoId = this.getAttribute('videoid'); | ||
|
||
let playBtnEl = this.querySelector('.lty-playbtn'); | ||
// A label for the button takes priority over a [playlabel] attribute on the custom-element | ||
this.playLabel = (playBtnEl && playBtnEl.textContent.trim()) || this.getAttribute('playlabel') || 'Play'; | ||
|
||
/** | ||
* Lo, the youtube placeholder image! (aka the thumbnail, poster image, etc) | ||
* | ||
* See https://github.com/paulirish/lite-youtube-embed/blob/master/youtube-thumbnail-urls.md | ||
* | ||
* TODO: Do the sddefault->hqdefault fallback | ||
* - When doing this, apply referrerpolicy (https://github.com/ampproject/amphtml/pull/3940) | ||
* TODO: Consider using webp if supported, falling back to jpg | ||
*/ | ||
if (!this.style.backgroundImage) { | ||
this.posterUrl = `https://i.ytimg.com/vi/${this.videoId}/hqdefault.jpg`; | ||
// Warm the connection for the poster image | ||
LiteYTEmbed.addPrefetch('preload', this.posterUrl, 'image'); | ||
|
||
this.style.backgroundImage = `url("${this.posterUrl}")`; | ||
} | ||
|
||
// Set up play button, and its visually hidden label | ||
if (!playBtnEl) { | ||
playBtnEl = document.createElement('button'); | ||
playBtnEl.type = 'button'; | ||
playBtnEl.classList.add('lty-playbtn'); | ||
this.append(playBtnEl); | ||
} | ||
if (!playBtnEl.textContent) { | ||
const playBtnLabelEl = document.createElement('span'); | ||
playBtnLabelEl.className = 'lyt-visually-hidden'; | ||
playBtnLabelEl.textContent = this.playLabel; | ||
playBtnEl.append(playBtnLabelEl); | ||
} | ||
|
||
// On hover (or tap), warm up the TCP connections we're (likely) about to use. | ||
this.addEventListener('pointerover', LiteYTEmbed.warmConnections, {once: true}); | ||
|
||
// Once the user clicks, add the real iframe and drop our play button | ||
// 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', e => this.addIframe()); | ||
} | ||
|
||
// // TODO: Support the the user changing the [videoid] attribute | ||
// attributeChangedCallback() { | ||
// } | ||
|
||
/** | ||
* Add a <link rel={preload | preconnect} ...> to the head | ||
*/ | ||
static addPrefetch(kind, url, as) { | ||
const linkEl = document.createElement('link'); | ||
linkEl.rel = kind; | ||
linkEl.href = url; | ||
if (as) { | ||
linkEl.as = as; | ||
} | ||
document.head.append(linkEl); | ||
} | ||
|
||
/** | ||
* Begin pre-connecting to warm up the iframe load | ||
* Since the embed's network requests load within its iframe, | ||
* preload/prefetch'ing them outside the iframe will only cause double-downloads. | ||
* So, the best we can do is warm up a few connections to origins that are in the critical path. | ||
* | ||
* Maybe `<link rel=preload as=document>` would work, but it's unsupported: http://crbug.com/593267 | ||
* But TBH, I don't think it'll happen soon with Site Isolation and split caches adding serious complexity. | ||
*/ | ||
static warmConnections() { | ||
if (LiteYTEmbed.preconnected) return; | ||
|
||
// The iframe document and most of its subresources come right off youtube.com | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://www.youtube-nocookie.com'); | ||
// The botguard script is fetched off from google.com | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://www.google.com'); | ||
|
||
// Not certain if these ad related domains are in the critical path. Could verify with domain-specific throttling. | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://googleads.g.doubleclick.net'); | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://static.doubleclick.net'); | ||
|
||
LiteYTEmbed.preconnected = true; | ||
} | ||
|
||
addIframe() { | ||
const params = new URLSearchParams(this.getAttribute('params') || []); | ||
params.append('autoplay', '1'); | ||
|
||
const iframeEl = document.createElement('iframe'); | ||
iframeEl.width = 560; | ||
iframeEl.height = 315; | ||
// No encoding necessary as [title] is safe. https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#:~:text=Safe%20HTML%20Attributes%20include | ||
iframeEl.title = this.playLabel; | ||
iframeEl.allow = 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture'; | ||
iframeEl.allowFullscreen = true; | ||
// AFAIK, the encoding here isn't necessary for XSS, but we'll do it only because this is a URL | ||
// https://stackoverflow.com/q/64959723/89484 | ||
iframeEl.src = `https://www.youtube-nocookie.com/embed/${encodeURIComponent(this.videoId)}?${params.toString()}`; | ||
this.append(iframeEl); | ||
|
||
this.classList.add('lyt-activated'); | ||
|
||
// Set focus for a11y | ||
this.querySelector('iframe').focus(); | ||
} | ||
} | ||
// Register custom element | ||
customElements.define('lite-youtube', LiteYTEmbed); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.