aboutsummaryrefslogtreecommitdiffstats
path: root/dist/plyr.js
diff options
context:
space:
mode:
Diffstat (limited to 'dist/plyr.js')
-rw-r--r--dist/plyr.js980
1 files changed, 523 insertions, 457 deletions
diff --git a/dist/plyr.js b/dist/plyr.js
index 0bcd4d39..fa39b186 100644
--- a/dist/plyr.js
+++ b/dist/plyr.js
@@ -75,20 +75,52 @@ typeof navigator === "object" && (function (global, factory) {
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) {
- return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
+ return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _toConsumableArray(arr) {
- return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
+ return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}
function _arrayWithoutHoles(arr) {
- if (Array.isArray(arr)) {
- for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
-
- return arr2;
- }
+ if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
function _arrayWithHoles(arr) {
@@ -96,14 +128,11 @@ typeof navigator === "object" && (function (global, factory) {
}
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) {
- if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) {
- return;
- }
-
+ if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
var _arr = [];
var _n = true;
var _d = false;
@@ -129,102 +158,142 @@ typeof navigator === "object" && (function (global, factory) {
return _arr;
}
- function _nonIterableSpread() {
- throw new TypeError("Invalid attempt to spread non-iterable instance");
- }
-
- function _nonIterableRest() {
- throw new TypeError("Invalid attempt to destructure non-iterable instance");
+ 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(n);
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
- var defaults = {
- addCSS: true,
- // Add CSS to the element to improve usability (required here or in your CSS!)
- thumbWidth: 15,
- // The width of the thumb handle
- watch: true // Watch for new elements that match a string target
-
- };
+ function _arrayLikeToArray(arr, len) {
+ if (len == null || len > arr.length) len = arr.length;
- // Element matches a selector
- function matches(element, selector) {
-
- function match() {
- return Array.from(document.querySelectorAll(selector)).includes(this);
- }
+ for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
- var matches = match;
- return matches.call(element, selector);
+ return arr2;
}
- // Trigger event
- function trigger(element, type) {
- if (!element || !type) {
- return;
- } // Create and dispatch the event
-
-
- var event = new Event(type); // Dispatch the event
-
- element.dispatchEvent(event);
+ function _nonIterableSpread() {
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
- // ==========================================================================
- // Type checking utils
- // ==========================================================================
- var getConstructor = function getConstructor(input) {
- return input !== null && typeof input !== 'undefined' ? input.constructor : null;
- };
+ function _nonIterableRest() {
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
+ }
- var instanceOf = function instanceOf(input, constructor) {
- return Boolean(input && constructor && input instanceof constructor);
- };
+ function _classCallCheck$1(e, t) {
+ if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function");
+ }
- var isNullOrUndefined = function isNullOrUndefined(input) {
- return input === null || typeof input === 'undefined';
- };
+ function _defineProperties$1(e, t) {
+ for (var n = 0; n < t.length; n++) {
+ var r = t[n];
+ r.enumerable = r.enumerable || !1, r.configurable = !0, "value" in r && (r.writable = !0), Object.defineProperty(e, r.key, r);
+ }
+ }
- var isObject = function isObject(input) {
- return getConstructor(input) === Object;
- };
+ function _createClass$1(e, t, n) {
+ return t && _defineProperties$1(e.prototype, t), n && _defineProperties$1(e, n), e;
+ }
- var isNumber = function isNumber(input) {
- return getConstructor(input) === Number && !Number.isNaN(input);
- };
+ function _defineProperty$1(e, t, n) {
+ return t in e ? Object.defineProperty(e, t, {
+ value: n,
+ enumerable: !0,
+ configurable: !0,
+ writable: !0
+ }) : e[t] = n, e;
+ }
- var isString = function isString(input) {
- return getConstructor(input) === String;
- };
+ function ownKeys$1(e, t) {
+ var n = Object.keys(e);
- var isBoolean = function isBoolean(input) {
- return getConstructor(input) === Boolean;
- };
+ if (Object.getOwnPropertySymbols) {
+ var r = Object.getOwnPropertySymbols(e);
+ t && (r = r.filter(function (t) {
+ return Object.getOwnPropertyDescriptor(e, t).enumerable;
+ })), n.push.apply(n, r);
+ }
- var isFunction = function isFunction(input) {
- return getConstructor(input) === Function;
- };
+ return n;
+ }
- var isArray = function isArray(input) {
- return Array.isArray(input);
- };
+ function _objectSpread2$1(e) {
+ for (var t = 1; t < arguments.length; t++) {
+ var n = null != arguments[t] ? arguments[t] : {};
+ t % 2 ? ownKeys$1(Object(n), !0).forEach(function (t) {
+ _defineProperty$1(e, t, n[t]);
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(n)) : ownKeys$1(Object(n)).forEach(function (t) {
+ Object.defineProperty(e, t, Object.getOwnPropertyDescriptor(n, t));
+ });
+ }
- var isNodeList = function isNodeList(input) {
- return instanceOf(input, NodeList);
- };
+ return e;
+ }
- var isElement = function isElement(input) {
- return instanceOf(input, Element);
+ var defaults = {
+ addCSS: !0,
+ thumbWidth: 15,
+ watch: !0
};
- var isEvent = function isEvent(input) {
- return instanceOf(input, Event);
- };
+ function matches(e, t) {
+ return function () {
+ return Array.from(document.querySelectorAll(t)).includes(this);
+ }.call(e, t);
+ }
- var isEmpty = function isEmpty(input) {
- return isNullOrUndefined(input) || (isString(input) || isArray(input) || isNodeList(input)) && !input.length || isObject(input) && !Object.keys(input).length;
- };
+ function trigger(e, t) {
+ if (e && t) {
+ var n = new Event(t, {
+ bubbles: !0
+ });
+ e.dispatchEvent(n);
+ }
+ }
- var is = {
+ var getConstructor = function getConstructor(e) {
+ return null != e ? e.constructor : null;
+ },
+ instanceOf = function instanceOf(e, t) {
+ return !!(e && t && e instanceof t);
+ },
+ isNullOrUndefined = function isNullOrUndefined(e) {
+ return null == e;
+ },
+ isObject = function isObject(e) {
+ return getConstructor(e) === Object;
+ },
+ isNumber = function isNumber(e) {
+ return getConstructor(e) === Number && !Number.isNaN(e);
+ },
+ isString = function isString(e) {
+ return getConstructor(e) === String;
+ },
+ isBoolean = function isBoolean(e) {
+ return getConstructor(e) === Boolean;
+ },
+ isFunction = function isFunction(e) {
+ return getConstructor(e) === Function;
+ },
+ isArray = function isArray(e) {
+ return Array.isArray(e);
+ },
+ isNodeList = function isNodeList(e) {
+ return instanceOf(e, NodeList);
+ },
+ isElement = function isElement(e) {
+ return instanceOf(e, Element);
+ },
+ isEvent = function isEvent(e) {
+ return instanceOf(e, Event);
+ },
+ isEmpty = function isEmpty(e) {
+ return isNullOrUndefined(e) || (isString(e) || isArray(e) || isNodeList(e)) && !e.length || isObject(e) && !Object.keys(e).length;
+ },
+ is = {
nullOrUndefined: isNullOrUndefined,
object: isObject,
number: isNumber,
@@ -238,219 +307,98 @@ typeof navigator === "object" && (function (global, factory) {
empty: isEmpty
};
- // Get the number of decimal places
- function getDecimalPlaces(value) {
- var match = "".concat(value).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
-
- if (!match) {
- return 0;
- }
-
- return Math.max(0, // Number of digits right of decimal point.
- (match[1] ? match[1].length : 0) - ( // Adjust for scientific notation.
- match[2] ? +match[2] : 0));
- } // Round to the nearest step
+ function getDecimalPlaces(e) {
+ var t = "".concat(e).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
+ return t ? Math.max(0, (t[1] ? t[1].length : 0) - (t[2] ? +t[2] : 0)) : 0;
+ }
- function round(number, step) {
- if (step < 1) {
- var places = getDecimalPlaces(step);
- return parseFloat(number.toFixed(places));
+ function round(e, t) {
+ if (1 > t) {
+ var n = getDecimalPlaces(t);
+ return parseFloat(e.toFixed(n));
}
- return Math.round(number / step) * step;
+ return Math.round(e / t) * t;
}
- var RangeTouch =
- /*#__PURE__*/
- function () {
- /**
- * Setup a new instance
- * @param {String|Element} target
- * @param {Object} options
- */
- function RangeTouch(target, options) {
- _classCallCheck(this, RangeTouch);
-
- if (is.element(target)) {
- // An Element is passed, use it directly
- this.element = target;
- } else if (is.string(target)) {
- // A CSS Selector is passed, fetch it from the DOM
- this.element = document.querySelector(target);
- }
-
- if (!is.element(this.element) || !is.empty(this.element.rangeTouch)) {
- return;
- }
-
- this.config = Object.assign({}, defaults, options);
- this.init();
+ var RangeTouch = function () {
+ function e(t, n) {
+ _classCallCheck$1(this, e), is.element(t) ? this.element = t : is.string(t) && (this.element = document.querySelector(t)), is.element(this.element) && is.empty(this.element.rangeTouch) && (this.config = _objectSpread2$1({}, defaults, {}, n), this.init());
}
- _createClass(RangeTouch, [{
+ return _createClass$1(e, [{
key: "init",
- value: function init() {
- // Bail if not a touch enabled device
- if (!RangeTouch.enabled) {
- return;
- } // Add useful CSS
-
-
- if (this.config.addCSS) {
- // TODO: Restore original values on destroy
- this.element.style.userSelect = 'none';
- this.element.style.webKitUserSelect = 'none';
- this.element.style.touchAction = 'manipulation';
- }
-
- this.listeners(true);
- this.element.rangeTouch = this;
+ value: function value() {
+ e.enabled && (this.config.addCSS && (this.element.style.userSelect = "none", this.element.style.webKitUserSelect = "none", this.element.style.touchAction = "manipulation"), this.listeners(!0), this.element.rangeTouch = this);
}
}, {
key: "destroy",
- value: function destroy() {
- // Bail if not a touch enabled device
- if (!RangeTouch.enabled) {
- return;
- }
-
- this.listeners(false);
- this.element.rangeTouch = null;
+ value: function value() {
+ e.enabled && (this.config.addCSS && (this.element.style.userSelect = "", this.element.style.webKitUserSelect = "", this.element.style.touchAction = ""), this.listeners(!1), this.element.rangeTouch = null);
}
}, {
key: "listeners",
- value: function listeners(toggle) {
- var _this = this;
-
- var method = toggle ? 'addEventListener' : 'removeEventListener'; // Listen for events
-
- ['touchstart', 'touchmove', 'touchend'].forEach(function (type) {
- _this.element[method](type, function (event) {
- return _this.set(event);
- }, false);
+ value: function value(e) {
+ var t = this,
+ n = e ? "addEventListener" : "removeEventListener";
+ ["touchstart", "touchmove", "touchend"].forEach(function (e) {
+ t.element[n](e, function (e) {
+ return t.set(e);
+ }, !1);
});
}
- /**
- * Get the value based on touch position
- * @param {Event} event
- */
-
}, {
key: "get",
- value: function get(event) {
- if (!RangeTouch.enabled || !is.event(event)) {
- return null;
- }
-
- var input = event.target;
- var touch = event.changedTouches[0];
- var min = parseFloat(input.getAttribute('min')) || 0;
- var max = parseFloat(input.getAttribute('max')) || 100;
- var step = parseFloat(input.getAttribute('step')) || 1;
- var delta = max - min; // Calculate percentage
-
- var percent;
- var clientRect = input.getBoundingClientRect();
- var thumbWidth = 100 / clientRect.width * (this.config.thumbWidth / 2) / 100; // Determine left percentage
-
- percent = 100 / clientRect.width * (touch.clientX - clientRect.left); // Don't allow outside bounds
-
- if (percent < 0) {
- percent = 0;
- } else if (percent > 100) {
- percent = 100;
- } // Factor in the thumb offset
-
-
- if (percent < 50) {
- percent -= (100 - percent * 2) * thumbWidth;
- } else if (percent > 50) {
- percent += (percent - 50) * 2 * thumbWidth;
- } // Find the closest step to the mouse position
-
-
- return min + round(delta * (percent / 100), step);
+ value: function value(t) {
+ if (!e.enabled || !is.event(t)) return null;
+ var n,
+ r = t.target,
+ i = t.changedTouches[0],
+ o = parseFloat(r.getAttribute("min")) || 0,
+ s = parseFloat(r.getAttribute("max")) || 100,
+ u = parseFloat(r.getAttribute("step")) || 1,
+ c = r.getBoundingClientRect(),
+ a = 100 / c.width * (this.config.thumbWidth / 2) / 100;
+ return 0 > (n = 100 / c.width * (i.clientX - c.left)) ? n = 0 : 100 < n && (n = 100), 50 > n ? n -= (100 - 2 * n) * a : 50 < n && (n += 2 * (n - 50) * a), o + round(n / 100 * (s - o), u);
}
- /**
- * Update range value based on position
- * @param {Event} event
- */
-
}, {
key: "set",
- value: function set(event) {
- if (!RangeTouch.enabled || !is.event(event) || event.target.disabled) {
- return;
- } // Prevent text highlight on iOS
-
-
- event.preventDefault(); // Set value
-
- event.target.value = this.get(event); // Trigger event
-
- trigger(event.target, event.type === 'touchend' ? 'change' : 'input');
+ value: function value(t) {
+ e.enabled && is.event(t) && !t.target.disabled && (t.preventDefault(), t.target.value = this.get(t), trigger(t.target, "touchend" === t.type ? "change" : "input"));
}
}], [{
key: "setup",
-
- /**
- * Setup multiple instances
- * @param {String|Element|NodeList|Array} target
- * @param {Object} options
- */
- value: function setup(target) {
- var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
- var targets = null;
-
- if (is.empty(target) || is.string(target)) {
- targets = Array.from(document.querySelectorAll(is.string(target) ? target : 'input[type="range"]'));
- } else if (is.element(target)) {
- targets = [target];
- } else if (is.nodeList(target)) {
- targets = Array.from(target);
- } else if (is.array(target)) {
- targets = target.filter(is.element);
- }
-
- if (is.empty(targets)) {
- return null;
- }
-
- var config = Object.assign({}, defaults, options);
-
- if (is.string(target) && config.watch) {
- // Create an observer instance
- var observer = new MutationObserver(function (mutations) {
- Array.from(mutations).forEach(function (mutation) {
- Array.from(mutation.addedNodes).forEach(function (node) {
- if (!is.element(node) || !matches(node, target)) {
- return;
- } // eslint-disable-next-line no-unused-vars
-
-
- var range = new RangeTouch(node, config);
+ value: function value(t) {
+ var n = 1 < arguments.length && void 0 !== arguments[1] ? arguments[1] : {},
+ r = null;
+ if (is.empty(t) || is.string(t) ? r = Array.from(document.querySelectorAll(is.string(t) ? t : 'input[type="range"]')) : is.element(t) ? r = [t] : is.nodeList(t) ? r = Array.from(t) : is.array(t) && (r = t.filter(is.element)), is.empty(r)) return null;
+
+ var i = _objectSpread2$1({}, defaults, {}, n);
+
+ if (is.string(t) && i.watch) {
+ var o = new MutationObserver(function (n) {
+ Array.from(n).forEach(function (n) {
+ Array.from(n.addedNodes).forEach(function (n) {
+ is.element(n) && matches(n, t) && new e(n, i);
});
});
- }); // Pass in the target node, as well as the observer options
-
- observer.observe(document.body, {
- childList: true,
- subtree: true
+ });
+ o.observe(document.body, {
+ childList: !0,
+ subtree: !0
});
}
- return targets.map(function (t) {
- return new RangeTouch(t, options);
+ return r.map(function (t) {
+ return new e(t, n);
});
}
}, {
key: "enabled",
get: function get() {
- return 'ontouchstart' in document.documentElement;
+ return "ontouchstart" in document.documentElement;
}
- }]);
-
- return RangeTouch;
+ }]), e;
}();
// ==========================================================================
@@ -525,7 +473,7 @@ typeof navigator === "object" && (function (global, factory) {
};
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) {
@@ -867,12 +815,33 @@ typeof navigator === "object" && (function (global, factory) {
} // Element matches selector
function matches$1(element, selector) {
+ var _Element = Element,
+ prototype = _Element.prototype;
function match() {
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);
} // Find all elements
@@ -1144,6 +1113,19 @@ typeof navigator === "object" && (function (global, factory) {
}).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) {
if (!is$1.array(input) && (!is$1.string(input) || !input.includes(':'))) {
return false;
@@ -1212,8 +1194,8 @@ typeof navigator === "object" && (function (global, factory) {
var padding = 100 / w * h;
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) {
- var height = 240;
+ if (this.isVimeo && !this.config.vimeo.premium && this.supported.ui) {
+ var height = 100 / this.media.offsetWidth * parseInt(window.getComputedStyle(this.media).paddingBottom, 10);
var offset = (height - padding) / (height / 50);
this.media.style.transform = "translateY(-".concat(offset, "%)");
} else if (this.isHTML5) {
@@ -1320,7 +1302,7 @@ typeof navigator === "object" && (function (global, factory) {
player.currentTime = currentTime; // Resume playing
if (!paused) {
- player.play();
+ silencePromise(player.play());
}
}); // Load new source
@@ -1369,7 +1351,7 @@ typeof navigator === "object" && (function (global, factory) {
});
} // Get the closest value in an array
- function closest(array, value) {
+ function closest$1(array, value) {
if (!is$1.array(array) || !array.length) {
return null;
}
@@ -1407,19 +1389,19 @@ typeof navigator === "object" && (function (global, factory) {
return (current / max * 100).toFixed(2);
} // 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 find = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
var replace = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
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] : '';
return input.toString().replace(/\w\S*/g, function (text) {
return text.charAt(0).toUpperCase() + text.substr(1).toLowerCase();
});
- } // Convert string to pascalCase
+ }; // Convert string to pascalCase
function toPascalCase() {
var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
@@ -1498,9 +1480,7 @@ typeof navigator === "object" && (function (global, factory) {
}
};
- var Storage =
- /*#__PURE__*/
- function () {
+ var Storage = /*#__PURE__*/function () {
function Storage(player) {
_classCallCheck(this, Storage);
@@ -1782,7 +1762,7 @@ typeof navigator === "object" && (function (global, factory) {
var icon = document.createElementNS(namespace, 'svg');
setAttributes(icon, extend(attributes, {
- role: 'presentation',
+ 'aria-hidden': 'true',
focusable: 'false'
})); // Create the <use> to reference sprite
@@ -2519,39 +2499,39 @@ typeof navigator === "object" && (function (global, factory) {
// Set the looping options
/* setLoopMenu() {
- // Menu required
- if (!is.element(this.elements.settings.panels.loop)) {
- return;
- }
- const options = ['start', 'end', 'all', 'reset'];
- const list = this.elements.settings.panels.loop.querySelector('[role="menu"]');
- // Show the pane and tab
- toggleHidden(this.elements.settings.buttons.loop, false);
- toggleHidden(this.elements.settings.panels.loop, false);
- // Toggle the pane and tab
- const toggle = !is.empty(this.loop.options);
- controls.toggleMenuButton.call(this, 'loop', toggle);
- // Empty the menu
- emptyElement(list);
- options.forEach(option => {
- const item = createElement('li');
- const button = createElement(
- 'button',
- extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {
- type: 'button',
- class: this.config.classNames.control,
- 'data-plyr-loop-action': option,
- }),
- i18n.get(option, this.config)
- );
- if (['start', 'end'].includes(option)) {
- const badge = controls.createBadge.call(this, '00:00');
- button.appendChild(badge);
- }
- item.appendChild(button);
- list.appendChild(item);
- });
- }, */
+ // Menu required
+ if (!is.element(this.elements.settings.panels.loop)) {
+ return;
+ }
+ const options = ['start', 'end', 'all', 'reset'];
+ const list = this.elements.settings.panels.loop.querySelector('[role="menu"]');
+ // Show the pane and tab
+ toggleHidden(this.elements.settings.buttons.loop, false);
+ toggleHidden(this.elements.settings.panels.loop, false);
+ // Toggle the pane and tab
+ const toggle = !is.empty(this.loop.options);
+ controls.toggleMenuButton.call(this, 'loop', toggle);
+ // Empty the menu
+ emptyElement(list);
+ options.forEach(option => {
+ const item = createElement('li');
+ const button = createElement(
+ 'button',
+ extend(getAttributesFromSelector(this.config.selectors.buttons.loop), {
+ type: 'button',
+ class: this.config.classNames.control,
+ 'data-plyr-loop-action': option,
+ }),
+ i18n.get(option, this.config)
+ );
+ if (['start', 'end'].includes(option)) {
+ const badge = controls.createBadge.call(this, '00:00');
+ button.appendChild(badge);
+ }
+ item.appendChild(button);
+ list.appendChild(item);
+ });
+ }, */
// Get current selected caption language
// TODO: rework this to user the getter in the API?
// Set a list of available captions languages
@@ -3353,9 +3333,15 @@ typeof navigator === "object" && (function (global, factory) {
meta.set(track, {
default: track.mode === 'showing'
}); // 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
- 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 () {
return captions.updateCues.call(_this);
@@ -3372,13 +3358,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
- 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);
}
},
// Toggle captions display
// Used internally for the toggleCaptions method, with the passive option forced to false
toggle: function toggle(input) {
+ var _this2 = this;
+
var passive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
// If there's no full support
@@ -3425,7 +3413,15 @@ typeof navigator === "object" && (function (global, factory) {
controls.updateSetting.call(this, 'captions'); // Trigger event (not used internally)
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
// Used internally for the currentTrack setter with the passive option forced to false
@@ -3506,7 +3502,7 @@ typeof navigator === "object" && (function (global, factory) {
// If update is false it will also ignore tracks without metadata
// This is used to "freeze" the language options when captions.update is false
getTracks: function getTracks() {
- var _this2 = this;
+ var _this3 = this;
var update = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
// Handle media or textTracks missing or null
@@ -3514,20 +3510,20 @@ typeof navigator === "object" && (function (global, factory) {
// Filter out removed tracks and tracks that aren't captions/subtitles (for example metadata)
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) {
return ['captions', 'subtitles'].includes(track.kind);
});
},
// Match tracks based on languages and get the first
findTrack: function findTrack(languages) {
- var _this3 = this;
+ var _this4 = this;
var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var tracks = captions.getTracks.call(this);
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) {
@@ -3708,6 +3704,9 @@ typeof navigator === "object" && (function (global, factory) {
fallback: true,
// Fallback using full viewport/window
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
@@ -3945,16 +3944,16 @@ typeof navigator === "object" && (function (global, factory) {
title: false,
speed: true,
transparent: false,
- // These settings require a pro or premium account to work
- sidedock: false,
- controls: false,
+ // Whether the owner of the video has a Pro or Business account
+ // (which allows us to properly hide controls without CSS hacks, etc)
+ premium: false,
// Custom settings from Plyr
referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
},
// YouTube plugin
youtube: {
- noCookie: false,
+ noCookie: true,
// Whether to use an alternative version of YouTube without cookies
rel: 0,
// No related vids
@@ -4011,9 +4010,7 @@ typeof navigator === "object" && (function (global, factory) {
// ==========================================================================
var noop = function noop() {};
- var Console =
- /*#__PURE__*/
- function () {
+ var Console = /*#__PURE__*/function () {
function Console() {
var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
@@ -4049,9 +4046,7 @@ typeof navigator === "object" && (function (global, factory) {
return Console;
}();
- var Fullscreen =
- /*#__PURE__*/
- function () {
+ var Fullscreen = /*#__PURE__*/function () {
function Fullscreen(player) {
var _this = this;
@@ -4068,7 +4063,10 @@ typeof navigator === "object" && (function (global, factory) {
y: 0
}; // 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)
on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () {
@@ -4241,7 +4239,7 @@ typeof navigator === "object" && (function (global, factory) {
if (browser.isIos && this.player.config.fullscreen.iosNative) {
this.target.webkitExitFullscreen();
- this.player.play();
+ silencePromise(this.player.play());
} else if (!Fullscreen.native || this.forceFallback) {
this.toggleFallback(false);
} else if (!this.prefix) {
@@ -4288,13 +4286,13 @@ typeof navigator === "object" && (function (global, factory) {
}
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
}, {
key: "target",
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",
@@ -4356,7 +4354,6 @@ typeof navigator === "object" && (function (global, factory) {
});
}
- // ==========================================================================
var ui = {
addStyleHook: function addStyleHook() {
toggleClass(this.elements.container, this.config.selectors.container.replace('.', ''), true);
@@ -4491,12 +4488,7 @@ typeof navigator === "object" && (function (global, factory) {
} // Set property synchronously to respect the call order
- this.media.setAttribute('poster', poster); // HTML5 uses native poster attribute
-
- if (this.isHTML5) {
- return Promise.resolve(poster);
- } // Wait until ui is ready
-
+ this.media.setAttribute('data-poster', poster); // Wait until ui is ready
return ready.call(this) // Load image
.then(function () {
@@ -4572,12 +4564,30 @@ typeof navigator === "object" && (function (global, factory) {
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 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');
+ }
}
};
- var Listeners =
- /*#__PURE__*/
- function () {
+ var Listeners = /*#__PURE__*/function () {
function Listeners(player) {
_classCallCheck(this, Listeners);
@@ -4668,7 +4678,7 @@ typeof navigator === "object" && (function (global, factory) {
case 75:
// Space and K key
if (!repeat) {
- player.togglePlay();
+ silencePromise(player.togglePlay());
}
break;
@@ -4782,15 +4792,17 @@ typeof navigator === "object" && (function (global, factory) {
removeCurrent(); // Delay the adding of classname until the focus has changed
// This event fires before the focusin event
- this.focusTimer = setTimeout(function () {
- var focused = document.activeElement; // Ignore if current focus element isn't inside the player
+ if (event.type !== 'focusout') {
+ this.focusTimer = setTimeout(function () {
+ var focused = document.activeElement; // Ignore if current focus element isn't inside the player
- if (!elements.container.contains(focused)) {
- return;
- }
+ if (!elements.container.contains(focused)) {
+ return;
+ }
- toggleClass(document.activeElement, player.config.classNames.tabFocus, true);
- }, 10);
+ toggleClass(document.activeElement, player.config.classNames.tabFocus, true);
+ }, 10);
+ }
} // Global window & document listeners
}, {
@@ -4808,7 +4820,7 @@ typeof navigator === "object" && (function (global, factory) {
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
}, {
@@ -4851,7 +4863,7 @@ typeof navigator === "object" && (function (global, factory) {
}); // Set a gutter for Vimeo
var setGutter = function setGutter(ratio, padding, toggle) {
- if (!player.isVimeo) {
+ if (!player.isVimeo || player.config.vimeo.premium) {
return;
}
@@ -4908,7 +4920,7 @@ typeof navigator === "object" && (function (global, factory) {
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 (isEnter) {
@@ -4986,9 +4998,13 @@ typeof navigator === "object" && (function (global, factory) {
if (player.ended) {
_this.proxy(event, player.restart, 'restart');
- _this.proxy(event, player.play, 'play');
+ _this.proxy(event, function () {
+ silencePromise(player.play());
+ }, 'play');
} else {
- _this.proxy(event, player.togglePlay, 'play');
+ _this.proxy(event, function () {
+ silencePromise(player.togglePlay());
+ }, 'play');
}
});
} // Disable right click
@@ -5086,7 +5102,9 @@ typeof navigator === "object" && (function (global, factory) {
if (elements.buttons.play) {
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
@@ -5183,7 +5201,7 @@ typeof navigator === "object" && (function (global, factory) {
if (play && done) {
seek.removeAttribute(attribute);
- player.play();
+ silencePromise(player.play());
} else if (!done && player.playing) {
seek.setAttribute(attribute, '');
player.pause();
@@ -5281,7 +5299,18 @@ typeof navigator === "object" && (function (global, factory) {
this.bind(elements.controls, '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)
+ }); // 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) {
elements.controls.pressed = ['mousedown', 'touchstart'].includes(event.type);
@@ -5697,15 +5726,28 @@ typeof navigator === "object" && (function (global, factory) {
var _this = this;
var player = this;
- var config = player.config.vimeo; // Get Vimeo params for the iframe
+ var config = player.config.vimeo;
+
+ 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
+
- var params = buildUrlParams(extend({}, {
+ if (premium) {
+ Object.assign(frameParams, {
+ controls: false,
+ sidedock: false
+ });
+ } // Get Vimeo params for the iframe
+
+
+ var params = buildUrlParams(_objectSpread2({
loop: player.config.loop.active,
autoplay: player.autoplay,
muted: player.muted,
gesture: 'media',
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
@@ -5719,22 +5761,27 @@ typeof navigator === "object" && (function (global, factory) {
var src = format(player.config.urls.vimeo.iframe, id, params);
iframe.setAttribute('src', src);
iframe.setAttribute('allowfullscreen', '');
- iframe.setAttribute('allowtransparency', '');
- iframe.setAttribute('allow', 'autoplay'); // Set the referrer policy if required
+ iframe.setAttribute('allow', 'autoplay,fullscreen,picture-in-picture'); // Set the referrer policy if required
- if (!is$1.empty(config.referrerPolicy)) {
- iframe.setAttribute('referrerPolicy', config.referrerPolicy);
- } // Get poster, if already set
+ if (!is$1.empty(referrerPolicy)) {
+ iframe.setAttribute('referrerPolicy', referrerPolicy);
+ } // 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', {
+ class: player.config.classNames.embedContainer,
+ 'data-poster': poster
+ });
+ wrapper.appendChild(iframe);
+ player.media = replaceElement(wrapper, player.media);
+ } // Get poster image
- var wrapper = createElement('div', {
- poster: poster,
- class: player.config.classNames.embedContainer
- });
- wrapper.appendChild(iframe);
- player.media = replaceElement(wrapper, player.media); // Get poster image
fetch(format(player.config.urls.vimeo.api, id), 'json').then(function (response) {
if (is$1.empty(response)) {
@@ -5818,6 +5865,9 @@ typeof navigator === "object" && (function (global, factory) {
player.embed.setPlaybackRate(input).then(function () {
speed = input;
triggerEvent.call(player, player.media, 'ratechange');
+ }).catch(function () {
+ // Cannot set Playback Rate, Video is probably not on Pro account
+ player.options.speed = [1];
});
}
}); // Volume
@@ -6104,7 +6154,7 @@ typeof navigator === "object" && (function (global, factory) {
var container = createElement('div', {
id: id,
- poster: poster
+ 'data-poster': poster
});
player.media = replaceElement(container, player.media); // Id to poster wrapper
@@ -6423,14 +6473,12 @@ typeof navigator === "object" && (function (global, factory) {
class: this.config.classNames.video
}); // 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', {
- class: this.config.classNames.poster
- });
- this.elements.wrapper.appendChild(this.elements.poster);
- }
+ this.elements.poster = createElement('div', {
+ class: this.config.classNames.poster
+ });
+ this.elements.wrapper.appendChild(this.elements.poster);
}
if (this.isHTML5) {
@@ -6457,9 +6505,7 @@ typeof navigator === "object" && (function (global, factory) {
instance.elements.container.remove();
};
- var Ads =
- /*#__PURE__*/
- function () {
+ var Ads = /*#__PURE__*/function () {
/**
* Ads constructor.
* @param {Object} player
@@ -6559,6 +6605,8 @@ typeof navigator === "object" && (function (global, factory) {
* mobile devices, this initialization is done as the result of a user action.
*/
value: function setupIMA() {
+ var _this4 = this;
+
// Create the container for our advertisements
this.elements.container = createElement('div', {
class: this.player.config.classNames.ads
@@ -6571,7 +6619,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
- 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();
}
@@ -6582,21 +6639,10 @@ typeof navigator === "object" && (function (global, factory) {
}, {
key: "requestAds",
value: function requestAds() {
- var _this4 = this;
-
var container = this.player.elements.container;
try {
- // 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
-
+ // Request video ads
var request = new google.ima.AdsRequest();
request.adTagUrl = this.tagUrl; // Specify the linear and nonlinear slot sizes. This helps the SDK
// to select the correct creative if multiple are returned
@@ -6775,7 +6821,13 @@ typeof navigator === "object" && (function (global, factory) {
// };
// TODO: So there is still this thing where a video should only be allowed to start
// playing when the IMA SDK is ready or has failed
- this.loadAds();
+ if (this.player.ended) {
+ this.loadAds();
+ } else {
+ // The SDK won't allow new ads to be called without receiving a contentComplete()
+ this.loader.contentComplete();
+ }
+
break;
case google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED:
@@ -6911,7 +6963,7 @@ typeof navigator === "object" && (function (global, factory) {
this.playing = false; // Play video
- this.player.media.play();
+ silencePromise(this.player.media.play());
}
/**
* Pause our video
@@ -6968,7 +7020,9 @@ typeof navigator === "object" && (function (global, factory) {
_this11.on('loaded', resolve);
_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();
}).catch(function () {});
@@ -7151,9 +7205,7 @@ typeof navigator === "object" && (function (global, factory) {
return result;
};
- var PreviewThumbnails =
- /*#__PURE__*/
- function () {
+ var PreviewThumbnails = /*#__PURE__*/function () {
/**
* PreviewThumbnails constructor.
* @param {Plyr} player
@@ -7214,15 +7266,10 @@ typeof navigator === "object" && (function (global, factory) {
if (is$1.empty(src)) {
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 promises = urls.map(function (u) {
- return _this2.getThumbnail(u);
- });
- Promise.all(promises).then(function () {
+ var sortAndResolve = function sortAndResolve() {
// Sort smallest to biggest (e.g., [120p, 480p, 1080p])
_this2.thumbnails.sort(function (x, y) {
return x.height - y.height;
@@ -7231,7 +7278,25 @@ typeof navigator === "object" && (function (global, factory) {
_this2.player.debug.log('Preview thumbnails', _this2.thumbnails);
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
@@ -7982,9 +8047,7 @@ typeof navigator === "object" && (function (global, factory) {
// const globals = new WeakMap();
// Plyr instance
- var Plyr =
- /*#__PURE__*/
- function () {
+ var Plyr = /*#__PURE__*/function () {
function Plyr(target, options) {
var _this = this;
@@ -8021,6 +8084,7 @@ typeof navigator === "object" && (function (global, factory) {
this.elements = {
container: null,
+ fullscreen: null,
captions: null,
buttons: {},
display: {},
@@ -8195,8 +8259,10 @@ typeof navigator === "object" && (function (global, factory) {
tabindex: 0
});
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
@@ -8206,9 +8272,11 @@ typeof navigator === "object" && (function (global, factory) {
on.call(this, this.elements.container, this.config.events.join(' '), function (event) {
_this.debug.log("event: ".concat(event.type));
});
- } // Setup interface
- // If embed but not fully supported, build interface now to avoid flash of controls
+ } // Setup fullscreen
+
+ 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) {
ui.build.call(this);
@@ -8217,9 +8285,7 @@ typeof navigator === "object" && (function (global, factory) {
this.listeners.container(); // Global listeners
- this.listeners.global(); // Setup fullscreen
-
- this.fullscreen = new Fullscreen(this); // Setup ads if provided
+ this.listeners.global(); // Setup ads if provided
if (this.config.ads.enabled) {
this.ads = new Ads(this);
@@ -8228,7 +8294,7 @@ typeof navigator === "object" && (function (global, factory) {
if (this.isHTML5 && this.config.autoplay) {
setTimeout(function () {
- return _this.play();
+ return silencePromise(_this.play());
}, 10);
} // Seek time will be recorded (in listeners.js) so we can prevent hiding controls for a few seconds after seek
@@ -8265,7 +8331,7 @@ typeof navigator === "object" && (function (global, factory) {
this.ads.managerPromise.then(function () {
return _this2.ads.play();
}).catch(function () {
- return _this2.media.play();
+ return silencePromise(_this2.media.play());
});
} // Return the promise (for HTML5)
@@ -8918,7 +8984,7 @@ typeof navigator === "object" && (function (global, factory) {
var updateStorage = true;
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"));
quality = value; // Don't update storage if quality is not supported
@@ -8957,41 +9023,41 @@ typeof navigator === "object" && (function (global, factory) {
this.media.loop = toggle; // Set default to be a true toggle
/* const type = ['start', 'end', 'all', 'none', 'toggle'].includes(input) ? input : 'toggle';
- switch (type) {
- case 'start':
- if (this.config.loop.end && this.config.loop.end <= this.currentTime) {
- this.config.loop.end = null;
- }
- this.config.loop.start = this.currentTime;
- // this.config.loop.indicator.start = this.elements.display.played.value;
- break;
- case 'end':
- if (this.config.loop.start >= this.currentTime) {
- return this;
- }
- this.config.loop.end = this.currentTime;
- // this.config.loop.indicator.end = this.elements.display.played.value;
- break;
- case 'all':
- this.config.loop.start = 0;
- this.config.loop.end = this.duration - 2;
- this.config.loop.indicator.start = 0;
- this.config.loop.indicator.end = 100;
- break;
- case 'toggle':
- if (this.config.loop.active) {
- this.config.loop.start = 0;
- this.config.loop.end = null;
- } else {
+ switch (type) {
+ case 'start':
+ if (this.config.loop.end && this.config.loop.end <= this.currentTime) {
+ this.config.loop.end = null;
+ }
+ this.config.loop.start = this.currentTime;
+ // this.config.loop.indicator.start = this.elements.display.played.value;
+ break;
+ case 'end':
+ if (this.config.loop.start >= this.currentTime) {
+ return this;
+ }
+ this.config.loop.end = this.currentTime;
+ // this.config.loop.indicator.end = this.elements.display.played.value;
+ break;
+ case 'all':
this.config.loop.start = 0;
this.config.loop.end = this.duration - 2;
- }
- break;
- default:
- this.config.loop.start = 0;
- this.config.loop.end = null;
- break;
- } */
+ this.config.loop.indicator.start = 0;
+ this.config.loop.indicator.end = 100;
+ break;
+ case 'toggle':
+ if (this.config.loop.active) {
+ this.config.loop.start = 0;
+ this.config.loop.end = null;
+ } else {
+ this.config.loop.start = 0;
+ this.config.loop.end = this.duration - 2;
+ }
+ break;
+ default:
+ this.config.loop.start = 0;
+ this.config.loop.end = null;
+ break;
+ } */
}
/**
* Get current loop state
@@ -9063,7 +9129,7 @@ typeof navigator === "object" && (function (global, factory) {
return null;
}
- return this.media.getAttribute('poster');
+ return this.media.getAttribute('poster') || this.media.getAttribute('data-poster');
}
/**
* Get the current aspect ratio in use