PageSourceSearch

https://www.akrontecnologia.com.br/_cdn/video_background/jquery.video.background.js?v=1763755651

js akrontecnologia.com.br collected 2026-10-02 01:18:12 UTC 36,770 bytes, 1,139 lines download raw bytes

1/**
2 * jquery.youtube-background v1.0.14 | Nikola Stamatovic <@stamat> | MIT
3 */
4
5(function () {
6  'use strict';
7
8  function hasClass(element, className) {
9    if (element.classList) {
10      return element.classList.contains(className);
11    }
12    return new RegExp('\\b'+ className+'\\b').test(element.className);
13  }
14
15  function addClass(element, classNames) {
16    if (element.classList) {
17      const classes = classNames.split(' ');
18      for (var i = 0; i < classes.length; i++) {
19        const el_class = classes[i];
20        element.classList.add(el_class);
21      }
22      return;
23    }
24
25    if (!hasClass(element, className)) {
26      element.className += ' ' + className;
27    }
28  }
29
30  function removeClass(element, className) {
31    if (element.classList) {
32      element.classList.remove(className);
33      return;
34    }
35
36    element.className = element.className.replace(new RegExp('\\b'+ className+'\\b', 'g'), '');
37  }
38
39  function isMobile() {
40    let is_mobile = false;
41    (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);
42
43    return is_mobile;
44  }
45
46  function getRandomIntInclusive(min, max) {
47    min = Math.ceil(min);
48    max = Math.floor(max);
49    return Math.floor(Math.random() * (max - min + 1)) + min; //The maximum is inclusive and the minimum is inclusive
50  }
51
52  function parseResolutionString(res) {
53    const pts = res.split(/\s?:\s?/i);
54    const DEFAULT_RESOLUTION = 16/9;
55    if (pts.length < 2) {
56      return DEFAULT_RESOLUTION;
57    }
58
59    const w = parseInt(pts[0], 10);
60    const h = parseInt(pts[1], 10);
61
62    if (isNaN(w) || isNaN(h)) {
63      return DEFAULT_RESOLUTION;
64    }
65
66    return w/h;
67  }
68
69  function parseProperties(params, defaults, element, attr_prefix) {
70    let res_params = {};
71
72    if (!params) {
73      res_params = defaults;
74    } else {
75      for (let k in defaults) {
76        if (!params.hasOwnProperty(k)) {
77          //load in defaults if the param hasn't been set
78          res_params[k] = defaults[k];
79        }
80      }
81    }
82
83    if (!element) return res_params;
84    // load params from data attributes
85    for (let k in res_params) {
86      let data;
87
88      if (attr_prefix instanceof Array) {
89        for (var i = 0; i < attr_prefix.length; i++) {
90          const temp_data = element.getAttribute(attr_prefix[i]+k);
91          if (temp_data) {
92            data = temp_data;
93            break;
94          }
95        }
96      } else {
97        data = element.getAttribute(attr_prefix+k);
98      }
99
100      if (data !== undefined && data !== null) {
101        data = data === 'false' ? false : data;
102        data = /^\d+$/.test(data) ? parseInt(data, 10) : data;
103        data = /^\d+\.\d+$/.test(data) ? parseFloat(data) : data;
104        res_params[k] = data;
105      }
106    }
107
108    return res_params;
109  }
110
111  const tag = document.createElement('script');
112  tag.src = "https://www.youtube.com/player_api";
113  const firstScriptTag = document.getElementsByTagName('script')[0];
114  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
115
116  function YoutubeBackground(elem, params, id, uid) {
117    this.is_mobile = isMobile();
118
119    this.element = elem;
120    this.ytid = id;
121    this.uid = uid;
122    this.player = null;
123    this.buttons = {};
124
125    this.state = {};
126    this.state.play = false;
127    this.state.mute = false;
128
129    this.params = {};
130
131    const DEFAULTS = {
132      'pause': false, //deprecated
133      'play-button': false,
134      'mute-button': false,
135      'autoplay': true,
136      'muted': true,
137      'loop': true,
138      'mobile': true,
139      'load-background': true,
140      'resolution': '16:9',
141      'onStatusChange': function() {},
142      'inline-styles': true,
143      'fit-box': false,
144      'offset': 200,
145      'start-at': 0,
146      'end-at': 0,
147      'poster': null
148    };
149
150    this.__init__ = function () {
151      if (!this.ytid) {
152        return;
153      }
154
155      this.params = parseProperties(params, DEFAULTS, this.element, ['data-ytbg-', 'data-vbg-']);
156      //pause deprecated
157      if (this.params.pause) {
158        this.params['play-button'] = this.params.pause;
159      }
160      this.params.resolution_mod = parseResolutionString(this.params.resolution);
161      this.state.playing = this.params.autoplay;
162      this.state.muted = this.params.muted;
163      this.buildHTML();
164      this.injectPlayer();
165
166
167      if (this.params['play-button']) {
168        this.generateActionButton({
169          name: 'play',
170          className: 'play-toggle',
171          innerHtml: '<i class="fa"></i>',
172          initialState: false,
173          stateClassName: 'paused',
174          condition_parameter: 'autoplay',
175          stateChildClassNames: ['fa-pause-circle', 'fa-play-circle'],
176          actions: ['play', 'pause']
177        });
178      }
179
180      if (this.params['mute-button']) {
181        this.generateActionButton({
182          name: 'mute',
183          className: 'mute-toggle',
184          innerHtml: '<span class="icon icon-notext"></span>',
185          initialState: true,
186          stateClassName: 'muted',
187          condition_parameter: 'muted',
188          stateChildClassNames: ['icon-volume-high', 'icon-volume-mute2'],
189          actions: ['unmute', 'mute']
190        });
191      }
192    };
193
194    this.__init__();
195  }
196
197  YoutubeBackground.prototype.initYTPlayer = function () {
198    const self = this;
199    if (window.hasOwnProperty('YT')) {
200      this.player = new YT.Player(this.uid, {
201        events: {
202          'onReady': function(event) {
203            self.onVideoPlayerReady(event);
204          },
205          'onStateChange': function(event) {
206            self.onVideoStateChange(event);
207          },
208          'onError' : function(event) {
209            //console.error('player_api', event);
210          }
211        }
212      });
213    }
214  };
215
216  YoutubeBackground.prototype.seekTo = function (seconds) {
217    if (seconds > 0) {
218      this.player.seekTo(seconds, true);
219    }
220  };
221
222  YoutubeBackground.prototype.onVideoPlayerReady = function (event) {
223    if (this.params.autoplay) {
224      this.seekTo(this.params['start-at']);
225      this.player.playVideo();
226    }
227  };
228
229  YoutubeBackground.prototype.onVideoStateChange = function (event) {
230    if (event.data === 0 && this.params.loop) {
231      this.seekTo(this.params['start-at']);
232      this.player.playVideo();
233    }
234
235    if (event.data === -1 && this.params.autoplay) {
236      this.seekTo(this.params['start-at']);
237      this.player.playVideo();
238      this.element.dispatchEvent(new CustomEvent('video-background-play', { bubbles: true, detail: this }));
239    }
240
241    if (event.data === 1) {
242      this.iframe.style.opacity = 1;
243    }
244
245    this.params["onStatusChange"](event);
246  };
247
248  YoutubeBackground.prototype.injectPlayer = function () {
249    this.iframe = document.createElement('iframe');
250    this.iframe.setAttribute('frameborder', 0);
251    this.iframe.setAttribute('allow', 'autoplay; mute');
252    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`;
253
254    if (this.params.muted) {
255      src += '&mute=1';
256    }
257
258    if (this.params.autoplay) {
259      src += '&autoplay=1';
260    }
261
262    if (this.params.loop) {
263      src += '&loop=1';
264    }
265
266    if (this.params['end-at'] > 0) {
267      src += `&end=${this.params['end-at']}`;
268    }
269
270    this.iframe.src = src;
271
272    if (this.uid) {
273      this.iframe.id = this.uid;
274    }
275
276    if (this.params['inline-styles']) {
277      this.iframe.style.top = '50%';
278      this.iframe.style.left = '50%';
279      this.iframe.style.transform = 'translate(-50%, -50%)';
280      this.iframe.style.position = 'absolute';
281      this.iframe.style.opacity = 0;
282    }
283
284    this.element.appendChild(this.iframe);
285
286    if (this.params['fit-box']) {
287      this.iframe.style.width = '100%';
288      this.iframe.style.height = '100%';
289    } else {
290      const self = this;
291
292      //TODO❗️: maybe a spacer or at least add requestAnimationFrame
293      function onResize() {
294        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
295        const w = self.iframe.parentNode.offsetWidth + self.params.offset;
296        const res = self.params.resolution_mod;
297
298        if (res > w/h) {
299          self.iframe.style.width = h*res + 'px';
300          self.iframe.style.height = h + 'px';
301        } else {
302          self.iframe.style.width = w + 'px';
303          self.iframe.style.height = w/res + 'px';
304        }
305      }
306
307      if (window.hasOwnProperty('ResizeObserver')) {
308        const resize_observer = new ResizeObserver(() => {
309          window.requestAnimationFrame(onResize);
310        });
311        resize_observer.observe(this.element);
312      } else {
313        window.addEventListener('resize', () => {
314          window.requestAnimationFrame(onResize);
315        });
316      }
317      onResize();
318    }
319  };
320
321  YoutubeBackground.prototype.buildHTML = function () {
322    const parent = this.element.parentNode;
323    // wrap
324    addClass(this.element, 'youtube-background video-background');
325
326    //set css rules
327    const wrapper_styles = {
328      "height" : "100%",
329      "width" : "100%",
330      "z-index": "0",
331      "position": "absolute",
332      "overflow": "hidden",
333      "top": 0, // added by @insad
334      "left": 0,
335      "bottom": 0,
336      "right": 0
337    };
338
339    if (!this.params['mute-button']) {
340      wrapper_styles["pointer-events"] = "none"; // avoid right mouse click popup menu
341    }
342
343    if (this.params['load-background'] || this.params['poster']) {
344      if (this.params['load-background']) wrapper_styles['background-image'] = 'url(https://img.youtube.com/vi/'+this.ytid+'/maxresdefault.jpg)';
345      if (this.params['poster']) wrapper_styles['background-image'] = this.params['poster'];
346      wrapper_styles['background-size'] = 'cover';
347      wrapper_styles['background-repeat'] = 'no-repeat';
348      wrapper_styles['background-position'] = 'center';
349    }
350
351    if (this.params['inline-styles']) {
352      for (let property in wrapper_styles) {
353        this.element.style[property] = wrapper_styles[property];
354      }
355      
356      if (!['absolute', 'fixed', 'relative', 'sticky'].indexOf(parent.style.position)) {
357        parent.style.position = 'relative';
358      }
359    }
360
361    if (this.is_mobile && !this.params.mobile) {
362      return this.element;
363    }
364
365    // set play/mute controls wrap
366    if (this.params['play-button'] || this.params['mute-button']) {
367      const controls = document.createElement('div');
368      controls.className = 'video-background-controls';
369
370      controls.style.position = 'absolute';
371      // controls.style.top = '-10px';
372      controls.style.top = '10px';
373      controls.style.right = '10px';
374      controls.style['z-index'] = 2;
375
376      this.controls_element = controls;
377      parent.appendChild(controls);
378    }
379
380    return this.element;
381  };
382
383  YoutubeBackground.prototype.play = function () {
384    //TODO: solve this with ARIA toggle states. P.S. warning repetitive code!!!
385    if (this.buttons.hasOwnProperty('play')) {
386      const btn_obj = this.buttons.play;
387      removeClass(btn_obj.element, btn_obj.button_properties.stateClassName);
388      addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]);
389      removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]);
390    }
391
392    if (this.player) {
393      if (this.params['start-at'] && this.player.getCurrentTime() < this.params['start-at'] ) {
394        this.seekTo(this.params['start-at']);
395      }
396      this.player.playVideo();
397      this.element.dispatchEvent(new CustomEvent('video-background-play', { bubbles: true, detail: this }));
398    }
399  };
400
401  YoutubeBackground.prototype.pause = function () {
402    //TODO: solve this with ARIA toggle states
403    if (this.buttons.hasOwnProperty('play')) {
404      const btn_obj = this.buttons.play;
405      addClass(btn_obj.element, btn_obj.button_properties.stateClassName);
406      removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]);
407      addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]);
408    }
409
410    if (this.player) {
411      this.player.pauseVideo();
412      this.element.dispatchEvent(new CustomEvent('video-background-pause', { bubbles: true, detail: this }));
413    }
414  };
415
416  YoutubeBackground.prototype.unmute = function () {
417    //TODO: solve this with ARIA toggle states
418    if (this.buttons.hasOwnProperty('mute')) {
419      const btn_obj = this.buttons.mute;
420      removeClass(btn_obj.element, btn_obj.button_properties.stateClassName);
421      addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]);
422      removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]);
423    }
424
425    if (this.player) {
426      this.player.unMute();
427      this.element.dispatchEvent(new CustomEvent('video-background-unmute', { bubbles: true, detail: this }));
428    }
429  };
430
431  YoutubeBackground.prototype.mute = function () {
432    //TODO: solve this with ARIA toggle states
433    if (this.buttons.hasOwnProperty('mute')) {
434      const btn_obj = this.buttons.mute;
435      addClass(btn_obj.element, btn_obj.button_properties.stateClassName);
436      removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]);
437      addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]);
438    }
439
440    if (this.player) {
441      this.player.mute();
442      this.element.dispatchEvent(new CustomEvent('video-background-mute', { bubbles: true, detail: this }));
443    }
444  };
445
446  //TODO: refactor states to be equal for all buttons
447  YoutubeBackground.prototype.generateActionButton = function (obj) {
448    const btn = document.createElement('button');
449    btn.className = obj.className;
450    btn.innerHTML = obj.innerHtml;
451    addClass(btn.firstChild, obj.stateChildClassNames[0]);
452
453    //TODO: solve this with ARIA toggle states
454    if (this.params[obj.condition_parameter] === obj.initialState) {
455      addClass(btn, obj.stateClassName);
456      removeClass(btn.firstChild, obj.stateChildClassNames[0]);
457      addClass(btn.firstChild, obj.stateChildClassNames[1]);
458    }
459
460    const self = this;
461    btn.addEventListener('click', function(e) {
462      if (hasClass(this, obj.stateClassName)) {
463        self.state[obj.name] = false;
464        self[obj.actions[0]]();
465      } else {
466        self.state[obj.name] = true;
467        self[obj.actions[1]]();
468      }
469    });
470
471    this.buttons[obj.name] = {
472      element: btn,
473      button_properties: obj
474    };
475
476    this.controls_element.appendChild(btn);
477  };
478
479  function VimeoBackground(elem, params, id, uid) {
480    this.is_mobile = isMobile();
481
482    this.element = elem;
483    this.vid = id;
484    this.uid = uid;
485    this.player = null;
486    this.buttons = {};
487
488    this.state = {};
489    this.state.play = false;
490    this.state.mute = false;
491
492    this.params = {};
493
494    const DEFAULTS = {
495      'pause': false, //deprecated
496      'play-button': false,
497      'mute-button': false,
498      'autoplay': true,
499      'muted': true,
500      'loop': true,
501      'mobile': false,
502      'load-background': true,
503      'resolution': '16:9',
504      'inline-styles': true,
505      'fit-box': false,
506      'offset': 200,
507      'start-at': 0,
508      'poster': null
509    };
510
511    this.__init__ = function () {
512      if (!this.vid) {
513        return;
514      }
515
516      this.params = parseProperties(params, DEFAULTS, this.element, ['data-ytbg-', 'data-vbg-']);
517      //pause deprecated
518      if (this.params.pause) {
519        this.params['play-button'] = this.params.pause;
520      }
521      this.params.resolution_mod = parseResolutionString(this.params.resolution);
522      this.state.playing = this.params.autoplay;
523      this.state.muted = this.params.muted;
524
525      this.buildHTML();
526      this.injectPlayer();
527    };
528
529    this.__init__();
530  }
531
532  VimeoBackground.prototype.injectPlayer = function () {
533    this.iframe = document.createElement('iframe');
534    this.iframe.setAttribute('frameborder', 0);
535    this.iframe.setAttribute('allow', ['autoplay; mute']);
536    let src = 'https://player.vimeo.com/video/'+this.vid+'?background=1&controls=0';
537
538    if (this.params.muted) {
539      src += '&muted=1';
540    }
541
542    if (this.params.autoplay) {
543      src += '&autoplay=1';
544    }
545
546    if (this.params.loop) {
547      src += '&loop=1&autopause=0';
548    }
549
550    //WARN❗️ this is a hash not a query param
551    if (this.params['start-at']) {
552      src += '#t=' + this.params['start-at'] + 's';
553    }
554
555    this.iframe.src = src;
556
557    if (this.uid) {
558      this.iframe.id = this.uid;
559    }
560
561    if (this.params['load-background'] || this.params['poster']) {
562      //if (this.params['load-background']) wrapper_styles['background-image'] = 'url(https://img.youtube.com/vi/'+this.ytid+'/maxresdefault.jpg)';
563      if (this.params['poster']) wrapper_styles['background-image'] = this.params['poster'];
564      wrapper_styles['background-size'] = 'cover';
565      wrapper_styles['background-repeat'] = 'no-repeat';
566      wrapper_styles['background-position'] = 'center';
567    }
568
569    if (this.params['inline-styles']) {
570      this.iframe.style.top = '50%';
571      this.iframe.style.left = '50%';
572      this.iframe.style.transform = 'translate(-50%, -50%)';
573      this.iframe.style.position = 'absolute';
574      this.iframe.style.opacity = 1;
575    }
576
577    this.element.appendChild(this.iframe);
578
579    if (this.params['fit-box']) {
580      this.iframe.style.width = '100%';
581      this.iframe.style.height = '100%';
582    } else {
583      const self = this;
584
585      const onResize = function() {
586        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
587        const w = self.iframe.parentNode.offsetWidth + self.params.offset;
588        const res = self.params.resolution_mod;
589
590        if (res > w/h) {
591          self.iframe.style.width = h*res + 'px';
592          self.iframe.style.height = h + 'px';
593        } else {
594          self.iframe.style.width = w + 'px';
595          self.iframe.style.height = w/res + 'px';
596        }
597      };
598
599      if (window.hasOwnProperty('ResizeObserver')) {
600        const resize_observer = new ResizeObserver(() => {
601          window.requestAnimationFrame(onResize);
602        });
603        resize_observer.observe(this.element);
604      } else {
605        window.addEventListener('resize', () => {
606          window.requestAnimationFrame(onResize);
607        });
608      }
609      onResize();
610    }
611  };
612
613  VimeoBackground.prototype.buildHTML = function () {
614    const parent = this.element.parentNode;
615    // wrap
616    addClass(this.element, 'youtube-background');
617
618    //set css rules
619    const wrapper_styles = {
620      "height" : "100%",
621      "width" : "100%",
622      "z-index": "0",
623      "position": "absolute",
624      "overflow": "hidden",
625      "top": 0, // added by @insad
626      "left": 0,
627      "bottom": 0,
628      "right": 0
629    };
630
631    if (this.params['load-background'] || this.params['poster']) {
632      //if (this.params['load-background']) wrapper_styles['background-image'] = 'url(https://img.youtube.com/vi/'+this.ytid+'/maxresdefault.jpg)';
633      if (this.params['poster']) wrapper_styles['background-image'] = this.params['poster'];
634      wrapper_styles['background-size'] = 'cover';
635      wrapper_styles['background-repeat'] = 'no-repeat';
636      wrapper_styles['background-position'] = 'center';
637    }
638
639    if (!this.params['mute-button']) {
640      wrapper_styles["pointer-events"] = "none"; // avoid right mouse click popup menu
641    }
642
643    if (this.params['load-background']) {
644      //TODO: wrapper_styles['background-image'] = 'url(https://img.youtube.com/vi/'+this.vid+'/maxresdefault.jpg)';
645      wrapper_styles['background-size'] = 'cover';
646      wrapper_styles['background-repeat'] = 'no-repeat';
647      wrapper_styles['background-position'] = 'center';
648    }
649
650    if (this.params['inline-styles']) {
651      for (let property in wrapper_styles) {
652        this.element.style[property] = wrapper_styles[property];
653      }
654
655      if (!['absolute', 'fixed', 'relative', 'sticky'].indexOf(parent.style.position)) {
656        parent.style.position = 'relative';
657      }
658    }
659
660    return this.element;
661  };
662
663  function VideoBackground(elem, params, vid_data, uid) {
664    this.is_mobile = isMobile();
665
666    this.element = elem;
667    this.link = vid_data.link;
668    this.ext = vid_data.id;
669    this.uid = uid;
670    this.player = null;
671    this.buttons = {};
672
673    this.state = {};
674    this.state.play = false;
675    this.state.mute = false;
676
677    this.params = {};
678
679    const MIME_MAP = {
680      'ogv' : 'video/ogg',
681      'ogm' : 'video/ogg',
682      'ogg' : 'video/ogg',
683      'avi' : 'video/avi',
684      'mp4' : 'video/mp4',
685      'webm' : 'video/webm'
686    };
687
688    const DEFAULTS = {
689      'pause': false, //deprecated
690      'play-button': false,
691      'mute-button': false,
692      'autoplay': true,
693      'muted': true,
694      'loop': true,
695      'mobile': false,
696      'resolution': '16:9',
697      'inline-styles': true,
698      'fit-box': false,
699      'offset': 200,
700      'start-at': 0,
701      'end-at': 0,
702      'poster': null
703    };
704
705    this.__init__ = function () {
706      if (!this.link || !this.ext) {
707        return;
708      }
709
710      this.mime = MIME_MAP[this.ext.toLowerCase()];
711      this.params = parseProperties(params, DEFAULTS, this.element, ['data-ytbg-', 'data-vbg-']);
712      //pause deprecated
713      if (this.params.pause) {
714        this.params['play-button'] = this.params.pause;
715      }
716      this.params.resolution_mod = parseResolutionString(this.params.resolution);
717      this.state.playing = this.params.autoplay;
718      this.state.muted = this.params.muted;
719
720      this.buildHTML();
721      this.injectPlayer();
722
723
724      if (this.params['play-button']) {
725        this.generateActionButton({
726          name: 'play',
727          className: 'play-toggle',
728          innerHtml: '<i class="fa"></i>',
729          initialState: false,
730          stateClassName: 'paused',
731          condition_parameter: 'autoplay',
732          stateChildClassNames: ['fa-pause-circle', 'fa-play-circle'],
733          actions: ['play', 'pause']
734        });
735      }
736
737      if (this.params['mute-button']) {
738        this.generateActionButton({
739          name: 'mute',
740          className: 'mute-toggle',
741          innerHtml: '<span class="icon icon-notext"></span>',
742          initialState: true,
743          stateClassName: 'muted',
744          condition_parameter: 'muted',
745          stateChildClassNames: ['icon-volume-high', 'icon-volume-mute2'],
746          actions: ['unmute', 'mute']
747        });
748      }
749    };
750
751    this.__init__();
752  }
753
754  VideoBackground.prototype.seekTo = function (seconds) {
755    if (this.player.hasOwnProperty('fastSeek')) {
756      this.player.fastSeek(seconds);
757      return;
758    }
759    this.player.currentTime = seconds;
760  };
761
762  VideoBackground.prototype.injectPlayer = function () {
763    this.player = document.createElement('video');
764    this.player.muted = this.params.muted;
765    this.player.autoplay = this.params.autoplay;
766    this.player.loop = this.params.loop;
767    this.player.playsinline = true;
768
769    this.player.setAttribute('id', this.uid);
770
771    if (this.params['inline-styles']) {
772      this.player.style.top = '50%';
773      this.player.style.left = '50%';
774      this.player.style.transform = 'translate(-50%, -50%)';
775      this.player.style.position = 'absolute';
776      this.player.style.opacity = 0;
777
778      this.player.addEventListener('canplay', (e) => {
779        e.target.style.opacity = 1;
780      });
781    }
782
783    const self = this;
784    /*
785    this.player.addEventListener('canplay', (e) => {
786      if (self.params['start-at'] && self.params.autoplay) {
787        self.seekTo(self.params['start-at']);
788      }
789    });
790
791    this.player.addEventListener('canplaythrough', (e) => {
792      if (self.params['end-at'] > 0) {
793      self.player.addEventListener('timeupdate', (e) => {
794        if (self.params['end-at'] >= self.player.currentTime) {
795          self.seekTo(self.params['start-at']);
796        }
797      });
798    }
799    });
800    */
801
802    const source = document.createElement('source');
803    source.setAttribute('src', this.link);
804    source.setAttribute('type', this.mime);
805    this.player.appendChild(source);
806    this.element.appendChild(this.player);
807
808    if (this.params['fit-box']) {
809      this.player.style.width = '100%';
810      this.player.style.height = '100%';
811    } else {
812      //TODO❗️: maybe a spacer or at least add requestAnimationFrame
813      function onResize() {
814        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
815        const w = self.player.parentNode.offsetWidth + self.params.offset;
816        const res = self.params.resolution_mod;
817
818        if (res > w/h) {
819          self.player.style.width = h*res + 'px';
820          self.player.style.height = h + 'px';
821        } else {
822          self.player.style.width = w + 'px';
823          self.player.style.height = w/res + 'px';
824        }
825      }
826
827      if (window.hasOwnProperty('ResizeObserver')) {
828        const resize_observer = new ResizeObserver(() => {
829          window.requestAnimationFrame(onResize);
830        });
831        resize_observer.observe(this.element);
832      } else {
833        window.addEventListener('resize', () => {
834          window.requestAnimationFrame(onResize);
835        });
836      }
837      onResize();
838    }
839  };
840
841  VideoBackground.prototype.buildHTML = function () {
842    const parent = this.element.parentNode;
843    // wrap
844    addClass(this.element, 'video-background');
845
846    //set css rules
847    const wrapper_styles = {
848      "height" : "100%",
849      "width" : "100%",
850      "z-index": "0",
851      "position": "absolute",
852      "overflow": "hidden",
853      "top": 0, // added by @insad
854      "left": 0,
855      "bottom": 0,
856      "right": 0
857    };
858
859    if (!this.params['mute-button']) {
860      wrapper_styles["pointer-events"] = "none"; // avoid right mouse click popup menu
861    }
862
863    if (this.params['load-background'] || this.params['poster']) {
864      if (this.params['poster']) wrapper_styles['background-image'] = `url('${this.params['poster']}')`;
865      wrapper_styles['background-size'] = 'cover';
866      wrapper_styles['background-repeat'] = 'no-repeat';
867      wrapper_styles['background-position'] = 'center';
868    }
869
870    if (this.params['inline-styles']) {
871      for (let property in wrapper_styles) {
872        this.element.style[property] = wrapper_styles[property];
873      }
874
875      if (!['absolute', 'fixed', 'relative', 'sticky'].indexOf(parent.style.position)) {
876        parent.style.position = 'relative';
877      }
878    }
879
880    if (this.is_mobile && !this.params.mobile) {
881      return this.element;
882    }
883
884    // set play/mute controls wrap
885    if (this.params['play-button'] || this.params['mute-button']) {
886      const controls = document.createElement('div');
887      controls.className = 'video-background-controls';
888
889      controls.style.position = 'absolute';
890      controls.style.top = '-10px';
891      controls.style.right = '10px';
892      controls.style['z-index'] = 2;
893
894      this.controls_element = controls;
895      parent.appendChild(controls);
896    }
897
898    return this.element;
899  };
900
901  VideoBackground.prototype.play = function () {
902    //TODO: solve this with ARIA toggle states. P.S. warning repetitive code!!!
903    if (this.buttons.hasOwnProperty('play')) {
904      const btn_obj = this.buttons.play;
905      removeClass(btn_obj.element, btn_obj.button_properties.stateClassName);
906      addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]);
907      removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]);
908    }
909
910    if (this.player) {
911      /* if (this.params['start-at'] && this.player.currentTime < this.params['start-at'] ) {
912        this.seekTo(this.params['start-at']);
913      } */
914      this.player.play();
915      this.element.dispatchEvent(new CustomEvent('video-background-play', { bubbles: true, detail: this }));
916    }
917  };
918
919  VideoBackground.prototype.pause = function () {
920    //TODO: solve this with ARIA toggle states
921    if (this.buttons.hasOwnProperty('play')) {
922      const btn_obj = this.buttons.play;
923      addClass(btn_obj.element, btn_obj.button_properties.stateClassName);
924      removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]);
925      addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]);
926    }
927
928    if (this.player) {
929      this.player.pause();
930      this.element.dispatchEvent(new CustomEvent('video-background-pause', { bubbles: true, detail: this }));
931    }
932  };
933
934  VideoBackground.prototype.unmute = function () {
935    //TODO: solve this with ARIA toggle states
936    if (this.buttons.hasOwnProperty('mute')) {
937      const btn_obj = this.buttons.mute;
938      removeClass(btn_obj.element, btn_obj.button_properties.stateClassName);
939      addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]);
940      removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]);
941    }
942
943    if (this.player) {
944      this.player.muted = false;
945      this.element.dispatchEvent(new CustomEvent('video-background-unmute', { bubbles: true, detail: this }));
946    }
947  };
948
949  VideoBackground.prototype.mute = function () {
950    //TODO: solve this with ARIA toggle states
951    if (this.buttons.hasOwnProperty('mute')) {
952      const btn_obj = this.buttons.mute;
953      addClass(btn_obj.element, btn_obj.button_properties.stateClassName);
954      removeClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[0]);
955      addClass(btn_obj.element.firstChild, btn_obj.button_properties.stateChildClassNames[1]);
956    }
957
958    if (this.player) {
959      this.player.muted = true;
960      this.element.dispatchEvent(new CustomEvent('video-background-mute', { bubbles: true, detail: this }));
961    }
962  };
963
964  //TODO: refactor states to be equal for all buttons
965  VideoBackground.prototype.generateActionButton = function (obj) {
966    const btn = document.createElement('button');
967    btn.className = obj.className;
968    btn.innerHTML = obj.innerHtml;
969    addClass(btn.firstChild, obj.stateChildClassNames[0]);
970
971    //TODO: solve this with ARIA toggle states
972    if (this.params[obj.condition_parameter] === obj.initialState) {
973      addClass(btn, obj.stateClassName);
974      removeClass(btn.firstChild, obj.stateChildClassNames[0]);
975      addClass(btn.firstChild, obj.stateChildClassNames[1]);
976    }
977
978    const self = this;
979    btn.addEventListener('click', function(e) {
980      if (hasClass(this, obj.stateClassName)) {
981        self.state[obj.name] = false;
982        self[obj.actions[0]]();
983      } else {
984        self.state[obj.name] = true;
985        self[obj.actions[1]]();
986      }
987    });
988
989    this.buttons[obj.name] = {
990      element: btn,
991      button_properties: obj
992    };
993
994    this.controls_element.appendChild(btn);
995  };
996
997  function VideoBackgrounds(selector, params) {
998    this.elements = selector;
999
1000    if (typeof selector === 'string') {
1001      this.elements = document.querySelectorAll(selector);
1002    }
1003
1004    this.index = {};
1005    this.re = {};
1006    this.re.YOUTUBE = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i;
1007    this.re.VIMEO = /(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^\/]*)\/videos\/|album\/(?:\d+)\/video\/|video\/|)(\d+)(?:[a-zA-Z0-9_\-]+)?/i;
1008    this.re.VIDEO = /\/[^\/]+\.(mp4|ogg|ogv|ogm|webm|avi)\s?$/i;
1009
1010    this.__init__ = function () {
1011      for (let i = 0; i < this.elements.length; i++) {
1012        const element = this.elements[i];
1013
1014        const link = element.getAttribute('data-youtube') || element.getAttribute('data-vbg');
1015        const vid_data = this.getVidID(link);
1016
1017        if (!vid_data) {
1018          continue;
1019        }
1020
1021        const uid = this.generateUID(vid_data.id);
1022
1023        if (!uid) {
1024          continue;
1025        }
1026
1027        switch (vid_data.type) {
1028          case 'YOUTUBE':
1029            const yb = new YoutubeBackground(element, params, vid_data.id, uid);
1030            this.index[uid] = yb;
1031            break;
1032          case 'VIMEO':
1033            const vm = new VimeoBackground(element, params, vid_data.id, uid);
1034            this.index[uid] = vm;
1035            break;
1036          case 'VIDEO':
1037            const vid = new VideoBackground(element, params, vid_data, uid);
1038            this.index[uid] = vid;
1039            break;
1040        }
1041      }
1042
1043      this.initYTPlayers(/*function() {
1044        //TODO: FIX!
1045        if (params &&
1046          (params.hasOwnProperty('activity_timeout')
1047            || params.hasOwnProperty('inactivity_timeout'))) {
1048          this.activity_monitor = new ActivityMonitor(function () {
1049              self.playVideos();
1050            }, function() {
1051              self.pauseVideos();
1052            },
1053            params ? params.activity_timeout : null,
1054            params ? params.inactivity_timeout : null,
1055            ['mousemove', 'scroll']
1056          );
1057        }
1058      }*/);
1059    };
1060
1061    this.__init__();
1062  }
1063
1064  VideoBackgrounds.prototype.getVidID = function (link) {
1065    if (link !== undefined && link !== null) {
1066      for (let k in this.re) {
1067        const pts = link.match(this.re[k]);
1068
1069        if (pts && pts.length) {
1070          this.re[k].lastIndex = 0;
1071          return {
1072            id: pts[1],
1073            type: k,
1074            regex_pts: pts,
1075            link: link
1076          };
1077        }
1078      }
1079    }
1080
1081    return null;
1082  };
1083
1084
1085  VideoBackgrounds.prototype.generateUID = function (pref) {
1086    //index the instance
1087    let uid = pref +'-'+ getRandomIntInclusive(0, 9999);
1088    while (this.index.hasOwnProperty(uid)) {
1089      uid = pref +'-'+ getRandomIntInclusive(0, 9999);
1090    }
1091
1092    return uid;
1093  };
1094
1095  VideoBackgrounds.prototype.pauseVideos = function () {
1096    for (let k in this.index) {
1097      this.index[k].pause();
1098    }
1099  };
1100
1101  VideoBackgrounds.prototype.playVideos = function () {
1102    for (let k in this.index) {
1103      this.index[k].play();
1104    }
1105  };
1106
1107  VideoBackgrounds.prototype.initYTPlayers = function (callback) {
1108    const self = this;
1109
1110    window.onYouTubeIframeAPIReady = function () {
1111      for (let k in self.index) {
1112        if (self.index[k] instanceof YoutubeBackground) {
1113          self.index[k].initYTPlayer();
1114        }
1115      }
1116
1117      if (callback) {
1118        setTimeout(callback, 100);
1119      }
1120    };
1121
1122    if (window.hasOwnProperty('YT') && window.YT.loaded) {
1123      window.onYouTubeIframeAPIReady();
1124    }
1125  };
1126
1127  if (typeof jQuery == 'function') {
1128    (function ($) {
1129      $.fn.youtube_background = function (params) {
1130        const $this = $(this);
1131        new VideoBackgrounds(this, params);
1132        return $this;
1133      };
1134    })(jQuery);
1135  }
1136
1137  window.VideoBackgrounds = VideoBackgrounds;
1138
1139})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.