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