@justinribeiro/lite-youtube
Advanced tools
Comparing version 1.5.0 to 1.6.0
@@ -21,2 +21,3 @@ export declare class LiteYTEmbed extends HTMLElement { | ||
get autoLoad(): boolean; | ||
get autoPause(): boolean; | ||
get noCookie(): boolean; | ||
@@ -23,0 +24,0 @@ get posterQuality(): string; |
@@ -8,6 +8,6 @@ export class LiteYTEmbed extends HTMLElement { | ||
static get observedAttributes() { | ||
return ['videoid', 'playlistid']; | ||
return ['videoid', 'playlistid', 'videoplay', 'videotitle']; | ||
} | ||
connectedCallback() { | ||
this.addEventListener('pointerover', LiteYTEmbed.warmConnections, { | ||
this.addEventListener('pointerover', () => LiteYTEmbed.warmConnections(this), { | ||
once: true, | ||
@@ -36,6 +36,6 @@ }); | ||
get videoPlay() { | ||
return this.getAttribute('videoPlay') || 'Play'; | ||
return this.getAttribute('videoplay') || 'Play'; | ||
} | ||
set videoPlay(name) { | ||
this.setAttribute('videoPlay', name); | ||
this.setAttribute('videoplay', name); | ||
} | ||
@@ -48,2 +48,5 @@ get videoStartAt() { | ||
} | ||
get autoPause() { | ||
return this.hasAttribute('autopause'); | ||
} | ||
get noCookie() { | ||
@@ -74,2 +77,5 @@ return this.hasAttribute('nocookie'); | ||
:host { | ||
--aspect-ratio: var(--lite-youtube-aspect-ratio, 16 / 9); | ||
--aspect-ratio-short: var(--lite-youtube-aspect-ratio-short, 9 / 16); | ||
--frame-shadow-visible: var(--lite-youtube-frame-shadow-visible, yes); | ||
contain: content; | ||
@@ -79,3 +85,3 @@ display: block; | ||
width: 100%; | ||
padding-bottom: calc(100% / (16 / 9)); | ||
aspect-ratio: var(--aspect-ratio); | ||
} | ||
@@ -85,3 +91,3 @@ | ||
:host([short]) { | ||
padding-bottom: calc(100% / (9 / 16)); | ||
aspect-ratio: var(--aspect-ratio-short); | ||
} | ||
@@ -101,15 +107,18 @@ } | ||
#fallbackPlaceholder { | ||
#fallbackPlaceholder, slot[name=image]::slotted(*) { | ||
object-fit: cover; | ||
width: 100%; | ||
} | ||
#frame::before { | ||
content: ''; | ||
display: block; | ||
position: absolute; | ||
top: 0; | ||
background-image: linear-gradient(180deg, #111 -20%, transparent 90%); | ||
height: 60px; | ||
width: 100%; | ||
z-index: 1; | ||
@container style(--frame-shadow-visible: yes) { | ||
#frame::before { | ||
content: ''; | ||
display: block; | ||
position: absolute; | ||
top: 0; | ||
background-image: linear-gradient(180deg, #111 -20%, transparent 90%); | ||
height: 60px; | ||
width: 100%; | ||
z-index: 1; | ||
} | ||
} | ||
@@ -155,5 +164,7 @@ | ||
<picture> | ||
<source id="webpPlaceholder" type="image/webp"> | ||
<source id="jpegPlaceholder" type="image/jpeg"> | ||
<img id="fallbackPlaceholder" referrerpolicy="origin" loading="lazy"> | ||
<slot name="image"> | ||
<source id="webpPlaceholder" type="image/webp"> | ||
<source id="jpegPlaceholder" type="image/jpeg"> | ||
<img id="fallbackPlaceholder" referrerpolicy="origin" loading="lazy"> | ||
</slot> | ||
</picture> | ||
@@ -175,3 +186,3 @@ <button id="playButton"></button> | ||
this.setAttribute('title', `${this.videoPlay}: ${this.videoTitle}`); | ||
if (this.autoLoad || this.isYouTubeShort()) { | ||
if (this.autoLoad || this.isYouTubeShort() || this.autoPause) { | ||
this.initIntersectionObserver(); | ||
@@ -181,19 +192,9 @@ } | ||
attributeChangedCallback(name, oldVal, newVal) { | ||
switch (name) { | ||
case 'videoid': | ||
case 'playlistid': | ||
case 'videoTitle': | ||
case 'videoPlay': { | ||
if (oldVal !== newVal) { | ||
this.setupComponent(); | ||
if (this.domRefFrame.classList.contains('activated')) { | ||
this.domRefFrame.classList.remove('activated'); | ||
this.shadowRoot.querySelector('iframe').remove(); | ||
this.isIframeLoaded = false; | ||
} | ||
} | ||
break; | ||
if (oldVal !== newVal) { | ||
this.setupComponent(); | ||
if (this.domRefFrame.classList.contains('activated')) { | ||
this.domRefFrame.classList.remove('activated'); | ||
this.shadowRoot.querySelector('iframe').remove(); | ||
this.isIframeLoaded = false; | ||
} | ||
default: | ||
break; | ||
} | ||
@@ -212,2 +213,5 @@ } | ||
} | ||
if (this.autoPause) { | ||
this.params = `enablejsapi=1`; | ||
} | ||
if (this.isYouTubeShort()) { | ||
@@ -218,3 +222,3 @@ this.params = `loop=1&mute=1&modestbranding=1&playsinline=1&rel=0&enablejsapi=1&playlist=${this.videoId}`; | ||
const iframeHTML = ` | ||
<iframe frameborder="0" title="${this.videoTitle}" | ||
<iframe credentialless frameborder="0" title="${this.videoTitle}" | ||
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen | ||
@@ -255,3 +259,3 @@ src="https://www.youtube${wantsNoCookie}.com/embed/${embedTarget}autoplay=${autoplay}&${this.params}" | ||
if (entry.isIntersecting && !this.isIframeLoaded) { | ||
LiteYTEmbed.warmConnections(); | ||
LiteYTEmbed.warmConnections(this); | ||
this.addIframe(true); | ||
@@ -263,2 +267,14 @@ observer.unobserve(this); | ||
observer.observe(this); | ||
if (this.autoPause) { | ||
const windowPause = new IntersectionObserver((e, o) => { | ||
e.forEach(entry => { | ||
if (entry.intersectionRatio !== 1) { | ||
this.shadowRoot | ||
.querySelector('iframe') | ||
?.contentWindow?.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*'); | ||
} | ||
}); | ||
}, { threshold: 1 }); | ||
windowPause.observe(this); | ||
} | ||
} | ||
@@ -285,3 +301,3 @@ attemptShortAutoPlay() { | ||
} | ||
static warmConnections() { | ||
static warmConnections(context) { | ||
if (LiteYTEmbed.isPreconnected || window.liteYouTubeIsPreconnected) | ||
@@ -291,6 +307,11 @@ return; | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://s.ytimg.com'); | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://www.youtube.com'); | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://www.google.com'); | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://googleads.g.doubleclick.net'); | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://static.doubleclick.net'); | ||
if (!context.noCookie) { | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://www.youtube.com'); | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://www.google.com'); | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://googleads.g.doubleclick.net'); | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://static.doubleclick.net'); | ||
} | ||
else { | ||
LiteYTEmbed.addPrefetch('preconnect', 'https://www.youtube-nocookie.com'); | ||
} | ||
LiteYTEmbed.isPreconnected = true; | ||
@@ -297,0 +318,0 @@ window.liteYouTubeIsPreconnected = true; |
@@ -28,3 +28,3 @@ { | ||
"license": "MIT", | ||
"version": "1.5.0", | ||
"version": "1.6.0", | ||
"type": "module", | ||
@@ -40,14 +40,17 @@ "main": "lite-youtube.js", | ||
"@esm-bundle/chai": "^4.3.4-fix.0", | ||
"@open-wc/eslint-config": "^7.0.0", | ||
"@open-wc/testing": "^3.0.0", | ||
"@typescript-eslint/eslint-plugin": "^5.0.0", | ||
"@typescript-eslint/parser": "^5.0.0", | ||
"@web/dev-server": "^0.1.24", | ||
"@web/test-runner": "^0.13.18", | ||
"concurrently": "^7.0.0", | ||
"eslint": "^8.0.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"istanbul-badges-readme": "^1.4.0", | ||
"prettier": "^2.0.0", | ||
"typescript": "^4.7.0" | ||
"@open-wc/eslint-config": "^12.0.3", | ||
"@open-wc/testing": "^4.0.0", | ||
"@types/mocha": "^10.0.9", | ||
"@types/node": "^22.9.0", | ||
"@typescript-eslint/eslint-plugin": "^8.14.0", | ||
"@typescript-eslint/parser": "^8.14.0", | ||
"@web/dev-server": "^0.4.6", | ||
"@web/test-runner": "^0.19.0", | ||
"concurrently": "^9.1.0", | ||
"eslint": "^9.14.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
"istanbul-badges-readme": "^1.9.0", | ||
"mocha": "^10.8.2", | ||
"prettier": "^3.3.3", | ||
"typescript": "^5.6.3" | ||
}, | ||
@@ -82,2 +85,2 @@ "eslintConfig": { | ||
} | ||
} | ||
} |
@@ -25,2 +25,3 @@ [![npm version](https://badge.fury.io/js/@justinribeiro%2Flite-youtube.svg)](https://badge.fury.io/js/@justinribeiro%2Flite-youtube) ![min+gzip](https://img.shields.io/badge/min%2Bgzip-2.2kb-blue) ![min+br](https://img.shields.io/badge/min%2Bbr-1.7kb-blue) [![](https://data.jsdelivr.com/v1/package/npm/@justinribeiro/lite-youtube/badge)](https://www.jsdelivr.com/package/npm/@justinribeiro/lite-youtube) | ||
- _new in v1.5_: Adds support for nonce attribute via `window.liteYouTubeNonce` for CSP 2/3 support. | ||
- _new in v1.6_: Adds `autoPause` for pausing videos scrolled off screen; adds `--lite-youtube-aspect-ratio` CSS custom property create custom aspect ratio videos; adds `--lite-youtube-frame-shadow-visible` CSS custom property to disable frame shadow (flat look); adds a named slot `image` that allows for setting custom poster image; adds `credentialless` for COEP | ||
@@ -51,3 +52,3 @@ ## Install via package manager | ||
```html | ||
<script type="module" src="https://cdn.jsdelivr.net/npm/@justinribeiro/lite-youtube@1.5.0/lite-youtube.js"></script> | ||
<script type="module" src="https://cdn.jsdelivr.net/npm/@justinribeiro/lite-youtube@1/lite-youtube.min.js"></script> | ||
``` | ||
@@ -189,2 +190,35 @@ | ||
## Use the named slot to set a custom poster image | ||
```html | ||
<lite-youtube videoid="guJLfqTFfIw"> | ||
<img slot="image" src="my-poster-override.jpg"> | ||
</lite-youtube> | ||
``` | ||
## Set custom aspect ratio | ||
```html | ||
<style> | ||
lite-youtube { | ||
--lite-youtube-aspect-ratio: 2 / 3; | ||
} | ||
</style> | ||
<lite-youtube videoid="guJLfqTFfIw"></lite-youtube> | ||
``` | ||
## Disable the frame shadow (flat look) | ||
```html | ||
<style> | ||
lite-youtube { | ||
/* No Shadow */ | ||
--lite-youtube-frame-shadow-visible: no; | ||
} | ||
</style> | ||
<lite-youtube videoid="guJLfqTFfIw"></lite-youtube> | ||
``` | ||
## Auto-Pause video when scrolled out of view | ||
```html | ||
<lite-youtube videoid="VLrYOji75Vc" autopause></lite-youtube> | ||
``` | ||
## YouTube QueryParams | ||
@@ -191,0 +225,0 @@ |
Sorry, the diff of this file is not supported yet
47670
343
259
16