|
/**
|
|
* @fileoverview YouTube Embed Component for Rantii
|
|
* @author retoor <retoor@molodetz.nl>
|
|
* @description Embeds YouTube videos with preview thumbnail
|
|
* @keywords youtube, video, embed, media, player
|
|
*/
|
|
|
|
import { BaseComponent } from './base-component.js';
|
|
import { getYoutubeVideoId, getYoutubeThumbnail, getYoutubeEmbedUrl } from '../utils/url.js';
|
|
|
|
class YoutubeEmbed extends BaseComponent {
|
|
static get observedAttributes() {
|
|
return ['url', 'video-id'];
|
|
}
|
|
|
|
init() {
|
|
this.isPlaying = false;
|
|
this.render();
|
|
this.bindEvents();
|
|
}
|
|
|
|
render() {
|
|
let videoId = this.getAttr('video-id');
|
|
const url = this.getAttr('url');
|
|
|
|
if (!videoId && url) {
|
|
videoId = getYoutubeVideoId(url);
|
|
}
|
|
|
|
if (!videoId) {
|
|
this.setHtml('');
|
|
return;
|
|
}
|
|
|
|
this.addClass('youtube-embed');
|
|
|
|
if (this.isPlaying) {
|
|
const embedUrl = getYoutubeEmbedUrl(videoId);
|
|
this.setHtml(`
|
|
<div class="youtube-player">
|
|
<iframe src="${embedUrl}?autoplay=1&rel=0"
|
|
frameborder="0"
|
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
allowfullscreen>
|
|
</iframe>
|
|
</div>
|
|
`);
|
|
} else {
|
|
const thumbnail = getYoutubeThumbnail(videoId);
|
|
this.setHtml(`
|
|
<div class="youtube-preview">
|
|
<img class="youtube-thumbnail" src="${thumbnail}" alt="Video thumbnail" loading="lazy">
|
|
<button class="youtube-play" aria-label="Play video">
|
|
<svg viewBox="0 0 68 48" width="68" height="48">
|
|
<path fill="#f00" d="M66.52 7.74c-.78-2.93-2.49-5.41-5.42-6.19C55.79.13 34 0 34 0S12.21.13 6.9 1.55c-2.93.78-4.63 3.26-5.42 6.19C.06 13.05 0 24 0 24s.06 10.95 1.48 16.26c.78 2.93 2.49 5.41 5.42 6.19C12.21 47.87 34 48 34 48s21.79-.13 27.1-1.55c2.93-.78 4.64-3.26 5.42-6.19C67.94 34.95 68 24 68 24s-.06-10.95-1.48-16.26z"/>
|
|
<path fill="#fff" d="M45 24L27 14v20"/>
|
|
</svg>
|
|
</button>
|
|
<span class="youtube-badge">YouTube</span>
|
|
</div>
|
|
`);
|
|
}
|
|
}
|
|
|
|
bindEvents() {
|
|
this.on(this, 'click', this.handleClick);
|
|
}
|
|
|
|
handleClick(e) {
|
|
const playBtn = e.target.closest('.youtube-play');
|
|
const preview = e.target.closest('.youtube-preview');
|
|
|
|
if (playBtn || preview) {
|
|
e.preventDefault();
|
|
this.play();
|
|
}
|
|
}
|
|
|
|
play() {
|
|
this.isPlaying = true;
|
|
this.render();
|
|
}
|
|
|
|
stop() {
|
|
this.isPlaying = false;
|
|
this.render();
|
|
}
|
|
|
|
onAttributeChanged(name, oldValue, newValue) {
|
|
this.isPlaying = false;
|
|
this.render();
|
|
}
|
|
}
|
|
|
|
customElements.define('youtube-embed', YoutubeEmbed);
|
|
|
|
export { YoutubeEmbed };
|