aboutsummaryrefslogtreecommitdiffstats
path: root/demo/dist/demo.js
diff options
context:
space:
mode:
authorSam Potts <sam@potts.es>2019-04-25 12:14:48 +1000
committerSam Potts <sam@potts.es>2019-04-25 12:14:48 +1000
commit0694e586502f7ce85ce7858b67d515403b48c87e (patch)
tree0257e2274dc3b3b897e596dfbc77682df8855ecf /demo/dist/demo.js
parente644eeb5b62e6e2eb915d5915cb65ba8af88c05e (diff)
downloadplyr-0694e586502f7ce85ce7858b67d515403b48c87e.tar.lz
plyr-0694e586502f7ce85ce7858b67d515403b48c87e.tar.xz
plyr-0694e586502f7ce85ce7858b67d515403b48c87e.zip
v3.5.4
Diffstat (limited to 'demo/dist/demo.js')
-rw-r--r--demo/dist/demo.js895
1 files changed, 507 insertions, 388 deletions
diff --git a/demo/dist/demo.js b/demo/dist/demo.js
index f83878b7..97c120e0 100644
--- a/demo/dist/demo.js
+++ b/demo/dist/demo.js
@@ -4536,6 +4536,47 @@ typeof navigator === "object" && (function () {
}).then(function () {});
}
+ function cloneDeep(object) {
+ return JSON.parse(JSON.stringify(object));
+ } // Get a nested value in an object
+
+ function getDeep(object, path) {
+ return path.split('.').reduce(function (obj, key) {
+ return obj && obj[key];
+ }, object);
+ } // Deep extend destination object with N more objects
+
+ function extend() {
+ var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+ for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ sources[_key - 1] = arguments[_key];
+ }
+
+ if (!sources.length) {
+ return target;
+ }
+
+ var source = sources.shift();
+
+ if (!is$1.object(source)) {
+ return target;
+ }
+
+ Object.keys(source).forEach(function (key) {
+ if (is$1.object(source[key])) {
+ if (!Object.keys(target).includes(key)) {
+ Object.assign(target, _defineProperty({}, key, {}));
+ }
+
+ extend(target[key], source[key]);
+ } else {
+ Object.assign(target, _defineProperty({}, key, source[key]));
+ }
+ });
+ return extend.apply(void 0, [target].concat(sources));
+ }
+
function wrap(elements, wrapper) {
// Convert `elements` to an array, if necessary.
var targets = elements.length ? elements : [elements]; // Loops backwards to prevent having to clone the wrapper on the
@@ -4659,7 +4700,7 @@ typeof navigator === "object" && (function () {
}
var attributes = {};
- var existing = existingAttributes;
+ var existing = extend({}, existingAttributes);
sel.split(',').forEach(function (s) {
// Remove whitespace
var selector = s.trim();
@@ -4667,7 +4708,10 @@ typeof navigator === "object" && (function () {
var stripped = selector.replace(/[[\]]/g, ''); // Get the parts and value
var parts = stripped.split('=');
- var key = parts[0];
+
+ var _parts = _slicedToArray(parts, 1),
+ key = _parts[0];
+
var value = parts.length > 1 ? parts[1].replace(/["']/g, '') : ''; // Get the first character
var start = selector.charAt(0);
@@ -4675,11 +4719,12 @@ typeof navigator === "object" && (function () {
switch (start) {
case '.':
// Add to existing classname
- if (is$1.object(existing) && is$1.string(existing.class)) {
- existing.class += " ".concat(className);
+ if (is$1.string(existing.class)) {
+ attributes.class = "".concat(existing.class, " ").concat(className);
+ } else {
+ attributes.class = className;
}
- attributes.class = className;
break;
case '#':
@@ -4696,7 +4741,7 @@ typeof navigator === "object" && (function () {
break;
}
});
- return attributes;
+ return extend(existing, attributes);
} // Toggle hidden
function toggleHidden(element, hidden) {
@@ -4992,8 +5037,16 @@ typeof navigator === "object" && (function () {
} // Get from embed
- if (ratio === null && !is$1.empty(this.embed) && is$1.string(this.embed.ratio)) {
- ratio = parse(this.embed.ratio);
+ if (ratio === null && !is$1.empty(this.embed) && is$1.array(this.embed.ratio)) {
+ ratio = this.embed.ratio;
+ } // Get from HTML5 video
+
+
+ if (ratio === null && this.isHTML5) {
+ var _this$media = this.media,
+ videoWidth = _this$media.videoWidth,
+ videoHeight = _this$media.videoHeight;
+ ratio = reduceAspectRatio([videoWidth, videoHeight]);
}
return ratio;
@@ -5160,47 +5213,6 @@ typeof navigator === "object" && (function () {
});
}
- function cloneDeep(object) {
- return JSON.parse(JSON.stringify(object));
- } // Get a nested value in an object
-
- function getDeep(object, path) {
- return path.split('.').reduce(function (obj, key) {
- return obj && obj[key];
- }, object);
- } // Deep extend destination object with N more objects
-
- function extend() {
- var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
-
- for (var _len = arguments.length, sources = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
- sources[_key - 1] = arguments[_key];
- }
-
- if (!sources.length) {
- return target;
- }
-
- var source = sources.shift();
-
- if (!is$1.object(source)) {
- return target;
- }
-
- Object.keys(source).forEach(function (key) {
- if (is$1.object(source[key])) {
- if (!Object.keys(target).includes(key)) {
- Object.assign(target, _defineProperty({}, key, {}));
- }
-
- extend(target[key], source[key]);
- } else {
- Object.assign(target, _defineProperty({}, key, source[key]));
- }
- });
- return extend.apply(void 0, [target].concat(sources));
- }
-
// ==========================================================================
function generateId(prefix) {
@@ -5647,7 +5659,9 @@ typeof navigator === "object" && (function () {
},
// Create a <button>
createButton: function createButton(buttonType, attr) {
- var attributes = Object.assign({}, attr);
+ var _this = this;
+
+ var attributes = extend({}, attr);
var type = toCamelCase(buttonType);
var props = {
element: 'button',
@@ -5670,8 +5684,12 @@ typeof navigator === "object" && (function () {
if (Object.keys(attributes).includes('class')) {
- if (!attributes.class.includes(this.config.classNames.control)) {
- attributes.class += " ".concat(this.config.classNames.control);
+ if (!attributes.class.split(' ').some(function (c) {
+ return c === _this.config.classNames.control;
+ })) {
+ extend(attributes, {
+ class: "".concat(attributes.class, " ").concat(this.config.classNames.control)
+ });
}
} else {
attributes.class = this.config.classNames.control;
@@ -5815,10 +5833,10 @@ typeof navigator === "object" && (function () {
return progress;
},
// Create time display
- createTime: function createTime(type) {
- var attributes = getAttributesFromSelector(this.config.selectors.display[type]);
+ createTime: function createTime(type, attrs) {
+ var attributes = getAttributesFromSelector(this.config.selectors.display[type], attrs);
var container = createElement('div', extend(attributes, {
- class: "".concat(this.config.classNames.display.time, " ").concat(attributes.class ? attributes.class : '').trim(),
+ class: "".concat(attributes.class ? attributes.class : '', " ").concat(this.config.classNames.display.time, " ").trim(),
'aria-label': i18n.get(type, this.config)
}), '00:00'); // Reference for updates
@@ -5829,7 +5847,7 @@ typeof navigator === "object" && (function () {
// We have to bind to keyup otherwise Firefox triggers a click when a keydown event handler shifts focus
// https://bugzilla.mozilla.org/show_bug.cgi?id=1220143
bindMenuItemShortcuts: function bindMenuItemShortcuts(menuItem, type) {
- var _this = this;
+ var _this2 = this;
// Navigate through menus via arrow keys and space
on(menuItem, 'keydown keyup', function (event) {
@@ -5849,7 +5867,7 @@ typeof navigator === "object" && (function () {
var isRadioButton = matches$1(menuItem, '[role="menuitemradio"]'); // Show the respective menu
if (!isRadioButton && [32, 39].includes(event.which)) {
- controls.showMenuPanel.call(_this, type, true);
+ controls.showMenuPanel.call(_this2, type, true);
} else {
var target;
@@ -5868,7 +5886,7 @@ typeof navigator === "object" && (function () {
}
}
- setFocus.call(_this, target, true);
+ setFocus.call(_this2, target, true);
}
}
}, false); // Enter will fire a `click` event but we still need to manage focus
@@ -5879,12 +5897,12 @@ typeof navigator === "object" && (function () {
return;
}
- controls.focusFirstMenuItem.call(_this, null, true);
+ controls.focusFirstMenuItem.call(_this2, null, true);
});
},
// Create a settings menu item
createMenuItem: function createMenuItem(_ref) {
- var _this2 = this;
+ var _this3 = this;
var value = _ref.value,
list = _ref.list,
@@ -5941,22 +5959,22 @@ typeof navigator === "object" && (function () {
switch (type) {
case 'language':
- _this2.currentTrack = Number(value);
+ _this3.currentTrack = Number(value);
break;
case 'quality':
- _this2.quality = value;
+ _this3.quality = value;
break;
case 'speed':
- _this2.speed = parseFloat(value);
+ _this3.speed = parseFloat(value);
break;
default:
break;
}
- controls.showMenuPanel.call(_this2, 'home', is$1.keyboardEvent(event));
+ controls.showMenuPanel.call(_this3, 'home', is$1.keyboardEvent(event));
}, type, false);
controls.bindMenuItemShortcuts.call(this, menuItem, type);
list.appendChild(menuItem);
@@ -6020,7 +6038,7 @@ typeof navigator === "object" && (function () {
},
// Update <progress> elements
updateProgress: function updateProgress(event) {
- var _this3 = this;
+ var _this4 = this;
if (!this.supported.ui || !is$1.event(event)) {
return;
@@ -6030,7 +6048,7 @@ typeof navigator === "object" && (function () {
var setProgress = function setProgress(target, input) {
var value = is$1.number(input) ? input : 0;
- var progress = is$1.element(target) ? target : _this3.elements.display.buffer; // Update value and label
+ var progress = is$1.element(target) ? target : _this4.elements.display.buffer; // Update value and label
if (is$1.element(progress)) {
progress.value = value; // Update text label inside
@@ -6102,7 +6120,7 @@ typeof navigator === "object" && (function () {
},
// Update hover tooltip for seeking
updateSeekTooltip: function updateSeekTooltip(event) {
- var _this4 = this;
+ var _this5 = this;
// Bail if setting not true
if (!this.config.tooltips.seek || !is$1.element(this.elements.inputs.seek) || !is$1.element(this.elements.display.seekTooltip) || this.duration === 0) {
@@ -6115,7 +6133,7 @@ typeof navigator === "object" && (function () {
var visible = "".concat(this.config.classNames.tooltip, "--visible");
var toggle = function toggle(_toggle) {
- toggleClass(_this4.elements.display.seekTooltip, visible, _toggle);
+ toggleClass(_this5.elements.display.seekTooltip, visible, _toggle);
}; // Hide on touch
@@ -6281,7 +6299,7 @@ typeof navigator === "object" && (function () {
},
// Set the quality menu
setQualityMenu: function setQualityMenu(options) {
- var _this5 = this;
+ var _this6 = this;
// Menu required
if (!is$1.element(this.elements.settings.panels.quality)) {
@@ -6293,7 +6311,7 @@ typeof navigator === "object" && (function () {
if (is$1.array(options)) {
this.options.quality = dedupe(options).filter(function (quality) {
- return _this5.config.quality.options.includes(quality);
+ return _this6.config.quality.options.includes(quality);
});
} // Toggle the pane and tab
@@ -6311,25 +6329,25 @@ typeof navigator === "object" && (function () {
var getBadge = function getBadge(quality) {
- var label = i18n.get("qualityBadge.".concat(quality), _this5.config);
+ var label = i18n.get("qualityBadge.".concat(quality), _this6.config);
if (!label.length) {
return null;
}
- return controls.createBadge.call(_this5, label);
+ return controls.createBadge.call(_this6, label);
}; // Sort options by the config and then render options
this.options.quality.sort(function (a, b) {
- var sorting = _this5.config.quality.options;
+ var sorting = _this6.config.quality.options;
return sorting.indexOf(a) > sorting.indexOf(b) ? 1 : -1;
}).forEach(function (quality) {
- controls.createMenuItem.call(_this5, {
+ controls.createMenuItem.call(_this6, {
value: quality,
list: list,
type: type,
- title: controls.getLabel.call(_this5, 'quality', quality),
+ title: controls.getLabel.call(_this6, 'quality', quality),
badge: getBadge(quality)
});
});
@@ -6375,7 +6393,7 @@ typeof navigator === "object" && (function () {
// TODO: rework this to user the getter in the API?
// Set a list of available captions languages
setCaptionsMenu: function setCaptionsMenu() {
- var _this6 = this;
+ var _this7 = this;
// Menu required
if (!is$1.element(this.elements.settings.panels.captions)) {
@@ -6402,9 +6420,9 @@ typeof navigator === "object" && (function () {
var options = tracks.map(function (track, value) {
return {
value: value,
- checked: _this6.captions.toggled && _this6.currentTrack === value,
- title: captions.getLabel.call(_this6, track),
- badge: track.language && controls.createBadge.call(_this6, track.language.toUpperCase()),
+ checked: _this7.captions.toggled && _this7.currentTrack === value,
+ title: captions.getLabel.call(_this7, track),
+ badge: track.language && controls.createBadge.call(_this7, track.language.toUpperCase()),
list: list,
type: 'language'
};
@@ -6423,7 +6441,7 @@ typeof navigator === "object" && (function () {
},
// Set a list of available captions languages
setSpeedMenu: function setSpeedMenu(options) {
- var _this7 = this;
+ var _this8 = this;
// Menu required
if (!is$1.element(this.elements.settings.panels.speed)) {
@@ -6441,7 +6459,7 @@ typeof navigator === "object" && (function () {
this.options.speed = this.options.speed.filter(function (speed) {
- return _this7.config.speed.options.includes(speed);
+ return _this8.config.speed.options.includes(speed);
}); // Toggle the pane and tab
var toggle = !is$1.empty(this.options.speed) && this.options.speed.length > 1;
@@ -6457,11 +6475,11 @@ typeof navigator === "object" && (function () {
this.options.speed.forEach(function (speed) {
- controls.createMenuItem.call(_this7, {
+ controls.createMenuItem.call(_this8, {
value: speed,
list: list,
type: type,
- title: controls.getLabel.call(_this7, 'speed', speed)
+ title: controls.getLabel.call(_this8, 'speed', speed)
});
});
controls.updateSetting.call(this, type, list);
@@ -6511,7 +6529,10 @@ typeof navigator === "object" && (function () {
} else if (is$1.keyboardEvent(input) && input.which === 27) {
show = false;
} else if (is$1.event(input)) {
- var isMenuItem = popup.contains(input.target); // If the click was inside the menu or if the click
+ // If Plyr is in a shadowDOM, the event target is set to the component, instead of the
+ // Element in the shadowDOM. The path, if available, is complete.
+ var target = is$1.function(input.composedPath) ? input.composedPath()[0] : input.target;
+ var isMenuItem = popup.contains(target); // If the click was inside the menu or if the click
// wasn't the button or menu item and we're trying to
// show the menu (a doc click shouldn't show the menu)
@@ -6554,11 +6575,11 @@ typeof navigator === "object" && (function () {
},
// Show a panel in the menu
showMenuPanel: function showMenuPanel() {
- var _this8 = this;
+ var _this9 = this;
var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
var tabFocus = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
- var target = document.getElementById("plyr-settings-".concat(this.id, "-").concat(type)); // Nothing to show, bail
+ var target = this.elements.container.querySelector("#plyr-settings-".concat(this.id, "-").concat(type)); // Nothing to show, bail
if (!is$1.element(target)) {
return;
@@ -6587,7 +6608,7 @@ typeof navigator === "object" && (function () {
container.style.width = '';
container.style.height = ''; // Only listen once
- off.call(_this8, container, transitionEndEvent, restore);
+ off.call(_this9, container, transitionEndEvent, restore);
}; // Listen for the transition finishing and restore auto height/width
@@ -6604,265 +6625,293 @@ typeof navigator === "object" && (function () {
controls.focusFirstMenuItem.call(this, target, tabFocus);
},
- // Set the download link
- setDownloadLink: function setDownloadLink() {
+ // Set the download URL
+ setDownloadUrl: function setDownloadUrl() {
var button = this.elements.buttons.download; // Bail if no button
if (!is$1.element(button)) {
return;
- } // Set download link
+ } // Set attribute
button.setAttribute('href', this.download);
},
// Build the default HTML
- // TODO: Set order based on order in the config.controls array?
create: function create(data) {
- var _this9 = this;
-
- // Create the container
- var container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper)); // Restart button
-
- if (this.config.controls.includes('restart')) {
- container.appendChild(controls.createButton.call(this, 'restart'));
- } // Rewind button
-
+ var _this10 = this;
- if (this.config.controls.includes('rewind')) {
- container.appendChild(controls.createButton.call(this, 'rewind'));
- } // Play/Pause button
+ var bindMenuItemShortcuts = controls.bindMenuItemShortcuts,
+ createButton = controls.createButton,
+ createProgress = controls.createProgress,
+ createRange = controls.createRange,
+ createTime = controls.createTime,
+ setQualityMenu = controls.setQualityMenu,
+ setSpeedMenu = controls.setSpeedMenu,
+ showMenuPanel = controls.showMenuPanel;
+ this.elements.controls = null; // Larger overlaid play button
+ if (this.config.controls.includes('play-large')) {
+ this.elements.container.appendChild(createButton.call(this, 'play-large'));
+ } // Create the container
- if (this.config.controls.includes('play')) {
- container.appendChild(controls.createButton.call(this, 'play'));
- } // Fast forward button
+ var container = createElement('div', getAttributesFromSelector(this.config.selectors.controls.wrapper));
+ this.elements.controls = container; // Default item attributes
- if (this.config.controls.includes('fast-forward')) {
- container.appendChild(controls.createButton.call(this, 'fast-forward'));
- } // Progress
+ var defaultAttributes = {
+ class: 'plyr__controls__item'
+ }; // Loop through controls in order
+ dedupe(this.config.controls).forEach(function (control) {
+ // Restart button
+ if (control === 'restart') {
+ container.appendChild(createButton.call(_this10, 'restart', defaultAttributes));
+ } // Rewind button
- if (this.config.controls.includes('progress')) {
- var progress = createElement('div', getAttributesFromSelector(this.config.selectors.progress)); // Seek range slider
- progress.appendChild(controls.createRange.call(this, 'seek', {
- id: "plyr-seek-".concat(data.id)
- })); // Buffer progress
+ if (control === 'rewind') {
+ container.appendChild(createButton.call(_this10, 'rewind', defaultAttributes));
+ } // Play/Pause button
- progress.appendChild(controls.createProgress.call(this, 'buffer')); // TODO: Add loop display indicator
- // Seek tooltip
- if (this.config.tooltips.seek) {
- var tooltip = createElement('span', {
- class: this.config.classNames.tooltip
- }, '00:00');
- progress.appendChild(tooltip);
- this.elements.display.seekTooltip = tooltip;
- }
+ if (control === 'play') {
+ container.appendChild(createButton.call(_this10, 'play', defaultAttributes));
+ } // Fast forward button
- this.elements.progress = progress;
- container.appendChild(this.elements.progress);
- } // Media current time display
+ if (control === 'fast-forward') {
+ container.appendChild(createButton.call(_this10, 'fast-forward', defaultAttributes));
+ } // Progress
- if (this.config.controls.includes('current-time')) {
- container.appendChild(controls.createTime.call(this, 'currentTime'));
- } // Media duration display
+ if (control === 'progress') {
+ var progressContainer = createElement('div', {
+ class: "".concat(defaultAttributes.class, " plyr__progress__container")
+ });
+ var progress = createElement('div', getAttributesFromSelector(_this10.config.selectors.progress)); // Seek range slider
- if (this.config.controls.includes('duration')) {
- container.appendChild(controls.createTime.call(this, 'duration'));
- } // Volume controls
+ progress.appendChild(createRange.call(_this10, 'seek', {
+ id: "plyr-seek-".concat(data.id)
+ })); // Buffer progress
+ progress.appendChild(createProgress.call(_this10, 'buffer')); // TODO: Add loop display indicator
+ // Seek tooltip
- if (this.config.controls.includes('mute') || this.config.controls.includes('volume')) {
- var volume = createElement('div', {
- class: 'plyr__volume'
- }); // Toggle mute button
+ if (_this10.config.tooltips.seek) {
+ var tooltip = createElement('span', {
+ class: _this10.config.classNames.tooltip
+ }, '00:00');
+ progress.appendChild(tooltip);
+ _this10.elements.display.seekTooltip = tooltip;
+ }
- if (this.config.controls.includes('mute')) {
- volume.appendChild(controls.createButton.call(this, 'mute'));
- } // Volume range control
+ _this10.elements.progress = progress;
+ progressContainer.appendChild(_this10.elements.progress);
+ container.appendChild(progressContainer);
+ } // Media current time display
- if (this.config.controls.includes('volume')) {
- // Set the attributes
- var attributes = {
- max: 1,
- step: 0.05,
- value: this.config.volume
- }; // Create the volume range slider
+ if (control === 'current-time') {
+ container.appendChild(createTime.call(_this10, 'currentTime', defaultAttributes));
+ } // Media duration display
- volume.appendChild(controls.createRange.call(this, 'volume', extend(attributes, {
- id: "plyr-volume-".concat(data.id)
- })));
- this.elements.volume = volume;
- }
- container.appendChild(volume);
- } // Toggle captions button
+ if (control === 'duration') {
+ container.appendChild(createTime.call(_this10, 'duration', defaultAttributes));
+ } // Volume controls
- if (this.config.controls.includes('captions')) {
- container.appendChild(controls.createButton.call(this, 'captions'));
- } // Settings button / menu
+ if (control === 'mute' || control === 'volume') {
+ var volume = _this10.elements.volume; // Create the volume container if needed
+ if (!is$1.element(volume) || !container.contains(volume)) {
+ volume = createElement('div', extend({}, defaultAttributes, {
+ class: "".concat(defaultAttributes.class, " plyr__volume").trim()
+ }));
+ _this10.elements.volume = volume;
+ container.appendChild(volume);
+ } // Toggle mute button
- if (this.config.controls.includes('settings') && !is$1.empty(this.config.settings)) {
- var control = createElement('div', {
- class: 'plyr__menu',
- hidden: ''
- });
- control.appendChild(controls.createButton.call(this, 'settings', {
- 'aria-haspopup': true,
- 'aria-controls': "plyr-settings-".concat(data.id),
- 'aria-expanded': false
- }));
- var popup = createElement('div', {
- class: 'plyr__menu__container',
- id: "plyr-settings-".concat(data.id),
- hidden: ''
- });
- var inner = createElement('div');
- var home = createElement('div', {
- id: "plyr-settings-".concat(data.id, "-home")
- }); // Create the menu
- var menu = createElement('div', {
- role: 'menu'
- });
- home.appendChild(menu);
- inner.appendChild(home);
- this.elements.settings.panels.home = home; // Build the menu items
-
- this.config.settings.forEach(function (type) {
- // TODO: bundle this with the createMenuItem helper and bindings
- var menuItem = createElement('button', extend(getAttributesFromSelector(_this9.config.selectors.buttons.settings), {
- type: 'button',
- class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--forward"),
- role: 'menuitem',
- 'aria-haspopup': true,
- hidden: ''
- })); // Bind menu shortcuts for keyboard users
+ if (control === 'mute') {
+ volume.appendChild(createButton.call(_this10, 'mute'));
+ } // Volume range control
- controls.bindMenuItemShortcuts.call(_this9, menuItem, type); // Show menu on click
- on(menuItem, 'click', function () {
- controls.showMenuPanel.call(_this9, type, false);
- });
- var flex = createElement('span', null, i18n.get(type, _this9.config));
- var value = createElement('span', {
- class: _this9.config.classNames.menu.value
- }); // Speed contains HTML entities
-
- value.innerHTML = data[type];
- flex.appendChild(value);
- menuItem.appendChild(flex);
- menu.appendChild(menuItem); // Build the panes
-
- var pane = createElement('div', {
- id: "plyr-settings-".concat(data.id, "-").concat(type),
- hidden: ''
- }); // Back button
+ if (control === 'volume') {
+ // Set the attributes
+ var attributes = {
+ max: 1,
+ step: 0.05,
+ value: _this10.config.volume
+ }; // Create the volume range slider
- var backButton = createElement('button', {
- type: 'button',
- class: "".concat(_this9.config.classNames.control, " ").concat(_this9.config.classNames.control, "--back")
- }); // Visible label
+ volume.appendChild(createRange.call(_this10, 'volume', extend(attributes, {
+ id: "plyr-volume-".concat(data.id)
+ })));
+ }
+ } // Toggle captions button
- backButton.appendChild(createElement('span', {
- 'aria-hidden': true
- }, i18n.get(type, _this9.config))); // Screen reader label
- backButton.appendChild(createElement('span', {
- class: _this9.config.classNames.hidden
- }, i18n.get('menuBack', _this9.config))); // Go back via keyboard
+ if (control === 'captions') {
+ container.appendChild(createButton.call(_this10, 'captions', defaultAttributes));
+ } // Settings button / menu
- on(pane, 'keydown', function (event) {
- // We only care about <-
- if (event.which !== 37) {
- return;
- } // Prevent seek
+ if (control === 'settings' && !is$1.empty(_this10.config.settings)) {
+ var _control = createElement('div', extend({}, defaultAttributes, {
+ class: "".concat(defaultAttributes.class, " plyr__menu").trim(),
+ hidden: ''
+ }));
- event.preventDefault();
- event.stopPropagation(); // Show the respective menu
+ _control.appendChild(createButton.call(_this10, 'settings', {
+ 'aria-haspopup': true,
+ 'aria-controls': "plyr-settings-".concat(data.id),
+ 'aria-expanded': false
+ }));
- controls.showMenuPanel.call(_this9, 'home', true);
- }, false); // Go back via button click
+ var popup = createElement('div', {
+ class: 'plyr__menu__container',
+ id: "plyr-settings-".concat(data.id),
+ hidden: ''
+ });
+ var inner = createElement('div');
+ var home = createElement('div', {
+ id: "plyr-settings-".concat(data.id, "-home")
+ }); // Create the menu
- on(backButton, 'click', function () {
- controls.showMenuPanel.call(_this9, 'home', false);
- }); // Add to pane
+ var menu = createElement('div', {
+ role: 'menu'
+ });
+ home.appendChild(menu);
+ inner.appendChild(home);
+ _this10.elements.settings.panels.home = home; // Build the menu items
+
+ _this10.config.settings.forEach(function (type) {
+ // TODO: bundle this with the createMenuItem helper and bindings
+ var menuItem = createElement('button', extend(getAttributesFromSelector(_this10.config.selectors.buttons.settings), {
+ type: 'button',
+ class: "".concat(_this10.config.classNames.control, " ").concat(_this10.config.classNames.control, "--forward"),
+ role: 'menuitem',
+ 'aria-haspopup': true,
+ hidden: ''
+ })); // Bind menu shortcuts for keyboard users
+
+ bindMenuItemShortcuts.call(_this10, menuItem, type); // Show menu on click
+
+ on(menuItem, 'click', function () {
+ showMenuPanel.call(_this10, type, false);
+ });
+ var flex = createElement('span', null, i18n.get(type, _this10.config));
+ var value = createElement('span', {
+ class: _this10.config.classNames.menu.value
+ }); // Speed contains HTML entities
+
+ value.innerHTML = data[type];
+ flex.appendChild(value);
+ menuItem.appendChild(flex);
+ menu.appendChild(menuItem); // Build the panes
+
+ var pane = createElement('div', {
+ id: "plyr-settings-".concat(data.id, "-").concat(type),
+ hidden: ''
+ }); // Back button
+
+ var backButton = createElement('button', {
+ type: 'button',
+ class: "".concat(_this10.config.classNames.control, " ").concat(_this10.config.classNames.control, "--back")
+ }); // Visible label
+
+ backButton.appendChild(createElement('span', {
+ 'aria-hidden': true
+ }, i18n.get(type, _this10.config))); // Screen reader label
+
+ backButton.appendChild(createElement('span', {
+ class: _this10.config.classNames.hidden
+ }, i18n.get('menuBack', _this10.config))); // Go back via keyboard
+
+ on(pane, 'keydown', function (event) {
+ // We only care about <-
+ if (event.which !== 37) {
+ return;
+ } // Prevent seek
+
+
+ event.preventDefault();
+ event.stopPropagation(); // Show the respective menu
+
+ showMenuPanel.call(_this10, 'home', true);
+ }, false); // Go back via button click
+
+ on(backButton, 'click', function () {
+ showMenuPanel.call(_this10, 'home', false);
+ }); // Add to pane
+
+ pane.appendChild(backButton); // Menu
+
+ pane.appendChild(createElement('div', {
+ role: 'menu'
+ }));
+ inner.appendChild(pane);
+ _this10.elements.settings.buttons[type] = menuItem;
+ _this10.elements.settings.panels[type] = pane;
+ });
- pane.appendChild(backButton); // Menu
+ popup.appendChild(inner);
- pane.appendChild(createElement('div', {
- role: 'menu'
- }));
- inner.appendChild(pane);
- _this9.elements.settings.buttons[type] = menuItem;
- _this9.elements.settings.panels[type] = pane;
- });
- popup.appendChild(inner);
- control.appendChild(popup);
- container.appendChild(control);
- this.elements.settings.popup = popup;
- this.elements.settings.menu = control;
- } // Picture in picture button
+ _control.appendChild(popup);
+ container.appendChild(_control);
+ _this10.elements.settings.popup = popup;
+ _this10.elements.settings.menu = _control;
+ } // Picture in picture button
- if (this.config.controls.includes('pip') && support.pip) {
- container.appendChild(controls.createButton.call(this, 'pip'));
- } // Airplay button
+ if (control === 'pip' && support.pip) {
+ container.appendChild(createButton.call(_this10, 'pip', defaultAttributes));
+ } // Airplay button
- if (this.config.controls.includes('airplay') && support.airplay) {
- container.appendChild(controls.createButton.call(this, 'airplay'));
- } // Download button
+ if (control === 'airplay' && support.airplay) {
+ container.appendChild(createButton.call(_this10, 'airplay', defaultAttributes));
+ } // Download button
- if (this.config.controls.includes('download')) {
- var _attributes = {
- element: 'a',
- href: this.download,
- target: '_blank'
- };
- var download = this.config.urls.download;
- if (!is$1.url(download) && this.isEmbed) {
- extend(_attributes, {
- icon: "logo-".concat(this.provider),
- label: this.provider
+ if (control === 'download') {
+ var _attributes = extend({}, defaultAttributes, {
+ element: 'a',
+ href: _this10.download,
+ target: '_blank'
});
- }
-
- container.appendChild(controls.createButton.call(this, 'download', _attributes));
- } // Toggle fullscreen button
+ var download = _this10.config.urls.download;
- if (this.config.controls.includes('fullscreen')) {
- container.appendChild(controls.createButton.call(this, 'fullscreen'));
- } // Larger overlaid play button
+ if (!is$1.url(download) && _this10.isEmbed) {
+ extend(_attributes, {
+ icon: "logo-".concat(_this10.provider),
+ label: _this10.provider
+ });
+ }
+ container.appendChild(createButton.call(_this10, 'download', _attributes));
+ } // Toggle fullscreen button
- if (this.config.controls.includes('play-large')) {
- this.elements.container.appendChild(controls.createButton.call(this, 'play-large'));
- }
- this.elements.controls = container; // Set available quality levels
+ if (control === 'fullscreen') {
+ container.appendChild(createButton.call(_this10, 'fullscreen', defaultAttributes));
+ }
+ }); // Set available quality levels
if (this.isHTML5) {
- controls.setQualityMenu.call(this, html5.getQualityOptions.call(this));
+ setQualityMenu.call(this, html5.getQualityOptions.call(this));
}
- controls.setSpeedMenu.call(this);
+ setSpeedMenu.call(this);
return container;
},
// Insert controls
inject: function inject() {
- var _this10 = this;
+ var _this11 = this;
// Sprite
if (this.config.loadSprite) {
@@ -6957,7 +7006,7 @@ typeof navigator === "object" && (function () {
if (!is$1.empty(this.elements.buttons)) {
var addProperty = function addProperty(button) {
- var className = _this10.config.classNames.controlPressed;
+ var className = _this11.config.classNames.controlPressed;
Object.defineProperty(button, 'pressed', {
enumerable: true,
get: function get() {
@@ -6993,8 +7042,8 @@ typeof navigator === "object" && (function () {
var selector = "".concat(selectors.controls.wrapper, " ").concat(selectors.labels, " .").concat(classNames.hidden);
var labels = getElements.call(this, selector);
Array.from(labels).forEach(function (label) {
- toggleClass(label, _this10.config.classNames.hidden, false);
- toggleClass(label, _this10.config.classNames.tooltip, true);
+ toggleClass(label, _this11.config.classNames.hidden, false);
+ toggleClass(label, _this11.config.classNames.tooltip, true);
});
}
}
@@ -7451,7 +7500,7 @@ typeof navigator === "object" && (function () {
// Sprite (for icons)
loadSprite: true,
iconPrefix: 'plyr',
- iconUrl: 'https://cdn.plyr.io/3.5.3/plyr.svg',
+ iconUrl: 'https://cdn.plyr.io/3.5.4/plyr.svg',
// Blank video (used to prevent errors on source change)
blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
// Quality default
@@ -7564,7 +7613,8 @@ typeof navigator === "object" && (function () {
},
youtube: {
sdk: 'https://www.youtube.com/iframe_api',
- api: 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title))&part=snippet'
+ api: 'https://noembed.com/embed?url=https://www.youtube.com/watch?v={0}' // 'https://www.googleapis.com/youtube/v3/videos?id={0}&key={1}&fields=items(snippet(title),fileDetails)&part=snippet',
+
},
googleIMA: {
sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js'
@@ -7640,10 +7690,7 @@ typeof navigator === "object" && (function () {
},
progress: '.plyr__progress',
captions: '.plyr__captions',
- caption: '.plyr__caption',
- menu: {
- quality: '.js-plyr__menu__list--quality'
- }
+ caption: '.plyr__caption'
},
// Class hooks added to the player in different states
classNames: {
@@ -7714,10 +7761,6 @@ typeof navigator === "object" && (function () {
id: 'data-plyr-embed-id'
}
},
- // API keys
- keys: {
- google: null
- },
// Advertisements plugin
// Register for an account here: http://vi.ai/publisher-video-monetization/?aid=plyrio
ads: {
@@ -8167,13 +8210,13 @@ typeof navigator === "object" && (function () {
this.volume = null; // Reset mute state
- this.muted = null; // Reset speed
-
- this.speed = null; // Reset loop state
+ this.muted = null; // Reset loop state
this.loop = null; // Reset quality setting
- this.quality = null; // Reset volume display
+ this.quality = null; // Reset speed
+
+ this.speed = null; // Reset volume display
controls.updateVolume.call(this); // Reset time display
@@ -8580,8 +8623,6 @@ typeof navigator === "object" && (function () {
}, {
key: "container",
value: function container() {
- var _this = this;
-
var player = this.player;
var config = player.config,
elements = player.elements,
@@ -8636,7 +8677,7 @@ typeof navigator === "object" && (function () {
var _ratio = _slicedToArray(ratio, 2),
y = _ratio[1];
- var _getAspectRatio$call = getAspectRatio.call(_this),
+ var _getAspectRatio$call = getAspectRatio.call(player),
_getAspectRatio$call2 = _slicedToArray(_getAspectRatio$call, 2),
videoX = _getAspectRatio$call2[0],
videoY = _getAspectRatio$call2[1];
@@ -8694,7 +8735,7 @@ typeof navigator === "object" && (function () {
}, {
key: "media",
value: function media() {
- var _this2 = this;
+ var _this = this;
var player = this.player;
var elements = player.elements; // Time change on media
@@ -8759,11 +8800,11 @@ typeof navigator === "object" && (function () {
}
if (player.ended) {
- _this2.proxy(event, player.restart, 'restart');
+ _this.proxy(event, player.restart, 'restart');
- _this2.proxy(event, player.play, 'play');
+ _this.proxy(event, player.play, 'play');
} else {
- _this2.proxy(event, player.togglePlay, 'play');
+ _this.proxy(event, player.togglePlay, 'play');
}
});
} // Disable right click
@@ -8800,7 +8841,7 @@ typeof navigator === "object" && (function () {
}); // Update download link when ready and if quality changes
on.call(player, player.media, 'ready qualitychange', function () {
- controls.setDownloadLink.call(player);
+ controls.setDownloadUrl.call(player);
}); // Proxy events to container
// Bubble up key events for Edge
@@ -8838,21 +8879,21 @@ typeof navigator === "object" && (function () {
}, {
key: "bind",
value: function bind(element, type, defaultHandler, customHandlerKey) {
- var _this3 = this;
+ var _this2 = this;
var passive = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
var player = this.player;
var customHandler = player.config.listeners[customHandlerKey];
var hasCustomHandler = is$1.function(customHandler);
on.call(player, element, type, function (event) {
- return _this3.proxy(event, defaultHandler, customHandlerKey);
+ return _this2.proxy(event, defaultHandler, customHandlerKey);
}, passive && !hasCustomHandler);
} // Listen for control events
}, {
key: "controls",
value: function controls$1() {
- var _this4 = this;
+ var _this3 = this;
var player = this.player;
var elements = player.elements; // IE doesn't support input event, so we fallback to change
@@ -8861,7 +8902,7 @@ typeof navigator === "object" && (function () {
if (elements.buttons.play) {
Array.from(elements.buttons.play).forEach(function (button) {
- _this4.bind(button, 'click', player.togglePlay, 'play');
+ _this3.bind(button, 'click', player.togglePlay, 'play');
});
} // Pause
@@ -8968,7 +9009,7 @@ typeof navigator === "object" && (function () {
if (browser.isIos) {
var inputs = getElements.call(player, 'input[type="range"]');
Array.from(inputs).forEach(function (input) {
- return _this4.bind(input, inputEvent, function (event) {
+ return _this3.bind(input, inputEvent, function (event) {
return repaint(event.target);
});
});
@@ -9026,7 +9067,7 @@ typeof navigator === "object" && (function () {
if (browser.isWebkit) {
Array.from(getElements.call(player, 'input[type="range"]')).forEach(function (element) {
- _this4.bind(element, 'input', function (event) {
+ _this3.bind(element, 'input', function (event) {
return controls.updateRangeFill.call(player, event.target);
});
});
@@ -9073,7 +9114,7 @@ typeof navigator === "object" && (function () {
toggleClass(elements.controls, config.classNames.noTransition, false);
}, 0); // Delay a little more for mouse users
- var delay = _this4.touch ? 3000 : 4000; // Clear timer
+ var delay = _this3.touch ? 3000 : 4000; // Clear timer
clearTimeout(timers.controls); // Hide again after delay
@@ -9446,13 +9487,13 @@ typeof navigator === "object" && (function () {
// Add embed class for responsive
toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set intial ratio
- setAspectRatio.call(this); // Load the API if not already
+ setAspectRatio.call(this); // Load the SDK if not already
if (!is$1.object(window.Vimeo)) {
loadScript(this.config.urls.vimeo.sdk).then(function () {
vimeo.ready.call(_this);
}).catch(function (error) {
- _this.debug.warn('Vimeo API failed to load', error);
+ _this.debug.warn('Vimeo SDK (player.js) failed to load', error);
});
} else {
vimeo.ready.call(this);
@@ -9631,7 +9672,7 @@ typeof navigator === "object" && (function () {
var currentSrc;
player.embed.getVideoUrl().then(function (value) {
currentSrc = value;
- controls.setDownloadLink.call(player);
+ controls.setDownloadUrl.call(player);
}).catch(function (error) {
_this2.debug.warn(error);
});
@@ -9652,7 +9693,7 @@ typeof navigator === "object" && (function () {
width = _dimensions[0],
height = _dimensions[1];
- player.embed.ratio = "".concat(width, ":").concat(height);
+ player.embed.ratio = [width, height];
setAspectRatio.call(_this2);
}); // Set autopause
@@ -9793,9 +9834,7 @@ typeof navigator === "object" && (function () {
var _this = this;
// Add embed class for responsive
- toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Set aspect ratio
-
- setAspectRatio.call(this); // Setup API
+ toggleClass(this.elements.wrapper, this.config.classNames.embed, true); // Setup API
if (is$1.object(window.YT) && is$1.function(window.YT.Player)) {
youtube.ready.call(this);
@@ -9823,32 +9862,24 @@ typeof navigator === "object" && (function () {
getTitle: function getTitle(videoId) {
var _this2 = this;
- // Try via undocumented API method first
- // This method disappears now and then though...
- // https://github.com/sampotts/plyr/issues/709
- if (is$1.function(this.embed.getVideoData)) {
- var _this$embed$getVideoD = this.embed.getVideoData(),
- title = _this$embed$getVideoD.title;
-
- if (is$1.empty(title)) {
- this.config.title = title;
- ui.setTitle.call(this);
- return;
- }
- } // Or via Google API
+ var url = format(this.config.urls.youtube.api, videoId);
+ fetch(url).then(function (data) {
+ if (is$1.object(data)) {
+ var title = data.title,
+ height = data.height,
+ width = data.width; // Set title
+ _this2.config.title = title;
+ ui.setTitle.call(_this2); // Set aspect ratio
- var key = this.config.keys.google;
+ _this2.embed.ratio = [width, height];
+ }
- if (is$1.string(key) && !is$1.empty(key)) {
- var url = format(this.config.urls.youtube.api, videoId, key);
- fetch(url).then(function (result) {
- if (is$1.object(result)) {
- _this2.config.title = result.items[0].snippet.title;
- ui.setTitle.call(_this2);
- }
- }).catch(function () {});
- }
+ setAspectRatio.call(_this2);
+ }).catch(function () {
+ // Set aspect ratio
+ setAspectRatio.call(_this2);
+ });
},
// API ready
ready: function ready() {
@@ -10206,6 +10237,20 @@ typeof navigator === "object" && (function () {
}
};
+ var destroy = function destroy(instance) {
+ // Destroy our adsManager
+ if (instance.manager) {
+ instance.manager.destroy();
+ } // Destroy our adsManager
+
+
+ if (instance.elements.displayContainer) {
+ instance.elements.displayContainer.destroy();
+ }
+
+ instance.elements.container.remove();
+ };
+
var Ads =
/*#__PURE__*/
function () {
@@ -10253,18 +10298,20 @@ typeof navigator === "object" && (function () {
value: function load() {
var _this2 = this;
- if (this.enabled) {
- // Check if the Google IMA3 SDK is loaded or load it ourselves
- if (!is$1.object(window.google) || !is$1.object(window.google.ima)) {
- loadScript(this.player.config.urls.googleIMA.sdk).then(function () {
- _this2.ready();
- }).catch(function () {
- // Script failed to load or is blocked
- _this2.trigger('error', new Error('Google IMA SDK failed to load'));
- });
- } else {
- this.ready();
- }
+ if (!this.enabled) {
+ return;
+ } // Check if the Google IMA3 SDK is loaded or load it ourselves
+
+
+ if (!is$1.object(window.google) || !is$1.object(window.google.ima)) {
+ loadScript(this.player.config.urls.googleIMA.sdk).then(function () {
+ _this2.ready();
+ }).catch(function () {
+ // Script failed to load or is blocked
+ _this2.trigger('error', new Error('Google IMA SDK failed to load'));
+ });
+ } else {
+ this.ready();
}
}
/**
@@ -10276,8 +10323,13 @@ typeof navigator === "object" && (function () {
value: function ready() {
var _this3 = this;
- // Start ticking our safety timer. If the whole advertisement
+ // Double check we're enabled
+ if (!this.enabled) {
+ destroy(this);
+ } // Start ticking our safety timer. If the whole advertisement
// thing doesn't resolve within our set time; we bail
+
+
this.startSafetyTimer(12000, 'ready()'); // Clear the safety timer
this.managerPromise.then(function () {
@@ -10407,9 +10459,7 @@ typeof navigator === "object" && (function () {
this.manager = event.getAdsManager(this.player, settings); // Get the cue points for any mid-rolls by filtering out the pre- and post-roll
- this.cuePoints = this.manager.getCuePoints(); // Set volume to match player
-
- this.manager.setVolume(this.player.volume); // Add listeners to the required events
+ this.cuePoints = this.manager.getCuePoints(); // Add listeners to the required events
// Advertisement error events
this.manager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, function (error) {
@@ -10468,15 +10518,16 @@ typeof navigator === "object" && (function () {
var dispatchEvent = function dispatchEvent(type) {
var event = "ads".concat(type.replace(/_/g, '').toLowerCase());
triggerEvent.call(_this8.player, _this8.player.media, event);
- };
+ }; // Bubble the event
+
+
+ dispatchEvent(event.type);
switch (event.type) {
case google.ima.AdEvent.Type.LOADED:
// This is the first event sent for an ad - it is possible to determine whether the
// ad is a video ad or an overlay
- this.trigger('loaded'); // Bubble event
-
- dispatchEvent(event.type); // Start countdown
+ this.trigger('loaded'); // Start countdown
this.pollCountdown(true);
@@ -10490,11 +10541,15 @@ typeof navigator === "object" && (function () {
break;
+ case google.ima.AdEvent.Type.STARTED:
+ // Set volume to match player
+ this.manager.setVolume(this.player.volume);
+ break;
+
case google.ima.AdEvent.Type.ALL_ADS_COMPLETED:
// All ads for the current videos are done. We can now request new advertisements
// in case the video is re-played
- // Fire event
- dispatchEvent(event.type); // TODO: Example for what happens when a next video in a playlist would be loaded.
+ // TODO: Example for what happens when a next video in a playlist would be loaded.
// So here we load a new video when all ads are done.
// Then we load new ads within a new adsManager. When the video
// Is started - after - the ads are loaded, then we get ads.
@@ -10515,7 +10570,6 @@ typeof navigator === "object" && (function () {
// };
// TODO: So there is still this thing where a video should only be allowed to start
// playing when the IMA SDK is ready or has failed
-
this.loadAds();
break;
@@ -10523,7 +10577,6 @@ typeof navigator === "object" && (function () {
// This event indicates the ad has started - the video player can adjust the UI,
// for example display a pause button and remaining time. Fired when content should
// be paused. This usually happens right before an ad is about to cover the content
- dispatchEvent(event.type);
this.pauseContent();
break;
@@ -10532,19 +10585,10 @@ typeof navigator === "object" && (function () {
// appropriate UI actions, such as removing the timer for remaining time detection.
// Fired when content should be resumed. This usually happens when an ad finishes
// or collapses
- dispatchEvent(event.type);
this.pollCountdown();
this.resumeContent();
break;
- case google.ima.AdEvent.Type.STARTED:
- case google.ima.AdEvent.Type.MIDPOINT:
- case google.ima.AdEvent.Type.COMPLETE:
- case google.ima.AdEvent.Type.IMPRESSION:
- case google.ima.AdEvent.Type.CLICK:
- dispatchEvent(event.type);
- break;
-
case google.ima.AdEvent.Type.LOG:
if (adData.adError) {
this.player.debug.warn("Non-fatal ad error: ".concat(adData.adError.getMessage()));
@@ -10629,7 +10673,10 @@ typeof navigator === "object" && (function () {
this.managerPromise.then(function () {
- // Initialize the container. Must be done via a user action on mobile devices
+ // Set volume to match player
+ _this10.manager.setVolume(_this10.player.volume); // Initialize the container. Must be done via a user action on mobile devices
+
+
_this10.elements.displayContainer.initialize();
try {
@@ -11129,7 +11176,10 @@ typeof navigator === "object" && (function () {
timeContainer.appendChild(this.elements.thumb.time);
this.elements.thumb.container.appendChild(timeContainer); // Inject the whole thumb
- this.player.elements.progress.appendChild(this.elements.thumb.container); // Create HTML element: plyr__preview-scrubbing-container
+ if (is$1.element(this.player.elements.progress)) {
+ this.player.elements.progress.appendChild(this.elements.thumb.container);
+ } // Create HTML element: plyr__preview-scrubbing-container
+
this.elements.scrubbing.container = createElement('div', {
class: this.player.config.classNames.previewThumbnails.scrubbingContainer
@@ -11638,6 +11688,25 @@ typeof navigator === "object" && (function () {
}
};
+ /**
+ * Returns a number whose value is limited to the given range.
+ *
+ * Example: limit the output of this computation to between 0 and 255
+ * (x * 255).clamp(0, 255)
+ *
+ * @param {Number} input
+ * @param {Number} min The lower boundary of the output range
+ * @param {Number} max The upper boundary of the output range
+ * @returns A number in the range [min, max]
+ * @type Number
+ */
+ function clamp() {
+ var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+ var min = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
+ var max = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 255;
+ return Math.min(Math.max(input, min), max);
+ }
+
// TODO: Use a WeakMap for private globals
// const globals = new WeakMap();
// Plyr instance
@@ -12484,6 +12553,8 @@ typeof navigator === "object" && (function () {
}, {
key: "speed",
set: function set(input) {
+ var _this4 = this;
+
var speed = null;
if (is$1.number(input)) {
@@ -12496,26 +12567,18 @@ typeof navigator === "object" && (function () {
if (!is$1.number(speed)) {
speed = this.config.speed.selected;
- } // Set min/max
-
-
- if (speed < 0.1) {
- speed = 0.1;
- }
-
- if (speed > 2.0) {
- speed = 2.0;
- }
+ } // Clamp to min/max
- if (!this.config.speed.options.includes(speed)) {
- this.debug.warn("Unsupported speed (".concat(speed, ")"));
- return;
- } // Update config
+ var min = this.minimumSpeed,
+ max = this.maximumSpeed;
+ speed = clamp(speed, min, max); // Update config
this.config.speed.selected = speed; // Set media speed
- this.media.playbackRate = speed;
+ setTimeout(function () {
+ _this4.media.playbackRate = speed;
+ }, 0);
}
/**
* Get current playback speed
@@ -12525,6 +12588,46 @@ typeof navigator === "object" && (function () {
return Number(this.media.playbackRate);
}
/**
+ * Get the minimum allowed speed
+ */
+
+ }, {
+ key: "minimumSpeed",
+ get: function get() {
+ if (this.isYouTube) {
+ // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate
+ return Math.min.apply(Math, _toConsumableArray(this.options.speed));
+ }
+
+ if (this.isVimeo) {
+ // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror
+ return 0.5;
+ } // https://stackoverflow.com/a/32320020/1191319
+
+
+ return 0.0625;
+ }
+ /**
+ * Get the maximum allowed speed
+ */
+
+ }, {
+ key: "maximumSpeed",
+ get: function get() {
+ if (this.isYouTube) {
+ // https://developers.google.com/youtube/iframe_api_reference#setPlaybackRate
+ return Math.max.apply(Math, _toConsumableArray(this.options.speed));
+ }
+
+ if (this.isVimeo) {
+ // https://github.com/vimeo/player.js/#setplaybackrateplaybackrate-number-promisenumber-rangeerrorerror
+ return 2;
+ } // https://stackoverflow.com/a/32320020/1191319
+
+
+ return 16;
+ }
+ /**
* Set playback quality
* Currently HTML5 & YouTube only
* @param {Number} input - Quality level
@@ -12654,6 +12757,18 @@ typeof navigator === "object" && (function () {
return is$1.url(download) ? download : this.source;
}
/**
+ * Set the download URL
+ */
+ ,
+ set: function set(input) {
+ if (!is$1.url(input)) {
+ return;
+ }
+
+ this.config.urls.download = input;
+ controls.setDownloadUrl.call(this);
+ }
+ /**
* Set the poster image for a video
* @param {String} input - the URL for the new poster image
*/
@@ -12686,6 +12801,10 @@ typeof navigator === "object" && (function () {
}, {
key: "ratio",
get: function get() {
+ if (!this.isVideo) {
+ return null;
+ }
+
var ratio = reduceAspectRatio(getAspectRatio.call(this));
return is$1.array(ratio) ? ratio.join(':') : ratio;
}