PageSourceSearch

https://www.signingsavvy.com/node_modules/videojs-contrib-ads/dist/videojs.ads.js

js signingsavvy.com collected 2026-10-02 04:04:07 UTC 45,846 bytes, 1,232 lines download raw bytes

1/**
2 * videojs-contrib-ads
3 * @version 4.1.6
4 * @copyright 2016 Brightcove
5 * @license Apache-2.0
6 */
7(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.videojsContribAds = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
8(function (global){
9'use strict';
10
11var _video = (typeof window !== "undefined" ? window['videojs'] : typeof global !== "undefined" ? global['videojs'] : null);
12
13var _video2 = _interopRequireDefault(_video);
14
15function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
17var cancelContentPlay = function cancelContentPlay(player) {
18  if (player.ads.cancelPlayTimeout) {
19    // another cancellation is already in flight, so do nothing
20    return;
21  }
22
23  // Avoid content flash on non-iPad iOS and iPhones on iOS10 with playsinline
24  if (_video2.default.browser.IS_IOS && _video2.default.browser.IS_IPHONE && !player.el_.hasAttribute('playsinline')) {
25    (function () {
26
27      var width = player.currentWidth ? player.currentWidth() : player.width();
28      var height = player.currentHeight ? player.currentHeight() : player.height();
29
30      // A placeholder black box will be shown in the document while the player is hidden.
31      var placeholder = document.createElement('div');
32
33      placeholder.style.width = width + 'px';
34      placeholder.style.height = height + 'px';
35      placeholder.style.background = 'black';
36      player.el_.parentNode.insertBefore(placeholder, player.el_);
37
38      // Hide the player. While in full-screen video playback mode on iOS, this
39      // makes the player show a black screen instead of content flash.
40      player.el_.style.display = 'none';
41
42      // Unhide the player and remove the placeholder once we're ready to move on.
43      player.one(['adstart', 'adplaying', 'adtimeout', 'adserror', 'adscanceled', 'adskip', 'playing'], function () {
44        player.el_.style.display = 'block';
45        placeholder.remove();
46      });
47
48      // Detect fullscreen change, if returning from fullscreen and placeholder exists,
49      // remove placeholder and show player whether or not playsinline was attached.
50      player.on('fullscreenchange', function () {
51        if (placeholder && player.hasClass('vjs-fullscreen')) {
52          player.el_.style.display = 'block';
53          placeholder.remove();
54        }
55      });
56    })();
57  }
58
59  // The timeout is necessary because pausing a video element while processing a `play`
60  // event on iOS can cause the video element to continuously toggle between playing and
61  // paused states.
62  player.ads.cancelPlayTimeout = window.setTimeout(function () {
63    // deregister the cancel timeout so subsequent cancels are scheduled
64    player.ads.cancelPlayTimeout = null;
65
66    // pause playback so ads can be handled.
67    if (!player.paused()) {
68      player.pause();
69    }
70
71    // When the 'content-playback' state is entered, this will let us know to play
72    player.ads.cancelledPlay = true;
73  }, 1);
74}; /*
75   This feature makes sure the player is paused during ad loading.
76   
77   It does this by pausing the player immediately after a "play" where ads will be requested,
78   then signalling that we should play after the ad is done.
79   */
80
81module.exports = cancelContentPlay;
82}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
83},{}],2:[function(require,module,exports){
84'use strict';
85
86/*
87This feature sends a `contentupdate` event when the player source changes.
88*/
89
90// Start sending contentupdate events
91var initializeContentupdate = function initializeContentupdate(player) {
92
93  // Keep track of the current content source
94  // If you want to change the src of the video without triggering
95  // the ad workflow to restart, you can update this variable before
96  // modifying the player's source
97  player.ads.contentSrc = player.currentSrc();
98
99  // Check if a new src has been set, if so, trigger contentupdate
100  var checkSrc = function checkSrc() {
101    if (player.ads.state !== 'ad-playback') {
102      var src = player.currentSrc();
103
104      if (src !== player.ads.contentSrc) {
105        player.trigger({
106          type: 'contentupdate',
107          oldValue: player.ads.contentSrc,
108          newValue: src
109        });
110        player.ads.contentSrc = src;
111      }
112    }
113  };
114
115  // loadstart reliably indicates a new src has been set
116  player.on('loadstart', checkSrc);
117  // check immediately in case we missed the loadstart
118  window.setTimeout(checkSrc, 1);
119};
120
121module.exports = initializeContentupdate;
122},{}],3:[function(require,module,exports){
123(function (global){
124'use strict';
125
126var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /*
127                                                                                                                                                                                                                                                                              This feature provides an optional method for ad integrations to insert run-time values
128                                                                                                                                                                                                                                                                              into an ad server URL or configuration.
129                                                                                                                                                                                                                                                                              */
130
131var _video = (typeof window !== "undefined" ? window['videojs'] : typeof global !== "undefined" ? global['videojs'] : null);
132
133var _video2 = _interopRequireDefault(_video);
134
135function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
136
137// Return URI encoded version of value if uriEncode is true
138var uriEncodeIfNeeded = function uriEncodeIfNeeded(value, uriEncode) {
139  if (uriEncode) {
140    return encodeURIComponent(value);
141  }
142  return value;
143};
144
145// Add custom field macros to macros object
146// based on given name for custom fields property of mediainfo object.
147var customFields = function customFields(mediainfo, macros, customFieldsName) {
148  if (mediainfo && mediainfo[customFieldsName]) {
149    var _customFields = mediainfo[customFieldsName];
150    var fieldNames = Object.keys(_customFields);
151
152    for (var i = 0; i < fieldNames.length; i++) {
153      var tag = '{mediainfo.' + customFieldsName + '.' + fieldNames[i] + '}';
154
155      macros[tag] = _customFields[fieldNames[i]];
156    }
157  }
158};
159
160// Public method that integrations use for ad macros.
161// "string" is any string with macros to be replaced
162// "uriEncode" if true will uri encode macro values when replaced
163// "customMacros" is a object with custom macros and values to map them to
164//  - For example: {'{five}': 5}
165// Return value is is "string" with macros replaced
166//  - For example: adMacroReplacement('{player.id}') returns a string of the player id
167var adMacroReplacement = function adMacroReplacement(string, uriEncode, customMacros) {
168
169  if (uriEncode === undefined) {
170    uriEncode = false;
171  }
172
173  var macros = {};
174
175  if (customMacros !== undefined) {
176    macros = customMacros;
177  }
178
179  // Static macros
180  macros['{player.id}'] = this.options_['data-player'];
181  macros['{mediainfo.id}'] = this.mediainfo ? this.mediainfo.id : '';
182  macros['{mediainfo.name}'] = this.mediainfo ? this.mediainfo.name : '';
183  macros['{mediainfo.description}'] = this.mediainfo ? this.mediainfo.description : '';
184  macros['{mediainfo.tags}'] = this.mediainfo ? this.mediainfo.tags : '';
185  macros['{mediainfo.reference_id}'] = this.mediainfo ? this.mediainfo.reference_id : '';
186  macros['{mediainfo.duration}'] = this.mediainfo ? this.mediainfo.duration : '';
187  macros['{mediainfo.ad_keys}'] = this.mediainfo ? this.mediainfo.ad_keys : '';
188  macros['{player.duration}'] = this.duration();
189  macros['{timestamp}'] = new Date().getTime();
190  macros['{document.referrer}'] = document.referrer;
191  macros['{window.location.href}'] = window.location.href;
192  macros['{random}'] = Math.floor(Math.random() * 1000000000000);
193
194  // Custom fields in mediainfo
195  customFields(this.mediainfo, macros, 'custom_fields');
196  customFields(this.mediainfo, macros, 'customFields');
197
198  // Go through all the replacement macros and apply them to the string.
199  // This will replace all occurrences of the replacement macros.
200  for (var i in macros) {
201    string = string.split(i).join(uriEncodeIfNeeded(macros[i], uriEncode));
202  }
203
204  // Page variables
205  string = string.replace(/{pageVariable\.([^}]+)}/g, function (match, name) {
206    var value = void 0;
207    var context = window;
208    var names = name.split('.');
209
210    // Iterate down multiple levels of selector without using eval
211    // This makes things like pageVariable.foo.bar work
212    for (var _i = 0; _i < names.length; _i++) {
213      if (_i === names.length - 1) {
214        value = context[names[_i]];
215      } else {
216        context = context[names[_i]];
217      }
218    }
219
220    var type = typeof value === 'undefined' ? 'undefined' : _typeof(value);
221
222    // Only allow certain types of values. Anything else is probably a mistake.
223    if (value === null) {
224      return 'null';
225    } else if (value === undefined) {
226      _video2.default.log.warn('Page variable "' + name + '" not found');
227      return '';
228    } else if (type !== 'string' && type !== 'number' && type !== 'boolean') {
229      _video2.default.log.warn('Page variable "' + name + '" is not a supported type');
230      return '';
231    }
232
233    return uriEncodeIfNeeded(String(value), uriEncode);
234  });
235
236  return string;
237};
238
239module.exports = adMacroReplacement;
240}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
241},{}],4:[function(require,module,exports){
242(function (global){
243'use strict';
244
245var _video = (typeof window !== "undefined" ? window['videojs'] : typeof global !== "undefined" ? global['videojs'] : null);
246
247var _video2 = _interopRequireDefault(_video);
248
249function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
250
251// Stop propogation for an event
252var cancelEvent = function cancelEvent(player, event) {
253  // Pretend we called stopImmediatePropagation because we want the native
254  // element events to continue propagating
255  event.isImmediatePropagationStopped = function () {
256    return true;
257  };
258  event.cancelBubble = true;
259  event.isPropagationStopped = function () {
260    return true;
261  };
262};
263
264// Stop propogation for an event, then send a new event with the type of the original
265// event with the given prefix added.
266/*
267The goal of this feature is to make player events work as an integrator would
268expect despite the presense of ads. For example, an integrator would expect
269an `ended` event to happen once the content is ended. If an `ended` event is sent
270as a result of an ad ending, that is a bug. The `redispatch` method should recognize
271such `ended` events and prefix them so they are sent as `adended`, and so on with
272all other player events.
273*/
274
275var prefixEvent = function prefixEvent(player, prefix, event) {
276  cancelEvent(player, event);
277  player.trigger({
278    type: prefix + event.type,
279    state: player.ads.state,
280    originalEvent: event
281  });
282};
283
284// Handle a player event, either by redispatching it with a prefix, or by
285// letting it go on its way without any meddling.
286var redispatch = function redispatch(event) {
287
288  // We do a quick play/pause before we check for prerolls. This creates a "playing"
289  // event. This conditional block prefixes that event so it's "adplaying" if it
290  // happens while we're in the "preroll?" state. Not every browser is in the
291  // "preroll?" state for this event, so the following browsers come through here:
292  //  * iPad
293  //  * iPhone
294  //  * Android
295  //  * Safari
296  // This is too soon to check videoElementRecycled because there is no snapshot
297  // yet. We rely on the coincidence that all browsers for which
298  // videoElementRecycled would be true also happen to send their initial playing
299  // event during "preroll?"
300  if (event.type === 'playing' && this.ads.state === 'preroll?') {
301    prefixEvent(this, 'ad', event);
302
303    // Here we send "adplaying" for browsers that send their initial "playing" event
304    // (caused by the the initial play/pause) during the "ad-playback" state.
305    // The following browsers come through here:
306    // * Chrome
307    // * IE11
308    // If the ad plays in the content tech (aka videoElementRecycled) there will be
309    // another playing event when the ad starts. We check videoElementRecycled to
310    // avoid a second adplaying event. Thankfully, at this point a snapshot exists
311    // so we can safely check videoElementRecycled.
312  } else if (event.type === 'playing' && this.ads.state === 'ad-playback' && !this.ads.videoElementRecycled()) {
313    prefixEvent(this, 'ad', event);
314
315    // If the ad takes a long time to load, "playing" caused by play/pause can happen
316    // during "ads-ready?" instead of "preroll?" or "ad-playback", skipping the
317    // other conditions that would normally catch it
318  } else if (event.type === 'playing' && this.ads.state === 'ads-ready?') {
319    prefixEvent(this, 'ad', event);
320
321    // When an ad is playing in content tech, we would normally prefix
322    // "playing" with "ad" to send "adplaying". However, when we did a play/pause
323    // before the preroll, we already sent "adplaying". This condition prevents us
324    // from sending another.
325  } else if (event.type === 'playing' && this.ads.state === 'ad-playback' && this.ads.videoElementRecycled()) {
326    cancelEvent(this, event);
327    return;
328
329    // When ad is playing in content tech, prefix everything with "ad".
330    // This block catches many events such as emptied, play, timeupdate, and ended.
331  } else if (this.ads.state === 'ad-playback') {
332    if (this.ads.videoElementRecycled() || this.ads.stitchedAds()) {
333      prefixEvent(this, 'ad', event);
334    }
335
336    // Send contentended if ended happens during content.
337    // We will make sure an ended event is sent after postrolls.
338  } else if (this.ads.state === 'content-playback' && event.type === 'ended') {
339    prefixEvent(this, 'content', event);
340
341    // Event prefixing during content resuming is complicated
342  } else if (this.ads.state === 'content-resuming') {
343
344    // This does not happen during normal circumstances. I wasn't able to reproduce
345    // it, but the working theory is that it handles cases where restoring the
346    // snapshot takes a long time, such as in iOS7 and older Firefox.
347    if (this.ads.snapshot && this.currentSrc() !== this.ads.snapshot.currentSrc) {
348
349      // Don't prefix `loadstart` event
350      if (event.type === 'loadstart') {
351        return;
352      }
353
354      // All other events get "content" prefix
355      return prefixEvent(this, 'content', event);
356
357      // Content resuming after postroll
358    } else if (this.ads.snapshot && this.ads.snapshot.ended) {
359
360      // Don't prefix `pause` and `ended` events
361      // They don't always happen during content-resuming, but they might.
362      // It seems to happen most often on iOS and Android.
363      if (event.type === 'pause' || event.type === 'ended') {
364        return;
365      }
366
367      // All other events get "content" prefix
368      return prefixEvent(this, 'content', event);
369    }
370
371    // Content resuming after preroll or midroll
372    // Events besides "playing" get "content" prefix
373    if (event.type !== 'playing') {
374      prefixEvent(this, 'content', event);
375    }
376  }
377};
378
379module.exports = redispatch;
380}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
381},{}],5:[function(require,module,exports){
382(function (global){
383'use strict';
384
385var _video = (typeof window !== "undefined" ? window['videojs'] : typeof global !== "undefined" ? global['videojs'] : null);
386
387var _video2 = _interopRequireDefault(_video);
388
389function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
390
391var snapshot = {};
392
393/**
394 * Returns an object that captures the portions of player state relevant to
395 * video playback. The result of this function can be passed to
396 * restorePlayerSnapshot with a player to return the player to the state it
397 * was in when this function was invoked.
398 * @param {object} player The videojs player object
399 */
400/*
401The snapshot feature is responsible for saving the player state before an ad, then
402restoring the player state after an ad.
403*/
404
405snapshot.getPlayerSnapshot = function (player) {
406
407  var currentTime = void 0;
408
409  if (_video2.default.browser.IS_IOS && player.ads.isLive(player)) {
410    // Record how far behind live we are
411    if (player.seekable().length > 0) {
412      currentTime = player.currentTime() - player.seekable().end(0);
413    } else {
414      currentTime = player.currentTime();
415    }
416  } else {
417    currentTime = player.currentTime();
418  }
419
420  var tech = player.$('.vjs-tech');
421  var tracks = player.remoteTextTracks ? player.remoteTextTracks() : [];
422  var suppressedTracks = [];
423  var snapshot = {
424    ended: player.ended(),
425    currentSrc: player.currentSrc(),
426    src: player.src(),
427    currentTime: currentTime,
428    type: player.currentType()
429  };
430
431  if (tech) {
432    snapshot.nativePoster = tech.poster;
433    snapshot.style = tech.getAttribute('style');
434  }
435
436  for (var i = 0; i < tracks.length; i++) {
437    var track = tracks[i];
438
439    suppressedTracks.push({
440      track: track,
441      mode: track.mode
442    });
443    track.mode = 'disabled';
444  }
445  snapshot.suppressedTracks = suppressedTracks;
446
447  return snapshot;
448};
449
450/**
451 * Attempts to modify the specified player so that its state is equivalent to
452 * the state of the snapshot.
453 * @param {object} snapshot - the player state to apply
454 */
455snapshot.restorePlayerSnapshot = function (player, snapshot) {
456
457  if (player.ads.disableNextSnapshotRestore === true) {
458    player.ads.disableNextSnapshotRestore = false;
459    return;
460  }
461
462  // The playback tech
463  var tech = player.$('.vjs-tech');
464
465  // the number of[ remaining attempts to restore the snapshot
466  var attempts = 20;
467
468  var suppressedTracks = snapshot.suppressedTracks;
469  var trackSnapshot = void 0;
470  var restoreTracks = function restoreTracks() {
471    for (var i = 0; i < suppressedTracks.length; i++) {
472      trackSnapshot = suppressedTracks[i];
473      trackSnapshot.track.mode = trackSnapshot.mode;
474    }
475  };
476
477  // finish restoring the playback state
478  var resume = function resume() {
479    var currentTime = void 0;
480
481    if (_video2.default.browser.IS_IOS && player.ads.isLive(player)) {
482      if (snapshot.currentTime < 0) {
483        // Playback was behind real time, so seek backwards to match
484        if (player.seekable().length > 0) {
485          currentTime = player.seekable().end(0) + snapshot.currentTime;
486        } else {
487          currentTime = player.currentTime();
488        }
489        player.currentTime(currentTime);
490      }
491    } else {
492      player.currentTime(snapshot.ended ? player.duration() : snapshot.currentTime);
493    }
494
495    // Resume playback if this wasn't a postroll
496    if (!snapshot.ended) {
497      player.play();
498    }
499  };
500
501  // determine if the video element has loaded enough of the snapshot source
502  // to be ready to apply the rest of the state
503  var tryToResume = function tryToResume() {
504
505    // tryToResume can either have been called through the `contentcanplay`
506    // event or fired through setTimeout.
507    // When tryToResume is called, we should make sure to clear out the other
508    // way it could've been called by removing the listener and clearing out
509    // the timeout.
510    player.off('contentcanplay', tryToResume);
511    if (player.ads.tryToResumeTimeout_) {
512      player.clearTimeout(player.ads.tryToResumeTimeout_);
513      player.ads.tryToResumeTimeout_ = null;
514    }
515
516    // Tech may have changed depending on the differences in sources of the
517    // original video and that of the ad
518    tech = player.el().querySelector('.vjs-tech');
519
520    if (tech.readyState > 1) {
521      // some browsers and media aren't "seekable".
522      // readyState greater than 1 allows for seeking without exceptions
523      return resume();
524    }
525
526    if (tech.seekable === undefined) {
527      // if the tech doesn't expose the seekable time ranges, try to
528      // resume playback immediately
529      return resume();
530    }
531
532    if (tech.seekable.length > 0) {
533      // if some period of the video is seekable, resume playback
534      return resume();
535    }
536
537    // delay a bit and then check again unless we're out of attempts
538    if (attempts--) {
539      window.setTimeout(tryToResume, 50);
540    } else {
541      try {
542        resume();
543      } catch (e) {
544        _video2.default.log.warn('Failed to resume the content after an advertisement', e);
545      }
546    }
547  };
548
549  if (snapshot.nativePoster) {
550    tech.poster = snapshot.nativePoster;
551  }
552
553  if ('style' in snapshot) {
554    // overwrite all css style properties to restore state precisely
555    tech.setAttribute('style', snapshot.style || '');
556  }
557
558  // Determine whether the player needs to be restored to its state
559  // before ad playback began. With a custom ad display or burned-in
560  // ads, the content player state hasn't been modified and so no
561  // restoration is required
562
563  if (player.ads.videoElementRecycled()) {
564    // on ios7, fiddling with textTracks too early will cause safari to crash
565    player.one('contentloadedmetadata', restoreTracks);
566
567    // if the src changed for ad playback, reset it
568    player.src({ src: snapshot.currentSrc, type: snapshot.type });
569    // safari requires a call to `load` to pick up a changed source
570    player.load();
571    // and then resume from the snapshots time once the original src has loaded
572    // in some browsers (firefox) `canplay` may not fire correctly.
573    // Reace the `canplay` event with a timeout.
574    player.one('contentcanplay', tryToResume);
575    player.ads.tryToResumeTimeout_ = player.setTimeout(tryToResume, 2000);
576  } else if (!player.ended() || !snapshot.ended) {
577    // if we didn't change the src, just restore the tracks
578    restoreTracks();
579    // the src didn't change and this wasn't a postroll
580    // just resume playback at the current time.
581    player.play();
582  }
583};
584
585module.exports = snapshot;
586}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
587},{}],6:[function(require,module,exports){
588(function (global){
589'use strict';
590
591var _video = (typeof window !== "undefined" ? window['videojs'] : typeof global !== "undefined" ? global['videojs'] : null);
592
593var _video2 = _interopRequireDefault(_video);
594
595var _redispatch = require('./redispatch.js');
596
597var _redispatch2 = _interopRequireDefault(_redispatch);
598
599var _snapshot = require('./snapshot.js');
600
601var _snapshot2 = _interopRequireDefault(_snapshot);
602
603var _contentupdate = require('./contentupdate.js');
604
605var _contentupdate2 = _interopRequireDefault(_contentupdate);
606
607var _cancelContentPlay = require('./cancelContentPlay.js');
608
609var _cancelContentPlay2 = _interopRequireDefault(_cancelContentPlay);
610
611var _macros = require('./macros.js');
612
613var _macros2 = _interopRequireDefault(_macros);
614
615function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
616
617/*
618This main plugin file is responsible for integration logic and enabling the features
619that live in in separate files.
620*/
621
622var VIDEO_EVENTS = _video2.default.getComponent('Html5').Events;
623
624/**
625 * Remove the poster attribute from the video element tech, if present. When
626 * reusing a video element for multiple videos, the poster image will briefly
627 * reappear while the new source loads. Removing the attribute ahead of time
628 * prevents the poster from showing up between videos.
629 * @param {object} player The videojs player object
630 */
631var removeNativePoster = function removeNativePoster(player) {
632  var tech = player.$('.vjs-tech');
633
634  if (tech) {
635    tech.removeAttribute('poster');
636  }
637};
638
639// ---------------------------------------------------------------------------
640// Ad Framework
641// ---------------------------------------------------------------------------
642
643// default framework settings
644var defaults = {
645  // maximum amount of time in ms to wait to receive `adsready` from the ad
646  // implementation after play has been requested. Ad implementations are
647  // expected to load any dynamic libraries and make any requests to determine
648  // ad policies for a video during this time.
649  timeout: 5000,
650
651  // maximum amount of time in ms to wait for the ad implementation to start
652  // linear ad mode after `readyforpreroll` has fired. This is in addition to
653  // the standard timeout.
654  prerollTimeout: 100,
655
656  // maximum amount of time in ms to wait for the ad implementation to start
657  // linear ad mode after `contentended` has fired.
658  postrollTimeout: 100,
659
660  // when truthy, instructs the plugin to output additional information about
661  // plugin state to the video.js log. On most devices, the video.js log is
662  // the same as the developer console.
663  debug: false,
664
665  // set this to true when using ads that are part of the content video
666  stitchedAds: false
667};
668
669var contribAdsPlugin = function contribAdsPlugin(options) {
670
671  var player = this; // eslint-disable-line consistent-this
672
673  var settings = _video2.default.mergeOptions(defaults, options);
674
675  // prefix all video element events during ad playback
676  // if the video element emits ad-related events directly,
677  // plugins that aren't ad-aware will break. prefixing allows
678  // plugins that wish to handle ad events to do so while
679  // avoiding the complexity for common usage
680  var videoEvents = VIDEO_EVENTS.concat(['firstplay', 'loadedalldata', 'playing']);
681
682  // Set up redispatching of player events
683  player.on(videoEvents, _redispatch2.default);
684
685  // "vjs-has-started" should be present at the end of a video. This makes sure it's
686  // always there.
687  player.on('ended', function () {
688    if (!player.hasClass('vjs-has-started')) {
689      player.addClass('vjs-has-started');
690    }
691  });
692
693  // We now auto-play when an ad gets loaded if we're playing ads in the same video
694  // element as the content.
695  // The problem is that in IE11, we cannot play in addurationchange but in iOS8, we
696  // cannot play from adcanplay.
697  // This will prevent ad-integrations from needing to do this themselves.
698  player.on(['addurationchange', 'adcanplay'], function () {
699    if (player.currentSrc() === player.ads.snapshot.currentSrc) {
700      return;
701    }
702
703    player.play();
704  });
705
706  player.on('nopreroll', function () {
707    player.ads.nopreroll_ = true;
708  });
709
710  player.on('nopostroll', function () {
711    player.ads.nopostroll_ = true;
712  });
713
714  // Remove ad-loading class when ad plays or when content plays (in case there was no ad)
715  // If you remove this class too soon you can get a flash of content!
716  player.on(['ads-ad-started', 'playing'], function () {
717    player.removeClass('vjs-ad-loading');
718  });
719
720  // Replace the plugin constructor with the ad namespace
721  player.ads = {
722    state: 'content-set',
723    disableNextSnapshotRestore: false,
724
725    // This is set to true if the content has ended once. After that, the user can
726    // seek backwards and replay content, but _contentHasEnded remains true.
727    _contentHasEnded: false,
728
729    VERSION: '4.1.6',
730
731    reset: function reset() {
732      player.ads.disableNextSnapshotRestore = false;
733      player.ads._contentHasEnded = false;
734      player.ads.snapshot = null;
735    },
736
737
738    // Call this when an ad response has been received and there are
739    // linear ads ready to be played.
740    startLinearAdMode: function startLinearAdMode() {
741      if (player.ads.state === 'preroll?' || player.ads.state === 'content-playback' || player.ads.state === 'postroll?') {
742        player.trigger('adstart');
743      }
744    },
745
746
747    // Call this when a linear ad pod has finished playing.
748    endLinearAdMode: function endLinearAdMode() {
749      if (player.ads.state === 'ad-playback') {
750        player.trigger('adend');
751        // In the case of an empty ad response, we want to make sure that
752        // the vjs-ad-loading class is always removed. We could probably check for
753        // duration on adPlayer for an empty ad but we remove it here just to make sure
754        player.removeClass('vjs-ad-loading');
755      }
756    },
757
758
759    // Call this when an ad response has been received but there are no
760    // linear ads to be played (i.e. no ads available, or overlays).
761    // This has no effect if we are already in a linear ad mode.  Always
762    // use endLinearAdMode() to exit from linear ad-playback state.
763    skipLinearAdMode: function skipLinearAdMode() {
764      if (player.ads.state !== 'ad-playback') {
765        player.trigger('adskip');
766      }
767    },
768    stitchedAds: function stitchedAds(arg) {
769      if (arg !== undefined) {
770        this._stitchedAds = !!arg;
771      }
772      return this._stitchedAds;
773    },
774
775
776    // Returns whether the video element has been modified since the
777    // snapshot was taken.
778    // We test both src and currentSrc because changing the src attribute to a URL that
779    // AdBlocker is intercepting doesn't update currentSrc.
780    videoElementRecycled: function videoElementRecycled() {
781      var srcChanged = void 0;
782      var currentSrcChanged = void 0;
783
784      if (!this.snapshot) {
785        throw new Error('You cannot use videoElementRecycled while there is no snapshot.');
786      }
787
788      srcChanged = player.src() !== this.snapshot.src;
789      currentSrcChanged = player.currentSrc() !== this.snapshot.currentSrc;
790
791      return srcChanged || currentSrcChanged;
792    },
793
794
795    // Returns a boolean indicating if given player is in live mode.
796    // Can be replaced when this is fixed: https://github.com/videojs/video.js/issues/3262
797    isLive: function isLive(somePlayer) {
798      if (somePlayer.duration() === Infinity) {
799        return true;
800      } else if (_video2.default.browser.IOS_VERSION === '8' && somePlayer.duration() === 0) {
801        return true;
802      }
803      return false;
804    },
805
806
807    // Return true if content playback should mute and continue during ad breaks.
808    // This is only done during live streams on platforms where it's supported.
809    // This improves speed and accuracy when returning from an ad break.
810    shouldPlayContentBehindAd: function shouldPlayContentBehindAd(somePlayer) {
811      return !_video2.default.browser.IS_IOS && !_video2.default.browser.IS_ANDROID && somePlayer.duration() === Infinity;
812    }
813  };
814
815  player.ads.stitchedAds(settings.stitchedAds);
816
817  player.ads.adMacroReplacement = _macros2.default.bind(player);
818
819  // Start sending contentupdate events for this player
820  (0, _contentupdate2.default)(player);
821
822  // Global contentupdate handler for resetting plugin state
823  player.on('contentupdate', player.ads.reset);
824
825  // Ad Playback State Machine
826  var states = {
827    'content-set': {
828      events: {
829        adscanceled: function adscanceled() {
830          this.state = 'content-playback';
831        },
832        adsready: function adsready() {
833          this.state = 'ads-ready';
834        },
835        play: function play() {
836          this.state = 'ads-ready?';
837          (0, _cancelContentPlay2.default)(player);
838          // remove the poster so it doesn't flash between videos
839          removeNativePoster(player);
840        },
841        adserror: function adserror() {
842          this.state = 'content-playback';
843        },
844        adskip: function adskip() {
845          this.state = 'content-playback';
846        }
847      }
848    },
849    'ads-ready': {
850      events: {
851        play: function play() {
852          this.state = 'preroll?';
853          (0, _cancelContentPlay2.default)(player);
854        },
855        adskip: function adskip() {
856          this.state = 'content-playback';
857        },
858        adserror: function adserror() {
859          this.state = 'content-playback';
860        }
861      }
862    },
863    'preroll?': {
864      enter: function enter() {
865        if (player.ads.nopreroll_) {
866          // This will start the ads manager in case there are later ads
867          player.trigger('readyforpreroll');
868
869          // If we don't wait a tick, entering content-playback will cancel
870          // cancelPlayTimeout, causing the video to not pause for the ad
871          window.setTimeout(function () {
872            // Don't wait for a preroll
873            player.trigger('nopreroll');
874          }, 1);
875        } else {
876          // change class to show that we're waiting on ads
877          player.addClass('vjs-ad-loading');
878          // schedule an adtimeout event to fire if we waited too long
879          player.ads.adTimeoutTimeout = window.setTimeout(function () {
880            player.trigger('adtimeout');
881          }, settings.prerollTimeout);
882          // signal to ad plugin that it's their opportunity to play a preroll
883          player.trigger('readyforpreroll');
884        }
885      },
886      leave: function leave() {
887        window.clearTimeout(player.ads.adTimeoutTimeout);
888      },
889
890      events: {
891        play: function play() {
892          (0, _cancelContentPlay2.default)(player);
893        },
894        adstart: function adstart() {
895          this.state = 'ad-playback';
896        },
897        adskip: function adskip() {
898          this.state = 'content-playback';
899        },
900        adtimeout: function adtimeout() {
901          this.state = 'content-playback';
902        },
903        adserror: function adserror() {
904          this.state = 'content-playback';
905        },
906        nopreroll: function nopreroll() {
907          this.state = 'content-playback';
908        }
909      }
910    },
911    'ads-ready?': {
912      enter: function enter() {
913        player.addClass('vjs-ad-loading');
914        player.ads.adTimeoutTimeout = window.setTimeout(function () {
915          player.trigger('adtimeout');
916        }, settings.timeout);
917      },
918      leave: function leave() {
919        window.clearTimeout(player.ads.adTimeoutTimeout);
920        player.removeClass('vjs-ad-loading');
921      },
922
923      events: {
924        play: function play() {
925          (0, _cancelContentPlay2.default)(player);
926        },
927        adscanceled: function adscanceled() {
928          this.state = 'content-playback';
929        },
930        adsready: function adsready() {
931          this.state = 'preroll?';
932        },
933        adskip: function adskip() {
934          this.state = 'content-playback';
935        },
936        adtimeout: function adtimeout() {
937          this.state = 'content-playback';
938        },
939        adserror: function adserror() {
940          this.state = 'content-playback';
941        }
942      }
943    },
944    'ad-playback': {
945      enter: function enter() {
946        // capture current player state snapshot (playing, currentTime, src)
947        if (!player.ads.shouldPlayContentBehindAd(player)) {
948          this.snapshot = _snapshot2.default.getPlayerSnapshot(player);
949        }
950
951        // Mute the player behind the ad
952        if (player.ads.shouldPlayContentBehindAd(player)) {
953          this.preAdVolume_ = player.volume();
954          player.volume(0);
955        }
956
957        // add css to the element to indicate and ad is playing.
958        player.addClass('vjs-ad-playing');
959
960        // We should remove the vjs-live class if it has been added in order to 
961        // show the adprogress control bar on Android devices for falsely
962        // determined LIVE videos due to the duration incorrectly reported as Infinity
963        if (player.hasClass('vjs-live')) {
964          player.removeClass('vjs-live');
965        }
966
967        // remove the poster so it doesn't flash between ads
968        removeNativePoster(player);
969
970        // We no longer need to supress play events once an ad is playing.
971        // Clear it if we were.
972        if (player.ads.cancelPlayTimeout) {
973          // If we don't wait a tick, we could cancel the pause for cancelContentPlay,
974          // resulting in content playback behind the ad
975          window.setTimeout(function () {
976            window.clearTimeout(player.ads.cancelPlayTimeout);
977            player.ads.cancelPlayTimeout = null;
978          }, 1);
979        }
980      },
981      leave: function leave() {
982        player.removeClass('vjs-ad-playing');
983
984        // We should add the vjs-live class back if the video is a LIVE video
985        // If we dont do this, then for a LIVE Video, we will get an incorrect
986        // styled control, which displays the time for the video
987        if (player.ads.isLive(player)) {
988          player.addClass('vjs-live');
989        }
990        if (!player.ads.shouldPlayContentBehindAd(player)) {
991          _snapshot2.default.restorePlayerSnapshot(player, this.snapshot);
992        }
993
994        // Reset the volume to pre-ad levels
995        if (player.ads.shouldPlayContentBehindAd(player)) {
996          player.volume(this.preAdVolume_);
997        }
998      },
999
1000      events: {
1001        adend: function adend() {
1002          this.state = 'content-resuming';
1003        },
1004        adserror: function adserror() {
1005          this.state = 'content-resuming';
1006          // Trigger 'adend' to notify that we are exiting 'ad-playback'
1007          player.trigger('adend');
1008        }
1009      }
1010    },
1011    'content-resuming': {
1012      enter: function enter() {
1013        if (this._contentHasEnded) {
1014          window.clearTimeout(player.ads._fireEndedTimeout);
1015          // in some cases, ads are played in a swf or another video element
1016          // so we do not get an ended event in this state automatically.
1017          // If we don't get an ended event we can use, we need to trigger
1018          // one ourselves or else we won't actually ever end the current video.
1019          player.ads._fireEndedTimeout = window.setTimeout(function () {
1020            player.trigger('ended');
1021          }, 1000);
1022        }
1023      },
1024      leave: function leave() {
1025        window.clearTimeout(player.ads._fireEndedTimeout);
1026      },
1027
1028      events: {
1029        contentupdate: function contentupdate() {
1030          this.state = 'content-set';
1031        },
1032        contentresumed: function contentresumed() {
1033          this.state = 'content-playback';
1034        },
1035        playing: function playing() {
1036          this.state = 'content-playback';
1037        },
1038        ended: function ended() {
1039          this.state = 'content-playback';
1040        }
1041      }
1042    },
1043    'postroll?': {
1044      enter: function enter() {
1045        this.snapshot = _snapshot2.default.getPlayerSnapshot(player);
1046        if (player.ads.nopostroll_) {
1047          window.setTimeout(function () {
1048            // content-resuming happens after the timeout for backward-compatibility
1049            // with plugins that relied on a postrollTimeout before nopostroll was
1050            // implemented
1051            player.ads.state = 'content-resuming';
1052            player.trigger('ended');
1053          }, 1);
1054        } else {
1055          player.addClass('vjs-ad-loading');
1056
1057          player.ads.adTimeoutTimeout = window.setTimeout(function () {
1058            player.trigger('adtimeout');
1059          }, settings.postrollTimeout);
1060        }
1061      },
1062      leave: function leave() {
1063        window.clearTimeout(player.ads.adTimeoutTimeout);
1064        player.removeClass('vjs-ad-loading');
1065      },
1066
1067      events: {
1068        adstart: function adstart() {
1069          this.state = 'ad-playback';
1070        },
1071        adskip: function adskip() {
1072          this.state = 'content-resuming';
1073          window.setTimeout(function () {
1074            player.trigger('ended');
1075          }, 1);
1076        },
1077        adtimeout: function adtimeout() {
1078          this.state = 'content-resuming';
1079          window.setTimeout(function () {
1080            player.trigger('ended');
1081          }, 1);
1082        },
1083        adserror: function adserror() {
1084          this.state = 'content-resuming';
1085          window.setTimeout(function () {
1086            player.trigger('ended');
1087          }, 1);
1088        },
1089        contentupdate: function contentupdate() {
1090          this.state = 'ads-ready?';
1091        }
1092      }
1093    },
1094    'content-playback': {
1095      enter: function enter() {
1096        // make sure that any cancelPlayTimeout is cleared
1097        if (player.ads.cancelPlayTimeout) {
1098          window.clearTimeout(player.ads.cancelPlayTimeout);
1099          player.ads.cancelPlayTimeout = null;
1100        }
1101
1102        // This was removed because now that "playing" is fixed to only play after
1103        // preroll, any integration should just use the "playing" event. However,
1104        // we found out some 3rd party code relied on this event, so we've temporarily
1105        // added it back in to give people more time to update their code.
1106        player.trigger({
1107          type: 'contentplayback',
1108          triggerevent: player.ads.triggerevent
1109        });
1110
1111        // Play the content
1112        if (player.ads.cancelledPlay) {
1113          player.ads.cancelledPlay = false;
1114          if (player.paused()) {
1115            player.play();
1116          }
1117        }
1118      },
1119
1120      events: {
1121        // In the case of a timeout, adsready might come in late.
1122        // This assumes the behavior that if an ad times out, it c
1122ould still
1123        // interrupt the content and start playing. An integration could
1124        // still decide to behave otherwise.
1125        adsready: function adsready() {
1126          player.trigger('readyforpreroll');
1127        },
1128        adstart: function adstart() {
1129          this.state = 'ad-playback';
1130        },
1131        contentupdate: function contentupdate() {
1132          // We know sources have changed, so we call CancelContentPlay
1133          // to avoid playback of video in the background of an ad. Playback Occurs on
1134          // Android devices if we do not call cancelContentPlay. This is because
1135          // the sources do not get updated in time on Android due to timing issues.
1136          // So instead of checking if the sources have changed in the play handler
1137          // and calling cancelContentPlay() there we call it here.
1138          // This does not happen on Desktop as the sources do get updated in time.
1139          if (!player.ads.shouldPlayContentBehindAd(player)) {
1140            (0, _cancelContentPlay2.default)(player);
1141          }
1142          if (player.paused()) {
1143            this.state = 'content-set';
1144          } else {
1145            this.state = 'ads-ready?';
1146          }
1147        },
1148        contentended: function contentended() {
1149
1150          // If _contentHasEnded is true it means we already checked for postrolls and
1151          // played postrolls if needed, so now we're ready to send an ended event
1152          if (this._contentHasEnded) {
1153            // Causes ended event to trigger in content-resuming.enter.
1154            // From there, the ended event event is not redispatched.
1155            // Then we end up back in content-playback state.
1156            this.state = 'content-resuming';
1157            return;
1158          }
1159
1160          this._contentHasEnded = true;
1161          this.state = 'postroll?';
1162        }
1163      }
1164    }
1165  };
1166
1167  var processEvent = function processEvent(event) {
1168
1169    var state = player.ads.state;
1170
1171    // Execute the current state's handler for this event
1172    var eventHandlers = states[state].events;
1173
1174    if (eventHandlers) {
1175      var handler = eventHandlers[event.type];
1176
1177      if (handler) {
1178        handler.apply(player.ads);
1179      }
1180    }
1181
1182    // If the state has changed...
1183    if (state !== player.ads.state) {
1184      var previousState = state;
1185      var newState = player.ads.state;
1186
1187      // Record the event that caused the state transition
1188      player.ads.triggerevent = event.type;
1189
1190      // Execute "leave" method for the previous state
1191      if (states[previousState].leave) {
1192        states[previousState].leave.apply(player.ads);
1193      }
1194
1195      // Execute "enter" method for the new state
1196      if (states[newState].enter) {
1197        states[newState].enter.apply(player.ads);
1198      }
1199
1200      // Debug log message for state changes
1201      if (settings.debug) {
1202        _video2.default.log('ads', player.ads.triggerevent + ' triggered: ' + previousState + ' -> ' + newState);
1203      }
1204    }
1205  };
1206
1207  // Register our handler for the events that the state machine will process
1208  player.on(VIDEO_EVENTS.concat([
1209  // Events emitted by this plugin
1210  'adtimeout', 'contentupdate', 'contentplaying', 'contentended', 'contentresumed',
1211  // Triggered by startLinearAdMode()
1212  'adstart',
1213  // Triggered by endLinearAdMode()
1214  'adend',
1215  // Triggered by skipLinearAdMode()
1216  'adskip',
1217
1218  // Events emitted by integrations
1219  'adsready', 'adserror', 'adscanceled', 'nopreroll']), processEvent);
1220
1221  // If we're autoplaying, the state machine will immidiately process
1222  // a synthetic play event
1223  if (!player.paused()) {
1224    processEvent({ type: 'play' });
1225  }
1226};
1227
1228// Register this plugin with videojs
1229_video2.default.plugin('ads', contribAdsPlugin);
1230}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1231},{"./cancelContentPlay.js":1,"./contentupdate.js":2,"./macros.js":3,"./redispatch.js":4,"./snapshot.js":5}]},{},[6])(6)
1232});

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.