/* youtube-background v1.1.7 | https://github.com/stamat/youtube-background | MIT License */ (() => { // src/lib/buttons.js function buttonOn(buttonObj) { if (!buttonObj) return; buttonObj.element.classList.add(buttonObj.stateClassName); buttonObj.element.firstChild.classList.remove(buttonObj.stateChildClassNames[0]); buttonObj.element.firstChild.classList.add(buttonObj.stateChildClassNames[1]); buttonObj.element.setAttribute("aria-checked", false); } function buttonOff(buttonObj) { if (!buttonObj) return; buttonObj.element.classList.remove(buttonObj.stateClassName); buttonObj.element.firstChild.classList.add(buttonObj.stateChildClassNames[0]); buttonObj.element.firstChild.classList.remove(buttonObj.stateChildClassNames[1]); buttonObj.element.setAttribute("aria-checked", true); } function generateActionButton(obj, props) { const btn = document.createElement("button"); btn.className = props.className; btn.innerHTML = props.innerHtml; btn.setAttribute("role", "switch"); btn.firstChild.classList.add(props.stateChildClassNames[0]); btn.setAttribute("aria-checked", !props.initialState); props.element = btn; if (obj.params[props.condition_parameter] === props.initialState) { buttonOn(props); } btn.addEventListener("click", function(e) { if (this.classList.contains(props.stateClassName)) { buttonOff(props); obj[props.actions[0]](); } else { buttonOn(props); obj[props.actions[1]](); } }); obj.buttons[props.name] = { element: btn, button_properties: props }; obj.controls_element.appendChild(btn); } // node_modules/book-of-spells/src/helpers.mjs function stringToBoolean(str) { if (/^\s*(true|false)\s*$/i.test(str)) return str === "true"; } function stringToNumber(str) { if (/^\s*\d+\s*$/.test(str)) return parseInt(str); if (/^\s*[\d.]+\s*$/.test(str)) return parseFloat(str); } function stringToArray(str) { if (!/^\s*\[.*\]\s*$/.test(str)) return; try { return JSON.parse(str); } catch (e) { } } function stringToObject(str) { if (!/^\s*\{.*\}\s*$/.test(str)) return; try { return JSON.parse(str); } catch (e) { } } function stringToRegex(str) { if (!/^\s*\/.*\/g?i?\s*$/.test(str)) return; try { return new RegExp(str); } catch (e) { } } function stringToType(str) { if (/^\s*null\s*$/.test(str)) return null; const bool = stringToBoolean(str); if (bool !== void 0) return bool; return stringToNumber(str) || stringToArray(str) || stringToObject(str) || stringToRegex(str) || str; } function isArray(o) { return Array.isArray(o); } function isString(o) { return typeof o === "string"; } function randomIntInclusive(min, max, safe = false) { min = Number(min); max = Number(max); if (isNaN(min) || isNaN(max)) throw new TypeError("Both min and max must be numbers"); if (min > max) [min, max] = [max, min]; if (min === max) return min; min = Math.round(min); max = Math.round(max); const rand = safe ? random() : Math.random(); return Math.floor(rand * (max - min + 1)) + min; } function fixed(number, digits) { if (!digits) return parseInt(number); return parseFloat(number.toFixed(digits)); } function percentage(num, total) { if (!num || !total || Number.isNaN(num) || Number.isNaN(total)) return 0; return num / total * 100; } function random() { if (!crypto) return Math.random(); if (crypto.getRandomValues) return crypto.getRandomValues(new Uint32Array(1))[0] / 4294967295; } // node_modules/book-of-spells/src/regex.mjs var RE_YOUTUBE = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i; var RE_VIMEO = /(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^\/]*)\/videos\/|album\/(?:\d+)\/video\/|video\/|)(\d+)(?:[a-zA-Z0-9_\-]+)?/i; var RE_VIDEO = /\/([^\/]+\.(?:mp4|ogg|ogv|ogm|webm|avi))\s*$/i; // node_modules/book-of-spells/src/parsers.mjs function parseResolutionString(res) { const DEFAULT_RESOLUTION = 1.7777777778; if (!res || !res.length || /16[\:x\-\/]{1}9/i.test(res)) return DEFAULT_RESOLUTION; const pts = res.split(/\s?[\:x\-\/]{1}\s?/i); if (pts.length < 2) return DEFAULT_RESOLUTION; const w = parseInt(pts[0]); const h = parseInt(pts[1]); if (w === 0 || h === 0) return DEFAULT_RESOLUTION; if (isNaN(w) || isNaN(h)) return DEFAULT_RESOLUTION; return w / h; } // node_modules/book-of-spells/src/dom.mjs function query(selector, from = document) { if (selector instanceof Array || selector instanceof NodeList) return selector; if (selector instanceof Element) return [selector]; if (from instanceof Element || from instanceof Document) return from.querySelectorAll(selector); if (isString(from)) from = query(from); if (!from instanceof Array && !from instanceof NodeList) return []; const res = []; for (const element of from) { res.push(...element.querySelectorAll(selector)); } return res; } function proportionalParentCoverResize(elements, ratio = 1, offset = 0) { if (elements instanceof Element) elements = [elements]; if (typeof elements === "string") elements = query(elements); for (const element of elements) { const h = element.parentNode.offsetHeight + offset; const w = element.parentNode.offsetWidth + offset; if (ratio > w / h) { element.style.width = h * ratio + "px"; element.style.height = h + "px"; } else { element.style.width = w + "px"; element.style.height = w / ratio + "px"; } } } // node_modules/book-of-spells/src/browser.mjs function isUserAgentMobile(str) { return /\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(str) || /\b(Android|Windows Phone|iPad|iPod)\b/i.test(str); } function isMobile() { if ("maxTouchPoints" in navigator) return navigator.maxTouchPoints > 0; if ("matchMedia" in window) return !!matchMedia("(pointer:coarse)").matches; if ("orientation" in window) return true; return isUserAgentMobile(navigator.userAgent); } // src/lib/super-video-background.js var SuperVideoBackground = class { constructor(elem, params, id, uid, type, factoryInstance) { if (!id) return; this.is_mobile = isMobile(); this.type = type; this.id = id; this.factoryInstance = factoryInstance; this.element = elem; this.playerElement = null; this.uid = uid; this.element.setAttribute("data-vbg-uid", uid); this.buttons = {}; this.isIntersecting = false; this.paused = false; this.muted = false; this.currentState = "notstarted"; this.initialPlay = false; this.initialVolume = false; this.volume = 1; this.params = {}; const DEFAULTS = { "pause": false, //deprecated "play-button": false, "mute-button": false, "autoplay": true, "muted": true, "loop": true, "mobile": true, "load-background": false, "resolution": "16:9", "inline-styles": true, "fit-box": false, "offset": 100, // since showinfo is deprecated and ignored after September 25, 2018. we add +100 to hide it in the overflow "start-at": 0, "end-at": 0, "poster": null, "always-play": false, "volume": 1, "no-cookie": true, "force-on-low-battery": false, "lazyloading": false, "title": "Video background" }; this.params = this.parseProperties(params, DEFAULTS, this.element, ["data-ytbg-", "data-vbg-"]); if (this.params.pause) { this.params["play-button"] = this.params.pause; } this.params.resolution_mod = parseResolutionString(this.params.resolution); this.muted = this.params.muted; this.volume = this.params.volume; this.currentTime = this.params["start-at"] || 0; this.duration = this.params["end-at"] || 0; this.percentComplete = 0; if (this.params["start-at"]) this.percentComplete = this.timeToPercentage(this.params["start-at"]); this.buildWrapperHTML(); if (this.is_mobile && !this.params.mobile) return; if (this.params["play-button"]) { generateActionButton(this, { name: "playing", className: "play-toggle", innerHtml: '', initialState: !this.paused, stateClassName: "paused", condition_parameter: "paused", stateChildClassNames: ["fa-pause-circle", "fa-play-circle"], actions: ["play", "pause"] }); } if (this.params["mute-button"]) { generateActionButton(this, { name: "muted", className: "mute-toggle", innerHtml: '', initialState: this.muted, stateClassName: "muted", condition_parameter: "muted", stateChildClassNames: ["fa-volume-up", "fa-volume-mute"], actions: ["unmute", "mute"] }); } } timeToPercentage(time) { if (time <= this.params["start-at"]) return 0; if (time >= this.duration) return 100; if (time <= 0) return 0; time -= this.params["start-at"]; const duration = this.duration - this.params["start-at"]; return percentage(time, duration); } percentageToTime(percentage2) { if (!this.duration) return this.params["start-at"] || 0; if (percentage2 > 100) return this.duration; if (percentage2 <= 0) return this.params["start-at"] || 0; const duration = this.duration - this.params["start-at"]; let time = percentage2 * duration / 100; time = fixed(time, 3); if (time > duration) time = duration; if (this.params["start-at"]) time += this.params["start-at"]; return time; } resize(element) { if (!this.params["fit-box"]) proportionalParentCoverResize(element || this.playerElement, this.params.resolution_mod, this.params.offset); this.dispatchEvent("video-background-resize"); } stylePlayerElement(element) { if (!element) return; if (this.params["inline-styles"]) { element.style.top = "50%"; element.style.left = "50%"; element.style.transform = "translateX(-50%) translateY(-50%)"; element.style.position = "absolute"; element.style.opacity = 0; } if (this.params["fit-box"]) { element.style.width = "951px"; element.style.height = "535px"; } } buildWrapperHTML() { const parent = this.element.parentNode; this.element.classList.add("youtube-background", "video-background"); const wrapper_styles = { "height": "520px", "width": "950px", "z-index": "0", "overflow": "hidden", "top": 0, // added by @insad "left": 0, "bottom": 0, "right": 0 }; if (!this.params["mute-button"]) { wrapper_styles["pointer-events"] = "none"; } if (this.params["load-background"] || this.params["poster"]) { this.loadBackground(this.id); if (this.params["poster"]) wrapper_styles["background-image"] = `url(${this.params["poster"]})`; wrapper_styles["background-size"] = "cover"; wrapper_styles["background-repeat"] = "no-repeat"; wrapper_styles["background-position"] = "center"; } if (this.params["inline-styles"]) { for (let property in wrapper_styles) { this.element.style[property] = wrapper_styles[property]; } if (!["absolute", "fixed", "relative", "sticky"].indexOf(parent.style.position)) { parent.style.position = "relative"; } } if (this.params["play-button"] || this.params["mute-button"]) { const controls = document.createElement("div"); controls.className = "video-background-controls"; controls.style.position = "absolute"; controls.style.top = "10px"; controls.style.right = "10px"; controls.style["z-index"] = 2; this.controls_element = controls; parent.appendChild(controls); } return this.element; } loadBackground(id) { if (!this.params["load-background"]) return; if (!id) return; if (this.type === "youtube") this.element.style["background-image"] = `url(https://img.youtube.com/vi/${id}/hqdefault.jpg)`; if (this.type === "vimeo") this.element.style["background-image"] = `url(https://vumbnail.com/${id}.jpg)`; } destroy() { this.playerElement.remove(); this.element.classList.remove("youtube-background", "video-background"); this.element.removeAttribute("data-vbg-uid"); this.element.style = ""; if (this.params["play-button"] || this.params["mute-button"]) { this.controls_element.remove(); } if (this.timeUpdateTimer) clearInterval(this.timeUpdateTimer); this.dispatchEvent("video-background-destroyed"); } setDuration(duration) { if (this.duration === duration) return; if (this.params["end-at"]) { if (duration > this.params["end-at"]) { this.duration = this.params["end-at"]; return; } if (duration < this.params["end-at"]) { this.duration = duration; return; } } else { this.duration = duration; return; } if (duration <= 0) this.duration = this.params["end-at"]; } setStartAt(startAt) { this.params["start-at"] = startAt; } setEndAt(endAt) { this.params["end-at"] = endAt; if (this.duration > endAt) this.duration = endAt; if (this.currentTime > endAt) this.onVideoEnded(); } dispatchEvent(name) { this.element.dispatchEvent(new CustomEvent(name, { bubbles: true, detail: this })); } shouldPlay() { if (this.currentState === "ended" && !this.params.loop) return false; if (this.params["always-play"] && this.currentState !== "playing") return true; if (this.isIntersecting && this.params.autoplay && this.currentState !== "playing") return true; return false; } mobileLowBatteryAutoplayHack() { if (!this.params["force-on-low-battery"]) return; if (!this.is_mobile && this.params.mobile) return; const forceAutoplay = function() { if (!this.initialPlay && this.params.autoplay && this.params.muted) { this.softPlay(); if (!this.isIntersecting && !this.params["always-play"]) { this.softPause(); } } }; document.addEventListener("touchstart", forceAutoplay.bind(this), { once: true }); } parseProperties(params, defaults, element, attr_prefix) { let res_params = {}; if (!params) { res_params = defaults; } else { for (let k in defaults) { res_params[k] = !params.hasOwnProperty(k) ? defaults[k] : params[k]; } } if (!element) return res_params; for (let k in res_params) { let data; if (isArray(attr_prefix)) { for (let i = 0; i < attr_prefix.length; i++) { const temp_data = element.getAttribute(attr_prefix[i] + k); if (temp_data) { data = temp_data; break; } } } else { data = element.getAttribute(attr_prefix + k); } if (data !== void 0 && data !== null) { res_params[k] = stringToType(data); } } return res_params; } }; // src/lib/youtube-background.js var YoutubeBackground = class extends SuperVideoBackground { constructor(elem, params, id, uid, factoryInstance) { super(elem, params, id, uid, "youtube", factoryInstance); if (!id) return; if (this.is_mobile && !this.params.mobile) return; this.injectScript(); this.player = null; this.injectPlayer(); this.STATES = { "-1": "notstarted", "0": "ended", "1": "playing", "2": "paused", "3": "buffering", "5": "cued" }; this.timeUpdateTimer = null; this.timeUpdateInterval = 250; this.initYTPlayer(); } startTimeUpdateTimer() { if (this.timeUpdateTimer) return; this.timeUpdateTimer = setInterval(this.onVideoTimeUpdate.bind(this), this.timeUpdateInterval); } stopTimeUpdateTimer() { clearInterval(this.timeUpdateTimer); this.timeUpdateTimer = null; } convertState(state) { return this.STATES[state]; } initYTPlayer() { if (!window.hasOwnProperty("YT") || this.player !== null) return; this.player = new YT.Player(this.uid, { events: { "onReady": this.onVideoPlayerReady.bind(this), "onStateChange": this.onVideoStateChange.bind(this) // 'onError': this.onVideoError.bind(this) } }); if (this.volume !== 1 && !this.muted) this.setVolume(this.volume); } onVideoError(event) { console.error(event); } injectScript() { const src = "https://www.youtube.com/player_api"; if (window.hasOwnProperty("YT") || document.querySelector(`script[src="${src}"]`)) return; const tag = document.createElement("script"); tag.async = true; tag.src = src; const firstScriptTag = document.getElementsByTagName("script")[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); } generatePlayerElement() { const playerElement = document.createElement("iframe"); if (this.params.title) playerElement.setAttribute("title", this.params.title); playerElement.setAttribute("frameborder", 0); playerElement.setAttribute("allow", "autoplay; mute"); if (this.params["lazyloading"]) playerElement.setAttribute("loading", "lazy"); return playerElement; } generateSrcURL(id) { let site = "https://www.youtube.com/embed/"; if (this.params["no-cookie"]) { site = "https://www.youtube-nocookie.com/embed/"; } let src = `${site}${id}?&enablejsapi=1&disablekb=1&controls=0&rel=0&iv_load_policy=3&cc_load_policy=0&playsinline=1&showinfo=0&modestbranding=1&fs=0`; if (this.params.muted) { src += "&mute=1"; } if (this.params.autoplay && (this.params["always-play"] || this.isIntersecting)) { src += "&autoplay=1"; } if (this.params.loop) { src += "&loop=1"; } return src; } injectPlayer() { this.playerElement = this.generatePlayerElement(); this.src = this.generateSrcURL(this.id); this.playerElement.src = this.src; this.playerElement.id = this.uid; this.stylePlayerElement(this.playerElement); this.element.appendChild(this.playerElement); this.resize(this.playerElement); } /* ===== API ===== */ setSource(url) { const pts = url.match(RE_YOUTUBE); if (!pts || !pts.length) return; this.id = pts[1]; this.src = this.generateSrcURL(this.id); this.playerElement.src = this.src; if (this.element.hasAttribute("data-vbg")) this.element.setAttribute("data-vbg", this.src); if (this.element.hasAttribute("data-ytbg")) this.element.setAttribute("data-ytbg", this.src); this.loadBackground(this.id); } onVideoTimeUpdate() { const ctime = this.player.getCurrentTime(); if (ctime === this.currentTime) return; this.currentTime = ctime; this.percentComplete = this.timeToPercentage(this.currentTime); if (this.params["end-at"] && this.duration && this.currentTime >= this.duration) { this.currentState = "ended"; this.dispatchEvent("video-background-state-change"); this.onVideoEnded(); this.stopTimeUpdateTimer(); return; } this.dispatchEvent("video-background-time-update"); } onVideoPlayerReady() { this.mobileLowBatteryAutoplayHack(); if (this.params.autoplay && (this.params["always-play"] || this.isIntersecting)) { if (this.params["start-at"]) this.seekTo(this.params["start-at"]); this.player.playVideo(); } this.setDuration(this.player.getDuration()); this.dispatchEvent("video-background-ready"); } onVideoStateChange(event) { this.currentState = this.convertState(event.data); if (this.currentState === "ended") this.onVideoEnded(); if (this.currentState === "notstarted" && this.params.autoplay) { this.seekTo(this.params["start-at"]); this.player.playVideo(); } if (this.currentState === "playing") this.onVideoPlay(); if (this.currentState === "paused") this.onVideoPause(); this.dispatchEvent("video-background-state-change"); } onVideoPlay() { if (!this.initialPlay) { this.initialPlay = true; this.playerElement.style.opacity = 1; } const seconds = this.player.getCurrentTime(); if (this.params["start-at"] && seconds < this.params["start-at"]) { this.seekTo(this.params["start-at"]); } if (this.duration && seconds >= this.duration) { this.seekTo(this.params["start-at"]); } if (!this.duration) { this.setDuration(this.player.getDuration()); } this.dispatchEvent("video-background-play"); this.startTimeUpdateTimer(); } onVideoPause() { this.stopTimeUpdateTimer(); this.dispatchEvent("video-background-pause"); } onVideoEnded() { this.dispatchEvent("video-background-ended"); if (!this.params.loop) return this.pause(); this.seekTo(this.params["start-at"]); this.player.playVideo(); } seek(percentage2) { this.seekTo(this.percentageToTime(percentage2), true); } seekTo(seconds, allowSeekAhead = true) { if (!this.player) return; this.player.seekTo(seconds, allowSeekAhead); this.dispatchEvent("video-background-seeked"); } softPause() { if (!this.player || this.currentState === "paused") return; this.stopTimeUpdateTimer(); this.player.pauseVideo(); } softPlay() { if (!this.player || this.currentState === "playing") return; this.player.playVideo(); } play() { if (!this.player) return; this.paused = false; this.player.playVideo(); } pause() { if (!this.player) return; this.paused = true; this.stopTimeUpdateTimer(); this.player.pauseVideo(); } unmute() { if (!this.player) return; this.muted = false; if (!this.initialVolume) { this.initialVolume = true; this.setVolume(this.params.volume); } this.player.unMute(); this.dispatchEvent("video-background-unmute"); } mute() { if (!this.player) return; this.muted = true; this.player.mute(); this.dispatchEvent("video-background-mute"); } getVolume() { if (!this.player) return; return this.player.getVolume() / 100; } setVolume(volume) { if (!this.player) return; this.volume = volume; this.player.setVolume(volume * 100); this.dispatchEvent("video-background-volume-change"); } }; // src/lib/vimeo-background.js var VimeoBackground = class extends SuperVideoBackground { constructor(elem, params, id, uid, factoryInstance) { super(elem, params, id.id, uid, "vimeo", factoryInstance); if (!id) return; this.unlisted = id.unlisted; if (this.is_mobile && !this.params.mobile) return; this.injectScript(); this.player = null; this.injectPlayer(); this.initVimeoPlayer(); } injectScript() { const src = "https://player.vimeo.com/api/player.js"; if (window.hasOwnProperty("Vimeo") || document.querySelector(`script[src="${src}"]`)) return; const tag = document.createElement("script"); tag.async = true; if (window.hasOwnProperty("onVimeoIframeAPIReady") && typeof window.onVimeoIframeAPIReady === "function") tag.addEventListener("load", () => { window.onVimeoIframeAPIReady(); }); tag.src = src; const firstScriptTag = document.getElementsByTagName("script")[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); } initVimeoPlayer() { if (!window.hasOwnProperty("Vimeo") || this.player !== null) return; this.player = new Vimeo.Player(this.playerElement); this.player.on("loaded", this.onVideoPlayerReady.bind(this)); this.player.on("ended", this.onVideoEnded.bind(this)); this.player.on("play", this.onVideoPlay.bind(this)); this.player.on("pause", this.onVideoPause.bind(this)); this.player.on("bufferstart", this.onVideoBuffering.bind(this)); this.player.on("timeupdate", this.onVideoTimeUpdate.bind(this)); if (this.volume !== 1 && !this.muted) this.setVolume(this.volume); } onVideoError(event) { console.error(event); } generatePlayerElement() { const playerElement = document.createElement("iframe"); if (this.params.title) playerElement.setAttribute("title", this.params.title); playerElement.setAttribute("frameborder", 0); playerElement.setAttribute("allow", "autoplay; mute"); if (this.params["lazyloading"]) playerElement.setAttribute("loading", "lazy"); return playerElement; } generateSrcURL(id, unlisted) { unlisted = unlisted ? `h=${unlisted}&` : ""; let src = `https://player.vimeo.com/video/${id}?${unlisted}background=1&controls=0`; if (this.params.muted) { src += "&muted=1"; } if (this.params.autoplay && (this.params["always-play"] || this.isIntersecting)) { src += "&autoplay=1"; } if (this.params.loop) { src += "&loop=1&autopause=0"; } if (this.params["no-cookie"]) { src += "&dnt=1"; } if (this.params["start-at"]) { src += "#t=" + this.params["start-at"] + "s"; } return src; } injectPlayer() { this.playerElement = this.generatePlayerElement(); this.src = this.generateSrcURL(this.id, this.unlisted); this.playerElement.src = this.src; this.playerElement.id = this.uid; this.stylePlayerElement(this.playerElement); this.element.appendChild(this.playerElement); this.resize(this.playerElement); } updateState(state) { this.currentState = state; this.dispatchEvent("video-background-state-change"); } /* ===== API ===== */ setSource(url) { const pts = url.match(RE_VIMEO); if (!pts || !pts.length) return; this.id = pts[1]; this.src = this.generateSrcURL(this.id); this.playerElement.src = this.src; if (this.element.hasAttribute("data-vbg")) this.element.setAttribute("data-vbg", this.src); if (this.element.hasAttribute("data-ytbg")) this.element.setAttribute("data-ytbg", this.src); this.loadBackground(this.id); } onVideoPlayerReady() { this.mobileLowBatteryAutoplayHack(); if (this.params["start-at"]) this.seekTo(this.params["start-at"]); if (this.params.autoplay && (this.params["always-play"] || this.isIntersecting)) { this.player.play(); } this.player.getDuration().then((duration) => { this.setDuration(duration); }); this.dispatchEvent("video-background-ready"); } onVideoEnded() { this.updateState("ended"); this.dispatchEvent("video-background-ended"); if (!this.params.loop) return this.pause(); this.seekTo(this.params["start-at"]); this.updateState("playing"); this.dispatchEvent("video-background-play"); } onVideoTimeUpdate(event) { this.currentTime = event.seconds; this.percentComplete = this.timeToPercentage(event.seconds); this.dispatchEvent("video-background-time-update"); this.setDuration(event.duration); if (this.params["end-at"] && this.duration && event.seconds >= this.duration) { this.onVideoEnded(); } } onVideoBuffering() { this.updateState("buffering"); } onVideoPlay(event) { this.setDuration(event.duration); if (!this.initialPlay) { this.initialPlay = true; this.playerElement.style.opacity = 1; this.player.setLoop(this.params.loop); if (!(this.params.autoplay && (this.params["always-play"] || this.isIntersecting))) { return this.player.pause(); } } const seconds = event.seconds; if (this.params["start-at"] && seconds < this.params["start-at"]) { this.seekTo(this.params["start-at"]); } if (this.duration && seconds >= this.duration) { this.seekTo(this.params["start-at"]); } this.updateState("playing"); this.dispatchEvent("video-background-play"); } onVideoPause() { this.updateState("paused"); this.dispatchEvent("video-background-pause"); } seek(percentage2) { this.seekTo(this.percentageToTime(percentage2)); } seekTo(time) { if (!this.player) return; this.player.setCurrentTime(time); this.dispatchEvent("video-background-seeked"); } softPause() { if (!this.player || this.currentState === "paused") return; this.player.pause(); } softPlay() { if (!this.player || this.currentState === "playing") return; this.player.play(); } play() { if (!this.player) return; this.paused = false; this.player.play(); } pause() { if (!this.player) return; this.paused = true; this.player.pause(); } unmute() { if (!this.player) return; this.muted = false; if (!this.initialVolume) { this.initialVolume = true; this.setVolume(this.params.volume); } this.player.setMuted(false); this.dispatchEvent("video-background-unmute"); } mute() { if (!this.player) return; this.muted = true; this.player.setMuted(true); this.dispatchEvent("video-background-mute"); } getVolume() { if (!this.player) return; return this.player.getVolume(); } setVolume(volume) { if (!this.player) return; this.volume = volume; this.player.setVolume(volume); this.dispatchEvent("video-background-volume-change"); } }; // src/lib/video-background.js var VideoBackground = class extends SuperVideoBackground { constructor(elem, params, vid_data, uid, factoryInstance) { super(elem, params, vid_data.link, uid, "video", factoryInstance); if (!vid_data || !vid_data.link) return; if (this.is_mobile && !this.params.mobile) return; this.src = vid_data.link; this.ext = /(?:\.([^.]+))?$/.exec(vid_data.id)[1]; this.uid = uid; this.element.setAttribute("data-vbg-uid", uid); this.player = null; this.buttons = {}; this.MIME_MAP = { "ogv": "video/ogg", "ogm": "video/ogg", "ogg": "video/ogg", "avi": "video/avi", "mp4": "video/mp4", "webm": "video/webm" }; this.mime = this.MIME_MAP[this.ext.toLowerCase()]; this.injectPlayer(); this.mobileLowBatteryAutoplayHack(); this.dispatchEvent("video-background-ready"); } generatePlayerElement() { const playerElement = document.createElement("video"); if (this.params.title) playerElement.setAttribute("title", this.params.title); playerElement.setAttribute("playsinline", ""); if (this.params.loop) playerElement.setAttribute("loop", ""); if (this.params.autoplay && (this.params["always-play"] || this.isIntersecting)) { playerElement.setAttribute("autoplay", ""); playerElement.autoplay = true; } if (this.muted) { playerElement.setAttribute("muted", ""); playerElement.muted = true; } if (this.params["lazyloading"]) playerElement.setAttribute("loading", "lazy"); return playerElement; } injectPlayer() { this.player = this.generatePlayerElement(); this.playerElement = this.player; if (this.volume !== 1 && !this.muted) this.setVolume(this.volume); this.playerElement.setAttribute("id", this.uid); this.stylePlayerElement(this.playerElement); this.player.addEventListener("loadedmetadata", this.onVideoLoadedMetadata.bind(this)); this.player.addEventListener("durationchange", this.onVideoLoadedMetadata.bind(this)); this.player.addEventListener("canplay", this.onVideoCanPlay.bind(this)); this.player.addEventListener("timeupdate", this.onVideoTimeUpdate.bind(this)); this.player.addEventListener("play", this.onVideoPlay.bind(this)); this.player.addEventListener("pause", this.onVideoPause.bind(this)); this.player.addEventListener("waiting", this.onVideoBuffering.bind(this)); this.player.addEventListener("ended", this.onVideoEnded.bind(this)); this.element.appendChild(this.playerElement); const source = document.createElement("source"); source.setAttribute("src", this.src); source.setAttribute("type", this.mime); this.playerElement.appendChild(source); this.resize(this.playerElement); } updateState(state) { this.currentState = state; this.dispatchEvent("video-background-state-change"); } /* ===== API ===== */ setSource(url) { const pts = url.match(RE_VIDEO); if (!pts || !pts.length) return; this.id = pts[1]; this.ext = /(?:\.([^.]+))?$/.exec(this.id)[1]; this.mime = this.MIME_MAP[this.ext.toLowerCase()]; this.playerElement.innerHTML = ""; const source = document.createElement("source"); source.setAttribute("src", url); source.setAttribute("type", this.mime); this.playerElement.appendChild(source); this.src = url; if (this.element.hasAttribute("data-vbg")) this.element.setAttribute("data-vbg", this.src); if (this.element.hasAttribute("data-ytbg")) this.element.setAttribute("data-ytbg", this.src); } onVideoLoadedMetadata() { this.setDuration(this.player.duration); } onVideoCanPlay() { this.setDuration(this.player.duration); } onVideoTimeUpdate() { this.currentTime = this.player.currentTime; this.percentComplete = this.timeToPercentage(this.player.currentTime); this.dispatchEvent("video-background-time-update"); if (this.params["end-at"] && this.currentTime >= this.duration) { this.onVideoEnded(); } } onVideoPlay() { if (!this.initialPlay) { this.initialPlay = true; this.playerElement.style.opacity = 1; } const seconds = this.player.currentTime; if (this.params["start-at"] && seconds <= this.params["start-at"]) { this.seekTo(this.params["start-at"]); } if (this.duration && seconds >= this.duration) { this.seekTo(this.params["start-at"]); } this.updateState("playing"); this.dispatchEvent("video-background-play"); } onVideoPause() { this.updateState("paused"); this.dispatchEvent("video-background-pause"); } onVideoEnded() { this.updateState("ended"); this.dispatchEvent("video-background-ended"); if (!this.params.loop) return this.pause(); this.seekTo(this.params["start-at"]); this.onVideoPlay(); } onVideoBuffering() { this.updateState("buffering"); } seek(percentage2) { this.seekTo(this.percentageToTime(percentage2)); } seekTo(seconds) { if (!this.player) return; if (this.player.hasOwnProperty("fastSeek")) { this.player.fastSeek(seconds); return; } this.player.currentTime = seconds; this.dispatchEvent("video-background-seeked"); } softPause() { if (!this.player || this.currentState === "paused") return; this.player.pause(); } softPlay() { if (!this.player || this.currentState === "playing") return; this.player.play(); } play() { if (!this.player) return; this.paused = false; this.player.play(); } pause() { if (!this.player) return; this.paused = true; this.player.pause(); } unmute() { if (!this.player) return; this.muted = false; this.player.muted = false; if (!this.initialVolume) { this.initialVolume = true; this.setVolume(this.params.volume); } this.dispatchEvent("video-background-unmute"); } mute() { if (!this.player) return; this.muted = true; this.player.muted = true; this.dispatchEvent("video-background-mute"); } getVolume() { if (!this.player) return; return this.player.volume; } setVolume(volume) { if (!this.player) return; this.volume = volume; this.player.volume = volume; this.dispatchEvent("video-background-volume-change"); } }; // src/video-backgrounds.js var VideoBackgrounds = class { constructor(selector, params) { this.elements = selector; if (this.elements instanceof Element) this.elements = [this.elements]; if (typeof this.elements === "string") this.elements = document.querySelectorAll(selector); this.index = {}; const self = this; this.intersectionObserver = null; if ("IntersectionObserver" in window) { this.intersectionObserver = new IntersectionObserver(function(entries) { entries.forEach(function(entry) { const uid = entry.target.getAttribute("data-vbg-uid"); if (uid && self.index.hasOwnProperty(uid) && entry.isIntersecting) { self.index[uid].isIntersecting = true; try { if (self.index[uid].player && !self.index[uid].paused) self.index[uid].softPlay(); } catch (e) { } } else { self.index[uid].isIntersecting = false; try { if (self.index[uid].player) self.index[uid].softPause(); } catch (e) { } } }); }); } this.resizeObserver = null; if ("ResizeObserver" in window) { this.resizeObserver = new ResizeObserver(function(entries) { entries.forEach(function(entry) { const uid = entry.target.getAttribute("data-vbg-uid"); if (uid && self.index.hasOwnProperty(uid)) { window.requestAnimationFrame(() => self.index[uid].resize()); } }); }); } else { window.addEventListener("resize", function() { for (let k in self.index) { window.requestAnimationFrame(() => self.index[k].resize(self.index[k].playerElement)); } }); } this.initPlayers(); if (!this.elements || !this.elements.length) return; for (let i = 0; i < this.elements.length; i++) { const element = this.elements[i]; this.add(element, params); } document.addEventListener("visibilitychange", this.onVisibilityChange.bind(this)); } onVisibilityChange() { if (document.hidden) return; for (let k in this.index) { const instance = this.index[k]; if (instance.shouldPlay()) { instance.softPlay(); } } } add(element, params) { if (!element) return; if (element.hasAttribute("data-vbg-uid")) return; if (!this.intersectionObserver) { if (!params) params = {}; params["always-play"] = true; } const link = element.getAttribute("data-youtube") || element.getAttribute("data-vbg"); const vid_data = this.getVidID(link); if (!vid_data) return; const uid = this.generateUID(vid_data.id); if (!uid) return; switch (vid_data.type) { case "YOUTUBE": const yb = new YoutubeBackground(element, params, vid_data.id, uid, this); this.index[uid] = yb; break; case "VIMEO": const vm = new VimeoBackground(element, params, vid_data, uid, this); this.index[uid] = vm; break; case "VIDEO": const vid = new VideoBackground(element, params, vid_data, uid, this); this.index[uid] = vid; break; } if (this.resizeObserver) { this.resizeObserver.observe(element); } if (!this.index[uid].params["always-play"] && this.intersectionObserver) { this.intersectionObserver.observe(element); } } destroy(element) { const uid = element.uid || element.getAttribute("data-vbg-uid"); if (uid && this.index.hasOwnProperty(uid)) { if (!this.index[uid].params["always-play"] && this.intersectionObserver) this.intersectionObserver.unobserve(element); if (this.resizeObserver) this.resizeObserver.unobserve(element); this.index[uid].destroy(); delete this.index[uid]; } } destroyAll() { for (let k in this.index) { this.destroy(this.index[k].playerElement); } } getVidID(link) { if (link === void 0 && link === null) return; this.re = {}; this.re.YOUTUBE = RE_YOUTUBE; this.re.VIMEO = RE_VIMEO; this.re.VIDEO = RE_VIDEO; for (let k in this.re) { const pts = link.match(this.re[k]); if (pts && pts.length) { this.re[k].lastIndex = 0; const data = { id: pts[1], type: k, regex_pts: pts, link }; if (k === "VIMEO") { const unlistedQueryRegex = /(\?|&)h=([^=&#?]+)/; const unlistedPathRegex = /\/[^\/\:\.]+(\:|\/)([^:?\/]+)\s?$/; const unlistedQuery = link.match(unlistedPathRegex) || link.match(unlistedQueryRegex); if (unlistedQuery) data.unlisted = unlistedQuery[2]; } return data; } } return; } generateUID(pref) { pref = pref.replace(/[^a-zA-Z0-9\-_]/g, "-"); pref = pref.replace(/-{2,}/g, "-"); pref = pref.replace(/^-+/, "").replace(/-+$/, ""); pref = "vbg-" + pref; let uid = pref + "-" + randomIntInclusive(0, 9999); while (this.index.hasOwnProperty(uid)) { uid = pref + "-" + randomIntInclusive(0, 9999); } return uid; } get(element) { const uid = typeof element === "string" ? element : element.getAttribute("data-vbg-uid"); if (uid && this.index.hasOwnProperty(uid)) return this.index[uid]; } pauseAll() { for (let k in this.index) { this.index[k].pause(); } } playAll() { for (let k in this.index) { this.index[k].play(); } } muteAll() { for (let k in this.index) { this.index[k].mute(); } } unmuteAll() { for (let k in this.index) { this.index[k].unmute(); } } setVolumeAll(volume) { for (let k in this.index) { this.index[k].setVolume(volume); } } initPlayers(callback) { const self = this; window.onYouTubeIframeAPIReady = function() { for (let k in self.index) { if (self.index[k] instanceof YoutubeBackground) { self.index[k].initYTPlayer(); } } if (callback) { setTimeout(callback, 100); } }; if (window.hasOwnProperty("YT") && window.YT.loaded) { window.onYouTubeIframeAPIReady(); } window.onVimeoIframeAPIReady = function() { for (let k in self.index) { if (self.index[k] instanceof VimeoBackground) { self.index[k].initVimeoPlayer(); } } if (callback) { setTimeout(callback, 100); } }; if (window.hasOwnProperty("Vimeo") && window.Vimeo.hasOwnProperty("Player")) { window.onVimeoIframeAPIReady(); } } }; // src/main.js if (typeof jQuery == "function") { (function($) { $.fn.youtube_background = function(params) { const $this = $(this); if (window.hasOwnProperty("VIDEO_BACKGROUNDS")) { window.VIDEO_BACKGROUNDS.add($this, params); return $this; } window.VIDEO_BACKGROUNDS = new VideoBackgrounds(this, params); return $this; }; })(jQuery); } window.VideoBackgrounds = VideoBackgrounds; const videoBackgrounds = new VideoBackgrounds('[data-vbg]'); })(); //# sourceMappingURL=jquery.youtube-background.js.map