From 2e970a41c0753b3853213333a5cca866c2e39246 Mon Sep 17 00:00:00 2001 From: Pardeep Gera Date: Tue, 17 Oct 2023 20:42:58 +0530 Subject: [PATCH] embed block --- blocks/embed/embed.css | 65 ++++++++++++++++++++++++ blocks/embed/embed.js | 113 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 blocks/embed/embed.css create mode 100644 blocks/embed/embed.js diff --git a/blocks/embed/embed.css b/blocks/embed/embed.css new file mode 100644 index 00000000..dbc29cc8 --- /dev/null +++ b/blocks/embed/embed.css @@ -0,0 +1,65 @@ +main .embed { + width: unset; + text-align: center; + max-width: 800px; + margin: 32px auto; + } + + main .embed > div { + display: flex; + justify-content: center; + } + + main .embed.embed-twitter .twitter-tweet-rendered { + margin-left: auto; + margin-right: auto; + } + + main .embed .embed-placeholder { + width: 100%; + aspect-ratio: 16 / 9; + position: relative; + } + + main .embed .embed-placeholder > * { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + } + + main .embed .embed-placeholder picture img { + width: 100%; + height: 100%; + object-fit: cover; + } + + main .embed .embed-placeholder-play button { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(3); + width: 22px; + height: 22px; + border: 2px solid; + border-radius: 20px; + padding: 0; + } + + main .embed .embed-placeholder-play button::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 0; + height: 10px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 6px solid; + top: 4px; + left: 7px; + } \ No newline at end of file diff --git a/blocks/embed/embed.js b/blocks/embed/embed.js new file mode 100644 index 00000000..1634dddf --- /dev/null +++ b/blocks/embed/embed.js @@ -0,0 +1,113 @@ +/* + * Embed Block + * Show videos and social posts directly on your page + * https://www.hlx.live/developer/block-collection/embed + */ + +const loadScript = (url, callback, type) => { + const head = document.querySelector('head'); + const script = document.createElement('script'); + script.src = url; + if (type) { + script.setAttribute('type', type); + } + script.onload = callback; + head.append(script); + return script; +}; + +const getDefaultEmbed = (url) => `
+ +
`; + +const embedYoutube = (url, autoplay) => { + const usp = new URLSearchParams(url.search); + const suffix = autoplay ? '&muted=1&autoplay=1' : ''; + let vid = encodeURIComponent(usp.get('v')); + const embed = url.pathname; + if (url.origin.includes('youtu.be')) { + [, vid] = url.pathname.split('/'); + } + const embedHTML = `
+ +
`; + return embedHTML; +}; + +const embedVimeo = (url, autoplay) => { + const [, video] = url.pathname.split('/'); + const suffix = autoplay ? '?muted=1&autoplay=1' : ''; + const embedHTML = `
+ +
`; + return embedHTML; +}; + +const embedTwitter = (url) => { + const embedHTML = `
`; + loadScript('https://platform.twitter.com/widgets.js'); + return embedHTML; +}; + +const loadEmbed = (block, link, autoplay) => { + if (block.classList.contains('embed-is-loaded')) { + return; + } + + const EMBEDS_CONFIG = [ + { + match: ['youtube', 'youtu.be'], + embed: embedYoutube, + }, + { + match: ['vimeo'], + embed: embedVimeo, + }, + { + match: ['twitter'], + embed: embedTwitter, + }, + ]; + + const config = EMBEDS_CONFIG.find((e) => e.match.some((match) => link.includes(match))); + const url = new URL(link); + if (config) { + block.innerHTML = config.embed(url, autoplay); + block.classList = `block embed embed-${config.match[0]}`; + } else { + block.innerHTML = getDefaultEmbed(url); + block.classList = 'block embed'; + } + block.classList.add('embed-is-loaded'); +}; + +export default function decorate(block) { + const placeholder = block.querySelector('picture'); + const link = block.querySelector('a').href; + block.textContent = ''; + + if (placeholder) { + const wrapper = document.createElement('div'); + wrapper.className = 'embed-placeholder'; + wrapper.innerHTML = '
'; + wrapper.prepend(placeholder); + wrapper.addEventListener('click', () => { + loadEmbed(block, link, true); + }); + block.append(wrapper); + } else { + const observer = new IntersectionObserver((entries) => { + if (entries.some((e) => e.isIntersecting)) { + observer.disconnect(); + loadEmbed(block, link); + } + }); + observer.observe(block); + } +}