aboutsummaryrefslogtreecommitdiffstats
path: root/libretube-theme/static/modules/plyr/plyr.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'libretube-theme/static/modules/plyr/plyr.mjs')
-rw-r--r--libretube-theme/static/modules/plyr/plyr.mjs1334
1 files changed, 670 insertions, 664 deletions
diff --git a/libretube-theme/static/modules/plyr/plyr.mjs b/libretube-theme/static/modules/plyr/plyr.mjs
index 89fc799..288d6ae 100644
--- a/libretube-theme/static/modules/plyr/plyr.mjs
+++ b/libretube-theme/static/modules/plyr/plyr.mjs
@@ -35,6 +35,40 @@ function _defineProperty(obj, key, value) {
return obj;
}
+function ownKeys(object, enumerableOnly) {
+ var keys = Object.keys(object);
+
+ if (Object.getOwnPropertySymbols) {
+ var symbols = Object.getOwnPropertySymbols(object);
+ if (enumerableOnly) symbols = symbols.filter(function (sym) {
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
+ });
+ keys.push.apply(keys, symbols);
+ }
+
+ return keys;
+}
+
+function _objectSpread2(target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i] != null ? arguments[i] : {};
+
+ if (i % 2) {
+ ownKeys(Object(source), true).forEach(function (key) {
+ _defineProperty(target, key, source[key]);
+ });
+ } else if (Object.getOwnPropertyDescriptors) {
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
+ } else {
+ ownKeys(Object(source)).forEach(function (key) {
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
+ });
+ }
+ }
+
+ return target;
+}
+
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
}
@@ -60,6 +94,10 @@ function _iterableToArray(iter) {
}
function _iterableToArrayLimit(arr, i) {
+ if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) {
+ return;
+ }
+
var _arr = [];
var _n = true;
var _d = false;
@@ -93,94 +131,117 @@ function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
-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
-
-};
-
-// Element matches a selector
-function matches(element, selector) {
+function _classCallCheck$1(e, t) {
+ if (!(e instanceof t)) throw new TypeError("Cannot call a class as a function");
+}
- function match() {
- return Array.from(document.querySelectorAll(selector)).includes(this);
+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 matches = match;
- return matches.call(element, selector);
}
-// 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 _createClass$1(e, t, n) {
+ return t && _defineProperties$1(e.prototype, t), n && _defineProperties$1(e, n), e;
}
-// ==========================================================================
-// Type checking utils
-// ==========================================================================
-var getConstructor = function getConstructor(input) {
- return input !== null && typeof input !== 'undefined' ? input.constructor : null;
-};
-
-var instanceOf = function instanceOf(input, constructor) {
- return Boolean(input && constructor && input instanceof constructor);
-};
-
-var isNullOrUndefined = function isNullOrUndefined(input) {
- return input === null || typeof input === 'undefined';
-};
-
-var isObject = function isObject(input) {
- return getConstructor(input) === Object;
-};
-
-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,
@@ -194,219 +255,98 @@ var is = {
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;
}();
// ==========================================================================
@@ -577,152 +517,6 @@ var browser = {
isIos: /(iPad|iPhone|iPod)/gi.test(navigator.platform)
};
-// ==========================================================================
-// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
-// https://www.youtube.com/watch?v=NPM6172J22g
-
-var supportsPassiveListeners = function () {
- // Test via a getter in the options object to see if the passive property is accessed
- var supported = false;
-
- try {
- var options = Object.defineProperty({}, 'passive', {
- get: function get() {
- supported = true;
- return null;
- }
- });
- window.addEventListener('test', null, options);
- window.removeEventListener('test', null, options);
- } catch (e) {// Do nothing
- }
-
- return supported;
-}(); // Toggle event listener
-
-
-function toggleListener(element, event, callback) {
- var _this = this;
-
- var toggle = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
- var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
- var capture = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
-
- // Bail if no element, event, or callback
- if (!element || !('addEventListener' in element) || is$1.empty(event) || !is$1.function(callback)) {
- return;
- } // Allow multiple events
-
-
- var events = event.split(' '); // Build options
- // Default to just the capture boolean for browsers with no passive listener support
-
- var options = capture; // If passive events listeners are supported
-
- if (supportsPassiveListeners) {
- options = {
- // Whether the listener can be passive (i.e. default never prevented)
- passive: passive,
- // Whether the listener is a capturing listener or not
- capture: capture
- };
- } // If a single node is passed, bind the event listener
-
-
- events.forEach(function (type) {
- if (_this && _this.eventListeners && toggle) {
- // Cache event listener
- _this.eventListeners.push({
- element: element,
- type: type,
- callback: callback,
- options: options
- });
- }
-
- element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);
- });
-} // Bind event handler
-
-function on(element) {
- var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
- var callback = arguments.length > 2 ? arguments[2] : undefined;
- var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
- var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
- toggleListener.call(this, element, events, callback, true, passive, capture);
-} // Unbind event handler
-
-function off(element) {
- var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
- var callback = arguments.length > 2 ? arguments[2] : undefined;
- var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
- var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
- toggleListener.call(this, element, events, callback, false, passive, capture);
-} // Bind once-only event handler
-
-function once(element) {
- var _this2 = this;
-
- var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
- var callback = arguments.length > 2 ? arguments[2] : undefined;
- var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
- var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
-
- var onceCallback = function onceCallback() {
- off(element, events, onceCallback, passive, capture);
-
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
- args[_key] = arguments[_key];
- }
-
- callback.apply(_this2, args);
- };
-
- toggleListener.call(this, element, events, onceCallback, true, passive, capture);
-} // Trigger event
-
-function triggerEvent(element) {
- var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
- var bubbles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
- var detail = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
-
- // Bail if no element
- if (!is$1.element(element) || is$1.empty(type)) {
- return;
- } // Create and dispatch the event
-
-
- var event = new CustomEvent(type, {
- bubbles: bubbles,
- detail: Object.assign({}, detail, {
- plyr: this
- })
- }); // Dispatch the event
-
- element.dispatchEvent(event);
-} // Unbind all cached event listeners
-
-function unbindListeners() {
- if (this && this.eventListeners) {
- this.eventListeners.forEach(function (item) {
- var element = item.element,
- type = item.type,
- callback = item.callback,
- options = item.options;
- element.removeEventListener(type, callback, options);
- });
- this.eventListeners = [];
- }
-} // Run method when / if player is ready
-
-function ready() {
- var _this3 = this;
-
- return new Promise(function (resolve) {
- return _this3.ready ? setTimeout(resolve, 0) : on.call(_this3, _this3.elements.container, 'ready', resolve);
- }).then(function () {});
-}
-
function cloneDeep(object) {
return JSON.parse(JSON.stringify(object));
} // Get a nested value in an object
@@ -923,9 +717,6 @@ function getAttributesFromSelector(sel, existingAttributes) {
// Attribute selector
attributes[key] = value;
break;
-
- default:
- break;
}
});
return extend(existing, attributes);
@@ -987,41 +778,6 @@ function getElements(selector) {
function getElement(selector) {
return this.elements.container.querySelector(selector);
-} // Trap focus inside container
-
-function trapFocus() {
- var element = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
- var toggle = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
-
- if (!is$1.element(element)) {
- return;
- }
-
- var focusable = getElements.call(this, 'button:not(:disabled), input:not(:disabled), [tabindex]');
- var first = focusable[0];
- var last = focusable[focusable.length - 1];
-
- var trap = function trap(event) {
- // Bail if not tab key or not fullscreen
- if (event.key !== 'Tab' || event.keyCode !== 9) {
- return;
- } // Get the current focused element
-
-
- var focused = document.activeElement;
-
- if (focused === last && !event.shiftKey) {
- // Move focus to first element that can be tabbed if Shift isn't used
- first.focus();
- event.preventDefault();
- } else if (focused === first && event.shiftKey) {
- // Move focus to last element that can be tabbed if Shift is used
- last.focus();
- event.preventDefault();
- }
- };
-
- toggleListener.call(this, this.elements.container, 'keydown', trap, toggle, false);
} // Set focus and tab focus class
function setFocus() {
@@ -1139,6 +895,151 @@ var support = {
reducedMotion: 'matchMedia' in window && window.matchMedia('(prefers-reduced-motion)').matches
};
+// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
+// https://www.youtube.com/watch?v=NPM6172J22g
+
+var supportsPassiveListeners = function () {
+ // Test via a getter in the options object to see if the passive property is accessed
+ var supported = false;
+
+ try {
+ var options = Object.defineProperty({}, 'passive', {
+ get: function get() {
+ supported = true;
+ return null;
+ }
+ });
+ window.addEventListener('test', null, options);
+ window.removeEventListener('test', null, options);
+ } catch (e) {// Do nothing
+ }
+
+ return supported;
+}(); // Toggle event listener
+
+
+function toggleListener(element, event, callback) {
+ var _this = this;
+
+ var toggle = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
+ var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
+ var capture = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
+
+ // Bail if no element, event, or callback
+ if (!element || !('addEventListener' in element) || is$1.empty(event) || !is$1.function(callback)) {
+ return;
+ } // Allow multiple events
+
+
+ var events = event.split(' '); // Build options
+ // Default to just the capture boolean for browsers with no passive listener support
+
+ var options = capture; // If passive events listeners are supported
+
+ if (supportsPassiveListeners) {
+ options = {
+ // Whether the listener can be passive (i.e. default never prevented)
+ passive: passive,
+ // Whether the listener is a capturing listener or not
+ capture: capture
+ };
+ } // If a single node is passed, bind the event listener
+
+
+ events.forEach(function (type) {
+ if (_this && _this.eventListeners && toggle) {
+ // Cache event listener
+ _this.eventListeners.push({
+ element: element,
+ type: type,
+ callback: callback,
+ options: options
+ });
+ }
+
+ element[toggle ? 'addEventListener' : 'removeEventListener'](type, callback, options);
+ });
+} // Bind event handler
+
+function on(element) {
+ var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
+ var callback = arguments.length > 2 ? arguments[2] : undefined;
+ var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
+ var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
+ toggleListener.call(this, element, events, callback, true, passive, capture);
+} // Unbind event handler
+
+function off(element) {
+ var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
+ var callback = arguments.length > 2 ? arguments[2] : undefined;
+ var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
+ var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
+ toggleListener.call(this, element, events, callback, false, passive, capture);
+} // Bind once-only event handler
+
+function once(element) {
+ var _this2 = this;
+
+ var events = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
+ var callback = arguments.length > 2 ? arguments[2] : undefined;
+ var passive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
+ var capture = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
+
+ var onceCallback = function onceCallback() {
+ off(element, events, onceCallback, passive, capture);
+
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
+ args[_key] = arguments[_key];
+ }
+
+ callback.apply(_this2, args);
+ };
+
+ toggleListener.call(this, element, events, onceCallback, true, passive, capture);
+} // Trigger event
+
+function triggerEvent(element) {
+ var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
+ var bubbles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+ var detail = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
+
+ // Bail if no element
+ if (!is$1.element(element) || is$1.empty(type)) {
+ return;
+ } // Create and dispatch the event
+
+
+ var event = new CustomEvent(type, {
+ bubbles: bubbles,
+ detail: _objectSpread2({}, detail, {
+ plyr: this
+ })
+ }); // Dispatch the event
+
+ element.dispatchEvent(event);
+} // Unbind all cached event listeners
+
+function unbindListeners() {
+ if (this && this.eventListeners) {
+ this.eventListeners.forEach(function (item) {
+ var element = item.element,
+ type = item.type,
+ callback = item.callback,
+ options = item.options;
+ element.removeEventListener(type, callback, options);
+ });
+ this.eventListeners = [];
+ }
+} // Run method when / if player is ready
+
+function ready() {
+ var _this3 = this;
+
+ return new Promise(function (resolve) {
+ return _this3.ready ? setTimeout(resolve, 0) : on.call(_this3, _this3.elements.container, 'ready', resolve);
+ }).then(function () {});
+}
+
function validateRatio(input) {
if (!is$1.array(input) && (!is$1.string(input) || !input.includes(':'))) {
return false;
@@ -1196,6 +1097,7 @@ function setAspectRatio(input) {
return {};
}
+ var wrapper = this.elements.wrapper;
var ratio = getAspectRatio.call(this, input);
var _ref = is$1.array(ratio) ? ratio : [0, 0],
@@ -1204,14 +1106,14 @@ function setAspectRatio(input) {
h = _ref2[1];
var padding = 100 / w * h;
- this.elements.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) {
var height = 240;
var offset = (height - padding) / (height / 50);
this.media.style.transform = "translateY(-".concat(offset, "%)");
} else if (this.isHTML5) {
- this.elements.wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null);
+ wrapper.classList.toggle(this.config.classNames.videoFixedRatio, ratio !== null);
}
return {
@@ -1243,17 +1145,24 @@ var html5 = {
},
// Get quality levels
getQualityOptions: function getQualityOptions() {
- // Get sizes from <source> elements
+ // Whether we're forcing all options (e.g. for streaming)
+ if (this.config.quality.forced) {
+ return this.config.quality.options;
+ } // Get sizes from <source> elements
+
+
return html5.getSources.call(this).map(function (source) {
return Number(source.getAttribute('data-res'));
}).filter(Boolean);
},
- extend: function extend() {
+ setup: function setup() {
if (!this.isHTML5) {
return;
}
- var player = this; // Set aspect ratio if fixed
+ var player = this; // Set speed options from config
+
+ player.options.speed = player.config.speed.options; // Set aspect ratio if fixed
if (!is$1.empty(this.config.ratio)) {
setAspectRatio.call(player);
@@ -1271,37 +1180,48 @@ var html5 = {
return source && Number(source.getAttribute('data-res'));
},
set: function set(input) {
- // Get sources
- var sources = html5.getSources.call(player); // Get first match for requested size
+ if (player.quality === input) {
+ return;
+ } // If we're using an an external handler...
- var source = sources.find(function (s) {
- return Number(s.getAttribute('data-res')) === input;
- }); // No matching source found
- if (!source) {
- return;
- } // Get current state
+ if (player.config.quality.forced && is$1.function(player.config.quality.onChange)) {
+ player.config.quality.onChange(input);
+ } else {
+ // Get sources
+ var sources = html5.getSources.call(player); // Get first match for requested size
+ var source = sources.find(function (s) {
+ return Number(s.getAttribute('data-res')) === input;
+ }); // No matching source found
- var _player$media = player.media,
- currentTime = _player$media.currentTime,
- paused = _player$media.paused,
- preload = _player$media.preload,
- readyState = _player$media.readyState; // Set new source
+ if (!source) {
+ return;
+ } // Get current state
- player.media.src = source.getAttribute('src'); // Prevent loading if preload="none" and the current source isn't loaded (#1044)
- if (preload !== 'none' || readyState) {
- // Restore time
- player.once('loadedmetadata', function () {
- player.currentTime = currentTime; // Resume playing
+ var _player$media = player.media,
+ currentTime = _player$media.currentTime,
+ paused = _player$media.paused,
+ preload = _player$media.preload,
+ readyState = _player$media.readyState,
+ playbackRate = _player$media.playbackRate; // Set new source
- if (!paused) {
- player.play();
- }
- }); // Load new source
+ player.media.src = source.getAttribute('src'); // Prevent loading if preload="none" and the current source isn't loaded (#1044)
- player.media.load();
+ if (preload !== 'none' || readyState) {
+ // Restore time
+ player.once('loadedmetadata', function () {
+ player.speed = playbackRate;
+ player.currentTime = currentTime; // Resume playing
+
+ if (!paused) {
+ player.play();
+ }
+ }); // Load new source
+
+ player.media.load();
+ }
} // Trigger change event
@@ -1474,9 +1394,7 @@ var i18n = {
}
};
-var Storage =
-/*#__PURE__*/
-function () {
+var Storage = /*#__PURE__*/function () {
function Storage(player) {
_classCallCheck(this, Storage);
@@ -1672,7 +1590,7 @@ function formatTime() {
// Bail if the value isn't a number
if (!is$1.number(time)) {
- return formatTime(null, displayHours, inverted);
+ return formatTime(undefined, displayHours, inverted);
} // Format time component to add leading zero
@@ -1781,9 +1699,11 @@ var controls = {
createLabel: function createLabel(key) {
var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var text = i18n.get(key, this.config);
- var attributes = Object.assign({}, attr, {
+
+ var attributes = _objectSpread2({}, attr, {
class: [attr.class, this.config.classNames.hidden].filter(Boolean).join(' ')
});
+
return createElement('span', attributes, text);
},
// Create a badge
@@ -1993,7 +1913,7 @@ var controls = {
var _this2 = this;
// Navigate through menus via arrow keys and space
- on(menuItem, 'keydown keyup', function (event) {
+ on.call(this, menuItem, 'keydown keyup', function (event) {
// We only care about space and ⬆️ ⬇️️ ➡️
if (![32, 38, 39, 40].includes(event.which)) {
return;
@@ -2035,7 +1955,7 @@ var controls = {
}, false); // Enter will fire a `click` event but we still need to manage focus
// So we bind to keyup which fires after and set focus here
- on(menuItem, 'keyup', function (event) {
+ on.call(this, menuItem, 'keyup', function (event) {
if (event.which !== 13) {
return;
}
@@ -2112,9 +2032,6 @@ var controls = {
case 'speed':
_this3.speed = parseFloat(value);
break;
-
- default:
- break;
}
controls.showMenuPanel.call(_this3, 'home', is$1.keyboardEvent(event));
@@ -2223,9 +2140,6 @@ var controls = {
case 'progress':
setProgress(this.elements.display.buffer, this.buffered * 100);
break;
-
- default:
- break;
}
}
},
@@ -2545,7 +2459,7 @@ var controls = {
var type = 'captions';
- var list = this.elements.settings.panels.captions.querySelector('[role="menucaptions"]');
+ var list = this.elements.settings.panels.captions.querySelector('[role="menu"]');
var tracks = captions.getTracks.call(this);
var toggle = Boolean(tracks.length); // Toggle the pane and tab
@@ -2583,7 +2497,7 @@ var controls = {
controls.updateSetting.call(this, type, list);
},
// Set a list of available captions languages
- setSpeedMenu: function setSpeedMenu(options) {
+ setSpeedMenu: function setSpeedMenu() {
var _this8 = this;
// Menu required
@@ -2592,17 +2506,10 @@ var controls = {
}
var type = 'speed';
- var list = this.elements.settings.panels.speed.querySelector('[role="menu"]'); // Set the speed options
+ var list = this.elements.settings.panels.speed.querySelector('[role="menu"]'); // Filter out invalid speeds
- if (is$1.array(options)) {
- this.options.speed = options;
- } else if (this.isHTML5 || this.isVimeo) {
- this.options.speed = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
- } // Set options if passed and filter based on config
-
-
- this.options.speed = this.options.speed.filter(function (speed) {
- return _this8.config.speed.options.includes(speed);
+ this.options.speed = this.options.speed.filter(function (o) {
+ return o >= _this8.minimumSpeed && o <= _this8.maximumSpeed;
}); // Toggle the pane and tab
var toggle = !is$1.empty(this.options.speed) && this.options.speed.length > 1;
@@ -2879,9 +2786,11 @@ var controls = {
if (control === 'mute') {
volume.appendChild(createButton.call(_this10, 'mute'));
} // Volume range control
+ // Ignored on iOS as it's handled globally
+ // https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html
- if (control === 'volume') {
+ if (control === 'volume' && !browser.isIos) {
// Set the attributes
var attributes = {
max: 1,
@@ -2940,7 +2849,7 @@ var controls = {
bindMenuItemShortcuts.call(_this10, menuItem, type); // Show menu on click
- on(menuItem, 'click', function () {
+ on.call(_this10, menuItem, 'click', function () {
showMenuPanel.call(_this10, type, false);
});
var flex = createElement('span', null, i18n.get(type, _this10.config));
@@ -2971,7 +2880,7 @@ var controls = {
class: _this10.config.classNames.hidden
}, i18n.get('menuBack', _this10.config))); // Go back via keyboard
- on(pane, 'keydown', function (event) {
+ on.call(_this10, pane, 'keydown', function (event) {
// We only care about <-
if (event.which !== 37) {
return;
@@ -2984,7 +2893,7 @@ var controls = {
showMenuPanel.call(_this10, 'home', true);
}, false); // Go back via button click
- on(backButton, 'click', function () {
+ on.call(_this10, backButton, 'click', function () {
showMenuPanel.call(_this10, 'home', false);
}); // Add to pane
@@ -2992,10 +2901,6 @@ var controls = {
pane.appendChild(createElement('div', {
role: 'menu'
- })); // Menu Captions
-
- pane.appendChild(createElement('div', {
- role: 'menucaptions'
}));
inner.appendChild(pane);
_this10.elements.settings.buttons[type] = menuItem;
@@ -3025,7 +2930,12 @@ var controls = {
element: 'a',
href: _this10.download,
target: '_blank'
- });
+ }); // Set download attribute for HTML5 only
+
+
+ if (_this10.isHTML5) {
+ _attributes.download = '';
+ }
var download = _this10.config.urls.download;
@@ -3650,7 +3560,10 @@ var defaults$1 = {
// Quality default
quality: {
default: 576,
- options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240]
+ // The options to display in the UI, if available for the source media
+ options: [4320, 2880, 2160, 1440, 1080, 720, 576, 480, 360, 240],
+ forced: false,
+ onChange: null
},
// Set loops
loop: {
@@ -3661,7 +3574,8 @@ var defaults$1 = {
// Speed default and options to display
speed: {
selected: 1,
- options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]
+ // The options to display in the UI, if available for the source media (e.g. Vimeo and YouTube only support 0.5x-4x)
+ options: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 4]
},
// Keyboard shortcut settings
keyboard: {
@@ -3727,6 +3641,7 @@ var defaults$1 = {
frameTitle: 'Player for {title}',
captions: 'Captions',
settings: 'Settings',
+ pip: 'PIP',
menuBack: 'Go back to previous menu',
speed: 'Speed',
normal: 'Normal',
@@ -3923,7 +3838,13 @@ var defaults$1 = {
portrait: false,
title: false,
speed: true,
- transparent: false
+ transparent: false,
+ // These settings require a pro or premium account to work
+ sidedock: false,
+ controls: false,
+ // Custom settings from Plyr
+ referrerPolicy: null // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/referrerPolicy
+
},
// YouTube plugin
youtube: {
@@ -3984,9 +3905,7 @@ function getProviderByUrl(url) {
// ==========================================================================
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;
@@ -4022,76 +3941,7 @@ function () {
return Console;
}();
-function onChange() {
- if (!this.enabled) {
- return;
- } // Update toggle button
-
-
- var button = this.player.elements.buttons.fullscreen;
-
- if (is$1.element(button)) {
- button.pressed = this.active;
- } // Trigger an event
-
-
- triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true); // Trap focus in container
-
- if (!browser.isIos) {
- trapFocus.call(this.player, this.target, this.active);
- }
-}
-
-function toggleFallback() {
- var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
-
- // Store or restore scroll position
- if (toggle) {
- this.scrollPosition = {
- x: window.scrollX || 0,
- y: window.scrollY || 0
- };
- } else {
- window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);
- } // Toggle scroll
-
-
- document.body.style.overflow = toggle ? 'hidden' : ''; // Toggle class hook
-
- toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle); // Force full viewport on iPhone X+
-
- if (browser.isIos) {
- var viewport = document.head.querySelector('meta[name="viewport"]');
- var property = 'viewport-fit=cover'; // Inject the viewport meta if required
-
- if (!viewport) {
- viewport = document.createElement('meta');
- viewport.setAttribute('name', 'viewport');
- } // Check if the property already exists
-
-
- var hasProperty = is$1.string(viewport.content) && viewport.content.includes(property);
-
- if (toggle) {
- this.cleanupViewport = !hasProperty;
-
- if (!hasProperty) {
- viewport.content += ",".concat(property);
- }
- } else if (this.cleanupViewport) {
- viewport.content = viewport.content.split(',').filter(function (part) {
- return part.trim() !== property;
- }).join(',');
- }
- } // Toggle button and fire events
-
-
- onChange.call(this);
-}
-
-var Fullscreen =
-/*#__PURE__*/
-function () {
+var Fullscreen = /*#__PURE__*/function () {
function Fullscreen(player) {
var _this = this;
@@ -4113,7 +3963,7 @@ function () {
on.call(this.player, document, this.prefix === 'ms' ? 'MSFullscreenChange' : "".concat(this.prefix, "fullscreenchange"), function () {
// TODO: Filter for target??
- onChange.call(_this);
+ _this.onChange();
}); // Fullscreen toggle on double click
on.call(this.player, this.player.elements.container, 'dblclick', function (event) {
@@ -4123,6 +3973,10 @@ function () {
}
_this.toggle();
+ }); // Tap focus when in fullscreen
+
+ on.call(this, this.player.elements.container, 'keydown', function (event) {
+ return _this.trapFocus(event);
}); // Update the UI
this.update();
@@ -4130,8 +3984,101 @@ function () {
_createClass(Fullscreen, [{
+ key: "onChange",
+ value: function onChange() {
+ if (!this.enabled) {
+ return;
+ } // Update toggle button
+
+
+ var button = this.player.elements.buttons.fullscreen;
+
+ if (is$1.element(button)) {
+ button.pressed = this.active;
+ } // Trigger an event
+
+
+ triggerEvent.call(this.player, this.target, this.active ? 'enterfullscreen' : 'exitfullscreen', true);
+ }
+ }, {
+ key: "toggleFallback",
+ value: function toggleFallback() {
+ var toggle = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+
+ // Store or restore scroll position
+ if (toggle) {
+ this.scrollPosition = {
+ x: window.scrollX || 0,
+ y: window.scrollY || 0
+ };
+ } else {
+ window.scrollTo(this.scrollPosition.x, this.scrollPosition.y);
+ } // Toggle scroll
+
+
+ document.body.style.overflow = toggle ? 'hidden' : ''; // Toggle class hook
+
+ toggleClass(this.target, this.player.config.classNames.fullscreen.fallback, toggle); // Force full viewport on iPhone X+
+
+ if (browser.isIos) {
+ var viewport = document.head.querySelector('meta[name="viewport"]');
+ var property = 'viewport-fit=cover'; // Inject the viewport meta if required
+
+ if (!viewport) {
+ viewport = document.createElement('meta');
+ viewport.setAttribute('name', 'viewport');
+ } // Check if the property already exists
+
+
+ var hasProperty = is$1.string(viewport.content) && viewport.content.includes(property);
+
+ if (toggle) {
+ this.cleanupViewport = !hasProperty;
+
+ if (!hasProperty) {
+ viewport.content += ",".concat(property);
+ }
+ } else if (this.cleanupViewport) {
+ viewport.content = viewport.content.split(',').filter(function (part) {
+ return part.trim() !== property;
+ }).join(',');
+ }
+ } // Toggle button and fire events
+
+
+ this.onChange();
+ } // Trap focus inside container
+
+ }, {
+ key: "trapFocus",
+ value: function trapFocus(event) {
+ // Bail if iOS, not active, not the tab key
+ if (browser.isIos || !this.active || event.key !== 'Tab' || event.keyCode !== 9) {
+ return;
+ } // Get the current focused element
+
+
+ var focused = document.activeElement;
+ var focusable = getElements.call(this.player, 'a[href], button:not(:disabled), input:not(:disabled), [tabindex]');
+
+ var _focusable = _slicedToArray(focusable, 1),
+ first = _focusable[0];
+
+ var last = focusable[focusable.length - 1];
+
+ if (focused === last && !event.shiftKey) {
+ // Move focus to first element that can be tabbed if Shift isn't used
+ first.focus();
+ event.preventDefault();
+ } else if (focused === first && event.shiftKey) {
+ // Move focus to last element that can be tabbed if Shift is used
+ last.focus();
+ event.preventDefault();
+ }
+ } // Update UI
+
+ }, {
key: "update",
- // Update UI
value: function update() {
if (this.enabled) {
var mode;
@@ -4164,9 +4111,11 @@ function () {
if (browser.isIos && this.player.config.fullscreen.iosNative) {
this.target.webkitEnterFullscreen();
} else if (!Fullscreen.native || this.forceFallback) {
- toggleFallback.call(this, true);
+ this.toggleFallback(true);
} else if (!this.prefix) {
- this.target.requestFullscreen();
+ this.target.requestFullscreen({
+ navigationUI: 'hide'
+ });
} else if (!is$1.empty(this.prefix)) {
this.target["".concat(this.prefix, "Request").concat(this.property)]();
}
@@ -4184,7 +4133,7 @@ function () {
this.target.webkitExitFullscreen();
this.player.play();
} else if (!Fullscreen.native || this.forceFallback) {
- toggleFallback.call(this, false);
+ this.toggleFallback(false);
} else if (!this.prefix) {
(document.cancelFullScreen || document.exitFullscreen).call(document);
} else if (!is$1.empty(this.prefix)) {
@@ -4432,7 +4381,12 @@ var ui = {
} // Set property synchronously to respect the call order
- this.media.setAttribute('poster', poster); // Wait until ui is ready
+ this.media.setAttribute('poster', poster); // HTML5 uses native poster attribute
+
+ if (this.isHTML5) {
+ return Promise.resolve(poster);
+ } // Wait until ui is ready
+
return ready.call(this) // Load image
.then(function () {
@@ -4473,6 +4427,7 @@ var ui = {
Object.assign(target, {
pressed: _this3.playing
});
+ target.setAttribute('aria-label', i18n.get(_this3.playing ? 'pause' : 'play', _this3.config));
}); // Only update controls on non timeupdate events
if (is$1.event(event) && event.type === 'timeupdate') {
@@ -4510,9 +4465,7 @@ var ui = {
}
};
-var Listeners =
-/*#__PURE__*/
-function () {
+var Listeners = /*#__PURE__*/function () {
function Listeners(player) {
_classCallCheck(this, Listeners);
@@ -4653,18 +4606,6 @@ function () {
// L key
player.loop = !player.loop;
break;
- // case 73:
- // this.setLoop('start');
- // break;
- // case 76:
- // this.setLoop();
- // break;
- // case 79:
- // this.setLoop('end');
- // break;
-
- default:
- break;
} // Escape is handle natively when in full screen
// So we only need to worry about non native
@@ -4881,19 +4822,15 @@ function () {
on.call(player, player.media, 'durationchange loadeddata loadedmetadata', function (event) {
return controls.durationUpdate.call(player, event);
- }); // Check for audio tracks on load
- // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point
-
- on.call(player, player.media, 'canplay loadeddata', function () {
- toggleHidden(elements.volume, !player.hasAudio);
- toggleHidden(elements.buttons.mute, !player.hasAudio);
}); // Handle the media finishing
on.call(player, player.media, 'ended', function () {
// Show poster on end
if (player.isHTML5 && player.isVideo && player.config.resetOnEnd) {
// Restart
- player.restart();
+ player.restart(); // Call pause otherwise IE11 will start playing the video again
+
+ player.pause();
}
}); // Check for buffer progress
@@ -5006,7 +4943,7 @@ function () {
} // Only call default handler if not prevented in custom handler
- if (returned && is$1.function(defaultHandler)) {
+ if (returned !== false && is$1.function(defaultHandler)) {
defaultHandler.call(player, event);
}
} // Trigger custom and default handlers
@@ -5073,9 +5010,11 @@ function () {
this.bind(elements.buttons.settings, 'click', function (event) {
// Prevent the document click listener closing the menu
event.stopPropagation();
+ event.preventDefault();
controls.toggleMenu.call(player, event);
- }); // Settings menu - keyboard toggle
+ }, null, false); // Can't be passive as we're preventing default
+ // Settings menu - keyboard toggle
// We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus
// https://bugzilla.mozilla.org/show_bug.cgi?id=1220143
@@ -5177,7 +5116,7 @@ function () {
}
}); // Hide thumbnail preview - on mouse click, mouse leave, and video play/seek. All four are required, e.g., for buffering
- this.bind(elements.progress, 'mouseleave click', function () {
+ this.bind(elements.progress, 'mouseleave touchend click', function () {
var previewThumbnails = player.previewThumbnails;
if (previewThumbnails && previewThumbnails.loaded) {
@@ -5394,12 +5333,13 @@ var loadjs_umd = createCommonjsModule(function (module, exports) {
async = args.async,
maxTries = (args.numRetries || 0) + 1,
beforeCallbackFn = args.before || devnull,
+ pathname = path.replace(/[\?|#].*$/, ''),
pathStripped = path.replace(/^(css|img)!/, ''),
isLegacyIECss,
e;
numTries = numTries || 0;
- if (/(^css!|\.css$)/.test(path)) {
+ if (/(^css!|\.css$)/.test(pathname)) {
// css
e = doc.createElement('link');
e.rel = 'stylesheet';
@@ -5412,7 +5352,7 @@ var loadjs_umd = createCommonjsModule(function (module, exports) {
e.rel = 'preload';
e.as = 'style';
}
- } else if (/(^img!|\.(png|gif|jpg|svg)$)/.test(path)) {
+ } else if (/(^img!|\.(png|gif|jpg|svg|webp)$)/.test(pathname)) {
// image
e = doc.createElement('img');
e.src = pathStripped;
@@ -5622,26 +5562,27 @@ function assurePlaybackState(play) {
var vimeo = {
setup: function setup() {
- var _this = this;
+ var player = this; // Add embed class for responsive
- // Add embed class for responsive
- toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set intial ratio
+ toggleClass(player.elements.wrapper, player.config.classNames.embed, true); // Set speed options from config
+
+ player.options.speed = player.config.speed.options; // Set intial ratio
- setAspectRatio.call(this); // Load the SDK if not already
+ setAspectRatio.call(player); // Load the SDK if not already
if (!is$1.object(window.Vimeo)) {
- loadScript(this.config.urls.vimeo.sdk).then(function () {
- vimeo.ready.call(_this);
+ loadScript(player.config.urls.vimeo.sdk).then(function () {
+ vimeo.ready.call(player);
}).catch(function (error) {
- _this.debug.warn('Vimeo SDK (player.js) failed to load', error);
+ player.debug.warn('Vimeo SDK (player.js) failed to load', error);
});
} else {
- vimeo.ready.call(this);
+ vimeo.ready.call(player);
}
},
// API Ready
ready: function ready() {
- var _this2 = this;
+ var _this = this;
var player = this;
var config = player.config.vimeo; // Get Vimeo params for the iframe
@@ -5667,7 +5608,12 @@ var vimeo = {
iframe.setAttribute('src', src);
iframe.setAttribute('allowfullscreen', '');
iframe.setAttribute('allowtransparency', '');
- iframe.setAttribute('allow', 'autoplay'); // Get poster, if already set
+ iframe.setAttribute('allow', 'autoplay'); // Set the referrer policy if required
+
+ if (!is$1.empty(config.referrerPolicy)) {
+ iframe.setAttribute('referrerPolicy', config.referrerPolicy);
+ } // Get poster, if already set
+
var poster = player.poster; // Inject the package
@@ -5760,11 +5706,6 @@ var vimeo = {
player.embed.setPlaybackRate(input).then(function () {
speed = input;
triggerEvent.call(player, player.media, 'ratechange');
- }).catch(function (error) {
- // Hide menu item (and menu if empty)
- if (error.name === 'Error') {
- controls.setSpeedMenu.call(player, []);
- }
});
}
}); // Volume
@@ -5814,7 +5755,7 @@ var vimeo = {
currentSrc = value;
controls.setDownloadUrl.call(player);
}).catch(function (error) {
- _this2.debug.warn(error);
+ _this.debug.warn(error);
});
Object.defineProperty(player.media, 'currentSrc', {
get: function get() {
@@ -5834,7 +5775,7 @@ var vimeo = {
height = _dimensions[1];
player.embed.ratio = [width, height];
- setAspectRatio.call(_this2);
+ setAspectRatio.call(_this);
}); // Set autopause
player.embed.setAutopause(player.config.autopause).then(function (state) {
@@ -5843,7 +5784,7 @@ var vimeo = {
player.embed.getVideoTitle().then(function (title) {
player.config.title = title;
- ui.setTitle.call(_this2);
+ ui.setTitle.call(_this);
}); // Get current time
player.embed.getCurrentTime().then(function (value) {
@@ -5885,6 +5826,12 @@ var vimeo = {
frame.setAttribute('tabindex', -1);
}
});
+ player.embed.on('bufferstart', function () {
+ triggerEvent.call(player, player.media, 'waiting');
+ });
+ player.embed.on('bufferend', function () {
+ triggerEvent.call(player, player.media, 'playing');
+ });
player.embed.on('play', function () {
assurePlaybackState.call(player, true);
triggerEvent.call(player, player.media, 'playing');
@@ -6212,7 +6159,11 @@ var youtube = {
}
}); // Get available speeds
- player.options.speed = instance.getAvailablePlaybackRates(); // Set the tabindex to avoid focus entering iframe
+ var speeds = instance.getAvailablePlaybackRates(); // Filter based on config
+
+ player.options.speed = speeds.filter(function (s) {
+ return player.config.speed.options.includes(s);
+ }); // Set the tabindex to avoid focus entering iframe
if (player.supported.ui) {
player.media.setAttribute('tabindex', -1);
@@ -6318,7 +6269,9 @@ var youtube = {
assurePlaybackState$1.call(player, false);
break;
- default:
+ case 3:
+ // Trigger waiting event to add loading classes to container as the video buffers.
+ triggerEvent.call(player, player.media, 'waiting');
break;
}
@@ -6360,14 +6313,16 @@ var media = {
wrap(this.media, this.elements.wrapper); // Faux poster container
- this.elements.poster = createElement('div', {
- class: this.config.classNames.poster
- });
- this.elements.wrapper.appendChild(this.elements.poster);
+ if (this.isEmbed) {
+ this.elements.poster = createElement('div', {
+ class: this.config.classNames.poster
+ });
+ this.elements.wrapper.appendChild(this.elements.poster);
+ }
}
if (this.isHTML5) {
- html5.extend.call(this);
+ html5.setup.call(this);
} else if (this.isYouTube) {
youtube.setup.call(this);
} else if (this.isVimeo) {
@@ -6390,9 +6345,7 @@ var destroy = function destroy(instance) {
instance.elements.container.remove();
};
-var Ads =
-/*#__PURE__*/
-function () {
+var Ads = /*#__PURE__*/function () {
/**
* Ads constructor.
* @param {Object} player
@@ -6733,9 +6686,6 @@ function () {
}
break;
-
- default:
- break;
}
}
/**
@@ -7007,7 +6957,7 @@ function () {
cb: Date.now(),
AV_WIDTH: 640,
AV_HEIGHT: 480,
- AV_CDIM2: this.publisherId
+ AV_CDIM2: config.publisherId
};
var base = 'https://go.aniview.com/api/adserver6/vast/';
return "".concat(base, "?").concat(buildUrlParams(params));
@@ -7072,9 +7022,22 @@ var parseVtt = function parseVtt(vttDataString) {
*/
-var PreviewThumbnails =
-/*#__PURE__*/
-function () {
+var fitRatio = function fitRatio(ratio, outer) {
+ var targetRatio = outer.width / outer.height;
+ var result = {};
+
+ if (ratio > targetRatio) {
+ result.width = outer.width;
+ result.height = 1 / ratio * outer.width;
+ } else {
+ result.height = outer.height;
+ result.width = ratio * outer.height;
+ }
+
+ return result;
+};
+
+var PreviewThumbnails = /*#__PURE__*/function () {
/**
* PreviewThumbnails constructor.
* @param {Plyr} player
@@ -7101,7 +7064,7 @@ function () {
value: function load() {
var _this = this;
- // Togglethe regular seek tooltip
+ // Toggle the regular seek tooltip
if (this.player.elements.display.seekTooltip) {
this.player.elements.display.seekTooltip.hidden = this.enabled;
}
@@ -7242,8 +7205,8 @@ function () {
}, {
key: "startScrubbing",
value: function startScrubbing(event) {
- // Only act on left mouse button (0), or touch device (event.button is false)
- if (event.button === false || event.button === 0) {
+ // Only act on left mouse button (0), or touch device (event.button does not exist or is false)
+ if (is$1.nullOrUndefined(event.button) || event.button === false || event.button === 0) {
this.mouseDown = true; // Wait until media has a duration
if (this.player.media.duration) {
@@ -7329,6 +7292,17 @@ function () {
this.player.elements.wrapper.appendChild(this.elements.scrubbing.container);
}
}, {
+ key: "destroy",
+ value: function destroy() {
+ if (this.elements.thumb.container) {
+ this.elements.thumb.container.remove();
+ }
+
+ if (this.elements.scrubbing.container) {
+ this.elements.scrubbing.container.remove();
+ }
+ }
+ }, {
key: "showImageAtCurrentTime",
value: function showImageAtCurrentTime() {
var _this6 = this;
@@ -7573,7 +7547,7 @@ function () {
}, {
key: "determineContainerAutoSizing",
value: function determineContainerAutoSizing() {
- if (this.elements.thumb.imageContainer.clientHeight > 20) {
+ if (this.elements.thumb.imageContainer.clientHeight > 20 || this.elements.thumb.imageContainer.clientWidth > 20) {
// This will prevent auto sizing in this.setThumbContainerSizeAndPos()
this.sizeSpecifiedInCSS = true;
}
@@ -7586,6 +7560,13 @@ function () {
var thumbWidth = Math.floor(this.thumbContainerHeight * this.thumbAspectRatio);
this.elements.thumb.imageContainer.style.height = "".concat(this.thumbContainerHeight, "px");
this.elements.thumb.imageContainer.style.width = "".concat(thumbWidth, "px");
+ } else if (this.elements.thumb.imageContainer.clientHeight > 20 && this.elements.thumb.imageContainer.clientWidth < 20) {
+ var _thumbWidth = Math.floor(this.elements.thumb.imageContainer.clientHeight * this.thumbAspectRatio);
+
+ this.elements.thumb.imageContainer.style.width = "".concat(_thumbWidth, "px");
+ } else if (this.elements.thumb.imageContainer.clientHeight < 20 && this.elements.thumb.imageContainer.clientWidth > 20) {
+ var thumbHeight = Math.floor(this.elements.thumb.imageContainer.clientWidth / this.thumbAspectRatio);
+ this.elements.thumb.imageContainer.style.height = "".concat(thumbHeight, "px");
}
this.setThumbContainerPos();
@@ -7616,9 +7597,15 @@ function () {
}, {
key: "setScrubbingContainerSize",
value: function setScrubbingContainerSize() {
- this.elements.scrubbing.container.style.width = "".concat(this.player.media.clientWidth, "px"); // Can't use media.clientHeight - html5 video goes big and does black bars above and below
-
- this.elements.scrubbing.container.style.height = "".concat(this.player.media.clientWidth / this.thumbAspectRatio, "px");
+ var _fitRatio = fitRatio(this.thumbAspectRatio, {
+ width: this.player.media.clientWidth,
+ height: this.player.media.clientHeight
+ }),
+ width = _fitRatio.width,
+ height = _fitRatio.height;
+
+ this.elements.scrubbing.container.style.width = "".concat(width, "px");
+ this.elements.scrubbing.container.style.height = "".concat(height, "px");
} // Sprites need to be offset to the correct location
}, {
@@ -7631,9 +7618,9 @@ function () {
var multiplier = this.thumbContainerHeight / frame.h; // eslint-disable-next-line no-param-reassign
- previewImage.style.height = "".concat(Math.floor(previewImage.naturalHeight * multiplier), "px"); // eslint-disable-next-line no-param-reassign
+ previewImage.style.height = "".concat(previewImage.naturalHeight * multiplier, "px"); // eslint-disable-next-line no-param-reassign
- previewImage.style.width = "".concat(Math.floor(previewImage.naturalWidth * multiplier), "px"); // eslint-disable-next-line no-param-reassign
+ previewImage.style.width = "".concat(previewImage.naturalWidth * multiplier, "px"); // eslint-disable-next-line no-param-reassign
previewImage.style.left = "-".concat(frame.x * multiplier, "px"); // eslint-disable-next-line no-param-reassign
@@ -7671,8 +7658,18 @@ function () {
key: "thumbContainerHeight",
get: function get() {
if (this.mouseDown) {
- // Can't use media.clientHeight - HTML5 video goes big and does black bars above and below
- return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio);
+ var _fitRatio2 = fitRatio(this.thumbAspectRatio, {
+ width: this.player.media.clientWidth,
+ height: this.player.media.clientHeight
+ }),
+ height = _fitRatio2.height;
+
+ return height;
+ } // If css is used this needs to return the css height for sprites to work (see setImageSizeAndOffset)
+
+
+ if (this.sizeSpecifiedInCSS) {
+ return this.elements.thumb.imageContainer.clientHeight;
}
return Math.floor(this.player.media.clientWidth / this.thumbAspectRatio / 4);
@@ -7822,11 +7819,22 @@ var source = {
if (_this2.isHTML5) {
_this2.media.load();
- } // Reload thumbnails
+ } // Update previewThumbnails config & reload plugin
+
+ if (!is$1.empty(input.previewThumbnails)) {
+ Object.assign(_this2.config.previewThumbnails, input.previewThumbnails); // Cleanup previewThumbnails plugin if it was loaded
- if (_this2.previewThumbnails) {
- _this2.previewThumbnails.load();
+ if (_this2.previewThumbnails && _this2.previewThumbnails.loaded) {
+ _this2.previewThumbnails.destroy();
+
+ _this2.previewThumbnails = null;
+ } // Create new instance if it is still enabled
+
+
+ if (_this2.config.previewThumbnails.enabled) {
+ _this2.previewThumbnails = new PreviewThumbnails(_this2);
+ }
} // Update the fullscreen support
@@ -7858,9 +7866,7 @@ function clamp() {
// const globals = new WeakMap();
// Plyr instance
-var Plyr =
-/*#__PURE__*/
-function () {
+var Plyr = /*#__PURE__*/function () {
function Plyr(target, options) {
var _this = this;
@@ -8156,10 +8162,10 @@ function () {
key: "pause",
value: function pause() {
if (!this.playing || !is$1.function(this.media.pause)) {
- return;
+ return null;
}
- this.media.pause();
+ return this.media.pause();
}
/**
* Get playing state
@@ -8177,10 +8183,10 @@ function () {
var toggle = is$1.boolean(input) ? input : !this.playing;
if (toggle) {
- this.play();
- } else {
- this.pause();
+ return this.play();
}
+
+ return this.pause();
}
/**
* Stop playback
@@ -8213,7 +8219,7 @@ function () {
}, {
key: "rewind",
value: function rewind(seekTime) {
- this.currentTime = this.currentTime - (is$1.number(seekTime) ? seekTime : this.config.seekTime);
+ this.currentTime -= is$1.number(seekTime) ? seekTime : this.config.seekTime;
}
/**
* Fast forward
@@ -8223,7 +8229,7 @@ function () {
}, {
key: "forward",
value: function forward(seekTime) {
- this.currentTime = this.currentTime + (is$1.number(seekTime) ? seekTime : this.config.seekTime);
+ this.currentTime += is$1.number(seekTime) ? seekTime : this.config.seekTime;
}
/**
* Seek to a time