{"version":3,"file":"video-lazy.min.js","sources":["https:\/\/lms.svhs.co\/media\/player\/videojs\/amd\/src\/video-lazy.js"],"sourcesContent":["\/**\n * @license\n * Video.js 8.17.3 \n * Copyright Brightcove, Inc. \n * Available under Apache License Version 2.0\n * \n *\n * Includes vtt.js \n * Available under Apache License Version 2.0\n * \n *\/\n\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.videojs = factory());\n})(this, (function () { 'use strict';\n\n var version$5 = \"8.17.3\";\n\n \/**\n * An Object that contains lifecycle hooks as keys which point to an array\n * of functions that are run when a lifecycle is triggered\n *\n * @private\n *\/\n const hooks_ = {};\n\n \/**\n * Get a list of hooks for a specific lifecycle\n *\n * @param {string} type\n * the lifecycle to get hooks from\n *\n * @param {Function|Function[]} [fn]\n * Optionally add a hook (or hooks) to the lifecycle that your are getting.\n *\n * @return {Array}\n * an array of hooks, or an empty array if there are none.\n *\/\n const hooks = function (type, fn) {\n hooks_[type] = hooks_[type] || [];\n if (fn) {\n hooks_[type] = hooks_[type].concat(fn);\n }\n return hooks_[type];\n };\n\n \/**\n * Add a function hook to a specific videojs lifecycle.\n *\n * @param {string} type\n * the lifecycle to hook the function to.\n *\n * @param {Function|Function[]}\n * The function or array of functions to attach.\n *\/\n const hook = function (type, fn) {\n hooks(type, fn);\n };\n\n \/**\n * Remove a hook from a specific videojs lifecycle.\n *\n * @param {string} type\n * the lifecycle that the function hooked to\n *\n * @param {Function} fn\n * The hooked function to remove\n *\n * @return {boolean}\n * The function that was removed or undef\n *\/\n const removeHook = function (type, fn) {\n const index = hooks(type).indexOf(fn);\n if (index <= -1) {\n return false;\n }\n hooks_[type] = hooks_[type].slice();\n hooks_[type].splice(index, 1);\n return true;\n };\n\n \/**\n * Add a function hook that will only run once to a specific videojs lifecycle.\n *\n * @param {string} type\n * the lifecycle to hook the function to.\n *\n * @param {Function|Function[]}\n * The function or array of functions to attach.\n *\/\n const hookOnce = function (type, fn) {\n hooks(type, [].concat(fn).map(original => {\n const wrapper = (...args) => {\n removeHook(type, wrapper);\n return original(...args);\n };\n return wrapper;\n }));\n };\n\n \/**\n * @file fullscreen-api.js\n * @module fullscreen-api\n *\/\n\n \/**\n * Store the browser-specific methods for the fullscreen API.\n *\n * @type {Object}\n * @see [Specification]{@link https:\/\/fullscreen.spec.whatwg.org}\n * @see [Map Approach From Screenfull.js]{@link https:\/\/github.com\/sindresorhus\/screenfull.js}\n *\/\n const FullscreenApi = {\n prefixed: true\n };\n\n \/\/ browser API methods\n const apiMap = [['requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror', 'fullscreen'],\n \/\/ WebKit\n ['webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitFullscreenElement', 'webkitFullscreenEnabled', 'webkitfullscreenchange', 'webkitfullscreenerror', '-webkit-full-screen']];\n const specApi = apiMap[0];\n let browserApi;\n\n \/\/ determine the supported set of functions\n for (let i = 0; i < apiMap.length; i++) {\n \/\/ check for exitFullscreen function\n if (apiMap[i][1] in document) {\n browserApi = apiMap[i];\n break;\n }\n }\n\n \/\/ map the browser API names to the spec API names\n if (browserApi) {\n for (let i = 0; i < browserApi.length; i++) {\n FullscreenApi[specApi[i]] = browserApi[i];\n }\n FullscreenApi.prefixed = browserApi[0] !== specApi[0];\n }\n\n \/**\n * @file create-logger.js\n * @module create-logger\n *\/\n\n \/\/ This is the private tracking variable for the logging history.\n let history = [];\n\n \/**\n * Log messages to the console and history based on the type of message\n *\n * @private\n * @param {string} name\n * The name of the console method to use.\n *\n * @param {Object} log\n * The arguments to be passed to the matching console method.\n *\n * @param {string} [styles]\n * styles for name\n *\/\n const LogByTypeFactory = (name, log, styles) => (type, level, args) => {\n const lvl = log.levels[level];\n const lvlRegExp = new RegExp(`^(${lvl})$`);\n let resultName = name;\n if (type !== 'log') {\n \/\/ Add the type to the front of the message when it's not \"log\".\n args.unshift(type.toUpperCase() + ':');\n }\n if (styles) {\n resultName = `%c${name}`;\n args.unshift(styles);\n }\n\n \/\/ Add console prefix after adding to history.\n args.unshift(resultName + ':');\n\n \/\/ Add a clone of the args at this point to history.\n if (history) {\n history.push([].concat(args));\n\n \/\/ only store 1000 history entries\n const splice = history.length - 1000;\n history.splice(0, splice > 0 ? splice : 0);\n }\n\n \/\/ If there's no console then don't try to output messages, but they will\n \/\/ still be stored in history.\n if (!window.console) {\n return;\n }\n\n \/\/ Was setting these once outside of this function, but containing them\n \/\/ in the function makes it easier to test cases where console doesn't exist\n \/\/ when the module is executed.\n let fn = window.console[type];\n if (!fn && type === 'debug') {\n \/\/ Certain browsers don't have support for console.debug. For those, we\n \/\/ should default to the closest comparable log.\n fn = window.console.info || window.console.log;\n }\n\n \/\/ Bail out if there's no console or if this type is not allowed by the\n \/\/ current logging level.\n if (!fn || !lvl || !lvlRegExp.test(type)) {\n return;\n }\n fn[Array.isArray(args) ? 'apply' : 'call'](window.console, args);\n };\n function createLogger$1(name, delimiter = ':', styles = '') {\n \/\/ This is the private tracking variable for logging level.\n let level = 'info';\n\n \/\/ the curried logByType bound to the specific log and history\n let logByType;\n\n \/**\n * Logs plain debug messages. Similar to `console.log`.\n *\n * Due to [limitations](https:\/\/github.com\/jsdoc3\/jsdoc\/issues\/955#issuecomment-313829149)\n * of our JSDoc template, we cannot properly document this as both a function\n * and a namespace, so its function signature is documented here.\n *\n * #### Arguments\n * ##### *args\n * *[]\n *\n * Any combination of values that could be passed to `console.log()`.\n *\n * #### Return Value\n *\n * `undefined`\n *\n * @namespace\n * @param {...*} args\n * One or more messages or objects that should be logged.\n *\/\n function log(...args) {\n logByType('log', level, args);\n }\n\n \/\/ This is the logByType helper that the logging methods below use\n logByType = LogByTypeFactory(name, log, styles);\n\n \/**\n * Create a new subLogger which chains the old name to the new name.\n *\n * For example, doing `mylogger = videojs.log.createLogger('player')` and then using that logger will log the following:\n * ```js\n * mylogger('foo');\n * \/\/ > VIDEOJS: player: foo\n * ```\n *\n * @param {string} subName\n * The name to add call the new logger\n * @param {string} [subDelimiter]\n * Optional delimiter\n * @param {string} [subStyles]\n * Optional styles\n * @return {Object}\n *\/\n log.createLogger = (subName, subDelimiter, subStyles) => {\n const resultDelimiter = subDelimiter !== undefined ? subDelimiter : delimiter;\n const resultStyles = subStyles !== undefined ? subStyles : styles;\n const resultName = `${name} ${resultDelimiter} ${subName}`;\n return createLogger$1(resultName, resultDelimiter, resultStyles);\n };\n\n \/**\n * Create a new logger.\n *\n * @param {string} newName\n * The name for the new logger\n * @param {string} [newDelimiter]\n * Optional delimiter\n * @param {string} [newStyles]\n * Optional styles\n * @return {Object}\n *\/\n log.createNewLogger = (newName, newDelimiter, newStyles) => {\n return createLogger$1(newName, newDelimiter, newStyles);\n };\n\n \/**\n * Enumeration of available logging levels, where the keys are the level names\n * and the values are `|`-separated strings containing logging methods allowed\n * in that logging level. These strings are used to create a regular expression\n * matching the function name being called.\n *\n * Levels provided by Video.js are:\n *\n * - `off`: Matches no calls. Any value that can be cast to `false` will have\n * this effect. The most restrictive.\n * - `all`: Matches only Video.js-provided functions (`debug`, `log`,\n * `log.warn`, and `log.error`).\n * - `debug`: Matches `log.debug`, `log`, `log.warn`, and `log.error` calls.\n * - `info` (default): Matches `log`, `log.warn`, and `log.error` calls.\n * - `warn`: Matches `log.warn` and `log.error` calls.\n * - `error`: Matches only `log.error` calls.\n *\n * @type {Object}\n *\/\n log.levels = {\n all: 'debug|log|warn|error',\n off: '',\n debug: 'debug|log|warn|error',\n info: 'log|warn|error',\n warn: 'warn|error',\n error: 'error',\n DEFAULT: level\n };\n\n \/**\n * Get or set the current logging level.\n *\n * If a string matching a key from {@link module:log.levels} is provided, acts\n * as a setter.\n *\n * @param {'all'|'debug'|'info'|'warn'|'error'|'off'} [lvl]\n * Pass a valid level to set a new logging level.\n *\n * @return {string}\n * The current logging level.\n *\/\n log.level = lvl => {\n if (typeof lvl === 'string') {\n if (!log.levels.hasOwnProperty(lvl)) {\n throw new Error(`\"${lvl}\" in not a valid log level`);\n }\n level = lvl;\n }\n return level;\n };\n\n \/**\n * Returns an array containing everything that has been logged to the history.\n *\n * This array is a shallow clone of the internal history record. However, its\n * contents are _not_ cloned; so, mutating objects inside this array will\n * mutate them in history.\n *\n * @return {Array}\n *\/\n log.history = () => history ? [].concat(history) : [];\n\n \/**\n * Allows you to filter the history by the given logger name\n *\n * @param {string} fname\n * The name to filter by\n *\n * @return {Array}\n * The filtered list to return\n *\/\n log.history.filter = fname => {\n return (history || []).filter(historyItem => {\n \/\/ if the first item in each historyItem includes `fname`, then it's a match\n return new RegExp(`.*${fname}.*`).test(historyItem[0]);\n });\n };\n\n \/**\n * Clears the internal history tracking, but does not prevent further history\n * tracking.\n *\/\n log.history.clear = () => {\n if (history) {\n history.length = 0;\n }\n };\n\n \/**\n * Disable history tracking if it is currently enabled.\n *\/\n log.history.disable = () => {\n if (history !== null) {\n history.length = 0;\n history = null;\n }\n };\n\n \/**\n * Enable history tracking if it is currently disabled.\n *\/\n log.history.enable = () => {\n if (history === null) {\n history = [];\n }\n };\n\n \/**\n * Logs error messages. Similar to `console.error`.\n *\n * @param {...*} args\n * One or more messages or objects that should be logged as an error\n *\/\n log.error = (...args) => logByType('error', level, args);\n\n \/**\n * Logs warning messages. Similar to `console.warn`.\n *\n * @param {...*} args\n * One or more messages or objects that should be logged as a warning.\n *\/\n log.warn = (...args) => logByType('warn', level, args);\n\n \/**\n * Logs debug messages. Similar to `console.debug`, but may also act as a comparable\n * log if `console.debug` is not available\n *\n * @param {...*} args\n * One or more messages or objects that should be logged as debug.\n *\/\n log.debug = (...args) => logByType('debug', level, args);\n return log;\n }\n\n \/**\n * @file log.js\n * @module log\n *\/\n const log$1 = createLogger$1('VIDEOJS');\n const createLogger = log$1.createLogger;\n\n \/**\n * @file obj.js\n * @module obj\n *\/\n\n \/**\n * @callback obj:EachCallback\n *\n * @param {*} value\n * The current key for the object that is being iterated over.\n *\n * @param {string} key\n * The current key-value for object that is being iterated over\n *\/\n\n \/**\n * @callback obj:ReduceCallback\n *\n * @param {*} accum\n * The value that is accumulating over the reduce loop.\n *\n * @param {*} value\n * The current key for the object that is being iterated over.\n *\n * @param {string} key\n * The current key-value for object that is being iterated over\n *\n * @return {*}\n * The new accumulated value.\n *\/\n const toString$1 = Object.prototype.toString;\n\n \/**\n * Get the keys of an Object\n *\n * @param {Object}\n * The Object to get the keys from\n *\n * @return {string[]}\n * An array of the keys from the object. Returns an empty array if the\n * object passed in was invalid or had no keys.\n *\n * @private\n *\/\n const keys = function (object) {\n return isObject$1(object) ? Object.keys(object) : [];\n };\n\n \/**\n * Array-like iteration for objects.\n *\n * @param {Object} object\n * The object to iterate over\n *\n * @param {obj:EachCallback} fn\n * The callback function which is called for each key in the object.\n *\/\n function each(object, fn) {\n keys(object).forEach(key => fn(object[key], key));\n }\n\n \/**\n * Array-like reduce for objects.\n *\n * @param {Object} object\n * The Object that you want to reduce.\n *\n * @param {Function} fn\n * A callback function which is called for each key in the object. It\n * receives the accumulated value and the per-iteration value and key\n * as arguments.\n *\n * @param {*} [initial = 0]\n * Starting value\n *\n * @return {*}\n * The final accumulated value.\n *\/\n function reduce(object, fn, initial = 0) {\n return keys(object).reduce((accum, key) => fn(accum, object[key], key), initial);\n }\n\n \/**\n * Returns whether a value is an object of any kind - including DOM nodes,\n * arrays, regular expressions, etc. Not functions, though.\n *\n * This avoids the gotcha where using `typeof` on a `null` value\n * results in `'object'`.\n *\n * @param {Object} value\n * @return {boolean}\n *\/\n function isObject$1(value) {\n return !!value && typeof value === 'object';\n }\n\n \/**\n * Returns whether an object appears to be a \"plain\" object - that is, a\n * direct instance of `Object`.\n *\n * @param {Object} value\n * @return {boolean}\n *\/\n function isPlain(value) {\n return isObject$1(value) && toString$1.call(value) === '[object Object]' && value.constructor === Object;\n }\n\n \/**\n * Merge two objects recursively.\n *\n * Performs a deep merge like\n * {@link https:\/\/lodash.com\/docs\/4.17.10#merge|lodash.merge}, but only merges\n * plain objects (not arrays, elements, or anything else).\n *\n * Non-plain object values will be copied directly from the right-most\n * argument.\n *\n * @param {Object[]} sources\n * One or more objects to merge into a new object.\n *\n * @return {Object}\n * A new object that is the merged result of all sources.\n *\/\n function merge$2(...sources) {\n const result = {};\n sources.forEach(source => {\n if (!source) {\n return;\n }\n each(source, (value, key) => {\n if (!isPlain(value)) {\n result[key] = value;\n return;\n }\n if (!isPlain(result[key])) {\n result[key] = {};\n }\n result[key] = merge$2(result[key], value);\n });\n });\n return result;\n }\n\n \/**\n * Returns an array of values for a given object\n *\n * @param {Object} source - target object\n * @return {Array} - object values\n *\/\n function values$1(source = {}) {\n const result = [];\n for (const key in source) {\n if (source.hasOwnProperty(key)) {\n const value = source[key];\n result.push(value);\n }\n }\n return result;\n }\n\n \/**\n * Object.defineProperty but \"lazy\", which means that the value is only set after\n * it is retrieved the first time, rather than being set right away.\n *\n * @param {Object} obj the object to set the property on\n * @param {string} key the key for the property to set\n * @param {Function} getValue the function used to get the value when it is needed.\n * @param {boolean} setter whether a setter should be allowed or not\n *\/\n function defineLazyProperty(obj, key, getValue, setter = true) {\n const set = value => Object.defineProperty(obj, key, {\n value,\n enumerable: true,\n writable: true\n });\n const options = {\n configurable: true,\n enumerable: true,\n get() {\n const value = getValue();\n set(value);\n return value;\n }\n };\n if (setter) {\n options.set = set;\n }\n return Object.defineProperty(obj, key, options);\n }\n\n var Obj = \/*#__PURE__*\/Object.freeze({\n __proto__: null,\n each: each,\n reduce: reduce,\n isObject: isObject$1,\n isPlain: isPlain,\n merge: merge$2,\n values: values$1,\n defineLazyProperty: defineLazyProperty\n });\n\n \/**\n * @file browser.js\n * @module browser\n *\/\n\n \/**\n * Whether or not this device is an iPod.\n *\n * @static\n * @type {Boolean}\n *\/\n let IS_IPOD = false;\n\n \/**\n * The detected iOS version - or `null`.\n *\n * @static\n * @type {string|null}\n *\/\n let IOS_VERSION = null;\n\n \/**\n * Whether or not this is an Android device.\n *\n * @static\n * @type {Boolean}\n *\/\n let IS_ANDROID = false;\n\n \/**\n * The detected Android version - or `null` if not Android or indeterminable.\n *\n * @static\n * @type {number|string|null}\n *\/\n let ANDROID_VERSION;\n\n \/**\n * Whether or not this is Mozilla Firefox.\n *\n * @static\n * @type {Boolean}\n *\/\n let IS_FIREFOX = false;\n\n \/**\n * Whether or not this is Microsoft Edge.\n *\n * @static\n * @type {Boolean}\n *\/\n let IS_EDGE = false;\n\n \/**\n * Whether or not this is any Chromium Browser\n *\n * @static\n * @type {Boolean}\n *\/\n let IS_CHROMIUM = false;\n\n \/**\n * Whether or not this is any Chromium browser that is not Edge.\n *\n * This will also be `true` for Chrome on iOS, which will have different support\n * as it is actually Safari under the hood.\n *\n * Deprecated, as the behaviour to not match Edge was to prevent Legacy Edge's UA matching.\n * IS_CHROMIUM should be used instead.\n * \"Chromium but not Edge\" could be explicitly tested with IS_CHROMIUM && !IS_EDGE\n *\n * @static\n * @deprecated\n * @type {Boolean}\n *\/\n let IS_CHROME = false;\n\n \/**\n * The detected Chromium version - or `null`.\n *\n * @static\n * @type {number|null}\n *\/\n let CHROMIUM_VERSION = null;\n\n \/**\n * The detected Google Chrome version - or `null`.\n * This has always been the _Chromium_ version, i.e. would return on Chromium Edge.\n * Deprecated, use CHROMIUM_VERSION instead.\n *\n * @static\n * @deprecated\n * @type {number|null}\n *\/\n let CHROME_VERSION = null;\n\n \/**\n * Whether or not this is a Chromecast receiver application.\n *\n * @static\n * @type {Boolean}\n *\/\n const IS_CHROMECAST_RECEIVER = Boolean(window.cast && window.cast.framework && window.cast.framework.CastReceiverContext);\n\n \/**\n * The detected Internet Explorer version - or `null`.\n *\n * @static\n * @deprecated\n * @type {number|null}\n *\/\n let IE_VERSION = null;\n\n \/**\n * Whether or not this is desktop Safari.\n *\n * @static\n * @type {Boolean}\n *\/\n let IS_SAFARI = false;\n\n \/**\n * Whether or not this is a Windows machine.\n *\n * @static\n * @type {Boolean}\n *\/\n let IS_WINDOWS = false;\n\n \/**\n * Whether or not this device is an iPad.\n *\n * @static\n * @type {Boolean}\n *\/\n let IS_IPAD = false;\n\n \/**\n * Whether or not this device is an iPhone.\n *\n * @static\n * @type {Boolean}\n *\/\n \/\/ The Facebook app's UIWebView identifies as both an iPhone and iPad, so\n \/\/ to identify iPhones, we need to exclude iPads.\n \/\/ http:\/\/artsy.github.io\/blog\/2012\/10\/18\/the-perils-of-ios-user-agent-sniffing\/\n let IS_IPHONE = false;\n\n \/**\n * Whether or not this is a Tizen device.\n *\n * @static\n * @type {Boolean}\n *\/\n let IS_TIZEN = false;\n\n \/**\n * Whether or not this is a WebOS device.\n *\n * @static\n * @type {Boolean}\n *\/\n let IS_WEBOS = false;\n\n \/**\n * Whether or not this is a Smart TV (Tizen or WebOS) device.\n *\n * @static\n * @type {Boolean}\n *\/\n let IS_SMART_TV = false;\n\n \/**\n * Whether or not this device is touch-enabled.\n *\n * @static\n * @const\n * @type {Boolean}\n *\/\n const TOUCH_ENABLED = Boolean(isReal() && ('ontouchstart' in window || window.navigator.maxTouchPoints || window.DocumentTouch && window.document instanceof window.DocumentTouch));\n const UAD = window.navigator && window.navigator.userAgentData;\n if (UAD && UAD.platform && UAD.brands) {\n \/\/ If userAgentData is present, use it instead of userAgent to avoid warnings\n \/\/ Currently only implemented on Chromium\n \/\/ userAgentData does not expose Android version, so ANDROID_VERSION remains `null`\n\n IS_ANDROID = UAD.platform === 'Android';\n IS_EDGE = Boolean(UAD.brands.find(b => b.brand === 'Microsoft Edge'));\n IS_CHROMIUM = Boolean(UAD.brands.find(b => b.brand === 'Chromium'));\n IS_CHROME = !IS_EDGE && IS_CHROMIUM;\n CHROMIUM_VERSION = CHROME_VERSION = (UAD.brands.find(b => b.brand === 'Chromium') || {}).version || null;\n IS_WINDOWS = UAD.platform === 'Windows';\n }\n\n \/\/ If the browser is not Chromium, either userAgentData is not present which could be an old Chromium browser,\n \/\/ or it's a browser that has added userAgentData since that we don't have tests for yet. In either case,\n \/\/ the checks need to be made agiainst the regular userAgent string.\n if (!IS_CHROMIUM) {\n const USER_AGENT = window.navigator && window.navigator.userAgent || '';\n IS_IPOD = \/iPod\/i.test(USER_AGENT);\n IOS_VERSION = function () {\n const match = USER_AGENT.match(\/OS (\\d+)_\/i);\n if (match && match[1]) {\n return match[1];\n }\n return null;\n }();\n IS_ANDROID = \/Android\/i.test(USER_AGENT);\n ANDROID_VERSION = function () {\n \/\/ This matches Android Major.Minor.Patch versions\n \/\/ ANDROID_VERSION is Major.Minor as a Number, if Minor isn't available, then only Major is returned\n const match = USER_AGENT.match(\/Android (\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))*\/i);\n if (!match) {\n return null;\n }\n const major = match[1] && parseFloat(match[1]);\n const minor = match[2] && parseFloat(match[2]);\n if (major && minor) {\n return parseFloat(match[1] + '.' + match[2]);\n } else if (major) {\n return major;\n }\n return null;\n }();\n IS_FIREFOX = \/Firefox\/i.test(USER_AGENT);\n IS_EDGE = \/Edg\/i.test(USER_AGENT);\n IS_CHROMIUM = \/Chrome\/i.test(USER_AGENT) || \/CriOS\/i.test(USER_AGENT);\n IS_CHROME = !IS_EDGE && IS_CHROMIUM;\n CHROMIUM_VERSION = CHROME_VERSION = function () {\n const match = USER_AGENT.match(\/(Chrome|CriOS)\\\/(\\d+)\/);\n if (match && match[2]) {\n return parseFloat(match[2]);\n }\n return null;\n }();\n IE_VERSION = function () {\n const result = \/MSIE\\s(\\d+)\\.\\d\/.exec(USER_AGENT);\n let version = result && parseFloat(result[1]);\n if (!version && \/Trident\\\/7.0\/i.test(USER_AGENT) && \/rv:11.0\/.test(USER_AGENT)) {\n \/\/ IE 11 has a different user agent string than other IE versions\n version = 11.0;\n }\n return version;\n }();\n IS_TIZEN = \/Tizen\/i.test(USER_AGENT);\n IS_WEBOS = \/Web0S\/i.test(USER_AGENT);\n IS_SMART_TV = IS_TIZEN || IS_WEBOS;\n IS_SAFARI = \/Safari\/i.test(USER_AGENT) && !IS_CHROME && !IS_ANDROID && !IS_EDGE && !IS_SMART_TV;\n IS_WINDOWS = \/Windows\/i.test(USER_AGENT);\n IS_IPAD = \/iPad\/i.test(USER_AGENT) || IS_SAFARI && TOUCH_ENABLED && !\/iPhone\/i.test(USER_AGENT);\n IS_IPHONE = \/iPhone\/i.test(USER_AGENT) && !IS_IPAD;\n }\n\n \/**\n * Whether or not this is an iOS device.\n *\n * @static\n * @const\n * @type {Boolean}\n *\/\n const IS_IOS = IS_IPHONE || IS_IPAD || IS_IPOD;\n\n \/**\n * Whether or not this is any flavor of Safari - including iOS.\n *\n * @static\n * @const\n * @type {Boolean}\n *\/\n const IS_ANY_SAFARI = (IS_SAFARI || IS_IOS) && !IS_CHROME;\n\n var browser = \/*#__PURE__*\/Object.freeze({\n __proto__: null,\n get IS_IPOD () { return IS_IPOD; },\n get IOS_VERSION () { return IOS_VERSION; },\n get IS_ANDROID () { return IS_ANDROID; },\n get ANDROID_VERSION () { return ANDROID_VERSION; },\n get IS_FIREFOX () { return IS_FIREFOX; },\n get IS_EDGE () { return IS_EDGE; },\n get IS_CHROMIUM () { return IS_CHROMIUM; },\n get IS_CHROME () { return IS_CHROME; },\n get CHROMIUM_VERSION () { return CHROMIUM_VERSION; },\n get CHROME_VERSION () { return CHROME_VERSION; },\n IS_CHROMECAST_RECEIVER: IS_CHROMECAST_RECEIVER,\n get IE_VERSION () { return IE_VERSION; },\n get IS_SAFARI () { return IS_SAFARI; },\n get IS_WINDOWS () { return IS_WINDOWS; },\n get IS_IPAD () { return IS_IPAD; },\n get IS_IPHONE () { return IS_IPHONE; },\n get IS_TIZEN () { return IS_TIZEN; },\n get IS_WEBOS () { return IS_WEBOS; },\n get IS_SMART_TV () { return IS_SMART_TV; },\n TOUCH_ENABLED: TOUCH_ENABLED,\n IS_IOS: IS_IOS,\n IS_ANY_SAFARI: IS_ANY_SAFARI\n });\n\n \/**\n * @file dom.js\n * @module dom\n *\/\n\n \/**\n * Detect if a value is a string with any non-whitespace characters.\n *\n * @private\n * @param {string} str\n * The string to check\n *\n * @return {boolean}\n * Will be `true` if the string is non-blank, `false` otherwise.\n *\n *\/\n function isNonBlankString(str) {\n \/\/ we use str.trim as it will trim any whitespace characters\n \/\/ from the front or back of non-whitespace characters. aka\n \/\/ Any string that contains non-whitespace characters will\n \/\/ still contain them after `trim` but whitespace only strings\n \/\/ will have a length of 0, failing this check.\n return typeof str === 'string' && Boolean(str.trim());\n }\n\n \/**\n * Throws an error if the passed string has whitespace. This is used by\n * class methods to be relatively consistent with the classList API.\n *\n * @private\n * @param {string} str\n * The string to check for whitespace.\n *\n * @throws {Error}\n * Throws an error if there is whitespace in the string.\n *\/\n function throwIfWhitespace(str) {\n \/\/ str.indexOf instead of regex because str.indexOf is faster performance wise.\n if (str.indexOf(' ') >= 0) {\n throw new Error('class has illegal whitespace characters');\n }\n }\n\n \/**\n * Whether the current DOM interface appears to be real (i.e. not simulated).\n *\n * @return {boolean}\n * Will be `true` if the DOM appears to be real, `false` otherwise.\n *\/\n function isReal() {\n \/\/ Both document and window will never be undefined thanks to `global`.\n return document === window.document;\n }\n\n \/**\n * Determines, via duck typing, whether or not a value is a DOM element.\n *\n * @param {*} value\n * The value to check.\n *\n * @return {boolean}\n * Will be `true` if the value is a DOM element, `false` otherwise.\n *\/\n function isEl(value) {\n return isObject$1(value) && value.nodeType === 1;\n }\n\n \/**\n * Determines if the current DOM is embedded in an iframe.\n *\n * @return {boolean}\n * Will be `true` if the DOM is embedded in an iframe, `false`\n * otherwise.\n *\/\n function isInFrame() {\n \/\/ We need a try\/catch here because Safari will throw errors when attempting\n \/\/ to get either `parent` or `self`\n try {\n return window.parent !== window.self;\n } catch (x) {\n return true;\n }\n }\n\n \/**\n * Creates functions to query the DOM using a given method.\n *\n * @private\n * @param {string} method\n * The method to create the query with.\n *\n * @return {Function}\n * The query method\n *\/\n function createQuerier(method) {\n return function (selector, context) {\n if (!isNonBlankString(selector)) {\n return document[method](null);\n }\n if (isNonBlankString(context)) {\n context = document.querySelector(context);\n }\n const ctx = isEl(context) ? context : document;\n return ctx[method] && ctx[method](selector);\n };\n }\n\n \/**\n * Creates an element and applies properties, attributes, and inserts content.\n *\n * @param {string} [tagName='div']\n * Name of tag to be created.\n *\n * @param {Object} [properties={}]\n * Element properties to be applied.\n *\n * @param {Object} [attributes={}]\n * Element attributes to be applied.\n *\n * @param {ContentDescriptor} [content]\n * A content descriptor object.\n *\n * @return {Element}\n * The element that was created.\n *\/\n function createEl(tagName = 'div', properties = {}, attributes = {}, content) {\n const el = document.createElement(tagName);\n Object.getOwnPropertyNames(properties).forEach(function (propName) {\n const val = properties[propName];\n\n \/\/ Handle textContent since it's not supported everywhere and we have a\n \/\/ method for it.\n if (propName === 'textContent') {\n textContent(el, val);\n } else if (el[propName] !== val || propName === 'tabIndex') {\n el[propName] = val;\n }\n });\n Object.getOwnPropertyNames(attributes).forEach(function (attrName) {\n el.setAttribute(attrName, attributes[attrName]);\n });\n if (content) {\n appendContent(el, content);\n }\n return el;\n }\n\n \/**\n * Injects text into an element, replacing any existing contents entirely.\n *\n * @param {HTMLElement} el\n * The element to add text content into\n *\n * @param {string} text\n * The text content to add.\n *\n * @return {Element}\n * The element with added text content.\n *\/\n function textContent(el, text) {\n if (typeof el.textContent === 'undefined') {\n el.innerText = text;\n } else {\n el.textContent = text;\n }\n return el;\n }\n\n \/**\n * Insert an element as the first child node of another\n *\n * @param {Element} child\n * Element to insert\n *\n * @param {Element} parent\n * Element to insert child into\n *\/\n function prependTo(child, parent) {\n if (parent.firstChild) {\n parent.insertBefore(child, parent.firstChild);\n } else {\n parent.appendChild(child);\n }\n }\n\n \/**\n * Check if an element has a class name.\n *\n * @param {Element} element\n * Element to check\n *\n * @param {string} classToCheck\n * Class name to check for\n *\n * @return {boolean}\n * Will be `true` if the element has a class, `false` otherwise.\n *\n * @throws {Error}\n * Throws an error if `classToCheck` has white space.\n *\/\n function hasClass(element, classToCheck) {\n throwIfWhitespace(classToCheck);\n return element.classList.contains(classToCheck);\n }\n\n \/**\n * Add a class name to an element.\n *\n * @param {Element} element\n * Element to add class name to.\n *\n * @param {...string} classesToAdd\n * One or more class name to add.\n *\n * @return {Element}\n * The DOM element with the added class name.\n *\/\n function addClass(element, ...classesToAdd) {\n element.classList.add(...classesToAdd.reduce((prev, current) => prev.concat(current.split(\/\\s+\/)), []));\n return element;\n }\n\n \/**\n * Remove a class name from an element.\n *\n * @param {Element} element\n * Element to remove a class name from.\n *\n * @param {...string} classesToRemove\n * One or more class name to remove.\n *\n * @return {Element}\n * The DOM element with class name removed.\n *\/\n function removeClass(element, ...classesToRemove) {\n \/\/ Protect in case the player gets disposed\n if (!element) {\n log$1.warn(\"removeClass was called with an element that doesn't exist\");\n return null;\n }\n element.classList.remove(...classesToRemove.reduce((prev, current) => prev.concat(current.split(\/\\s+\/)), []));\n return element;\n }\n\n \/**\n * The callback definition for toggleClass.\n *\n * @callback module:dom~PredicateCallback\n * @param {Element} element\n * The DOM element of the Component.\n *\n * @param {string} classToToggle\n * The `className` that wants to be toggled\n *\n * @return {boolean|undefined}\n * If `true` is returned, the `classToToggle` will be added to the\n * `element`. If `false`, the `classToToggle` will be removed from\n * the `element`. If `undefined`, the callback will be ignored.\n *\/\n\n \/**\n * Adds or removes a class name to\/from an element depending on an optional\n * condition or the presence\/absence of the class name.\n *\n * @param {Element} element\n * The element to toggle a class name on.\n *\n * @param {string} classToToggle\n * The class that should be toggled.\n *\n * @param {boolean|module:dom~PredicateCallback} [predicate]\n * See the return value for {@link module:dom~PredicateCallback}\n *\n * @return {Element}\n * The element with a class that has been toggled.\n *\/\n function toggleClass(element, classToToggle, predicate) {\n if (typeof predicate === 'function') {\n predicate = predicate(element, classToToggle);\n }\n if (typeof predicate !== 'boolean') {\n predicate = undefined;\n }\n classToToggle.split(\/\\s+\/).forEach(className => element.classList.toggle(className, predicate));\n return element;\n }\n\n \/**\n * Apply attributes to an HTML element.\n *\n * @param {Element} el\n * Element to add attributes to.\n *\n * @param {Object} [attributes]\n * Attributes to be applied.\n *\/\n function setAttributes(el, attributes) {\n Object.getOwnPropertyNames(attributes).forEach(function (attrName) {\n const attrValue = attributes[attrName];\n if (attrValue === null || typeof attrValue === 'undefined' || attrValue === false) {\n el.removeAttribute(attrName);\n } else {\n el.setAttribute(attrName, attrValue === true ? '' : attrValue);\n }\n });\n }\n\n \/**\n * Get an element's attribute values, as defined on the HTML tag.\n *\n * Attributes are not the same as properties. They're defined on the tag\n * or with setAttribute.\n *\n * @param {Element} tag\n * Element from which to get tag attributes.\n *\n * @return {Object}\n * All attributes of the element. Boolean attributes will be `true` or\n * `false`, others will be strings.\n *\/\n function getAttributes(tag) {\n const obj = {};\n\n \/\/ known boolean attributes\n \/\/ we can check for matching boolean properties, but not all browsers\n \/\/ and not all tags know about these attributes, so, we still want to check them manually\n const knownBooleans = ['autoplay', 'controls', 'playsinline', 'loop', 'muted', 'default', 'defaultMuted'];\n if (tag && tag.attributes && tag.attributes.length > 0) {\n const attrs = tag.attributes;\n for (let i = attrs.length - 1; i >= 0; i--) {\n const attrName = attrs[i].name;\n \/** @type {boolean|string} *\/\n let attrVal = attrs[i].value;\n\n \/\/ check for known booleans\n \/\/ the matching element property will return a value for typeof\n if (knownBooleans.includes(attrName)) {\n \/\/ the value of an included boolean attribute is typically an empty\n \/\/ string ('') which would equal false if we just check for a false value.\n \/\/ we also don't want support bad code like autoplay='false'\n attrVal = attrVal !== null ? true : false;\n }\n obj[attrName] = attrVal;\n }\n }\n return obj;\n }\n\n \/**\n * Get the value of an element's attribute.\n *\n * @param {Element} el\n * A DOM element.\n *\n * @param {string} attribute\n * Attribute to get the value of.\n *\n * @return {string}\n * The value of the attribute.\n *\/\n function getAttribute(el, attribute) {\n return el.getAttribute(attribute);\n }\n\n \/**\n * Set the value of an element's attribute.\n *\n * @param {Element} el\n * A DOM element.\n *\n * @param {string} attribute\n * Attribute to set.\n *\n * @param {string} value\n * Value to set the attribute to.\n *\/\n function setAttribute(el, attribute, value) {\n el.setAttribute(attribute, value);\n }\n\n \/**\n * Remove an element's attribute.\n *\n * @param {Element} el\n * A DOM element.\n *\n * @param {string} attribute\n * Attribute to remove.\n *\/\n function removeAttribute(el, attribute) {\n el.removeAttribute(attribute);\n }\n\n \/**\n * Attempt to block the ability to select text.\n *\/\n function blockTextSelection() {\n document.body.focus();\n document.onselectstart = function () {\n return false;\n };\n }\n\n \/**\n * Turn off text selection blocking.\n *\/\n function unblockTextSelection() {\n document.onselectstart = function () {\n return true;\n };\n }\n\n \/**\n * Identical to the native `getBoundingClientRect` function, but ensures that\n * the method is supported at all (it is in all browsers we claim to support)\n * and that the element is in the DOM before continuing.\n *\n * This wrapper function also shims properties which are not provided by some\n * older browsers (namely, IE8).\n *\n * Additionally, some browsers do not support adding properties to a\n * `ClientRect`\/`DOMRect` object; so, we shallow-copy it with the standard\n * properties (except `x` and `y` which are not widely supported). This helps\n * avoid implementations where keys are non-enumerable.\n *\n * @param {Element} el\n * Element whose `ClientRect` we want to calculate.\n *\n * @return {Object|undefined}\n * Always returns a plain object - or `undefined` if it cannot.\n *\/\n function getBoundingClientRect(el) {\n if (el && el.getBoundingClientRect && el.parentNode) {\n const rect = el.getBoundingClientRect();\n const result = {};\n ['bottom', 'height', 'left', 'right', 'top', 'width'].forEach(k => {\n if (rect[k] !== undefined) {\n result[k] = rect[k];\n }\n });\n if (!result.height) {\n result.height = parseFloat(computedStyle(el, 'height'));\n }\n if (!result.width) {\n result.width = parseFloat(computedStyle(el, 'width'));\n }\n return result;\n }\n }\n\n \/**\n * Represents the position of a DOM element on the page.\n *\n * @typedef {Object} module:dom~Position\n *\n * @property {number} left\n * Pixels to the left.\n *\n * @property {number} top\n * Pixels from the top.\n *\/\n\n \/**\n * Get the position of an element in the DOM.\n *\n * Uses `getBoundingClientRect` technique from John Resig.\n *\n * @see http:\/\/ejohn.org\/blog\/getboundingclientrect-is-awesome\/\n *\n * @param {Element} el\n * Element from which to get offset.\n *\n * @return {module:dom~Position}\n * The position of the element that was passed in.\n *\/\n function findPosition(el) {\n if (!el || el && !el.offsetParent) {\n return {\n left: 0,\n top: 0,\n width: 0,\n height: 0\n };\n }\n const width = el.offsetWidth;\n const height = el.offsetHeight;\n let left = 0;\n let top = 0;\n while (el.offsetParent && el !== document[FullscreenApi.fullscreenElement]) {\n left += el.offsetLeft;\n top += el.offsetTop;\n el = el.offsetParent;\n }\n return {\n left,\n top,\n width,\n height\n };\n }\n\n \/**\n * Represents x and y coordinates for a DOM element or mouse pointer.\n *\n * @typedef {Object} module:dom~Coordinates\n *\n * @property {number} x\n * x coordinate in pixels\n *\n * @property {number} y\n * y coordinate in pixels\n *\/\n\n \/**\n * Get the pointer position within an element.\n *\n * The base on the coordinates are the bottom left of the element.\n *\n * @param {Element} el\n * Element on which to get the pointer position on.\n *\n * @param {Event} event\n * Event object.\n *\n * @return {module:dom~Coordinates}\n * A coordinates object corresponding to the mouse position.\n *\n *\/\n function getPointerPosition(el, event) {\n const translated = {\n x: 0,\n y: 0\n };\n if (IS_IOS) {\n let item = el;\n while (item && item.nodeName.toLowerCase() !== 'html') {\n const transform = computedStyle(item, 'transform');\n if (\/^matrix\/.test(transform)) {\n const values = transform.slice(7, -1).split(\/,\\s\/).map(Number);\n translated.x += values[4];\n translated.y += values[5];\n } else if (\/^matrix3d\/.test(transform)) {\n const values = transform.slice(9, -1).split(\/,\\s\/).map(Number);\n translated.x += values[12];\n translated.y += values[13];\n }\n if (item.assignedSlot && item.assignedSlot.parentElement && window.WebKitCSSMatrix) {\n const transformValue = window.getComputedStyle(item.assignedSlot.parentElement).transform;\n const matrix = new window.WebKitCSSMatrix(transformValue);\n translated.x += matrix.m41;\n translated.y += matrix.m42;\n }\n item = item.parentNode || item.host;\n }\n }\n const position = {};\n const boxTarget = findPosition(event.target);\n const box = findPosition(el);\n const boxW = box.width;\n const boxH = box.height;\n let offsetY = event.offsetY - (box.top - boxTarget.top);\n let offsetX = event.offsetX - (box.left - boxTarget.left);\n if (event.changedTouches) {\n offsetX = event.changedTouches[0].pageX - box.left;\n offsetY = event.changedTouches[0].pageY + box.top;\n if (IS_IOS) {\n offsetX -= translated.x;\n offsetY -= translated.y;\n }\n }\n position.y = 1 - Math.max(0, Math.min(1, offsetY \/ boxH));\n position.x = Math.max(0, Math.min(1, offsetX \/ boxW));\n return position;\n }\n\n \/**\n * Determines, via duck typing, whether or not a value is a text node.\n *\n * @param {*} value\n * Check if this value is a text node.\n *\n * @return {boolean}\n * Will be `true` if the value is a text node, `false` otherwise.\n *\/\n function isTextNode$1(value) {\n return isObject$1(value) && value.nodeType === 3;\n }\n\n \/**\n * Empties the contents of an element.\n *\n * @param {Element} el\n * The element to empty children from\n *\n * @return {Element}\n * The element with no children\n *\/\n function emptyEl(el) {\n while (el.firstChild) {\n el.removeChild(el.firstChild);\n }\n return el;\n }\n\n \/**\n * This is a mixed value that describes content to be injected into the DOM\n * via some method. It can be of the following types:\n *\n * Type | Description\n * -----------|-------------\n * `string` | The value will be normalized into a text node.\n * `Element` | The value will be accepted as-is.\n * `Text` | A TextNode. The value will be accepted as-is.\n * `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).\n * `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.\n *\n * @typedef {string|Element|Text|Array|Function} ContentDescriptor\n *\/\n\n \/**\n * Normalizes content for eventual insertion into the DOM.\n *\n * This allows a wide range of content definition methods, but helps protect\n * from falling into the trap of simply writing to `innerHTML`, which could\n * be an XSS concern.\n *\n * The content for an element can be passed in multiple types and\n * combinations, whose behavior is as follows:\n *\n * @param {ContentDescriptor} content\n * A content descriptor value.\n *\n * @return {Array}\n * All of the content that was passed in, normalized to an array of\n * elements or text nodes.\n *\/\n function normalizeContent(content) {\n \/\/ First, invoke content if it is a function. If it produces an array,\n \/\/ that needs to happen before normalization.\n if (typeof content === 'function') {\n content = content();\n }\n\n \/\/ Next up, normalize to an array, so one or many items can be normalized,\n \/\/ filtered, and returned.\n return (Array.isArray(content) ? content : [content]).map(value => {\n \/\/ First, invoke value if it is a function to produce a new value,\n \/\/ which will be subsequently normalized to a Node of some kind.\n if (typeof value === 'function') {\n value = value();\n }\n if (isEl(value) || isTextNode$1(value)) {\n return value;\n }\n if (typeof value === 'string' && \/\\S\/.test(value)) {\n return document.createTextNode(value);\n }\n }).filter(value => value);\n }\n\n \/**\n * Normalizes and appends content to an element.\n *\n * @param {Element} el\n * Element to append normalized content to.\n *\n * @param {ContentDescriptor} content\n * A content descriptor value.\n *\n * @return {Element}\n * The element with appended normalized content.\n *\/\n function appendContent(el, content) {\n normalizeContent(content).forEach(node => el.appendChild(node));\n return el;\n }\n\n \/**\n * Normalizes and inserts content into an element; this is identical to\n * `appendContent()`, except it empties the element first.\n *\n * @param {Element} el\n * Element to insert normalized content into.\n *\n * @param {ContentDescriptor} content\n * A content descriptor value.\n *\n * @return {Element}\n * The element with inserted normalized content.\n *\/\n function insertContent(el, content) {\n return appendContent(emptyEl(el), content);\n }\n\n \/**\n * Check if an event was a single left click.\n *\n * @param {MouseEvent} event\n * Event object.\n *\n * @return {boolean}\n * Will be `true` if a single left click, `false` otherwise.\n *\/\n function isSingleLeftClick(event) {\n \/\/ Note: if you create something draggable, be sure to\n \/\/ call it on both `mousedown` and `mousemove` event,\n \/\/ otherwise `mousedown` should be enough for a button\n\n if (event.button === undefined && event.buttons === undefined) {\n \/\/ Why do we need `buttons` ?\n \/\/ Because, middle mouse sometimes have this:\n \/\/ e.button === 0 and e.buttons === 4\n \/\/ Furthermore, we want to prevent combination click, something like\n \/\/ HOLD middlemouse then left click, that would be\n \/\/ e.button === 0, e.buttons === 5\n \/\/ just `button` is not gonna work\n\n \/\/ Alright, then what this block does ?\n \/\/ this is for chrome `simulate mobile devices`\n \/\/ I want to support this as well\n\n return true;\n }\n if (event.button === 0 && event.buttons === undefined) {\n \/\/ Touch screen, sometimes on some specific device, `buttons`\n \/\/ doesn't have anything (safari on ios, blackberry...)\n\n return true;\n }\n\n \/\/ `mouseup` event on a single left click has\n \/\/ `button` and `buttons` equal to 0\n if (event.type === 'mouseup' && event.button === 0 && event.buttons === 0) {\n return true;\n }\n\n \/\/ MacOS Sonoma trackpad when \"tap to click enabled\"\n if (event.type === 'mousedown' && event.button === 0 && event.buttons === 0) {\n return true;\n }\n if (event.button !== 0 || event.buttons !== 1) {\n \/\/ This is the reason we have those if else block above\n \/\/ if any special case we can catch and let it slide\n \/\/ we do it above, when get to here, this definitely\n \/\/ is-not-left-click\n\n return false;\n }\n return true;\n }\n\n \/**\n * Finds a single DOM element matching `selector` within the optional\n * `context` of another DOM element (defaulting to `document`).\n *\n * @param {string} selector\n * A valid CSS selector, which will be passed to `querySelector`.\n *\n * @param {Element|String} [context=document]\n * A DOM element within which to query. Can also be a selector\n * string in which case the first matching element will be used\n * as context. If missing (or no element matches selector), falls\n * back to `document`.\n *\n * @return {Element|null}\n * The element that was found or null.\n *\/\n const $ = createQuerier('querySelector');\n\n \/**\n * Finds a all DOM elements matching `selector` within the optional\n * `context` of another DOM element (defaulting to `document`).\n *\n * @param {string} selector\n * A valid CSS selector, which will be passed to `querySelectorAll`.\n *\n * @param {Element|String} [context=document]\n * A DOM element within which to query. Can also be a selector\n * string in which case the first matching element will be used\n * as context. If missing (or no element matches selector), falls\n * back to `document`.\n *\n * @return {NodeList}\n * A element list of elements that were found. Will be empty if none\n * were found.\n *\n *\/\n const $$ = createQuerier('querySelectorAll');\n\n \/**\n * A safe getComputedStyle.\n *\n * This is needed because in Firefox, if the player is loaded in an iframe with\n * `display:none`, then `getComputedStyle` returns `null`, so, we do a\n * null-check to make sure that the player doesn't break in these cases.\n *\n * @param {Element} el\n * The element you want the computed style of\n *\n * @param {string} prop\n * The property name you want\n *\n * @see https:\/\/bugzilla.mozilla.org\/show_bug.cgi?id=548397\n *\/\n function computedStyle(el, prop) {\n if (!el || !prop) {\n return '';\n }\n if (typeof window.getComputedStyle === 'function') {\n let computedStyleValue;\n try {\n computedStyleValue = window.getComputedStyle(el);\n } catch (e) {\n return '';\n }\n return computedStyleValue ? computedStyleValue.getPropertyValue(prop) || computedStyleValue[prop] : '';\n }\n return '';\n }\n\n \/**\n * Copy document style sheets to another window.\n *\n * @param {Window} win\n * The window element you want to copy the document style sheets to.\n *\n *\/\n function copyStyleSheetsToWindow(win) {\n [...document.styleSheets].forEach(styleSheet => {\n try {\n const cssRules = [...styleSheet.cssRules].map(rule => rule.cssText).join('');\n const style = document.createElement('style');\n style.textContent = cssRules;\n win.document.head.appendChild(style);\n } catch (e) {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.type = styleSheet.type;\n \/\/ For older Safari this has to be the string; on other browsers setting the MediaList works\n link.media = styleSheet.media.mediaText;\n link.href = styleSheet.href;\n win.document.head.appendChild(link);\n }\n });\n }\n\n var Dom = \/*#__PURE__*\/Object.freeze({\n __proto__: null,\n isReal: isReal,\n isEl: isEl,\n isInFrame: isInFrame,\n createEl: createEl,\n textContent: textContent,\n prependTo: prependTo,\n hasClass: hasClass,\n addClass: addClass,\n removeClass: removeClass,\n toggleClass: toggleClass,\n setAttributes: setAttributes,\n getAttributes: getAttributes,\n getAttribute: getAttribute,\n setAttribute: setAttribute,\n removeAttribute: removeAttribute,\n blockTextSelection: blockTextSelection,\n unblockTextSelection: unblockTextSelection,\n getBoundingClientRect: getBoundingClientRect,\n findPosition: findPosition,\n getPointerPosition: getPointerPosition,\n isTextNode: isTextNode$1,\n emptyEl: emptyEl,\n normalizeContent: normalizeContent,\n appendContent: appendContent,\n insertContent: insertContent,\n isSingleLeftClick: isSingleLeftClick,\n $: $,\n $$: $$,\n computedStyle: computedStyle,\n copyStyleSheetsToWindow: copyStyleSheetsToWindow\n });\n\n \/**\n * @file setup.js - Functions for setting up a player without\n * user interaction based on the data-setup `attribute` of the video tag.\n *\n * @module setup\n *\/\n let _windowLoaded = false;\n let videojs$1;\n\n \/**\n * Set up any tags that have a data-setup `attribute` when the player is started.\n *\/\n const autoSetup = function () {\n if (videojs$1.options.autoSetup === false) {\n return;\n }\n const vids = Array.prototype.slice.call(document.getElementsByTagName('video'));\n const audios = Array.prototype.slice.call(document.getElementsByTagName('audio'));\n const divs = Array.prototype.slice.call(document.getElementsByTagName('video-js'));\n const mediaEls = vids.concat(audios, divs);\n\n \/\/ Check if any media elements exist\n if (mediaEls && mediaEls.length > 0) {\n for (let i = 0, e = mediaEls.length; i < e; i++) {\n const mediaEl = mediaEls[i];\n\n \/\/ Check if element exists, has getAttribute func.\n if (mediaEl && mediaEl.getAttribute) {\n \/\/ Make sure this player hasn't already been set up.\n if (mediaEl.player === undefined) {\n const options = mediaEl.getAttribute('data-setup');\n\n \/\/ Check if data-setup attr exists.\n \/\/ We only auto-setup if they've added the data-setup attr.\n if (options !== null) {\n \/\/ Create new video.js instance.\n videojs$1(mediaEl);\n }\n }\n\n \/\/ If getAttribute isn't defined, we need to wait for the DOM.\n } else {\n autoSetupTimeout(1);\n break;\n }\n }\n\n \/\/ No videos were found, so keep looping unless page is finished loading.\n } else if (!_windowLoaded) {\n autoSetupTimeout(1);\n }\n };\n\n \/**\n * Wait until the page is loaded before running autoSetup. This will be called in\n * autoSetup if `hasLoaded` returns false.\n *\n * @param {number} wait\n * How long to wait in ms\n *\n * @param {module:videojs} [vjs]\n * The videojs library function\n *\/\n function autoSetupTimeout(wait, vjs) {\n \/\/ Protect against breakage in non-browser environments\n if (!isReal()) {\n return;\n }\n if (vjs) {\n videojs$1 = vjs;\n }\n window.setTimeout(autoSetup, wait);\n }\n\n \/**\n * Used to set the internal tracking of window loaded state to true.\n *\n * @private\n *\/\n function setWindowLoaded() {\n _windowLoaded = true;\n window.removeEventListener('load', setWindowLoaded);\n }\n if (isReal()) {\n if (document.readyState === 'complete') {\n setWindowLoaded();\n } else {\n \/**\n * Listen for the load event on window, and set _windowLoaded to true.\n *\n * We use a standard event listener here to avoid incrementing the GUID\n * before any players are created.\n *\n * @listens load\n *\/\n window.addEventListener('load', setWindowLoaded);\n }\n }\n\n \/**\n * @file stylesheet.js\n * @module stylesheet\n *\/\n\n \/**\n * Create a DOM style element given a className for it.\n *\n * @param {string} className\n * The className to add to the created style element.\n *\n * @return {Element}\n * The element that was created.\n *\/\n const createStyleElement = function (className) {\n const style = document.createElement('style');\n style.className = className;\n return style;\n };\n\n \/**\n * Add text to a DOM element.\n *\n * @param {Element} el\n * The Element to add text content to.\n *\n * @param {string} content\n * The text to add to the element.\n *\/\n const setTextContent = function (el, content) {\n if (el.styleSheet) {\n el.styleSheet.cssText = content;\n } else {\n el.textContent = content;\n }\n };\n\n \/**\n * @file dom-data.js\n * @module dom-data\n *\/\n\n \/**\n * Element Data Store.\n *\n * Allows for binding data to an element without putting it directly on the\n * element. Ex. Event listeners are stored here.\n * (also from jsninja.com, slightly modified and updated for closure compiler)\n *\n * @type {Object}\n * @private\n *\/\n var DomData = new WeakMap();\n\n \/**\n * @file guid.js\n * @module guid\n *\/\n\n \/\/ Default value for GUIDs. This allows us to reset the GUID counter in tests.\n \/\/\n \/\/ The initial GUID is 3 because some users have come to rely on the first\n \/\/ default player ID ending up as `vjs_video_3`.\n \/\/\n \/\/ See: https:\/\/github.com\/videojs\/video.js\/pull\/6216\n const _initialGuid = 3;\n\n \/**\n * Unique ID for an element or function\n *\n * @type {Number}\n *\/\n let _guid = _initialGuid;\n\n \/**\n * Get a unique auto-incrementing ID by number that has not been returned before.\n *\n * @return {number}\n * A new unique ID.\n *\/\n function newGUID() {\n return _guid++;\n }\n\n \/**\n * @file events.js. An Event System (John Resig - Secrets of a JS Ninja http:\/\/jsninja.com\/)\n * (Original book version wasn't completely usable, so fixed some things and made Closure Compiler compatible)\n * This should work very similarly to jQuery's events, however it's based off the book version which isn't as\n * robust as jquery's, so there's probably some differences.\n *\n * @file events.js\n * @module events\n *\/\n\n \/**\n * Clean up the listener cache and dispatchers\n *\n * @param {Element|Object} elem\n * Element to clean up\n *\n * @param {string} type\n * Type of event to clean up\n *\/\n function _cleanUpEvents(elem, type) {\n if (!DomData.has(elem)) {\n return;\n }\n const data = DomData.get(elem);\n\n \/\/ Remove the events of a particular type if there are none left\n if (data.handlers[type].length === 0) {\n delete data.handlers[type];\n \/\/ data.handlers[type] = null;\n \/\/ Setting to null was causing an error with data.handlers\n\n \/\/ Remove the meta-handler from the element\n if (elem.removeEventListener) {\n elem.removeEventListener(type, data.dispatcher, false);\n } else if (elem.detachEvent) {\n elem.detachEvent('on' + type, data.dispatcher);\n }\n }\n\n \/\/ Remove the events object if there are no types left\n if (Object.getOwnPropertyNames(data.handlers).length <= 0) {\n delete data.handlers;\n delete data.dispatcher;\n delete data.disabled;\n }\n\n \/\/ Finally remove the element data if there is no data left\n if (Object.getOwnPropertyNames(data).length === 0) {\n DomData.delete(elem);\n }\n }\n\n \/**\n * Loops through an array of event types and calls the requested method for each type.\n *\n * @param {Function} fn\n * The event method we want to use.\n *\n * @param {Element|Object} elem\n * Element or object to bind listeners to\n *\n * @param {string[]} types\n * Type of event to bind to.\n *\n * @param {Function} callback\n * Event listener.\n *\/\n function _handleMultipleEvents(fn, elem, types, callback) {\n types.forEach(function (type) {\n \/\/ Call the event method for each one of the types\n fn(elem, type, callback);\n });\n }\n\n \/**\n * Fix a native event to have standard property values\n *\n * @param {Object} event\n * Event object to fix.\n *\n * @return {Object}\n * Fixed event object.\n *\/\n function fixEvent(event) {\n if (event.fixed_) {\n return event;\n }\n function returnTrue() {\n return true;\n }\n function returnFalse() {\n return false;\n }\n\n \/\/ Test if fixing up is needed\n \/\/ Used to check if !event.stopPropagation instead of isPropagationStopped\n \/\/ But native events return true for stopPropagation, but don't have\n \/\/ other expected methods like isPropagationStopped. Seems to be a problem\n \/\/ with the Javascript Ninja code. So we're just overriding all events now.\n if (!event || !event.isPropagationStopped || !event.isImmediatePropagationStopped) {\n const old = event || window.event;\n event = {};\n \/\/ Clone the old object so that we can modify the values event = {};\n \/\/ IE8 Doesn't like when you mess with native event properties\n \/\/ Firefox returns false for event.hasOwnProperty('type') and other props\n \/\/ which makes copying more difficult.\n\n \/\/ TODO: Probably best to create an allowlist of event props\n const deprecatedProps = ['layerX', 'layerY', 'keyLocation', 'path', 'webkitMovementX', 'webkitMovementY', 'mozPressure', 'mozInputSource'];\n for (const key in old) {\n \/\/ Safari 6.0.3 warns you if you try to copy deprecated layerX\/Y\n \/\/ Chrome warns you if you try to copy deprecated keyboardEvent.keyLocation\n \/\/ and webkitMovementX\/Y\n \/\/ Lighthouse complains if Event.path is copied\n if (!deprecatedProps.includes(key)) {\n \/\/ Chrome 32+ warns if you try to copy deprecated returnValue, but\n \/\/ we still want to if preventDefault isn't supported (IE8).\n if (!(key === 'returnValue' && old.preventDefault)) {\n event[key] = old[key];\n }\n }\n }\n\n \/\/ The event occurred on this element\n if (!event.target) {\n event.target = event.srcElement || document;\n }\n\n \/\/ Handle which other element the event is related to\n if (!event.relatedTarget) {\n event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;\n }\n\n \/\/ Stop the default browser action\n event.preventDefault = function () {\n if (old.preventDefault) {\n old.preventDefault();\n }\n event.returnValue = false;\n old.returnValue = false;\n event.defaultPrevented = true;\n };\n event.defaultPrevented = false;\n\n \/\/ Stop the event from bubbling\n event.stopPropagation = function () {\n if (old.stopPropagation) {\n old.stopPropagation();\n }\n event.cancelBubble = true;\n old.cancelBubble = true;\n event.isPropagationStopped = returnTrue;\n };\n event.isPropagationStopped = returnFalse;\n\n \/\/ Stop the event from bubbling and executing other handlers\n event.stopImmediatePropagation = function () {\n if (old.stopImmediatePropagation) {\n old.stopImmediatePropagation();\n }\n event.isImmediatePropagationStopped = returnTrue;\n event.stopPropagation();\n };\n event.isImmediatePropagationStopped = returnFalse;\n\n \/\/ Handle mouse position\n if (event.clientX !== null && event.clientX !== undefined) {\n const doc = document.documentElement;\n const body = document.body;\n event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);\n event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);\n }\n\n \/\/ Handle key presses\n event.which = event.charCode || event.keyCode;\n\n \/\/ Fix button for mouse clicks:\n \/\/ 0 == left; 1 == middle; 2 == right\n if (event.button !== null && event.button !== undefined) {\n \/\/ The following is disabled because it does not pass videojs-standard\n \/\/ and... yikes.\n \/* eslint-disable *\/\n event.button = event.button & 1 ? 0 : event.button & 4 ? 1 : event.button & 2 ? 2 : 0;\n \/* eslint-enable *\/\n }\n }\n event.fixed_ = true;\n \/\/ Returns fixed-up instance\n return event;\n }\n\n \/**\n * Whether passive event listeners are supported\n *\/\n let _supportsPassive;\n const supportsPassive = function () {\n if (typeof _supportsPassive !== 'boolean') {\n _supportsPassive = false;\n try {\n const opts = Object.defineProperty({}, 'passive', {\n get() {\n _supportsPassive = true;\n }\n });\n window.addEventListener('test', null, opts);\n window.removeEventListener('test', null, opts);\n } catch (e) {\n \/\/ disregard\n }\n }\n return _supportsPassive;\n };\n\n \/**\n * Touch events Chrome expects to be passive\n *\/\n const passiveEvents = ['touchstart', 'touchmove'];\n\n \/**\n * Add an event listener to element\n * It stores the handler function in a separate cache object\n * and adds a generic handler to the element's event,\n * along with a unique id (guid) to the element.\n *\n * @param {Element|Object} elem\n * Element or object to bind listeners to\n *\n * @param {string|string[]} type\n * Type of event to bind to.\n *\n * @param {Function} fn\n * Event listener.\n *\/\n function on(elem, type, fn) {\n if (Array.isArray(type)) {\n return _handleMultipleEvents(on, elem, type, fn);\n }\n if (!DomData.has(elem)) {\n DomData.set(elem, {});\n }\n const data = DomData.get(elem);\n\n \/\/ We need a place to store all our handler data\n if (!data.handlers) {\n data.handlers = {};\n }\n if (!data.handlers[type]) {\n data.handlers[type] = [];\n }\n if (!fn.guid) {\n fn.guid = newGUID();\n }\n data.handlers[type].push(fn);\n if (!data.dispatcher) {\n data.disabled = false;\n data.dispatcher = function (event, hash) {\n if (data.disabled) {\n return;\n }\n event = fixEvent(event);\n const handlers = data.handlers[event.type];\n if (handlers) {\n \/\/ Copy handlers so if handlers are added\/removed during the process it doesn't throw everything off.\n const handlersCopy = handlers.slice(0);\n for (let m = 0, n = handlersCopy.length; m < n; m++) {\n if (event.isImmediatePropagationStopped()) {\n break;\n } else {\n try {\n handlersCopy[m].call(elem, event, hash);\n } catch (e) {\n log$1.error(e);\n }\n }\n }\n }\n };\n }\n if (data.handlers[type].length === 1) {\n if (elem.addEventListener) {\n let options = false;\n if (supportsPassive() && passiveEvents.indexOf(type) > -1) {\n options = {\n passive: true\n };\n }\n elem.addEventListener(type, data.dispatcher, options);\n } else if (elem.attachEvent) {\n elem.attachEvent('on' + type, data.dispatcher);\n }\n }\n }\n\n \/**\n * Removes event listeners from an element\n *\n * @param {Element|Object} elem\n * Object to remove listeners from.\n *\n * @param {string|string[]} [type]\n * Type of listener to remove. Don't include to remove all events from element.\n *\n * @param {Function} [fn]\n * Specific listener to remove. Don't include to remove listeners for an event\n * type.\n *\/\n function off(elem, type, fn) {\n \/\/ Don't want to add a cache object through getElData if not needed\n if (!DomData.has(elem)) {\n return;\n }\n const data = DomData.get(elem);\n\n \/\/ If no events exist, nothing to unbind\n if (!data.handlers) {\n return;\n }\n if (Array.isArray(type)) {\n return _handleMultipleEvents(off, elem, type, fn);\n }\n\n \/\/ Utility function\n const removeType = function (el, t) {\n data.handlers[t] = [];\n _cleanUpEvents(el, t);\n };\n\n \/\/ Are we removing all bound events?\n if (type === undefined) {\n for (const t in data.handlers) {\n if (Object.prototype.hasOwnProperty.call(data.handlers || {}, t)) {\n removeType(elem, t);\n }\n }\n return;\n }\n const handlers = data.handlers[type];\n\n \/\/ If no handlers exist, nothing to unbind\n if (!handlers) {\n return;\n }\n\n \/\/ If no listener was provided, remove all listeners for type\n if (!fn) {\n removeType(elem, type);\n return;\n }\n\n \/\/ We're only removing a single handler\n if (fn.guid) {\n for (let n = 0; n < handlers.length; n++) {\n if (handlers[n].guid === fn.guid) {\n handlers.splice(n--, 1);\n }\n }\n }\n _cleanUpEvents(elem, type);\n }\n\n \/**\n * Trigger an event for an element\n *\n * @param {Element|Object} elem\n * Element to trigger an event on\n *\n * @param {EventTarget~Event|string} event\n * A string (the type) or an event object with a type attribute\n *\n * @param {Object} [hash]\n * data hash to pass along with the event\n *\n * @return {boolean|undefined}\n * Returns the opposite of `defaultPrevented` if default was\n * prevented. Otherwise, returns `undefined`\n *\/\n function trigger(elem, event, hash) {\n \/\/ Fetches element data and a reference to the parent (for bubbling).\n \/\/ Don't want to add a data object to cache for every parent,\n \/\/ so checking hasElData first.\n const elemData = DomData.has(elem) ? DomData.get(elem) : {};\n const parent = elem.parentNode || elem.ownerDocument;\n \/\/ type = event.type || event,\n \/\/ handler;\n\n \/\/ If an event name was passed as a string, creates an event out of it\n if (typeof event === 'string') {\n event = {\n type: event,\n target: elem\n };\n } else if (!event.target) {\n event.target = elem;\n }\n\n \/\/ Normalizes the event properties.\n event = fixEvent(event);\n\n \/\/ If the passed element has a dispatcher, executes the established handlers.\n if (elemData.dispatcher) {\n elemData.dispatcher.call(elem, event, hash);\n }\n\n \/\/ Unless explicitly stopped or the event does not bubble (e.g. media events)\n \/\/ recursively calls this function to bubble the event up the DOM.\n if (parent && !event.isPropagationStopped() && event.bubbles === true) {\n trigger.call(null, parent, event, hash);\n\n \/\/ If at the top of the DOM, triggers the default action unless disabled.\n } else if (!parent && !event.defaultPrevented && event.target && event.target[event.type]) {\n if (!DomData.has(event.target)) {\n DomData.set(event.target, {});\n }\n const targetData = DomData.get(event.target);\n\n \/\/ Checks if the target has a default action for this event.\n if (event.target[event.type]) {\n \/\/ Temporarily disables event dispatching on the target as we have already executed the handler.\n targetData.disabled = true;\n \/\/ Executes the default action.\n if (typeof event.target[event.type] === 'function') {\n event.target[event.type]();\n }\n \/\/ Re-enables event dispatching.\n targetData.disabled = false;\n }\n }\n\n \/\/ Inform the triggerer if the default was prevented by returning false\n return !event.defaultPrevented;\n }\n\n \/**\n * Trigger a listener only once for an event.\n *\n * @param {Element|Object} elem\n * Element or object to bind to.\n *\n * @param {string|string[]} type\n * Name\/type of event\n *\n * @param {Event~EventListener} fn\n * Event listener function\n *\/\n function one(elem, type, fn) {\n if (Array.isArray(type)) {\n return _handleMultipleEvents(one, elem, type, fn);\n }\n const func = function () {\n off(elem, type, func);\n fn.apply(this, arguments);\n };\n\n \/\/ copy the guid to the new function so it can removed using the original function's ID\n func.guid = fn.guid = fn.guid || newGUID();\n on(elem, type, func);\n }\n\n \/**\n * Trigger a listener only once and then turn if off for all\n * configured events\n *\n * @param {Element|Object} elem\n * Element or object to bind to.\n *\n * @param {string|string[]} type\n * Name\/type of event\n *\n * @param {Event~EventListener} fn\n * Event listener function\n *\/\n function any(elem, type, fn) {\n const func = function () {\n off(elem, type, func);\n fn.apply(this, arguments);\n };\n\n \/\/ copy the guid to the new function so it can removed using the original function's ID\n func.guid = fn.guid = fn.guid || newGUID();\n\n \/\/ multiple ons, but one off for everything\n on(elem, type, func);\n }\n\n var Events = \/*#__PURE__*\/Object.freeze({\n __proto__: null,\n fixEvent: fixEvent,\n on: on,\n off: off,\n trigger: trigger,\n one: one,\n any: any\n });\n\n \/**\n * @file fn.js\n * @module fn\n *\/\n const UPDATE_REFRESH_INTERVAL = 30;\n\n \/**\n * A private, internal-only function for changing the context of a function.\n *\n * It also stores a unique id on the function so it can be easily removed from\n * events.\n *\n * @private\n * @function\n * @param {*} context\n * The object to bind as scope.\n *\n * @param {Function} fn\n * The function to be bound to a scope.\n *\n * @param {number} [uid]\n * An optional unique ID for the function to be set\n *\n * @return {Function}\n * The new function that will be bound into the context given\n *\/\n const bind_ = function (context, fn, uid) {\n \/\/ Make sure the function has a unique ID\n if (!fn.guid) {\n fn.guid = newGUID();\n }\n\n \/\/ Create the new function that changes the context\n const bound = fn.bind(context);\n\n \/\/ Allow for the ability to individualize this function\n \/\/ Needed in the case where multiple objects might share the same prototype\n \/\/ IF both items add an event listener with the same function, then you try to remove just one\n \/\/ it will remove both because they both have the same guid.\n \/\/ when using this, you need to use the bind method when you remove the listener as well.\n \/\/ currently used in text tracks\n bound.guid = uid ? uid + '_' + fn.guid : fn.guid;\n return bound;\n };\n\n \/**\n * Wraps the given function, `fn`, with a new function that only invokes `fn`\n * at most once per every `wait` milliseconds.\n *\n * @function\n * @param {Function} fn\n * The function to be throttled.\n *\n * @param {number} wait\n * The number of milliseconds by which to throttle.\n *\n * @return {Function}\n *\/\n const throttle = function (fn, wait) {\n let last = window.performance.now();\n const throttled = function (...args) {\n const now = window.performance.now();\n if (now - last >= wait) {\n fn(...args);\n last = now;\n }\n };\n return throttled;\n };\n\n \/**\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked.\n *\n * Inspired by lodash and underscore implementations.\n *\n * @function\n * @param {Function} func\n * The function to wrap with debounce behavior.\n *\n * @param {number} wait\n * The number of milliseconds to wait after the last invocation.\n *\n * @param {boolean} [immediate]\n * Whether or not to invoke the function immediately upon creation.\n *\n * @param {Object} [context=window]\n * The \"context\" in which the debounced function should debounce. For\n * example, if this function should be tied to a Video.js player,\n * the player can be passed here. Alternatively, defaults to the\n * global `window` object.\n *\n * @return {Function}\n * A debounced function.\n *\/\n const debounce = function (func, wait, immediate, context = window) {\n let timeout;\n const cancel = () => {\n context.clearTimeout(timeout);\n timeout = null;\n };\n\n \/* eslint-disable consistent-this *\/\n const debounced = function () {\n const self = this;\n const args = arguments;\n let later = function () {\n timeout = null;\n later = null;\n if (!immediate) {\n func.apply(self, args);\n }\n };\n if (!timeout && immediate) {\n func.apply(self, args);\n }\n context.clearTimeout(timeout);\n timeout = context.setTimeout(later, wait);\n };\n \/* eslint-enable consistent-this *\/\n\n debounced.cancel = cancel;\n return debounced;\n };\n\n var Fn = \/*#__PURE__*\/Object.freeze({\n __proto__: null,\n UPDATE_REFRESH_INTERVAL: UPDATE_REFRESH_INTERVAL,\n bind_: bind_,\n throttle: throttle,\n debounce: debounce\n });\n\n \/**\n * @file src\/js\/event-target.js\n *\/\n let EVENT_MAP;\n\n \/**\n * `EventTarget` is a class that can have the same API as the DOM `EventTarget`. It\n * adds shorthand functions that wrap around lengthy functions. For example:\n * the `on` function is a wrapper around `addEventListener`.\n *\n * @see [EventTarget Spec]{@link https:\/\/www.w3.org\/TR\/DOM-Level-2-Events\/events.html#Events-EventTarget}\n * @class EventTarget\n *\/\n class EventTarget$2 {\n \/**\n * Adds an `event listener` to an instance of an `EventTarget`. An `event listener` is a\n * function that will get called when an event with a certain name gets triggered.\n *\n * @param {string|string[]} type\n * An event name or an array of event names.\n *\n * @param {Function} fn\n * The function to call with `EventTarget`s\n *\/\n on(type, fn) {\n \/\/ Remove the addEventListener alias before calling Events.on\n \/\/ so we don't get into an infinite type loop\n const ael = this.addEventListener;\n this.addEventListener = () => {};\n on(this, type, fn);\n this.addEventListener = ael;\n }\n \/**\n * Removes an `event listener` for a specific event from an instance of `EventTarget`.\n * This makes it so that the `event listener` will no longer get called when the\n * named event happens.\n *\n * @param {string|string[]} type\n * An event name or an array of event names.\n *\n * @param {Function} fn\n * The function to remove.\n *\/\n off(type, fn) {\n off(this, type, fn);\n }\n \/**\n * This function will add an `event listener` that gets triggered only once. After the\n * first trigger it will get removed. This is like adding an `event listener`\n * with {@link EventTarget#on} that calls {@link EventTarget#off} on itself.\n *\n * @param {string|string[]} type\n * An event name or an array of event names.\n *\n * @param {Function} fn\n * The function to be called once for each event name.\n *\/\n one(type, fn) {\n \/\/ Remove the addEventListener aliasing Events.on\n \/\/ so we don't get into an infinite type loop\n const ael = this.addEventListener;\n this.addEventListener = () => {};\n one(this, type, fn);\n this.addEventListener = ael;\n }\n \/**\n * This function will add an `event listener` that gets triggered only once and is\n * removed from all events. This is like adding an array of `event listener`s\n * with {@link EventTarget#on} that calls {@link EventTarget#off} on all events the\n * first time it is triggered.\n *\n * @param {string|string[]} type\n * An event name or an array of event names.\n *\n * @param {Function} fn\n * The function to be called once for each event name.\n *\/\n any(type, fn) {\n \/\/ Remove the addEventListener aliasing Events.on\n \/\/ so we don't get into an infinite type loop\n const ael = this.addEventListener;\n this.addEventListener = () => {};\n any(this, type, fn);\n this.addEventListener = ael;\n }\n \/**\n * This function causes an event to happen. This will then cause any `event listeners`\n * that are waiting for that event, to get called. If there are no `event listeners`\n * for an event then nothing will happen.\n *\n * If the name of the `Event` that is being triggered is in `EventTarget.allowedEvents_`.\n * Trigger will also call the `on` + `uppercaseEventName` function.\n *\n * Example:\n * 'click' is in `EventTarget.allowedEvents_`, so, trigger will attempt to call\n * `onClick` if it exists.\n *\n * @param {string|EventTarget~Event|Object} event\n * The name of the event, an `Event`, or an object with a key of type set to\n * an event name.\n *\/\n trigger(event) {\n const type = event.type || event;\n\n \/\/ deprecation\n \/\/ In a future version we should default target to `this`\n \/\/ similar to how we default the target to `elem` in\n \/\/ `Events.trigger`. Right now the default `target` will be\n \/\/ `document` due to the `Event.fixEvent` call.\n if (typeof event === 'string') {\n event = {\n type\n };\n }\n event = fixEvent(event);\n if (this.allowedEvents_[type] && this['on' + type]) {\n this['on' + type](event);\n }\n trigger(this, event);\n }\n queueTrigger(event) {\n \/\/ only set up EVENT_MAP if it'll be used\n if (!EVENT_MAP) {\n EVENT_MAP = new Map();\n }\n const type = event.type || event;\n let map = EVENT_MAP.get(this);\n if (!map) {\n map = new Map();\n EVENT_MAP.set(this, map);\n }\n const oldTimeout = map.get(type);\n map.delete(type);\n window.clearTimeout(oldTimeout);\n const timeout = window.setTimeout(() => {\n map.delete(type);\n \/\/ if we cleared out all timeouts for the current target, delete its map\n if (map.size === 0) {\n map = null;\n EVENT_MAP.delete(this);\n }\n this.trigger(event);\n }, 0);\n map.set(type, timeout);\n }\n }\n\n \/**\n * A Custom DOM event.\n *\n * @typedef {CustomEvent} Event\n * @see [Properties]{@link https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/CustomEvent}\n *\/\n\n \/**\n * All event listeners should follow the following format.\n *\n * @callback EventListener\n * @this {EventTarget}\n *\n * @param {Event} event\n * the event that triggered this function\n *\n * @param {Object} [hash]\n * hash of data sent during the event\n *\/\n\n \/**\n * An object containing event names as keys and booleans as values.\n *\n * > NOTE: If an event name is set to a true value here {@link EventTarget#trigger}\n * will have extra functionality. See that function for more information.\n *\n * @property EventTarget.prototype.allowedEvents_\n * @protected\n *\/\n EventTarget$2.prototype.allowedEvents_ = {};\n\n \/**\n * An alias of {@link EventTarget#on}. Allows `EventTarget` to mimic\n * the standard DOM API.\n *\n * @function\n * @see {@link EventTarget#on}\n *\/\n EventTarget$2.prototype.addEventListener = EventTarget$2.prototype.on;\n\n \/**\n * An alias of {@link EventTarget#off}. Allows `EventTarget` to mimic\n * the standard DOM API.\n *\n * @function\n * @see {@link EventTarget#off}\n *\/\n EventTarget$2.prototype.removeEventListener = EventTarget$2.prototype.off;\n\n \/**\n * An alias of {@link EventTarget#trigger}. Allows `EventTarget` to mimic\n * the standard DOM API.\n *\n * @function\n * @see {@link EventTarget#trigger}\n *\/\n EventTarget$2.prototype.dispatchEvent = EventTarget$2.prototype.trigger;\n\n \/**\n * @file mixins\/evented.js\n * @module evented\n *\/\n const objName = obj => {\n if (typeof obj.name === 'function') {\n return obj.name();\n }\n if (typeof obj.name === 'string') {\n return obj.name;\n }\n if (obj.name_) {\n return obj.name_;\n }\n if (obj.constructor && obj.constructor.name) {\n return obj.constructor.name;\n }\n return typeof obj;\n };\n\n \/**\n * Returns whether or not an object has had the evented mixin applied.\n *\n * @param {Object} object\n * An object to test.\n *\n * @return {boolean}\n * Whether or not the object appears to be evented.\n *\/\n const isEvented = object => object instanceof EventTarget$2 || !!object.eventBusEl_ && ['on', 'one', 'off', 'trigger'].every(k => typeof object[k] === 'function');\n\n \/**\n * Adds a callback to run after the evented mixin applied.\n *\n * @param {Object} target\n * An object to Add\n * @param {Function} callback\n * The callback to run.\n *\/\n const addEventedCallback = (target, callback) => {\n if (isEvented(target)) {\n callback();\n } else {\n if (!target.eventedCallbacks) {\n target.eventedCallbacks = [];\n }\n target.eventedCallbacks.push(callback);\n }\n };\n\n \/**\n * Whether a value is a valid event type - non-empty string or array.\n *\n * @private\n * @param {string|Array} type\n * The type value to test.\n *\n * @return {boolean}\n * Whether or not the type is a valid event type.\n *\/\n const isValidEventType = type =>\n \/\/ The regex here verifies that the `type` contains at least one non-\n \/\/ whitespace character.\n typeof type === 'string' && \/\\S\/.test(type) || Array.isArray(type) && !!type.length;\n\n \/**\n * Validates a value to determine if it is a valid event target. Throws if not.\n *\n * @private\n * @throws {Error}\n * If the target does not appear to be a valid event target.\n *\n * @param {Object} target\n * The object to test.\n *\n * @param {Object} obj\n * The evented object we are validating for\n *\n * @param {string} fnName\n * The name of the evented mixin function that called this.\n *\/\n const validateTarget = (target, obj, fnName) => {\n if (!target || !target.nodeName && !isEvented(target)) {\n throw new Error(`Invalid target for ${objName(obj)}#${fnName}; must be a DOM node or evented object.`);\n }\n };\n\n \/**\n * Validates a value to determine if it is a valid event target. Throws if not.\n *\n * @private\n * @throws {Error}\n * If the type does not appear to be a valid event type.\n *\n * @param {string|Array} type\n * The type to test.\n *\n * @param {Object} obj\n * The evented object we are validating for\n *\n * @param {string} fnName\n * The name of the evented mixin function that called this.\n *\/\n const validateEventType = (type, obj, fnName) => {\n if (!isValidEventType(type)) {\n throw new Error(`Invalid event type for ${objName(obj)}#${fnName}; must be a non-empty string or array.`);\n }\n };\n\n \/**\n * Validates a value to determine if it is a valid listener. Throws if not.\n *\n * @private\n * @throws {Error}\n * If the listener is not a function.\n *\n * @param {Function} listener\n * The listener to test.\n *\n * @param {Object} obj\n * The evented object we are validating for\n *\n * @param {string} fnName\n * The name of the evented mixin function that called this.\n *\/\n const validateListener = (listener, obj, fnName) => {\n if (typeof listener !== 'function') {\n throw new Error(`Invalid listener for ${objName(obj)}#${fnName}; must be a function.`);\n }\n };\n\n \/**\n * Takes an array of arguments given to `on()` or `one()`, validates them, and\n * normalizes them into an object.\n *\n * @private\n * @param {Object} self\n * The evented object on which `on()` or `one()` was called. This\n * object will be bound as the `this` value for the listener.\n *\n * @param {Array} args\n * An array of arguments passed to `on()` or `one()`.\n *\n * @param {string} fnName\n * The name of the evented mixin function that called this.\n *\n * @return {Object}\n * An object containing useful values for `on()` or `one()` calls.\n *\/\n const normalizeListenArgs = (self, args, fnName) => {\n \/\/ If the number of arguments is less than 3, the target is always the\n \/\/ evented object itself.\n const isTargetingSelf = args.length < 3 || args[0] === self || args[0] === self.eventBusEl_;\n let target;\n let type;\n let listener;\n if (isTargetingSelf) {\n target = self.eventBusEl_;\n\n \/\/ Deal with cases where we got 3 arguments, but we are still listening to\n \/\/ the evented object itself.\n if (args.length >= 3) {\n args.shift();\n }\n [type, listener] = args;\n } else {\n \/\/ This was `[target, type, listener] = args;` but this block needs more than\n \/\/ one statement to produce minified output compatible with Chrome 53.\n \/\/ See https:\/\/github.com\/videojs\/video.js\/pull\/8810\n target = args[0];\n type = args[1];\n listener = args[2];\n }\n validateTarget(target, self, fnName);\n validateEventType(type, self, fnName);\n validateListener(listener, self, fnName);\n listener = bind_(self, listener);\n return {\n isTargetingSelf,\n target,\n type,\n listener\n };\n };\n\n \/**\n * Adds the listener to the event type(s) on the target, normalizing for\n * the type of target.\n *\n * @private\n * @param {Element|Object} target\n * A DOM node or evented object.\n *\n * @param {string} method\n * The event binding method to use (\"on\" or \"one\").\n *\n * @param {string|Array} type\n * One or more event type(s).\n *\n * @param {Function} listener\n * A listener function.\n *\/\n const listen = (target, method, type, listener) => {\n validateTarget(target, target, method);\n if (target.nodeName) {\n Events[method](target, type, listener);\n } else {\n target[method](type, listener);\n }\n };\n\n \/**\n * Contains methods that provide event capabilities to an object which is passed\n * to {@link module:evented|evented}.\n *\n * @mixin EventedMixin\n *\/\n const EventedMixin = {\n \/**\n * Add a listener to an event (or events) on this object or another evented\n * object.\n *\n * @param {string|Array|Element|Object} targetOrType\n * If this is a string or array, it represents the event type(s)\n * that will trigger the listener.\n *\n * Another evented object can be passed here instead, which will\n * cause the listener to listen for events on _that_ object.\n *\n * In either case, the listener's `this` value will be bound to\n * this object.\n *\n * @param {string|Array|Function} typeOrListener\n * If the first argument was a string or array, this should be the\n * listener function. Otherwise, this is a string or array of event\n * type(s).\n *\n * @param {Function} [listener]\n * If the first argument was another evented object, this will be\n * the listener function.\n *\/\n on(...args) {\n const {\n isTargetingSelf,\n target,\n type,\n listener\n } = normalizeListenArgs(this, args, 'on');\n listen(target, 'on', type, listener);\n\n \/\/ If this object is listening to another evented object.\n if (!isTargetingSelf) {\n \/\/ If this object is disposed, remove the listener.\n const removeListenerOnDispose = () => this.off(target, type, listener);\n\n \/\/ Use the same function ID as the listener so we can remove it later it\n \/\/ using the ID of the original listener.\n removeListenerOnDispose.guid = listener.guid;\n\n \/\/ Add a listener to the target's dispose event as well. This ensures\n \/\/ that if the target is disposed BEFORE this object, we remove the\n \/\/ removal listener that was just added. Otherwise, we create a memory leak.\n const removeRemoverOnTargetDispose = () => this.off('dispose', removeListenerOnDispose);\n\n \/\/ Use the same function ID as the listener so we can remove it later\n \/\/ it using the ID of the original listener.\n removeRemoverOnTargetDispose.guid = listener.guid;\n listen(this, 'on', 'dispose', removeListenerOnDispose);\n listen(target, 'on', 'dispose', removeRemoverOnTargetDispose);\n }\n },\n \/**\n * Add a listener to an event (or events) on this object or another evented\n * object. The listener will be called once per event and then removed.\n *\n * @param {string|Array|Element|Object} targetOrType\n * If this is a string or array, it represents the event type(s)\n * that will trigger the listener.\n *\n * Another evented object can be passed here instead, which will\n * cause the listener to listen for events on _that_ object.\n *\n * In either case, the listener's `this` value will be bound to\n * this object.\n *\n * @param {string|Array|Function} typeOrListener\n * If the first argument was a string or array, this should be the\n * listener function. Otherwise, this is a string or array of event\n * type(s).\n *\n * @param {Function} [listener]\n * If the first argument was another evented object, this will be\n * the listener function.\n *\/\n one(...args) {\n const {\n isTargetingSelf,\n target,\n type,\n listener\n } = normalizeListenArgs(this, args, 'one');\n\n \/\/ Targeting this evented object.\n if (isTargetingSelf) {\n listen(target, 'one', type, listener);\n\n \/\/ Targeting another evented object.\n } else {\n \/\/ TODO: This wrapper is incorrect! It should only\n \/\/ remove the wrapper for the event type that called it.\n \/\/ Instead all listeners are removed on the first trigger!\n \/\/ see https:\/\/github.com\/videojs\/video.js\/issues\/5962\n const wrapper = (...largs) => {\n this.off(target, type, wrapper);\n listener.apply(null, largs);\n };\n\n \/\/ Use the same function ID as the listener so we can remove it later\n \/\/ it using the ID of the original listener.\n wrapper.guid = listener.guid;\n listen(target, 'one', type, wrapper);\n }\n },\n \/**\n * Add a listener to an event (or events) on this object or another evented\n * object. The listener will only be called once for the first event that is triggered\n * then removed.\n *\n * @param {string|Array|Element|Object} targetOrType\n * If this is a string or array, it represents the event type(s)\n * that will trigger the listener.\n *\n * Another evented object can be passed here instead, which will\n * cause the listener to listen for events on _that_ object.\n *\n * In either case, the listener's `this` value will be bound to\n * this object.\n *\n * @param {string|Array|Function} typeOrListener\n * If the first argument was a string or array, this should be the\n * listener function. Otherwise, this is a string or array of event\n * type(s).\n *\n * @param {Function} [listener]\n * If the first argument was another evented object, this will be\n * the listener function.\n *\/\n any(...args) {\n const {\n isTargetingSelf,\n target,\n type,\n listener\n } = normalizeListenArgs(this, args, 'any');\n\n \/\/ Targeting this evented object.\n if (isTargetingSelf) {\n listen(target, 'any', type, listener);\n\n \/\/ Targeting another evented object.\n } else {\n const wrapper = (...largs) => {\n this.off(target, type, wrapper);\n listener.apply(null, largs);\n };\n\n \/\/ Use the same function ID as the listener so we can remove it later\n \/\/ it using the ID of the original listener.\n wrapper.guid = listener.guid;\n listen(target, 'any', type, wrapper);\n }\n },\n \/**\n * Removes listener(s) from event(s) on an evented object.\n *\n * @param {string|Array|Element|Object} [targetOrType]\n * If this is a string or array, it represents the event type(s).\n *\n * Another evented object can be passed here instead, in which case\n * ALL 3 arguments are _required_.\n *\n * @param {string|Array|Function} [typeOrListener]\n * If the first argument was a string or array, this may be the\n * listener function. Otherwise, this is a string or array of event\n * type(s).\n *\n * @param {Function} [listener]\n * If the first argument was another evented object, this will be\n * the listener function; otherwise, _all_ listeners bound to the\n * event type(s) will be removed.\n *\/\n off(targetOrType, typeOrListener, listener) {\n \/\/ Targeting this evented object.\n if (!targetOrType || isValidEventType(targetOrType)) {\n off(this.eventBusEl_, targetOrType, typeOrListener);\n\n \/\/ Targeting another evented object.\n } else {\n const target = targetOrType;\n const type = typeOrListener;\n\n \/\/ Fail fast and in a meaningful way!\n validateTarget(target, this, 'off');\n validateEventType(type, this, 'off');\n validateListener(listener, this, 'off');\n\n \/\/ Ensure there's at least a guid, even if the function hasn't been used\n listener = bind_(this, listener);\n\n \/\/ Remove the dispose listener on this evented object, which was given\n \/\/ the same guid as the event listener in on().\n this.off('dispose', listener);\n if (target.nodeName) {\n off(target, type, listener);\n off(target, 'dispose', listener);\n } else if (isEvented(target)) {\n target.off(type, listener);\n target.off('dispose', listener);\n }\n }\n },\n \/**\n * Fire an event on this evented object, causing its listeners to be called.\n *\n * @param {string|Object} event\n * An event type or an object with a type property.\n *\n * @param {Object} [hash]\n * An additional object to pass along to listeners.\n *\n * @return {boolean}\n * Whether or not the default behavior was prevented.\n *\/\n trigger(event, hash) {\n validateTarget(this.eventBusEl_, this, 'trigger');\n const type = event && typeof event !== 'string' ? event.type : event;\n if (!isValidEventType(type)) {\n throw new Error(`Invalid event type for ${objName(this)}#trigger; ` + 'must be a non-empty string or object with a type key that has a non-empty value.');\n }\n return trigger(this.eventBusEl_, event, hash);\n }\n };\n\n \/**\n * Applies {@link module:evented~EventedMixin|EventedMixin} to a target object.\n *\n * @param {Object} target\n * The object to which to add event methods.\n *\n * @param {Object} [options={}]\n * Options for customizing the mixin behavior.\n *\n * @param {string} [options.eventBusKey]\n * By default, adds a `eventBusEl_` DOM element to the target object,\n * which is used as an event bus. If the target object already has a\n * DOM element that should be used, pass its key here.\n *\n * @return {Object}\n * The target object.\n *\/\n function evented(target, options = {}) {\n const {\n eventBusKey\n } = options;\n\n \/\/ Set or create the eventBusEl_.\n if (eventBusKey) {\n if (!target[eventBusKey].nodeName) {\n throw new Error(`The eventBusKey \"${eventBusKey}\" does not refer to an element.`);\n }\n target.eventBusEl_ = target[eventBusKey];\n } else {\n target.eventBusEl_ = createEl('span', {\n className: 'vjs-event-bus'\n });\n }\n Object.assign(target, EventedMixin);\n if (target.eventedCallbacks) {\n target.eventedCallbacks.forEach(callback => {\n callback();\n });\n }\n\n \/\/ When any evented object is disposed, it removes all its listeners.\n target.on('dispose', () => {\n target.off();\n [target, target.el_, target.eventBusEl_].forEach(function (val) {\n if (val && DomData.has(val)) {\n DomData.delete(val);\n }\n });\n window.setTimeout(() => {\n target.eventBusEl_ = null;\n }, 0);\n });\n return target;\n }\n\n \/**\n * @file mixins\/stateful.js\n * @module stateful\n *\/\n\n \/**\n * Contains methods that provide statefulness to an object which is passed\n * to {@link module:stateful}.\n *\n * @mixin StatefulMixin\n *\/\n const StatefulMixin = {\n \/**\n * A hash containing arbitrary keys and values representing the state of\n * the object.\n *\n * @type {Object}\n *\/\n state: {},\n \/**\n * Set the state of an object by mutating its\n * {@link module:stateful~StatefulMixin.state|state} object in place.\n *\n * @fires module:stateful~StatefulMixin#statechanged\n * @param {Object|Function} stateUpdates\n * A new set of properties to shallow-merge into the plugin state.\n * Can be a plain object or a function returning a plain object.\n *\n * @return {Object|undefined}\n * An object containing changes that occurred. If no changes\n * occurred, returns `undefined`.\n *\/\n setState(stateUpdates) {\n \/\/ Support providing the `stateUpdates` state as a function.\n if (typeof stateUpdates === 'function') {\n stateUpdates = stateUpdates();\n }\n let changes;\n each(stateUpdates, (value, key) => {\n \/\/ Record the change if the value is different from what's in the\n \/\/ current state.\n if (this.state[key] !== value) {\n changes = changes || {};\n changes[key] = {\n from: this.state[key],\n to: value\n };\n }\n this.state[key] = value;\n });\n\n \/\/ Only trigger \"statechange\" if there were changes AND we have a trigger\n \/\/ function. This allows us to not require that the target object be an\n \/\/ evented object.\n if (changes && isEvented(this)) {\n \/**\n * An event triggered on an object that is both\n * {@link module:stateful|stateful} and {@link module:evented|evented}\n * indicating that its state has changed.\n *\n * @event module:stateful~StatefulMixin#statechanged\n * @type {Object}\n * @property {Object} changes\n * A hash containing the properties that were changed and\n * the values they were changed `from` and `to`.\n *\/\n this.trigger({\n changes,\n type: 'statechanged'\n });\n }\n return changes;\n }\n };\n\n \/**\n * Applies {@link module:stateful~StatefulMixin|StatefulMixin} to a target\n * object.\n *\n * If the target object is {@link module:evented|evented} and has a\n * `handleStateChanged` method, that method will be automatically bound to the\n * `statechanged` event on itself.\n *\n * @param {Object} target\n * The object to be made stateful.\n *\n * @param {Object} [defaultState]\n * A default set of properties to populate the newly-stateful object's\n * `state` property.\n *\n * @return {Object}\n * Returns the `target`.\n *\/\n function stateful(target, defaultState) {\n Object.assign(target, StatefulMixin);\n\n \/\/ This happens after the mixing-in because we need to replace the `state`\n \/\/ added in that step.\n target.state = Object.assign({}, target.state, defaultState);\n\n \/\/ Auto-bind the `handleStateChanged` method of the target object if it exists.\n if (typeof target.handleStateChanged === 'function' && isEvented(target)) {\n target.on('statechanged', target.handleStateChanged);\n }\n return target;\n }\n\n \/**\n * @file str.js\n * @module to-lower-case\n *\/\n\n \/**\n * Lowercase the first letter of a string.\n *\n * @param {string} string\n * String to be lowercased\n *\n * @return {string}\n * The string with a lowercased first letter\n *\/\n const toLowerCase = function (string) {\n if (typeof string !== 'string') {\n return string;\n }\n return string.replace(\/.\/, w => w.toLowerCase());\n };\n\n \/**\n * Uppercase the first letter of a string.\n *\n * @param {string} string\n * String to be uppercased\n *\n * @return {string}\n * The string with an uppercased first letter\n *\/\n const toTitleCase$1 = function (string) {\n if (typeof string !== 'string') {\n return string;\n }\n return string.replace(\/.\/, w => w.toUpperCase());\n };\n\n \/**\n * Compares the TitleCase versions of the two strings for equality.\n *\n * @param {string} str1\n * The first string to compare\n *\n * @param {string} str2\n * The second string to compare\n *\n * @return {boolean}\n * Whether the TitleCase versions of the strings are equal\n *\/\n const titleCaseEquals = function (str1, str2) {\n return toTitleCase$1(str1) === toTitleCase$1(str2);\n };\n\n var Str = \/*#__PURE__*\/Object.freeze({\n __proto__: null,\n toLowerCase: toLowerCase,\n toTitleCase: toTitleCase$1,\n titleCaseEquals: titleCaseEquals\n });\n\n \/**\n * Player Component - Base class for all UI objects\n *\n * @file component.js\n *\/\n\n \/** @import Player from '.\/player' *\/\n\n \/**\n * A callback to be called if and when the component is ready.\n * `this` will be the Component instance.\n *\n * @callback ReadyCallback\n * @returns {void}\n *\/\n\n \/**\n * Base class for all UI Components.\n * Components are UI objects which represent both a javascript object and an element\n * in the DOM. They can be children of other components, and can have\n * children themselves.\n *\n * Components can also use methods from {@link EventTarget}\n *\/\n class Component$1 {\n \/**\n * Creates an instance of this class.\n *\n * @param {Player} player\n * The `Player` that this class should be attached to.\n *\n * @param {Object} [options]\n * The key\/value store of component options.\n *\n * @param {Object[]} [options.children]\n * An array of children objects to initialize this component with. Children objects have\n * a name property that will be used if more than one component of the same type needs to be\n * added.\n *\n * @param {string} [options.className]\n * A class or space separated list of classes to add the component\n *\n * @param {ReadyCallback} [ready]\n * Function that gets called when the `Component` is ready.\n *\/\n constructor(player, options, ready) {\n \/\/ The component might be the player itself and we can't pass `this` to super\n if (!player && this.play) {\n this.player_ = player = this; \/\/ eslint-disable-line\n } else {\n this.player_ = player;\n }\n this.isDisposed_ = false;\n\n \/\/ Hold the reference to the parent component via `addChild` method\n this.parentComponent_ = null;\n\n \/\/ Make a copy of prototype.options_ to protect against overriding defaults\n this.options_ = merge$2({}, this.options_);\n\n \/\/ Updated options with supplied options\n options = this.options_ = merge$2(this.options_, options);\n\n \/\/ Get ID from options or options element if one is supplied\n this.id_ = options.id || options.el && options.el.id;\n\n \/\/ If there was no ID from the options, generate one\n if (!this.id_) {\n \/\/ Don't require the player ID function in the case of mock players\n const id = player && player.id && player.id() || 'no_player';\n this.id_ = `${id}_component_${newGUID()}`;\n }\n this.name_ = options.name || null;\n\n \/\/ Create element if one wasn't provided in options\n if (options.el) {\n this.el_ = options.el;\n } else if (options.createEl !== false) {\n this.el_ = this.createEl();\n }\n if (options.className && this.el_) {\n options.className.split(' ').forEach(c => this.addClass(c));\n }\n\n \/\/ Remove the placeholder event methods. If the component is evented, the\n \/\/ real methods are added next\n ['on', 'off', 'one', 'any', 'trigger'].forEach(fn => {\n this[fn] = undefined;\n });\n\n \/\/ if evented is anything except false, we want to mixin in evented\n if (options.evented !== false) {\n \/\/ Make this an evented object and use `el_`, if available, as its event bus\n evented(this, {\n eventBusKey: this.el_ ? 'el_' : null\n });\n this.handleLanguagechange = this.handleLanguagechange.bind(this);\n this.on(this.player_, 'languagechange', this.handleLanguagechange);\n }\n stateful(this, this.constructor.defaultState);\n this.children_ = [];\n this.childIndex_ = {};\n this.childNameIndex_ = {};\n this.setTimeoutIds_ = new Set();\n this.setIntervalIds_ = new Set();\n this.rafIds_ = new Set();\n this.namedRafs_ = new Map();\n this.clearingTimersOnDispose_ = false;\n\n \/\/ Add any child components in options\n if (options.initChildren !== false) {\n this.initChildren();\n }\n\n \/\/ Don't want to trigger ready here or it will go before init is actually\n \/\/ finished for all children that run this constructor\n this.ready(ready);\n if (options.reportTouchActivity !== false) {\n this.enableTouchActivity();\n }\n }\n\n \/\/ `on`, `off`, `one`, `any` and `trigger` are here so tsc includes them in definitions.\n \/\/ They are replaced or removed in the constructor\n\n \/**\n * Adds an `event listener` to an instance of an `EventTarget`. An `event listener` is a\n * function that will get called when an event with a certain name gets triggered.\n *\n * @param {string|string[]} type\n * An event name or an array of event names.\n *\n * @param {Function} fn\n * The function to call with `EventTarget`s\n *\/\n on(type, fn) {}\n\n \/**\n * Removes an `event listener` for a specific event from an instance of `EventTarget`.\n * This makes it so that the `event listener` will no longer get called when the\n * named event happens.\n *\n * @param {string|string[]} type\n * An event name or an array of event names.\n *\n * @param {Function} [fn]\n * The function to remove. If not specified, all listeners managed by Video.js will be removed.\n *\/\n off(type, fn) {}\n\n \/**\n * This function will add an `event listener` that gets triggered only once. After the\n * first trigger it will get removed. This is like adding an `event listener`\n * with {@link EventTarget#on} that calls {@link EventTarget#off} on itself.\n *\n * @param {string|string[]} type\n * An event name or an array of event names.\n *\n * @param {Function} fn\n * The function to be called once for each event name.\n *\/\n one(type, fn) {}\n\n \/**\n * This function will add an `event listener` that gets triggered only once and is\n * removed from all events. This is like adding an array of `event listener`s\n * with {@link EventTarget#on} that calls {@link EventTarget#off} on all events the\n * first time it is triggered.\n *\n * @param {string|string[]} type\n * An event name or an array of event names.\n *\n * @param {Function} fn\n * The function to be called once for each event name.\n *\/\n any(type, fn) {}\n\n \/**\n * This function causes an event to happen. This will then cause any `event listeners`\n * that are waiting for that event, to get called. If there are no `event listeners`\n * for an event then nothing will happen.\n *\n * If the name of the `Event` that is being triggered is in `EventTarget.allowedEvents_`.\n * Trigger will also call the `on` + `uppercaseEventName` function.\n *\n * Example:\n * 'click' is in `EventTarget.allowedEvents_`, so, trigger will attempt to call\n * `onClick` if it exists.\n *\n * @param {string|Event|Object} event\n * The name of the event, an `Event`, or an object with a key of type set to\n * an event name.\n *\n * @param {Object} [hash]\n * Optionally extra argument to pass through to an event listener\n *\/\n trigger(event, hash) {}\n\n \/**\n * Dispose of the `Component` and all child components.\n *\n * @fires Component#dispose\n *\n * @param {Object} options\n * @param {Element} options.originalEl element with which to replace player element\n *\/\n dispose(options = {}) {\n \/\/ Bail out if the component has already been disposed.\n if (this.isDisposed_) {\n return;\n }\n if (this.readyQueue_) {\n this.readyQueue_.length = 0;\n }\n\n \/**\n * Triggered when a `Component` is disposed.\n *\n * @event Component#dispose\n * @type {Event}\n *\n * @property {boolean} [bubbles=false]\n * set to false so that the dispose event does not\n * bubble up\n *\/\n this.trigger({\n type: 'dispose',\n bubbles: false\n });\n this.isDisposed_ = true;\n\n \/\/ Dispose all children.\n if (this.children_) {\n for (let i = this.children_.length - 1; i >= 0; i--) {\n if (this.children_[i].dispose) {\n this.children_[i].dispose();\n }\n }\n }\n\n \/\/ Delete child references\n this.children_ = null;\n this.childIndex_ = null;\n this.childNameIndex_ = null;\n this.parentComponent_ = null;\n if (this.el_) {\n \/\/ Remove element from DOM\n if (this.el_.parentNode) {\n if (options.restoreEl) {\n this.el_.parentNode.replaceChild(options.restoreEl, this.el_);\n } else {\n this.el_.parentNode.removeChild(this.el_);\n }\n }\n this.el_ = null;\n }\n\n \/\/ remove reference to the player after disposing of the element\n this.player_ = null;\n }\n\n \/**\n * Determine whether or not this component has been disposed.\n *\n * @return {boolean}\n * If the component has been disposed, will be `true`. Otherwise, `false`.\n *\/\n isDisposed() {\n return Boolean(this.isDisposed_);\n }\n\n \/**\n * Return the {@link Player} that the `Component` has attached to.\n *\n * @return {Player}\n * The player that this `Component` has attached to.\n *\/\n player() {\n return this.player_;\n }\n\n \/**\n * Deep merge of options objects with new options.\n * > Note: When both `obj` and `options` contain properties whose values are objects.\n * The two properties get merged using {@link module:obj.merge}\n *\n * @param {Object} obj\n * The object that contains new options.\n *\n * @return {Object}\n * A new object of `this.options_` and `obj` merged together.\n *\/\n options(obj) {\n if (!obj) {\n return this.options_;\n }\n this.options_ = merge$2(this.options_, obj);\n return this.options_;\n }\n\n \/**\n * Get the `Component`s DOM element\n *\n * @return {Element}\n * The DOM element for this `Component`.\n *\/\n el() {\n return this.el_;\n }\n\n \/**\n * Create the `Component`s DOM element.\n *\n * @param {string} [tagName]\n * Element's DOM node type. e.g. 'div'\n *\n * @param {Object} [properties]\n * An object of properties that should be set.\n *\n * @param {Object} [attributes]\n * An object of attributes that should be set.\n *\n * @return {Element}\n * The element that gets created.\n *\/\n createEl(tagName, properties, attributes) {\n return createEl(tagName, properties, attributes);\n }\n\n \/**\n * Localize a string given the string in english.\n *\n * If tokens are provided, it'll try and run a simple token replacement on the provided string.\n * The tokens it looks for look like `{1}` with the index being 1-indexed into the tokens array.\n *\n * If a `defaultValue` is provided, it'll use that over `string`,\n * if a value isn't found in provided language files.\n * This is useful if you want to have a descriptive key for token replacement\n * but have a succinct localized string and not require `en.json` to be included.\n *\n * Currently, it is used for the progress bar timing.\n * ```js\n * {\n * \"progress bar timing: currentTime={1} duration={2}\": \"{1} of {2}\"\n * }\n * ```\n * It is then used like so:\n * ```js\n * this.localize('progress bar timing: currentTime={1} duration{2}',\n * [this.player_.currentTime(), this.player_.duration()],\n * '{1} of {2}');\n * ```\n *\n * Which outputs something like: `01:23 of 24:56`.\n *\n *\n * @param {string} string\n * The string to localize and the key to lookup in the language files.\n * @param {string[]} [tokens]\n * If the current item has token replacements, provide the tokens here.\n * @param {string} [defaultValue]\n * Defaults to `string`. Can be a default value to use for token replacement\n * if the lookup key is needed to be separate.\n *\n * @return {string}\n * The localized string or if no localization exists the english string.\n *\/\n localize(string, tokens, defaultValue = string) {\n const code = this.player_.language && this.player_.language();\n const languages = this.player_.languages && this.player_.languages();\n const language = languages && languages[code];\n const primaryCode = code && code.split('-')[0];\n const primaryLang = languages && languages[primaryCode];\n let localizedString = defaultValue;\n if (language && language[string]) {\n localizedString = language[string];\n } else if (primaryLang && primaryLang[string]) {\n localizedString = primaryLang[string];\n }\n if (tokens) {\n localizedString = localizedString.replace(\/\\{(\\d+)\\}\/g, function (match, index) {\n const value = tokens[index - 1];\n let ret = value;\n if (typeof value === 'undefined') {\n ret = match;\n }\n return ret;\n });\n }\n return localizedString;\n }\n\n \/**\n * Handles language change for the player in components. Should be overridden by sub-components.\n *\n * @abstract\n *\/\n handleLanguagechange() {}\n\n \/**\n * Return the `Component`s DOM element. This is where children get inserted.\n * This will usually be the the same as the element returned in {@link Component#el}.\n *\n * @return {Element}\n * The content element for this `Component`.\n *\/\n contentEl() {\n return this.contentEl_ || this.el_;\n }\n\n \/**\n * Get this `Component`s ID\n *\n * @return {string}\n * The id of this `Component`\n *\/\n id() {\n return this.id_;\n }\n\n \/**\n * Get the `Component`s name. The name gets used to reference the `Component`\n * and is set during registration.\n *\n * @return {string}\n * The name of this `Component`.\n *\/\n name() {\n return this.name_;\n }\n\n \/**\n * Get an array of all child components\n *\n * @return {Array}\n * The children\n *\/\n children() {\n return this.children_;\n }\n\n \/**\n * Returns the child `Component` with the given `id`.\n *\n * @param {string} id\n * The id of the child `Component` to get.\n *\n * @return {Component|undefined}\n * The child `Component` with the given `id` or undefined.\n *\/\n getChildById(id) {\n return this.childIndex_[id];\n }\n\n \/**\n * Returns the child `Component` with the given `name`.\n *\n * @param {string} name\n * The name of the child `Component` to get.\n *\n * @return {Component|undefined}\n * The child `Component` with the given `name` or undefined.\n *\/\n getChild(name) {\n if (!name) {\n return;\n }\n return this.childNameIndex_[name];\n }\n\n \/**\n * Returns the descendant `Component` following the givent\n * descendant `names`. For instance ['foo', 'bar', 'baz'] would\n * try to get 'foo' on the current component, 'bar' on the 'foo'\n * component and 'baz' on the 'bar' component and return undefined\n * if any of those don't exist.\n *\n * @param {...string[]|...string} names\n * The name of the child `Component` to get.\n *\n * @return {Component|undefined}\n * The descendant `Component` following the given descendant\n * `names` or undefined.\n *\/\n getDescendant(...names) {\n \/\/ flatten array argument into the main array\n names = names.reduce((acc, n) => acc.concat(n), []);\n let currentChild = this;\n for (let i = 0; i < names.length; i++) {\n currentChild = currentChild.getChild(names[i]);\n if (!currentChild || !currentChild.getChild) {\n return;\n }\n }\n return currentChild;\n }\n\n \/**\n * Adds an SVG icon element to another element or component.\n *\n * @param {string} iconName\n * The name of icon. A list of all the icon names can be found at 'sandbox\/svg-icons.html'\n *\n * @param {Element} [el=this.el()]\n * Element to set the title on. Defaults to the current Component's element.\n *\n * @return {Element}\n * The newly created icon element.\n *\/\n setIcon(iconName, el = this.el()) {\n \/\/ TODO: In v9 of video.js, we will want to remove font icons entirely.\n \/\/ This means this check, as well as the others throughout the code, and\n \/\/ the unecessary CSS for font icons, will need to be removed.\n \/\/ See https:\/\/github.com\/videojs\/video.js\/pull\/8260 as to which components\n \/\/ need updating.\n if (!this.player_.options_.experimentalSvgIcons) {\n return;\n }\n const xmlnsURL = 'http:\/\/www.w3.org\/2000\/svg';\n\n \/\/ The below creates an element in the format of:\n \/\/