Merge branch 'MDL-68216-master' of git://github.com/lucaboesch/moodle
[moodle.git] / media / player / videojs / amd / src / video-lazy.js
1 /**
2  * @license
3  * Video.js 7.7.6 <http://videojs.com/>
4  * Copyright Brightcove, Inc. <https://www.brightcove.com/>
5  * Available under Apache License Version 2.0
6  * <https://github.com/videojs/video.js/blob/master/LICENSE>
7  *
8  * Includes vtt.js <https://github.com/mozilla/vtt.js>
9  * Available under Apache License Version 2.0
10  * <https://github.com/mozilla/vtt.js/blob/master/LICENSE>
11  */
13 (function (global, factory) {
14   typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('global/window'), require('global/document')) :
15   typeof define === 'function' && define.amd ? define(['./window', './document'], factory) :
16   (global = global || self, global.videojs = factory(global.window, global.document));
17 }(this, function (window$3, document) { 'use strict';
19   window$3 = window$3 && window$3.hasOwnProperty('default') ? window$3['default'] : window$3;
20   document = document && document.hasOwnProperty('default') ? document['default'] : document;
22   var version = "7.7.6";
24   /**
25    * @file create-logger.js
26    * @module create-logger
27    */
29   var history = [];
30   /**
31    * Log messages to the console and history based on the type of message
32    *
33    * @private
34    * @param  {string} type
35    *         The name of the console method to use.
36    *
37    * @param  {Array} args
38    *         The arguments to be passed to the matching console method.
39    */
41   var LogByTypeFactory = function LogByTypeFactory(name, log) {
42     return function (type, level, args) {
43       var lvl = log.levels[level];
44       var lvlRegExp = new RegExp("^(" + lvl + ")$");
46       if (type !== 'log') {
47         // Add the type to the front of the message when it's not "log".
48         args.unshift(type.toUpperCase() + ':');
49       } // Add console prefix after adding to history.
52       args.unshift(name + ':'); // Add a clone of the args at this point to history.
54       if (history) {
55         history.push([].concat(args)); // only store 1000 history entries
57         var splice = history.length - 1000;
58         history.splice(0, splice > 0 ? splice : 0);
59       } // If there's no console then don't try to output messages, but they will
60       // still be stored in history.
63       if (!window$3.console) {
64         return;
65       } // Was setting these once outside of this function, but containing them
66       // in the function makes it easier to test cases where console doesn't exist
67       // when the module is executed.
70       var fn = window$3.console[type];
72       if (!fn && type === 'debug') {
73         // Certain browsers don't have support for console.debug. For those, we
74         // should default to the closest comparable log.
75         fn = window$3.console.info || window$3.console.log;
76       } // Bail out if there's no console or if this type is not allowed by the
77       // current logging level.
80       if (!fn || !lvl || !lvlRegExp.test(type)) {
81         return;
82       }
84       fn[Array.isArray(args) ? 'apply' : 'call'](window$3.console, args);
85     };
86   };
88   function createLogger(name) {
89     // This is the private tracking variable for logging level.
90     var level = 'info'; // the curried logByType bound to the specific log and history
92     var logByType;
93     /**
94      * Logs plain debug messages. Similar to `console.log`.
95      *
96      * Due to [limitations](https://github.com/jsdoc3/jsdoc/issues/955#issuecomment-313829149)
97      * of our JSDoc template, we cannot properly document this as both a function
98      * and a namespace, so its function signature is documented here.
99      *
100      * #### Arguments
101      * ##### *args
102      * Mixed[]
103      *
104      * Any combination of values that could be passed to `console.log()`.
105      *
106      * #### Return Value
107      *
108      * `undefined`
109      *
110      * @namespace
111      * @param    {Mixed[]} args
112      *           One or more messages or objects that should be logged.
113      */
115     var log = function log() {
116       for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
117         args[_key] = arguments[_key];
118       }
120       logByType('log', level, args);
121     }; // This is the logByType helper that the logging methods below use
124     logByType = LogByTypeFactory(name, log);
125     /**
126      * Create a new sublogger which chains the old name to the new name.
127      *
128      * For example, doing `videojs.log.createLogger('player')` and then using that logger will log the following:
129      * ```js
130      *  mylogger('foo');
131      *  // > VIDEOJS: player: foo
132      * ```
133      *
134      * @param {string} name
135      *        The name to add call the new logger
136      * @return {Object}
137      */
139     log.createLogger = function (subname) {
140       return createLogger(name + ': ' + subname);
141     };
142     /**
143      * Enumeration of available logging levels, where the keys are the level names
144      * and the values are `|`-separated strings containing logging methods allowed
145      * in that logging level. These strings are used to create a regular expression
146      * matching the function name being called.
147      *
148      * Levels provided by Video.js are:
149      *
150      * - `off`: Matches no calls. Any value that can be cast to `false` will have
151      *   this effect. The most restrictive.
152      * - `all`: Matches only Video.js-provided functions (`debug`, `log`,
153      *   `log.warn`, and `log.error`).
154      * - `debug`: Matches `log.debug`, `log`, `log.warn`, and `log.error` calls.
155      * - `info` (default): Matches `log`, `log.warn`, and `log.error` calls.
156      * - `warn`: Matches `log.warn` and `log.error` calls.
157      * - `error`: Matches only `log.error` calls.
158      *
159      * @type {Object}
160      */
163     log.levels = {
164       all: 'debug|log|warn|error',
165       off: '',
166       debug: 'debug|log|warn|error',
167       info: 'log|warn|error',
168       warn: 'warn|error',
169       error: 'error',
170       DEFAULT: level
171     };
172     /**
173      * Get or set the current logging level.
174      *
175      * If a string matching a key from {@link module:log.levels} is provided, acts
176      * as a setter.
177      *
178      * @param  {string} [lvl]
179      *         Pass a valid level to set a new logging level.
180      *
181      * @return {string}
182      *         The current logging level.
183      */
185     log.level = function (lvl) {
186       if (typeof lvl === 'string') {
187         if (!log.levels.hasOwnProperty(lvl)) {
188           throw new Error("\"" + lvl + "\" in not a valid log level");
189         }
191         level = lvl;
192       }
194       return level;
195     };
196     /**
197      * Returns an array containing everything that has been logged to the history.
198      *
199      * This array is a shallow clone of the internal history record. However, its
200      * contents are _not_ cloned; so, mutating objects inside this array will
201      * mutate them in history.
202      *
203      * @return {Array}
204      */
207     log.history = function () {
208       return history ? [].concat(history) : [];
209     };
210     /**
211      * Allows you to filter the history by the given logger name
212      *
213      * @param {string} fname
214      *        The name to filter by
215      *
216      * @return {Array}
217      *         The filtered list to return
218      */
221     log.history.filter = function (fname) {
222       return (history || []).filter(function (historyItem) {
223         // if the first item in each historyItem includes `fname`, then it's a match
224         return new RegExp(".*" + fname + ".*").test(historyItem[0]);
225       });
226     };
227     /**
228      * Clears the internal history tracking, but does not prevent further history
229      * tracking.
230      */
233     log.history.clear = function () {
234       if (history) {
235         history.length = 0;
236       }
237     };
238     /**
239      * Disable history tracking if it is currently enabled.
240      */
243     log.history.disable = function () {
244       if (history !== null) {
245         history.length = 0;
246         history = null;
247       }
248     };
249     /**
250      * Enable history tracking if it is currently disabled.
251      */
254     log.history.enable = function () {
255       if (history === null) {
256         history = [];
257       }
258     };
259     /**
260      * Logs error messages. Similar to `console.error`.
261      *
262      * @param {Mixed[]} args
263      *        One or more messages or objects that should be logged as an error
264      */
267     log.error = function () {
268       for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
269         args[_key2] = arguments[_key2];
270       }
272       return logByType('error', level, args);
273     };
274     /**
275      * Logs warning messages. Similar to `console.warn`.
276      *
277      * @param {Mixed[]} args
278      *        One or more messages or objects that should be logged as a warning.
279      */
282     log.warn = function () {
283       for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
284         args[_key3] = arguments[_key3];
285       }
287       return logByType('warn', level, args);
288     };
289     /**
290      * Logs debug messages. Similar to `console.debug`, but may also act as a comparable
291      * log if `console.debug` is not available
292      *
293      * @param {Mixed[]} args
294      *        One or more messages or objects that should be logged as debug.
295      */
298     log.debug = function () {
299       for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
300         args[_key4] = arguments[_key4];
301       }
303       return logByType('debug', level, args);
304     };
306     return log;
307   }
309   /**
310    * @file log.js
311    * @module log
312    */
313   var log = createLogger('VIDEOJS');
314   var createLogger$1 = log.createLogger;
316   function createCommonjsModule(fn, module) {
317         return module = { exports: {} }, fn(module, module.exports), module.exports;
318   }
320   var _extends_1 = createCommonjsModule(function (module) {
321     function _extends() {
322       module.exports = _extends = Object.assign || function (target) {
323         for (var i = 1; i < arguments.length; i++) {
324           var source = arguments[i];
326           for (var key in source) {
327             if (Object.prototype.hasOwnProperty.call(source, key)) {
328               target[key] = source[key];
329             }
330           }
331         }
333         return target;
334       };
336       return _extends.apply(this, arguments);
337     }
339     module.exports = _extends;
340   });
342   /**
343    * @file obj.js
344    * @module obj
345    */
347   /**
348    * @callback obj:EachCallback
349    *
350    * @param {Mixed} value
351    *        The current key for the object that is being iterated over.
352    *
353    * @param {string} key
354    *        The current key-value for object that is being iterated over
355    */
357   /**
358    * @callback obj:ReduceCallback
359    *
360    * @param {Mixed} accum
361    *        The value that is accumulating over the reduce loop.
362    *
363    * @param {Mixed} value
364    *        The current key for the object that is being iterated over.
365    *
366    * @param {string} key
367    *        The current key-value for object that is being iterated over
368    *
369    * @return {Mixed}
370    *         The new accumulated value.
371    */
372   var toString = Object.prototype.toString;
373   /**
374    * Get the keys of an Object
375    *
376    * @param {Object}
377    *        The Object to get the keys from
378    *
379    * @return {string[]}
380    *         An array of the keys from the object. Returns an empty array if the
381    *         object passed in was invalid or had no keys.
382    *
383    * @private
384    */
386   var keys = function keys(object) {
387     return isObject(object) ? Object.keys(object) : [];
388   };
389   /**
390    * Array-like iteration for objects.
391    *
392    * @param {Object} object
393    *        The object to iterate over
394    *
395    * @param {obj:EachCallback} fn
396    *        The callback function which is called for each key in the object.
397    */
400   function each(object, fn) {
401     keys(object).forEach(function (key) {
402       return fn(object[key], key);
403     });
404   }
405   /**
406    * Array-like reduce for objects.
407    *
408    * @param {Object} object
409    *        The Object that you want to reduce.
410    *
411    * @param {Function} fn
412    *         A callback function which is called for each key in the object. It
413    *         receives the accumulated value and the per-iteration value and key
414    *         as arguments.
415    *
416    * @param {Mixed} [initial = 0]
417    *        Starting value
418    *
419    * @return {Mixed}
420    *         The final accumulated value.
421    */
423   function reduce(object, fn, initial) {
424     if (initial === void 0) {
425       initial = 0;
426     }
428     return keys(object).reduce(function (accum, key) {
429       return fn(accum, object[key], key);
430     }, initial);
431   }
432   /**
433    * Object.assign-style object shallow merge/extend.
434    *
435    * @param  {Object} target
436    * @param  {Object} ...sources
437    * @return {Object}
438    */
440   function assign(target) {
441     for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
442       sources[_key - 1] = arguments[_key];
443     }
445     if (Object.assign) {
446       return _extends_1.apply(void 0, [target].concat(sources));
447     }
449     sources.forEach(function (source) {
450       if (!source) {
451         return;
452       }
454       each(source, function (value, key) {
455         target[key] = value;
456       });
457     });
458     return target;
459   }
460   /**
461    * Returns whether a value is an object of any kind - including DOM nodes,
462    * arrays, regular expressions, etc. Not functions, though.
463    *
464    * This avoids the gotcha where using `typeof` on a `null` value
465    * results in `'object'`.
466    *
467    * @param  {Object} value
468    * @return {boolean}
469    */
471   function isObject(value) {
472     return !!value && typeof value === 'object';
473   }
474   /**
475    * Returns whether an object appears to be a "plain" object - that is, a
476    * direct instance of `Object`.
477    *
478    * @param  {Object} value
479    * @return {boolean}
480    */
482   function isPlain(value) {
483     return isObject(value) && toString.call(value) === '[object Object]' && value.constructor === Object;
484   }
486   /**
487    * @file computed-style.js
488    * @module computed-style
489    */
490   /**
491    * A safe getComputedStyle.
492    *
493    * This is needed because in Firefox, if the player is loaded in an iframe with
494    * `display:none`, then `getComputedStyle` returns `null`, so, we do a
495    * null-check to make sure that the player doesn't break in these cases.
496    *
497    * @function
498    * @param    {Element} el
499    *           The element you want the computed style of
500    *
501    * @param    {string} prop
502    *           The property name you want
503    *
504    * @see      https://bugzilla.mozilla.org/show_bug.cgi?id=548397
505    */
507   function computedStyle(el, prop) {
508     if (!el || !prop) {
509       return '';
510     }
512     if (typeof window$3.getComputedStyle === 'function') {
513       var computedStyleValue = window$3.getComputedStyle(el);
514       return computedStyleValue ? computedStyleValue.getPropertyValue(prop) || computedStyleValue[prop] : '';
515     }
517     return '';
518   }
520   /**
521    * @file dom.js
522    * @module dom
523    */
524   /**
525    * Detect if a value is a string with any non-whitespace characters.
526    *
527    * @private
528    * @param  {string} str
529    *         The string to check
530    *
531    * @return {boolean}
532    *         Will be `true` if the string is non-blank, `false` otherwise.
533    *
534    */
536   function isNonBlankString(str) {
537     // we use str.trim as it will trim any whitespace characters
538     // from the front or back of non-whitespace characters. aka
539     // Any string that contains non-whitespace characters will
540     // still contain them after `trim` but whitespace only strings
541     // will have a length of 0, failing this check.
542     return typeof str === 'string' && Boolean(str.trim());
543   }
544   /**
545    * Throws an error if the passed string has whitespace. This is used by
546    * class methods to be relatively consistent with the classList API.
547    *
548    * @private
549    * @param  {string} str
550    *         The string to check for whitespace.
551    *
552    * @throws {Error}
553    *         Throws an error if there is whitespace in the string.
554    */
557   function throwIfWhitespace(str) {
558     // str.indexOf instead of regex because str.indexOf is faster performance wise.
559     if (str.indexOf(' ') >= 0) {
560       throw new Error('class has illegal whitespace characters');
561     }
562   }
563   /**
564    * Produce a regular expression for matching a className within an elements className.
565    *
566    * @private
567    * @param  {string} className
568    *         The className to generate the RegExp for.
569    *
570    * @return {RegExp}
571    *         The RegExp that will check for a specific `className` in an elements
572    *         className.
573    */
576   function classRegExp(className) {
577     return new RegExp('(^|\\s)' + className + '($|\\s)');
578   }
579   /**
580    * Whether the current DOM interface appears to be real (i.e. not simulated).
581    *
582    * @return {boolean}
583    *         Will be `true` if the DOM appears to be real, `false` otherwise.
584    */
587   function isReal() {
588     // Both document and window will never be undefined thanks to `global`.
589     return document === window$3.document;
590   }
591   /**
592    * Determines, via duck typing, whether or not a value is a DOM element.
593    *
594    * @param  {Mixed} value
595    *         The value to check.
596    *
597    * @return {boolean}
598    *         Will be `true` if the value is a DOM element, `false` otherwise.
599    */
601   function isEl(value) {
602     return isObject(value) && value.nodeType === 1;
603   }
604   /**
605    * Determines if the current DOM is embedded in an iframe.
606    *
607    * @return {boolean}
608    *         Will be `true` if the DOM is embedded in an iframe, `false`
609    *         otherwise.
610    */
612   function isInFrame() {
613     // We need a try/catch here because Safari will throw errors when attempting
614     // to get either `parent` or `self`
615     try {
616       return window$3.parent !== window$3.self;
617     } catch (x) {
618       return true;
619     }
620   }
621   /**
622    * Creates functions to query the DOM using a given method.
623    *
624    * @private
625    * @param   {string} method
626    *          The method to create the query with.
627    *
628    * @return  {Function}
629    *          The query method
630    */
632   function createQuerier(method) {
633     return function (selector, context) {
634       if (!isNonBlankString(selector)) {
635         return document[method](null);
636       }
638       if (isNonBlankString(context)) {
639         context = document.querySelector(context);
640       }
642       var ctx = isEl(context) ? context : document;
643       return ctx[method] && ctx[method](selector);
644     };
645   }
646   /**
647    * Creates an element and applies properties, attributes, and inserts content.
648    *
649    * @param  {string} [tagName='div']
650    *         Name of tag to be created.
651    *
652    * @param  {Object} [properties={}]
653    *         Element properties to be applied.
654    *
655    * @param  {Object} [attributes={}]
656    *         Element attributes to be applied.
657    *
658    * @param {module:dom~ContentDescriptor} content
659    *        A content descriptor object.
660    *
661    * @return {Element}
662    *         The element that was created.
663    */
666   function createEl(tagName, properties, attributes, content) {
667     if (tagName === void 0) {
668       tagName = 'div';
669     }
671     if (properties === void 0) {
672       properties = {};
673     }
675     if (attributes === void 0) {
676       attributes = {};
677     }
679     var el = document.createElement(tagName);
680     Object.getOwnPropertyNames(properties).forEach(function (propName) {
681       var val = properties[propName]; // See #2176
682       // We originally were accepting both properties and attributes in the
683       // same object, but that doesn't work so well.
685       if (propName.indexOf('aria-') !== -1 || propName === 'role' || propName === 'type') {
686         log.warn('Setting attributes in the second argument of createEl()\n' + 'has been deprecated. Use the third argument instead.\n' + ("createEl(type, properties, attributes). Attempting to set " + propName + " to " + val + "."));
687         el.setAttribute(propName, val); // Handle textContent since it's not supported everywhere and we have a
688         // method for it.
689       } else if (propName === 'textContent') {
690         textContent(el, val);
691       } else if (el[propName] !== val) {
692         el[propName] = val;
693       }
694     });
695     Object.getOwnPropertyNames(attributes).forEach(function (attrName) {
696       el.setAttribute(attrName, attributes[attrName]);
697     });
699     if (content) {
700       appendContent(el, content);
701     }
703     return el;
704   }
705   /**
706    * Injects text into an element, replacing any existing contents entirely.
707    *
708    * @param  {Element} el
709    *         The element to add text content into
710    *
711    * @param  {string} text
712    *         The text content to add.
713    *
714    * @return {Element}
715    *         The element with added text content.
716    */
718   function textContent(el, text) {
719     if (typeof el.textContent === 'undefined') {
720       el.innerText = text;
721     } else {
722       el.textContent = text;
723     }
725     return el;
726   }
727   /**
728    * Insert an element as the first child node of another
729    *
730    * @param {Element} child
731    *        Element to insert
732    *
733    * @param {Element} parent
734    *        Element to insert child into
735    */
737   function prependTo(child, parent) {
738     if (parent.firstChild) {
739       parent.insertBefore(child, parent.firstChild);
740     } else {
741       parent.appendChild(child);
742     }
743   }
744   /**
745    * Check if an element has a class name.
746    *
747    * @param  {Element} element
748    *         Element to check
749    *
750    * @param  {string} classToCheck
751    *         Class name to check for
752    *
753    * @return {boolean}
754    *         Will be `true` if the element has a class, `false` otherwise.
755    *
756    * @throws {Error}
757    *         Throws an error if `classToCheck` has white space.
758    */
760   function hasClass(element, classToCheck) {
761     throwIfWhitespace(classToCheck);
763     if (element.classList) {
764       return element.classList.contains(classToCheck);
765     }
767     return classRegExp(classToCheck).test(element.className);
768   }
769   /**
770    * Add a class name to an element.
771    *
772    * @param  {Element} element
773    *         Element to add class name to.
774    *
775    * @param  {string} classToAdd
776    *         Class name to add.
777    *
778    * @return {Element}
779    *         The DOM element with the added class name.
780    */
782   function addClass(element, classToAdd) {
783     if (element.classList) {
784       element.classList.add(classToAdd); // Don't need to `throwIfWhitespace` here because `hasElClass` will do it
785       // in the case of classList not being supported.
786     } else if (!hasClass(element, classToAdd)) {
787       element.className = (element.className + ' ' + classToAdd).trim();
788     }
790     return element;
791   }
792   /**
793    * Remove a class name from an element.
794    *
795    * @param  {Element} element
796    *         Element to remove a class name from.
797    *
798    * @param  {string} classToRemove
799    *         Class name to remove
800    *
801    * @return {Element}
802    *         The DOM element with class name removed.
803    */
805   function removeClass(element, classToRemove) {
806     if (element.classList) {
807       element.classList.remove(classToRemove);
808     } else {
809       throwIfWhitespace(classToRemove);
810       element.className = element.className.split(/\s+/).filter(function (c) {
811         return c !== classToRemove;
812       }).join(' ');
813     }
815     return element;
816   }
817   /**
818    * The callback definition for toggleClass.
819    *
820    * @callback module:dom~PredicateCallback
821    * @param    {Element} element
822    *           The DOM element of the Component.
823    *
824    * @param    {string} classToToggle
825    *           The `className` that wants to be toggled
826    *
827    * @return   {boolean|undefined}
828    *           If `true` is returned, the `classToToggle` will be added to the
829    *           `element`. If `false`, the `classToToggle` will be removed from
830    *           the `element`. If `undefined`, the callback will be ignored.
831    */
833   /**
834    * Adds or removes a class name to/from an element depending on an optional
835    * condition or the presence/absence of the class name.
836    *
837    * @param  {Element} element
838    *         The element to toggle a class name on.
839    *
840    * @param  {string} classToToggle
841    *         The class that should be toggled.
842    *
843    * @param  {boolean|module:dom~PredicateCallback} [predicate]
844    *         See the return value for {@link module:dom~PredicateCallback}
845    *
846    * @return {Element}
847    *         The element with a class that has been toggled.
848    */
850   function toggleClass(element, classToToggle, predicate) {
851     // This CANNOT use `classList` internally because IE11 does not support the
852     // second parameter to the `classList.toggle()` method! Which is fine because
853     // `classList` will be used by the add/remove functions.
854     var has = hasClass(element, classToToggle);
856     if (typeof predicate === 'function') {
857       predicate = predicate(element, classToToggle);
858     }
860     if (typeof predicate !== 'boolean') {
861       predicate = !has;
862     } // If the necessary class operation matches the current state of the
863     // element, no action is required.
866     if (predicate === has) {
867       return;
868     }
870     if (predicate) {
871       addClass(element, classToToggle);
872     } else {
873       removeClass(element, classToToggle);
874     }
876     return element;
877   }
878   /**
879    * Apply attributes to an HTML element.
880    *
881    * @param {Element} el
882    *        Element to add attributes to.
883    *
884    * @param {Object} [attributes]
885    *        Attributes to be applied.
886    */
888   function setAttributes(el, attributes) {
889     Object.getOwnPropertyNames(attributes).forEach(function (attrName) {
890       var attrValue = attributes[attrName];
892       if (attrValue === null || typeof attrValue === 'undefined' || attrValue === false) {
893         el.removeAttribute(attrName);
894       } else {
895         el.setAttribute(attrName, attrValue === true ? '' : attrValue);
896       }
897     });
898   }
899   /**
900    * Get an element's attribute values, as defined on the HTML tag.
901    *
902    * Attributes are not the same as properties. They're defined on the tag
903    * or with setAttribute.
904    *
905    * @param  {Element} tag
906    *         Element from which to get tag attributes.
907    *
908    * @return {Object}
909    *         All attributes of the element. Boolean attributes will be `true` or
910    *         `false`, others will be strings.
911    */
913   function getAttributes(tag) {
914     var obj = {}; // known boolean attributes
915     // we can check for matching boolean properties, but not all browsers
916     // and not all tags know about these attributes, so, we still want to check them manually
918     var knownBooleans = ',' + 'autoplay,controls,playsinline,loop,muted,default,defaultMuted' + ',';
920     if (tag && tag.attributes && tag.attributes.length > 0) {
921       var attrs = tag.attributes;
923       for (var i = attrs.length - 1; i >= 0; i--) {
924         var attrName = attrs[i].name;
925         var attrVal = attrs[i].value; // check for known booleans
926         // the matching element property will return a value for typeof
928         if (typeof tag[attrName] === 'boolean' || knownBooleans.indexOf(',' + attrName + ',') !== -1) {
929           // the value of an included boolean attribute is typically an empty
930           // string ('') which would equal false if we just check for a false value.
931           // we also don't want support bad code like autoplay='false'
932           attrVal = attrVal !== null ? true : false;
933         }
935         obj[attrName] = attrVal;
936       }
937     }
939     return obj;
940   }
941   /**
942    * Get the value of an element's attribute.
943    *
944    * @param {Element} el
945    *        A DOM element.
946    *
947    * @param {string} attribute
948    *        Attribute to get the value of.
949    *
950    * @return {string}
951    *         The value of the attribute.
952    */
954   function getAttribute(el, attribute) {
955     return el.getAttribute(attribute);
956   }
957   /**
958    * Set the value of an element's attribute.
959    *
960    * @param {Element} el
961    *        A DOM element.
962    *
963    * @param {string} attribute
964    *        Attribute to set.
965    *
966    * @param {string} value
967    *        Value to set the attribute to.
968    */
970   function setAttribute(el, attribute, value) {
971     el.setAttribute(attribute, value);
972   }
973   /**
974    * Remove an element's attribute.
975    *
976    * @param {Element} el
977    *        A DOM element.
978    *
979    * @param {string} attribute
980    *        Attribute to remove.
981    */
983   function removeAttribute(el, attribute) {
984     el.removeAttribute(attribute);
985   }
986   /**
987    * Attempt to block the ability to select text.
988    */
990   function blockTextSelection() {
991     document.body.focus();
993     document.onselectstart = function () {
994       return false;
995     };
996   }
997   /**
998    * Turn off text selection blocking.
999    */
1001   function unblockTextSelection() {
1002     document.onselectstart = function () {
1003       return true;
1004     };
1005   }
1006   /**
1007    * Identical to the native `getBoundingClientRect` function, but ensures that
1008    * the method is supported at all (it is in all browsers we claim to support)
1009    * and that the element is in the DOM before continuing.
1010    *
1011    * This wrapper function also shims properties which are not provided by some
1012    * older browsers (namely, IE8).
1013    *
1014    * Additionally, some browsers do not support adding properties to a
1015    * `ClientRect`/`DOMRect` object; so, we shallow-copy it with the standard
1016    * properties (except `x` and `y` which are not widely supported). This helps
1017    * avoid implementations where keys are non-enumerable.
1018    *
1019    * @param  {Element} el
1020    *         Element whose `ClientRect` we want to calculate.
1021    *
1022    * @return {Object|undefined}
1023    *         Always returns a plain object - or `undefined` if it cannot.
1024    */
1026   function getBoundingClientRect(el) {
1027     if (el && el.getBoundingClientRect && el.parentNode) {
1028       var rect = el.getBoundingClientRect();
1029       var result = {};
1030       ['bottom', 'height', 'left', 'right', 'top', 'width'].forEach(function (k) {
1031         if (rect[k] !== undefined) {
1032           result[k] = rect[k];
1033         }
1034       });
1036       if (!result.height) {
1037         result.height = parseFloat(computedStyle(el, 'height'));
1038       }
1040       if (!result.width) {
1041         result.width = parseFloat(computedStyle(el, 'width'));
1042       }
1044       return result;
1045     }
1046   }
1047   /**
1048    * Represents the position of a DOM element on the page.
1049    *
1050    * @typedef  {Object} module:dom~Position
1051    *
1052    * @property {number} left
1053    *           Pixels to the left.
1054    *
1055    * @property {number} top
1056    *           Pixels from the top.
1057    */
1059   /**
1060    * Get the position of an element in the DOM.
1061    *
1062    * Uses `getBoundingClientRect` technique from John Resig.
1063    *
1064    * @see http://ejohn.org/blog/getboundingclientrect-is-awesome/
1065    *
1066    * @param  {Element} el
1067    *         Element from which to get offset.
1068    *
1069    * @return {module:dom~Position}
1070    *         The position of the element that was passed in.
1071    */
1073   function findPosition(el) {
1074     var box;
1076     if (el.getBoundingClientRect && el.parentNode) {
1077       box = el.getBoundingClientRect();
1078     }
1080     if (!box) {
1081       return {
1082         left: 0,
1083         top: 0
1084       };
1085     }
1087     var docEl = document.documentElement;
1088     var body = document.body;
1089     var clientLeft = docEl.clientLeft || body.clientLeft || 0;
1090     var scrollLeft = window$3.pageXOffset || body.scrollLeft;
1091     var left = box.left + scrollLeft - clientLeft;
1092     var clientTop = docEl.clientTop || body.clientTop || 0;
1093     var scrollTop = window$3.pageYOffset || body.scrollTop;
1094     var top = box.top + scrollTop - clientTop; // Android sometimes returns slightly off decimal values, so need to round
1096     return {
1097       left: Math.round(left),
1098       top: Math.round(top)
1099     };
1100   }
1101   /**
1102    * Represents x and y coordinates for a DOM element or mouse pointer.
1103    *
1104    * @typedef  {Object} module:dom~Coordinates
1105    *
1106    * @property {number} x
1107    *           x coordinate in pixels
1108    *
1109    * @property {number} y
1110    *           y coordinate in pixels
1111    */
1113   /**
1114    * Get the pointer position within an element.
1115    *
1116    * The base on the coordinates are the bottom left of the element.
1117    *
1118    * @param  {Element} el
1119    *         Element on which to get the pointer position on.
1120    *
1121    * @param  {EventTarget~Event} event
1122    *         Event object.
1123    *
1124    * @return {module:dom~Coordinates}
1125    *         A coordinates object corresponding to the mouse position.
1126    *
1127    */
1129   function getPointerPosition(el, event) {
1130     var position = {};
1131     var box = findPosition(el);
1132     var boxW = el.offsetWidth;
1133     var boxH = el.offsetHeight;
1134     var boxY = box.top;
1135     var boxX = box.left;
1136     var pageY = event.pageY;
1137     var pageX = event.pageX;
1139     if (event.changedTouches) {
1140       pageX = event.changedTouches[0].pageX;
1141       pageY = event.changedTouches[0].pageY;
1142     }
1144     position.y = Math.max(0, Math.min(1, (boxY - pageY + boxH) / boxH));
1145     position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW));
1146     return position;
1147   }
1148   /**
1149    * Determines, via duck typing, whether or not a value is a text node.
1150    *
1151    * @param  {Mixed} value
1152    *         Check if this value is a text node.
1153    *
1154    * @return {boolean}
1155    *         Will be `true` if the value is a text node, `false` otherwise.
1156    */
1158   function isTextNode(value) {
1159     return isObject(value) && value.nodeType === 3;
1160   }
1161   /**
1162    * Empties the contents of an element.
1163    *
1164    * @param  {Element} el
1165    *         The element to empty children from
1166    *
1167    * @return {Element}
1168    *         The element with no children
1169    */
1171   function emptyEl(el) {
1172     while (el.firstChild) {
1173       el.removeChild(el.firstChild);
1174     }
1176     return el;
1177   }
1178   /**
1179    * This is a mixed value that describes content to be injected into the DOM
1180    * via some method. It can be of the following types:
1181    *
1182    * Type       | Description
1183    * -----------|-------------
1184    * `string`   | The value will be normalized into a text node.
1185    * `Element`  | The value will be accepted as-is.
1186    * `TextNode` | The value will be accepted as-is.
1187    * `Array`    | A one-dimensional array of strings, elements, text nodes, or functions. These functions should return a string, element, or text node (any other return value, like an array, will be ignored).
1188    * `Function` | A function, which is expected to return a string, element, text node, or array - any of the other possible values described above. This means that a content descriptor could be a function that returns an array of functions, but those second-level functions must return strings, elements, or text nodes.
1189    *
1190    * @typedef {string|Element|TextNode|Array|Function} module:dom~ContentDescriptor
1191    */
1193   /**
1194    * Normalizes content for eventual insertion into the DOM.
1195    *
1196    * This allows a wide range of content definition methods, but helps protect
1197    * from falling into the trap of simply writing to `innerHTML`, which could
1198    * be an XSS concern.
1199    *
1200    * The content for an element can be passed in multiple types and
1201    * combinations, whose behavior is as follows:
1202    *
1203    * @param {module:dom~ContentDescriptor} content
1204    *        A content descriptor value.
1205    *
1206    * @return {Array}
1207    *         All of the content that was passed in, normalized to an array of
1208    *         elements or text nodes.
1209    */
1211   function normalizeContent(content) {
1212     // First, invoke content if it is a function. If it produces an array,
1213     // that needs to happen before normalization.
1214     if (typeof content === 'function') {
1215       content = content();
1216     } // Next up, normalize to an array, so one or many items can be normalized,
1217     // filtered, and returned.
1220     return (Array.isArray(content) ? content : [content]).map(function (value) {
1221       // First, invoke value if it is a function to produce a new value,
1222       // which will be subsequently normalized to a Node of some kind.
1223       if (typeof value === 'function') {
1224         value = value();
1225       }
1227       if (isEl(value) || isTextNode(value)) {
1228         return value;
1229       }
1231       if (typeof value === 'string' && /\S/.test(value)) {
1232         return document.createTextNode(value);
1233       }
1234     }).filter(function (value) {
1235       return value;
1236     });
1237   }
1238   /**
1239    * Normalizes and appends content to an element.
1240    *
1241    * @param  {Element} el
1242    *         Element to append normalized content to.
1243    *
1244    * @param {module:dom~ContentDescriptor} content
1245    *        A content descriptor value.
1246    *
1247    * @return {Element}
1248    *         The element with appended normalized content.
1249    */
1251   function appendContent(el, content) {
1252     normalizeContent(content).forEach(function (node) {
1253       return el.appendChild(node);
1254     });
1255     return el;
1256   }
1257   /**
1258    * Normalizes and inserts content into an element; this is identical to
1259    * `appendContent()`, except it empties the element first.
1260    *
1261    * @param {Element} el
1262    *        Element to insert normalized content into.
1263    *
1264    * @param {module:dom~ContentDescriptor} content
1265    *        A content descriptor value.
1266    *
1267    * @return {Element}
1268    *         The element with inserted normalized content.
1269    */
1271   function insertContent(el, content) {
1272     return appendContent(emptyEl(el), content);
1273   }
1274   /**
1275    * Check if an event was a single left click.
1276    *
1277    * @param  {EventTarget~Event} event
1278    *         Event object.
1279    *
1280    * @return {boolean}
1281    *         Will be `true` if a single left click, `false` otherwise.
1282    */
1284   function isSingleLeftClick(event) {
1285     // Note: if you create something draggable, be sure to
1286     // call it on both `mousedown` and `mousemove` event,
1287     // otherwise `mousedown` should be enough for a button
1288     if (event.button === undefined && event.buttons === undefined) {
1289       // Why do we need `buttons` ?
1290       // Because, middle mouse sometimes have this:
1291       // e.button === 0 and e.buttons === 4
1292       // Furthermore, we want to prevent combination click, something like
1293       // HOLD middlemouse then left click, that would be
1294       // e.button === 0, e.buttons === 5
1295       // just `button` is not gonna work
1296       // Alright, then what this block does ?
1297       // this is for chrome `simulate mobile devices`
1298       // I want to support this as well
1299       return true;
1300     }
1302     if (event.button === 0 && event.buttons === undefined) {
1303       // Touch screen, sometimes on some specific device, `buttons`
1304       // doesn't have anything (safari on ios, blackberry...)
1305       return true;
1306     } // `mouseup` event on a single left click has
1307     // `button` and `buttons` equal to 0
1310     if (event.type === 'mouseup' && event.button === 0 && event.buttons === 0) {
1311       return true;
1312     }
1314     if (event.button !== 0 || event.buttons !== 1) {
1315       // This is the reason we have those if else block above
1316       // if any special case we can catch and let it slide
1317       // we do it above, when get to here, this definitely
1318       // is-not-left-click
1319       return false;
1320     }
1322     return true;
1323   }
1324   /**
1325    * Finds a single DOM element matching `selector` within the optional
1326    * `context` of another DOM element (defaulting to `document`).
1327    *
1328    * @param  {string} selector
1329    *         A valid CSS selector, which will be passed to `querySelector`.
1330    *
1331    * @param  {Element|String} [context=document]
1332    *         A DOM element within which to query. Can also be a selector
1333    *         string in which case the first matching element will be used
1334    *         as context. If missing (or no element matches selector), falls
1335    *         back to `document`.
1336    *
1337    * @return {Element|null}
1338    *         The element that was found or null.
1339    */
1341   var $ = createQuerier('querySelector');
1342   /**
1343    * Finds a all DOM elements matching `selector` within the optional
1344    * `context` of another DOM element (defaulting to `document`).
1345    *
1346    * @param  {string} selector
1347    *         A valid CSS selector, which will be passed to `querySelectorAll`.
1348    *
1349    * @param  {Element|String} [context=document]
1350    *         A DOM element within which to query. Can also be a selector
1351    *         string in which case the first matching element will be used
1352    *         as context. If missing (or no element matches selector), falls
1353    *         back to `document`.
1354    *
1355    * @return {NodeList}
1356    *         A element list of elements that were found. Will be empty if none
1357    *         were found.
1358    *
1359    */
1361   var $$ = createQuerier('querySelectorAll');
1363   var Dom = /*#__PURE__*/Object.freeze({
1364     isReal: isReal,
1365     isEl: isEl,
1366     isInFrame: isInFrame,
1367     createEl: createEl,
1368     textContent: textContent,
1369     prependTo: prependTo,
1370     hasClass: hasClass,
1371     addClass: addClass,
1372     removeClass: removeClass,
1373     toggleClass: toggleClass,
1374     setAttributes: setAttributes,
1375     getAttributes: getAttributes,
1376     getAttribute: getAttribute,
1377     setAttribute: setAttribute,
1378     removeAttribute: removeAttribute,
1379     blockTextSelection: blockTextSelection,
1380     unblockTextSelection: unblockTextSelection,
1381     getBoundingClientRect: getBoundingClientRect,
1382     findPosition: findPosition,
1383     getPointerPosition: getPointerPosition,
1384     isTextNode: isTextNode,
1385     emptyEl: emptyEl,
1386     normalizeContent: normalizeContent,
1387     appendContent: appendContent,
1388     insertContent: insertContent,
1389     isSingleLeftClick: isSingleLeftClick,
1390     $: $,
1391     $$: $$
1392   });
1394   /**
1395    * @file setup.js - Functions for setting up a player without
1396    * user interaction based on the data-setup `attribute` of the video tag.
1397    *
1398    * @module setup
1399    */
1400   var _windowLoaded = false;
1401   var videojs;
1402   /**
1403    * Set up any tags that have a data-setup `attribute` when the player is started.
1404    */
1406   var autoSetup = function autoSetup() {
1407     // Protect against breakage in non-browser environments and check global autoSetup option.
1408     if (!isReal() || videojs.options.autoSetup === false) {
1409       return;
1410     }
1412     var vids = Array.prototype.slice.call(document.getElementsByTagName('video'));
1413     var audios = Array.prototype.slice.call(document.getElementsByTagName('audio'));
1414     var divs = Array.prototype.slice.call(document.getElementsByTagName('video-js'));
1415     var mediaEls = vids.concat(audios, divs); // Check if any media elements exist
1417     if (mediaEls && mediaEls.length > 0) {
1418       for (var i = 0, e = mediaEls.length; i < e; i++) {
1419         var mediaEl = mediaEls[i]; // Check if element exists, has getAttribute func.
1421         if (mediaEl && mediaEl.getAttribute) {
1422           // Make sure this player hasn't already been set up.
1423           if (mediaEl.player === undefined) {
1424             var options = mediaEl.getAttribute('data-setup'); // Check if data-setup attr exists.
1425             // We only auto-setup if they've added the data-setup attr.
1427             if (options !== null) {
1428               // Create new video.js instance.
1429               videojs(mediaEl);
1430             }
1431           } // If getAttribute isn't defined, we need to wait for the DOM.
1433         } else {
1434           autoSetupTimeout(1);
1435           break;
1436         }
1437       } // No videos were found, so keep looping unless page is finished loading.
1439     } else if (!_windowLoaded) {
1440       autoSetupTimeout(1);
1441     }
1442   };
1443   /**
1444    * Wait until the page is loaded before running autoSetup. This will be called in
1445    * autoSetup if `hasLoaded` returns false.
1446    *
1447    * @param {number} wait
1448    *        How long to wait in ms
1449    *
1450    * @param {module:videojs} [vjs]
1451    *        The videojs library function
1452    */
1455   function autoSetupTimeout(wait, vjs) {
1456     if (vjs) {
1457       videojs = vjs;
1458     }
1460     window$3.setTimeout(autoSetup, wait);
1461   }
1462   /**
1463    * Used to set the internal tracking of window loaded state to true.
1464    *
1465    * @private
1466    */
1469   function setWindowLoaded() {
1470     _windowLoaded = true;
1471     window$3.removeEventListener('load', setWindowLoaded);
1472   }
1474   if (isReal()) {
1475     if (document.readyState === 'complete') {
1476       setWindowLoaded();
1477     } else {
1478       /**
1479        * Listen for the load event on window, and set _windowLoaded to true.
1480        *
1481        * We use a standard event listener here to avoid incrementing the GUID
1482        * before any players are created.
1483        *
1484        * @listens load
1485        */
1486       window$3.addEventListener('load', setWindowLoaded);
1487     }
1488   }
1490   /**
1491    * @file stylesheet.js
1492    * @module stylesheet
1493    */
1494   /**
1495    * Create a DOM syle element given a className for it.
1496    *
1497    * @param {string} className
1498    *        The className to add to the created style element.
1499    *
1500    * @return {Element}
1501    *         The element that was created.
1502    */
1504   var createStyleElement = function createStyleElement(className) {
1505     var style = document.createElement('style');
1506     style.className = className;
1507     return style;
1508   };
1509   /**
1510    * Add text to a DOM element.
1511    *
1512    * @param {Element} el
1513    *        The Element to add text content to.
1514    *
1515    * @param {string} content
1516    *        The text to add to the element.
1517    */
1519   var setTextContent = function setTextContent(el, content) {
1520     if (el.styleSheet) {
1521       el.styleSheet.cssText = content;
1522     } else {
1523       el.textContent = content;
1524     }
1525   };
1527   /**
1528    * @file guid.js
1529    * @module guid
1530    */
1531   // Default value for GUIDs. This allows us to reset the GUID counter in tests.
1532   //
1533   // The initial GUID is 3 because some users have come to rely on the first
1534   // default player ID ending up as `vjs_video_3`.
1535   //
1536   // See: https://github.com/videojs/video.js/pull/6216
1537   var _initialGuid = 3;
1538   /**
1539    * Unique ID for an element or function
1540    *
1541    * @type {Number}
1542    */
1544   var _guid = _initialGuid;
1545   /**
1546    * Get a unique auto-incrementing ID by number that has not been returned before.
1547    *
1548    * @return {number}
1549    *         A new unique ID.
1550    */
1552   function newGUID() {
1553     return _guid++;
1554   }
1556   /**
1557    * @file dom-data.js
1558    * @module dom-data
1559    */
1560   var FakeWeakMap;
1562   if (!window$3.WeakMap) {
1563     FakeWeakMap = /*#__PURE__*/function () {
1564       function FakeWeakMap() {
1565         this.vdata = 'vdata' + Math.floor(window$3.performance && window$3.performance.now() || Date.now());
1566         this.data = {};
1567       }
1569       var _proto = FakeWeakMap.prototype;
1571       _proto.set = function set(key, value) {
1572         var access = key[this.vdata] || newGUID();
1574         if (!key[this.vdata]) {
1575           key[this.vdata] = access;
1576         }
1578         this.data[access] = value;
1579         return this;
1580       };
1582       _proto.get = function get(key) {
1583         var access = key[this.vdata]; // we have data, return it
1585         if (access) {
1586           return this.data[access];
1587         } // we don't have data, return nothing.
1588         // return undefined explicitly as that's the contract for this method
1591         log('We have no data for this element', key);
1592         return undefined;
1593       };
1595       _proto.has = function has(key) {
1596         var access = key[this.vdata];
1597         return access in this.data;
1598       };
1600       _proto["delete"] = function _delete(key) {
1601         var access = key[this.vdata];
1603         if (access) {
1604           delete this.data[access];
1605           delete key[this.vdata];
1606         }
1607       };
1609       return FakeWeakMap;
1610     }();
1611   }
1612   /**
1613    * Element Data Store.
1614    *
1615    * Allows for binding data to an element without putting it directly on the
1616    * element. Ex. Event listeners are stored here.
1617    * (also from jsninja.com, slightly modified and updated for closure compiler)
1618    *
1619    * @type {Object}
1620    * @private
1621    */
1624   var DomData = window$3.WeakMap ? new WeakMap() : new FakeWeakMap();
1626   /**
1627    * @file events.js. An Event System (John Resig - Secrets of a JS Ninja http://jsninja.com/)
1628    * (Original book version wasn't completely usable, so fixed some things and made Closure Compiler compatible)
1629    * This should work very similarly to jQuery's events, however it's based off the book version which isn't as
1630    * robust as jquery's, so there's probably some differences.
1631    *
1632    * @file events.js
1633    * @module events
1634    */
1635   /**
1636    * Clean up the listener cache and dispatchers
1637    *
1638    * @param {Element|Object} elem
1639    *        Element to clean up
1640    *
1641    * @param {string} type
1642    *        Type of event to clean up
1643    */
1645   function _cleanUpEvents(elem, type) {
1646     if (!DomData.has(elem)) {
1647       return;
1648     }
1650     var data = DomData.get(elem); // Remove the events of a particular type if there are none left
1652     if (data.handlers[type].length === 0) {
1653       delete data.handlers[type]; // data.handlers[type] = null;
1654       // Setting to null was causing an error with data.handlers
1655       // Remove the meta-handler from the element
1657       if (elem.removeEventListener) {
1658         elem.removeEventListener(type, data.dispatcher, false);
1659       } else if (elem.detachEvent) {
1660         elem.detachEvent('on' + type, data.dispatcher);
1661       }
1662     } // Remove the events object if there are no types left
1665     if (Object.getOwnPropertyNames(data.handlers).length <= 0) {
1666       delete data.handlers;
1667       delete data.dispatcher;
1668       delete data.disabled;
1669     } // Finally remove the element data if there is no data left
1672     if (Object.getOwnPropertyNames(data).length === 0) {
1673       DomData["delete"](elem);
1674     }
1675   }
1676   /**
1677    * Loops through an array of event types and calls the requested method for each type.
1678    *
1679    * @param {Function} fn
1680    *        The event method we want to use.
1681    *
1682    * @param {Element|Object} elem
1683    *        Element or object to bind listeners to
1684    *
1685    * @param {string} type
1686    *        Type of event to bind to.
1687    *
1688    * @param {EventTarget~EventListener} callback
1689    *        Event listener.
1690    */
1693   function _handleMultipleEvents(fn, elem, types, callback) {
1694     types.forEach(function (type) {
1695       // Call the event method for each one of the types
1696       fn(elem, type, callback);
1697     });
1698   }
1699   /**
1700    * Fix a native event to have standard property values
1701    *
1702    * @param {Object} event
1703    *        Event object to fix.
1704    *
1705    * @return {Object}
1706    *         Fixed event object.
1707    */
1710   function fixEvent(event) {
1711     if (event.fixed_) {
1712       return event;
1713     }
1715     function returnTrue() {
1716       return true;
1717     }
1719     function returnFalse() {
1720       return false;
1721     } // Test if fixing up is needed
1722     // Used to check if !event.stopPropagation instead of isPropagationStopped
1723     // But native events return true for stopPropagation, but don't have
1724     // other expected methods like isPropagationStopped. Seems to be a problem
1725     // with the Javascript Ninja code. So we're just overriding all events now.
1728     if (!event || !event.isPropagationStopped) {
1729       var old = event || window$3.event;
1730       event = {}; // Clone the old object so that we can modify the values event = {};
1731       // IE8 Doesn't like when you mess with native event properties
1732       // Firefox returns false for event.hasOwnProperty('type') and other props
1733       //  which makes copying more difficult.
1734       // TODO: Probably best to create a whitelist of event props
1736       for (var key in old) {
1737         // Safari 6.0.3 warns you if you try to copy deprecated layerX/Y
1738         // Chrome warns you if you try to copy deprecated keyboardEvent.keyLocation
1739         // and webkitMovementX/Y
1740         if (key !== 'layerX' && key !== 'layerY' && key !== 'keyLocation' && key !== 'webkitMovementX' && key !== 'webkitMovementY') {
1741           // Chrome 32+ warns if you try to copy deprecated returnValue, but
1742           // we still want to if preventDefault isn't supported (IE8).
1743           if (!(key === 'returnValue' && old.preventDefault)) {
1744             event[key] = old[key];
1745           }
1746         }
1747       } // The event occurred on this element
1750       if (!event.target) {
1751         event.target = event.srcElement || document;
1752       } // Handle which other element the event is related to
1755       if (!event.relatedTarget) {
1756         event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
1757       } // Stop the default browser action
1760       event.preventDefault = function () {
1761         if (old.preventDefault) {
1762           old.preventDefault();
1763         }
1765         event.returnValue = false;
1766         old.returnValue = false;
1767         event.defaultPrevented = true;
1768       };
1770       event.defaultPrevented = false; // Stop the event from bubbling
1772       event.stopPropagation = function () {
1773         if (old.stopPropagation) {
1774           old.stopPropagation();
1775         }
1777         event.cancelBubble = true;
1778         old.cancelBubble = true;
1779         event.isPropagationStopped = returnTrue;
1780       };
1782       event.isPropagationStopped = returnFalse; // Stop the event from bubbling and executing other handlers
1784       event.stopImmediatePropagation = function () {
1785         if (old.stopImmediatePropagation) {
1786           old.stopImmediatePropagation();
1787         }
1789         event.isImmediatePropagationStopped = returnTrue;
1790         event.stopPropagation();
1791       };
1793       event.isImmediatePropagationStopped = returnFalse; // Handle mouse position
1795       if (event.clientX !== null && event.clientX !== undefined) {
1796         var doc = document.documentElement;
1797         var body = document.body;
1798         event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
1799         event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
1800       } // Handle key presses
1803       event.which = event.charCode || event.keyCode; // Fix button for mouse clicks:
1804       // 0 == left; 1 == middle; 2 == right
1806       if (event.button !== null && event.button !== undefined) {
1807         // The following is disabled because it does not pass videojs-standard
1808         // and... yikes.
1810         /* eslint-disable */
1811         event.button = event.button & 1 ? 0 : event.button & 4 ? 1 : event.button & 2 ? 2 : 0;
1812         /* eslint-enable */
1813       }
1814     }
1816     event.fixed_ = true; // Returns fixed-up instance
1818     return event;
1819   }
1820   /**
1821    * Whether passive event listeners are supported
1822    */
1824   var _supportsPassive;
1826   var supportsPassive = function supportsPassive() {
1827     if (typeof _supportsPassive !== 'boolean') {
1828       _supportsPassive = false;
1830       try {
1831         var opts = Object.defineProperty({}, 'passive', {
1832           get: function get() {
1833             _supportsPassive = true;
1834           }
1835         });
1836         window$3.addEventListener('test', null, opts);
1837         window$3.removeEventListener('test', null, opts);
1838       } catch (e) {// disregard
1839       }
1840     }
1842     return _supportsPassive;
1843   };
1844   /**
1845    * Touch events Chrome expects to be passive
1846    */
1849   var passiveEvents = ['touchstart', 'touchmove'];
1850   /**
1851    * Add an event listener to element
1852    * It stores the handler function in a separate cache object
1853    * and adds a generic handler to the element's event,
1854    * along with a unique id (guid) to the element.
1855    *
1856    * @param {Element|Object} elem
1857    *        Element or object to bind listeners to
1858    *
1859    * @param {string|string[]} type
1860    *        Type of event to bind to.
1861    *
1862    * @param {EventTarget~EventListener} fn
1863    *        Event listener.
1864    */
1866   function on(elem, type, fn) {
1867     if (Array.isArray(type)) {
1868       return _handleMultipleEvents(on, elem, type, fn);
1869     }
1871     if (!DomData.has(elem)) {
1872       DomData.set(elem, {});
1873     }
1875     var data = DomData.get(elem); // We need a place to store all our handler data
1877     if (!data.handlers) {
1878       data.handlers = {};
1879     }
1881     if (!data.handlers[type]) {
1882       data.handlers[type] = [];
1883     }
1885     if (!fn.guid) {
1886       fn.guid = newGUID();
1887     }
1889     data.handlers[type].push(fn);
1891     if (!data.dispatcher) {
1892       data.disabled = false;
1894       data.dispatcher = function (event, hash) {
1895         if (data.disabled) {
1896           return;
1897         }
1899         event = fixEvent(event);
1900         var handlers = data.handlers[event.type];
1902         if (handlers) {
1903           // Copy handlers so if handlers are added/removed during the process it doesn't throw everything off.
1904           var handlersCopy = handlers.slice(0);
1906           for (var m = 0, n = handlersCopy.length; m < n; m++) {
1907             if (event.isImmediatePropagationStopped()) {
1908               break;
1909             } else {
1910               try {
1911                 handlersCopy[m].call(elem, event, hash);
1912               } catch (e) {
1913                 log.error(e);
1914               }
1915             }
1916           }
1917         }
1918       };
1919     }
1921     if (data.handlers[type].length === 1) {
1922       if (elem.addEventListener) {
1923         var options = false;
1925         if (supportsPassive() && passiveEvents.indexOf(type) > -1) {
1926           options = {
1927             passive: true
1928           };
1929         }
1931         elem.addEventListener(type, data.dispatcher, options);
1932       } else if (elem.attachEvent) {
1933         elem.attachEvent('on' + type, data.dispatcher);
1934       }
1935     }
1936   }
1937   /**
1938    * Removes event listeners from an element
1939    *
1940    * @param {Element|Object} elem
1941    *        Object to remove listeners from.
1942    *
1943    * @param {string|string[]} [type]
1944    *        Type of listener to remove. Don't include to remove all events from element.
1945    *
1946    * @param {EventTarget~EventListener} [fn]
1947    *        Specific listener to remove. Don't include to remove listeners for an event
1948    *        type.
1949    */
1951   function off(elem, type, fn) {
1952     // Don't want to add a cache object through getElData if not needed
1953     if (!DomData.has(elem)) {
1954       return;
1955     }
1957     var data = DomData.get(elem); // If no events exist, nothing to unbind
1959     if (!data.handlers) {
1960       return;
1961     }
1963     if (Array.isArray(type)) {
1964       return _handleMultipleEvents(off, elem, type, fn);
1965     } // Utility function
1968     var removeType = function removeType(el, t) {
1969       data.handlers[t] = [];
1971       _cleanUpEvents(el, t);
1972     }; // Are we removing all bound events?
1975     if (type === undefined) {
1976       for (var t in data.handlers) {
1977         if (Object.prototype.hasOwnProperty.call(data.handlers || {}, t)) {
1978           removeType(elem, t);
1979         }
1980       }
1982       return;
1983     }
1985     var handlers = data.handlers[type]; // If no handlers exist, nothing to unbind
1987     if (!handlers) {
1988       return;
1989     } // If no listener was provided, remove all listeners for type
1992     if (!fn) {
1993       removeType(elem, type);
1994       return;
1995     } // We're only removing a single handler
1998     if (fn.guid) {
1999       for (var n = 0; n < handlers.length; n++) {
2000         if (handlers[n].guid === fn.guid) {
2001           handlers.splice(n--, 1);
2002         }
2003       }
2004     }
2006     _cleanUpEvents(elem, type);
2007   }
2008   /**
2009    * Trigger an event for an element
2010    *
2011    * @param {Element|Object} elem
2012    *        Element to trigger an event on
2013    *
2014    * @param {EventTarget~Event|string} event
2015    *        A string (the type) or an event object with a type attribute
2016    *
2017    * @param {Object} [hash]
2018    *        data hash to pass along with the event
2019    *
2020    * @return {boolean|undefined}
2021    *         Returns the opposite of `defaultPrevented` if default was
2022    *         prevented. Otherwise, returns `undefined`
2023    */
2025   function trigger(elem, event, hash) {
2026     // Fetches element data and a reference to the parent (for bubbling).
2027     // Don't want to add a data object to cache for every parent,
2028     // so checking hasElData first.
2029     var elemData = DomData.has(elem) ? DomData.get(elem) : {};
2030     var parent = elem.parentNode || elem.ownerDocument; // type = event.type || event,
2031     // handler;
2032     // If an event name was passed as a string, creates an event out of it
2034     if (typeof event === 'string') {
2035       event = {
2036         type: event,
2037         target: elem
2038       };
2039     } else if (!event.target) {
2040       event.target = elem;
2041     } // Normalizes the event properties.
2044     event = fixEvent(event); // If the passed element has a dispatcher, executes the established handlers.
2046     if (elemData.dispatcher) {
2047       elemData.dispatcher.call(elem, event, hash);
2048     } // Unless explicitly stopped or the event does not bubble (e.g. media events)
2049     // recursively calls this function to bubble the event up the DOM.
2052     if (parent && !event.isPropagationStopped() && event.bubbles === true) {
2053       trigger.call(null, parent, event, hash); // If at the top of the DOM, triggers the default action unless disabled.
2054     } else if (!parent && !event.defaultPrevented && event.target && event.target[event.type]) {
2055       if (!DomData.has(event.target)) {
2056         DomData.set(event.target, {});
2057       }
2059       var targetData = DomData.get(event.target); // Checks if the target has a default action for this event.
2061       if (event.target[event.type]) {
2062         // Temporarily disables event dispatching on the target as we have already executed the handler.
2063         targetData.disabled = true; // Executes the default action.
2065         if (typeof event.target[event.type] === 'function') {
2066           event.target[event.type]();
2067         } // Re-enables event dispatching.
2070         targetData.disabled = false;
2071       }
2072     } // Inform the triggerer if the default was prevented by returning false
2075     return !event.defaultPrevented;
2076   }
2077   /**
2078    * Trigger a listener only once for an event.
2079    *
2080    * @param {Element|Object} elem
2081    *        Element or object to bind to.
2082    *
2083    * @param {string|string[]} type
2084    *        Name/type of event
2085    *
2086    * @param {Event~EventListener} fn
2087    *        Event listener function
2088    */
2090   function one(elem, type, fn) {
2091     if (Array.isArray(type)) {
2092       return _handleMultipleEvents(one, elem, type, fn);
2093     }
2095     var func = function func() {
2096       off(elem, type, func);
2097       fn.apply(this, arguments);
2098     }; // copy the guid to the new function so it can removed using the original function's ID
2101     func.guid = fn.guid = fn.guid || newGUID();
2102     on(elem, type, func);
2103   }
2104   /**
2105    * Trigger a listener only once and then turn if off for all
2106    * configured events
2107    *
2108    * @param {Element|Object} elem
2109    *        Element or object to bind to.
2110    *
2111    * @param {string|string[]} type
2112    *        Name/type of event
2113    *
2114    * @param {Event~EventListener} fn
2115    *        Event listener function
2116    */
2118   function any(elem, type, fn) {
2119     var func = function func() {
2120       off(elem, type, func);
2121       fn.apply(this, arguments);
2122     }; // copy the guid to the new function so it can removed using the original function's ID
2125     func.guid = fn.guid = fn.guid || newGUID(); // multiple ons, but one off for everything
2127     on(elem, type, func);
2128   }
2130   var Events = /*#__PURE__*/Object.freeze({
2131     fixEvent: fixEvent,
2132     on: on,
2133     off: off,
2134     trigger: trigger,
2135     one: one,
2136     any: any
2137   });
2139   /**
2140    * @file fn.js
2141    * @module fn
2142    */
2143   var UPDATE_REFRESH_INTERVAL = 30;
2144   /**
2145    * Bind (a.k.a proxy or context). A simple method for changing the context of
2146    * a function.
2147    *
2148    * It also stores a unique id on the function so it can be easily removed from
2149    * events.
2150    *
2151    * @function
2152    * @param    {Mixed} context
2153    *           The object to bind as scope.
2154    *
2155    * @param    {Function} fn
2156    *           The function to be bound to a scope.
2157    *
2158    * @param    {number} [uid]
2159    *           An optional unique ID for the function to be set
2160    *
2161    * @return   {Function}
2162    *           The new function that will be bound into the context given
2163    */
2165   var bind = function bind(context, fn, uid) {
2166     // Make sure the function has a unique ID
2167     if (!fn.guid) {
2168       fn.guid = newGUID();
2169     } // Create the new function that changes the context
2172     var bound = fn.bind(context); // Allow for the ability to individualize this function
2173     // Needed in the case where multiple objects might share the same prototype
2174     // IF both items add an event listener with the same function, then you try to remove just one
2175     // it will remove both because they both have the same guid.
2176     // when using this, you need to use the bind method when you remove the listener as well.
2177     // currently used in text tracks
2179     bound.guid = uid ? uid + '_' + fn.guid : fn.guid;
2180     return bound;
2181   };
2182   /**
2183    * Wraps the given function, `fn`, with a new function that only invokes `fn`
2184    * at most once per every `wait` milliseconds.
2185    *
2186    * @function
2187    * @param    {Function} fn
2188    *           The function to be throttled.
2189    *
2190    * @param    {number}   wait
2191    *           The number of milliseconds by which to throttle.
2192    *
2193    * @return   {Function}
2194    */
2196   var throttle = function throttle(fn, wait) {
2197     var last = window$3.performance.now();
2199     var throttled = function throttled() {
2200       var now = window$3.performance.now();
2202       if (now - last >= wait) {
2203         fn.apply(void 0, arguments);
2204         last = now;
2205       }
2206     };
2208     return throttled;
2209   };
2210   /**
2211    * Creates a debounced function that delays invoking `func` until after `wait`
2212    * milliseconds have elapsed since the last time the debounced function was
2213    * invoked.
2214    *
2215    * Inspired by lodash and underscore implementations.
2216    *
2217    * @function
2218    * @param    {Function} func
2219    *           The function to wrap with debounce behavior.
2220    *
2221    * @param    {number} wait
2222    *           The number of milliseconds to wait after the last invocation.
2223    *
2224    * @param    {boolean} [immediate]
2225    *           Whether or not to invoke the function immediately upon creation.
2226    *
2227    * @param    {Object} [context=window]
2228    *           The "context" in which the debounced function should debounce. For
2229    *           example, if this function should be tied to a Video.js player,
2230    *           the player can be passed here. Alternatively, defaults to the
2231    *           global `window` object.
2232    *
2233    * @return   {Function}
2234    *           A debounced function.
2235    */
2237   var debounce = function debounce(func, wait, immediate, context) {
2238     if (context === void 0) {
2239       context = window$3;
2240     }
2242     var timeout;
2244     var cancel = function cancel() {
2245       context.clearTimeout(timeout);
2246       timeout = null;
2247     };
2248     /* eslint-disable consistent-this */
2251     var debounced = function debounced() {
2252       var self = this;
2253       var args = arguments;
2255       var _later = function later() {
2256         timeout = null;
2257         _later = null;
2259         if (!immediate) {
2260           func.apply(self, args);
2261         }
2262       };
2264       if (!timeout && immediate) {
2265         func.apply(self, args);
2266       }
2268       context.clearTimeout(timeout);
2269       timeout = context.setTimeout(_later, wait);
2270     };
2271     /* eslint-enable consistent-this */
2274     debounced.cancel = cancel;
2275     return debounced;
2276   };
2278   /**
2279    * @file src/js/event-target.js
2280    */
2281   /**
2282    * `EventTarget` is a class that can have the same API as the DOM `EventTarget`. It
2283    * adds shorthand functions that wrap around lengthy functions. For example:
2284    * the `on` function is a wrapper around `addEventListener`.
2285    *
2286    * @see [EventTarget Spec]{@link https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget}
2287    * @class EventTarget
2288    */
2290   var EventTarget = function EventTarget() {};
2291   /**
2292    * A Custom DOM event.
2293    *
2294    * @typedef {Object} EventTarget~Event
2295    * @see [Properties]{@link https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent}
2296    */
2298   /**
2299    * All event listeners should follow the following format.
2300    *
2301    * @callback EventTarget~EventListener
2302    * @this {EventTarget}
2303    *
2304    * @param {EventTarget~Event} event
2305    *        the event that triggered this function
2306    *
2307    * @param {Object} [hash]
2308    *        hash of data sent during the event
2309    */
2311   /**
2312    * An object containing event names as keys and booleans as values.
2313    *
2314    * > NOTE: If an event name is set to a true value here {@link EventTarget#trigger}
2315    *         will have extra functionality. See that function for more information.
2316    *
2317    * @property EventTarget.prototype.allowedEvents_
2318    * @private
2319    */
2322   EventTarget.prototype.allowedEvents_ = {};
2323   /**
2324    * Adds an `event listener` to an instance of an `EventTarget`. An `event listener` is a
2325    * function that will get called when an event with a certain name gets triggered.
2326    *
2327    * @param {string|string[]} type
2328    *        An event name or an array of event names.
2329    *
2330    * @param {EventTarget~EventListener} fn
2331    *        The function to call with `EventTarget`s
2332    */
2334   EventTarget.prototype.on = function (type, fn) {
2335     // Remove the addEventListener alias before calling Events.on
2336     // so we don't get into an infinite type loop
2337     var ael = this.addEventListener;
2339     this.addEventListener = function () {};
2341     on(this, type, fn);
2342     this.addEventListener = ael;
2343   };
2344   /**
2345    * An alias of {@link EventTarget#on}. Allows `EventTarget` to mimic
2346    * the standard DOM API.
2347    *
2348    * @function
2349    * @see {@link EventTarget#on}
2350    */
2353   EventTarget.prototype.addEventListener = EventTarget.prototype.on;
2354   /**
2355    * Removes an `event listener` for a specific event from an instance of `EventTarget`.
2356    * This makes it so that the `event listener` will no longer get called when the
2357    * named event happens.
2358    *
2359    * @param {string|string[]} type
2360    *        An event name or an array of event names.
2361    *
2362    * @param {EventTarget~EventListener} fn
2363    *        The function to remove.
2364    */
2366   EventTarget.prototype.off = function (type, fn) {
2367     off(this, type, fn);
2368   };
2369   /**
2370    * An alias of {@link EventTarget#off}. Allows `EventTarget` to mimic
2371    * the standard DOM API.
2372    *
2373    * @function
2374    * @see {@link EventTarget#off}
2375    */
2378   EventTarget.prototype.removeEventListener = EventTarget.prototype.off;
2379   /**
2380    * This function will add an `event listener` that gets triggered only once. After the
2381    * first trigger it will get removed. This is like adding an `event listener`
2382    * with {@link EventTarget#on} that calls {@link EventTarget#off} on itself.
2383    *
2384    * @param {string|string[]} type
2385    *        An event name or an array of event names.
2386    *
2387    * @param {EventTarget~EventListener} fn
2388    *        The function to be called once for each event name.
2389    */
2391   EventTarget.prototype.one = function (type, fn) {
2392     // Remove the addEventListener aliasing Events.on
2393     // so we don't get into an infinite type loop
2394     var ael = this.addEventListener;
2396     this.addEventListener = function () {};
2398     one(this, type, fn);
2399     this.addEventListener = ael;
2400   };
2402   EventTarget.prototype.any = function (type, fn) {
2403     // Remove the addEventListener aliasing Events.on
2404     // so we don't get into an infinite type loop
2405     var ael = this.addEventListener;
2407     this.addEventListener = function () {};
2409     any(this, type, fn);
2410     this.addEventListener = ael;
2411   };
2412   /**
2413    * This function causes an event to happen. This will then cause any `event listeners`
2414    * that are waiting for that event, to get called. If there are no `event listeners`
2415    * for an event then nothing will happen.
2416    *
2417    * If the name of the `Event` that is being triggered is in `EventTarget.allowedEvents_`.
2418    * Trigger will also call the `on` + `uppercaseEventName` function.
2419    *
2420    * Example:
2421    * 'click' is in `EventTarget.allowedEvents_`, so, trigger will attempt to call
2422    * `onClick` if it exists.
2423    *
2424    * @param {string|EventTarget~Event|Object} event
2425    *        The name of the event, an `Event`, or an object with a key of type set to
2426    *        an event name.
2427    */
2430   EventTarget.prototype.trigger = function (event) {
2431     var type = event.type || event; // deprecation
2432     // In a future version we should default target to `this`
2433     // similar to how we default the target to `elem` in
2434     // `Events.trigger`. Right now the default `target` will be
2435     // `document` due to the `Event.fixEvent` call.
2437     if (typeof event === 'string') {
2438       event = {
2439         type: type
2440       };
2441     }
2443     event = fixEvent(event);
2445     if (this.allowedEvents_[type] && this['on' + type]) {
2446       this['on' + type](event);
2447     }
2449     trigger(this, event);
2450   };
2451   /**
2452    * An alias of {@link EventTarget#trigger}. Allows `EventTarget` to mimic
2453    * the standard DOM API.
2454    *
2455    * @function
2456    * @see {@link EventTarget#trigger}
2457    */
2460   EventTarget.prototype.dispatchEvent = EventTarget.prototype.trigger;
2461   var EVENT_MAP;
2463   EventTarget.prototype.queueTrigger = function (event) {
2464     var _this = this;
2466     // only set up EVENT_MAP if it'll be used
2467     if (!EVENT_MAP) {
2468       EVENT_MAP = new Map();
2469     }
2471     var type = event.type || event;
2472     var map = EVENT_MAP.get(this);
2474     if (!map) {
2475       map = new Map();
2476       EVENT_MAP.set(this, map);
2477     }
2479     var oldTimeout = map.get(type);
2480     map["delete"](type);
2481     window$3.clearTimeout(oldTimeout);
2482     var timeout = window$3.setTimeout(function () {
2483       // if we cleared out all timeouts for the current target, delete its map
2484       if (map.size === 0) {
2485         map = null;
2486         EVENT_MAP["delete"](_this);
2487       }
2489       _this.trigger(event);
2490     }, 0);
2491     map.set(type, timeout);
2492   };
2494   /**
2495    * @file mixins/evented.js
2496    * @module evented
2497    */
2498   /**
2499    * Returns whether or not an object has had the evented mixin applied.
2500    *
2501    * @param  {Object} object
2502    *         An object to test.
2503    *
2504    * @return {boolean}
2505    *         Whether or not the object appears to be evented.
2506    */
2508   var isEvented = function isEvented(object) {
2509     return object instanceof EventTarget || !!object.eventBusEl_ && ['on', 'one', 'off', 'trigger'].every(function (k) {
2510       return typeof object[k] === 'function';
2511     });
2512   };
2513   /**
2514    * Adds a callback to run after the evented mixin applied.
2515    *
2516    * @param  {Object} object
2517    *         An object to Add
2518    * @param  {Function} callback
2519    *         The callback to run.
2520    */
2523   var addEventedCallback = function addEventedCallback(target, callback) {
2524     if (isEvented(target)) {
2525       callback();
2526     } else {
2527       if (!target.eventedCallbacks) {
2528         target.eventedCallbacks = [];
2529       }
2531       target.eventedCallbacks.push(callback);
2532     }
2533   };
2534   /**
2535    * Whether a value is a valid event type - non-empty string or array.
2536    *
2537    * @private
2538    * @param  {string|Array} type
2539    *         The type value to test.
2540    *
2541    * @return {boolean}
2542    *         Whether or not the type is a valid event type.
2543    */
2546   var isValidEventType = function isValidEventType(type) {
2547     return (// The regex here verifies that the `type` contains at least one non-
2548       // whitespace character.
2549       typeof type === 'string' && /\S/.test(type) || Array.isArray(type) && !!type.length
2550     );
2551   };
2552   /**
2553    * Validates a value to determine if it is a valid event target. Throws if not.
2554    *
2555    * @private
2556    * @throws {Error}
2557    *         If the target does not appear to be a valid event target.
2558    *
2559    * @param  {Object} target
2560    *         The object to test.
2561    */
2564   var validateTarget = function validateTarget(target) {
2565     if (!target.nodeName && !isEvented(target)) {
2566       throw new Error('Invalid target; must be a DOM node or evented object.');
2567     }
2568   };
2569   /**
2570    * Validates a value to determine if it is a valid event target. Throws if not.
2571    *
2572    * @private
2573    * @throws {Error}
2574    *         If the type does not appear to be a valid event type.
2575    *
2576    * @param  {string|Array} type
2577    *         The type to test.
2578    */
2581   var validateEventType = function validateEventType(type) {
2582     if (!isValidEventType(type)) {
2583       throw new Error('Invalid event type; must be a non-empty string or array.');
2584     }
2585   };
2586   /**
2587    * Validates a value to determine if it is a valid listener. Throws if not.
2588    *
2589    * @private
2590    * @throws {Error}
2591    *         If the listener is not a function.
2592    *
2593    * @param  {Function} listener
2594    *         The listener to test.
2595    */
2598   var validateListener = function validateListener(listener) {
2599     if (typeof listener !== 'function') {
2600       throw new Error('Invalid listener; must be a function.');
2601     }
2602   };
2603   /**
2604    * Takes an array of arguments given to `on()` or `one()`, validates them, and
2605    * normalizes them into an object.
2606    *
2607    * @private
2608    * @param  {Object} self
2609    *         The evented object on which `on()` or `one()` was called. This
2610    *         object will be bound as the `this` value for the listener.
2611    *
2612    * @param  {Array} args
2613    *         An array of arguments passed to `on()` or `one()`.
2614    *
2615    * @return {Object}
2616    *         An object containing useful values for `on()` or `one()` calls.
2617    */
2620   var normalizeListenArgs = function normalizeListenArgs(self, args) {
2621     // If the number of arguments is less than 3, the target is always the
2622     // evented object itself.
2623     var isTargetingSelf = args.length < 3 || args[0] === self || args[0] === self.eventBusEl_;
2624     var target;
2625     var type;
2626     var listener;
2628     if (isTargetingSelf) {
2629       target = self.eventBusEl_; // Deal with cases where we got 3 arguments, but we are still listening to
2630       // the evented object itself.
2632       if (args.length >= 3) {
2633         args.shift();
2634       }
2636       type = args[0];
2637       listener = args[1];
2638     } else {
2639       target = args[0];
2640       type = args[1];
2641       listener = args[2];
2642     }
2644     validateTarget(target);
2645     validateEventType(type);
2646     validateListener(listener);
2647     listener = bind(self, listener);
2648     return {
2649       isTargetingSelf: isTargetingSelf,
2650       target: target,
2651       type: type,
2652       listener: listener
2653     };
2654   };
2655   /**
2656    * Adds the listener to the event type(s) on the target, normalizing for
2657    * the type of target.
2658    *
2659    * @private
2660    * @param  {Element|Object} target
2661    *         A DOM node or evented object.
2662    *
2663    * @param  {string} method
2664    *         The event binding method to use ("on" or "one").
2665    *
2666    * @param  {string|Array} type
2667    *         One or more event type(s).
2668    *
2669    * @param  {Function} listener
2670    *         A listener function.
2671    */
2674   var listen = function listen(target, method, type, listener) {
2675     validateTarget(target);
2677     if (target.nodeName) {
2678       Events[method](target, type, listener);
2679     } else {
2680       target[method](type, listener);
2681     }
2682   };
2683   /**
2684    * Contains methods that provide event capabilities to an object which is passed
2685    * to {@link module:evented|evented}.
2686    *
2687    * @mixin EventedMixin
2688    */
2691   var EventedMixin = {
2692     /**
2693      * Add a listener to an event (or events) on this object or another evented
2694      * object.
2695      *
2696      * @param  {string|Array|Element|Object} targetOrType
2697      *         If this is a string or array, it represents the event type(s)
2698      *         that will trigger the listener.
2699      *
2700      *         Another evented object can be passed here instead, which will
2701      *         cause the listener to listen for events on _that_ object.
2702      *
2703      *         In either case, the listener's `this` value will be bound to
2704      *         this object.
2705      *
2706      * @param  {string|Array|Function} typeOrListener
2707      *         If the first argument was a string or array, this should be the
2708      *         listener function. Otherwise, this is a string or array of event
2709      *         type(s).
2710      *
2711      * @param  {Function} [listener]
2712      *         If the first argument was another evented object, this will be
2713      *         the listener function.
2714      */
2715     on: function on() {
2716       var _this = this;
2718       for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
2719         args[_key] = arguments[_key];
2720       }
2722       var _normalizeListenArgs = normalizeListenArgs(this, args),
2723           isTargetingSelf = _normalizeListenArgs.isTargetingSelf,
2724           target = _normalizeListenArgs.target,
2725           type = _normalizeListenArgs.type,
2726           listener = _normalizeListenArgs.listener;
2728       listen(target, 'on', type, listener); // If this object is listening to another evented object.
2730       if (!isTargetingSelf) {
2731         // If this object is disposed, remove the listener.
2732         var removeListenerOnDispose = function removeListenerOnDispose() {
2733           return _this.off(target, type, listener);
2734         }; // Use the same function ID as the listener so we can remove it later it
2735         // using the ID of the original listener.
2738         removeListenerOnDispose.guid = listener.guid; // Add a listener to the target's dispose event as well. This ensures
2739         // that if the target is disposed BEFORE this object, we remove the
2740         // removal listener that was just added. Otherwise, we create a memory leak.
2742         var removeRemoverOnTargetDispose = function removeRemoverOnTargetDispose() {
2743           return _this.off('dispose', removeListenerOnDispose);
2744         }; // Use the same function ID as the listener so we can remove it later
2745         // it using the ID of the original listener.
2748         removeRemoverOnTargetDispose.guid = listener.guid;
2749         listen(this, 'on', 'dispose', removeListenerOnDispose);
2750         listen(target, 'on', 'dispose', removeRemoverOnTargetDispose);
2751       }
2752     },
2754     /**
2755      * Add a listener to an event (or events) on this object or another evented
2756      * object. The listener will be called once per event and then removed.
2757      *
2758      * @param  {string|Array|Element|Object} targetOrType
2759      *         If this is a string or array, it represents the event type(s)
2760      *         that will trigger the listener.
2761      *
2762      *         Another evented object can be passed here instead, which will
2763      *         cause the listener to listen for events on _that_ object.
2764      *
2765      *         In either case, the listener's `this` value will be bound to
2766      *         this object.
2767      *
2768      * @param  {string|Array|Function} typeOrListener
2769      *         If the first argument was a string or array, this should be the
2770      *         listener function. Otherwise, this is a string or array of event
2771      *         type(s).
2772      *
2773      * @param  {Function} [listener]
2774      *         If the first argument was another evented object, this will be
2775      *         the listener function.
2776      */
2777     one: function one() {
2778       var _this2 = this;
2780       for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
2781         args[_key2] = arguments[_key2];
2782       }
2784       var _normalizeListenArgs2 = normalizeListenArgs(this, args),
2785           isTargetingSelf = _normalizeListenArgs2.isTargetingSelf,
2786           target = _normalizeListenArgs2.target,
2787           type = _normalizeListenArgs2.type,
2788           listener = _normalizeListenArgs2.listener; // Targeting this evented object.
2791       if (isTargetingSelf) {
2792         listen(target, 'one', type, listener); // Targeting another evented object.
2793       } else {
2794         // TODO: This wrapper is incorrect! It should only
2795         //       remove the wrapper for the event type that called it.
2796         //       Instead all listners are removed on the first trigger!
2797         //       see https://github.com/videojs/video.js/issues/5962
2798         var wrapper = function wrapper() {
2799           _this2.off(target, type, wrapper);
2801           for (var _len3 = arguments.length, largs = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
2802             largs[_key3] = arguments[_key3];
2803           }
2805           listener.apply(null, largs);
2806         }; // Use the same function ID as the listener so we can remove it later
2807         // it using the ID of the original listener.
2810         wrapper.guid = listener.guid;
2811         listen(target, 'one', type, wrapper);
2812       }
2813     },
2815     /**
2816      * Add a listener to an event (or events) on this object or another evented
2817      * object. The listener will only be called once for the first event that is triggered
2818      * then removed.
2819      *
2820      * @param  {string|Array|Element|Object} targetOrType
2821      *         If this is a string or array, it represents the event type(s)
2822      *         that will trigger the listener.
2823      *
2824      *         Another evented object can be passed here instead, which will
2825      *         cause the listener to listen for events on _that_ object.
2826      *
2827      *         In either case, the listener's `this` value will be bound to
2828      *         this object.
2829      *
2830      * @param  {string|Array|Function} typeOrListener
2831      *         If the first argument was a string or array, this should be the
2832      *         listener function. Otherwise, this is a string or array of event
2833      *         type(s).
2834      *
2835      * @param  {Function} [listener]
2836      *         If the first argument was another evented object, this will be
2837      *         the listener function.
2838      */
2839     any: function any() {
2840       var _this3 = this;
2842       for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
2843         args[_key4] = arguments[_key4];
2844       }
2846       var _normalizeListenArgs3 = normalizeListenArgs(this, args),
2847           isTargetingSelf = _normalizeListenArgs3.isTargetingSelf,
2848           target = _normalizeListenArgs3.target,
2849           type = _normalizeListenArgs3.type,
2850           listener = _normalizeListenArgs3.listener; // Targeting this evented object.
2853       if (isTargetingSelf) {
2854         listen(target, 'any', type, listener); // Targeting another evented object.
2855       } else {
2856         var wrapper = function wrapper() {
2857           _this3.off(target, type, wrapper);
2859           for (var _len5 = arguments.length, largs = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
2860             largs[_key5] = arguments[_key5];
2861           }
2863           listener.apply(null, largs);
2864         }; // Use the same function ID as the listener so we can remove it later
2865         // it using the ID of the original listener.
2868         wrapper.guid = listener.guid;
2869         listen(target, 'any', type, wrapper);
2870       }
2871     },
2873     /**
2874      * Removes listener(s) from event(s) on an evented object.
2875      *
2876      * @param  {string|Array|Element|Object} [targetOrType]
2877      *         If this is a string or array, it represents the event type(s).
2878      *
2879      *         Another evented object can be passed here instead, in which case
2880      *         ALL 3 arguments are _required_.
2881      *
2882      * @param  {string|Array|Function} [typeOrListener]
2883      *         If the first argument was a string or array, this may be the
2884      *         listener function. Otherwise, this is a string or array of event
2885      *         type(s).
2886      *
2887      * @param  {Function} [listener]
2888      *         If the first argument was another evented object, this will be
2889      *         the listener function; otherwise, _all_ listeners bound to the
2890      *         event type(s) will be removed.
2891      */
2892     off: function off$1(targetOrType, typeOrListener, listener) {
2893       // Targeting this evented object.
2894       if (!targetOrType || isValidEventType(targetOrType)) {
2895         off(this.eventBusEl_, targetOrType, typeOrListener); // Targeting another evented object.
2896       } else {
2897         var target = targetOrType;
2898         var type = typeOrListener; // Fail fast and in a meaningful way!
2900         validateTarget(target);
2901         validateEventType(type);
2902         validateListener(listener); // Ensure there's at least a guid, even if the function hasn't been used
2904         listener = bind(this, listener); // Remove the dispose listener on this evented object, which was given
2905         // the same guid as the event listener in on().
2907         this.off('dispose', listener);
2909         if (target.nodeName) {
2910           off(target, type, listener);
2911           off(target, 'dispose', listener);
2912         } else if (isEvented(target)) {
2913           target.off(type, listener);
2914           target.off('dispose', listener);
2915         }
2916       }
2917     },
2919     /**
2920      * Fire an event on this evented object, causing its listeners to be called.
2921      *
2922      * @param   {string|Object} event
2923      *          An event type or an object with a type property.
2924      *
2925      * @param   {Object} [hash]
2926      *          An additional object to pass along to listeners.
2927      *
2928      * @return {boolean}
2929      *          Whether or not the default behavior was prevented.
2930      */
2931     trigger: function trigger$1(event, hash) {
2932       return trigger(this.eventBusEl_, event, hash);
2933     }
2934   };
2935   /**
2936    * Applies {@link module:evented~EventedMixin|EventedMixin} to a target object.
2937    *
2938    * @param  {Object} target
2939    *         The object to which to add event methods.
2940    *
2941    * @param  {Object} [options={}]
2942    *         Options for customizing the mixin behavior.
2943    *
2944    * @param  {string} [options.eventBusKey]
2945    *         By default, adds a `eventBusEl_` DOM element to the target object,
2946    *         which is used as an event bus. If the target object already has a
2947    *         DOM element that should be used, pass its key here.
2948    *
2949    * @return {Object}
2950    *         The target object.
2951    */
2953   function evented(target, options) {
2954     if (options === void 0) {
2955       options = {};
2956     }
2958     var _options = options,
2959         eventBusKey = _options.eventBusKey; // Set or create the eventBusEl_.
2961     if (eventBusKey) {
2962       if (!target[eventBusKey].nodeName) {
2963         throw new Error("The eventBusKey \"" + eventBusKey + "\" does not refer to an element.");
2964       }
2966       target.eventBusEl_ = target[eventBusKey];
2967     } else {
2968       target.eventBusEl_ = createEl('span', {
2969         className: 'vjs-event-bus'
2970       });
2971     }
2973     assign(target, EventedMixin);
2975     if (target.eventedCallbacks) {
2976       target.eventedCallbacks.forEach(function (callback) {
2977         callback();
2978       });
2979     } // When any evented object is disposed, it removes all its listeners.
2982     target.on('dispose', function () {
2983       target.off();
2984       window$3.setTimeout(function () {
2985         target.eventBusEl_ = null;
2986       }, 0);
2987     });
2988     return target;
2989   }
2991   /**
2992    * @file mixins/stateful.js
2993    * @module stateful
2994    */
2995   /**
2996    * Contains methods that provide statefulness to an object which is passed
2997    * to {@link module:stateful}.
2998    *
2999    * @mixin StatefulMixin
3000    */
3002   var StatefulMixin = {
3003     /**
3004      * A hash containing arbitrary keys and values representing the state of
3005      * the object.
3006      *
3007      * @type {Object}
3008      */
3009     state: {},
3011     /**
3012      * Set the state of an object by mutating its
3013      * {@link module:stateful~StatefulMixin.state|state} object in place.
3014      *
3015      * @fires   module:stateful~StatefulMixin#statechanged
3016      * @param   {Object|Function} stateUpdates
3017      *          A new set of properties to shallow-merge into the plugin state.
3018      *          Can be a plain object or a function returning a plain object.
3019      *
3020      * @return {Object|undefined}
3021      *          An object containing changes that occurred. If no changes
3022      *          occurred, returns `undefined`.
3023      */
3024     setState: function setState(stateUpdates) {
3025       var _this = this;
3027       // Support providing the `stateUpdates` state as a function.
3028       if (typeof stateUpdates === 'function') {
3029         stateUpdates = stateUpdates();
3030       }
3032       var changes;
3033       each(stateUpdates, function (value, key) {
3034         // Record the change if the value is different from what's in the
3035         // current state.
3036         if (_this.state[key] !== value) {
3037           changes = changes || {};
3038           changes[key] = {
3039             from: _this.state[key],
3040             to: value
3041           };
3042         }
3044         _this.state[key] = value;
3045       }); // Only trigger "statechange" if there were changes AND we have a trigger
3046       // function. This allows us to not require that the target object be an
3047       // evented object.
3049       if (changes && isEvented(this)) {
3050         /**
3051          * An event triggered on an object that is both
3052          * {@link module:stateful|stateful} and {@link module:evented|evented}
3053          * indicating that its state has changed.
3054          *
3055          * @event    module:stateful~StatefulMixin#statechanged
3056          * @type     {Object}
3057          * @property {Object} changes
3058          *           A hash containing the properties that were changed and
3059          *           the values they were changed `from` and `to`.
3060          */
3061         this.trigger({
3062           changes: changes,
3063           type: 'statechanged'
3064         });
3065       }
3067       return changes;
3068     }
3069   };
3070   /**
3071    * Applies {@link module:stateful~StatefulMixin|StatefulMixin} to a target
3072    * object.
3073    *
3074    * If the target object is {@link module:evented|evented} and has a
3075    * `handleStateChanged` method, that method will be automatically bound to the
3076    * `statechanged` event on itself.
3077    *
3078    * @param   {Object} target
3079    *          The object to be made stateful.
3080    *
3081    * @param   {Object} [defaultState]
3082    *          A default set of properties to populate the newly-stateful object's
3083    *          `state` property.
3084    *
3085    * @return {Object}
3086    *          Returns the `target`.
3087    */
3089   function stateful(target, defaultState) {
3090     assign(target, StatefulMixin); // This happens after the mixing-in because we need to replace the `state`
3091     // added in that step.
3093     target.state = assign({}, target.state, defaultState); // Auto-bind the `handleStateChanged` method of the target object if it exists.
3095     if (typeof target.handleStateChanged === 'function' && isEvented(target)) {
3096       target.on('statechanged', target.handleStateChanged);
3097     }
3099     return target;
3100   }
3102   /**
3103    * @file string-cases.js
3104    * @module to-lower-case
3105    */
3107   /**
3108    * Lowercase the first letter of a string.
3109    *
3110    * @param {string} string
3111    *        String to be lowercased
3112    *
3113    * @return {string}
3114    *         The string with a lowercased first letter
3115    */
3116   var toLowerCase = function toLowerCase(string) {
3117     if (typeof string !== 'string') {
3118       return string;
3119     }
3121     return string.replace(/./, function (w) {
3122       return w.toLowerCase();
3123     });
3124   };
3125   /**
3126    * Uppercase the first letter of a string.
3127    *
3128    * @param {string} string
3129    *        String to be uppercased
3130    *
3131    * @return {string}
3132    *         The string with an uppercased first letter
3133    */
3135   var toTitleCase = function toTitleCase(string) {
3136     if (typeof string !== 'string') {
3137       return string;
3138     }
3140     return string.replace(/./, function (w) {
3141       return w.toUpperCase();
3142     });
3143   };
3144   /**
3145    * Compares the TitleCase versions of the two strings for equality.
3146    *
3147    * @param {string} str1
3148    *        The first string to compare
3149    *
3150    * @param {string} str2
3151    *        The second string to compare
3152    *
3153    * @return {boolean}
3154    *         Whether the TitleCase versions of the strings are equal
3155    */
3157   var titleCaseEquals = function titleCaseEquals(str1, str2) {
3158     return toTitleCase(str1) === toTitleCase(str2);
3159   };
3161   /**
3162    * @file merge-options.js
3163    * @module merge-options
3164    */
3165   /**
3166    * Merge two objects recursively.
3167    *
3168    * Performs a deep merge like
3169    * {@link https://lodash.com/docs/4.17.10#merge|lodash.merge}, but only merges
3170    * plain objects (not arrays, elements, or anything else).
3171    *
3172    * Non-plain object values will be copied directly from the right-most
3173    * argument.
3174    *
3175    * @static
3176    * @param   {Object[]} sources
3177    *          One or more objects to merge into a new object.
3178    *
3179    * @return {Object}
3180    *          A new object that is the merged result of all sources.
3181    */
3183   function mergeOptions() {
3184     var result = {};
3186     for (var _len = arguments.length, sources = new Array(_len), _key = 0; _key < _len; _key++) {
3187       sources[_key] = arguments[_key];
3188     }
3190     sources.forEach(function (source) {
3191       if (!source) {
3192         return;
3193       }
3195       each(source, function (value, key) {
3196         if (!isPlain(value)) {
3197           result[key] = value;
3198           return;
3199         }
3201         if (!isPlain(result[key])) {
3202           result[key] = {};
3203         }
3205         result[key] = mergeOptions(result[key], value);
3206       });
3207     });
3208     return result;
3209   }
3211   /**
3212    * Player Component - Base class for all UI objects
3213    *
3214    * @file component.js
3215    */
3216   /**
3217    * Base class for all UI Components.
3218    * Components are UI objects which represent both a javascript object and an element
3219    * in the DOM. They can be children of other components, and can have
3220    * children themselves.
3221    *
3222    * Components can also use methods from {@link EventTarget}
3223    */
3225   var Component = /*#__PURE__*/function () {
3226     /**
3227      * A callback that is called when a component is ready. Does not have any
3228      * paramters and any callback value will be ignored.
3229      *
3230      * @callback Component~ReadyCallback
3231      * @this Component
3232      */
3234     /**
3235      * Creates an instance of this class.
3236      *
3237      * @param {Player} player
3238      *        The `Player` that this class should be attached to.
3239      *
3240      * @param {Object} [options]
3241      *        The key/value store of player options.
3242      *
3243      * @param {Object[]} [options.children]
3244      *        An array of children objects to intialize this component with. Children objects have
3245      *        a name property that will be used if more than one component of the same type needs to be
3246      *        added.
3247      *
3248      * @param {Component~ReadyCallback} [ready]
3249      *        Function that gets called when the `Component` is ready.
3250      */
3251     function Component(player, options, ready) {
3252       // The component might be the player itself and we can't pass `this` to super
3253       if (!player && this.play) {
3254         this.player_ = player = this; // eslint-disable-line
3255       } else {
3256         this.player_ = player;
3257       }
3259       this.isDisposed_ = false; // Hold the reference to the parent component via `addChild` method
3261       this.parentComponent_ = null; // Make a copy of prototype.options_ to protect against overriding defaults
3263       this.options_ = mergeOptions({}, this.options_); // Updated options with supplied options
3265       options = this.options_ = mergeOptions(this.options_, options); // Get ID from options or options element if one is supplied
3267       this.id_ = options.id || options.el && options.el.id; // If there was no ID from the options, generate one
3269       if (!this.id_) {
3270         // Don't require the player ID function in the case of mock players
3271         var id = player && player.id && player.id() || 'no_player';
3272         this.id_ = id + "_component_" + newGUID();
3273       }
3275       this.name_ = options.name || null; // Create element if one wasn't provided in options
3277       if (options.el) {
3278         this.el_ = options.el;
3279       } else if (options.createEl !== false) {
3280         this.el_ = this.createEl();
3281       } // if evented is anything except false, we want to mixin in evented
3284       if (options.evented !== false) {
3285         // Make this an evented object and use `el_`, if available, as its event bus
3286         evented(this, {
3287           eventBusKey: this.el_ ? 'el_' : null
3288         });
3289       }
3291       stateful(this, this.constructor.defaultState);
3292       this.children_ = [];
3293       this.childIndex_ = {};
3294       this.childNameIndex_ = {};
3295       var SetSham;
3297       if (!window$3.Set) {
3298         SetSham = /*#__PURE__*/function () {
3299           function SetSham() {
3300             this.set_ = {};
3301           }
3303           var _proto2 = SetSham.prototype;
3305           _proto2.has = function has(key) {
3306             return key in this.set_;
3307           };
3309           _proto2["delete"] = function _delete(key) {
3310             var has = this.has(key);
3311             delete this.set_[key];
3312             return has;
3313           };
3315           _proto2.add = function add(key) {
3316             this.set_[key] = 1;
3317             return this;
3318           };
3320           _proto2.forEach = function forEach(callback, thisArg) {
3321             for (var key in this.set_) {
3322               callback.call(thisArg, key, key, this);
3323             }
3324           };
3326           return SetSham;
3327         }();
3328       }
3330       this.setTimeoutIds_ = window$3.Set ? new Set() : new SetSham();
3331       this.setIntervalIds_ = window$3.Set ? new Set() : new SetSham();
3332       this.rafIds_ = window$3.Set ? new Set() : new SetSham();
3333       this.clearingTimersOnDispose_ = false; // Add any child components in options
3335       if (options.initChildren !== false) {
3336         this.initChildren();
3337       }
3339       this.ready(ready); // Don't want to trigger ready here or it will before init is actually
3340       // finished for all children that run this constructor
3342       if (options.reportTouchActivity !== false) {
3343         this.enableTouchActivity();
3344       }
3345     }
3346     /**
3347      * Dispose of the `Component` and all child components.
3348      *
3349      * @fires Component#dispose
3350      */
3353     var _proto = Component.prototype;
3355     _proto.dispose = function dispose() {
3356       // Bail out if the component has already been disposed.
3357       if (this.isDisposed_) {
3358         return;
3359       }
3360       /**
3361        * Triggered when a `Component` is disposed.
3362        *
3363        * @event Component#dispose
3364        * @type {EventTarget~Event}
3365        *
3366        * @property {boolean} [bubbles=false]
3367        *           set to false so that the dispose event does not
3368        *           bubble up
3369        */
3372       this.trigger({
3373         type: 'dispose',
3374         bubbles: false
3375       });
3376       this.isDisposed_ = true; // Dispose all children.
3378       if (this.children_) {
3379         for (var i = this.children_.length - 1; i >= 0; i--) {
3380           if (this.children_[i].dispose) {
3381             this.children_[i].dispose();
3382           }
3383         }
3384       } // Delete child references
3387       this.children_ = null;
3388       this.childIndex_ = null;
3389       this.childNameIndex_ = null;
3390       this.parentComponent_ = null;
3392       if (this.el_) {
3393         // Remove element from DOM
3394         if (this.el_.parentNode) {
3395           this.el_.parentNode.removeChild(this.el_);
3396         }
3398         if (DomData.has(this.el_)) {
3399           DomData["delete"](this.el_);
3400         }
3402         this.el_ = null;
3403       } // remove reference to the player after disposing of the element
3406       this.player_ = null;
3407     }
3408     /**
3409      * Determine whether or not this component has been disposed.
3410      *
3411      * @return {boolean}
3412      *         If the component has been disposed, will be `true`. Otherwise, `false`.
3413      */
3414     ;
3416     _proto.isDisposed = function isDisposed() {
3417       return Boolean(this.isDisposed_);
3418     }
3419     /**
3420      * Return the {@link Player} that the `Component` has attached to.
3421      *
3422      * @return {Player}
3423      *         The player that this `Component` has attached to.
3424      */
3425     ;
3427     _proto.player = function player() {
3428       return this.player_;
3429     }
3430     /**
3431      * Deep merge of options objects with new options.
3432      * > Note: When both `obj` and `options` contain properties whose values are objects.
3433      *         The two properties get merged using {@link module:mergeOptions}
3434      *
3435      * @param {Object} obj
3436      *        The object that contains new options.
3437      *
3438      * @return {Object}
3439      *         A new object of `this.options_` and `obj` merged together.
3440      */
3441     ;
3443     _proto.options = function options(obj) {
3444       if (!obj) {
3445         return this.options_;
3446       }
3448       this.options_ = mergeOptions(this.options_, obj);
3449       return this.options_;
3450     }
3451     /**
3452      * Get the `Component`s DOM element
3453      *
3454      * @return {Element}
3455      *         The DOM element for this `Component`.
3456      */
3457     ;
3459     _proto.el = function el() {
3460       return this.el_;
3461     }
3462     /**
3463      * Create the `Component`s DOM element.
3464      *
3465      * @param {string} [tagName]
3466      *        Element's DOM node type. e.g. 'div'
3467      *
3468      * @param {Object} [properties]
3469      *        An object of properties that should be set.
3470      *
3471      * @param {Object} [attributes]
3472      *        An object of attributes that should be set.
3473      *
3474      * @return {Element}
3475      *         The element that gets created.
3476      */
3477     ;
3479     _proto.createEl = function createEl$1(tagName, properties, attributes) {
3480       return createEl(tagName, properties, attributes);
3481     }
3482     /**
3483      * Localize a string given the string in english.
3484      *
3485      * If tokens are provided, it'll try and run a simple token replacement on the provided string.
3486      * The tokens it looks for look like `{1}` with the index being 1-indexed into the tokens array.
3487      *
3488      * If a `defaultValue` is provided, it'll use that over `string`,
3489      * if a value isn't found in provided language files.
3490      * This is useful if you want to have a descriptive key for token replacement
3491      * but have a succinct localized string and not require `en.json` to be included.
3492      *
3493      * Currently, it is used for the progress bar timing.
3494      * ```js
3495      * {
3496      *   "progress bar timing: currentTime={1} duration={2}": "{1} of {2}"
3497      * }
3498      * ```
3499      * It is then used like so: