Skip to content

Commit

Permalink
feat(auto-pause): adds autopause attribute for pausing videos off of …
Browse files Browse the repository at this point in the history
…screen (#112)
  • Loading branch information
justinribeiro authored Nov 15, 2024
1 parent 3deee62 commit 316b2b9
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 4 deletions.
46 changes: 46 additions & 0 deletions demo/auto-pause.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes"
/>
<title>lite-youtube demo</title>
<script type="module" src="../lite-youtube.js"></script>

<style>
* {
box-sizing: content-box;
}
body {
max-width: 800px;
margin: auto;
}
pre {
width: 100%;
padding: 1em;
overflow-x: scroll;
background-clip: z;
background-color: #eee;
}
.styleIt {
width: 400px;
}
#bigBlock {
height: 600px;
}
#noShadow {
--lite-youtube-frame-shadow-visible: no;
}
</style>
</head>
<body>
<pre>
&lt;style&gt;&#10; lite-youtube {&#10; --lite-youtube-frame-shadow-visible: no;&#10; }&#10; &lt;/style&gt;
&lt;lite-youtube videoid=&quot;guJLfqTFfIw&quot;&lt;/lite-youtube&gt;
</pre>
<lite-youtube id="noShadow" videoid="VLrYOji75Vc" autopause></lite-youtube>
<div style="height: 400vh"></div>
</body>
</html>
43 changes: 39 additions & 4 deletions lite-youtube.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,13 @@ export class LiteYTEmbed extends HTMLElement {
}

connectedCallback(): void {
this.addEventListener('pointerover', () => LiteYTEmbed.warmConnections(this), {
once: true,
});
this.addEventListener(
'pointerover',
() => LiteYTEmbed.warmConnections(this),
{
once: true,
},
);

this.addEventListener('click', () => this.addIframe());
}
Expand Down Expand Up @@ -83,6 +87,10 @@ export class LiteYTEmbed extends HTMLElement {
return this.hasAttribute('autoload');
}

get autoPause(): boolean {
return this.hasAttribute('autopause');
}

get noCookie(): boolean {
return this.hasAttribute('nocookie');
}
Expand Down Expand Up @@ -231,7 +239,7 @@ export class LiteYTEmbed extends HTMLElement {
);
this.setAttribute('title', `${this.videoPlay}: ${this.videoTitle}`);

if (this.autoLoad || this.isYouTubeShort()) {
if (this.autoLoad || this.isYouTubeShort() || this.autoPause) {
this.initIntersectionObserver();
}
}
Expand Down Expand Up @@ -275,6 +283,12 @@ export class LiteYTEmbed extends HTMLElement {
embedTarget = `${this.videoId}?`;
}

// autopause needs the postMessage() in the iframe, so you have to enable
// the jsapi
if (this.autoPause) {
this.params = `enablejsapi=1`;
}

// Oh wait, you're a YouTube short, so let's try to make you more workable
if (this.isYouTubeShort()) {
this.params = `loop=1&mute=1&modestbranding=1&playsinline=1&rel=0&enablejsapi=1&playlist=${this.videoId}`;
Expand Down Expand Up @@ -343,6 +357,27 @@ export class LiteYTEmbed extends HTMLElement {
}, options);

observer.observe(this);

// this needs the iframe loaded, so it has to run post the IO load at the
// least otherwise things will break
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);
}
}

/**
Expand Down
9 changes: 9 additions & 0 deletions test/lite-youtube.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@ describe('<lite-youtube>', () => {
expect(document.head.querySelectorAll('link').length).to.be.equal(1);
});

it('autoPause should inject iframe and warm', async () => {
const el = await fixture<LiteYTEmbed>(
html`<lite-youtube videoid="guJLfqTFfIw" autoPause></lite-youtube>`,
);
// this is a cheeky test by counting the test runner + the warm injector
// TODO write a better observer
expect(document.head.querySelectorAll('link').length).to.be.equal(7);
});

it('nocookie attr should change iframe url target', async () => {
const el = await fixture<LiteYTEmbed>(
html`<lite-youtube videoid="guJLfqTFfIw" nocookie></lite-youtube>`,
Expand Down

0 comments on commit 316b2b9

Please # to comment.