<div class="background-fullscreen--idle background-fullscreen" data-background-image="../../.html">
</div>
<div class="background-fullscreen--idle background-fullscreen" data-background-image="{{ path '{{backgroundImagePath}}' }}">
  {{#if selfHostVideoPath}}
    <video class="background-fullscreen__video" data-videopath={{ selfHostVideoPath }} type="video/mp4" autoplay muted loop playsinline>
    </video>
  {{/if}}
  {{#if youtubeid}}
    <div class="youtube__iframe-wrapper" data-youtubeid="{{youtubeid}}">
    </div>
  {{/if}}    
  {{#if vimeoid}}
    <iframe class="iframe vimeo__iframe" data-vimeoid="{{vimeoid}}"
    frameborder="0" 
    webkitallowfullscreen 
    mozallowfullscreen 
    allowfullscreen
    >
    </iframe>
  {{/if}}
</div>
/* No context defined for this component. */
  • Content:
    'use strict';
    
    var novicell = novicell || {};
    
    novicell.pageheaderVideoFullscreenSelfHost =
        novicell.pageheaderVideoFullscreenSelfHost ||
        new function () {
            this.init = function () {
                if (screenWidth()) {
                    const fullscreenBackground = document.querySelector(".background-fullscreen") || false;
                    if (fullscreenBackground) {
                        // Remove class associated with background image
                        fullscreenBackground.classList.remove("background-fullscreen--idle");
                        // Add class associated with ajax gif loader
                        fullscreenBackground.classList.add("background-fullscreen--loading");
                    }
                    const videoList = document.querySelectorAll(".background-fullscreen__video") || false;
                    this.removeAjaxLoader = function (element) {
                        // Function for removing the class associated with the ajax loading gif.
                        element.classList.remove("background-fullscreen--loading");
                    };
                    if (videoList) {
                        // Make the data-videopath the actual src of the video element
                        for (let i = 0; i < videoList.length; i++) {
                            videoList[i].src = videoList[i].dataset.videopath;
                            // Remove ajax loader when play event triggers
                            videoList[i].addEventListener("play", () => {
                                novicell.pageheaderVideoFullscreenSelfHost.removeAjaxLoader(fullscreenBackground);
                            })
                        }
                    }
                }
            };
        }();
    
    function screenWidth() {
        return window.screen.width > 768;
    }
    
  • URL: /components/raw/pageheader-video-fullscreen/pageheader-video-fullscreen--self-host.js
  • Filesystem Path: patterns/03-organisms/pageheaders/pageheader-video-fullscreen/pageheader-video-fullscreen--self-host.js
  • Size: 1.7 KB
  • Content:
    'use strict';
    
    var novicell = novicell || {};
    
    novicell.pageheaderVideoFullscreenVimeo =
        novicell.pageheaderVideoFullscreenVimeo ||
        new function () {
            this.init = function () {
                if (screenWidth()) {
                    const fullscreenBackground = document.querySelector(".background-fullscreen") || false;
                    if (fullscreenBackground) {
                        // Remove class associated with background image
                        fullscreenBackground.classList.remove("background-fullscreen--idle");
                        // Add class associated with ajax gif loader
                        fullscreenBackground.classList.add("background-fullscreen--loading");
                    }
                    const vimeoIframeList = document.querySelector(".vimeo__iframe") || false;
                    this.removeAjaxLoader = function (element) {
                        // Function for removing the class associated with the ajax loading gif.
                        element.classList.remove("background-fullscreen--loading");
                    };
                    if (vimeoIframeList) {
                        const vimeoId = vimeoIframeList.dataset.vimeoid;
                        const fullUrl = `https://player.vimeo.com/video/${vimeoId}?autoplay=1&loop=1&color=000000&title=0&byline=0&portrait=0&muted=1&controls=0&background=1`;
                        const shortUrl = `https://vimeo.com/${vimeoId}`;
                        validateVimeoId(shortUrl)
                            .then(response => {
                                if (response === 200) {
                                    // Load video if the vimeo id exists
                                    vimeoIframeList.src = fullUrl;
                                } else {
                                    // If bad status, we remove the iframe and add the fallback BG image
                                    fullscreenBackground.style.backgroundImage = `url(${fullscreenBackground.dataset.backgroundImage})`;
                                    vimeoIframeList.remove();
                                }
                            }).then(() => {
                                // As we are not using the vimeo API, we can't listen for events on the Iframe.
                                // Consequently, I've had to make a guesstimate on when's a relatively good time to remove the ajax loader
                                setTimeout(() => {
                                    novicell.pageheaderVideoFullscreenVimeo.removeAjaxLoader(fullscreenBackground);
                                }, 5000);
                            }).catch(err => console.log(err));
                    }
                }
            };
        }();
    
    function screenWidth() {
        return window.screen.width > 768;
    }
    // Function for checking vimeo video validity
    function validateVimeoId(url) {
        let options = {
            method: 'GET'
        };
        // Anything but status 200 will throw an error
        return fetch(`https://vimeo.com/api/oembed.json?url=${encodeURIComponent(url)}`, options)
            .then((response) => {
                if (response.status === 200) {
                    return response.status;
                } else {
                    throw Error(`Bad response: ${response.status}`);
                }
            })
            .catch(err => console.log(err));
    }
    
  • URL: /components/raw/pageheader-video-fullscreen/pageheader-video-fullscreen--vimeo.js
  • Filesystem Path: patterns/03-organisms/pageheaders/pageheader-video-fullscreen/pageheader-video-fullscreen--vimeo.js
  • Size: 3.2 KB
  • Content:
    'use strict';
    
    var novicell = novicell || {};
    
    novicell.pageheaderVideoFullscreenYT =
        novicell.pageheaderVideoFullscreenYT ||
        new function () {
            this.init = function () {
                if (screenWidth()) {
                    const fullscreenBackground = document.querySelector(".background-fullscreen") || false;
                    if (fullscreenBackground) {
                        // Remove class associated with background image
                        fullscreenBackground.classList.remove("background-fullscreen--idle");
                        // Add class associated with ajax gif loader
                        fullscreenBackground.classList.add("background-fullscreen--loading");
                    }
                    const youtubeIframeList = document.querySelector(".youtube__iframe-wrapper") || false;
                    this.removeAjaxLoader = function (element) {
                        // Function for removing the class associated with the ajax loading gif.
                        element.classList.remove("background-fullscreen--loading");
                    };
                    if (youtubeIframeList) {
                        let videoStart = 0;
                        let youtubeid = youtubeIframeList.dataset.youtubeid;
                        let tag = document.createElement("script");
                        tag.src = "https://www.youtube.com/player_api";
                        let lastScriptTag = document.getElementsByTagName("script")[
                            document.getElementsByTagName("script").length - 1
                        ];
                        lastScriptTag.parentNode.insertBefore(tag, lastScriptTag);
                        this.changeCaseState = function (e) {
                            // Already written as switch case as there are more possibilities that might be implemented in the future.
                            // In this case, we remove the background gif when the video starts playing.
                            // See list of available cases on official YT embed docs on Playback_status
                            switch (e.data) {
                                // Case 1 is "video is playing"
                                case 1:
                                    {
                                        novicell.pageheaderVideoFullscreenYT.removeAjaxLoader(fullscreenBackground);
                                        break;
                                    }
                            }
                        };
                        this.onPlayerReady = function (event) {
                            event.target.mute();
                            event.target.seekTo(videoStart);
                        };
                        this.onErrorResponse = function (event) {
                            // In case of bad response, kill the player and add the background image.
                            // Currently, the url for the BG image is stored on the background-fullscreen wrapper itself.
                            // An alternative would be having a css class added that holds a background image attribute and the path value already, and simply append the classname to the element
                            fullscreenBackground.style.backgroundImage = `url(${fullscreenBackground.dataset.backgroundImage})`;
                            event.target.destroy();
                            novicell.pageheaderVideoFullscreenYT.removeAjaxLoader(fullscreenBackground);
                        };
                        this.onYouTubeFullscreenIframeAPIReady = function () {
                            let player = new YT.Player(youtubeIframeList, {
                                videoId: youtubeid,
                                playerVars: {
                                    autoplay: 1,
                                    autohide: 1,
                                    loop: 1,
                                    // Playlist is required, otherwise the video refuses to loop for some reason
                                    playlist: youtubeid,
                                    modestbranding: 1,
                                    rel: 0,
                                    controls: 0,
                                    disablekb: 1,
                                    enablejsapi: 0,
                                    iv_load_policy: 3
                                },
                                events: {
                                    onReady: novicell.pageheaderVideoFullscreenYT.onPlayerReady,
                                    onError: novicell.pageheaderVideoFullscreenYT.onErrorResponse,
                                    onStateChange: novicell.pageheaderVideoFullscreenYT.changeCaseState
                                }
                            });
                        };
                        window.addEventListener(
                            "load",
                            function () {
                                novicell.pageheaderVideoFullscreenYT.onYouTubeFullscreenIframeAPIReady();
                            },
                            true
                        );
                    }
                }
            };
        }();
    
    function screenWidth() {
        return window.screen.width > 768;
    }
    
  • URL: /components/raw/pageheader-video-fullscreen/pageheader-video-fullscreen--yt.js
  • Filesystem Path: patterns/03-organisms/pageheaders/pageheader-video-fullscreen/pageheader-video-fullscreen--yt.js
  • Size: 5 KB
  • Content:
    /**
     * Component: pageheader-video-fullscreen
     */
    .background-fullscreen {
        /* Position it relative if you want to be able to scroll below the video */
        position: absolute;
        top: 0;
        left: 0;
        width: 100vw;
        height: 100vh;
        z-index: -1;
        pointer-events: none;
        overflow: hidden;
        background-size: cover;
        background-image: none;
    
        &--idle {
            background-image: url("/dist/images/placeholder-images/hero--mona-eendra-313518.jpg");
        }
    
        &--loading {
            background-image: url("/dist/images/outro_2-loader.gif");
            background-size: auto;
            background-repeat: no-repeat;
            background-position: center;
        }
    
        & iframe {
            width: 100vw;
            height: 56.25vw;
            /* Given a 16:9 aspect ratio, 9/16*100 = 56.25 */
            min-height: 100vh;
            min-width: 190vh;
            /* Given a 16:9 aspect ratio, 16/9*100 = 177.77 */
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }
    
        &__video {
            position: fixed;
            right: 0;
            bottom: 0;
            min-width: 100%;
            min-height: 100%;
        }
    
        &__foreground {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 100vw;
            height: 100vh;
            font-size: 1.7em;
            text-decoration: overline underline;
        }
    }
    
  • URL: /components/raw/pageheader-video-fullscreen/pageheader-video-fullscreen.css
  • Filesystem Path: patterns/03-organisms/pageheaders/pageheader-video-fullscreen/pageheader-video-fullscreen.css
  • Size: 1.4 KB

In production, consider having preconnect links in the head for faster connection with YT and Vimeo:

link rel=”preconnect” href=”https://player.vimeo.com"

link rel=”preconnect” href=”https://www.youtube.com"