98 lines
3.0 KiB
JavaScript
Raw Normal View History

2025-12-04 20:29:35 +01:00
/**
* @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 };