1
+ /*
2
+ * Embed Block
3
+ * Show videos and social posts directly on your page
4
+ * https://www.hlx.live/developer/block-collection/embed
5
+ */
6
+
7
+ const loadScript = ( url , callback , type ) => {
8
+ const head = document . querySelector ( 'head' ) ;
9
+ const script = document . createElement ( 'script' ) ;
10
+ script . src = url ;
11
+ if ( type ) {
12
+ script . setAttribute ( 'type' , type ) ;
13
+ }
14
+ script . onload = callback ;
15
+ head . append ( script ) ;
16
+ return script ;
17
+ } ;
18
+
19
+ const getDefaultEmbed = ( url ) => `<div style="left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;">
20
+ <iframe src="${ url . href } " style="border: 0; top: 0; left: 0; width: 100%; height: 100%; position: absolute;" allowfullscreen=""
21
+ scrolling="no" allow="encrypted-media" title="Content from ${ url . hostname } " loading="lazy">
22
+ </iframe>
23
+ </div>` ;
24
+
25
+ const embedYoutube = ( url , autoplay ) => {
26
+ const usp = new URLSearchParams ( url . search ) ;
27
+ const suffix = autoplay ? '&muted=1&autoplay=1' : '' ;
28
+ let vid = usp . get ( 'v' ) ? encodeURIComponent ( usp . get ( 'v' ) ) : '' ;
29
+ const embed = url . pathname ;
30
+ if ( url . origin . includes ( 'youtu.be' ) ) {
31
+ [ , vid ] = url . pathname . split ( '/' ) ;
32
+ }
33
+ const embedHTML = `<div style="left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;">
34
+ <iframe src="https://www.youtube.com${ vid ? `/embed/${ vid } ?rel=0&v=${ vid } ${ suffix } ` : embed } " style="border: 0; top: 0; left: 0; width: 100%; height: 100%; position: absolute;"
35
+ allow="autoplay; fullscreen; picture-in-picture; encrypted-media; accelerometer; gyroscope; picture-in-picture" allowfullscreen="" scrolling="no" title="Content from Youtube" loading="lazy"></iframe>
36
+ </div>` ;
37
+ return embedHTML ;
38
+ } ;
39
+
40
+ const embedVimeo = ( url , autoplay ) => {
41
+ const [ , video ] = url . pathname . split ( '/' ) ;
42
+ const suffix = autoplay ? '?muted=1&autoplay=1' : '' ;
43
+ const embedHTML = `<div style="left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;">
44
+ <iframe src="https://player.vimeo.com/video/${ video } ${ suffix } "
45
+ style="border: 0; top: 0; left: 0; width: 100%; height: 100%; position: absolute;"
46
+ frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen
47
+ title="Content from Vimeo" loading="lazy"></iframe>
48
+ </div>` ;
49
+ return embedHTML ;
50
+ } ;
51
+
52
+ const embedTwitter = ( url ) => {
53
+ const embedHTML = `<blockquote class="twitter-tweet"><a href="${ url . href } "></a></blockquote>` ;
54
+ loadScript ( 'https://platform.twitter.com/widgets.js' ) ;
55
+ return embedHTML ;
56
+ } ;
57
+
58
+ const loadEmbed = ( block , link , autoplay ) => {
59
+ if ( block . classList . contains ( 'embed-is-loaded' ) ) {
60
+ return ;
61
+ }
62
+
63
+ const EMBEDS_CONFIG = [
64
+ {
65
+ match : [ 'youtube' , 'youtu.be' ] ,
66
+ embed : embedYoutube ,
67
+ } ,
68
+ {
69
+ match : [ 'vimeo' ] ,
70
+ embed : embedVimeo ,
71
+ } ,
72
+ {
73
+ match : [ 'twitter' ] ,
74
+ embed : embedTwitter ,
75
+ } ,
76
+ ] ;
77
+
78
+ const config = EMBEDS_CONFIG . find ( ( e ) => e . match . some ( ( match ) => link . includes ( match ) ) ) ;
79
+ const url = new URL ( link ) ;
80
+ if ( config ) {
81
+ block . innerHTML = config . embed ( url , autoplay ) ;
82
+ block . classList = `block embed embed-${ config . match [ 0 ] } ` ;
83
+ } else {
84
+ block . innerHTML = getDefaultEmbed ( url ) ;
85
+ block . classList = 'block embed' ;
86
+ }
87
+ block . classList . add ( 'embed-is-loaded' ) ;
88
+ } ;
89
+
90
+ export default function decorate ( block ) {
91
+ const placeholder = block . querySelector ( 'picture' ) ;
92
+ const link = block . querySelector ( 'a' ) . href ;
93
+ block . textContent = '' ;
94
+
95
+ if ( placeholder ) {
96
+ const wrapper = document . createElement ( 'div' ) ;
97
+ wrapper . className = 'embed-placeholder' ;
98
+ wrapper . innerHTML = '<div class="embed-placeholder-play"><button type="button" title="Play"></button></div>' ;
99
+ wrapper . prepend ( placeholder ) ;
100
+ wrapper . addEventListener ( 'click' , ( ) => {
101
+ loadEmbed ( block , link , true ) ;
102
+ } ) ;
103
+ block . append ( wrapper ) ;
104
+ } else {
105
+ const observer = new IntersectionObserver ( ( entries ) => {
106
+ if ( entries . some ( ( e ) => e . isIntersecting ) ) {
107
+ observer . disconnect ( ) ;
108
+ loadEmbed ( block , link ) ;
109
+ }
110
+ } ) ;
111
+ observer . observe ( block ) ;
112
+ }
113
+ }
0 commit comments