PageSourceSearch

https://www.coloradoicsb.com/plugins/editor/cms/assets/js/libs/videojs/Youtube.js?v.1.257

js coloradoicsb.com collected 2026-10-04 13:27:10 UTC 17,857 bytes, 635 lines download raw bytes

1/* The MIT License (MIT)
2
3Copyright (c) 2014-2015 Benoit Tremblay <[email protected]>
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE. */
22/*global define, YT*/
23(function (root, factory) {
24  if(typeof define === 'function' && define.amd) {
25    define(['video.js'], function(videojs){
26      return (root.Youtube = factory(videojs));
27    });
28  } else if(typeof module === 'object' && module.exports) {
29    module.exports = (root.Youtube = factory(require('video.js')));
30  } else {
31    root.Youtube = factory(root.videojs);
32  }
33}(this, function(videojs) {
34  'use strict';
35
36  var Tech = videojs.getComponent('Tech');
37
38  var Youtube = videojs.extend(Tech, {
39
40    constructor: function(options, ready) {
41      Tech.call(this, options, ready);
42
43      this.setPoster(options.poster);
44      this.setSrc(this.options_.source, true);
45
46      // Set the vjs-youtube class to the player
47      // Parent is not set yet so we have to wait a tick
48      setTimeout(function() {
49        this.el_.parentNode.className += ' vjs-youtube';
50
51        if (_isOnMobile) {
52          this.el_.parentNode.className += ' vjs-youtube-mobile';
53        }
54
55        if (Youtube.isApiReady) {
56          this.initYTPlayer();
57        } else {
58          Youtube.apiReadyQueue.push(this);
59        }
60      }.bind(this));
61    },
62
63    dispose: function() {
64      this.el_.parentNode.className = this.el_.parentNode.className
65        .replace(' vjs-youtube', '')
66        .replace(' vjs-youtube-mobile', '');
67    },
68
69    createEl: function() {
70      var div = document.createElement('div');
71      div.setAttribute('id', this.options_.techId);
72      div.setAttribute('style', 'width:100%;height:100%;top:0;left:0;position:absolute');
73
74      var divWrapper = document.createElement('div');
75      divWrapper.appendChild(div);
76
77      if (!_isOnMobile && !this.options_.ytControls) {
78        var divBlocker = document.createElement('div');
79        divBlocker.setAttribute('class', 'vjs-iframe-blocker');
80        divBlocker.setAttribute('style', 'position:absolute;top:0;left:0;width:100%;height:100%');
81
82        // In case the blocker is still there and we want to pause
83        divBlocker.onclick = function() {
84          this.pause();
85        }.bind(this);
86
87        divWrapper.appendChild(divBlocker);
88      }
89
90      return divWrapper;
91    },
92
93    initYTPlayer: function() {
94      var playerVars = {
95        controls: 0,
96        modestbranding: 1,
97        rel: 0,
98        showinfo: 0,
99        loop: this.options_.loop ? 1 : 0
100      };
101
102      // Let the user set any YouTube parameter
103      // https://developers.google.com/youtube/player_parameters?playerVersion=HTML5#Parameters
104      // To use YouTube controls, you must use ytControls instead
105      // To use the loop or autoplay, use the video.js settings
106
107      if (typeof this.options_.autohide !== 'undefined') {
108        playerVars.autohide = this.options_.autohide;
109      }
110
111      if (typeof this.options_['cc_load_policy'] !== 'undefined') {
112        playerVars['cc_load_policy'] = this.options_['cc_load_policy'];
113      }
114
115      if (typeof this.options_.ytControls !== 'undefined') {
116        playerVars.controls = this.options_.ytControls;
117      }
118
119      if (typeof this.options_.disablekb !== 'undefined') {
120        playerVars.disablekb = this.options_.disablekb;
121      }
122
123      if (typeof this.options_.end !== 'undefined') {
124        playerVars.end = this.options_.end;
125      }
126
127      if (typeof this.options_.color !== 'undefined') {
128        playerVars.color = this.options_.color;
129      }
130
131      if (!playerVars.controls) {
132        // Let video.js handle the fullscreen unless it is the YouTube native controls
133        playerVars.fs = 0;
134      } else if (typeof this.options_.fs !== 'undefined') {
135        playerVars.fs = this.options_.fs;
136      }
137
138      if (typeof this.options_.end !== 'undefined') {
139        playerVars.end = this.options_.end;
140      }
141
142      if (typeof this.options_.hl !== 'undefined') {
143        playerVars.hl = this.options_.hl;
144      } else if (typeof this.options_.language !== 'undefined') {
145        // Set the YouTube player on the same language than video.js
146        playerVars.hl = this.options_.language.substr(0, 2);
147      }
148
149      if (typeof this.options_['iv_load_policy'] !== 'undefined') {
150        playerVars['iv_load_policy'] = this.options_['iv_load_policy'];
151      }
152
153      if (typeof this.options_.list !== 'undefined') {
154        playerVars.list = this.options_.list;
155      } else if (this.url && typeof this.url.listId !== 'undefined') {
156        playerVars.list = this.url.listId;
157      }
158
159      if (typeof this.options_.listType !== 'undefined') {
160        playerVars.listType = this.options_.listType;
161      }
162
163      if (typeof this.options_.modestbranding !== 'undefined') {
164        playerVars.modestbranding = this.options_.modestbranding;
165      }
166
167      if (typeof this.options_.playlist !== 'undefined') {
168        playerVars.playlist = this.options_.playlist;
169      }
170
171      if (typeof this.options_.playsinline !== 'undefined') {
172        playerVars.playsinline = this.options_.playsinline;
173      }
174
175      if (typeof this.options_.rel !== 'undefined') {
176        playerVars.rel = this.options_.rel;
177      }
178
179      if (typeof this.options_.showinfo !== 'undefined') {
180        playerVars.showinfo = this.options_.showinfo;
181      }
182
183      if (typeof this.options_.start !== 'undefined') {
184        playerVars.start = this.options_.start;
185      }
186
187      if (typeof this.options_.theme !== 'undefined') {
188        playerVars.theme = this.options_.theme;
189      }
190
191      this.activeVideoId = this.url ? this.url.videoId : null;
192      this.activeList = playerVars.list;
193
194      this.ytPlayer = new YT.Player(this.options_.techId, {
195        videoId: this.activeVideoId,
196        playerVars: playerVars,
197        events: {
198          onReady: this.onPlayerReady.bind(this),
199          onPlaybackQualityChange: this.onPlayerPlaybackQualityChange.bind(this),
200          onStateChange: this.onPlayerStateChange.bind(this),
201          onError: this.onPlayerError.bind(this)
202        }
203      });
204    },
205
206    onPlayerReady: function() {
207      this.playerReady_ = true;
208      this.triggerReady();
209
210      if (this.playOnReady) {
211        this.play();
212      }
213    },
214
215    onPlayerPlaybackQualityChange: function() {
216
217    },
218
219    onPlayerStateChange: function(e) {
220      var state = e.data;
221
222      if (state === this.lastState) {
223        return;
224      }
225
226      switch (state) {
227        case -1:
228          this.trigger('loadedmetadata');
229          this.trigger('durationchange');
230          break;
231
232        case YT.PlayerState.ENDED:
233          this.trigger('ended');
234          break;
235
236        case YT.PlayerState.PLAYING:
237          this.trigger('timeupdate');
238          this.trigger('durationchange');
239          this.trigger('playing');
240          this.trigger('play');
241
242          if (this.isSeeking) {
243            this.onSeeked();
244          }
245          break;
246
247        case YT.PlayerState.PAUSED:
248          this.trigger('canplay');
249          if (this.isSeeking) {
250            this.onSeeked();
251          } else {
252            this.trigger('pause');
253          }
254          break;
255
256        case YT.PlayerState.BUFFERING:
257          this.player_.trigger('timeupdate');
258          this.player_.trigger('waiting');
259          break;
260      }
261
262      this.lastState = state;
263    },
264
265    onPlayerError: function(e) {
266      this.errorNumber = e.data;
267      this.trigger('error');
268
269      this.ytPlayer.stopVideo();
270      this.ytPlayer.destroy();
271      this.ytPlayer = null;
272    },
273
274    error: function() {
275      switch (this.errorNumber) {
276        case 2:
277          return { code: 'Unable to find the video' };
278
279        case 5:
280          return { code: 'Error while trying to play the video' };
281
282        case 100:
283          return { code: 'Unable to find the video' };
284
285        case 101:
286        case 150:
287          return { code: 'Playback on other Websites has been disabled by the video owner.' };
288      }
289
290      return { code: 'YouTube unknown error (' + this.errorNumber + ')' };
291    },
292
293    src: function(src) {
294      if (src) {
295        this.setSrc({ src: src });
296        this.play();
297      }
298
299      return this.source;
300    },
301
302    poster: function() {
303      // You can't start programmaticlly a video with a mobile
304      // through the iframe so we hide the poster and the play button (with CSS)
305      if (_isOnMobile) {
306        return null;
307      }
308
309      return this.poster_;
310    },
311
312    setPoster: function(poster) {
313      this.poster_ = poster;
314    },
315
316    setSrc: function(source) {
317      if (!source || !source.src) {
318        return;
319      }
320
321      this.source = source;
322      this.url = Youtube.parseUrl(source.src);
323
324      if (!this.options_.poster) {
325        if (this.url.videoId) {
326          // Set the low resolution first
327          this.poster_ = 'https://img.youtube.com/vi/' + this.url.videoId + '/0.jpg';
328
329          // Check if their is a high res
330          this.checkHighResPoster();
331        }
332      }
333
334      if (this.options_.autoplay && !_isOnMobile) {
335        if (this.isReady_) {
336          this.play();
337        } else {
338          this.playOnReady = true;
339        }
340      }
341    },
342
343    play: function() {
344      if (!this.url || !this.url.videoId) {
345        return;
346      }
347
348      if (this.isReady_) {
349        if (this.url.listId) {
350          if (this.activeList === this.url.listId) {
351            this.ytPlayer.playVideo();
352          } else {
353            this.ytPlayer.loadPlaylist(this.url.listId);
354            this.activeList = this.url.listId;
355          }
356        }
357
358        if (this.activeVideoId === this.url.videoId) {
359          this.ytPlayer.playVideo();
360        } else {
361          this.ytPlayer.loadVideoById(this.url.videoId);
362          this.activeVideoId = this.url.videoId;
363        }
364      } else {
365        this.trigger('waiting');
366        this.playOnReady = true;
367      }
368    },
369
370    pause: function() {
371      if (this.ytPlayer) {
372        this.ytPlayer.pauseVideo();
373      }
374    },
375
376    paused: function() {
377      return (this.ytPlayer) ?
378        (this.lastState !== YT.PlayerState.PLAYING && this.lastState !== YT.PlayerState.BUFFERING)
379        : true;
380    },
381
382    currentTime: function() {
383      return this.ytPlayer ? this.ytPlayer.getCurrentTime() : 0;
384    },
385
386    setCurrentTime: function(seconds) {
387      if (this.lastState === YT.PlayerState.PAUSED) {
388        this.timeBeforeSeek = this.currentTime();
389      }
390
391      if (!this.isSeeking) {
392        this.wasPausedBeforeSeek = this.paused();
393      }
394
395      this.ytPlayer.seekTo(seconds, true);
396      this.trigger('timeupdate');
397      this.trigger('seeking');
398      this.isSeeking = true;
399
400      // A seek event during pause does not return an event to trigger a seeked event,
401      // so run an interval timer to look for the currentTime to change
402      if (this.lastState === YT.PlayerState.PAUSED && this.timeBeforeSeek !== seconds) {
403        clearInterval(this.checkSeekedInPauseInterval);
404        this.checkSeekedInPauseInterval = setInterval(function() {
405          if (this.lastState !== YT.PlayerState.PAUSED || !this.isSeeking) {
406            // If something changed while we were waiting for the currentTime to change,
407            //  clear the interval timer
408            clearInterval(this.checkSeekedInPauseInterval);
409          } else if (this.currentTime() !== this.timeBeforeSeek) {
410            this.trigger('timeupdate');
411            this.onSeeked();
412          }
413        }.bind(this), 250);
414      }
415    },
416
417    onSeeked: function() {
418      clearInterval(this.checkSeekedInPauseInterval);
419      this.trigger('seeked');
420      this.isSeeking = false;
421      if (this.wasPausedBeforeSeek) {
422        this.pause();
423      }
424    },
425
426    playbackRate: function() {
427      return this.ytPlayer ? this.ytPlayer.getPlaybackRate() : 1;
428    },
429
430    setPlaybackRate: function(suggestedRate) {
431      if (!this.ytPlayer) {
432        return;
433      }
434
435      this.ytPlayer.setPlaybackRate(suggestedRate);
436      this.trigger('ratechange');
437    },
438
439    duration: function() {
440      return this.ytPlayer ? this.ytPlayer.getDuration() : 0;
441    },
442
443    currentSrc: function() {
444      return this.source;
445    },
446
447    ended: function() {
448      return this.ytPlayer ? (this.lastState === YT.PlayerState.ENDED) : false;
449    },
450
451    volume: function() {
452      return this.ytPlayer ? this.ytPlayer.getVolume() / 100.0 : 1;
453    },
454
455    setVolume: function(percentAsDecimal) {
456      if (!this.ytPlayer) {
457        return;
458      }
459
460      this.ytPlayer.setVolume(percentAsDecimal * 100.0);
461      this.setTimeout( function(){
462        this.trigger('volumechange');
463      }, 50);
464
465    },
466
467    muted: function() {
468      return this.ytPlayer ? this.ytPlayer.isMuted() : false;
469    },
470
471    setMuted: function(mute) {
472      if (!this.ytPlayer) {
473        return;
474      }
475      else{
476        this.muted(true);
477      }
478
479      if (mute) {
480        this.ytPlayer.mute();
481      } else {
482        this.ytPlayer.unMute();
483      }
484      this.setTimeout( function(){
485        this.trigger('volumechange');
486      }, 50);
487    },
488
489    buffered: function() {
490      if(!this.ytPlayer || !this.ytPlayer.getVideoLoadedFraction) {
491        return {
492          length: 0,
493          start: function() {
494            throw new Error('This TimeRanges object is empty');
495          },
496          end: function() {
497            throw new Error('This TimeRanges object is empty');
498          }
499        };
500      }
501
502      var end = this.ytPlayer.getVideoLoadedFraction() * this.ytPlayer.getDuration();
503
504      return {
505        length: 1,
506        start: function() { return 0; },
507        end: function() { return end; }
508      };
509    },
510
511
512
513    supportsFullScreen: function() {
514      return true;
515    },
516
517    // Tries to get the highest resolution thumbnail available for the video
518    checkHighResPoster: function(){
519      var uri = 'https://img.youtube.com/vi/' + this.url.videoId + '/maxresdefault.jpg';
520
521      try {
522        var image = new Image();
523        image.onload = function(){
524          // Onload may still be called if YouTube returns the 120x90 error thumbnail
525          if('naturalHeight' in image){
526            if(image.naturalHeight <= 90 || image.naturalWidth <= 120) {
527
528              if(typeof this.onerror == "function"){
529                this.onerror();
530              }
531
532              return;
533            }
534          } else if(image.height <= 90 || image.width <= 120) {
535            this.onerror();
536            return;
537          }
538
539          this.poster_ = uri;
540          this.trigger('posterchange');
541        }.bind(this);
542        image.onerror = function(){};
543        image.src = uri;
544      }
545      catch(e){}
546    }
547  });
548
549  Youtube.isSupported = function() {
550    return true;
551  };
552
553  Youtube.canPlaySource = function(e) {
554    return (e.type === 'video/youtube');
555  };
556
557  var _isOnMobile = /(iPad|iPhone|iPod|Android)/g.test(navigator.userAgent);
558
559  Youtube.parseUrl = function(url) {
560    var result = {
561      videoId: null
562    };
563
564    var regex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
565    var match = url.match(regex);
566
567    if (match && match[2].length === 11) {
568      result.videoId = match[2];
569    }
570
571    var regPlaylist = /[?&]list=([^#\&\?]+)/;
572    match = url.match(regPlaylist);
573
574    if(match && match[1]) {
575      result.listId = match[1];
576    }
577
578    return result;
579  };
580
581  function loadApi() {
582    var tag = document.createElement('script');
583    tag.src = 'https://www.youtube.com/iframe_api';
584    var firstScriptTag = document.getElementsByTagName('script')[0];
585    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
586  }
587
588  function injectCss() {
589    var css = // iframe blocker to catch mouse events
590              '.vjs-youtube .vjs-iframe-blocker { display: none; }' +
591              '.vjs-youtube.vjs-user-inactive .vjs-iframe-blocker { display: block; }' +
592              '.vjs-youtube .vjs-poster { background-size: cover; }' +
593              '.vjs-youtube-mobile .vjs-big-play-button { display: none; }';
594
595    var head = document.head || document.getElementsByTagName('head')[0];
596
597    var style = document.createElement('style');
598    style.type = 'text/css';
599
600    if (style.styleSheet){
601      style.styleSheet.cssText = css;
602    } else {
603      style.appendChild(document.createTextNode(css));
604    }
605
606    head.appendChild(style);
607  }
608
609  Youtube.apiReadyQueue = [];
610
611  window.onYouTubeIframeAPIReady = function() {
612    Youtube.isApiReady = true;
613
614    for (var i = 0; i < Youtube.apiReadyQueue.length; ++i) {
615      Youtube.apiReadyQueue[i].initYTPlayer();
616    }
617
618    if(typeof onYouTubeIframeAPIReadyFullscreenBackground == "function"){
619      onYouTubeIframeAPIReadyFullscreenBackground();
620    }
621  };
622
623  window.onYouTubeIframeAPIReadyYoutube = function() {
624    Youtube.isApiReady = true;
625
626    for (var i = 0; i < Youtube.apiReadyQueue.length; ++i) {
627      Youtube.apiReadyQueue[i].initYTPlayer();
628    }
629  };
630
631  loadApi();
632  injectCss();
633
634  videojs.registerTech('Youtube', Youtube);
635}));

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.