/*À¯Æ©ºê*/ jQuery(document).ready(function() { jQuery('[data-youtube]').youtube_background(); }); /** * jquery.youtube-background v1.0.14 | Nikola Stamatovic <@stamat> | MIT */ (function () { 'use strict'; function hasClass(element, className) { if (element.classList) { return element.classList.contains(className); } return new RegExp('\\b'+ className+'\\b').test(element.className); } function addClass(element, classNames) { if (element.classList) { const classes = classNames.split(' '); for (var i = 0; i < classes.length; i++) { const el_class = classes[i]; element.classList.add(el_class); } return; } if (!hasClass(element, className)) { element.className += ' ' + className; } } function removeClass(element, className) { if (element.classList) { element.classList.remove(className); return; } element.className = element.className.replace(new RegExp('\\b'+ className+'\\b', 'g'), ''); } function isMobile() { let is_mobile = false; (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) is_mobile = true;})(navigator.userAgent||navigator.vendor||window.opera); return is_mobile; } function getRandomIntInclusive(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; //The maximum is inclusive and the minimum is inclusive } function parseResolutionString(res) { const pts = res.split(/\s?:\s?/i); const DEFAULT_RESOLUTION = 16/9; if (pts.length < 2) { return DEFAULT_RESOLUTION; } const w = parseInt(pts[0], 10); const h = parseInt(pts[1], 10); if (isNaN(w) || isNaN(h)) { return DEFAULT_RESOLUTION; } return w/h; } function parseProperties(params, defaults, element, attr_prefix) { let res_params = {}; if (!params) { res_params = defaults; } else { for (let k in defaults) { if (!params.hasOwnProperty(k)) { //load in defaults if the param hasn't been set res_params[k] = defaults[k]; } } } if (!element) return res_params; // load params from data attributes for (let k in res_params) { let data; if (attr_prefix instanceof Array) { for (var 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 !== undefined && data !== null) { data = data === 'false' ? false : data; data = /^\d+$/.test(data) ? parseInt(data, 10) : data; data = /^\d+\.\d+$/.test(data) ? parseFloat(data) : data; res_params[k] = data; } } return res_params; } const tag = document.createElement('script'); tag.src = "https://www.youtube.com/player_api"; const firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); function YoutubeBackground(elem, params, id, uid) { this.is_mobile = isMobile(); this.element = elem; this.ytid = id; this.uid = uid; this.player = null; this.buttons = {}; this.state = {}; this.state.play = false; this.state.mute = false; this.params = {}; const DEFAULTS = { 'pause': false, //deprecated 'play-button': true, 'mute-button': false, 'autoplay': false, 'muted': false, 'loop': true, 'mobile': true, 'load-background': true, 'resolution': '16:9', 'onStatusChange': function() {}, 'inline-styles': true, 'fit-box': true, 'offset': 200, 'start-at': 0, 'end-at': 0, 'poster': null }; this.__init__ = function () { if (!this.ytid) { return; } this.params = parseProperties(params, DEFAULTS, this.element, ['data-ytbg-', 'data-vbg-']); //pause deprecated if (this.params.pause) { this.params['play-button'] = this.params.pause; } this.params.resolution_mod = parseResolutionString(this.params.resolution); this.state.playing = this.params.autoplay; this.state.muted = this.params.muted; this.buildHTML(); this.injectPlayer(); if (this.params['play-button']) { this.generateActionButton({ name: 'play', className: 'play-toggle', innerHtml: '', initialState: false, stateClassName: 'paused', condition_parameter: 'autoplay', stateChildClassNames: ['fa-pause-circle', 'fa-play-circle'], actions: ['play', 'pause'] }); } if (this.params['mute-button']) { this.generateActionButton({ name: 'mute', className: 'mute-toggle', innerHtml: '', initialState: true, stateClassName: 'muted', condition_parameter: 'muted', stateChildClassNames: ['fa-volume-up', 'fa-volume-mute'], actions: ['unmute', 'mute'] }); } }; this.__init__(); } YoutubeBackground.prototype.initYTPlayer = function () { const self = this; if (window.hasOwnProperty('YT')) { this.player = new YT.Player(this.uid, { events: { 'onReady': function(event) { self.onVideoPlayerReady(event); }, 'onStateChange': function(event) { self.onVideoStateChange(event); }, 'onError' : function(event) { //console.error('player_api', event); } } }); } }; YoutubeBackground.prototype.seekTo = function (seconds) { if (seconds > 0) { this.player.seekTo(seconds, true); } }; YoutubeBackground.prototype.onVideoPlayerReady = function (event) { if (this.params.autoplay) { this.seekTo(this.params['start-at']); this.player.playVideo(); } }; YoutubeBackground.prototype.onVideoStateChange = function (event) { if (event.data === 0 && this.params.loop) { this.seekTo(this.params['start-at']); this.player.playVideo(); } if (event.data === -1 && this.params.autoplay) { this.seekTo(this.params['start-at']); this.player.playVideo(); this.element.dispatchEvent(new CustomEvent('video-background-play', { bubbles: true, detail: this })); } if (event.data === 1) { this.iframe.style.opacity = 1; } this.params["onStatusChange"](event); }; YoutubeBackground.prototype.injectPlayer = function () { this.iframe = document.createElement('iframe'); this.iframe.setAttribute('frameborder', 0); this.iframe.setAttribute('allow', 'autoplay; mute'); let src = `https://www.youtube.com/embed/${this.ytid}?&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) { src += '&autoplay=1'; } if (this.params.loop) { src += '&loop=1'; } if (this.params['end-at'] > 0) { src += `&end=${this.params['end-at']}`; } this.iframe.src = src; if (this.uid) { this.iframe.id = this.uid; } if (this.params['inline-styles']) { this.iframe.style.top = '50%'; this.iframe.style.left = '50%'; this.iframe.style.transform = 'translateX(-50%) translateY(-50%)'; this.iframe.style.position = 'absolute'; this.iframe.style.opacity = 0; } this.element.appendChild(this.iframe); if (this.params['fit-box']) { this.iframe.style.width = '100%'; this.iframe.style.height = '100%'; } else { const self = this; //TODO❗️: maybe a spacer or at least add requestAnimationFrame function onResize() { const h = self.iframe.parentNode.offsetHeight + self.params.offset; // since showinfo is deprecated and ignored after September 25, 2018. we add +200 to hide it in the overflow const w = self.iframe.parentNode.offsetWidth + self.params.offset; const res = self.params.resolution_mod; if (res > w/h) { self.iframe.style.width = h*res + 'px'; self.iframe.style.height = h + 'px'; } else { self.iframe.style.width = w + 'px'; self.iframe.style.height = w/res + 'px'; } } if (window.hasOwnProperty('ResizeObserver')) { const resize_observer = new ResizeObserver(() => { window.requestAnimationFrame(onResize); }); resize_observer.observe(this.element); } else { window.addEventListener('resize', () => { window.requestAnimationFrame(onResize); }); } onResize(); } }; YoutubeBackground.prototype.buildHTML = function () { const parent = this.element.parentNode; // wrap addClass(this.element, 'youtube-background video-background'); //set css rules const wrapper_styles = { "height" : "100%", "width" : "100%", "z-index": "0", "position": "absolute", "overflow": "hidden", "top": 0, // added by @insad "left": 0, "bottom": 0, "right": 0 }; if (!this.params['mute-button']) { wrapper_styles["pointer-events"] = "none"; // avoid right mouse click popup menu } if (this.params['load-background'] || this.params['poster']) { if (this.params['load-background']) wrapper_styles['background-image'] = 'url(https://img.youtube.com/vi/'+this.ytid+'/maxresdefault.jpg)'; if (this.params['poster']) wrapper_styles['background-image'] = 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.is_mobile && !this.params.mobile) { return this.element; } // set play/mute controls wrap 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; }; YoutubeBackground.prototype.play = function () { //TODO: solve this with ARIA toggle states. P.S. warning repetitive code!!! if (this.buttons.hasOwnProperty('play')) { const btn_obj = this.buttons.play; removeClass(btn_obj.element, btn_obj.button_properties.stateClassName); addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]); removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]); } if (this.player) { if (this.params['start-at'] && this.player.getCurrentTime() < this.params['start-at'] ) { this.seekTo(this.params['start-at']); } this.player.playVideo(); this.element.dispatchEvent(new CustomEvent('video-background-play', { bubbles: true, detail: this })); } }; YoutubeBackground.prototype.pause = function () { //TODO: solve this with ARIA toggle states if (this.buttons.hasOwnProperty('play')) { const btn_obj = this.buttons.play; addClass(btn_obj.element, btn_obj.button_properties.stateClassName); removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]); addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]); } if (this.player) { this.player.pauseVideo(); this.element.dispatchEvent(new CustomEvent('video-background-pause', { bubbles: true, detail: this })); } }; YoutubeBackground.prototype.unmute = function () { //TODO: solve this with ARIA toggle states if (this.buttons.hasOwnProperty('mute')) { const btn_obj = this.buttons.mute; removeClass(btn_obj.element, btn_obj.button_properties.stateClassName); addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]); removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]); } if (this.player) { this.player.unMute(); this.element.dispatchEvent(new CustomEvent('video-background-unmute', { bubbles: true, detail: this })); } }; YoutubeBackground.prototype.mute = function () { //TODO: solve this with ARIA toggle states if (this.buttons.hasOwnProperty('mute')) { const btn_obj = this.buttons.mute; addClass(btn_obj.element, btn_obj.button_properties.stateClassName); removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]); addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]); } if (this.player) { this.player.mute(); this.element.dispatchEvent(new CustomEvent('video-background-mute', { bubbles: true, detail: this })); } }; //TODO: refactor states to be equal for all buttons YoutubeBackground.prototype.generateActionButton = function (obj) { const btn = document.createElement('button'); btn.className = obj.className; btn.innerHTML = obj.innerHtml; addClass(btn.firstChild, obj.stateChildClassNames[0]); //TODO: solve this with ARIA toggle states if (this.params[obj.condition_parameter] === obj.initialState) { addClass(btn, obj.stateClassName); removeClass(btn.firstChild, obj.stateChildClassNames[0]); addClass(btn.firstChild, obj.stateChildClassNames[1]); } const self = this; btn.addEventListener('click', function(e) { if (hasClass(this, obj.stateClassName)) { self.state[obj.name] = false; self[obj.actions[0]](); } else { self.state[obj.name] = true; self[obj.actions[1]](); } }); this.buttons[obj.name] = { element: btn, button_properties: obj }; this.controls_element.appendChild(btn); }; function VimeoBackground(elem, params, id, uid) { this.is_mobile = isMobile(); this.element = elem; this.vid = id; this.uid = uid; this.player = null; this.buttons = {}; this.state = {}; this.state.play = false; this.state.mute = false; this.params = {}; const DEFAULTS = { // 'pause': false, //deprecated // 'play-button': false, // 'mute-button': false, 'autoplay': true, 'muted': true, 'loop': true, 'mobile': false, // 'load-background': true, 'resolution': '16:9', 'inline-styles': true, 'fit-box': false, 'offset': 200, 'start-at': 0, 'poster': null }; this.__init__ = function () { if (!this.vid) { return; } this.params = parseProperties(params, DEFAULTS, this.element, ['data-ytbg-', 'data-vbg-']); //pause deprecated if (this.params.pause) { this.params['play-button'] = this.params.pause; } this.params.resolution_mod = parseResolutionString(this.params.resolution); this.state.playing = this.params.autoplay; this.state.muted = this.params.muted; this.buildHTML(); this.injectPlayer(); }; this.__init__(); } VimeoBackground.prototype.injectPlayer = function () { this.iframe = document.createElement('iframe'); this.iframe.setAttribute('frameborder', 0); this.iframe.setAttribute('allow', ['autoplay; mute']); let src = 'https://player.vimeo.com/video/'+this.vid+'?background=1&controls=0'; if (this.params.muted) { src += '&muted=1'; } if (this.params.autoplay) { src += '&autoplay=1'; } if (this.params.loop) { src += '&loop=1&autopause=0'; } //WARN❗️ this is a hash not a query param if (this.params['start-at']) { src += '#t=' + this.params['start-at'] + 's'; } this.iframe.src = src; if (this.uid) { this.iframe.id = this.uid; } if (this.params['load-background'] || this.params['poster']) { //if (this.params['load-background']) wrapper_styles['background-image'] = 'url(https://img.youtube.com/vi/'+this.ytid+'/maxresdefault.jpg)'; if (this.params['poster']) wrapper_styles['background-image'] = this.params['poster']; wrapper_styles['background-size'] = 'cover'; wrapper_styles['background-repeat'] = 'no-repeat'; wrapper_styles['background-position'] = 'center'; } if (this.params['inline-styles']) { this.iframe.style.top = '50%'; this.iframe.style.left = '50%'; this.iframe.style.transform = 'translateX(-50%) translateY(-50%)'; this.iframe.style.position = 'absolute'; this.iframe.style.opacity = 1; } this.element.appendChild(this.iframe); if (this.params['fit-box']) { this.iframe.style.width = '100%'; this.iframe.style.height = '100%'; } else { const self = this; const onResize = function() { const h = self.iframe.parentNode.offsetHeight + self.params.offset; // since showinfo is deprecated and ignored after September 25, 2018. we add +200 to hide it in the overflow const w = self.iframe.parentNode.offsetWidth + self.params.offset; const res = self.params.resolution_mod; if (res > w/h) { self.iframe.style.width = h*res + 'px'; self.iframe.style.height = h + 'px'; } else { self.iframe.style.width = w + 'px'; self.iframe.style.height = w/res + 'px'; } }; if (window.hasOwnProperty('ResizeObserver')) { const resize_observer = new ResizeObserver(() => { window.requestAnimationFrame(onResize); }); resize_observer.observe(this.element); } else { window.addEventListener('resize', () => { window.requestAnimationFrame(onResize); }); } onResize(); } }; VimeoBackground.prototype.buildHTML = function () { const parent = this.element.parentNode; // wrap addClass(this.element, 'youtube-background'); //set css rules const wrapper_styles = { "height" : "100%", "width" : "100%", "z-index": "0", "position": "absolute", "overflow": "hidden", "top": 0, // added by @insad "left": 0, "bottom": 0, "right": 0 }; if (this.params['load-background'] || this.params['poster']) { //if (this.params['load-background']) wrapper_styles['background-image'] = 'url(https://img.youtube.com/vi/'+this.ytid+'/maxresdefault.jpg)'; if (this.params['poster']) wrapper_styles['background-image'] = this.params['poster']; wrapper_styles['background-size'] = 'cover'; wrapper_styles['background-repeat'] = 'no-repeat'; wrapper_styles['background-position'] = 'center'; } if (!this.params['mute-button']) { wrapper_styles["pointer-events"] = "none"; // avoid right mouse click popup menu } if (this.params['load-background']) { //TODO: wrapper_styles['background-image'] = 'url(https://img.youtube.com/vi/'+this.vid+'/maxresdefault.jpg)'; 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'; } } return this.element; }; function VideoBackground(elem, params, vid_data, uid) { this.is_mobile = isMobile(); this.element = elem; this.link = vid_data.link; this.ext = vid_data.id; this.uid = uid; this.player = null; this.buttons = {}; this.state = {}; this.state.play = false; this.state.mute = false; this.params = {}; const MIME_MAP = { 'ogv' : 'video/ogg', 'ogm' : 'video/ogg', 'ogg' : 'video/ogg', 'avi' : 'video/avi', 'mp4' : 'video/mp4', 'webm' : 'video/webm' }; const DEFAULTS = { 'pause': false, //deprecated 'play-button': false, 'mute-button': false, 'autoplay': true, 'muted': true, 'loop': true, 'mobile': false, 'resolution': '16:9', 'inline-styles': true, 'fit-box': false, 'offset': 200, // 'start-at': 0, // 'end-at': 0, 'poster': null }; this.__init__ = function () { if (!this.link || !this.ext) { return; } this.mime = MIME_MAP[this.ext.toLowerCase()]; this.params = parseProperties(params, DEFAULTS, this.element, ['data-ytbg-', 'data-vbg-']); //pause deprecated if (this.params.pause) { this.params['play-button'] = this.params.pause; } this.params.resolution_mod = parseResolutionString(this.params.resolution); this.state.playing = this.params.autoplay; this.state.muted = this.params.muted; this.buildHTML(); this.injectPlayer(); if (this.params['play-button']) { this.generateActionButton({ name: 'play', className: 'play-toggle', innerHtml: '', initialState: false, stateClassName: 'paused', condition_parameter: 'autoplay', stateChildClassNames: ['fa-pause-circle', 'fa-play-circle'], actions: ['play', 'pause'] }); } if (this.params['mute-button']) { this.generateActionButton({ name: 'mute', className: 'mute-toggle', innerHtml: '', initialState: true, stateClassName: 'muted', condition_parameter: 'muted', stateChildClassNames: ['fa-volume-up', 'fa-volume-mute'], actions: ['unmute', 'mute'] }); } }; this.__init__(); } VideoBackground.prototype.seekTo = function (seconds) { if (this.player.hasOwnProperty('fastSeek')) { this.player.fastSeek(seconds); return; } this.player.currentTime = seconds; }; VideoBackground.prototype.injectPlayer = function () { this.player = document.createElement('video'); this.player.muted = this.params.muted; this.player.autoplay = this.params.autoplay; this.player.loop = this.params.loop; this.player.playsinline = true; this.player.setAttribute('id', this.uid); if (this.params['inline-styles']) { this.player.style.top = '50%'; this.player.style.left = '50%'; this.player.style.transform = 'translateX(-50%) translateY(-50%)'; this.player.style.position = 'absolute'; this.player.style.opacity = 0; this.player.addEventListener('canplay', (e) => { e.target.style.opacity = 1; }); } const self = this; /* this.player.addEventListener('canplay', (e) => { if (self.params['start-at'] && self.params.autoplay) { self.seekTo(self.params['start-at']); } }); this.player.addEventListener('canplaythrough', (e) => { if (self.params['end-at'] > 0) { self.player.addEventListener('timeupdate', (e) => { if (self.params['end-at'] >= self.player.currentTime) { self.seekTo(self.params['start-at']); } }); } }); */ const source = document.createElement('source'); source.setAttribute('src', this.link); source.setAttribute('type', this.mime); this.player.appendChild(source); this.element.appendChild(this.player); if (this.params['fit-box']) { this.player.style.width = '100%'; this.player.style.height = '100%'; } else { //TODO❗️: maybe a spacer or at least add requestAnimationFrame function onResize() { const h = self.player.parentNode.offsetHeight + self.params.offset; // since showinfo is deprecated and ignored after September 25, 2018. we add +200 to hide it in the overflow const w = self.player.parentNode.offsetWidth + self.params.offset; const res = self.params.resolution_mod; if (res > w/h) { self.player.style.width = h*res + 'px'; self.player.style.height = h + 'px'; } else { self.player.style.width = w + 'px'; self.player.style.height = w/res + 'px'; } } if (window.hasOwnProperty('ResizeObserver')) { const resize_observer = new ResizeObserver(() => { window.requestAnimationFrame(onResize); }); resize_observer.observe(this.element); } else { window.addEventListener('resize', () => { window.requestAnimationFrame(onResize); }); } onResize(); } }; VideoBackground.prototype.buildHTML = function () { const parent = this.element.parentNode; // wrap addClass(this.element, 'video-background'); //set css rules const wrapper_styles = { "height" : "100%", "width" : "100%", "z-index": "0", "position": "absolute", "overflow": "hidden", "top": 0, // added by @insad "left": 0, "bottom": 0, "right": 0 }; if (!this.params['mute-button']) { wrapper_styles["pointer-events"] = "none"; // avoid right mouse click popup menu } if (this.params['load-background'] || this.params['poster']) { 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.is_mobile && !this.params.mobile) { return this.element; } // set play/mute controls wrap 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; }; VideoBackground.prototype.play = function () { //TODO: solve this with ARIA toggle states. P.S. warning repetitive code!!! if (this.buttons.hasOwnProperty('play')) { const btn_obj = this.buttons.play; removeClass(btn_obj.element, btn_obj.button_properties.stateClassName); addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]); removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]); } if (this.player) { /* if (this.params['start-at'] && this.player.currentTime < this.params['start-at'] ) { this.seekTo(this.params['start-at']); } */ this.player.play(); this.element.dispatchEvent(new CustomEvent('video-background-play', { bubbles: true, detail: this })); } }; VideoBackground.prototype.pause = function () { //TODO: solve this with ARIA toggle states if (this.buttons.hasOwnProperty('play')) { const btn_obj = this.buttons.play; addClass(btn_obj.element, btn_obj.button_properties.stateClassName); removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]); addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]); } if (this.player) { this.player.pause(); this.element.dispatchEvent(new CustomEvent('video-background-pause', { bubbles: true, detail: this })); } }; VideoBackground.prototype.unmute = function () { //TODO: solve this with ARIA toggle states if (this.buttons.hasOwnProperty('mute')) { const btn_obj = this.buttons.mute; removeClass(btn_obj.element, btn_obj.button_properties.stateClassName); addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]); removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]); } if (this.player) { this.player.muted = false; this.element.dispatchEvent(new CustomEvent('video-background-unmute', { bubbles: true, detail: this })); } }; VideoBackground.prototype.mute = function () { //TODO: solve this with ARIA toggle states if (this.buttons.hasOwnProperty('mute')) { const btn_obj = this.buttons.mute; addClass(btn_obj.element, btn_obj.button_properties.stateClassName); removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]); addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]); } if (this.player) { this.player.muted = true; this.element.dispatchEvent(new CustomEvent('video-background-mute', { bubbles: true, detail: this })); } }; //TODO: refactor states to be equal for all buttons VideoBackground.prototype.generateActionButton = function (obj) { const btn = document.createElement('button'); btn.className = obj.className; btn.innerHTML = obj.innerHtml; addClass(btn.firstChild, obj.stateChildClassNames[0]); //TODO: solve this with ARIA toggle states if (this.params[obj.condition_parameter] === obj.initialState) { addClass(btn, obj.stateClassName); removeClass(btn.firstChild, obj.stateChildClassNames[0]); addClass(btn.firstChild, obj.stateChildClassNames[1]); } const self = this; btn.addEventListener('click', function(e) { if (hasClass(this, obj.stateClassName)) { self.state[obj.name] = false; self[obj.actions[0]](); } else { self.state[obj.name] = true; self[obj.actions[1]](); } }); this.buttons[obj.name] = { element: btn, button_properties: obj }; this.controls_element.appendChild(btn); }; function VideoBackgrounds(selector, params) { this.elements = selector; if (typeof selector === 'string') { this.elements = document.querySelectorAll(selector); } this.index = {}; this.re = {}; this.re.YOUTUBE = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i; this.re.VIMEO = /(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^\/]*)\/videos\/|album\/(?:\d+)\/video\/|video\/|)(\d+)(?:[a-zA-Z0-9_\-]+)?/i; this.re.VIDEO = /\/[^\/]+\.(mp4|ogg|ogv|ogm|webm|avi)\s?$/i; this.__init__ = function () { for (let i = 0; i < this.elements.length; i++) { const element = this.elements[i]; const link = element.getAttribute('data-youtube') || element.getAttribute('data-vbg'); const vid_data = this.getVidID(link); if (!vid_data) { continue; } const uid = this.generateUID(vid_data.id); if (!uid) { continue; } switch (vid_data.type) { case 'YOUTUBE': const yb = new YoutubeBackground(element, params, vid_data.id, uid); this.index[uid] = yb; break; case 'VIMEO': const vm = new VimeoBackground(element, params, vid_data.id, uid); this.index[uid] = vm; break; case 'VIDEO': const vid = new VideoBackground(element, params, vid_data, uid); this.index[uid] = vid; break; } } this.initYTPlayers(/*function() { //TODO: FIX! if (params && (params.hasOwnProperty('activity_timeout') || params.hasOwnProperty('inactivity_timeout'))) { this.activity_monitor = new ActivityMonitor(function () { self.playVideos(); }, function() { self.pauseVideos(); }, params ? params.activity_timeout : null, params ? params.inactivity_timeout : null, ['mousemove', 'scroll'] ); } }*/); }; this.__init__(); } VideoBackgrounds.prototype.getVidID = function (link) { if (link !== undefined && link !== null) { for (let k in this.re) { const pts = link.match(this.re[k]); if (pts && pts.length) { this.re[k].lastIndex = 0; return { id: pts[1], type: k, regex_pts: pts, link: link }; } } } return null; }; VideoBackgrounds.prototype.generateUID = function (pref) { //index the instance let uid = pref +'-'+ getRandomIntInclusive(0, 9999); while (this.index.hasOwnProperty(uid)) { uid = pref +'-'+ getRandomIntInclusive(0, 9999); } return uid; }; VideoBackgrounds.prototype.pauseVideos = function () { for (let k in this.index) { this.index[k].pause(); } }; VideoBackgrounds.prototype.playVideos = function () { for (let k in this.index) { this.index[k].play(); } }; VideoBackgrounds.prototype.initYTPlayers = function (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(); } }; if (typeof jQuery == 'function') { (function ($) { $.fn.youtube_background = function (params) { const $this = $(this); new VideoBackgrounds(this, params); return $this; }; })(jQuery); } window.VideoBackgrounds = VideoBackgrounds; })();