update plyr to 3.6.2

This commit is contained in:
Jesús 2020-06-14 23:23:55 -05:00
parent 3c81bce7a4
commit 9fc0b65630
No known key found for this signature in database
GPG Key ID: F6EE7BC59A315766
14 changed files with 1538 additions and 796 deletions

File diff suppressed because one or more lines are too long

View File

@ -75,20 +75,52 @@ typeof navigator === "object" && (function (global, factory) {
return target; return target;
} }
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function _slicedToArray(arr, i) { function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
} }
function _toConsumableArray(arr) { function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
} }
function _arrayWithoutHoles(arr) { function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) { if (Array.isArray(arr)) return _arrayLikeToArray(arr);
for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
}
} }
function _arrayWithHoles(arr) { function _arrayWithHoles(arr) {
@ -96,14 +128,11 @@ typeof navigator === "object" && (function (global, factory) {
} }
function _iterableToArray(iter) { function _iterableToArray(iter) {
if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
} }
function _iterableToArrayLimit(arr, i) { function _iterableToArrayLimit(arr, i) {
if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
return;
}
var _arr = []; var _arr = [];
var _n = true; var _n = true;
var _d = false; var _d = false;
@ -129,12 +158,29 @@ typeof navigator === "object" && (function (global, factory) {
return _arr; return _arr;
} }
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread() { function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance"); throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
} }
function _nonIterableRest() { function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance"); throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
} }
function _classCallCheck$1(e, t) { function _classCallCheck$1(e, t) {
@ -427,7 +473,7 @@ typeof navigator === "object" && (function (global, factory) {
}; };
var isPromise = function isPromise(input) { var isPromise = function isPromise(input) {
return instanceOf$1(input, Promise); return instanceOf$1(input, Promise) && isFunction$1(input.then);
}; };
var isEmpty$1 = function isEmpty(input) { var isEmpty$1 = function isEmpty(input) {
@ -769,12 +815,33 @@ typeof navigator === "object" && (function (global, factory) {
} // Element matches selector } // Element matches selector
function matches$1(element, selector) { function matches$1(element, selector) {
var _Element = Element,
prototype = _Element.prototype;
function match() { function match() {
return Array.from(document.querySelectorAll(selector)).includes(this); return Array.from(document.querySelectorAll(selector)).includes(this);
} }
var method = match; var method = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match;
return method.call(element, selector);
} // Closest ancestor element matching selector (also tests element itself)
function closest(element, selector) {
var _Element2 = Element,
prototype = _Element2.prototype; // https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
function closestElement() {
var el = this;
do {
if (matches$1.matches(el, selector)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
}
var method = prototype.closest || closestElement;
return method.call(element, selector); return method.call(element, selector);
} // Find all elements } // Find all elements
@ -1017,7 +1084,7 @@ typeof navigator === "object" && (function (global, factory) {
var event = new CustomEvent(type, { var event = new CustomEvent(type, {
bubbles: bubbles, bubbles: bubbles,
detail: _objectSpread2({}, detail, { detail: _objectSpread2(_objectSpread2({}, detail), {}, {
plyr: this plyr: this
}) })
}); // Dispatch the event }); // Dispatch the event
@ -1046,6 +1113,19 @@ typeof navigator === "object" && (function (global, factory) {
}).then(function () {}); }).then(function () {});
} }
/**
* Silence a Promise-like object.
* This is useful for avoiding non-harmful, but potentially confusing "uncaught
* play promise" rejection error messages.
* @param {Object} value An object that may or may not be `Promise`-like.
*/
function silencePromise(value) {
if (is$1.promise(value)) {
value.then(null, function () {});
}
}
function validateRatio(input) { function validateRatio(input) {
if (!is$1.array(input) && (!is$1.string(input) || !input.includes(':'))) { if (!is$1.array(input) && (!is$1.string(input) || !input.includes(':'))) {
return false; return false;
@ -1114,8 +1194,8 @@ typeof navigator === "object" && (function (global, factory) {
var padding = 100 / w * h; var padding = 100 / w * h;
wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI
if (this.isVimeo && this.supported.ui) { if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
var height = 240; var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
var offset = (height - padding) / (height / 50); var offset = (height - padding) / (height / 50);
this.media.style.transform = "translateY(-".concat(offset, "%)"); this.media.style.transform = "translateY(-".concat(offset, "%)");
} else if (this.isHTML5) { } else if (this.isHTML5) {
@ -1222,7 +1302,7 @@ typeof navigator === "object" && (function (global, factory) {
player.currentTime = currentTime; // Resume playing player.currentTime = currentTime; // Resume playing
if (!paused) { if (!paused) {
player.play(); silencePromise(player.play());
} }
}); // Load new source }); // Load new source
@ -1271,7 +1351,7 @@ typeof navigator === "object" && (function (global, factory) {
}); });
} // Get the closest value in an array } // Get the closest value in an array
function closest(array, value) { function closest$1(array, value) {
if (!is$1.array(array) || !array.length) { if (!is$1.array(array) || !array.length) {
return null; return null;
} }
@ -1309,19 +1389,19 @@ typeof navigator === "object" && (function (global, factory) {
return (current / max * 100).toFixed(2); return (current / max * 100).toFixed(2);
} // Replace all occurances of a string in a string } // Replace all occurances of a string in a string
function replaceAll() { var replaceAll = function replaceAll() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString());
} // Convert to title case }; // Convert to title case
function toTitleCase() { var toTitleCase = function toTitleCase() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
return input.toString().replace(/\w\S*/g, function (text) { return input.toString().replace(/\w\S*/g, function (text) {
return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase();
}); });
} // Convert string to pascalCase }; // Convert string to pascalCase
function toPascalCase() { function toPascalCase() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
@ -1682,7 +1762,7 @@ typeof navigator === "object" && (function (global, factory) {
var icon = document.createElementNS(namespace, 'svg'); var icon = document.createElementNS(namespace, 'svg');
setAttributes(icon, extend(attributes, { setAttributes(icon, extend(attributes, {
role: 'presentation', 'aria-hidden': 'true',
focusable: 'false' focusable: 'false'
})); // Create the <use> to reference sprite })); // Create the <use> to reference sprite
@ -1706,7 +1786,7 @@ typeof navigator === "object" && (function (global, factory) {
var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var text = i18n.get(key, this.config); var text = i18n.get(key, this.config);
var attributes = _objectSpread2({}, attr, { var attributes = _objectSpread2(_objectSpread2({}, attr), {}, {
class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ') class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ')
}); });
@ -2465,7 +2545,7 @@ typeof navigator === "object" && (function (global, factory) {
var type = 'captions'; var type = 'captions';
var list = this.elements.settings.panels.captions.querySelector('[role="menu"]'); var list = this.elements.settings.panels.captions.querySelector('[role="menucaptions"]');
var tracks = captions.getTracks.call(this); var tracks = captions.getTracks.call(this);
var toggle = Boolean(tracks.length); // Toggle the pane and tab var toggle = Boolean(tracks.length); // Toggle the pane and tab
@ -2706,7 +2786,7 @@ typeof navigator === "object" && (function (global, factory) {
showMenuPanel = controls.showMenuPanel; showMenuPanel = controls.showMenuPanel;
this.elements.controls = null; // Larger overlaid play button this.elements.controls = null; // Larger overlaid play button
if (this.config.controls.includes('play-large')) { if (is$1.array(this.config.controls) && this.config.controls.includes('play-large')) {
this.elements.container.appendChild(createButton.call(this, 'play-large')); this.elements.container.appendChild(createButton.call(this, 'play-large'));
} // Create the container } // Create the container
@ -2718,7 +2798,7 @@ typeof navigator === "object" && (function (global, factory) {
class: 'plyr__controls__item' class: 'plyr__controls__item'
}; // Loop through controls in order }; // Loop through controls in order
dedupe(this.config.controls).forEach(function (control) { dedupe(is$1.array(this.config.controls) ? this.config.controls : []).forEach(function (control) {
// Restart button // Restart button
if (control === 'restart') { if (control === 'restart') {
container.appendChild(createButton.call(_this10, 'restart', defaultAttributes)); container.appendChild(createButton.call(_this10, 'restart', defaultAttributes));
@ -2907,6 +2987,10 @@ typeof navigator === "object" && (function (global, factory) {
pane.appendChild(createElement('div', { pane.appendChild(createElement('div', {
role: 'menu' role: 'menu'
})); // Menu Captions
pane.appendChild(createElement('div', {
role: 'menucaptions'
})); }));
inner.appendChild(pane); inner.appendChild(pane);
_this10.elements.settings.buttons[type] = menuItem; _this10.elements.settings.buttons[type] = menuItem;
@ -3037,8 +3121,6 @@ typeof navigator === "object" && (function (global, factory) {
if (update) { if (update) {
if (is$1.string(this.config.controls)) { if (is$1.string(this.config.controls)) {
container = replace(container); container = replace(container);
} else if (is$1.element(container)) {
container.innerHTML = replace(container.innerHTML);
} }
} // Controls container } // Controls container
@ -3253,9 +3335,15 @@ typeof navigator === "object" && (function (global, factory) {
meta.set(track, { meta.set(track, {
default: track.mode === 'showing' default: track.mode === 'showing'
}); // Turn off native caption rendering to avoid double captions }); // Turn off native caption rendering to avoid double captions
// Note: mode='hidden' forces a track to download. To ensure every track
// isn't downloaded at once, only 'showing' tracks should be reassigned
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
track.mode = 'hidden'; // Add event listener for cue changes if (track.mode === 'showing') {
// eslint-disable-next-line no-param-reassign
track.mode = 'hidden';
} // Add event listener for cue changes
on.call(_this, track, 'cuechange', function () { on.call(_this, track, 'cuechange', function () {
return captions.updateCues.call(_this); return captions.updateCues.call(_this);
@ -3272,13 +3360,15 @@ typeof navigator === "object" && (function (global, factory) {
toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is$1.empty(tracks)); // Update available languages in list toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is$1.empty(tracks)); // Update available languages in list
if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) { if (is$1.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {
controls.setCaptionsMenu.call(this); controls.setCaptionsMenu.call(this);
} }
}, },
// Toggle captions display // Toggle captions display
// Used internally for the toggleCaptions method, with the passive option forced to false // Used internally for the toggleCaptions method, with the passive option forced to false
toggle: function toggle(input) { toggle: function toggle(input) {
var _this2 = this;
var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
// If there's no full support // If there's no full support
@ -3325,7 +3415,15 @@ typeof navigator === "object" && (function (global, factory) {
controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally) controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally)
triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled'); triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');
} // Wait for the call stack to clear before setting mode='hidden'
// on the active track - forcing the browser to download it
setTimeout(function () {
if (active && _this2.captions.toggled) {
_this2.captions.currentTrackNode.mode = 'hidden';
} }
});
}, },
// Set captions by track index // Set captions by track index
// Used internally for the currentTrack setter with the passive option forced to false // Used internally for the currentTrack setter with the passive option forced to false
@ -3406,7 +3504,7 @@ typeof navigator === "object" && (function (global, factory) {
// If update is false it will also ignore tracks without metadata // If update is false it will also ignore tracks without metadata
// This is used to "freeze" the language options when captions.update is false // This is used to "freeze" the language options when captions.update is false
getTracks: function getTracks() { getTracks: function getTracks() {
var _this2 = this; var _this3 = this;
var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
// Handle media or textTracks missing or null // Handle media or textTracks missing or null
@ -3414,20 +3512,20 @@ typeof navigator === "object" && (function (global, factory) {
// Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata) // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)
return tracks.filter(function (track) { return tracks.filter(function (track) {
return !_this2.isHTML5 || update || _this2.captions.meta.has(track); return !_this3.isHTML5 || update || _this3.captions.meta.has(track);
}).filter(function (track) { }).filter(function (track) {
return ['captions', 'subtitles'].includes(track.kind); return ['captions', 'subtitles'].includes(track.kind);
}); });
}, },
// Match tracks based on languages and get the first // Match tracks based on languages and get the first
findTrack: function findTrack(languages) { findTrack: function findTrack(languages) {
var _this3 = this; var _this4 = this;
var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var tracks = captions.getTracks.call(this); var tracks = captions.getTracks.call(this);
var sortIsDefault = function sortIsDefault(track) { var sortIsDefault = function sortIsDefault(track) {
return Number((_this3.captions.meta.get(track) || {}).default); return Number((_this4.captions.meta.get(track) || {}).default);
}; };
var sorted = Array.from(tracks).sort(function (a, b) { var sorted = Array.from(tracks).sort(function (a, b) {
@ -3608,6 +3706,9 @@ typeof navigator === "object" && (function (global, factory) {
fallback: true, fallback: true,
// Fallback using full viewport/window // Fallback using full viewport/window
iosNative: false // Use the native fullscreen in iOS (disables custom controls) iosNative: false // Use the native fullscreen in iOS (disables custom controls)
// Selector for the fullscreen container so contextual / non-player content can remain visible in fullscreen mode
// Non-ancestors of the player element will be ignored
// container: null, // defaults to the player element
}, },
// Local storage // Local storage
@ -3845,16 +3946,16 @@ typeof navigator === "object" && (function (global, factory) {
title: false, title: false,
speed: true, speed: true,
transparent: false, transparent: false,
// These settings require a pro or premium account to work // Whether the owner of the video has a Pro or Business account
sidedock: false, // (which allows us to properly hide controls without CSS hacks, etc)
controls: false, premium: false,
// Custom settings from Plyr // Custom settings from Plyr
referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
}, },
// YouTube plugin // YouTube plugin
youtube: { youtube: {
noCookie: false, noCookie: true,
// Whether to use an alternative version of YouTube without cookies // Whether to use an alternative version of YouTube without cookies
rel: 0, rel: 0,
// No related vids // No related vids
@ -3964,7 +4065,10 @@ typeof navigator === "object" && (function (global, factory) {
y: 0 y: 0
}; // Force the use of 'full window/browser' rather than fullscreen }; // Force the use of 'full window/browser' rather than fullscreen
this.forceFallback = player.config.fullscreen.fallback === 'force'; // Register event listeners this.forceFallback = player.config.fullscreen.fallback === 'force'; // Get the fullscreen element
// Checks container is an ancestor, defaults to null
this.player.elements.fullscreen = player.config.fullscreen.container && closest(this.player.elements.container, player.config.fullscreen.container); // Register event listeners
// Handle event (incase user presses escape etc) // Handle event (incase user presses escape etc)
on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () { on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () {
@ -4137,7 +4241,7 @@ typeof navigator === "object" && (function (global, factory) {
if (browser.isIos && this.player.config.fullscreen.iosNative) { if (browser.isIos && this.player.config.fullscreen.iosNative) {
this.target.webkitExitFullscreen(); this.target.webkitExitFullscreen();
this.player.play(); silencePromise(this.player.play());
} else if (!Fullscreen.native || this.forceFallback) { } else if (!Fullscreen.native || this.forceFallback) {
this.toggleFallback(false); this.toggleFallback(false);
} else if (!this.prefix) { } else if (!this.prefix) {
@ -4184,13 +4288,13 @@ typeof navigator === "object" && (function (global, factory) {
} }
var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")]; var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")];
return element === this.target; return element && element.shadowRoot ? element === this.target.getRootNode().host : element === this.target;
} // Get target element } // Get target element
}, { }, {
key: "target", key: "target",
get: function get() { get: function get() {
return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.fullscreen || this.player.elements.container;
} }
}], [{ }], [{
key: "native", key: "native",
@ -4252,7 +4356,6 @@ typeof navigator === "object" && (function (global, factory) {
}); });
} }
// ==========================================================================
var ui = { var ui = {
addStyleHook: function addStyleHook() { addStyleHook: function addStyleHook() {
toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true); toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);
@ -4387,12 +4490,7 @@ typeof navigator === "object" && (function (global, factory) {
} // Set property synchronously to respect the call order } // Set property synchronously to respect the call order
this.media.setAttribute('poster', poster); // HTML5 uses native poster attribute this.media.setAttribute('data-poster', poster); // Wait until ui is ready
if (this.isHTML5) {
return Promise.resolve(poster);
} // Wait until ui is ready
return ready.call(this) // Load image return ready.call(this) // Load image
.then(function () { .then(function () {
@ -4468,6 +4566,26 @@ typeof navigator === "object" && (function (global, factory) {
this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek)); this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek));
} }
},
// Migrate any custom properties from the media to the parent
migrateStyles: function migrateStyles() {
var _this5 = this;
// Loop through values (as they are the keys when the object is spread 🤔)
Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties
.filter(function (key) {
return !is$1.empty(key) && key.startsWith('--plyr');
}).forEach(function (key) {
// Set on the container
_this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element
_this5.media.style.removeProperty(key);
}); // Remove attribute if empty
if (is$1.empty(this.media.style)) {
this.media.removeAttribute('style');
}
} }
}; };
@ -4562,7 +4680,7 @@ typeof navigator === "object" && (function (global, factory) {
case 75: case 75:
// Space and K key // Space and K key
if (!repeat) { if (!repeat) {
player.togglePlay(); silencePromise(player.togglePlay());
} }
break; break;
@ -4676,6 +4794,7 @@ typeof navigator === "object" && (function (global, factory) {
removeCurrent(); // Delay the adding of classname until the focus has changed removeCurrent(); // Delay the adding of classname until the focus has changed
// This event fires before the focusin event // This event fires before the focusin event
if (event.type !== 'focusout') {
this.focusTimer = setTimeout(function () { this.focusTimer = setTimeout(function () {
var focused = document.activeElement; // Ignore if current focus element isn't inside the player var focused = document.activeElement; // Ignore if current focus element isn't inside the player
@ -4685,6 +4804,7 @@ typeof navigator === "object" && (function (global, factory) {
toggleClass(document.activeElement, player.config.classNames.tabFocus, true); toggleClass(document.activeElement, player.config.classNames.tabFocus, true);
}, 10); }, 10);
}
} // Global window & document listeners } // Global window & document listeners
}, { }, {
@ -4702,7 +4822,7 @@ typeof navigator === "object" && (function (global, factory) {
once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection
toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true); toggleListener.call(player, document.body, 'keydown focus blur focusout', this.setTabFocus, toggle, false, true);
} // Container listeners } // Container listeners
}, { }, {
@ -4745,7 +4865,7 @@ typeof navigator === "object" && (function (global, factory) {
}); // Set a gutter for Vimeo }); // Set a gutter for Vimeo
var setGutter = function setGutter(ratio, padding, toggle) { var setGutter = function setGutter(ratio, padding, toggle) {
if (!player.isVimeo) { if (!player.isVimeo || player.config.vimeo.premium) {
return; return;
} }
@ -4802,7 +4922,7 @@ typeof navigator === "object" && (function (global, factory) {
ratio = _setPlayerSize.ratio; // Set Vimeo gutter ratio = _setPlayerSize.ratio; // Set Vimeo gutter
setGutter(ratio, padding, isEnter); // If not using native fullscreen, we need to check for resizes of viewport setGutter(ratio, padding, isEnter); // If not using native browser fullscreen API, we need to check for resizes of viewport
if (!usingNative) { if (!usingNative) {
if (isEnter) { if (isEnter) {
@ -4880,9 +5000,13 @@ typeof navigator === "object" && (function (global, factory) {
if (player.ended) { if (player.ended) {
_this.proxy(event, player.restart, 'restart'); _this.proxy(event, player.restart, 'restart');
_this.proxy(event, player.play, 'play'); _this.proxy(event, function () {
silencePromise(player.play());
}, 'play');
} else { } else {
_this.proxy(event, player.togglePlay, 'play'); _this.proxy(event, function () {
silencePromise(player.togglePlay());
}, 'play');
} }
}); });
} // Disable right click } // Disable right click
@ -4980,7 +5104,9 @@ typeof navigator === "object" && (function (global, factory) {
if (elements.buttons.play) { if (elements.buttons.play) {
Array.from(elements.buttons.play).forEach(function (button) { Array.from(elements.buttons.play).forEach(function (button) {
_this3.bind(button, 'click', player.togglePlay, 'play'); _this3.bind(button, 'click', function () {
silencePromise(player.togglePlay());
}, 'play');
}); });
} // Pause } // Pause
@ -5077,7 +5203,7 @@ typeof navigator === "object" && (function (global, factory) {
if (play && done) { if (play && done) {
seek.removeAttribute(attribute); seek.removeAttribute(attribute);
player.play(); silencePromise(player.play());
} else if (!done && player.playing) { } else if (!done && player.playing) {
seek.setAttribute(attribute, ''); seek.setAttribute(attribute, '');
player.pause(); player.pause();
@ -5175,7 +5301,18 @@ typeof navigator === "object" && (function (global, factory) {
this.bind(elements.controls, 'mouseenter mouseleave', function (event) { this.bind(elements.controls, 'mouseenter mouseleave', function (event) {
elements.controls.hover = !player.touch && event.type === 'mouseenter'; elements.controls.hover = !player.touch && event.type === 'mouseenter';
}); // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting) }); // Also update controls.hover state for any non-player children of fullscreen element (as above)
if (elements.fullscreen) {
Array.from(elements.fullscreen.children).filter(function (c) {
return !c.contains(elements.container);
}).forEach(function (child) {
_this3.bind(child, 'mouseenter mouseleave', function (event) {
elements.controls.hover = !player.touch && event.type === 'mouseenter';
});
});
} // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)
this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) {
elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);
@ -5591,15 +5728,28 @@ typeof navigator === "object" && (function (global, factory) {
var _this = this; var _this = this;
var player = this; var player = this;
var config = player.config.vimeo; // Get Vimeo params for the iframe var config = player.config.vimeo;
var params = buildUrlParams(extend({}, { var premium = config.premium,
referrerPolicy = config.referrerPolicy,
frameParams = _objectWithoutProperties(config, ["premium", "referrerPolicy"]); // If the owner has a pro or premium account then we can hide controls etc
if (premium) {
Object.assign(frameParams, {
controls: false,
sidedock: false
});
} // Get Vimeo params for the iframe
var params = buildUrlParams(_objectSpread2({
loop: player.config.loop.active, loop: player.config.loop.active,
autoplay: player.autoplay, autoplay: player.autoplay,
muted: player.muted, muted: player.muted,
gesture: 'media', gesture: 'media',
playsinline: !this.config.fullscreen.iosNative playsinline: !this.config.fullscreen.iosNative
}, config)); // Get the source URL or ID }, frameParams)); // Get the source URL or ID
var source = player.media.getAttribute('src'); // Get from <div> if needed var source = player.media.getAttribute('src'); // Get from <div> if needed
@ -5613,22 +5763,27 @@ typeof navigator === "object" && (function (global, factory) {
var src = format(player.config.urls.vimeo.iframe, id, params); var src = format(player.config.urls.vimeo.iframe, id, params);
iframe.setAttribute('src', src); iframe.setAttribute('src', src);
iframe.setAttribute('allowfullscreen', ''); iframe.setAttribute('allowfullscreen', '');
iframe.setAttribute('allowtransparency', ''); iframe.setAttribute('allow', 'autoplay,fullscreen,picture-in-picture'); // Set the referrer policy if required
iframe.setAttribute('allow', 'autoplay'); // Set the referrer policy if required
if (!is$1.empty(config.referrerPolicy)) { if (!is$1.empty(referrerPolicy)) {
iframe.setAttribute('referrerPolicy', config.referrerPolicy); iframe.setAttribute('referrerPolicy', referrerPolicy);
} // Get poster, if already set } // Inject the package
var poster = player.poster; // Inject the package var poster = player.poster;
if (premium) {
iframe.setAttribute('data-poster', poster);
player.media = replaceElement(iframe, player.media);
} else {
var wrapper = createElement('div', { var wrapper = createElement('div', {
poster: poster, class: player.config.classNames.embedContainer,
class: player.config.classNames.embedContainer 'data-poster': poster
}); });
wrapper.appendChild(iframe); wrapper.appendChild(iframe);
player.media = replaceElement(wrapper, player.media); // Get poster image player.media = replaceElement(wrapper, player.media);
} // Get poster image
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
if (is$1.empty(response)) { if (is$1.empty(response)) {
@ -5712,6 +5867,9 @@ typeof navigator === "object" && (function (global, factory) {
player.embed.setPlaybackRate(input).then(function () { player.embed.setPlaybackRate(input).then(function () {
speed = input; speed = input;
triggerEvent.call(player, player.media, 'ratechange'); triggerEvent.call(player, player.media, 'ratechange');
}).catch(function () {
// Cannot set Playback Rate, Video is probably not on Pro account
player.options.speed = [1];
}); });
} }
}); // Volume }); // Volume
@ -5998,7 +6156,7 @@ typeof navigator === "object" && (function (global, factory) {
var container = createElement('div', { var container = createElement('div', {
id: id, id: id,
poster: poster 'data-poster': poster
}); });
player.media = replaceElement(container, player.media); // Id to poster wrapper player.media = replaceElement(container, player.media); // Id to poster wrapper
@ -6317,15 +6475,13 @@ typeof navigator === "object" && (function (global, factory) {
class: this.config.classNames.video class: this.config.classNames.video
}); // Wrap the video in a container }); // Wrap the video in a container
wrap(this.media, this.elements.wrapper); // Faux poster container wrap(this.media, this.elements.wrapper); // Poster image container
if (this.isEmbed) {
this.elements.poster = createElement('div', { this.elements.poster = createElement('div', {
class: this.config.classNames.poster class: this.config.classNames.poster
}); });
this.elements.wrapper.appendChild(this.elements.poster); this.elements.wrapper.appendChild(this.elements.poster);
} }
}
if (this.isHTML5) { if (this.isHTML5) {
html5.setup.call(this); html5.setup.call(this);
@ -6451,6 +6607,8 @@ typeof navigator === "object" && (function (global, factory) {
* mobile devices, this initialization is done as the result of a user action. * mobile devices, this initialization is done as the result of a user action.
*/ */
value: function setupIMA() { value: function setupIMA() {
var _this4 = this;
// Create the container for our advertisements // Create the container for our advertisements
this.elements.container = createElement('div', { this.elements.container = createElement('div', {
class: this.player.config.classNames.ads class: this.player.config.classNames.ads
@ -6463,7 +6621,16 @@ typeof navigator === "object" && (function (global, factory) {
google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline); // We assume the adContainer is the video container of the plyr element that will house the ads google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline); // We assume the adContainer is the video container of the plyr element that will house the ads
this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media); // Request video ads to be pre-loaded this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media); // Create ads loader
this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events
this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) {
return _this4.onAdsManagerLoaded(event);
}, false);
this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) {
return _this4.onAdError(error);
}, false); // Request video ads to be pre-loaded
this.requestAds(); this.requestAds();
} }
@ -6474,21 +6641,10 @@ typeof navigator === "object" && (function (global, factory) {
}, { }, {
key: "requestAds", key: "requestAds",
value: function requestAds() { value: function requestAds() {
var _this4 = this;
var container = this.player.elements.container; var container = this.player.elements.container;
try { try {
// Create ads loader // Request video ads
this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events
this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) {
return _this4.onAdsManagerLoaded(event);
}, false);
this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) {
return _this4.onAdError(error);
}, false); // Request video ads
var request = new google.ima.AdsRequest(); var request = new google.ima.AdsRequest();
request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK
// to select the correct creative if multiple are returned // to select the correct creative if multiple are returned
@ -6667,7 +6823,13 @@ typeof navigator === "object" && (function (global, factory) {
// }; // };
// TODO: So there is still this thing where a video should only be allowed to start // 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 // playing when the IMA SDK is ready or has failed
if (this.player.ended) {
this.loadAds(); this.loadAds();
} else {
// The SDK won't allow new ads to be called without receiving a contentComplete()
this.loader.contentComplete();
}
break; break;
case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED: case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:
@ -6803,7 +6965,7 @@ typeof navigator === "object" && (function (global, factory) {
this.playing = false; // Play video this.playing = false; // Play video
this.player.media.play(); silencePromise(this.player.media.play());
} }
/** /**
* Pause our video * Pause our video
@ -6860,7 +7022,9 @@ typeof navigator === "object" && (function (global, factory) {
_this11.on('loaded', resolve); _this11.on('loaded', resolve);
_this11.player.debug.log(_this11.manager); _this11.player.debug.log(_this11.manager);
}); // Now request some new advertisements }); // Now that the manager has been destroyed set it to also be un-initialized
_this11.initialized = false; // Now request some new advertisements
_this11.requestAds(); _this11.requestAds();
}).catch(function () {}); }).catch(function () {});
@ -7104,15 +7268,10 @@ typeof navigator === "object" && (function (global, factory) {
if (is$1.empty(src)) { if (is$1.empty(src)) {
throw new Error('Missing previewThumbnails.src config attribute'); throw new Error('Missing previewThumbnails.src config attribute');
} // If string, convert into single-element list } // Resolve promise
var urls = is$1.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails var sortAndResolve = function sortAndResolve() {
var promises = urls.map(function (u) {
return _this2.getThumbnail(u);
});
Promise.all(promises).then(function () {
// Sort smallest to biggest (e.g., [120p, 480p, 1080p]) // Sort smallest to biggest (e.g., [120p, 480p, 1080p])
_this2.thumbnails.sort(function (x, y) { _this2.thumbnails.sort(function (x, y) {
return x.height - y.height; return x.height - y.height;
@ -7121,7 +7280,25 @@ typeof navigator === "object" && (function (global, factory) {
_this2.player.debug.log('Preview thumbnails', _this2.thumbnails); _this2.player.debug.log('Preview thumbnails', _this2.thumbnails);
resolve(); resolve();
}; // Via callback()
if (is$1.function(src)) {
src(function (thumbnails) {
_this2.thumbnails = thumbnails;
sortAndResolve();
}); });
} // VTT urls
else {
// If string, convert into single-element list
var urls = is$1.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails
var promises = urls.map(function (u) {
return _this2.getThumbnail(u);
}); // Resolve
Promise.all(promises).then(sortAndResolve);
}
}); });
} // Process individual VTT file } // Process individual VTT file
@ -7909,6 +8086,7 @@ typeof navigator === "object" && (function (global, factory) {
this.elements = { this.elements = {
container: null, container: null,
fullscreen: null,
captions: null, captions: null,
buttons: {}, buttons: {},
display: {}, display: {},
@ -8083,9 +8261,11 @@ typeof navigator === "object" && (function (global, factory) {
tabindex: 0 tabindex: 0
}); });
wrap(this.media, this.elements.container); wrap(this.media, this.elements.container);
} // Add style hook } // Migrate custom properties from media to container (so they work 😉)
ui.migrateStyles.call(this); // Add style hook
ui.addStyleHook.call(this); // Setup media ui.addStyleHook.call(this); // Setup media
media.setup.call(this); // Listen for events if debugging media.setup.call(this); // Listen for events if debugging
@ -8094,10 +8274,12 @@ typeof navigator === "object" && (function (global, factory) {
on.call(this, this.elements.container, this.config.events.join(' '), function (event) { on.call(this, this.elements.container, this.config.events.join(' '), function (event) {
_this.debug.log("event: ".concat(event.type)); _this.debug.log("event: ".concat(event.type));
}); });
} // Setup interface } // Setup fullscreen
// If embed but not fully supported, build interface now to avoid flash of controls
this.fullscreen = new Fullscreen(this); // Setup interface
// If embed but not fully supported, build interface now to avoid flash of controls
if (this.isHTML5 || this.isEmbed && !this.supported.ui) { if (this.isHTML5 || this.isEmbed && !this.supported.ui) {
ui.build.call(this); ui.build.call(this);
} // Container listeners } // Container listeners
@ -8105,9 +8287,7 @@ typeof navigator === "object" && (function (global, factory) {
this.listeners.container(); // Global listeners this.listeners.container(); // Global listeners
this.listeners.global(); // Setup fullscreen this.listeners.global(); // Setup ads if provided
this.fullscreen = new Fullscreen(this); // Setup ads if provided
if (this.config.ads.enabled) { if (this.config.ads.enabled) {
this.ads = new Ads(this); this.ads = new Ads(this);
@ -8116,7 +8296,7 @@ typeof navigator === "object" && (function (global, factory) {
if (this.isHTML5 && this.config.autoplay) { if (this.isHTML5 && this.config.autoplay) {
setTimeout(function () { setTimeout(function () {
return _this.play(); return silencePromise(_this.play());
}, 10); }, 10);
} // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek
@ -8153,7 +8333,7 @@ typeof navigator === "object" && (function (global, factory) {
this.ads.managerPromise.then(function () { this.ads.managerPromise.then(function () {
return _this2.ads.play(); return _this2.ads.play();
}).catch(function () { }).catch(function () {
return _this2.media.play(); return silencePromise(_this2.media.play());
}); });
} // Return the promise (for HTML5) } // Return the promise (for HTML5)
@ -8313,7 +8493,7 @@ typeof navigator === "object" && (function (global, factory) {
var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu
if (hiding && this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) { if (hiding && is$1.array(this.config.controls) && this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) {
controls.toggleMenu.call(this, false); controls.toggleMenu.call(this, false);
} // Trigger event on change } // Trigger event on change
@ -8806,7 +8986,7 @@ typeof navigator === "object" && (function (global, factory) {
var updateStorage = true; var updateStorage = true;
if (!options.includes(quality)) { if (!options.includes(quality)) {
var value = closest(options, quality); var value = closest$1(options, quality);
this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead")); this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead"));
quality = value; // Don't update storage if quality is not supported quality = value; // Don't update storage if quality is not supported
@ -8951,7 +9131,7 @@ typeof navigator === "object" && (function (global, factory) {
return null; return null;
} }
return this.media.getAttribute('poster'); return this.media.getAttribute('poster') || this.media.getAttribute('data-poster');
} }
/** /**
* Get the current aspect ratio in use * Get the current aspect ratio in use

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -69,20 +69,52 @@ function _objectSpread2(target) {
return target; return target;
} }
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function _slicedToArray(arr, i) { function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
} }
function _toConsumableArray(arr) { function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
} }
function _arrayWithoutHoles(arr) { function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) { if (Array.isArray(arr)) return _arrayLikeToArray(arr);
for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
}
} }
function _arrayWithHoles(arr) { function _arrayWithHoles(arr) {
@ -90,14 +122,11 @@ function _arrayWithHoles(arr) {
} }
function _iterableToArray(iter) { function _iterableToArray(iter) {
if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
} }
function _iterableToArrayLimit(arr, i) { function _iterableToArrayLimit(arr, i) {
if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
return;
}
var _arr = []; var _arr = [];
var _n = true; var _n = true;
var _d = false; var _d = false;
@ -123,12 +152,29 @@ function _iterableToArrayLimit(arr, i) {
return _arr; return _arr;
} }
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread() { function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance"); throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
} }
function _nonIterableRest() { function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance"); throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
} }
function _classCallCheck$1(e, t) { function _classCallCheck$1(e, t) {
@ -421,7 +467,7 @@ var isTrack = function isTrack(input) {
}; };
var isPromise = function isPromise(input) { var isPromise = function isPromise(input) {
return instanceOf$1(input, Promise); return instanceOf$1(input, Promise) && isFunction$1(input.then);
}; };
var isEmpty$1 = function isEmpty(input) { var isEmpty$1 = function isEmpty(input) {
@ -763,12 +809,33 @@ function hasClass(element, className) {
} // Element matches selector } // Element matches selector
function matches$1(element, selector) { function matches$1(element, selector) {
var _Element = Element,
prototype = _Element.prototype;
function match() { function match() {
return Array.from(document.querySelectorAll(selector)).includes(this); return Array.from(document.querySelectorAll(selector)).includes(this);
} }
var method = match; var method = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match;
return method.call(element, selector);
} // Closest ancestor element matching selector (also tests element itself)
function closest(element, selector) {
var _Element2 = Element,
prototype = _Element2.prototype; // https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
function closestElement() {
var el = this;
do {
if (matches$1.matches(el, selector)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
}
var method = prototype.closest || closestElement;
return method.call(element, selector); return method.call(element, selector);
} // Find all elements } // Find all elements
@ -1011,7 +1078,7 @@ function triggerEvent(element) {
var event = new CustomEvent(type, { var event = new CustomEvent(type, {
bubbles: bubbles, bubbles: bubbles,
detail: _objectSpread2({}, detail, { detail: _objectSpread2(_objectSpread2({}, detail), {}, {
plyr: this plyr: this
}) })
}); // Dispatch the event }); // Dispatch the event
@ -1040,6 +1107,19 @@ function ready() {
}).then(function () {}); }).then(function () {});
} }
/**
* Silence a Promise-like object.
* This is useful for avoiding non-harmful, but potentially confusing "uncaught
* play promise" rejection error messages.
* @param {Object} value An object that may or may not be `Promise`-like.
*/
function silencePromise(value) {
if (is$1.promise(value)) {
value.then(null, function () {});
}
}
function validateRatio(input) { function validateRatio(input) {
if (!is$1.array(input) && (!is$1.string(input) || !input.includes(':'))) { if (!is$1.array(input) && (!is$1.string(input) || !input.includes(':'))) {
return false; return false;
@ -1108,8 +1188,8 @@ function setAspectRatio(input) {
var padding = 100 / w * h; var padding = 100 / w * h;
wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI
if (this.isVimeo && this.supported.ui) { if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
var height = 240; var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
var offset = (height - padding) / (height / 50); var offset = (height - padding) / (height / 50);
this.media.style.transform = "translateY(-".concat(offset, "%)"); this.media.style.transform = "translateY(-".concat(offset, "%)");
} else if (this.isHTML5) { } else if (this.isHTML5) {
@ -1216,7 +1296,7 @@ var html5 = {
player.currentTime = currentTime; // Resume playing player.currentTime = currentTime; // Resume playing
if (!paused) { if (!paused) {
player.play(); silencePromise(player.play());
} }
}); // Load new source }); // Load new source
@ -1265,7 +1345,7 @@ function dedupe(array) {
}); });
} // Get the closest value in an array } // Get the closest value in an array
function closest(array, value) { function closest$1(array, value) {
if (!is$1.array(array) || !array.length) { if (!is$1.array(array) || !array.length) {
return null; return null;
} }
@ -1303,19 +1383,19 @@ function getPercentage(current, max) {
return (current / max * 100).toFixed(2); return (current / max * 100).toFixed(2);
} // Replace all occurances of a string in a string } // Replace all occurances of a string in a string
function replaceAll() { var replaceAll = function replaceAll() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString());
} // Convert to title case }; // Convert to title case
function toTitleCase() { var toTitleCase = function toTitleCase() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
return input.toString().replace(/\w\S*/g, function (text) { return input.toString().replace(/\w\S*/g, function (text) {
return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase();
}); });
} // Convert string to pascalCase }; // Convert string to pascalCase
function toPascalCase() { function toPascalCase() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
@ -1676,7 +1756,7 @@ var controls = {
var icon = document.createElementNS(namespace, 'svg'); var icon = document.createElementNS(namespace, 'svg');
setAttributes(icon, extend(attributes, { setAttributes(icon, extend(attributes, {
role: 'presentation', 'aria-hidden': 'true',
focusable: 'false' focusable: 'false'
})); // Create the <use> to reference sprite })); // Create the <use> to reference sprite
@ -1700,7 +1780,7 @@ var controls = {
var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var text = i18n.get(key, this.config); var text = i18n.get(key, this.config);
var attributes = _objectSpread2({}, attr, { var attributes = _objectSpread2(_objectSpread2({}, attr), {}, {
class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ') class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ')
}); });
@ -2459,7 +2539,7 @@ var controls = {
var type = 'captions'; var type = 'captions';
var list = this.elements.settings.panels.captions.querySelector('[role="menu"]'); var list = this.elements.settings.panels.captions.querySelector('[role="menucaptions"]');
var tracks = captions.getTracks.call(this); var tracks = captions.getTracks.call(this);
var toggle = Boolean(tracks.length); // Toggle the pane and tab var toggle = Boolean(tracks.length); // Toggle the pane and tab
@ -2700,7 +2780,7 @@ var controls = {
showMenuPanel = controls.showMenuPanel; showMenuPanel = controls.showMenuPanel;
this.elements.controls = null; // Larger overlaid play button this.elements.controls = null; // Larger overlaid play button
if (this.config.controls.includes('play-large')) { if (is$1.array(this.config.controls) && this.config.controls.includes('play-large')) {
this.elements.container.appendChild(createButton.call(this, 'play-large')); this.elements.container.appendChild(createButton.call(this, 'play-large'));
} // Create the container } // Create the container
@ -2712,7 +2792,7 @@ var controls = {
class: 'plyr__controls__item' class: 'plyr__controls__item'
}; // Loop through controls in order }; // Loop through controls in order
dedupe(this.config.controls).forEach(function (control) { dedupe(is$1.array(this.config.controls) ? this.config.controls : []).forEach(function (control) {
// Restart button // Restart button
if (control === 'restart') { if (control === 'restart') {
container.appendChild(createButton.call(_this10, 'restart', defaultAttributes)); container.appendChild(createButton.call(_this10, 'restart', defaultAttributes));
@ -2901,6 +2981,10 @@ var controls = {
pane.appendChild(createElement('div', { pane.appendChild(createElement('div', {
role: 'menu' role: 'menu'
})); // Menu Captions
pane.appendChild(createElement('div', {
role: 'menucaptions'
})); }));
inner.appendChild(pane); inner.appendChild(pane);
_this10.elements.settings.buttons[type] = menuItem; _this10.elements.settings.buttons[type] = menuItem;
@ -3031,8 +3115,6 @@ var controls = {
if (update) { if (update) {
if (is$1.string(this.config.controls)) { if (is$1.string(this.config.controls)) {
container = replace(container); container = replace(container);
} else if (is$1.element(container)) {
container.innerHTML = replace(container.innerHTML);
} }
} // Controls container } // Controls container
@ -3247,9 +3329,15 @@ var captions = {
meta.set(track, { meta.set(track, {
default: track.mode === 'showing' default: track.mode === 'showing'
}); // Turn off native caption rendering to avoid double captions }); // Turn off native caption rendering to avoid double captions
// Note: mode='hidden' forces a track to download. To ensure every track
// isn't downloaded at once, only 'showing' tracks should be reassigned
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
track.mode = 'hidden'; // Add event listener for cue changes if (track.mode === 'showing') {
// eslint-disable-next-line no-param-reassign
track.mode = 'hidden';
} // Add event listener for cue changes
on.call(_this, track, 'cuechange', function () { on.call(_this, track, 'cuechange', function () {
return captions.updateCues.call(_this); return captions.updateCues.call(_this);
@ -3266,13 +3354,15 @@ var captions = {
toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is$1.empty(tracks)); // Update available languages in list toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is$1.empty(tracks)); // Update available languages in list
if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) { if (is$1.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {
controls.setCaptionsMenu.call(this); controls.setCaptionsMenu.call(this);
} }
}, },
// Toggle captions display // Toggle captions display
// Used internally for the toggleCaptions method, with the passive option forced to false // Used internally for the toggleCaptions method, with the passive option forced to false
toggle: function toggle(input) { toggle: function toggle(input) {
var _this2 = this;
var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
// If there's no full support // If there's no full support
@ -3319,7 +3409,15 @@ var captions = {
controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally) controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally)
triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled'); triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');
} // Wait for the call stack to clear before setting mode='hidden'
// on the active track - forcing the browser to download it
setTimeout(function () {
if (active && _this2.captions.toggled) {
_this2.captions.currentTrackNode.mode = 'hidden';
} }
});
}, },
// Set captions by track index // Set captions by track index
// Used internally for the currentTrack setter with the passive option forced to false // Used internally for the currentTrack setter with the passive option forced to false
@ -3400,7 +3498,7 @@ var captions = {
// If update is false it will also ignore tracks without metadata // If update is false it will also ignore tracks without metadata
// This is used to "freeze" the language options when captions.update is false // This is used to "freeze" the language options when captions.update is false
getTracks: function getTracks() { getTracks: function getTracks() {
var _this2 = this; var _this3 = this;
var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
// Handle media or textTracks missing or null // Handle media or textTracks missing or null
@ -3408,20 +3506,20 @@ var captions = {
// Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata) // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)
return tracks.filter(function (track) { return tracks.filter(function (track) {
return !_this2.isHTML5 || update || _this2.captions.meta.has(track); return !_this3.isHTML5 || update || _this3.captions.meta.has(track);
}).filter(function (track) { }).filter(function (track) {
return ['captions', 'subtitles'].includes(track.kind); return ['captions', 'subtitles'].includes(track.kind);
}); });
}, },
// Match tracks based on languages and get the first // Match tracks based on languages and get the first
findTrack: function findTrack(languages) { findTrack: function findTrack(languages) {
var _this3 = this; var _this4 = this;
var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var tracks = captions.getTracks.call(this); var tracks = captions.getTracks.call(this);
var sortIsDefault = function sortIsDefault(track) { var sortIsDefault = function sortIsDefault(track) {
return Number((_this3.captions.meta.get(track) || {}).default); return Number((_this4.captions.meta.get(track) || {}).default);
}; };
var sorted = Array.from(tracks).sort(function (a, b) { var sorted = Array.from(tracks).sort(function (a, b) {
@ -3602,6 +3700,9 @@ var defaults$1 = {
fallback: true, fallback: true,
// Fallback using full viewport/window // Fallback using full viewport/window
iosNative: false // Use the native fullscreen in iOS (disables custom controls) iosNative: false // Use the native fullscreen in iOS (disables custom controls)
// Selector for the fullscreen container so contextual / non-player content can remain visible in fullscreen mode
// Non-ancestors of the player element will be ignored
// container: null, // defaults to the player element
}, },
// Local storage // Local storage
@ -3839,16 +3940,16 @@ var defaults$1 = {
title: false, title: false,
speed: true, speed: true,
transparent: false, transparent: false,
// These settings require a pro or premium account to work // Whether the owner of the video has a Pro or Business account
sidedock: false, // (which allows us to properly hide controls without CSS hacks, etc)
controls: false, premium: false,
// Custom settings from Plyr // Custom settings from Plyr
referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
}, },
// YouTube plugin // YouTube plugin
youtube: { youtube: {
noCookie: false, noCookie: true,
// Whether to use an alternative version of YouTube without cookies // Whether to use an alternative version of YouTube without cookies
rel: 0, rel: 0,
// No related vids // No related vids
@ -3958,7 +4059,10 @@ var Fullscreen = /*#__PURE__*/function () {
y: 0 y: 0
}; // Force the use of 'full window/browser' rather than fullscreen }; // Force the use of 'full window/browser' rather than fullscreen
this.forceFallback = player.config.fullscreen.fallback === 'force'; // Register event listeners this.forceFallback = player.config.fullscreen.fallback === 'force'; // Get the fullscreen element
// Checks container is an ancestor, defaults to null
this.player.elements.fullscreen = player.config.fullscreen.container && closest(this.player.elements.container, player.config.fullscreen.container); // Register event listeners
// Handle event (incase user presses escape etc) // Handle event (incase user presses escape etc)
on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () { on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () {
@ -4131,7 +4235,7 @@ var Fullscreen = /*#__PURE__*/function () {
if (browser.isIos && this.player.config.fullscreen.iosNative) { if (browser.isIos && this.player.config.fullscreen.iosNative) {
this.target.webkitExitFullscreen(); this.target.webkitExitFullscreen();
this.player.play(); silencePromise(this.player.play());
} else if (!Fullscreen.native || this.forceFallback) { } else if (!Fullscreen.native || this.forceFallback) {
this.toggleFallback(false); this.toggleFallback(false);
} else if (!this.prefix) { } else if (!this.prefix) {
@ -4178,13 +4282,13 @@ var Fullscreen = /*#__PURE__*/function () {
} }
var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")]; var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")];
return element === this.target; return element && element.shadowRoot ? element === this.target.getRootNode().host : element === this.target;
} // Get target element } // Get target element
}, { }, {
key: "target", key: "target",
get: function get() { get: function get() {
return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.fullscreen || this.player.elements.container;
} }
}], [{ }], [{
key: "native", key: "native",
@ -4246,7 +4350,6 @@ function loadImage(src) {
}); });
} }
// ==========================================================================
var ui = { var ui = {
addStyleHook: function addStyleHook() { addStyleHook: function addStyleHook() {
toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true); toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);
@ -4381,12 +4484,7 @@ var ui = {
} // Set property synchronously to respect the call order } // Set property synchronously to respect the call order
this.media.setAttribute('poster', poster); // HTML5 uses native poster attribute this.media.setAttribute('data-poster', poster); // Wait until ui is ready
if (this.isHTML5) {
return Promise.resolve(poster);
} // Wait until ui is ready
return ready.call(this) // Load image return ready.call(this) // Load image
.then(function () { .then(function () {
@ -4462,6 +4560,26 @@ var ui = {
this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek)); this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek));
} }
},
// Migrate any custom properties from the media to the parent
migrateStyles: function migrateStyles() {
var _this5 = this;
// Loop through values (as they are the keys when the object is spread 🤔)
Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties
.filter(function (key) {
return !is$1.empty(key) && key.startsWith('--plyr');
}).forEach(function (key) {
// Set on the container
_this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element
_this5.media.style.removeProperty(key);
}); // Remove attribute if empty
if (is$1.empty(this.media.style)) {
this.media.removeAttribute('style');
}
} }
}; };
@ -4556,7 +4674,7 @@ var Listeners = /*#__PURE__*/function () {
case 75: case 75:
// Space and K key // Space and K key
if (!repeat) { if (!repeat) {
player.togglePlay(); silencePromise(player.togglePlay());
} }
break; break;
@ -4670,6 +4788,7 @@ var Listeners = /*#__PURE__*/function () {
removeCurrent(); // Delay the adding of classname until the focus has changed removeCurrent(); // Delay the adding of classname until the focus has changed
// This event fires before the focusin event // This event fires before the focusin event
if (event.type !== 'focusout') {
this.focusTimer = setTimeout(function () { this.focusTimer = setTimeout(function () {
var focused = document.activeElement; // Ignore if current focus element isn't inside the player var focused = document.activeElement; // Ignore if current focus element isn't inside the player
@ -4679,6 +4798,7 @@ var Listeners = /*#__PURE__*/function () {
toggleClass(document.activeElement, player.config.classNames.tabFocus, true); toggleClass(document.activeElement, player.config.classNames.tabFocus, true);
}, 10); }, 10);
}
} // Global window & document listeners } // Global window & document listeners
}, { }, {
@ -4696,7 +4816,7 @@ var Listeners = /*#__PURE__*/function () {
once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection
toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true); toggleListener.call(player, document.body, 'keydown focus blur focusout', this.setTabFocus, toggle, false, true);
} // Container listeners } // Container listeners
}, { }, {
@ -4739,7 +4859,7 @@ var Listeners = /*#__PURE__*/function () {
}); // Set a gutter for Vimeo }); // Set a gutter for Vimeo
var setGutter = function setGutter(ratio, padding, toggle) { var setGutter = function setGutter(ratio, padding, toggle) {
if (!player.isVimeo) { if (!player.isVimeo || player.config.vimeo.premium) {
return; return;
} }
@ -4796,7 +4916,7 @@ var Listeners = /*#__PURE__*/function () {
ratio = _setPlayerSize.ratio; // Set Vimeo gutter ratio = _setPlayerSize.ratio; // Set Vimeo gutter
setGutter(ratio, padding, isEnter); // If not using native fullscreen, we need to check for resizes of viewport setGutter(ratio, padding, isEnter); // If not using native browser fullscreen API, we need to check for resizes of viewport
if (!usingNative) { if (!usingNative) {
if (isEnter) { if (isEnter) {
@ -4874,9 +4994,13 @@ var Listeners = /*#__PURE__*/function () {
if (player.ended) { if (player.ended) {
_this.proxy(event, player.restart, 'restart'); _this.proxy(event, player.restart, 'restart');
_this.proxy(event, player.play, 'play'); _this.proxy(event, function () {
silencePromise(player.play());
}, 'play');
} else { } else {
_this.proxy(event, player.togglePlay, 'play'); _this.proxy(event, function () {
silencePromise(player.togglePlay());
}, 'play');
} }
}); });
} // Disable right click } // Disable right click
@ -4974,7 +5098,9 @@ var Listeners = /*#__PURE__*/function () {
if (elements.buttons.play) { if (elements.buttons.play) {
Array.from(elements.buttons.play).forEach(function (button) { Array.from(elements.buttons.play).forEach(function (button) {
_this3.bind(button, 'click', player.togglePlay, 'play'); _this3.bind(button, 'click', function () {
silencePromise(player.togglePlay());
}, 'play');
}); });
} // Pause } // Pause
@ -5071,7 +5197,7 @@ var Listeners = /*#__PURE__*/function () {
if (play && done) { if (play && done) {
seek.removeAttribute(attribute); seek.removeAttribute(attribute);
player.play(); silencePromise(player.play());
} else if (!done && player.playing) { } else if (!done && player.playing) {
seek.setAttribute(attribute, ''); seek.setAttribute(attribute, '');
player.pause(); player.pause();
@ -5169,7 +5295,18 @@ var Listeners = /*#__PURE__*/function () {
this.bind(elements.controls, 'mouseenter mouseleave', function (event) { this.bind(elements.controls, 'mouseenter mouseleave', function (event) {
elements.controls.hover = !player.touch && event.type === 'mouseenter'; elements.controls.hover = !player.touch && event.type === 'mouseenter';
}); // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting) }); // Also update controls.hover state for any non-player children of fullscreen element (as above)
if (elements.fullscreen) {
Array.from(elements.fullscreen.children).filter(function (c) {
return !c.contains(elements.container);
}).forEach(function (child) {
_this3.bind(child, 'mouseenter mouseleave', function (event) {
elements.controls.hover = !player.touch && event.type === 'mouseenter';
});
});
} // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)
this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) {
elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);
@ -5585,15 +5722,28 @@ var vimeo = {
var _this = this; var _this = this;
var player = this; var player = this;
var config = player.config.vimeo; // Get Vimeo params for the iframe var config = player.config.vimeo;
var params = buildUrlParams(extend({}, { var premium = config.premium,
referrerPolicy = config.referrerPolicy,
frameParams = _objectWithoutProperties(config, ["premium", "referrerPolicy"]); // If the owner has a pro or premium account then we can hide controls etc
if (premium) {
Object.assign(frameParams, {
controls: false,
sidedock: false
});
} // Get Vimeo params for the iframe
var params = buildUrlParams(_objectSpread2({
loop: player.config.loop.active, loop: player.config.loop.active,
autoplay: player.autoplay, autoplay: player.autoplay,
muted: player.muted, muted: player.muted,
gesture: 'media', gesture: 'media',
playsinline: !this.config.fullscreen.iosNative playsinline: !this.config.fullscreen.iosNative
}, config)); // Get the source URL or ID }, frameParams)); // Get the source URL or ID
var source = player.media.getAttribute('src'); // Get from <div> if needed var source = player.media.getAttribute('src'); // Get from <div> if needed
@ -5607,22 +5757,27 @@ var vimeo = {
var src = format(player.config.urls.vimeo.iframe, id, params); var src = format(player.config.urls.vimeo.iframe, id, params);
iframe.setAttribute('src', src); iframe.setAttribute('src', src);
iframe.setAttribute('allowfullscreen', ''); iframe.setAttribute('allowfullscreen', '');
iframe.setAttribute('allowtransparency', ''); iframe.setAttribute('allow', 'autoplay,fullscreen,picture-in-picture'); // Set the referrer policy if required
iframe.setAttribute('allow', 'autoplay'); // Set the referrer policy if required
if (!is$1.empty(config.referrerPolicy)) { if (!is$1.empty(referrerPolicy)) {
iframe.setAttribute('referrerPolicy', config.referrerPolicy); iframe.setAttribute('referrerPolicy', referrerPolicy);
} // Get poster, if already set } // Inject the package
var poster = player.poster; // Inject the package var poster = player.poster;
if (premium) {
iframe.setAttribute('data-poster', poster);
player.media = replaceElement(iframe, player.media);
} else {
var wrapper = createElement('div', { var wrapper = createElement('div', {
poster: poster, class: player.config.classNames.embedContainer,
class: player.config.classNames.embedContainer 'data-poster': poster
}); });
wrapper.appendChild(iframe); wrapper.appendChild(iframe);
player.media = replaceElement(wrapper, player.media); // Get poster image player.media = replaceElement(wrapper, player.media);
} // Get poster image
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
if (is$1.empty(response)) { if (is$1.empty(response)) {
@ -5706,6 +5861,9 @@ var vimeo = {
player.embed.setPlaybackRate(input).then(function () { player.embed.setPlaybackRate(input).then(function () {
speed = input; speed = input;
triggerEvent.call(player, player.media, 'ratechange'); triggerEvent.call(player, player.media, 'ratechange');
}).catch(function () {
// Cannot set Playback Rate, Video is probably not on Pro account
player.options.speed = [1];
}); });
} }
}); // Volume }); // Volume
@ -5992,7 +6150,7 @@ var youtube = {
var container = createElement('div', { var container = createElement('div', {
id: id, id: id,
poster: poster 'data-poster': poster
}); });
player.media = replaceElement(container, player.media); // Id to poster wrapper player.media = replaceElement(container, player.media); // Id to poster wrapper
@ -6311,15 +6469,13 @@ var media = {
class: this.config.classNames.video class: this.config.classNames.video
}); // Wrap the video in a container }); // Wrap the video in a container
wrap(this.media, this.elements.wrapper); // Faux poster container wrap(this.media, this.elements.wrapper); // Poster image container
if (this.isEmbed) {
this.elements.poster = createElement('div', { this.elements.poster = createElement('div', {
class: this.config.classNames.poster class: this.config.classNames.poster
}); });
this.elements.wrapper.appendChild(this.elements.poster); this.elements.wrapper.appendChild(this.elements.poster);
} }
}
if (this.isHTML5) { if (this.isHTML5) {
html5.setup.call(this); html5.setup.call(this);
@ -6445,6 +6601,8 @@ var Ads = /*#__PURE__*/function () {
* mobile devices, this initialization is done as the result of a user action. * mobile devices, this initialization is done as the result of a user action.
*/ */
value: function setupIMA() { value: function setupIMA() {
var _this4 = this;
// Create the container for our advertisements // Create the container for our advertisements
this.elements.container = createElement('div', { this.elements.container = createElement('div', {
class: this.player.config.classNames.ads class: this.player.config.classNames.ads
@ -6457,7 +6615,16 @@ var Ads = /*#__PURE__*/function () {
google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline); // We assume the adContainer is the video container of the plyr element that will house the ads google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline); // We assume the adContainer is the video container of the plyr element that will house the ads
this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media); // Request video ads to be pre-loaded this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media); // Create ads loader
this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events
this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) {
return _this4.onAdsManagerLoaded(event);
}, false);
this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) {
return _this4.onAdError(error);
}, false); // Request video ads to be pre-loaded
this.requestAds(); this.requestAds();
} }
@ -6468,21 +6635,10 @@ var Ads = /*#__PURE__*/function () {
}, { }, {
key: "requestAds", key: "requestAds",
value: function requestAds() { value: function requestAds() {
var _this4 = this;
var container = this.player.elements.container; var container = this.player.elements.container;
try { try {
// Create ads loader // Request video ads
this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events
this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) {
return _this4.onAdsManagerLoaded(event);
}, false);
this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) {
return _this4.onAdError(error);
}, false); // Request video ads
var request = new google.ima.AdsRequest(); var request = new google.ima.AdsRequest();
request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK
// to select the correct creative if multiple are returned // to select the correct creative if multiple are returned
@ -6661,7 +6817,13 @@ var Ads = /*#__PURE__*/function () {
// }; // };
// TODO: So there is still this thing where a video should only be allowed to start // 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 // playing when the IMA SDK is ready or has failed
if (this.player.ended) {
this.loadAds(); this.loadAds();
} else {
// The SDK won't allow new ads to be called without receiving a contentComplete()
this.loader.contentComplete();
}
break; break;
case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED: case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:
@ -6797,7 +6959,7 @@ var Ads = /*#__PURE__*/function () {
this.playing = false; // Play video this.playing = false; // Play video
this.player.media.play(); silencePromise(this.player.media.play());
} }
/** /**
* Pause our video * Pause our video
@ -6854,7 +7016,9 @@ var Ads = /*#__PURE__*/function () {
_this11.on('loaded', resolve); _this11.on('loaded', resolve);
_this11.player.debug.log(_this11.manager); _this11.player.debug.log(_this11.manager);
}); // Now request some new advertisements }); // Now that the manager has been destroyed set it to also be un-initialized
_this11.initialized = false; // Now request some new advertisements
_this11.requestAds(); _this11.requestAds();
}).catch(function () {}); }).catch(function () {});
@ -7098,15 +7262,10 @@ var PreviewThumbnails = /*#__PURE__*/function () {
if (is$1.empty(src)) { if (is$1.empty(src)) {
throw new Error('Missing previewThumbnails.src config attribute'); throw new Error('Missing previewThumbnails.src config attribute');
} // If string, convert into single-element list } // Resolve promise
var urls = is$1.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails var sortAndResolve = function sortAndResolve() {
var promises = urls.map(function (u) {
return _this2.getThumbnail(u);
});
Promise.all(promises).then(function () {
// Sort smallest to biggest (e.g., [120p, 480p, 1080p]) // Sort smallest to biggest (e.g., [120p, 480p, 1080p])
_this2.thumbnails.sort(function (x, y) { _this2.thumbnails.sort(function (x, y) {
return x.height - y.height; return x.height - y.height;
@ -7115,7 +7274,25 @@ var PreviewThumbnails = /*#__PURE__*/function () {
_this2.player.debug.log('Preview thumbnails', _this2.thumbnails); _this2.player.debug.log('Preview thumbnails', _this2.thumbnails);
resolve(); resolve();
}; // Via callback()
if (is$1.function(src)) {
src(function (thumbnails) {
_this2.thumbnails = thumbnails;
sortAndResolve();
}); });
} // VTT urls
else {
// If string, convert into single-element list
var urls = is$1.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails
var promises = urls.map(function (u) {
return _this2.getThumbnail(u);
}); // Resolve
Promise.all(promises).then(sortAndResolve);
}
}); });
} // Process individual VTT file } // Process individual VTT file
@ -7903,6 +8080,7 @@ var Plyr = /*#__PURE__*/function () {
this.elements = { this.elements = {
container: null, container: null,
fullscreen: null,
captions: null, captions: null,
buttons: {}, buttons: {},
display: {}, display: {},
@ -8077,9 +8255,11 @@ var Plyr = /*#__PURE__*/function () {
tabindex: 0 tabindex: 0
}); });
wrap(this.media, this.elements.container); wrap(this.media, this.elements.container);
} // Add style hook } // Migrate custom properties from media to container (so they work 😉)
ui.migrateStyles.call(this); // Add style hook
ui.addStyleHook.call(this); // Setup media ui.addStyleHook.call(this); // Setup media
media.setup.call(this); // Listen for events if debugging media.setup.call(this); // Listen for events if debugging
@ -8088,10 +8268,12 @@ var Plyr = /*#__PURE__*/function () {
on.call(this, this.elements.container, this.config.events.join(' '), function (event) { on.call(this, this.elements.container, this.config.events.join(' '), function (event) {
_this.debug.log("event: ".concat(event.type)); _this.debug.log("event: ".concat(event.type));
}); });
} // Setup interface } // Setup fullscreen
// If embed but not fully supported, build interface now to avoid flash of controls
this.fullscreen = new Fullscreen(this); // Setup interface
// If embed but not fully supported, build interface now to avoid flash of controls
if (this.isHTML5 || this.isEmbed && !this.supported.ui) { if (this.isHTML5 || this.isEmbed && !this.supported.ui) {
ui.build.call(this); ui.build.call(this);
} // Container listeners } // Container listeners
@ -8099,9 +8281,7 @@ var Plyr = /*#__PURE__*/function () {
this.listeners.container(); // Global listeners this.listeners.container(); // Global listeners
this.listeners.global(); // Setup fullscreen this.listeners.global(); // Setup ads if provided
this.fullscreen = new Fullscreen(this); // Setup ads if provided
if (this.config.ads.enabled) { if (this.config.ads.enabled) {
this.ads = new Ads(this); this.ads = new Ads(this);
@ -8110,7 +8290,7 @@ var Plyr = /*#__PURE__*/function () {
if (this.isHTML5 && this.config.autoplay) { if (this.isHTML5 && this.config.autoplay) {
setTimeout(function () { setTimeout(function () {
return _this.play(); return silencePromise(_this.play());
}, 10); }, 10);
} // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek
@ -8147,7 +8327,7 @@ var Plyr = /*#__PURE__*/function () {
this.ads.managerPromise.then(function () { this.ads.managerPromise.then(function () {
return _this2.ads.play(); return _this2.ads.play();
}).catch(function () { }).catch(function () {
return _this2.media.play(); return silencePromise(_this2.media.play());
}); });
} // Return the promise (for HTML5) } // Return the promise (for HTML5)
@ -8307,7 +8487,7 @@ var Plyr = /*#__PURE__*/function () {
var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu
if (hiding && this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) { if (hiding && is$1.array(this.config.controls) && this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) {
controls.toggleMenu.call(this, false); controls.toggleMenu.call(this, false);
} // Trigger event on change } // Trigger event on change
@ -8800,7 +8980,7 @@ var Plyr = /*#__PURE__*/function () {
var updateStorage = true; var updateStorage = true;
if (!options.includes(quality)) { if (!options.includes(quality)) {
var value = closest(options, quality); var value = closest$1(options, quality);
this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead")); this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead"));
quality = value; // Don't update storage if quality is not supported quality = value; // Don't update storage if quality is not supported
@ -8945,7 +9125,7 @@ var Plyr = /*#__PURE__*/function () {
return null; return null;
} }
return this.media.getAttribute('poster'); return this.media.getAttribute('poster') || this.media.getAttribute('data-poster');
} }
/** /**
* Get the current aspect ratio in use * Get the current aspect ratio in use

View File

@ -269,7 +269,7 @@ typeof navigator === "object" && (function (global, factory) {
(module.exports = function (key, value) { (module.exports = function (key, value) {
return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {}); return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
})('versions', []).push({ })('versions', []).push({
version: '3.6.4', version: '3.6.5',
mode: 'global', mode: 'global',
copyright: '© 2020 Denis Pushkarev (zloirock.ru)' copyright: '© 2020 Denis Pushkarev (zloirock.ru)'
}); });
@ -3061,7 +3061,7 @@ typeof navigator === "object" && (function (global, factory) {
var INVALID_PORT = 'Invalid port'; var INVALID_PORT = 'Invalid port';
var ALPHA = /[A-Za-z]/; var ALPHA = /[A-Za-z]/;
var ALPHANUMERIC = /[\d+\-.A-Za-z]/; var ALPHANUMERIC = /[\d+-.A-Za-z]/;
var DIGIT = /\d/; var DIGIT = /\d/;
var HEX_START = /^(0x|0X)/; var HEX_START = /^(0x|0X)/;
var OCT = /^[0-7]+$/; var OCT = /^[0-7]+$/;
@ -4123,20 +4123,52 @@ typeof navigator === "object" && (function (global, factory) {
return target; return target;
} }
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function _slicedToArray(arr, i) { function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
} }
function _toConsumableArray(arr) { function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
} }
function _arrayWithoutHoles(arr) { function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) { if (Array.isArray(arr)) return _arrayLikeToArray(arr);
for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
}
} }
function _arrayWithHoles(arr) { function _arrayWithHoles(arr) {
@ -4144,14 +4176,11 @@ typeof navigator === "object" && (function (global, factory) {
} }
function _iterableToArray(iter) { function _iterableToArray(iter) {
if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
} }
function _iterableToArrayLimit(arr, i) { function _iterableToArrayLimit(arr, i) {
if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
return;
}
var _arr = []; var _arr = [];
var _n = true; var _n = true;
var _d = false; var _d = false;
@ -4177,12 +4206,29 @@ typeof navigator === "object" && (function (global, factory) {
return _arr; return _arr;
} }
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread() { function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance"); throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
} }
function _nonIterableRest() { function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance"); throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
} }
(function (global) { (function (global) {
@ -4486,7 +4532,11 @@ typeof navigator === "object" && (function (global, factory) {
anchorElement.href = anchorElement.href; // force href to refresh anchorElement.href = anchorElement.href; // force href to refresh
} }
if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) { var inputElement = doc.createElement('input');
inputElement.type = 'url';
inputElement.value = url;
if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href) || !inputElement.checkValidity() && !base) {
throw new TypeError('Invalid URL'); throw new TypeError('Invalid URL');
} }
@ -5998,7 +6048,13 @@ typeof navigator === "object" && (function (global, factory) {
defer = functionBindContext(port.postMessage, port, 1); defer = functionBindContext(port.postMessage, port, 1);
// Browsers with postMessage, skip WebWorkers // Browsers with postMessage, skip WebWorkers
// IE8 has postMessage, but it's sync & typeof its postMessage is 'object' // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
} else if (global_1.addEventListener && typeof postMessage == 'function' && !global_1.importScripts && !fails(post)) { } else if (
global_1.addEventListener &&
typeof postMessage == 'function' &&
!global_1.importScripts &&
!fails(post) &&
location.protocol !== 'file:'
) {
defer = post; defer = post;
global_1.addEventListener('message', listener, false); global_1.addEventListener('message', listener, false);
// IE8- // IE8-
@ -6607,7 +6663,7 @@ typeof navigator === "object" && (function (global, factory) {
}; };
var isPromise = function isPromise(input) { var isPromise = function isPromise(input) {
return instanceOf$1(input, Promise); return instanceOf$1(input, Promise) && isFunction$1(input.then);
}; };
var isEmpty$1 = function isEmpty(input) { var isEmpty$1 = function isEmpty(input) {
@ -6999,12 +7055,33 @@ typeof navigator === "object" && (function (global, factory) {
} // Element matches selector } // Element matches selector
function matches$1(element, selector) { function matches$1(element, selector) {
var _Element = Element,
prototype = _Element.prototype;
function match() { function match() {
return Array.from(document.querySelectorAll(selector)).includes(this); return Array.from(document.querySelectorAll(selector)).includes(this);
} }
var method = match; var method = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match;
return method.call(element, selector);
} // Closest ancestor element matching selector (also tests element itself)
function closest(element, selector) {
var _Element2 = Element,
prototype = _Element2.prototype; // https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
function closestElement() {
var el = this;
do {
if (matches$1.matches(el, selector)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
}
var method = prototype.closest || closestElement;
return method.call(element, selector); return method.call(element, selector);
} // Find all elements } // Find all elements
@ -7247,7 +7324,7 @@ typeof navigator === "object" && (function (global, factory) {
var event = new CustomEvent(type, { var event = new CustomEvent(type, {
bubbles: bubbles, bubbles: bubbles,
detail: _objectSpread2({}, detail, { detail: _objectSpread2(_objectSpread2({}, detail), {}, {
plyr: this plyr: this
}) })
}); // Dispatch the event }); // Dispatch the event
@ -7276,6 +7353,19 @@ typeof navigator === "object" && (function (global, factory) {
}).then(function () {}); }).then(function () {});
} }
/**
* Silence a Promise-like object.
* This is useful for avoiding non-harmful, but potentially confusing "uncaught
* play promise" rejection error messages.
* @param {Object} value An object that may or may not be `Promise`-like.
*/
function silencePromise(value) {
if (is$1.promise(value)) {
value.then(null, function () {});
}
}
function validateRatio(input) { function validateRatio(input) {
if (!is$1.array(input) && (!is$1.string(input) || !input.includes(':'))) { if (!is$1.array(input) && (!is$1.string(input) || !input.includes(':'))) {
return false; return false;
@ -7344,8 +7434,8 @@ typeof navigator === "object" && (function (global, factory) {
var padding = 100 / w * h; var padding = 100 / w * h;
wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI
if (this.isVimeo && this.supported.ui) { if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
var height = 240; var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
var offset = (height - padding) / (height / 50); var offset = (height - padding) / (height / 50);
this.media.style.transform = "translateY(-".concat(offset, "%)"); this.media.style.transform = "translateY(-".concat(offset, "%)");
} else if (this.isHTML5) { } else if (this.isHTML5) {
@ -7451,7 +7541,7 @@ typeof navigator === "object" && (function (global, factory) {
player.currentTime = currentTime; // Resume playing player.currentTime = currentTime; // Resume playing
if (!paused) { if (!paused) {
player.play(); silencePromise(player.play());
} }
}); // Load new source }); // Load new source
@ -7498,7 +7588,7 @@ typeof navigator === "object" && (function (global, factory) {
}); });
} // Get the closest value in an array } // Get the closest value in an array
function closest(array, value) { function closest$1(array, value) {
if (!is$1.array(array) || !array.length) { if (!is$1.array(array) || !array.length) {
return null; return null;
} }
@ -7615,19 +7705,19 @@ typeof navigator === "object" && (function (global, factory) {
return (current / max * 100).toFixed(2); return (current / max * 100).toFixed(2);
} // Replace all occurances of a string in a string } // Replace all occurances of a string in a string
function replaceAll() { var replaceAll = function replaceAll() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString());
} // Convert to title case }; // Convert to title case
function toTitleCase() { var toTitleCase = function toTitleCase() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
return input.toString().replace(/\w\S*/g, function (text) { return input.toString().replace(/\w\S*/g, function (text) {
return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase();
}); });
} // Convert string to pascalCase }; // Convert string to pascalCase
function toPascalCase() { function toPascalCase() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
@ -7997,7 +8087,7 @@ typeof navigator === "object" && (function (global, factory) {
var icon = document.createElementNS(namespace, 'svg'); var icon = document.createElementNS(namespace, 'svg');
setAttributes(icon, extend(attributes, { setAttributes(icon, extend(attributes, {
role: 'presentation', 'aria-hidden': 'true',
focusable: 'false' focusable: 'false'
})); // Create the <use> to reference sprite })); // Create the <use> to reference sprite
@ -8021,7 +8111,7 @@ typeof navigator === "object" && (function (global, factory) {
var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var text = i18n.get(key, this.config); var text = i18n.get(key, this.config);
var attributes = _objectSpread2({}, attr, { var attributes = _objectSpread2(_objectSpread2({}, attr), {}, {
class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ') class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ')
}); });
@ -8780,7 +8870,7 @@ typeof navigator === "object" && (function (global, factory) {
var type = 'captions'; var type = 'captions';
var list = this.elements.settings.panels.captions.querySelector('[role="menu"]'); var list = this.elements.settings.panels.captions.querySelector('[role="menucaptions"]');
var tracks = captions.getTracks.call(this); var tracks = captions.getTracks.call(this);
var toggle = Boolean(tracks.length); // Toggle the pane and tab var toggle = Boolean(tracks.length); // Toggle the pane and tab
@ -9021,7 +9111,7 @@ typeof navigator === "object" && (function (global, factory) {
showMenuPanel = controls.showMenuPanel; showMenuPanel = controls.showMenuPanel;
this.elements.controls = null; // Larger overlaid play button this.elements.controls = null; // Larger overlaid play button
if (this.config.controls.includes('play-large')) { if (is$1.array(this.config.controls) && this.config.controls.includes('play-large')) {
this.elements.container.appendChild(createButton.call(this, 'play-large')); this.elements.container.appendChild(createButton.call(this, 'play-large'));
} // Create the container } // Create the container
@ -9033,7 +9123,7 @@ typeof navigator === "object" && (function (global, factory) {
class: 'plyr__controls__item' class: 'plyr__controls__item'
}; // Loop through controls in order }; // Loop through controls in order
dedupe(this.config.controls).forEach(function (control) { dedupe(is$1.array(this.config.controls) ? this.config.controls : []).forEach(function (control) {
// Restart button // Restart button
if (control === 'restart') { if (control === 'restart') {
container.appendChild(createButton.call(_this10, 'restart', defaultAttributes)); container.appendChild(createButton.call(_this10, 'restart', defaultAttributes));
@ -9222,6 +9312,10 @@ typeof navigator === "object" && (function (global, factory) {
pane.appendChild(createElement('div', { pane.appendChild(createElement('div', {
role: 'menu' role: 'menu'
})); // Menu Captions
pane.appendChild(createElement('div', {
role: 'menucaptions'
})); }));
inner.appendChild(pane); inner.appendChild(pane);
_this10.elements.settings.buttons[type] = menuItem; _this10.elements.settings.buttons[type] = menuItem;
@ -9352,8 +9446,6 @@ typeof navigator === "object" && (function (global, factory) {
if (update) { if (update) {
if (is$1.string(this.config.controls)) { if (is$1.string(this.config.controls)) {
container = replace(container); container = replace(container);
} else if (is$1.element(container)) {
container.innerHTML = replace(container.innerHTML);
} }
} // Controls container } // Controls container
@ -9568,9 +9660,15 @@ typeof navigator === "object" && (function (global, factory) {
meta.set(track, { meta.set(track, {
default: track.mode === 'showing' default: track.mode === 'showing'
}); // Turn off native caption rendering to avoid double captions }); // Turn off native caption rendering to avoid double captions
// Note: mode='hidden' forces a track to download. To ensure every track
// isn't downloaded at once, only 'showing' tracks should be reassigned
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
track.mode = 'hidden'; // Add event listener for cue changes if (track.mode === 'showing') {
// eslint-disable-next-line no-param-reassign
track.mode = 'hidden';
} // Add event listener for cue changes
on.call(_this, track, 'cuechange', function () { on.call(_this, track, 'cuechange', function () {
return captions.updateCues.call(_this); return captions.updateCues.call(_this);
@ -9587,13 +9685,15 @@ typeof navigator === "object" && (function (global, factory) {
toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is$1.empty(tracks)); // Update available languages in list toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is$1.empty(tracks)); // Update available languages in list
if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) { if (is$1.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {
controls.setCaptionsMenu.call(this); controls.setCaptionsMenu.call(this);
} }
}, },
// Toggle captions display // Toggle captions display
// Used internally for the toggleCaptions method, with the passive option forced to false // Used internally for the toggleCaptions method, with the passive option forced to false
toggle: function toggle(input) { toggle: function toggle(input) {
var _this2 = this;
var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
// If there's no full support // If there's no full support
@ -9640,7 +9740,15 @@ typeof navigator === "object" && (function (global, factory) {
controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally) controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally)
triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled'); triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');
} // Wait for the call stack to clear before setting mode='hidden'
// on the active track - forcing the browser to download it
setTimeout(function () {
if (active && _this2.captions.toggled) {
_this2.captions.currentTrackNode.mode = 'hidden';
} }
});
}, },
// Set captions by track index // Set captions by track index
// Used internally for the currentTrack setter with the passive option forced to false // Used internally for the currentTrack setter with the passive option forced to false
@ -9721,7 +9829,7 @@ typeof navigator === "object" && (function (global, factory) {
// If update is false it will also ignore tracks without metadata // If update is false it will also ignore tracks without metadata
// This is used to "freeze" the language options when captions.update is false // This is used to "freeze" the language options when captions.update is false
getTracks: function getTracks() { getTracks: function getTracks() {
var _this2 = this; var _this3 = this;
var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
// Handle media or textTracks missing or null // Handle media or textTracks missing or null
@ -9729,20 +9837,20 @@ typeof navigator === "object" && (function (global, factory) {
// Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata) // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)
return tracks.filter(function (track) { return tracks.filter(function (track) {
return !_this2.isHTML5 || update || _this2.captions.meta.has(track); return !_this3.isHTML5 || update || _this3.captions.meta.has(track);
}).filter(function (track) { }).filter(function (track) {
return ['captions', 'subtitles'].includes(track.kind); return ['captions', 'subtitles'].includes(track.kind);
}); });
}, },
// Match tracks based on languages and get the first // Match tracks based on languages and get the first
findTrack: function findTrack(languages) { findTrack: function findTrack(languages) {
var _this3 = this; var _this4 = this;
var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var tracks = captions.getTracks.call(this); var tracks = captions.getTracks.call(this);
var sortIsDefault = function sortIsDefault(track) { var sortIsDefault = function sortIsDefault(track) {
return Number((_this3.captions.meta.get(track) || {}).default); return Number((_this4.captions.meta.get(track) || {}).default);
}; };
var sorted = Array.from(tracks).sort(function (a, b) { var sorted = Array.from(tracks).sort(function (a, b) {
@ -9923,6 +10031,9 @@ typeof navigator === "object" && (function (global, factory) {
fallback: true, fallback: true,
// Fallback using full viewport/window // Fallback using full viewport/window
iosNative: false // Use the native fullscreen in iOS (disables custom controls) iosNative: false // Use the native fullscreen in iOS (disables custom controls)
// Selector for the fullscreen container so contextual / non-player content can remain visible in fullscreen mode
// Non-ancestors of the player element will be ignored
// container: null, // defaults to the player element
}, },
// Local storage // Local storage
@ -10160,16 +10271,16 @@ typeof navigator === "object" && (function (global, factory) {
title: false, title: false,
speed: true, speed: true,
transparent: false, transparent: false,
// These settings require a pro or premium account to work // Whether the owner of the video has a Pro or Business account
sidedock: false, // (which allows us to properly hide controls without CSS hacks, etc)
controls: false, premium: false,
// Custom settings from Plyr // Custom settings from Plyr
referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
}, },
// YouTube plugin // YouTube plugin
youtube: { youtube: {
noCookie: false, noCookie: true,
// Whether to use an alternative version of YouTube without cookies // Whether to use an alternative version of YouTube without cookies
rel: 0, rel: 0,
// No related vids // No related vids
@ -10279,7 +10390,10 @@ typeof navigator === "object" && (function (global, factory) {
y: 0 y: 0
}; // Force the use of 'full window/browser' rather than fullscreen }; // Force the use of 'full window/browser' rather than fullscreen
this.forceFallback = player.config.fullscreen.fallback === 'force'; // Register event listeners this.forceFallback = player.config.fullscreen.fallback === 'force'; // Get the fullscreen element
// Checks container is an ancestor, defaults to null
this.player.elements.fullscreen = player.config.fullscreen.container && closest(this.player.elements.container, player.config.fullscreen.container); // Register event listeners
// Handle event (incase user presses escape etc) // Handle event (incase user presses escape etc)
on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () { on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () {
@ -10452,7 +10566,7 @@ typeof navigator === "object" && (function (global, factory) {
if (browser.isIos && this.player.config.fullscreen.iosNative) { if (browser.isIos && this.player.config.fullscreen.iosNative) {
this.target.webkitExitFullscreen(); this.target.webkitExitFullscreen();
this.player.play(); silencePromise(this.player.play());
} else if (!Fullscreen.native || this.forceFallback) { } else if (!Fullscreen.native || this.forceFallback) {
this.toggleFallback(false); this.toggleFallback(false);
} else if (!this.prefix) { } else if (!this.prefix) {
@ -10499,13 +10613,13 @@ typeof navigator === "object" && (function (global, factory) {
} }
var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")]; var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")];
return element === this.target; return element && element.shadowRoot ? element === this.target.getRootNode().host : element === this.target;
} // Get target element } // Get target element
}, { }, {
key: "target", key: "target",
get: function get() { get: function get() {
return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.fullscreen || this.player.elements.container;
} }
}], [{ }], [{
key: "native", key: "native",
@ -10714,12 +10828,7 @@ typeof navigator === "object" && (function (global, factory) {
} // Set property synchronously to respect the call order } // Set property synchronously to respect the call order
this.media.setAttribute('poster', poster); // HTML5 uses native poster attribute this.media.setAttribute('data-poster', poster); // Wait until ui is ready
if (this.isHTML5) {
return Promise.resolve(poster);
} // Wait until ui is ready
return ready.call(this) // Load image return ready.call(this) // Load image
.then(function () { .then(function () {
@ -10795,6 +10904,26 @@ typeof navigator === "object" && (function (global, factory) {
this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek)); this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek));
} }
},
// Migrate any custom properties from the media to the parent
migrateStyles: function migrateStyles() {
var _this5 = this;
// Loop through values (as they are the keys when the object is spread 🤔)
Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties
.filter(function (key) {
return !is$1.empty(key) && key.startsWith('--plyr');
}).forEach(function (key) {
// Set on the container
_this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element
_this5.media.style.removeProperty(key);
}); // Remove attribute if empty
if (is$1.empty(this.media.style)) {
this.media.removeAttribute('style');
}
} }
}; };
@ -10889,7 +11018,7 @@ typeof navigator === "object" && (function (global, factory) {
case 75: case 75:
// Space and K key // Space and K key
if (!repeat) { if (!repeat) {
player.togglePlay(); silencePromise(player.togglePlay());
} }
break; break;
@ -11003,6 +11132,7 @@ typeof navigator === "object" && (function (global, factory) {
removeCurrent(); // Delay the adding of classname until the focus has changed removeCurrent(); // Delay the adding of classname until the focus has changed
// This event fires before the focusin event // This event fires before the focusin event
if (event.type !== 'focusout') {
this.focusTimer = setTimeout(function () { this.focusTimer = setTimeout(function () {
var focused = document.activeElement; // Ignore if current focus element isn't inside the player var focused = document.activeElement; // Ignore if current focus element isn't inside the player
@ -11012,6 +11142,7 @@ typeof navigator === "object" && (function (global, factory) {
toggleClass(document.activeElement, player.config.classNames.tabFocus, true); toggleClass(document.activeElement, player.config.classNames.tabFocus, true);
}, 10); }, 10);
}
} // Global window & document listeners } // Global window & document listeners
}, { }, {
@ -11029,7 +11160,7 @@ typeof navigator === "object" && (function (global, factory) {
once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection
toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true); toggleListener.call(player, document.body, 'keydown focus blur focusout', this.setTabFocus, toggle, false, true);
} // Container listeners } // Container listeners
}, { }, {
@ -11072,7 +11203,7 @@ typeof navigator === "object" && (function (global, factory) {
}); // Set a gutter for Vimeo }); // Set a gutter for Vimeo
var setGutter = function setGutter(ratio, padding, toggle) { var setGutter = function setGutter(ratio, padding, toggle) {
if (!player.isVimeo) { if (!player.isVimeo || player.config.vimeo.premium) {
return; return;
} }
@ -11129,7 +11260,7 @@ typeof navigator === "object" && (function (global, factory) {
ratio = _setPlayerSize.ratio; // Set Vimeo gutter ratio = _setPlayerSize.ratio; // Set Vimeo gutter
setGutter(ratio, padding, isEnter); // If not using native fullscreen, we need to check for resizes of viewport setGutter(ratio, padding, isEnter); // If not using native browser fullscreen API, we need to check for resizes of viewport
if (!usingNative) { if (!usingNative) {
if (isEnter) { if (isEnter) {
@ -11207,9 +11338,13 @@ typeof navigator === "object" && (function (global, factory) {
if (player.ended) { if (player.ended) {
_this.proxy(event, player.restart, 'restart'); _this.proxy(event, player.restart, 'restart');
_this.proxy(event, player.play, 'play'); _this.proxy(event, function () {
silencePromise(player.play());
}, 'play');
} else { } else {
_this.proxy(event, player.togglePlay, 'play'); _this.proxy(event, function () {
silencePromise(player.togglePlay());
}, 'play');
} }
}); });
} // Disable right click } // Disable right click
@ -11307,7 +11442,9 @@ typeof navigator === "object" && (function (global, factory) {
if (elements.buttons.play) { if (elements.buttons.play) {
Array.from(elements.buttons.play).forEach(function (button) { Array.from(elements.buttons.play).forEach(function (button) {
_this3.bind(button, 'click', player.togglePlay, 'play'); _this3.bind(button, 'click', function () {
silencePromise(player.togglePlay());
}, 'play');
}); });
} // Pause } // Pause
@ -11404,7 +11541,7 @@ typeof navigator === "object" && (function (global, factory) {
if (play && done) { if (play && done) {
seek.removeAttribute(attribute); seek.removeAttribute(attribute);
player.play(); silencePromise(player.play());
} else if (!done && player.playing) { } else if (!done && player.playing) {
seek.setAttribute(attribute, ''); seek.setAttribute(attribute, '');
player.pause(); player.pause();
@ -11502,7 +11639,18 @@ typeof navigator === "object" && (function (global, factory) {
this.bind(elements.controls, 'mouseenter mouseleave', function (event) { this.bind(elements.controls, 'mouseenter mouseleave', function (event) {
elements.controls.hover = !player.touch && event.type === 'mouseenter'; elements.controls.hover = !player.touch && event.type === 'mouseenter';
}); // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting) }); // Also update controls.hover state for any non-player children of fullscreen element (as above)
if (elements.fullscreen) {
Array.from(elements.fullscreen.children).filter(function (c) {
return !c.contains(elements.container);
}).forEach(function (child) {
_this3.bind(child, 'mouseenter mouseleave', function (event) {
elements.controls.hover = !player.touch && event.type === 'mouseenter';
});
});
} // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)
this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) {
elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);
@ -11971,15 +12119,28 @@ typeof navigator === "object" && (function (global, factory) {
var _this = this; var _this = this;
var player = this; var player = this;
var config = player.config.vimeo; // Get Vimeo params for the iframe var config = player.config.vimeo;
var params = buildUrlParams(extend({}, { var premium = config.premium,
referrerPolicy = config.referrerPolicy,
frameParams = _objectWithoutProperties(config, ["premium", "referrerPolicy"]); // If the owner has a pro or premium account then we can hide controls etc
if (premium) {
Object.assign(frameParams, {
controls: false,
sidedock: false
});
} // Get Vimeo params for the iframe
var params = buildUrlParams(_objectSpread2({
loop: player.config.loop.active, loop: player.config.loop.active,
autoplay: player.autoplay, autoplay: player.autoplay,
muted: player.muted, muted: player.muted,
gesture: 'media', gesture: 'media',
playsinline: !this.config.fullscreen.iosNative playsinline: !this.config.fullscreen.iosNative
}, config)); // Get the source URL or ID }, frameParams)); // Get the source URL or ID
var source = player.media.getAttribute('src'); // Get from <div> if needed var source = player.media.getAttribute('src'); // Get from <div> if needed
@ -11993,22 +12154,27 @@ typeof navigator === "object" && (function (global, factory) {
var src = format(player.config.urls.vimeo.iframe, id, params); var src = format(player.config.urls.vimeo.iframe, id, params);
iframe.setAttribute('src', src); iframe.setAttribute('src', src);
iframe.setAttribute('allowfullscreen', ''); iframe.setAttribute('allowfullscreen', '');
iframe.setAttribute('allowtransparency', ''); iframe.setAttribute('allow', 'autoplay,fullscreen,picture-in-picture'); // Set the referrer policy if required
iframe.setAttribute('allow', 'autoplay'); // Set the referrer policy if required
if (!is$1.empty(config.referrerPolicy)) { if (!is$1.empty(referrerPolicy)) {
iframe.setAttribute('referrerPolicy', config.referrerPolicy); iframe.setAttribute('referrerPolicy', referrerPolicy);
} // Get poster, if already set } // Inject the package
var poster = player.poster; // Inject the package var poster = player.poster;
if (premium) {
iframe.setAttribute('data-poster', poster);
player.media = replaceElement(iframe, player.media);
} else {
var wrapper = createElement('div', { var wrapper = createElement('div', {
poster: poster, class: player.config.classNames.embedContainer,
class: player.config.classNames.embedContainer 'data-poster': poster
}); });
wrapper.appendChild(iframe); wrapper.appendChild(iframe);
player.media = replaceElement(wrapper, player.media); // Get poster image player.media = replaceElement(wrapper, player.media);
} // Get poster image
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
if (is$1.empty(response)) { if (is$1.empty(response)) {
@ -12092,6 +12258,9 @@ typeof navigator === "object" && (function (global, factory) {
player.embed.setPlaybackRate(input).then(function () { player.embed.setPlaybackRate(input).then(function () {
speed = input; speed = input;
triggerEvent.call(player, player.media, 'ratechange'); triggerEvent.call(player, player.media, 'ratechange');
}).catch(function () {
// Cannot set Playback Rate, Video is probably not on Pro account
player.options.speed = [1];
}); });
} }
}); // Volume }); // Volume
@ -12376,7 +12545,7 @@ typeof navigator === "object" && (function (global, factory) {
var container = createElement('div', { var container = createElement('div', {
id: id, id: id,
poster: poster 'data-poster': poster
}); });
player.media = replaceElement(container, player.media); // Id to poster wrapper player.media = replaceElement(container, player.media); // Id to poster wrapper
@ -12694,15 +12863,13 @@ typeof navigator === "object" && (function (global, factory) {
class: this.config.classNames.video class: this.config.classNames.video
}); // Wrap the video in a container }); // Wrap the video in a container
wrap$1(this.media, this.elements.wrapper); // Faux poster container wrap$1(this.media, this.elements.wrapper); // Poster image container
if (this.isEmbed) {
this.elements.poster = createElement('div', { this.elements.poster = createElement('div', {
class: this.config.classNames.poster class: this.config.classNames.poster
}); });
this.elements.wrapper.appendChild(this.elements.poster); this.elements.wrapper.appendChild(this.elements.poster);
} }
}
if (this.isHTML5) { if (this.isHTML5) {
html5.setup.call(this); html5.setup.call(this);
@ -12828,6 +12995,8 @@ typeof navigator === "object" && (function (global, factory) {
* mobile devices, this initialization is done as the result of a user action. * mobile devices, this initialization is done as the result of a user action.
*/ */
value: function setupIMA() { value: function setupIMA() {
var _this4 = this;
// Create the container for our advertisements // Create the container for our advertisements
this.elements.container = createElement('div', { this.elements.container = createElement('div', {
class: this.player.config.classNames.ads class: this.player.config.classNames.ads
@ -12840,7 +13009,16 @@ typeof navigator === "object" && (function (global, factory) {
google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline); // We assume the adContainer is the video container of the plyr element that will house the ads google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline); // We assume the adContainer is the video container of the plyr element that will house the ads
this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media); // Request video ads to be pre-loaded this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media); // Create ads loader
this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events
this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) {
return _this4.onAdsManagerLoaded(event);
}, false);
this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) {
return _this4.onAdError(error);
}, false); // Request video ads to be pre-loaded
this.requestAds(); this.requestAds();
} }
@ -12851,21 +13029,10 @@ typeof navigator === "object" && (function (global, factory) {
}, { }, {
key: "requestAds", key: "requestAds",
value: function requestAds() { value: function requestAds() {
var _this4 = this;
var container = this.player.elements.container; var container = this.player.elements.container;
try { try {
// Create ads loader // Request video ads
this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events
this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) {
return _this4.onAdsManagerLoaded(event);
}, false);
this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) {
return _this4.onAdError(error);
}, false); // Request video ads
var request = new google.ima.AdsRequest(); var request = new google.ima.AdsRequest();
request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK
// to select the correct creative if multiple are returned // to select the correct creative if multiple are returned
@ -13044,7 +13211,13 @@ typeof navigator === "object" && (function (global, factory) {
// }; // };
// TODO: So there is still this thing where a video should only be allowed to start // 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 // playing when the IMA SDK is ready or has failed
if (this.player.ended) {
this.loadAds(); this.loadAds();
} else {
// The SDK won't allow new ads to be called without receiving a contentComplete()
this.loader.contentComplete();
}
break; break;
case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED: case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:
@ -13180,7 +13353,7 @@ typeof navigator === "object" && (function (global, factory) {
this.playing = false; // Play video this.playing = false; // Play video
this.player.media.play(); silencePromise(this.player.media.play());
} }
/** /**
* Pause our video * Pause our video
@ -13237,7 +13410,9 @@ typeof navigator === "object" && (function (global, factory) {
_this11.on('loaded', resolve); _this11.on('loaded', resolve);
_this11.player.debug.log(_this11.manager); _this11.player.debug.log(_this11.manager);
}); // Now request some new advertisements }); // Now that the manager has been destroyed set it to also be un-initialized
_this11.initialized = false; // Now request some new advertisements
_this11.requestAds(); _this11.requestAds();
}).catch(function () {}); }).catch(function () {});
@ -13532,15 +13707,10 @@ typeof navigator === "object" && (function (global, factory) {
if (is$1.empty(src)) { if (is$1.empty(src)) {
throw new Error('Missing previewThumbnails.src config attribute'); throw new Error('Missing previewThumbnails.src config attribute');
} // If string, convert into single-element list } // Resolve promise
var urls = is$1.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails var sortAndResolve = function sortAndResolve() {
var promises = urls.map(function (u) {
return _this2.getThumbnail(u);
});
Promise.all(promises).then(function () {
// Sort smallest to biggest (e.g., [120p, 480p, 1080p]) // Sort smallest to biggest (e.g., [120p, 480p, 1080p])
_this2.thumbnails.sort(function (x, y) { _this2.thumbnails.sort(function (x, y) {
return x.height - y.height; return x.height - y.height;
@ -13549,7 +13719,25 @@ typeof navigator === "object" && (function (global, factory) {
_this2.player.debug.log('Preview thumbnails', _this2.thumbnails); _this2.player.debug.log('Preview thumbnails', _this2.thumbnails);
resolve(); resolve();
}; // Via callback()
if (is$1.function(src)) {
src(function (thumbnails) {
_this2.thumbnails = thumbnails;
sortAndResolve();
}); });
} // VTT urls
else {
// If string, convert into single-element list
var urls = is$1.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails
var promises = urls.map(function (u) {
return _this2.getThumbnail(u);
}); // Resolve
Promise.all(promises).then(sortAndResolve);
}
}); });
} // Process individual VTT file } // Process individual VTT file
@ -14337,6 +14525,7 @@ typeof navigator === "object" && (function (global, factory) {
this.elements = { this.elements = {
container: null, container: null,
fullscreen: null,
captions: null, captions: null,
buttons: {}, buttons: {},
display: {}, display: {},
@ -14511,9 +14700,11 @@ typeof navigator === "object" && (function (global, factory) {
tabindex: 0 tabindex: 0
}); });
wrap$1(this.media, this.elements.container); wrap$1(this.media, this.elements.container);
} // Add style hook } // Migrate custom properties from media to container (so they work 😉)
ui.migrateStyles.call(this); // Add style hook
ui.addStyleHook.call(this); // Setup media ui.addStyleHook.call(this); // Setup media
media.setup.call(this); // Listen for events if debugging media.setup.call(this); // Listen for events if debugging
@ -14522,10 +14713,12 @@ typeof navigator === "object" && (function (global, factory) {
on.call(this, this.elements.container, this.config.events.join(' '), function (event) { on.call(this, this.elements.container, this.config.events.join(' '), function (event) {
_this.debug.log("event: ".concat(event.type)); _this.debug.log("event: ".concat(event.type));
}); });
} // Setup interface } // Setup fullscreen
// If embed but not fully supported, build interface now to avoid flash of controls
this.fullscreen = new Fullscreen(this); // Setup interface
// If embed but not fully supported, build interface now to avoid flash of controls
if (this.isHTML5 || this.isEmbed && !this.supported.ui) { if (this.isHTML5 || this.isEmbed && !this.supported.ui) {
ui.build.call(this); ui.build.call(this);
} // Container listeners } // Container listeners
@ -14533,9 +14726,7 @@ typeof navigator === "object" && (function (global, factory) {
this.listeners.container(); // Global listeners this.listeners.container(); // Global listeners
this.listeners.global(); // Setup fullscreen this.listeners.global(); // Setup ads if provided
this.fullscreen = new Fullscreen(this); // Setup ads if provided
if (this.config.ads.enabled) { if (this.config.ads.enabled) {
this.ads = new Ads(this); this.ads = new Ads(this);
@ -14544,7 +14735,7 @@ typeof navigator === "object" && (function (global, factory) {
if (this.isHTML5 && this.config.autoplay) { if (this.isHTML5 && this.config.autoplay) {
setTimeout(function () { setTimeout(function () {
return _this.play(); return silencePromise(_this.play());
}, 10); }, 10);
} // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek
@ -14581,7 +14772,7 @@ typeof navigator === "object" && (function (global, factory) {
this.ads.managerPromise.then(function () { this.ads.managerPromise.then(function () {
return _this2.ads.play(); return _this2.ads.play();
}).catch(function () { }).catch(function () {
return _this2.media.play(); return silencePromise(_this2.media.play());
}); });
} // Return the promise (for HTML5) } // Return the promise (for HTML5)
@ -14741,7 +14932,7 @@ typeof navigator === "object" && (function (global, factory) {
var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu
if (hiding && this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) { if (hiding && is$1.array(this.config.controls) && this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) {
controls.toggleMenu.call(this, false); controls.toggleMenu.call(this, false);
} // Trigger event on change } // Trigger event on change
@ -15234,7 +15425,7 @@ typeof navigator === "object" && (function (global, factory) {
var updateStorage = true; var updateStorage = true;
if (!options.includes(quality)) { if (!options.includes(quality)) {
var value = closest(options, quality); var value = closest$1(options, quality);
this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead")); this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead"));
quality = value; // Don't update storage if quality is not supported quality = value; // Don't update storage if quality is not supported
@ -15379,7 +15570,7 @@ typeof navigator === "object" && (function (global, factory) {
return null; return null;
} }
return this.media.getAttribute('poster'); return this.media.getAttribute('poster') || this.media.getAttribute('data-poster');
} }
/** /**
* Get the current aspect ratio in use * Get the current aspect ratio in use

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -263,7 +263,7 @@ var shared = createCommonjsModule(function (module) {
(module.exports = function (key, value) { (module.exports = function (key, value) {
return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {}); return sharedStore[key] || (sharedStore[key] = value !== undefined ? value : {});
})('versions', []).push({ })('versions', []).push({
version: '3.6.4', version: '3.6.5',
mode: 'global', mode: 'global',
copyright: '© 2020 Denis Pushkarev (zloirock.ru)' copyright: '© 2020 Denis Pushkarev (zloirock.ru)'
}); });
@ -3055,7 +3055,7 @@ var INVALID_HOST = 'Invalid host';
var INVALID_PORT = 'Invalid port'; var INVALID_PORT = 'Invalid port';
var ALPHA = /[A-Za-z]/; var ALPHA = /[A-Za-z]/;
var ALPHANUMERIC = /[\d+\-.A-Za-z]/; var ALPHANUMERIC = /[\d+-.A-Za-z]/;
var DIGIT = /\d/; var DIGIT = /\d/;
var HEX_START = /^(0x|0X)/; var HEX_START = /^(0x|0X)/;
var OCT = /^[0-7]+$/; var OCT = /^[0-7]+$/;
@ -4117,20 +4117,52 @@ function _objectSpread2(target) {
return target; return target;
} }
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function _slicedToArray(arr, i) { function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
} }
function _toConsumableArray(arr) { function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
} }
function _arrayWithoutHoles(arr) { function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) { if (Array.isArray(arr)) return _arrayLikeToArray(arr);
for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
}
} }
function _arrayWithHoles(arr) { function _arrayWithHoles(arr) {
@ -4138,14 +4170,11 @@ function _arrayWithHoles(arr) {
} }
function _iterableToArray(iter) { function _iterableToArray(iter) {
if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
} }
function _iterableToArrayLimit(arr, i) { function _iterableToArrayLimit(arr, i) {
if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
return;
}
var _arr = []; var _arr = [];
var _n = true; var _n = true;
var _d = false; var _d = false;
@ -4171,12 +4200,29 @@ function _iterableToArrayLimit(arr, i) {
return _arr; return _arr;
} }
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread() { function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance"); throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
} }
function _nonIterableRest() { function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance"); throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
} }
(function (global) { (function (global) {
@ -4480,7 +4526,11 @@ function _nonIterableRest() {
anchorElement.href = anchorElement.href; // force href to refresh anchorElement.href = anchorElement.href; // force href to refresh
} }
if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href)) { var inputElement = doc.createElement('input');
inputElement.type = 'url';
inputElement.value = url;
if (anchorElement.protocol === ':' || !/:/.test(anchorElement.href) || !inputElement.checkValidity() && !base) {
throw new TypeError('Invalid URL'); throw new TypeError('Invalid URL');
} }
@ -5992,7 +6042,13 @@ if (!set$1 || !clear) {
defer = functionBindContext(port.postMessage, port, 1); defer = functionBindContext(port.postMessage, port, 1);
// Browsers with postMessage, skip WebWorkers // Browsers with postMessage, skip WebWorkers
// IE8 has postMessage, but it's sync & typeof its postMessage is 'object' // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
} else if (global_1.addEventListener && typeof postMessage == 'function' && !global_1.importScripts && !fails(post)) { } else if (
global_1.addEventListener &&
typeof postMessage == 'function' &&
!global_1.importScripts &&
!fails(post) &&
location.protocol !== 'file:'
) {
defer = post; defer = post;
global_1.addEventListener('message', listener, false); global_1.addEventListener('message', listener, false);
// IE8- // IE8-
@ -6601,7 +6657,7 @@ var isTrack = function isTrack(input) {
}; };
var isPromise = function isPromise(input) { var isPromise = function isPromise(input) {
return instanceOf$1(input, Promise); return instanceOf$1(input, Promise) && isFunction$1(input.then);
}; };
var isEmpty$1 = function isEmpty(input) { var isEmpty$1 = function isEmpty(input) {
@ -6993,12 +7049,33 @@ function hasClass(element, className) {
} // Element matches selector } // Element matches selector
function matches$1(element, selector) { function matches$1(element, selector) {
var _Element = Element,
prototype = _Element.prototype;
function match() { function match() {
return Array.from(document.querySelectorAll(selector)).includes(this); return Array.from(document.querySelectorAll(selector)).includes(this);
} }
var method = match; var method = prototype.matches || prototype.webkitMatchesSelector || prototype.mozMatchesSelector || prototype.msMatchesSelector || match;
return method.call(element, selector);
} // Closest ancestor element matching selector (also tests element itself)
function closest(element, selector) {
var _Element2 = Element,
prototype = _Element2.prototype; // https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Polyfill
function closestElement() {
var el = this;
do {
if (matches$1.matches(el, selector)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
}
var method = prototype.closest || closestElement;
return method.call(element, selector); return method.call(element, selector);
} // Find all elements } // Find all elements
@ -7241,7 +7318,7 @@ function triggerEvent(element) {
var event = new CustomEvent(type, { var event = new CustomEvent(type, {
bubbles: bubbles, bubbles: bubbles,
detail: _objectSpread2({}, detail, { detail: _objectSpread2(_objectSpread2({}, detail), {}, {
plyr: this plyr: this
}) })
}); // Dispatch the event }); // Dispatch the event
@ -7270,6 +7347,19 @@ function ready() {
}).then(function () {}); }).then(function () {});
} }
/**
* Silence a Promise-like object.
* This is useful for avoiding non-harmful, but potentially confusing "uncaught
* play promise" rejection error messages.
* @param {Object} value An object that may or may not be `Promise`-like.
*/
function silencePromise(value) {
if (is$1.promise(value)) {
value.then(null, function () {});
}
}
function validateRatio(input) { function validateRatio(input) {
if (!is$1.array(input) && (!is$1.string(input) || !input.includes(':'))) { if (!is$1.array(input) && (!is$1.string(input) || !input.includes(':'))) {
return false; return false;
@ -7338,8 +7428,8 @@ function setAspectRatio(input) {
var padding = 100 / w * h; var padding = 100 / w * h;
wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI wrapper.style.paddingBottom = "".concat(padding, "%"); // For Vimeo we have an extra <div> to hide the standard controls and UI
if (this.isVimeo && this.supported.ui) { if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
var height = 240; var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
var offset = (height - padding) / (height / 50); var offset = (height - padding) / (height / 50);
this.media.style.transform = "translateY(-".concat(offset, "%)"); this.media.style.transform = "translateY(-".concat(offset, "%)");
} else if (this.isHTML5) { } else if (this.isHTML5) {
@ -7445,7 +7535,7 @@ var html5 = {
player.currentTime = currentTime; // Resume playing player.currentTime = currentTime; // Resume playing
if (!paused) { if (!paused) {
player.play(); silencePromise(player.play());
} }
}); // Load new source }); // Load new source
@ -7492,7 +7582,7 @@ function dedupe(array) {
}); });
} // Get the closest value in an array } // Get the closest value in an array
function closest(array, value) { function closest$1(array, value) {
if (!is$1.array(array) || !array.length) { if (!is$1.array(array) || !array.length) {
return null; return null;
} }
@ -7609,19 +7699,19 @@ function getPercentage(current, max) {
return (current / max * 100).toFixed(2); return (current / max * 100).toFixed(2);
} // Replace all occurances of a string in a string } // Replace all occurances of a string in a string
function replaceAll() { var replaceAll = function replaceAll() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ''; var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString()); return input.replace(new RegExp(find.toString().replace(/([.*+?^=!:${}()|[\]/\\])/g, '\\$1'), 'g'), replace.toString());
} // Convert to title case }; // Convert to title case
function toTitleCase() { var toTitleCase = function toTitleCase() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
return input.toString().replace(/\w\S*/g, function (text) { return input.toString().replace(/\w\S*/g, function (text) {
return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase(); return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase();
}); });
} // Convert string to pascalCase }; // Convert string to pascalCase
function toPascalCase() { function toPascalCase() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
@ -7991,7 +8081,7 @@ var controls = {
var icon = document.createElementNS(namespace, 'svg'); var icon = document.createElementNS(namespace, 'svg');
setAttributes(icon, extend(attributes, { setAttributes(icon, extend(attributes, {
role: 'presentation', 'aria-hidden': 'true',
focusable: 'false' focusable: 'false'
})); // Create the <use> to reference sprite })); // Create the <use> to reference sprite
@ -8015,7 +8105,7 @@ var controls = {
var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var text = i18n.get(key, this.config); var text = i18n.get(key, this.config);
var attributes = _objectSpread2({}, attr, { var attributes = _objectSpread2(_objectSpread2({}, attr), {}, {
class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ') class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ')
}); });
@ -8774,7 +8864,7 @@ var controls = {
var type = 'captions'; var type = 'captions';
var list = this.elements.settings.panels.captions.querySelector('[role="menu"]'); var list = this.elements.settings.panels.captions.querySelector('[role="menucaptions"]');
var tracks = captions.getTracks.call(this); var tracks = captions.getTracks.call(this);
var toggle = Boolean(tracks.length); // Toggle the pane and tab var toggle = Boolean(tracks.length); // Toggle the pane and tab
@ -9015,7 +9105,7 @@ var controls = {
showMenuPanel = controls.showMenuPanel; showMenuPanel = controls.showMenuPanel;
this.elements.controls = null; // Larger overlaid play button this.elements.controls = null; // Larger overlaid play button
if (this.config.controls.includes('play-large')) { if (is$1.array(this.config.controls) && this.config.controls.includes('play-large')) {
this.elements.container.appendChild(createButton.call(this, 'play-large')); this.elements.container.appendChild(createButton.call(this, 'play-large'));
} // Create the container } // Create the container
@ -9027,7 +9117,7 @@ var controls = {
class: 'plyr__controls__item' class: 'plyr__controls__item'
}; // Loop through controls in order }; // Loop through controls in order
dedupe(this.config.controls).forEach(function (control) { dedupe(is$1.array(this.config.controls) ? this.config.controls : []).forEach(function (control) {
// Restart button // Restart button
if (control === 'restart') { if (control === 'restart') {
container.appendChild(createButton.call(_this10, 'restart', defaultAttributes)); container.appendChild(createButton.call(_this10, 'restart', defaultAttributes));
@ -9216,6 +9306,10 @@ var controls = {
pane.appendChild(createElement('div', { pane.appendChild(createElement('div', {
role: 'menu' role: 'menu'
})); // Menu Captions
pane.appendChild(createElement('div', {
role: 'menucaptions'
})); }));
inner.appendChild(pane); inner.appendChild(pane);
_this10.elements.settings.buttons[type] = menuItem; _this10.elements.settings.buttons[type] = menuItem;
@ -9346,8 +9440,6 @@ var controls = {
if (update) { if (update) {
if (is$1.string(this.config.controls)) { if (is$1.string(this.config.controls)) {
container = replace(container); container = replace(container);
} else if (is$1.element(container)) {
container.innerHTML = replace(container.innerHTML);
} }
} // Controls container } // Controls container
@ -9562,9 +9654,15 @@ var captions = {
meta.set(track, { meta.set(track, {
default: track.mode === 'showing' default: track.mode === 'showing'
}); // Turn off native caption rendering to avoid double captions }); // Turn off native caption rendering to avoid double captions
// Note: mode='hidden' forces a track to download. To ensure every track
// isn't downloaded at once, only 'showing' tracks should be reassigned
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
track.mode = 'hidden'; // Add event listener for cue changes if (track.mode === 'showing') {
// eslint-disable-next-line no-param-reassign
track.mode = 'hidden';
} // Add event listener for cue changes
on.call(_this, track, 'cuechange', function () { on.call(_this, track, 'cuechange', function () {
return captions.updateCues.call(_this); return captions.updateCues.call(_this);
@ -9581,13 +9679,15 @@ var captions = {
toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is$1.empty(tracks)); // Update available languages in list toggleClass(this.elements.container, this.config.classNames.captions.enabled, !is$1.empty(tracks)); // Update available languages in list
if ((this.config.controls || []).includes('settings') && this.config.settings.includes('captions')) { if (is$1.array(this.config.controls) && this.config.controls.includes('settings') && this.config.settings.includes('captions')) {
controls.setCaptionsMenu.call(this); controls.setCaptionsMenu.call(this);
} }
}, },
// Toggle captions display // Toggle captions display
// Used internally for the toggleCaptions method, with the passive option forced to false // Used internally for the toggleCaptions method, with the passive option forced to false
toggle: function toggle(input) { toggle: function toggle(input) {
var _this2 = this;
var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
// If there's no full support // If there's no full support
@ -9634,7 +9734,15 @@ var captions = {
controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally) controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally)
triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled'); triggerEvent.call(this, this.media, active ? 'captionsenabled' : 'captionsdisabled');
} // Wait for the call stack to clear before setting mode='hidden'
// on the active track - forcing the browser to download it
setTimeout(function () {
if (active && _this2.captions.toggled) {
_this2.captions.currentTrackNode.mode = 'hidden';
} }
});
}, },
// Set captions by track index // Set captions by track index
// Used internally for the currentTrack setter with the passive option forced to false // Used internally for the currentTrack setter with the passive option forced to false
@ -9715,7 +9823,7 @@ var captions = {
// If update is false it will also ignore tracks without metadata // If update is false it will also ignore tracks without metadata
// This is used to "freeze" the language options when captions.update is false // This is used to "freeze" the language options when captions.update is false
getTracks: function getTracks() { getTracks: function getTracks() {
var _this2 = this; var _this3 = this;
var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
// Handle media or textTracks missing or null // Handle media or textTracks missing or null
@ -9723,20 +9831,20 @@ var captions = {
// Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata) // Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)
return tracks.filter(function (track) { return tracks.filter(function (track) {
return !_this2.isHTML5 || update || _this2.captions.meta.has(track); return !_this3.isHTML5 || update || _this3.captions.meta.has(track);
}).filter(function (track) { }).filter(function (track) {
return ['captions', 'subtitles'].includes(track.kind); return ['captions', 'subtitles'].includes(track.kind);
}); });
}, },
// Match tracks based on languages and get the first // Match tracks based on languages and get the first
findTrack: function findTrack(languages) { findTrack: function findTrack(languages) {
var _this3 = this; var _this4 = this;
var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var tracks = captions.getTracks.call(this); var tracks = captions.getTracks.call(this);
var sortIsDefault = function sortIsDefault(track) { var sortIsDefault = function sortIsDefault(track) {
return Number((_this3.captions.meta.get(track) || {}).default); return Number((_this4.captions.meta.get(track) || {}).default);
}; };
var sorted = Array.from(tracks).sort(function (a, b) { var sorted = Array.from(tracks).sort(function (a, b) {
@ -9917,6 +10025,9 @@ var defaults$1 = {
fallback: true, fallback: true,
// Fallback using full viewport/window // Fallback using full viewport/window
iosNative: false // Use the native fullscreen in iOS (disables custom controls) iosNative: false // Use the native fullscreen in iOS (disables custom controls)
// Selector for the fullscreen container so contextual / non-player content can remain visible in fullscreen mode
// Non-ancestors of the player element will be ignored
// container: null, // defaults to the player element
}, },
// Local storage // Local storage
@ -10154,16 +10265,16 @@ var defaults$1 = {
title: false, title: false,
speed: true, speed: true,
transparent: false, transparent: false,
// These settings require a pro or premium account to work // Whether the owner of the video has a Pro or Business account
sidedock: false, // (which allows us to properly hide controls without CSS hacks, etc)
controls: false, premium: false,
// Custom settings from Plyr // Custom settings from Plyr
referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
}, },
// YouTube plugin // YouTube plugin
youtube: { youtube: {
noCookie: false, noCookie: true,
// Whether to use an alternative version of YouTube without cookies // Whether to use an alternative version of YouTube without cookies
rel: 0, rel: 0,
// No related vids // No related vids
@ -10273,7 +10384,10 @@ var Fullscreen = /*#__PURE__*/function () {
y: 0 y: 0
}; // Force the use of 'full window/browser' rather than fullscreen }; // Force the use of 'full window/browser' rather than fullscreen
this.forceFallback = player.config.fullscreen.fallback === 'force'; // Register event listeners this.forceFallback = player.config.fullscreen.fallback === 'force'; // Get the fullscreen element
// Checks container is an ancestor, defaults to null
this.player.elements.fullscreen = player.config.fullscreen.container && closest(this.player.elements.container, player.config.fullscreen.container); // Register event listeners
// Handle event (incase user presses escape etc) // Handle event (incase user presses escape etc)
on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () { on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () {
@ -10446,7 +10560,7 @@ var Fullscreen = /*#__PURE__*/function () {
if (browser.isIos && this.player.config.fullscreen.iosNative) { if (browser.isIos && this.player.config.fullscreen.iosNative) {
this.target.webkitExitFullscreen(); this.target.webkitExitFullscreen();
this.player.play(); silencePromise(this.player.play());
} else if (!Fullscreen.native || this.forceFallback) { } else if (!Fullscreen.native || this.forceFallback) {
this.toggleFallback(false); this.toggleFallback(false);
} else if (!this.prefix) { } else if (!this.prefix) {
@ -10493,13 +10607,13 @@ var Fullscreen = /*#__PURE__*/function () {
} }
var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")]; var element = !this.prefix ? document.fullscreenElement : document["".concat(this.prefix).concat(this.property, "Element")];
return element === this.target; return element && element.shadowRoot ? element === this.target.getRootNode().host : element === this.target;
} // Get target element } // Get target element
}, { }, {
key: "target", key: "target",
get: function get() { get: function get() {
return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.container; return browser.isIos && this.player.config.fullscreen.iosNative ? this.player.media : this.player.elements.fullscreen || this.player.elements.container;
} }
}], [{ }], [{
key: "native", key: "native",
@ -10708,12 +10822,7 @@ var ui = {
} // Set property synchronously to respect the call order } // Set property synchronously to respect the call order
this.media.setAttribute('poster', poster); // HTML5 uses native poster attribute this.media.setAttribute('data-poster', poster); // Wait until ui is ready
if (this.isHTML5) {
return Promise.resolve(poster);
} // Wait until ui is ready
return ready.call(this) // Load image return ready.call(this) // Load image
.then(function () { .then(function () {
@ -10789,6 +10898,26 @@ var ui = {
this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek)); this.toggleControls(Boolean(force || this.loading || this.paused || controlsElement.pressed || controlsElement.hover || recentTouchSeek));
} }
},
// Migrate any custom properties from the media to the parent
migrateStyles: function migrateStyles() {
var _this5 = this;
// Loop through values (as they are the keys when the object is spread 🤔)
Object.values(_objectSpread2({}, this.media.style)) // We're only fussed about Plyr specific properties
.filter(function (key) {
return !is$1.empty(key) && key.startsWith('--plyr');
}).forEach(function (key) {
// Set on the container
_this5.elements.container.style.setProperty(key, _this5.media.style.getPropertyValue(key)); // Clean up from media element
_this5.media.style.removeProperty(key);
}); // Remove attribute if empty
if (is$1.empty(this.media.style)) {
this.media.removeAttribute('style');
}
} }
}; };
@ -10883,7 +11012,7 @@ var Listeners = /*#__PURE__*/function () {
case 75: case 75:
// Space and K key // Space and K key
if (!repeat) { if (!repeat) {
player.togglePlay(); silencePromise(player.togglePlay());
} }
break; break;
@ -10997,6 +11126,7 @@ var Listeners = /*#__PURE__*/function () {
removeCurrent(); // Delay the adding of classname until the focus has changed removeCurrent(); // Delay the adding of classname until the focus has changed
// This event fires before the focusin event // This event fires before the focusin event
if (event.type !== 'focusout') {
this.focusTimer = setTimeout(function () { this.focusTimer = setTimeout(function () {
var focused = document.activeElement; // Ignore if current focus element isn't inside the player var focused = document.activeElement; // Ignore if current focus element isn't inside the player
@ -11006,6 +11136,7 @@ var Listeners = /*#__PURE__*/function () {
toggleClass(document.activeElement, player.config.classNames.tabFocus, true); toggleClass(document.activeElement, player.config.classNames.tabFocus, true);
}, 10); }, 10);
}
} // Global window & document listeners } // Global window & document listeners
}, { }, {
@ -11023,7 +11154,7 @@ var Listeners = /*#__PURE__*/function () {
once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection once.call(player, document.body, 'touchstart', this.firstTouch); // Tab focus detection
toggleListener.call(player, document.body, 'keydown focus blur', this.setTabFocus, toggle, false, true); toggleListener.call(player, document.body, 'keydown focus blur focusout', this.setTabFocus, toggle, false, true);
} // Container listeners } // Container listeners
}, { }, {
@ -11066,7 +11197,7 @@ var Listeners = /*#__PURE__*/function () {
}); // Set a gutter for Vimeo }); // Set a gutter for Vimeo
var setGutter = function setGutter(ratio, padding, toggle) { var setGutter = function setGutter(ratio, padding, toggle) {
if (!player.isVimeo) { if (!player.isVimeo || player.config.vimeo.premium) {
return; return;
} }
@ -11123,7 +11254,7 @@ var Listeners = /*#__PURE__*/function () {
ratio = _setPlayerSize.ratio; // Set Vimeo gutter ratio = _setPlayerSize.ratio; // Set Vimeo gutter
setGutter(ratio, padding, isEnter); // If not using native fullscreen, we need to check for resizes of viewport setGutter(ratio, padding, isEnter); // If not using native browser fullscreen API, we need to check for resizes of viewport
if (!usingNative) { if (!usingNative) {
if (isEnter) { if (isEnter) {
@ -11201,9 +11332,13 @@ var Listeners = /*#__PURE__*/function () {
if (player.ended) { if (player.ended) {
_this.proxy(event, player.restart, 'restart'); _this.proxy(event, player.restart, 'restart');
_this.proxy(event, player.play, 'play'); _this.proxy(event, function () {
silencePromise(player.play());
}, 'play');
} else { } else {
_this.proxy(event, player.togglePlay, 'play'); _this.proxy(event, function () {
silencePromise(player.togglePlay());
}, 'play');
} }
}); });
} // Disable right click } // Disable right click
@ -11301,7 +11436,9 @@ var Listeners = /*#__PURE__*/function () {
if (elements.buttons.play) { if (elements.buttons.play) {
Array.from(elements.buttons.play).forEach(function (button) { Array.from(elements.buttons.play).forEach(function (button) {
_this3.bind(button, 'click', player.togglePlay, 'play'); _this3.bind(button, 'click', function () {
silencePromise(player.togglePlay());
}, 'play');
}); });
} // Pause } // Pause
@ -11398,7 +11535,7 @@ var Listeners = /*#__PURE__*/function () {
if (play && done) { if (play && done) {
seek.removeAttribute(attribute); seek.removeAttribute(attribute);
player.play(); silencePromise(player.play());
} else if (!done && player.playing) { } else if (!done && player.playing) {
seek.setAttribute(attribute, ''); seek.setAttribute(attribute, '');
player.pause(); player.pause();
@ -11496,7 +11633,18 @@ var Listeners = /*#__PURE__*/function () {
this.bind(elements.controls, 'mouseenter mouseleave', function (event) { this.bind(elements.controls, 'mouseenter mouseleave', function (event) {
elements.controls.hover = !player.touch && event.type === 'mouseenter'; elements.controls.hover = !player.touch && event.type === 'mouseenter';
}); // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting) }); // Also update controls.hover state for any non-player children of fullscreen element (as above)
if (elements.fullscreen) {
Array.from(elements.fullscreen.children).filter(function (c) {
return !c.contains(elements.container);
}).forEach(function (child) {
_this3.bind(child, 'mouseenter mouseleave', function (event) {
elements.controls.hover = !player.touch && event.type === 'mouseenter';
});
});
} // Update controls.pressed state (used for ui.toggleControls to avoid hiding when interacting)
this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) { this.bind(elements.controls, 'mousedown mouseup touchstart touchend touchcancel', function (event) {
elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type); elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);
@ -11965,15 +12113,28 @@ var vimeo = {
var _this = this; var _this = this;
var player = this; var player = this;
var config = player.config.vimeo; // Get Vimeo params for the iframe var config = player.config.vimeo;
var params = buildUrlParams(extend({}, { var premium = config.premium,
referrerPolicy = config.referrerPolicy,
frameParams = _objectWithoutProperties(config, ["premium", "referrerPolicy"]); // If the owner has a pro or premium account then we can hide controls etc
if (premium) {
Object.assign(frameParams, {
controls: false,
sidedock: false
});
} // Get Vimeo params for the iframe
var params = buildUrlParams(_objectSpread2({
loop: player.config.loop.active, loop: player.config.loop.active,
autoplay: player.autoplay, autoplay: player.autoplay,
muted: player.muted, muted: player.muted,
gesture: 'media', gesture: 'media',
playsinline: !this.config.fullscreen.iosNative playsinline: !this.config.fullscreen.iosNative
}, config)); // Get the source URL or ID }, frameParams)); // Get the source URL or ID
var source = player.media.getAttribute('src'); // Get from <div> if needed var source = player.media.getAttribute('src'); // Get from <div> if needed
@ -11987,22 +12148,27 @@ var vimeo = {
var src = format(player.config.urls.vimeo.iframe, id, params); var src = format(player.config.urls.vimeo.iframe, id, params);
iframe.setAttribute('src', src); iframe.setAttribute('src', src);
iframe.setAttribute('allowfullscreen', ''); iframe.setAttribute('allowfullscreen', '');
iframe.setAttribute('allowtransparency', ''); iframe.setAttribute('allow', 'autoplay,fullscreen,picture-in-picture'); // Set the referrer policy if required
iframe.setAttribute('allow', 'autoplay'); // Set the referrer policy if required
if (!is$1.empty(config.referrerPolicy)) { if (!is$1.empty(referrerPolicy)) {
iframe.setAttribute('referrerPolicy', config.referrerPolicy); iframe.setAttribute('referrerPolicy', referrerPolicy);
} // Get poster, if already set } // Inject the package
var poster = player.poster; // Inject the package var poster = player.poster;
if (premium) {
iframe.setAttribute('data-poster', poster);
player.media = replaceElement(iframe, player.media);
} else {
var wrapper = createElement('div', { var wrapper = createElement('div', {
poster: poster, class: player.config.classNames.embedContainer,
class: player.config.classNames.embedContainer 'data-poster': poster
}); });
wrapper.appendChild(iframe); wrapper.appendChild(iframe);
player.media = replaceElement(wrapper, player.media); // Get poster image player.media = replaceElement(wrapper, player.media);
} // Get poster image
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) { fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
if (is$1.empty(response)) { if (is$1.empty(response)) {
@ -12086,6 +12252,9 @@ var vimeo = {
player.embed.setPlaybackRate(input).then(function () { player.embed.setPlaybackRate(input).then(function () {
speed = input; speed = input;
triggerEvent.call(player, player.media, 'ratechange'); triggerEvent.call(player, player.media, 'ratechange');
}).catch(function () {
// Cannot set Playback Rate, Video is probably not on Pro account
player.options.speed = [1];
}); });
} }
}); // Volume }); // Volume
@ -12370,7 +12539,7 @@ var youtube = {
var container = createElement('div', { var container = createElement('div', {
id: id, id: id,
poster: poster 'data-poster': poster
}); });
player.media = replaceElement(container, player.media); // Id to poster wrapper player.media = replaceElement(container, player.media); // Id to poster wrapper
@ -12688,15 +12857,13 @@ var media = {
class: this.config.classNames.video class: this.config.classNames.video
}); // Wrap the video in a container }); // Wrap the video in a container
wrap$1(this.media, this.elements.wrapper); // Faux poster container wrap$1(this.media, this.elements.wrapper); // Poster image container
if (this.isEmbed) {
this.elements.poster = createElement('div', { this.elements.poster = createElement('div', {
class: this.config.classNames.poster class: this.config.classNames.poster
}); });
this.elements.wrapper.appendChild(this.elements.poster); this.elements.wrapper.appendChild(this.elements.poster);
} }
}
if (this.isHTML5) { if (this.isHTML5) {
html5.setup.call(this); html5.setup.call(this);
@ -12822,6 +12989,8 @@ var Ads = /*#__PURE__*/function () {
* mobile devices, this initialization is done as the result of a user action. * mobile devices, this initialization is done as the result of a user action.
*/ */
value: function setupIMA() { value: function setupIMA() {
var _this4 = this;
// Create the container for our advertisements // Create the container for our advertisements
this.elements.container = createElement('div', { this.elements.container = createElement('div', {
class: this.player.config.classNames.ads class: this.player.config.classNames.ads
@ -12834,7 +13003,16 @@ var Ads = /*#__PURE__*/function () {
google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline); // We assume the adContainer is the video container of the plyr element that will house the ads google.ima.settings.setDisableCustomPlaybackForIOS10Plus(this.player.config.playsinline); // We assume the adContainer is the video container of the plyr element that will house the ads
this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media); // Request video ads to be pre-loaded this.elements.displayContainer = new google.ima.AdDisplayContainer(this.elements.container, this.player.media); // Create ads loader
this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events
this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) {
return _this4.onAdsManagerLoaded(event);
}, false);
this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) {
return _this4.onAdError(error);
}, false); // Request video ads to be pre-loaded
this.requestAds(); this.requestAds();
} }
@ -12845,21 +13023,10 @@ var Ads = /*#__PURE__*/function () {
}, { }, {
key: "requestAds", key: "requestAds",
value: function requestAds() { value: function requestAds() {
var _this4 = this;
var container = this.player.elements.container; var container = this.player.elements.container;
try { try {
// Create ads loader // Request video ads
this.loader = new google.ima.AdsLoader(this.elements.displayContainer); // Listen and respond to ads loaded and error events
this.loader.addEventListener(google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, function (event) {
return _this4.onAdsManagerLoaded(event);
}, false);
this.loader.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) {
return _this4.onAdError(error);
}, false); // Request video ads
var request = new google.ima.AdsRequest(); var request = new google.ima.AdsRequest();
request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK
// to select the correct creative if multiple are returned // to select the correct creative if multiple are returned
@ -13038,7 +13205,13 @@ var Ads = /*#__PURE__*/function () {
// }; // };
// TODO: So there is still this thing where a video should only be allowed to start // 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 // playing when the IMA SDK is ready or has failed
if (this.player.ended) {
this.loadAds(); this.loadAds();
} else {
// The SDK won't allow new ads to be called without receiving a contentComplete()
this.loader.contentComplete();
}
break; break;
case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED: case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:
@ -13174,7 +13347,7 @@ var Ads = /*#__PURE__*/function () {
this.playing = false; // Play video this.playing = false; // Play video
this.player.media.play(); silencePromise(this.player.media.play());
} }
/** /**
* Pause our video * Pause our video
@ -13231,7 +13404,9 @@ var Ads = /*#__PURE__*/function () {
_this11.on('loaded', resolve); _this11.on('loaded', resolve);
_this11.player.debug.log(_this11.manager); _this11.player.debug.log(_this11.manager);
}); // Now request some new advertisements }); // Now that the manager has been destroyed set it to also be un-initialized
_this11.initialized = false; // Now request some new advertisements
_this11.requestAds(); _this11.requestAds();
}).catch(function () {}); }).catch(function () {});
@ -13526,15 +13701,10 @@ var PreviewThumbnails = /*#__PURE__*/function () {
if (is$1.empty(src)) { if (is$1.empty(src)) {
throw new Error('Missing previewThumbnails.src config attribute'); throw new Error('Missing previewThumbnails.src config attribute');
} // If string, convert into single-element list } // Resolve promise
var urls = is$1.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails var sortAndResolve = function sortAndResolve() {
var promises = urls.map(function (u) {
return _this2.getThumbnail(u);
});
Promise.all(promises).then(function () {
// Sort smallest to biggest (e.g., [120p, 480p, 1080p]) // Sort smallest to biggest (e.g., [120p, 480p, 1080p])
_this2.thumbnails.sort(function (x, y) { _this2.thumbnails.sort(function (x, y) {
return x.height - y.height; return x.height - y.height;
@ -13543,7 +13713,25 @@ var PreviewThumbnails = /*#__PURE__*/function () {
_this2.player.debug.log('Preview thumbnails', _this2.thumbnails); _this2.player.debug.log('Preview thumbnails', _this2.thumbnails);
resolve(); resolve();
}; // Via callback()
if (is$1.function(src)) {
src(function (thumbnails) {
_this2.thumbnails = thumbnails;
sortAndResolve();
}); });
} // VTT urls
else {
// If string, convert into single-element list
var urls = is$1.string(src) ? [src] : src; // Loop through each src URL. Download and process the VTT file, storing the resulting data in this.thumbnails
var promises = urls.map(function (u) {
return _this2.getThumbnail(u);
}); // Resolve
Promise.all(promises).then(sortAndResolve);
}
}); });
} // Process individual VTT file } // Process individual VTT file
@ -14331,6 +14519,7 @@ var Plyr = /*#__PURE__*/function () {
this.elements = { this.elements = {
container: null, container: null,
fullscreen: null,
captions: null, captions: null,
buttons: {}, buttons: {},
display: {}, display: {},
@ -14505,9 +14694,11 @@ var Plyr = /*#__PURE__*/function () {
tabindex: 0 tabindex: 0
}); });
wrap$1(this.media, this.elements.container); wrap$1(this.media, this.elements.container);
} // Add style hook } // Migrate custom properties from media to container (so they work 😉)
ui.migrateStyles.call(this); // Add style hook
ui.addStyleHook.call(this); // Setup media ui.addStyleHook.call(this); // Setup media
media.setup.call(this); // Listen for events if debugging media.setup.call(this); // Listen for events if debugging
@ -14516,10 +14707,12 @@ var Plyr = /*#__PURE__*/function () {
on.call(this, this.elements.container, this.config.events.join(' '), function (event) { on.call(this, this.elements.container, this.config.events.join(' '), function (event) {
_this.debug.log("event: ".concat(event.type)); _this.debug.log("event: ".concat(event.type));
}); });
} // Setup interface } // Setup fullscreen
// If embed but not fully supported, build interface now to avoid flash of controls
this.fullscreen = new Fullscreen(this); // Setup interface
// If embed but not fully supported, build interface now to avoid flash of controls
if (this.isHTML5 || this.isEmbed && !this.supported.ui) { if (this.isHTML5 || this.isEmbed && !this.supported.ui) {
ui.build.call(this); ui.build.call(this);
} // Container listeners } // Container listeners
@ -14527,9 +14720,7 @@ var Plyr = /*#__PURE__*/function () {
this.listeners.container(); // Global listeners this.listeners.container(); // Global listeners
this.listeners.global(); // Setup fullscreen this.listeners.global(); // Setup ads if provided
this.fullscreen = new Fullscreen(this); // Setup ads if provided
if (this.config.ads.enabled) { if (this.config.ads.enabled) {
this.ads = new Ads(this); this.ads = new Ads(this);
@ -14538,7 +14729,7 @@ var Plyr = /*#__PURE__*/function () {
if (this.isHTML5 && this.config.autoplay) { if (this.isHTML5 && this.config.autoplay) {
setTimeout(function () { setTimeout(function () {
return _this.play(); return silencePromise(_this.play());
}, 10); }, 10);
} // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek } // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek
@ -14575,7 +14766,7 @@ var Plyr = /*#__PURE__*/function () {
this.ads.managerPromise.then(function () { this.ads.managerPromise.then(function () {
return _this2.ads.play(); return _this2.ads.play();
}).catch(function () { }).catch(function () {
return _this2.media.play(); return silencePromise(_this2.media.play());
}); });
} // Return the promise (for HTML5) } // Return the promise (for HTML5)
@ -14735,7 +14926,7 @@ var Plyr = /*#__PURE__*/function () {
var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu var hiding = toggleClass(this.elements.container, this.config.classNames.hideControls, force); // Close menu
if (hiding && this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) { if (hiding && is$1.array(this.config.controls) && this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) {
controls.toggleMenu.call(this, false); controls.toggleMenu.call(this, false);
} // Trigger event on change } // Trigger event on change
@ -15228,7 +15419,7 @@ var Plyr = /*#__PURE__*/function () {
var updateStorage = true; var updateStorage = true;
if (!options.includes(quality)) { if (!options.includes(quality)) {
var value = closest(options, quality); var value = closest$1(options, quality);
this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead")); this.debug.warn("Unsupported quality option: ".concat(quality, ", using ").concat(value, " instead"));
quality = value; // Don't update storage if quality is not supported quality = value; // Don't update storage if quality is not supported
@ -15373,7 +15564,7 @@ var Plyr = /*#__PURE__*/function () {
return null; return null;
} }
return this.media.getAttribute('poster'); return this.media.getAttribute('poster') || this.media.getAttribute('data-poster');
} }
/** /**
* Get the current aspect ratio in use * Get the current aspect ratio in use

View File

@ -263,7 +263,7 @@
{% block extend_js %} {% block extend_js %}
<!-- Plyr --> <!-- Plyr -->
<script src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/modules/plyr/plyr.min.js" <script src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/modules/plyr/plyr.min.js"
integrity="sha512-h2OOBB+c2Z3y4ROK8VhcWgO0KtUl5yDHpUFlpDN7YN96fv8XUbapjrf6EEvKoxW+9nMN/QcJ9wrk9N8+OxYhOA==" integrity="sha512-l6ZzdXpfMHRfifqaR79wbYCEWjLDMI9DnROvb+oLkKq6d7MGroGpMbI7HFpicvmAH/2aQO+vJhewq8rhysrImw=="
crossorigin="anonymous"></script> crossorigin="anonymous"></script>
<script src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/js/play.js"></script> <script src="{{ SITEURL }}/{{ THEME_STATIC_DIR }}/js/play.js"></script>
<!-- /Plyr --> <!-- /Plyr -->