diff options
author | Sam Potts <sam@potts.es> | 2019-06-01 18:45:07 +1000 |
---|---|---|
committer | Sam Potts <sam@potts.es> | 2019-06-01 18:45:07 +1000 |
commit | c9055f391b3782d96d16fb6efa4337dc90120635 (patch) | |
tree | 6cd7d1fc8627bbe62f4f714a99fe3cd2ec49db09 /dist/plyr.js | |
parent | 5ddd9e02def654bb677c988403dbefbc4a32787c (diff) | |
download | plyr-c9055f391b3782d96d16fb6efa4337dc90120635.tar.lz plyr-c9055f391b3782d96d16fb6efa4337dc90120635.tar.xz plyr-c9055f391b3782d96d16fb6efa4337dc90120635.zip |
Linting changes
Diffstat (limited to 'dist/plyr.js')
-rw-r--r-- | dist/plyr.js | 1030 |
1 files changed, 578 insertions, 452 deletions
diff --git a/dist/plyr.js b/dist/plyr.js index 11c69184..1d682d32 100644 --- a/dist/plyr.js +++ b/dist/plyr.js @@ -686,6 +686,47 @@ typeof navigator === "object" && (function (global, factory) { }).then(function () {}); } + function cloneDeep(object) { + return JSON.parse(JSON.stringify(object)); + } // Get a nested value in an object + + function getDeep(object, path) { + return path.split('.').reduce(function (obj, key) { + return obj && obj[key]; + }, object); + } // Deep extend destination object with N more objects + + function extend() { + var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + sources[_key - 1] = arguments[_key]; + } + + if (!sources.length) { + return target; + } + + var source = sources.shift(); + + if (!is$1.object(source)) { + return target; + } + + Object.keys(source).forEach(function (key) { + if (is$1.object(source[key])) { + if (!Object.keys(target).includes(key)) { + Object.assign(target, _defineProperty({}, key, {})); + } + + extend(target[key], source[key]); + } else { + Object.assign(target, _defineProperty({}, key, source[key])); + } + }); + return extend.apply(void 0, [target].concat(sources)); + } + function wrap(elements, wrapper) { // Convert `elements` to an array, if necessary. var targets = elements.length ? elements : [elements]; // Loops backwards to prevent having to clone the wrapper on the @@ -809,7 +850,7 @@ typeof navigator === "object" && (function (global, factory) { } var attributes = {}; - var existing = existingAttributes; + var existing = extend({}, existingAttributes); sel.split(',').forEach(function (s) { // Remove whitespace var selector = s.trim(); @@ -817,7 +858,10 @@ typeof navigator === "object" && (function (global, factory) { var stripped = selector.replace(/[[\]]/g, ''); // Get the parts and value var parts = stripped.split('='); - var key = parts[0]; + + var _parts = _slicedToArray(parts, 1), + key = _parts[0]; + var value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; // Get the first character var start = selector.charAt(0); @@ -825,11 +869,12 @@ typeof navigator === "object" && (function (global, factory) { switch (start) { case '.': // Add to existing classname - if (is$1.object(existing) && is$1.string(existing.class)) { - existing.class += " ".concat(className); + if (is$1.string(existing.class)) { + attributes.class = "".concat(existing.class, " ").concat(className); + } else { + attributes.class = className; } - attributes.class = className; break; case '#': @@ -846,7 +891,7 @@ typeof navigator === "object" && (function (global, factory) { break; } }); - return attributes; + return extend(existing, attributes); } // Toggle hidden function toggleHidden(element, hidden) { @@ -898,8 +943,8 @@ typeof navigator === "object" && (function (global, factory) { return Array.from(document.querySelectorAll(selector)).includes(this); } - var matches = match; - return matches.call(element, selector); + var method = match; + return method.call(element, selector); } // Find all elements function getElements(selector) { @@ -1142,8 +1187,16 @@ typeof navigator === "object" && (function (global, factory) { } // Get from embed - if (ratio === null && !is$1.empty(this.embed) && is$1.string(this.embed.ratio)) { - ratio = parse(this.embed.ratio); + if (ratio === null && !is$1.empty(this.embed) && is$1.array(this.embed.ratio)) { + ratio = this.embed.ratio; + } // Get from HTML5 video + + + if (ratio === null && this.isHTML5) { + var _this$media = this.media, + videoWidth = _this$media.videoWidth, + videoHeight = _this$media.videoHeight; + ratio = reduceAspectRatio([videoWidth, videoHeight]); } return ratio; @@ -1219,8 +1272,8 @@ typeof navigator === "object" && (function (global, factory) { get: function get() { // Get sources var sources = html5.getSources.call(player); - var source = sources.find(function (source) { - return source.getAttribute('src') === player.source; + var source = sources.find(function (s) { + return s.getAttribute('src') === player.source; }); // Return size, if match is found return source && Number(source.getAttribute('size')); @@ -1229,8 +1282,8 @@ typeof navigator === "object" && (function (global, factory) { // Get sources var sources = html5.getSources.call(player); // Get first match for requested size - var source = sources.find(function (source) { - return Number(source.getAttribute('size')) === input; + var source = sources.find(function (s) { + return Number(s.getAttribute('size')) === input; }); // No matching source found if (!source) { @@ -1310,47 +1363,6 @@ typeof navigator === "object" && (function (global, factory) { }); } - function cloneDeep(object) { - return JSON.parse(JSON.stringify(object)); - } // Get a nested value in an object - - function getDeep(object, path) { - return path.split('.').reduce(function (obj, key) { - return obj && obj[key]; - }, object); - } // Deep extend destination object with N more objects - - function extend() { - var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - sources[_key - 1] = arguments[_key]; - } - - if (!sources.length) { - return target; - } - - var source = sources.shift(); - - if (!is$1.object(source)) { - return target; - } - - Object.keys(source).forEach(function (key) { - if (is$1.object(source[key])) { - if (!Object.keys(target).includes(key)) { - Object.assign(target, _defineProperty({}, key, {})); - } - - extend(target[key], source[key]); - } else { - Object.assign(target, _defineProperty({}, key, source[key])); - } - }); - return extend.apply(void 0, [target].concat(sources)); - } - // ========================================================================== function generateId(prefix) { @@ -1461,10 +1473,10 @@ typeof navigator === "object" && (function (global, factory) { }; Object.entries(replace).forEach(function (_ref) { var _ref2 = _slicedToArray(_ref, 2), - key = _ref2[0], - value = _ref2[1]; + k = _ref2[0], + v = _ref2[1]; - string = replaceAll(string, key, value); + string = replaceAll(string, k, v); }); return string; } @@ -1599,6 +1611,7 @@ typeof navigator === "object" && (function (global, factory) { }; var update = function update(container, data) { + // eslint-disable-next-line no-param-reassign container.innerHTML = data; // Check again incase of race condition if (hasId && exists()) { @@ -1797,7 +1810,9 @@ typeof navigator === "object" && (function (global, factory) { }, // Create a <button> createButton: function createButton(buttonType, attr) { - var attributes = Object.assign({}, attr); + var _this = this; + + var attributes = extend({}, attr); var type = toCamelCase(buttonType); var props = { element: 'button', @@ -1820,8 +1835,12 @@ typeof navigator === "object" && (function (global, factory) { if (Object.keys(attributes).includes('class')) { - if (!attributes.class.includes(this.config.classNames.control)) { - attributes.class += " ".concat(this.config.classNames.control); + if (!attributes.class.split(' ').some(function (c) { + return c === _this.config.classNames.control; + })) { + extend(attributes, { + class: "".concat(attributes.class, " ").concat(this.config.classNames.control) + }); } } else { attributes.class = this.config.classNames.control; @@ -1965,10 +1984,10 @@ typeof navigator === "object" && (function (global, factory) { return progress; }, // Create time display - createTime: function createTime(type) { - var attributes = getAttributesFromSelector(this.config.selectors.display[type]); + createTime: function createTime(type, attrs) { + var attributes = getAttributesFromSelector(this.config.selectors.display[type], attrs); var container = createElement('div', extend(attributes, { - class: "".concat(this.config.classNames.display.time, " ").concat(attributes.class ? attributes.class : '').trim(), + class: "".concat(attributes.class ? attributes.class : '', " ").concat(this.config.classNames.display.time, " ").trim(), 'aria-label': i18n.get(type, this.config) }), '00:00'); // Reference for updates @@ -1979,7 +1998,7 @@ typeof navigator === "object" && (function (global, factory) { // We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus // https://bugzilla.mozilla.org/show_bug.cgi?id=1220143 bindMenuItemShortcuts: function bindMenuItemShortcuts(menuItem, type) { - var _this = this; + var _this2 = this; // Navigate through menus via arrow keys and space on(menuItem, 'keydown keyup', function (event) { @@ -1999,7 +2018,7 @@ typeof navigator === "object" && (function (global, factory) { var isRadioButton = matches$1(menuItem, '[role="menuitemradio"]'); // Show the respective menu if (!isRadioButton && [32, 39].includes(event.which)) { - controls.showMenuPanel.call(_this, type, true); + controls.showMenuPanel.call(_this2, type, true); } else { var target; @@ -2018,7 +2037,7 @@ typeof navigator === "object" && (function (global, factory) { } } - setFocus.call(_this, target, true); + setFocus.call(_this2, target, true); } } }, false); // Enter will fire a `click` event but we still need to manage focus @@ -2029,12 +2048,12 @@ typeof navigator === "object" && (function (global, factory) { return; } - controls.focusFirstMenuItem.call(_this, null, true); + controls.focusFirstMenuItem.call(_this2, null, true); }); }, // Create a settings menu item createMenuItem: function createMenuItem(_ref) { - var _this2 = this; + var _this3 = this; var value = _ref.value, list = _ref.list, @@ -2067,9 +2086,9 @@ typeof navigator === "object" && (function (global, factory) { get: function get() { return menuItem.getAttribute('aria-checked') === 'true'; }, - set: function set(checked) { + set: function set(check) { // Ensure exclusivity - if (checked) { + if (check) { Array.from(menuItem.parentNode.children).filter(function (node) { return matches$1(node, '[role="menuitemradio"]'); }).forEach(function (node) { @@ -2077,7 +2096,7 @@ typeof navigator === "object" && (function (global, factory) { }); } - menuItem.setAttribute('aria-checked', checked ? 'true' : 'false'); + menuItem.setAttribute('aria-checked', check ? 'true' : 'false'); } }); this.listeners.bind(menuItem, 'click keyup', function (event) { @@ -2091,22 +2110,22 @@ typeof navigator === "object" && (function (global, factory) { switch (type) { case 'language': - _this2.currentTrack = Number(value); + _this3.currentTrack = Number(value); break; case 'quality': - _this2.quality = value; + _this3.quality = value; break; case 'speed': - _this2.speed = parseFloat(value); + _this3.speed = parseFloat(value); break; default: break; } - controls.showMenuPanel.call(_this2, 'home', is$1.keyboardEvent(event)); + controls.showMenuPanel.call(_this3, 'home', is$1.keyboardEvent(event)); }, type, false); controls.bindMenuItemShortcuts.call(this, menuItem, type); list.appendChild(menuItem); @@ -2170,7 +2189,7 @@ typeof navigator === "object" && (function (global, factory) { }, // Update <progress> elements updateProgress: function updateProgress(event) { - var _this3 = this; + var _this4 = this; if (!this.supported.ui || !is$1.event(event)) { return; @@ -2179,16 +2198,16 @@ typeof navigator === "object" && (function (global, factory) { var value = 0; var setProgress = function setProgress(target, input) { - var value = is$1.number(input) ? input : 0; - var progress = is$1.element(target) ? target : _this3.elements.display.buffer; // Update value and label + var val = is$1.number(input) ? input : 0; + var progress = is$1.element(target) ? target : _this4.elements.display.buffer; // Update value and label if (is$1.element(progress)) { - progress.value = value; // Update text label inside + progress.value = val; // Update text label inside var label = progress.getElementsByTagName('span')[0]; if (is$1.element(label)) { - label.childNodes[0].nodeValue = value; + label.childNodes[0].nodeValue = val; } } }; @@ -2252,20 +2271,17 @@ typeof navigator === "object" && (function (global, factory) { }, // Update hover tooltip for seeking updateSeekTooltip: function updateSeekTooltip(event) { - var _this4 = this; + var _this5 = this; // Bail if setting not true if (!this.config.tooltips.seek || !is$1.element(this.elements.inputs.seek) || !is$1.element(this.elements.display.seekTooltip) || this.duration === 0) { return; - } // Calculate percentage - + } - var percent = 0; - var clientRect = this.elements.progress.getBoundingClientRect(); var visible = "".concat(this.config.classNames.tooltip, "--visible"); - var toggle = function toggle(_toggle) { - toggleClass(_this4.elements.display.seekTooltip, visible, _toggle); + var toggle = function toggle(show) { + return toggleClass(_this5.elements.display.seekTooltip, visible, show); }; // Hide on touch @@ -2275,6 +2291,9 @@ typeof navigator === "object" && (function (global, factory) { } // Determine percentage, if already visible + var percent = 0; + var clientRect = this.elements.progress.getBoundingClientRect(); + if (is$1.event(event)) { percent = 100 / clientRect.width * (event.pageX - clientRect.left); } else if (hasClass(this.elements.display.seekTooltip, visible)) { @@ -2431,7 +2450,7 @@ typeof navigator === "object" && (function (global, factory) { }, // Set the quality menu setQualityMenu: function setQualityMenu(options) { - var _this5 = this; + var _this6 = this; // Menu required if (!is$1.element(this.elements.settings.panels.quality)) { @@ -2443,7 +2462,7 @@ typeof navigator === "object" && (function (global, factory) { if (is$1.array(options)) { this.options.quality = dedupe(options).filter(function (quality) { - return _this5.config.quality.options.includes(quality); + return _this6.config.quality.options.includes(quality); }); } // Toggle the pane and tab @@ -2461,25 +2480,25 @@ typeof navigator === "object" && (function (global, factory) { var getBadge = function getBadge(quality) { - var label = i18n.get("qualityBadge.".concat(quality), _this5.config); + var label = i18n.get("qualityBadge.".concat(quality), _this6.config); if (!label.length) { return null; } - return controls.createBadge.call(_this5, label); + return controls.createBadge.call(_this6, label); }; // Sort options by the config and then render options this.options.quality.sort(function (a, b) { - var sorting = _this5.config.quality.options; + var sorting = _this6.config.quality.options; return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1; }).forEach(function (quality) { - controls.createMenuItem.call(_this5, { + controls.createMenuItem.call(_this6, { value: quality, list: list, type: type, - title: controls.getLabel.call(_this5, 'quality', quality), + title: controls.getLabel.call(_this6, 'quality', quality), badge: getBadge(quality) }); }); @@ -2525,7 +2544,7 @@ typeof navigator === "object" && (function (global, factory) { // TODO: rework this to user the getter in the API? // Set a list of available captions languages setCaptionsMenu: function setCaptionsMenu() { - var _this6 = this; + var _this7 = this; // Menu required if (!is$1.element(this.elements.settings.panels.captions)) { @@ -2552,9 +2571,9 @@ typeof navigator === "object" && (function (global, factory) { var options = tracks.map(function (track, value) { return { value: value, - checked: _this6.captions.toggled && _this6.currentTrack === value, - title: captions.getLabel.call(_this6, track), - badge: track.language && controls.createBadge.call(_this6, track.language.toUpperCase()), + checked: _this7.captions.toggled && _this7.currentTrack === value, + title: captions.getLabel.call(_this7, track), + badge: track.language && controls.createBadge.call(_this7, track.language.toUpperCase()), list: list, type: 'language' }; @@ -2573,7 +2592,7 @@ typeof navigator === "object" && (function (global, factory) { }, // Set a list of available captions languages setSpeedMenu: function setSpeedMenu(options) { - var _this7 = this; + var _this8 = this; // Menu required if (!is$1.element(this.elements.settings.panels.speed)) { @@ -2591,7 +2610,7 @@ typeof navigator === "object" && (function (global, factory) { this.options.speed = this.options.speed.filter(function (speed) { - return _this7.config.speed.options.includes(speed); + return _this8.config.speed.options.includes(speed); }); // Toggle the pane and tab var toggle = !is$1.empty(this.options.speed) && this.options.speed.length > 1; @@ -2607,11 +2626,11 @@ typeof navigator === "object" && (function (global, factory) { this.options.speed.forEach(function (speed) { - controls.createMenuItem.call(_this7, { + controls.createMenuItem.call(_this8, { value: speed, list: list, type: type, - title: controls.getLabel.call(_this7, 'speed', speed) + title: controls.getLabel.call(_this8, 'speed', speed) }); }); controls.updateSetting.call(this, type, list); @@ -2635,8 +2654,8 @@ typeof navigator === "object" && (function (global, factory) { var target = pane; if (!is$1.element(target)) { - target = Object.values(this.elements.settings.panels).find(function (pane) { - return !pane.hidden; + target = Object.values(this.elements.settings.panels).find(function (p) { + return !p.hidden; }); } @@ -2661,7 +2680,10 @@ typeof navigator === "object" && (function (global, factory) { } else if (is$1.keyboardEvent(input) && input.which === 27) { show = false; } else if (is$1.event(input)) { - var isMenuItem = popup.contains(input.target); // If the click was inside the menu or if the click + // If Plyr is in a shadowDOM, the event target is set to the component, instead of the + // Element in the shadowDOM. The path, if available, is complete. + var target = is$1.function(input.composedPath) ? input.composedPath()[0] : input.target; + var isMenuItem = popup.contains(target); // If the click was inside the menu or if the click // wasn't the button or menu item and we're trying to // show the menu (a doc click shouldn't show the menu) @@ -2704,11 +2726,11 @@ typeof navigator === "object" && (function (global, factory) { }, // Show a panel in the menu showMenuPanel: function showMenuPanel() { - var _this8 = this; + var _this9 = this; var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - var target = document.getElementById("plyr-settings-".concat(this.id, "-").concat(type)); // Nothing to show, bail + var target = this.elements.container.querySelector("#plyr-settings-".concat(this.id, "-").concat(type)); // Nothing to show, bail if (!is$1.element(target)) { return; @@ -2737,7 +2759,7 @@ typeof navigator === "object" && (function (global, factory) { container.style.width = ''; container.style.height = ''; // Only listen once - off.call(_this8, container, transitionEndEvent, restore); + off.call(_this9, container, transitionEndEvent, restore); }; // Listen for the transition finishing and restore auto height/width @@ -2754,265 +2776,289 @@ typeof navigator === "object" && (function (global, factory) { controls.focusFirstMenuItem.call(this, target, tabFocus); }, - // Set the download link - setDownloadLink: function setDownloadLink() { + // Set the download URL + setDownloadUrl: function setDownloadUrl() { var button = this.elements.buttons.download; // Bail if no button if (!is$1.element(button)) { return; - } // Set download link + } // Set attribute button.setAttribute('href', this.download); }, // Build the default HTML - // TODO: Set order based on order in the config.controls array? create: function create(data) { - var _this9 = this; - - // Create the container - var container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper)); // Restart button - - if (this.config.controls.includes('restart')) { - container.appendChild(controls.createButton.call(this, 'restart')); - } // Rewind button - - - if (this.config.controls.includes('rewind')) { - container.appendChild(controls.createButton.call(this, 'rewind')); - } // Play/Pause button - - - if (this.config.controls.includes('play')) { - container.appendChild(controls.createButton.call(this, 'play')); - } // Fast forward button - + var _this10 = this; - if (this.config.controls.includes('fast-forward')) { - container.appendChild(controls.createButton.call(this, 'fast-forward')); - } // Progress + var bindMenuItemShortcuts = controls.bindMenuItemShortcuts, + createButton = controls.createButton, + createProgress = controls.createProgress, + createRange = controls.createRange, + createTime = controls.createTime, + setQualityMenu = controls.setQualityMenu, + setSpeedMenu = controls.setSpeedMenu, + showMenuPanel = controls.showMenuPanel; + this.elements.controls = null; // Larger overlaid play button + if (this.config.controls.includes('play-large')) { + this.elements.container.appendChild(createButton.call(this, 'play-large')); + } // Create the container - if (this.config.controls.includes('progress')) { - var progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress)); // Seek range slider - progress.appendChild(controls.createRange.call(this, 'seek', { - id: "plyr-seek-".concat(data.id) - })); // Buffer progress + var container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper)); + this.elements.controls = container; // Default item attributes - progress.appendChild(controls.createProgress.call(this, 'buffer')); // TODO: Add loop display indicator - // Seek tooltip + var defaultAttributes = { + class: 'plyr__controls__item' + }; // Loop through controls in order - if (this.config.tooltips.seek) { - var tooltip = createElement('span', { - class: this.config.classNames.tooltip - }, '00:00'); - progress.appendChild(tooltip); - this.elements.display.seekTooltip = tooltip; - } + dedupe(this.config.controls).forEach(function (control) { + // Restart button + if (control === 'restart') { + container.appendChild(createButton.call(_this10, 'restart', defaultAttributes)); + } // Rewind button - this.elements.progress = progress; - container.appendChild(this.elements.progress); - } // Media current time display + if (control === 'rewind') { + container.appendChild(createButton.call(_this10, 'rewind', defaultAttributes)); + } // Play/Pause button - if (this.config.controls.includes('current-time')) { - container.appendChild(controls.createTime.call(this, 'currentTime')); - } // Media duration display + if (control === 'play') { + container.appendChild(createButton.call(_this10, 'play', defaultAttributes)); + } // Fast forward button - if (this.config.controls.includes('duration')) { - container.appendChild(controls.createTime.call(this, 'duration')); - } // Volume controls + if (control === 'fast-forward') { + container.appendChild(createButton.call(_this10, 'fast-forward', defaultAttributes)); + } // Progress - if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) { - var volume = createElement('div', { - class: 'plyr__volume' - }); // Toggle mute button - if (this.config.controls.includes('mute')) { - volume.appendChild(controls.createButton.call(this, 'mute')); - } // Volume range control + if (control === 'progress') { + var progressContainer = createElement('div', { + class: "".concat(defaultAttributes.class, " plyr__progress__container") + }); + var progress = createElement('div', getAttributesFromSelector(_this10.config.selectors.progress)); // Seek range slider + progress.appendChild(createRange.call(_this10, 'seek', { + id: "plyr-seek-".concat(data.id) + })); // Buffer progress - if (this.config.controls.includes('volume')) { - // Set the attributes - var attributes = { - max: 1, - step: 0.05, - value: this.config.volume - }; // Create the volume range slider + progress.appendChild(createProgress.call(_this10, 'buffer')); // TODO: Add loop display indicator + // Seek tooltip - volume.appendChild(controls.createRange.call(this, 'volume', extend(attributes, { - id: "plyr-volume-".concat(data.id) - }))); - this.elements.volume = volume; - } + if (_this10.config.tooltips.seek) { + var tooltip = createElement('span', { + class: _this10.config.classNames.tooltip + }, '00:00'); + progress.appendChild(tooltip); + _this10.elements.display.seekTooltip = tooltip; + } - container.appendChild(volume); - } // Toggle captions button + _this10.elements.progress = progress; + progressContainer.appendChild(_this10.elements.progress); + container.appendChild(progressContainer); + } // Media current time display - if (this.config.controls.includes('captions')) { - container.appendChild(controls.createButton.call(this, 'captions')); - } // Settings button / menu + if (control === 'current-time') { + container.appendChild(createTime.call(_this10, 'currentTime', defaultAttributes)); + } // Media duration display - if (this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) { - var control = createElement('div', { - class: 'plyr__menu', - hidden: '' - }); - control.appendChild(controls.createButton.call(this, 'settings', { - 'aria-haspopup': true, - 'aria-controls': "plyr-settings-".concat(data.id), - 'aria-expanded': false - })); - var popup = createElement('div', { - class: 'plyr__menu__container', - id: "plyr-settings-".concat(data.id), - hidden: '' - }); - var inner = createElement('div'); - var home = createElement('div', { - id: "plyr-settings-".concat(data.id, "-home") - }); // Create the menu + if (control === 'duration') { + container.appendChild(createTime.call(_this10, 'duration', defaultAttributes)); + } // Volume controls - var menu = createElement('div', { - role: 'menu' - }); - home.appendChild(menu); - inner.appendChild(home); - this.elements.settings.panels.home = home; // Build the menu items - - this.config.settings.forEach(function (type) { - // TODO: bundle this with the createMenuItem helper and bindings - var menuItem = createElement('button', extend(getAttributesFromSelector(_this9.config.selectors.buttons.settings), { - type: 'button', - class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--forward"), - role: 'menuitem', - 'aria-haspopup': true, - hidden: '' - })); // Bind menu shortcuts for keyboard users - controls.bindMenuItemShortcuts.call(_this9, menuItem, type); // Show menu on click + if (control === 'mute' || control === 'volume') { + var volume = _this10.elements.volume; // Create the volume container if needed - on(menuItem, 'click', function () { - controls.showMenuPanel.call(_this9, type, false); - }); - var flex = createElement('span', null, i18n.get(type, _this9.config)); - var value = createElement('span', { - class: _this9.config.classNames.menu.value - }); // Speed contains HTML entities - - value.innerHTML = data[type]; - flex.appendChild(value); - menuItem.appendChild(flex); - menu.appendChild(menuItem); // Build the panes - - var pane = createElement('div', { - id: "plyr-settings-".concat(data.id, "-").concat(type), - hidden: '' - }); // Back button + if (!is$1.element(volume) || !container.contains(volume)) { + volume = createElement('div', extend({}, defaultAttributes, { + class: "".concat(defaultAttributes.class, " plyr__volume").trim() + })); + _this10.elements.volume = volume; + container.appendChild(volume); + } // Toggle mute button - var backButton = createElement('button', { - type: 'button', - class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--back") - }); // Visible label - backButton.appendChild(createElement('span', { - 'aria-hidden': true - }, i18n.get(type, _this9.config))); // Screen reader label + if (control === 'mute') { + volume.appendChild(createButton.call(_this10, 'mute')); + } // Volume range control - backButton.appendChild(createElement('span', { - class: _this9.config.classNames.hidden - }, i18n.get('menuBack', _this9.config))); // Go back via keyboard - on(pane, 'keydown', function (event) { - // We only care about <- - if (event.which !== 37) { - return; - } // Prevent seek + if (control === 'volume') { + // Set the attributes + var attributes = { + max: 1, + step: 0.05, + value: _this10.config.volume + }; // Create the volume range slider + volume.appendChild(createRange.call(_this10, 'volume', extend(attributes, { + id: "plyr-volume-".concat(data.id) + }))); + } + } // Toggle captions button - event.preventDefault(); - event.stopPropagation(); // Show the respective menu - controls.showMenuPanel.call(_this9, 'home', true); - }, false); // Go back via button click + if (control === 'captions') { + container.appendChild(createButton.call(_this10, 'captions', defaultAttributes)); + } // Settings button / menu - on(backButton, 'click', function () { - controls.showMenuPanel.call(_this9, 'home', false); - }); // Add to pane - pane.appendChild(backButton); // Menu + if (control === 'settings' && !is$1.empty(_this10.config.settings)) { + var wrapper = createElement('div', extend({}, defaultAttributes, { + class: "".concat(defaultAttributes.class, " plyr__menu").trim(), + hidden: '' + })); + wrapper.appendChild(createButton.call(_this10, 'settings', { + 'aria-haspopup': true, + 'aria-controls': "plyr-settings-".concat(data.id), + 'aria-expanded': false + })); + var popup = createElement('div', { + class: 'plyr__menu__container', + id: "plyr-settings-".concat(data.id), + hidden: '' + }); + var inner = createElement('div'); + var home = createElement('div', { + id: "plyr-settings-".concat(data.id, "-home") + }); // Create the menu - pane.appendChild(createElement('div', { + var menu = createElement('div', { role: 'menu' - })); - inner.appendChild(pane); - _this9.elements.settings.buttons[type] = menuItem; - _this9.elements.settings.panels[type] = pane; - }); - popup.appendChild(inner); - control.appendChild(popup); - container.appendChild(control); - this.elements.settings.popup = popup; - this.elements.settings.menu = control; - } // Picture in picture button + }); + home.appendChild(menu); + inner.appendChild(home); + _this10.elements.settings.panels.home = home; // Build the menu items + + _this10.config.settings.forEach(function (type) { + // TODO: bundle this with the createMenuItem helper and bindings + var menuItem = createElement('button', extend(getAttributesFromSelector(_this10.config.selectors.buttons.settings), { + type: 'button', + class: "".concat(_this10.config.classNames.control, " ").concat(_this10.config.classNames.control, "--forward"), + role: 'menuitem', + 'aria-haspopup': true, + hidden: '' + })); // Bind menu shortcuts for keyboard users + + bindMenuItemShortcuts.call(_this10, menuItem, type); // Show menu on click + + on(menuItem, 'click', function () { + showMenuPanel.call(_this10, type, false); + }); + var flex = createElement('span', null, i18n.get(type, _this10.config)); + var value = createElement('span', { + class: _this10.config.classNames.menu.value + }); // Speed contains HTML entities + + value.innerHTML = data[type]; + flex.appendChild(value); + menuItem.appendChild(flex); + menu.appendChild(menuItem); // Build the panes + + var pane = createElement('div', { + id: "plyr-settings-".concat(data.id, "-").concat(type), + hidden: '' + }); // Back button + + var backButton = createElement('button', { + type: 'button', + class: "".concat(_this10.config.classNames.control, " ").concat(_this10.config.classNames.control, "--back") + }); // Visible label + + backButton.appendChild(createElement('span', { + 'aria-hidden': true + }, i18n.get(type, _this10.config))); // Screen reader label + + backButton.appendChild(createElement('span', { + class: _this10.config.classNames.hidden + }, i18n.get('menuBack', _this10.config))); // Go back via keyboard + + on(pane, 'keydown', function (event) { + // We only care about <- + if (event.which !== 37) { + return; + } // Prevent seek + + + event.preventDefault(); + event.stopPropagation(); // Show the respective menu + + showMenuPanel.call(_this10, 'home', true); + }, false); // Go back via button click + + on(backButton, 'click', function () { + showMenuPanel.call(_this10, 'home', false); + }); // Add to pane + + pane.appendChild(backButton); // Menu + + pane.appendChild(createElement('div', { + role: 'menu' + })); + inner.appendChild(pane); + _this10.elements.settings.buttons[type] = menuItem; + _this10.elements.settings.panels[type] = pane; + }); + popup.appendChild(inner); + wrapper.appendChild(popup); + container.appendChild(wrapper); + _this10.elements.settings.popup = popup; + _this10.elements.settings.menu = wrapper; + } // Picture in picture button - if (this.config.controls.includes('pip') && support.pip) { - container.appendChild(controls.createButton.call(this, 'pip')); - } // Airplay button + if (control === 'pip' && support.pip) { + container.appendChild(createButton.call(_this10, 'pip', defaultAttributes)); + } // Airplay button - if (this.config.controls.includes('airplay') && support.airplay) { - container.appendChild(controls.createButton.call(this, 'airplay')); - } // Download button + if (control === 'airplay' && support.airplay) { + container.appendChild(createButton.call(_this10, 'airplay', defaultAttributes)); + } // Download button - if (this.config.controls.includes('download')) { - var _attributes = { - element: 'a', - href: this.download, - target: '_blank' - }; - var download = this.config.urls.download; - if (!is$1.url(download) && this.isEmbed) { - extend(_attributes, { - icon: "logo-".concat(this.provider), - label: this.provider + if (control === 'download') { + var _attributes = extend({}, defaultAttributes, { + element: 'a', + href: _this10.download, + target: '_blank' }); - } - - container.appendChild(controls.createButton.call(this, 'download', _attributes)); - } // Toggle fullscreen button + var download = _this10.config.urls.download; - if (this.config.controls.includes('fullscreen')) { - container.appendChild(controls.createButton.call(this, 'fullscreen')); - } // Larger overlaid play button + if (!is$1.url(download) && _this10.isEmbed) { + extend(_attributes, { + icon: "logo-".concat(_this10.provider), + label: _this10.provider + }); + } + container.appendChild(createButton.call(_this10, 'download', _attributes)); + } // Toggle fullscreen button - if (this.config.controls.includes('play-large')) { - this.elements.container.appendChild(controls.createButton.call(this, 'play-large')); - } - this.elements.controls = container; // Set available quality levels + if (control === 'fullscreen') { + container.appendChild(createButton.call(_this10, 'fullscreen', defaultAttributes)); + } + }); // Set available quality levels if (this.isHTML5) { - controls.setQualityMenu.call(this, html5.getQualityOptions.call(this)); + setQualityMenu.call(this, html5.getQualityOptions.call(this)); } - controls.setSpeedMenu.call(this); + setSpeedMenu.call(this); return container; }, // Insert controls inject: function inject() { - var _this10 = this; + var _this11 = this; // Sprite if (this.config.loadSprite) { @@ -3107,7 +3153,7 @@ typeof navigator === "object" && (function (global, factory) { if (!is$1.empty(this.elements.buttons)) { var addProperty = function addProperty(button) { - var className = _this10.config.classNames.controlPressed; + var className = _this11.config.classNames.controlPressed; Object.defineProperty(button, 'pressed', { enumerable: true, get: function get() { @@ -3143,8 +3189,8 @@ typeof navigator === "object" && (function (global, factory) { var selector = "".concat(selectors.controls.wrapper, " ").concat(selectors.labels, " .").concat(classNames.hidden); var labels = getElements.call(this, selector); Array.from(labels).forEach(function (label) { - toggleClass(label, _this10.config.classNames.hidden, false); - toggleClass(label, _this10.config.classNames.tooltip, true); + toggleClass(label, _this11.config.classNames.hidden, false); + toggleClass(label, _this11.config.classNames.tooltip, true); }); } } @@ -3296,7 +3342,9 @@ typeof navigator === "object" && (function (global, factory) { default: track.mode === 'showing' }); // Turn off native caption rendering to avoid double captions - track.mode = 'hidden'; // Add event listener for cue changes + Object.assign(track, { + mode: 'hidden' + }); // Add event listener for cue changes on.call(_this, track, 'cuechange', function () { return captions.updateCues.call(_this); @@ -3476,8 +3524,8 @@ typeof navigator === "object" && (function (global, factory) { }); var track; languages.every(function (language) { - track = sorted.find(function (track) { - return track.language === language; + track = sorted.find(function (t) { + return t.language === language; }); return !track; // Break iteration if there is a match }); // If no match is found but is required, get first @@ -3601,7 +3649,7 @@ typeof navigator === "object" && (function (global, factory) { // Sprite (for icons) loadSprite: true, iconPrefix: 'plyr', - iconUrl: 'https://cdn.plyr.io/3.5.3/plyr.svg', + iconUrl: 'https://cdn.plyr.io/3.5.2/plyr.svg', // Blank video (used to prevent errors on source change) blankVideo: 'https://cdn.plyr.io/static/blank.mp4', // Quality default @@ -3714,7 +3762,8 @@ typeof navigator === "object" && (function (global, factory) { }, youtube: { sdk: 'https://www.youtube.com/iframe_api', - api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet' + api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}' // 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title),fileDetails)&part=snippet', + }, googleIMA: { sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js' @@ -3790,10 +3839,7 @@ typeof navigator === "object" && (function (global, factory) { }, progress: '.plyr__progress', captions: '.plyr__captions', - caption: '.plyr__caption', - menu: { - quality: '.js-plyr__menu__list--quality' - } + caption: '.plyr__caption' }, // Class hooks added to the player in different states classNames: { @@ -3864,10 +3910,6 @@ typeof navigator === "object" && (function (global, factory) { id: 'data-plyr-embed-id' } }, - // API keys - keys: { - google: null - }, // Advertisements plugin // Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio ads: { @@ -4317,13 +4359,13 @@ typeof navigator === "object" && (function (global, factory) { this.volume = null; // Reset mute state - this.muted = null; // Reset speed - - this.speed = null; // Reset loop state + this.muted = null; // Reset loop state this.loop = null; // Reset quality setting - this.quality = null; // Reset volume display + this.quality = null; // Reset speed + + this.speed = null; // Reset volume display controls.updateVolume.call(this); // Reset time display @@ -4440,7 +4482,9 @@ typeof navigator === "object" && (function (global, factory) { toggleClass(this.elements.container, this.config.classNames.stopped, this.stopped); // Set state Array.from(this.elements.buttons.play || []).forEach(function (target) { - target.pressed = _this3.playing; + Object.assign(target, { + pressed: _this3.playing + }); }); // Only update controls on non timeupdate events if (is$1.event(event) && event.type === 'timeupdate') { @@ -4467,13 +4511,13 @@ typeof navigator === "object" && (function (global, factory) { }, // Toggle controls based on state and `force` argument toggleControls: function toggleControls(force) { - var controls = this.elements.controls; + var controlsElement = this.elements.controls; - if (controls && this.config.hideControls) { + if (controlsElement && this.config.hideControls) { // Don't hide controls if a touch-device user recently seeked. (Must be limited to touch devices, or it occasionally prevents desktop controls from hiding.) var recentTouchSeek = this.touch && this.lastSeekTime + 2000 > Date.now(); // Show controls if force, loading, paused, button interaction, or recent seek, otherwise hide - this.toggleControls(Boolean(force || this.loading || this.paused || controls.pressed || controls.hover || recentTouchSeek)); + this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek)); } } }; @@ -4623,14 +4667,14 @@ typeof navigator === "object" && (function (global, factory) { break; /* case 73: - this.setLoop('start'); - break; - case 76: - this.setLoop(); - break; - case 79: - this.setLoop('end'); - break; */ + this.setLoop('start'); + break; + case 76: + this.setLoop(); + break; + case 79: + this.setLoop('end'); + break; */ default: break; @@ -4730,8 +4774,6 @@ typeof navigator === "object" && (function (global, factory) { }, { key: "container", value: function container() { - var _this = this; - var player = this.player; var config = player.config, elements = player.elements, @@ -4743,11 +4785,11 @@ typeof navigator === "object" && (function (global, factory) { on.call(player, elements.container, 'mousemove mouseleave touchstart touchmove enterfullscreen exitfullscreen', function (event) { - var controls = elements.controls; // Remove button states for fullscreen + var controlsElement = elements.controls; // Remove button states for fullscreen - if (controls && event.type === 'enterfullscreen') { - controls.pressed = false; - controls.hover = false; + if (controlsElement && event.type === 'enterfullscreen') { + controlsElement.pressed = false; + controlsElement.hover = false; } // Show, then hide after a timeout unless another control event occurs @@ -4786,7 +4828,7 @@ typeof navigator === "object" && (function (global, factory) { var _ratio = _slicedToArray(ratio, 2), y = _ratio[1]; - var _getAspectRatio$call = getAspectRatio.call(_this), + var _getAspectRatio$call = getAspectRatio.call(player), _getAspectRatio$call2 = _slicedToArray(_getAspectRatio$call, 2), videoX = _getAspectRatio$call2[0], videoY = _getAspectRatio$call2[1]; @@ -4844,7 +4886,7 @@ typeof navigator === "object" && (function (global, factory) { }, { key: "media", value: function media() { - var _this2 = this; + var _this = this; var player = this.player; var elements = player.elements; // Time change on media @@ -4909,11 +4951,11 @@ typeof navigator === "object" && (function (global, factory) { } if (player.ended) { - _this2.proxy(event, player.restart, 'restart'); + _this.proxy(event, player.restart, 'restart'); - _this2.proxy(event, player.play, 'play'); + _this.proxy(event, player.play, 'play'); } else { - _this2.proxy(event, player.togglePlay, 'play'); + _this.proxy(event, player.togglePlay, 'play'); } }); } // Disable right click @@ -4950,7 +4992,7 @@ typeof navigator === "object" && (function (global, factory) { }); // Update download link when ready and if quality changes on.call(player, player.media, 'ready qualitychange', function () { - controls.setDownloadLink.call(player); + controls.setDownloadUrl.call(player); }); // Proxy events to container // Bubble up key events for Edge @@ -4988,21 +5030,21 @@ typeof navigator === "object" && (function (global, factory) { }, { key: "bind", value: function bind(element, type, defaultHandler, customHandlerKey) { - var _this3 = this; + var _this2 = this; var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; var player = this.player; var customHandler = player.config.listeners[customHandlerKey]; var hasCustomHandler = is$1.function(customHandler); on.call(player, element, type, function (event) { - return _this3.proxy(event, defaultHandler, customHandlerKey); + return _this2.proxy(event, defaultHandler, customHandlerKey); }, passive && !hasCustomHandler); } // Listen for control events }, { key: "controls", value: function controls$1() { - var _this4 = this; + var _this3 = this; var player = this.player; var elements = player.elements; // IE doesn't support input event, so we fallback to change @@ -5011,7 +5053,7 @@ typeof navigator === "object" && (function (global, factory) { if (elements.buttons.play) { Array.from(elements.buttons.play).forEach(function (button) { - _this4.bind(button, 'click', player.togglePlay, 'play'); + _this3.bind(button, 'click', player.togglePlay, 'play'); }); } // Pause @@ -5118,7 +5160,7 @@ typeof navigator === "object" && (function (global, factory) { if (browser.isIos) { var inputs = getElements.call(player, 'input[type="range"]'); Array.from(inputs).forEach(function (input) { - return _this4.bind(input, inputEvent, function (event) { + return _this3.bind(input, inputEvent, function (event) { return repaint(event.target); }); }); @@ -5176,7 +5218,7 @@ typeof navigator === "object" && (function (global, factory) { if (browser.isWebkit) { Array.from(getElements.call(player, 'input[type="range"]')).forEach(function (element) { - _this4.bind(element, 'input', function (event) { + _this3.bind(element, 'input', function (event) { return controls.updateRangeFill.call(player, event.target); }); }); @@ -5212,7 +5254,6 @@ typeof navigator === "object" && (function (global, factory) { this.bind(elements.controls, 'focusin', function () { var config = player.config, - elements = player.elements, timers = player.timers; // Skip transition to prevent focus from scrolling the parent element toggleClass(elements.controls, config.classNames.noTransition, true); // Toggle @@ -5223,7 +5264,7 @@ typeof navigator === "object" && (function (global, factory) { toggleClass(elements.controls, config.classNames.noTransition, false); }, 0); // Delay a little more for mouse users - var delay = _this4.touch ? 3000 : 4000; // Clear timer + var delay = _this3.touch ? 3000 : 4000; // Clear timer clearTimeout(timers.controls); // Hide again after delay @@ -5602,13 +5643,13 @@ typeof navigator === "object" && (function (global, factory) { // Add embed class for responsive toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set intial ratio - setAspectRatio.call(this); // Load the API if not already + setAspectRatio.call(this); // Load the SDK if not already if (!is$1.object(window.Vimeo)) { loadScript(this.config.urls.vimeo.sdk).then(function () { vimeo.ready.call(_this); }).catch(function (error) { - _this.debug.warn('Vimeo API failed to load', error); + _this.debug.warn('Vimeo SDK (player.js) failed to load', error); }); } else { vimeo.ready.call(this); @@ -5787,7 +5828,7 @@ typeof navigator === "object" && (function (global, factory) { var currentSrc; player.embed.getVideoUrl().then(function (value) { currentSrc = value; - controls.setDownloadLink.call(player); + controls.setDownloadUrl.call(player); }).catch(function (error) { _this2.debug.warn(error); }); @@ -5808,7 +5849,7 @@ typeof navigator === "object" && (function (global, factory) { width = _dimensions[0], height = _dimensions[1]; - player.embed.ratio = "".concat(width, ":").concat(height); + player.embed.ratio = [width, height]; setAspectRatio.call(_this2); }); // Set autopause @@ -5949,9 +5990,7 @@ typeof navigator === "object" && (function (global, factory) { var _this = this; // Add embed class for responsive - toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set aspect ratio - - setAspectRatio.call(this); // Setup API + toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Setup API if (is$1.object(window.YT) && is$1.function(window.YT.Player)) { youtube.ready.call(this); @@ -5979,32 +6018,24 @@ typeof navigator === "object" && (function (global, factory) { getTitle: function getTitle(videoId) { var _this2 = this; - // Try via undocumented API method first - // This method disappears now and then though... - // https://github.com/sampotts/plyr/issues/709 - if (is$1.function(this.embed.getVideoData)) { - var _this$embed$getVideoD = this.embed.getVideoData(), - title = _this$embed$getVideoD.title; + var url = format(this.config.urls.youtube.api, videoId); + fetch(url).then(function (data) { + if (is$1.object(data)) { + var title = data.title, + height = data.height, + width = data.width; // Set title - if (is$1.empty(title)) { - this.config.title = title; - ui.setTitle.call(this); - return; - } - } // Or via Google API + _this2.config.title = title; + ui.setTitle.call(_this2); // Set aspect ratio + _this2.embed.ratio = [width, height]; + } - var key = this.config.keys.google; - - if (is$1.string(key) && !is$1.empty(key)) { - var url = format(this.config.urls.youtube.api, videoId, key); - fetch(url).then(function (result) { - if (is$1.object(result)) { - _this2.config.title = result.items[0].snippet.title; - ui.setTitle.call(_this2); - } - }).catch(function () {}); - } + setAspectRatio.call(_this2); + }).catch(function () { + // Set aspect ratio + setAspectRatio.call(_this2); + }); }, // API ready ready: function ready() { @@ -6035,8 +6066,8 @@ typeof navigator === "object" && (function (global, factory) { }); player.media = replaceElement(container, player.media); // Id to poster wrapper - var posterSrc = function posterSrc(format) { - return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(format, "default.jpg"); + var posterSrc = function posterSrc(s) { + return "https://i.ytimg.com/vi/".concat(videoId, "/").concat(s, "default.jpg"); }; // Check thumbnail images in order of quality, but reject fallback thumbnails (120px wide) @@ -6049,9 +6080,9 @@ typeof navigator === "object" && (function (global, factory) { }) // 360p padded 4:3. Always exists .then(function (image) { return ui.setPoster.call(player, image.src); - }).then(function (posterSrc) { + }).then(function (src) { // If the image is padded, use background-size "cover" instead (like youtube does too with their posters) - if (!posterSrc.includes('maxres')) { + if (!src.includes('maxres')) { player.elements.poster.style.backgroundSize = 'cover'; } }).catch(function () {}); @@ -6362,6 +6393,20 @@ typeof navigator === "object" && (function (global, factory) { } }; + var destroy = function destroy(instance) { + // Destroy our adsManager + if (instance.manager) { + instance.manager.destroy(); + } // Destroy our adsManager + + + if (instance.elements.displayContainer) { + instance.elements.displayContainer.destroy(); + } + + instance.elements.container.remove(); + }; + var Ads = /*#__PURE__*/ function () { @@ -6409,18 +6454,20 @@ typeof navigator === "object" && (function (global, factory) { value: function load() { var _this2 = this; - if (this.enabled) { - // Check if the Google IMA3 SDK is loaded or load it ourselves - if (!is$1.object(window.google) || !is$1.object(window.google.ima)) { - loadScript(this.player.config.urls.googleIMA.sdk).then(function () { - _this2.ready(); - }).catch(function () { - // Script failed to load or is blocked - _this2.trigger('error', new Error('Google IMA SDK failed to load')); - }); - } else { - this.ready(); - } + if (!this.enabled) { + return; + } // Check if the Google IMA3 SDK is loaded or load it ourselves + + + if (!is$1.object(window.google) || !is$1.object(window.google.ima)) { + loadScript(this.player.config.urls.googleIMA.sdk).then(function () { + _this2.ready(); + }).catch(function () { + // Script failed to load or is blocked + _this2.trigger('error', new Error('Google IMA SDK failed to load')); + }); + } else { + this.ready(); } } /** @@ -6432,8 +6479,13 @@ typeof navigator === "object" && (function (global, factory) { value: function ready() { var _this3 = this; - // Start ticking our safety timer. If the whole advertisement + // Double check we're enabled + if (!this.enabled) { + destroy(this); + } // Start ticking our safety timer. If the whole advertisement // thing doesn't resolve within our set time; we bail + + this.startSafetyTimer(12000, 'ready()'); // Clear the safety timer this.managerPromise.then(function () { @@ -6563,9 +6615,7 @@ typeof navigator === "object" && (function (global, factory) { this.manager = event.getAdsManager(this.player, settings); // Get the cue points for any mid-rolls by filtering out the pre- and post-roll - this.cuePoints = this.manager.getCuePoints(); // Set volume to match player - - this.manager.setVolume(this.player.volume); // Add listeners to the required events + this.cuePoints = this.manager.getCuePoints(); // Add listeners to the required events // Advertisement error events this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) { @@ -6573,8 +6623,8 @@ typeof navigator === "object" && (function (global, factory) { }); // Advertisement regular events Object.keys(google.ima.AdEvent.Type).forEach(function (type) { - _this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (event) { - return _this6.onAdEvent(event); + _this6.manager.addEventListener(google.ima.AdEvent.Type[type], function (e) { + return _this6.onAdEvent(e); }); }); // Resolve our adsManager @@ -6622,17 +6672,17 @@ typeof navigator === "object" && (function (global, factory) { var adData = event.getAdData(); // Proxy event var dispatchEvent = function dispatchEvent(type) { - var event = "ads".concat(type.replace(/_/g, '').toLowerCase()); - triggerEvent.call(_this8.player, _this8.player.media, event); - }; + triggerEvent.call(_this8.player, _this8.player.media, "ads".concat(type.replace(/_/g, '').toLowerCase())); + }; // Bubble the event + + + dispatchEvent(event.type); switch (event.type) { case google.ima.AdEvent.Type.LOADED: // This is the first event sent for an ad - it is possible to determine whether the // ad is a video ad or an overlay - this.trigger('loaded'); // Bubble event - - dispatchEvent(event.type); // Start countdown + this.trigger('loaded'); // Start countdown this.pollCountdown(true); @@ -6646,11 +6696,15 @@ typeof navigator === "object" && (function (global, factory) { break; + case google.ima.AdEvent.Type.STARTED: + // Set volume to match player + this.manager.setVolume(this.player.volume); + break; + case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: // All ads for the current videos are done. We can now request new advertisements // in case the video is re-played - // Fire event - dispatchEvent(event.type); // TODO: Example for what happens when a next video in a playlist would be loaded. + // TODO: Example for what happens when a next video in a playlist would be loaded. // So here we load a new video when all ads are done. // Then we load new ads within a new adsManager. When the video // Is started - after - the ads are loaded, then we get ads. @@ -6671,7 +6725,6 @@ typeof navigator === "object" && (function (global, factory) { // }; // TODO: So there is still this thing where a video should only be allowed to start // playing when the IMA SDK is ready or has failed - this.loadAds(); break; @@ -6679,7 +6732,6 @@ typeof navigator === "object" && (function (global, factory) { // This event indicates the ad has started - the video player can adjust the UI, // for example display a pause button and remaining time. Fired when content should // be paused. This usually happens right before an ad is about to cover the content - dispatchEvent(event.type); this.pauseContent(); break; @@ -6688,19 +6740,10 @@ typeof navigator === "object" && (function (global, factory) { // appropriate UI actions, such as removing the timer for remaining time detection. // Fired when content should be resumed. This usually happens when an ad finishes // or collapses - dispatchEvent(event.type); this.pollCountdown(); this.resumeContent(); break; - case google.ima.AdEvent.Type.STARTED: - case google.ima.AdEvent.Type.MIDPOINT: - case google.ima.AdEvent.Type.COMPLETE: - case google.ima.AdEvent.Type.IMPRESSION: - case google.ima.AdEvent.Type.CLICK: - dispatchEvent(event.type); - break; - case google.ima.AdEvent.Type.LOG: if (adData.adError) { this.player.debug.warn("Non-fatal ad error: ".concat(adData.adError.getMessage())); @@ -6785,7 +6828,10 @@ typeof navigator === "object" && (function (global, factory) { this.managerPromise.then(function () { - // Initialize the container. Must be done via a user action on mobile devices + // Set volume to match player + _this10.manager.setVolume(_this10.player.volume); // Initialize the container. Must be done via a user action on mobile devices + + _this10.elements.displayContainer.initialize(); try { @@ -7285,7 +7331,10 @@ typeof navigator === "object" && (function (global, factory) { timeContainer.appendChild(this.elements.thumb.time); this.elements.thumb.container.appendChild(timeContainer); // Inject the whole thumb - this.player.elements.progress.appendChild(this.elements.thumb.container); // Create HTML element: plyr__preview-scrubbing-container + if (is$1.element(this.player.elements.progress)) { + this.player.elements.progress.appendChild(this.elements.thumb.container); + } // Create HTML element: plyr__preview-scrubbing-container + this.elements.scrubbing.container = createElement('div', { class: this.player.config.classNames.previewThumbnails.scrubbingContainer @@ -7414,7 +7463,11 @@ typeof navigator === "object" && (function (global, factory) { if (image.dataset.index !== currentImage.dataset.index && !image.dataset.deleting) { // Wait 200ms, as the new image can take some time to show on certain browsers (even though it was downloaded before showing). This will prevent flicker, and show some generosity towards slower clients // First set attribute 'deleting' to prevent multi-handling of this on repeat firing of this function - image.dataset.deleting = true; // This has to be set before the timeout - to prevent issues switching between hover and scrub + extend(image, { + dataset: { + deleting: true + } + }); // This has to be set before the timeout - to prevent issues switching between hover and scrub var currentImageContainer = _this8.currentImageContainer; setTimeout(function () { @@ -7592,10 +7645,14 @@ typeof navigator === "object" && (function (global, factory) { } // Find difference between height and preview container height - var multiplier = this.thumbContainerHeight / frame.h; - previewImage.style.height = "".concat(Math.floor(previewImage.naturalHeight * multiplier), "px"); - previewImage.style.width = "".concat(Math.floor(previewImage.naturalWidth * multiplier), "px"); - previewImage.style.left = "-".concat(frame.x * multiplier, "px"); + var multiplier = this.thumbContainerHeight / frame.h; // eslint-disable-next-line no-param-reassign + + previewImage.style.height = "".concat(Math.floor(previewImage.naturalHeight * multiplier), "px"); // eslint-disable-next-line no-param-reassign + + previewImage.style.width = "".concat(Math.floor(previewImage.naturalWidth * multiplier), "px"); // eslint-disable-next-line no-param-reassign + + previewImage.style.left = "-".concat(frame.x * multiplier, "px"); // eslint-disable-next-line no-param-reassign + previewImage.style.top = "-".concat(frame.y * multiplier, "px"); } }, { @@ -7794,6 +7851,25 @@ typeof navigator === "object" && (function (global, factory) { } }; + /** + * Returns a number whose value is limited to the given range. + * + * Example: limit the output of this computation to between 0 and 255 + * (x * 255).clamp(0, 255) + * + * @param {Number} input + * @param {Number} min The lower boundary of the output range + * @param {Number} max The upper boundary of the output range + * @returns A number in the range [min, max] + * @type Number + */ + function clamp() { + var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; + var min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + var max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 255; + return Math.min(Math.max(input, min), max); + } + // TODO: Use a WeakMap for private globals // const globals = new WeakMap(); // Plyr instance @@ -8408,32 +8484,32 @@ typeof navigator === "object" && (function (global, factory) { }, { key: "isHTML5", get: function get() { - return Boolean(this.provider === providers.html5); + return this.provider === providers.html5; } }, { key: "isEmbed", get: function get() { - return Boolean(this.isYouTube || this.isVimeo); + return this.isYouTube || this.isVimeo; } }, { key: "isYouTube", get: function get() { - return Boolean(this.provider === providers.youtube); + return this.provider === providers.youtube; } }, { key: "isVimeo", get: function get() { - return Boolean(this.provider === providers.vimeo); + return this.provider === providers.vimeo; } }, { key: "isVideo", get: function get() { - return Boolean(this.type === types.video); + return this.type === types.video; } }, { key: "isAudio", get: function get() { - return Boolean(this.type === types.audio); + return this.type === types.audio; } }, { key: "playing", @@ -8640,6 +8716,8 @@ typeof navigator === "object" && (function (global, factory) { }, { key: "speed", set: function set(input) { + var _this4 = this; + var speed = null; if (is$1.number(input)) { @@ -8652,26 +8730,18 @@ typeof navigator === "object" && (function (global, factory) { if (!is$1.number(speed)) { speed = this.config.speed.selected; - } // Set min/max - - - if (speed < 0.1) { - speed = 0.1; - } + } // Clamp to min/max - if (speed > 2.0) { - speed = 2.0; - } - - if (!this.config.speed.options.includes(speed)) { - this.debug.warn("Unsupported speed (".concat(speed, ")")); - return; - } // Update config + var min = this.minimumSpeed, + max = this.maximumSpeed; + speed = clamp(speed, min, max); // Update config this.config.speed.selected = speed; // Set media speed - this.media.playbackRate = speed; + setTimeout(function () { + _this4.media.playbackRate = speed; + }, 0); } /** * Get current playback speed @@ -8681,6 +8751,46 @@ typeof navigator === "object" && (function (global, factory) { return Number(this.media.playbackRate); } /** + * Get the minimum allowed speed + */ + + }, { + key: "minimumSpeed", + get: function get() { + if (this.isYouTube) { + // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate + return Math.min.apply(Math, _toConsumableArray(this.options.speed)); + } + + if (this.isVimeo) { + // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror + return 0.5; + } // https://stackoverflow.com/a/32320020/1191319 + + + return 0.0625; + } + /** + * Get the maximum allowed speed + */ + + }, { + key: "maximumSpeed", + get: function get() { + if (this.isYouTube) { + // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate + return Math.max.apply(Math, _toConsumableArray(this.options.speed)); + } + + if (this.isVimeo) { + // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror + return 2; + } // https://stackoverflow.com/a/32320020/1191319 + + + return 16; + } + /** * Set playback quality * Currently HTML5 & YouTube only * @param {Number} input - Quality level @@ -8810,6 +8920,18 @@ typeof navigator === "object" && (function (global, factory) { return is$1.url(download) ? download : this.source; } /** + * Set the download URL + */ + , + set: function set(input) { + if (!is$1.url(input)) { + return; + } + + this.config.urls.download = input; + controls.setDownloadUrl.call(this); + } + /** * Set the poster image for a video * @param {String} input - the URL for the new poster image */ @@ -8842,6 +8964,10 @@ typeof navigator === "object" && (function (global, factory) { }, { key: "ratio", get: function get() { + if (!this.isVideo) { + return null; + } + var ratio = reduceAspectRatio(getAspectRatio.call(this)); return is$1.array(ratio) ? ratio.join(':') : ratio; } |