Compare commits

..

14 Commits

Author SHA1 Message Date
Sam Potts a812650fea v3.2.4 2018-04-27 00:47:51 +10:00
Sam Potts fec7a77d6f v3.2.3 2018-04-25 20:02:36 +10:00
Sam Potts 971e261067 Fix for iOS 9 throwing error for name property in fullscreen API (fixes #908) 2018-04-25 19:59:22 +10:00
Sam Potts 27407ba021 v3.2.2 2018-04-25 19:46:39 +10:00
Sam Potts ef8e58ede4 Fix for hidden buffer and incorrect use of aria-hidden 2018-04-25 19:40:23 +10:00
Sam Potts f1b275aedc v3.2.1 2018-04-23 00:53:54 +10:00
Sam Potts b647af256c More a11y stuff and context menu fix 2018-04-23 00:01:19 +10:00
Sam Potts d2e9ed3467 Merge 2018-04-18 18:34:59 +10:00
Sam Potts 5b39986835 Merge branch 'master' of github.com:sampotts/plyr 2018-04-18 18:29:50 +10:00
Sam Potts a97b08e8ea ARIA and Vimeo fixes 2018-04-18 18:29:43 +10:00
Sam Potts 56d1be9447 Merge pull request #903 from friday/901
Show captions even if toggle button is omitted from controls
2018-04-18 08:49:05 +10:00
Sam Potts a241cb5215 Merge pull request #904 from friday/881
Fullscreen aria-pressed event listened fix for Chrome
2018-04-18 08:48:08 +10:00
Albin Larsson 042b1a8294 Fullscreen aria-pressed event listened fix for Chrome 2018-04-17 20:28:47 +02:00
Albin Larsson 6d79b8cd4c Don't require captions toggle button to be enabled in order to show captions 2018-04-17 18:59:19 +02:00
33 changed files with 1944 additions and 387 deletions
+24
View File
@@ -1,3 +1,27 @@
## v3.2.4
* Fix issue wher player never reports as ready if controls is empty array
* Fix issue where screen reader labels were removed from time displays
* Fix issue where custom controls placeholders were not populated
* Custom controls HTML example updated
* Fix for aria-label being set to the initial state on toggle buttons, overriding the inner labels
* Fix for hidden mute button on iOS (not functional for Vimeo due to API limitations) (fixes #656)
## v3.2.3
* Fix for iOS 9 throwing error for `name` property in fullscreen API (fixes #908)
## v3.2.2
* Fix for regression in 3.2.1 resulting in hidden buffer display (fixes #920)
* Cleaned up incorrect use of `aria-hidden` attribute
## v3.2.1
* Accessibility improvements for the controls (part of #905 fixes)
* Fix for context menu showing on YouTube (thanks Anthony Recenello in Slack)
* Vimeo fix for their API not returning the right duration until playback begins (fixes #891)
## v3.2.0 ## v3.2.0
* Fullscreen fixes (thanks @friday) * Fullscreen fixes (thanks @friday)
+2 -1
View File
@@ -121,7 +121,8 @@ const controls = `
<progress class="plyr__progress--buffer" min="0" max="100" value="0">% buffered</progress> <progress class="plyr__progress--buffer" min="0" max="100" value="0">% buffered</progress>
<span role="tooltip" class="plyr__tooltip">00:00</span> <span role="tooltip" class="plyr__tooltip">00:00</span>
</div> </div>
<div class="plyr__time">00:00</div> <div class="plyr__time plyr__time--current" aria-label="Current time">00:00</div>
<div class="plyr__time plyr__time--duration" aria-label="Duration">00:00</div>
<button type="button" class="plyr__control" aria-pressed="false" aria-label="Mute" data-plyr="mute"> <button type="button" class="plyr__control" aria-pressed="false" aria-label="Mute" data-plyr="mute">
<svg class="icon--pressed" role="presentation"><use xlink:href="#plyr-muted"></use></svg> <svg class="icon--pressed" role="presentation"><use xlink:href="#plyr-muted"></use></svg>
<svg class="icon--not-pressed" role="presentation"><use xlink:href="#plyr-volume"></use></svg> <svg class="icon--not-pressed" role="presentation"><use xlink:href="#plyr-volume"></use></svg>
+1 -1
View File
File diff suppressed because one or more lines are too long
+53 -20
View File
@@ -245,7 +245,13 @@ function objectFrozen(obj) {
} }
function truncate(str, max) { function truncate(str, max) {
return !max || str.length <= max ? str : str.substr(0, max) + '\u2026'; if (typeof max !== 'number') {
throw new Error('2nd argument to `truncate` function should be a number');
}
if (typeof str !== 'string' || max === 0) {
return str;
}
return str.length <= max ? str : str.substr(0, max) + '\u2026';
} }
/** /**
@@ -544,10 +550,9 @@ function jsonSize(value) {
} }
function serializeValue(value) { function serializeValue(value) {
var maxLength = 40;
if (typeof value === 'string') { if (typeof value === 'string') {
return value.length <= maxLength ? value : value.substr(0, maxLength - 1) + '\u2026'; var maxLength = 40;
return truncate(value, maxLength);
} else if ( } else if (
typeof value === 'number' || typeof value === 'number' ||
typeof value === 'boolean' || typeof value === 'boolean' ||
@@ -1777,7 +1782,7 @@ Raven.prototype = {
// webpack (using a build step causes webpack #1617). Grunt verifies that // webpack (using a build step causes webpack #1617). Grunt verifies that
// this value matches package.json during build. // this value matches package.json during build.
// See: https://github.com/getsentry/raven-js/issues/465 // See: https://github.com/getsentry/raven-js/issues/465
VERSION: '3.24.0', VERSION: '3.24.2',
debug: false, debug: false,
@@ -2066,7 +2071,11 @@ Raven.prototype = {
*/ */
_promiseRejectionHandler: function(event) { _promiseRejectionHandler: function(event) {
this._logDebug('debug', 'Raven caught unhandled promise rejection:', event); this._logDebug('debug', 'Raven caught unhandled promise rejection:', event);
this.captureException(event.reason); this.captureException(event.reason, {
extra: {
unhandledPromiseRejection: true
}
});
}, },
/** /**
@@ -2207,6 +2216,14 @@ Raven.prototype = {
// stack[0] is `throw new Error(msg)` call itself, we are interested in the frame that was just before that, stack[1] // stack[0] is `throw new Error(msg)` call itself, we are interested in the frame that was just before that, stack[1]
var initialCall = isArray$1(stack.stack) && stack.stack[1]; var initialCall = isArray$1(stack.stack) && stack.stack[1];
// if stack[1] is `Raven.captureException`, it means that someone passed a string to it and we redirected that call
// to be handled by `captureMessage`, thus `initialCall` is the 3rd one, not 2nd
// initialCall => captureException(string) => captureMessage(string)
if (initialCall && initialCall.func === 'Raven.captureException') {
initialCall = stack.stack[2];
}
var fileurl = (initialCall && initialCall.url) || ''; var fileurl = (initialCall && initialCall.url) || '';
if ( if (
@@ -3004,17 +3021,30 @@ Raven.prototype = {
status_code: null status_code: null
}; };
return origFetch.apply(this, args).then(function(response) { return origFetch
fetchData.status_code = response.status; .apply(this, args)
.then(function(response) {
fetchData.status_code = response.status;
self.captureBreadcrumb({ self.captureBreadcrumb({
type: 'http', type: 'http',
category: 'fetch', category: 'fetch',
data: fetchData data: fetchData
});
return response;
})
['catch'](function(err) {
// if there is an error performing the request
self.captureBreadcrumb({
type: 'http',
category: 'fetch',
data: fetchData,
level: 'error'
});
throw err;
}); });
return response;
});
}; };
}, },
wrappedBuiltIns wrappedBuiltIns
@@ -3027,7 +3057,7 @@ Raven.prototype = {
if (_document.addEventListener) { if (_document.addEventListener) {
_document.addEventListener('click', self._breadcrumbEventHandler('click'), false); _document.addEventListener('click', self._breadcrumbEventHandler('click'), false);
_document.addEventListener('keypress', self._keypressEventHandler(), false); _document.addEventListener('keypress', self._keypressEventHandler(), false);
} else { } else if (_document.attachEvent) {
// IE8 Compatibility // IE8 Compatibility
_document.attachEvent('onclick', self._breadcrumbEventHandler('click')); _document.attachEvent('onclick', self._breadcrumbEventHandler('click'));
_document.attachEvent('onkeypress', self._keypressEventHandler()); _document.attachEvent('onkeypress', self._keypressEventHandler());
@@ -3750,7 +3780,11 @@ Raven.prototype = {
}, },
_logDebug: function(level) { _logDebug: function(level) {
if (this._originalConsoleMethods[level] && this.debug) { // We allow `Raven.debug` and `Raven.config(DSN, { debug: true })` to not make backward incompatible API change
if (
this._originalConsoleMethods[level] &&
(this.debug || this._globalOptions.debug)
) {
// In IE<10 console methods do not have their own 'apply' method // In IE<10 console methods do not have their own 'apply' method
Function.prototype.apply.call( Function.prototype.apply.call(
this._originalConsoleMethods[level], this._originalConsoleMethods[level],
@@ -3823,11 +3857,11 @@ var singleton = Raven$1;
* const someAppReporter = new Raven.Client(); * const someAppReporter = new Raven.Client();
* const someOtherAppReporter = new Raven.Client(); * const someOtherAppReporter = new Raven.Client();
* *
* someAppReporter('__DSN__', { * someAppReporter.config('__DSN__', {
* ...config goes here * ...config goes here
* }); * });
* *
* someOtherAppReporter('__OTHER_DSN__', { * someOtherAppReporter.config('__OTHER_DSN__', {
* ...config goes here * ...config goes here
* }); * });
* *
@@ -4011,7 +4045,6 @@ singleton.Client = Client;
case types.youtube: case types.youtube:
player.source = { player.source = {
type: 'video', type: 'video',
title: 'View From A Blue Moon',
sources: [{ sources: [{
src: 'https://youtube.com/watch?v=bTqVqk7FSmY', src: 'https://youtube.com/watch?v=bTqVqk7FSmY',
provider: 'youtube' provider: 'youtube'
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -141,7 +141,7 @@
</li> </li>
<li class="plyr__cite plyr__cite--vimeo" hidden> <li class="plyr__cite plyr__cite--vimeo" hidden>
<small> <small>
<a href="https://vimeo.com/ondemand/viewfromabluemoon4k" target="_blank">View From A Blue Moon</a> on&nbsp; <a href="https://vimeo.com/76979871" target="_blank">The New Vimeo Player</a> on&nbsp;
<span class="color--vimeo"> <span class="color--vimeo">
<svg class="icon" role="presentation"> <svg class="icon" role="presentation">
<title>Vimeo</title> <title>Vimeo</title>
-1
View File
@@ -182,7 +182,6 @@ import Raven from 'raven-js';
case types.youtube: case types.youtube:
player.source = { player.source = {
type: 'video', type: 'video',
title: 'View From A Blue Moon',
sources: [{ sources: [{
src: 'https://youtube.com/watch?v=bTqVqk7FSmY', src: 'https://youtube.com/watch?v=bTqVqk7FSmY',
provider: 'youtube', provider: 'youtube',
+1 -1
View File
File diff suppressed because one or more lines are too long
+123 -88
View File
@@ -77,7 +77,7 @@ var defaults = {
// Sprite (for icons) // Sprite (for icons)
loadSprite: true, loadSprite: true,
iconPrefix: 'plyr', iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/3.1.0/plyr.svg', iconUrl: 'https://cdn.plyr.io/3.2.3/plyr.svg',
// Blank video (used to prevent errors on source change) // Blank video (used to prevent errors on source change)
blankVideo: 'https://cdn.plyr.io/static/blank.mp4', blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
@@ -1101,6 +1101,26 @@ var utils = {
}, },
// Toggle hidden
toggleHidden: function toggleHidden(element, hidden) {
if (!utils.is.element(element)) {
return;
}
var hide = hidden;
if (!utils.is.boolean(hide)) {
hide = !element.hasAttribute('hidden');
}
if (hide) {
element.setAttribute('hidden', '');
} else {
element.removeAttribute('hidden');
}
},
// Toggle class on an element // Toggle class on an element
toggleClass: function toggleClass(element, className, toggle) { toggleClass: function toggleClass(element, className, toggle) {
if (utils.is.element(element)) { if (utils.is.element(element)) {
@@ -1121,20 +1141,6 @@ var utils = {
}, },
// Toggle hidden attribute on an element
toggleHidden: function toggleHidden(element, toggle) {
if (!utils.is.element(element)) {
return;
}
if (toggle) {
element.setAttribute('hidden', '');
} else {
element.removeAttribute('hidden');
}
},
// Element matches selector // Element matches selector
matches: function matches(element, selector) { matches: function matches(element, selector) {
var prototype = { Element: Element }; var prototype = { Element: Element };
@@ -1194,8 +1200,8 @@ var utils = {
// Display // Display
this.elements.display = { this.elements.display = {
buffer: utils.getElement.call(this, this.config.selectors.display.buffer), buffer: utils.getElement.call(this, this.config.selectors.display.buffer),
duration: utils.getElement.call(this, this.config.selectors.display.duration), currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),
currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime) duration: utils.getElement.call(this, this.config.selectors.display.duration)
}; };
// Seek tooltip // Seek tooltip
@@ -1952,7 +1958,7 @@ var Fullscreen = function () {
// Get prefix // Get prefix
this.prefix = Fullscreen.prefix; this.prefix = Fullscreen.prefix;
this.name = Fullscreen.name; this.property = Fullscreen.property;
// Scroll position // Scroll position
this.scrollPosition = { x: 0, y: 0 }; this.scrollPosition = { x: 0, y: 0 };
@@ -1967,7 +1973,7 @@ var Fullscreen = function () {
// Fullscreen toggle on double click // Fullscreen toggle on double click
utils.on(this.player.elements.container, 'dblclick', function (event) { utils.on(this.player.elements.container, 'dblclick', function (event) {
// Ignore double click in controls // Ignore double click in controls
if (_this.player.elements.controls.contains(event.target)) { if (utils.is.element(_this.player.elements.controls) && _this.player.elements.controls.contains(event.target)) {
return; return;
} }
@@ -2016,7 +2022,7 @@ var Fullscreen = function () {
} else if (!this.prefix) { } else if (!this.prefix) {
this.target.requestFullscreen(); this.target.requestFullscreen();
} else if (!utils.is.empty(this.prefix)) { } else if (!utils.is.empty(this.prefix)) {
this.target[this.prefix + 'Request' + this.name](); this.target[this.prefix + 'Request' + this.property]();
} }
} }
@@ -2039,7 +2045,7 @@ var Fullscreen = function () {
(document.cancelFullScreen || document.exitFullscreen).call(document); (document.cancelFullScreen || document.exitFullscreen).call(document);
} else if (!utils.is.empty(this.prefix)) { } else if (!utils.is.empty(this.prefix)) {
var action = this.prefix === 'moz' ? 'Cancel' : 'Exit'; var action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
document['' + this.prefix + action + this.name](); document['' + this.prefix + action + this.property]();
} }
} }
@@ -2077,7 +2083,7 @@ var Fullscreen = function () {
return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback); return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback);
} }
var element = !this.prefix ? document.fullscreenElement : document['' + this.prefix + this.name + 'Element']; var element = !this.prefix ? document.fullscreenElement : document['' + this.prefix + this.property + 'Element'];
return element === this.target; return element === this.target;
} }
@@ -2102,7 +2108,7 @@ var Fullscreen = function () {
get: function get$$1() { get: function get$$1() {
// No prefix // No prefix
if (utils.is.function(document.exitFullscreen)) { if (utils.is.function(document.exitFullscreen)) {
return false; return '';
} }
// Check for fullscreen support by vendor prefix // Check for fullscreen support by vendor prefix
@@ -2121,7 +2127,7 @@ var Fullscreen = function () {
return value; return value;
} }
}, { }, {
key: 'name', key: 'property',
get: function get$$1() { get: function get$$1() {
return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen'; return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';
} }
@@ -2414,11 +2420,6 @@ var captions = {
// Display captions container and button (for initialization) // Display captions container and button (for initialization)
show: function show() { show: function show() {
// If there's no caption toggle, bail
if (!utils.is.element(this.elements.buttons.captions)) {
return;
}
// Try to load the value from storage // Try to load the value from storage
var active = this.storage.get('captions'); var active = this.storage.get('captions');
@@ -2485,11 +2486,6 @@ var ui = {
this.listeners.controls(); this.listeners.controls();
} }
// If there's no controls, bail
if (!utils.is.element(this.elements.controls)) {
return;
}
// Remove native controls // Remove native controls
ui.toggleNativeControls.call(this); ui.toggleNativeControls.call(this);
@@ -2730,10 +2726,10 @@ var ui = {
} }
// Always display hours if duration is over an hour // Always display hours if duration is over an hour
var displayHours = utils.getHours(this.duration) > 0; var forceHours = utils.getHours(this.duration) > 0;
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
target.textContent = utils.formatTime(time, displayHours, inverted); target.textContent = utils.formatTime(time, forceHours, inverted);
}, },
@@ -2940,11 +2936,6 @@ var browser$1 = utils.getBrowser();
var controls = { var controls = {
// Webkit polyfill for lower fill range // Webkit polyfill for lower fill range
updateRangeFill: function updateRangeFill(target) { updateRangeFill: function updateRangeFill(target) {
// WebKit only
if (!browser$1.isWebkit) {
return;
}
// Get range from event if event passed // Get range from event if event passed
var range = utils.is.event(target) ? target.target : target; var range = utils.is.event(target) ? target.target : target;
@@ -2953,6 +2944,14 @@ var controls = {
return; return;
} }
// Set aria value for https://github.com/sampotts/plyr/issues/905
range.setAttribute('aria-valuenow', range.value);
// WebKit only
if (!browser$1.isWebkit) {
return;
}
// Set CSS custom property // Set CSS custom property
range.style.setProperty('--value', range.value / range.max * 100 + '%'); range.style.setProperty('--value', range.value / range.max * 100 + '%');
}, },
@@ -2976,7 +2975,8 @@ var controls = {
// Create <svg> // Create <svg>
var icon = document.createElementNS(namespace, 'svg'); var icon = document.createElementNS(namespace, 'svg');
utils.setAttributes(icon, utils.extend(attributes, { utils.setAttributes(icon, utils.extend(attributes, {
role: 'presentation' role: 'presentation',
focusable: 'false'
})); }));
// Create the <use> to reference sprite // Create the <use> to reference sprite
@@ -3127,7 +3127,6 @@ var controls = {
// Add aria attributes // Add aria attributes
attributes['aria-pressed'] = false; attributes['aria-pressed'] = false;
attributes['aria-label'] = i18n.get(label, this.config);
} else { } else {
button.appendChild(controls.createIcon.call(this, icon)); button.appendChild(controls.createIcon.call(this, icon));
button.appendChild(controls.createLabel.call(this, label)); button.appendChild(controls.createLabel.call(this, label));
@@ -3158,6 +3157,7 @@ var controls = {
// Seek label // Seek label
var label = utils.createElement('label', { var label = utils.createElement('label', {
for: attributes.id, for: attributes.id,
id: attributes.id + '-label',
class: this.config.classNames.hidden class: this.config.classNames.hidden
}, i18n.get(type, this.config)); }, i18n.get(type, this.config));
@@ -3168,7 +3168,13 @@ var controls = {
max: 100, max: 100,
step: 0.01, step: 0.01,
value: 0, value: 0,
autocomplete: 'off' autocomplete: 'off',
// A11y fixes for https://github.com/sampotts/plyr/issues/905
role: 'slider',
'aria-labelledby': attributes.id + '-label',
'aria-valuemin': 0,
'aria-valuemax': 100,
'aria-valuenow': 0
}, attributes)); }, attributes));
this.elements.inputs[type] = input; this.elements.inputs[type] = input;
@@ -3188,7 +3194,9 @@ var controls = {
var progress = utils.createElement('progress', utils.extend(utils.getAttributesFromSelector(this.config.selectors.display[type]), { var progress = utils.createElement('progress', utils.extend(utils.getAttributesFromSelector(this.config.selectors.display[type]), {
min: 0, min: 0,
max: 100, max: 100,
value: 0 value: 0,
role: 'presentation',
'aria-hidden': true
}, attributes)); }, attributes));
// Create the label inside // Create the label inside
@@ -3220,16 +3228,14 @@ var controls = {
// Create time display // Create time display
createTime: function createTime(type) { createTime: function createTime(type) {
var container = utils.createElement('div', { var attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]);
class: 'plyr__time'
});
container.appendChild(utils.createElement('span', { var container = utils.createElement('div', utils.extend(attributes, {
class: this.config.classNames.hidden class: 'plyr__time ' + attributes.class,
}, i18n.get(type, this.config))); 'aria-label': i18n.get(type, this.config)
}), '0:00');
container.appendChild(utils.createElement('span', utils.getAttributesFromSelector(this.config.selectors.display[type]), '00:00'));
// Reference for updates
this.elements.display[type] = container; this.elements.display[type] = container;
return container; return container;
@@ -3255,7 +3261,7 @@ var controls = {
class: 'plyr__sr-only' class: 'plyr__sr-only'
})); }));
var faux = utils.createElement('span', { 'aria-hidden': true }); var faux = utils.createElement('span', { hidden: '' });
label.appendChild(radio); label.appendChild(radio);
label.appendChild(faux); label.appendChild(faux);
@@ -3326,11 +3332,7 @@ var controls = {
// Hide/show a tab // Hide/show a tab
toggleTab: function toggleTab(setting, toggle) { toggleTab: function toggleTab(setting, toggle) {
var tab = this.elements.settings.tabs[setting]; utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);
var pane = this.elements.settings.panes[setting];
utils.toggleHidden(tab, !toggle);
utils.toggleHidden(pane, !toggle);
}, },
@@ -3542,7 +3544,6 @@ var controls = {
// Get current selected caption language // Get current selected caption language
// TODO: rework this to user the getter in the API? // TODO: rework this to user the getter in the API?
// Set a list of available captions languages // Set a list of available captions languages
setCaptionsMenu: function setCaptionsMenu() { setCaptionsMenu: function setCaptionsMenu() {
var _this3 = this; var _this3 = this;
@@ -3637,10 +3638,6 @@ var controls = {
// Get the list to populate // Get the list to populate
var list = this.elements.settings.panes.speed.querySelector('ul'); var list = this.elements.settings.panes.speed.querySelector('ul');
// Show the pane and tab
utils.toggleHidden(this.elements.settings.tabs.speed, false);
utils.toggleHidden(this.elements.settings.panes.speed, false);
// Empty the menu // Empty the menu
utils.emptyElement(list); utils.emptyElement(list);
@@ -3677,7 +3674,7 @@ var controls = {
return; return;
} }
var show = utils.is.boolean(event) ? event : utils.is.element(form) && form.getAttribute('aria-hidden') === 'true'; var show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden');
if (utils.is.event(event)) { if (utils.is.event(event)) {
var isMenuItem = utils.is.element(form) && form.contains(event.target); var isMenuItem = utils.is.element(form) && form.contains(event.target);
@@ -3702,7 +3699,7 @@ var controls = {
} }
if (utils.is.element(form)) { if (utils.is.element(form)) {
form.setAttribute('aria-hidden', !show); utils.toggleHidden(form, !show);
utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show); utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show);
if (show) { if (show) {
@@ -3719,7 +3716,7 @@ var controls = {
var clone = tab.cloneNode(true); var clone = tab.cloneNode(true);
clone.style.position = 'absolute'; clone.style.position = 'absolute';
clone.style.opacity = 0; clone.style.opacity = 0;
clone.setAttribute('aria-hidden', false); clone.removeAttribute('hidden');
// Prevent input's being unchecked due to the name being identical // Prevent input's being unchecked due to the name being identical
Array.from(clone.querySelectorAll('input[name]')).forEach(function (input) { Array.from(clone.querySelectorAll('input[name]')).forEach(function (input) {
@@ -3765,7 +3762,7 @@ var controls = {
// Hide all other tabs // Hide all other tabs
// Get other tabs // Get other tabs
var current = menu.querySelector('[role="tabpanel"][aria-hidden="false"]'); var current = menu.querySelector('[role="tabpanel"]:not([hidden])');
var container = current.parentNode; var container = current.parentNode;
// Set other toggles to be expanded false // Set other toggles to be expanded false
@@ -3806,11 +3803,11 @@ var controls = {
} }
// Set attributes on current tab // Set attributes on current tab
current.setAttribute('aria-hidden', true); utils.toggleHidden(current, true);
current.setAttribute('tabindex', -1); current.setAttribute('tabindex', -1);
// Set attributes on target // Set attributes on target
pane.setAttribute('aria-hidden', !show); utils.toggleHidden(pane, !show);
tab.setAttribute('aria-expanded', show); tab.setAttribute('aria-expanded', show);
pane.removeAttribute('tabindex'); pane.removeAttribute('tabindex');
@@ -3945,7 +3942,7 @@ var controls = {
var form = utils.createElement('form', { var form = utils.createElement('form', {
class: 'plyr__menu__container', class: 'plyr__menu__container',
id: 'plyr-settings-' + data.id, id: 'plyr-settings-' + data.id,
'aria-hidden': true, hidden: '',
'aria-labelled-by': 'plyr-settings-toggle-' + data.id, 'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
role: 'tablist', role: 'tablist',
tabindex: -1 tabindex: -1
@@ -3955,7 +3952,6 @@ var controls = {
var home = utils.createElement('div', { var home = utils.createElement('div', {
id: 'plyr-settings-' + data.id + '-home', id: 'plyr-settings-' + data.id + '-home',
'aria-hidden': false,
'aria-labelled-by': 'plyr-settings-toggle-' + data.id, 'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
role: 'tabpanel' role: 'tabpanel'
}); });
@@ -4002,11 +3998,10 @@ var controls = {
this.config.settings.forEach(function (type) { this.config.settings.forEach(function (type) {
var pane = utils.createElement('div', { var pane = utils.createElement('div', {
id: 'plyr-settings-' + data.id + '-' + type, id: 'plyr-settings-' + data.id + '-' + type,
'aria-hidden': true, hidden: '',
'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab', 'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab',
role: 'tabpanel', role: 'tabpanel',
tabindex: -1, tabindex: -1
hidden: ''
}); });
var back = utils.createElement('button', { var back = utils.createElement('button', {
@@ -4088,17 +4083,21 @@ var controls = {
var container = null; var container = null;
this.elements.controls = null; this.elements.controls = null;
// HTML or Element passed as the option // Set template properties
var props = {
id: this.id,
seektime: this.config.seekTime,
title: this.config.title
};
var update = true;
if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) { if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) {
// String or HTMLElement passed as the option
container = this.config.controls; container = this.config.controls;
} else if (utils.is.function(this.config.controls)) { } else if (utils.is.function(this.config.controls)) {
// A custom function to build controls // A custom function to build controls
// The function can return a HTMLElement or String // The function can return a HTMLElement or String
container = this.config.controls({ container = this.config.controls.call(this, props);
id: this.id,
seektime: this.config.seekTime,
title: this.config.title
});
} else { } else {
// Create controls // Create controls
container = controls.create.call(this, { container = controls.create.call(this, {
@@ -4110,6 +4109,31 @@ var controls = {
// TODO: Looping // TODO: Looping
// loop: 'None', // loop: 'None',
}); });
update = false;
}
// Replace props with their value
var replace = function replace(input) {
var result = input;
Object.entries(props).forEach(function (_ref) {
var _ref2 = slicedToArray(_ref, 2),
key = _ref2[0],
value = _ref2[1];
result = utils.replaceAll(result, '{' + key + '}', value);
});
return result;
};
// Update markup
if (update) {
if (utils.is.string(this.config.controls)) {
container = replace(container);
} else if (utils.is.element(container)) {
container.innerHTML = replace(container.innerHTML);
}
} }
// Controls container // Controls container
@@ -4411,7 +4435,7 @@ var Listeners = function () {
}); });
// Display duration // Display duration
utils.on(this.player.media, 'durationchange loadedmetadata', function (event) { utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', function (event) {
return ui.durationUpdate.call(_this3.player, event); return ui.durationUpdate.call(_this3.player, event);
}); });
@@ -4505,7 +4529,7 @@ var Listeners = function () {
// Disable right click // Disable right click
if (this.player.supported.ui && this.player.config.disableContextMenu) { if (this.player.supported.ui && this.player.config.disableContextMenu) {
utils.on(this.player.media, 'contextmenu', function (event) { utils.on(this.player.elements.wrapper, 'contextmenu', function (event) {
event.preventDefault(); event.preventDefault();
}, false); }, false);
} }
@@ -6149,7 +6173,9 @@ var vimeo = {
utils.dispatchEvent.call(player, player.media, 'seeking'); utils.dispatchEvent.call(player, player.media, 'seeking');
// Seek after events // Seek after events
player.embed.setCurrentTime(time); player.embed.setCurrentTime(time).catch(function () {
// Do nothing
});
// Restore pause state // Restore pause state
if (paused) { if (paused) {
@@ -6329,6 +6355,15 @@ var vimeo = {
if (parseInt(data.percent, 10) === 1) { if (parseInt(data.percent, 10) === 1) {
utils.dispatchEvent.call(player, player.media, 'canplaythrough'); utils.dispatchEvent.call(player, player.media, 'canplaythrough');
} }
// Get duration as if we do it before load, it gives an incorrect value
// https://github.com/sampotts/plyr/issues/891
player.embed.getDuration().then(function (value) {
if (value !== player.media.duration) {
player.media.duration = value;
utils.dispatchEvent.call(player, player.media, 'durationchange');
}
});
}); });
player.embed.on('seeked', function () { player.embed.on('seeked', function () {
@@ -7013,8 +7048,8 @@ var Plyr = function () {
* @param {boolean} input - Whether to enable captions * @param {boolean} input - Whether to enable captions
*/ */
value: function toggleCaptions(input) { value: function toggleCaptions(input) {
// If there's no full support, or there's no caption toggle // If there's no full support
if (!this.supported.ui || !utils.is.element(this.elements.buttons.captions)) { if (!this.supported.ui) {
return; return;
} }
@@ -7407,7 +7442,7 @@ var Plyr = function () {
} }
// Set // Set
this.media.currentTime = parseFloat(targetTime.toFixed(4)); this.media.currentTime = targetTime;
// Logging // Logging
this.debug.log('Seeking to ' + this.currentTime + ' seconds'); this.debug.log('Seeking to ' + this.currentTime + ' seconds');
@@ -7464,7 +7499,7 @@ var Plyr = function () {
key: 'duration', key: 'duration',
get: function get$$1() { get: function get$$1() {
// Faux duration set via config // Faux duration set via config
var fauxDuration = parseInt(this.config.duration, 10); var fauxDuration = parseFloat(this.config.duration);
// True duration // True duration
var realDuration = this.media ? Number(this.media.duration) : 0; var realDuration = this.media ? Number(this.media.duration) : 0;
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+123 -88
View File
@@ -5117,7 +5117,7 @@ var defaults = {
// Sprite (for icons) // Sprite (for icons)
loadSprite: true, loadSprite: true,
iconPrefix: 'plyr', iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/3.2.0/plyr.svg', iconUrl: 'https://cdn.plyr.io/3.2.4/plyr.svg',
// Blank video (used to prevent errors on source change) // Blank video (used to prevent errors on source change)
blankVideo: 'https://cdn.plyr.io/static/blank.mp4', blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
@@ -6135,6 +6135,26 @@ var utils = {
}, },
// Toggle hidden
toggleHidden: function toggleHidden(element, hidden) {
if (!utils.is.element(element)) {
return;
}
var hide = hidden;
if (!utils.is.boolean(hide)) {
hide = !element.hasAttribute('hidden');
}
if (hide) {
element.setAttribute('hidden', '');
} else {
element.removeAttribute('hidden');
}
},
// Toggle class on an element // Toggle class on an element
toggleClass: function toggleClass(element, className, toggle) { toggleClass: function toggleClass(element, className, toggle) {
if (utils.is.element(element)) { if (utils.is.element(element)) {
@@ -6155,20 +6175,6 @@ var utils = {
}, },
// Toggle hidden attribute on an element
toggleHidden: function toggleHidden(element, toggle) {
if (!utils.is.element(element)) {
return;
}
if (toggle) {
element.setAttribute('hidden', '');
} else {
element.removeAttribute('hidden');
}
},
// Element matches selector // Element matches selector
matches: function matches(element, selector) { matches: function matches(element, selector) {
var prototype = { Element: Element }; var prototype = { Element: Element };
@@ -6228,8 +6234,8 @@ var utils = {
// Display // Display
this.elements.display = { this.elements.display = {
buffer: utils.getElement.call(this, this.config.selectors.display.buffer), buffer: utils.getElement.call(this, this.config.selectors.display.buffer),
duration: utils.getElement.call(this, this.config.selectors.display.duration), currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),
currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime) duration: utils.getElement.call(this, this.config.selectors.display.duration)
}; };
// Seek tooltip // Seek tooltip
@@ -6986,7 +6992,7 @@ var Fullscreen = function () {
// Get prefix // Get prefix
this.prefix = Fullscreen.prefix; this.prefix = Fullscreen.prefix;
this.name = Fullscreen.name; this.property = Fullscreen.property;
// Scroll position // Scroll position
this.scrollPosition = { x: 0, y: 0 }; this.scrollPosition = { x: 0, y: 0 };
@@ -7001,7 +7007,7 @@ var Fullscreen = function () {
// Fullscreen toggle on double click // Fullscreen toggle on double click
utils.on(this.player.elements.container, 'dblclick', function (event) { utils.on(this.player.elements.container, 'dblclick', function (event) {
// Ignore double click in controls // Ignore double click in controls
if (_this.player.elements.controls.contains(event.target)) { if (utils.is.element(_this.player.elements.controls) && _this.player.elements.controls.contains(event.target)) {
return; return;
} }
@@ -7050,7 +7056,7 @@ var Fullscreen = function () {
} else if (!this.prefix) { } else if (!this.prefix) {
this.target.requestFullscreen(); this.target.requestFullscreen();
} else if (!utils.is.empty(this.prefix)) { } else if (!utils.is.empty(this.prefix)) {
this.target[this.prefix + 'Request' + this.name](); this.target[this.prefix + 'Request' + this.property]();
} }
} }
@@ -7073,7 +7079,7 @@ var Fullscreen = function () {
(document.cancelFullScreen || document.exitFullscreen).call(document); (document.cancelFullScreen || document.exitFullscreen).call(document);
} else if (!utils.is.empty(this.prefix)) { } else if (!utils.is.empty(this.prefix)) {
var action = this.prefix === 'moz' ? 'Cancel' : 'Exit'; var action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
document['' + this.prefix + action + this.name](); document['' + this.prefix + action + this.property]();
} }
} }
@@ -7111,7 +7117,7 @@ var Fullscreen = function () {
return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback); return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback);
} }
var element = !this.prefix ? document.fullscreenElement : document['' + this.prefix + this.name + 'Element']; var element = !this.prefix ? document.fullscreenElement : document['' + this.prefix + this.property + 'Element'];
return element === this.target; return element === this.target;
} }
@@ -7136,7 +7142,7 @@ var Fullscreen = function () {
get: function get() { get: function get() {
// No prefix // No prefix
if (utils.is.function(document.exitFullscreen)) { if (utils.is.function(document.exitFullscreen)) {
return false; return '';
} }
// Check for fullscreen support by vendor prefix // Check for fullscreen support by vendor prefix
@@ -7155,7 +7161,7 @@ var Fullscreen = function () {
return value; return value;
} }
}, { }, {
key: 'name', key: 'property',
get: function get() { get: function get() {
return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen'; return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';
} }
@@ -7448,11 +7454,6 @@ var captions = {
// Display captions container and button (for initialization) // Display captions container and button (for initialization)
show: function show() { show: function show() {
// If there's no caption toggle, bail
if (!utils.is.element(this.elements.buttons.captions)) {
return;
}
// Try to load the value from storage // Try to load the value from storage
var active = this.storage.get('captions'); var active = this.storage.get('captions');
@@ -7519,11 +7520,6 @@ var ui = {
this.listeners.controls(); this.listeners.controls();
} }
// If there's no controls, bail
if (!utils.is.element(this.elements.controls)) {
return;
}
// Remove native controls // Remove native controls
ui.toggleNativeControls.call(this); ui.toggleNativeControls.call(this);
@@ -7764,10 +7760,10 @@ var ui = {
} }
// Always display hours if duration is over an hour // Always display hours if duration is over an hour
var displayHours = utils.getHours(this.duration) > 0; var forceHours = utils.getHours(this.duration) > 0;
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
target.textContent = utils.formatTime(time, displayHours, inverted); target.textContent = utils.formatTime(time, forceHours, inverted);
}, },
@@ -7974,11 +7970,6 @@ var browser$1 = utils.getBrowser();
var controls = { var controls = {
// Webkit polyfill for lower fill range // Webkit polyfill for lower fill range
updateRangeFill: function updateRangeFill(target) { updateRangeFill: function updateRangeFill(target) {
// WebKit only
if (!browser$1.isWebkit) {
return;
}
// Get range from event if event passed // Get range from event if event passed
var range = utils.is.event(target) ? target.target : target; var range = utils.is.event(target) ? target.target : target;
@@ -7987,6 +7978,14 @@ var controls = {
return; return;
} }
// Set aria value for https://github.com/sampotts/plyr/issues/905
range.setAttribute('aria-valuenow', range.value);
// WebKit only
if (!browser$1.isWebkit) {
return;
}
// Set CSS custom property // Set CSS custom property
range.style.setProperty('--value', range.value / range.max * 100 + '%'); range.style.setProperty('--value', range.value / range.max * 100 + '%');
}, },
@@ -8010,7 +8009,8 @@ var controls = {
// Create <svg> // Create <svg>
var icon = document.createElementNS(namespace, 'svg'); var icon = document.createElementNS(namespace, 'svg');
utils.setAttributes(icon, utils.extend(attributes, { utils.setAttributes(icon, utils.extend(attributes, {
role: 'presentation' role: 'presentation',
focusable: 'false'
})); }));
// Create the <use> to reference sprite // Create the <use> to reference sprite
@@ -8161,7 +8161,6 @@ var controls = {
// Add aria attributes // Add aria attributes
attributes['aria-pressed'] = false; attributes['aria-pressed'] = false;
attributes['aria-label'] = i18n.get(label, this.config);
} else { } else {
button.appendChild(controls.createIcon.call(this, icon)); button.appendChild(controls.createIcon.call(this, icon));
button.appendChild(controls.createLabel.call(this, label)); button.appendChild(controls.createLabel.call(this, label));
@@ -8192,6 +8191,7 @@ var controls = {
// Seek label // Seek label
var label = utils.createElement('label', { var label = utils.createElement('label', {
for: attributes.id, for: attributes.id,
id: attributes.id + '-label',
class: this.config.classNames.hidden class: this.config.classNames.hidden
}, i18n.get(type, this.config)); }, i18n.get(type, this.config));
@@ -8202,7 +8202,13 @@ var controls = {
max: 100, max: 100,
step: 0.01, step: 0.01,
value: 0, value: 0,
autocomplete: 'off' autocomplete: 'off',
// A11y fixes for https://github.com/sampotts/plyr/issues/905
role: 'slider',
'aria-labelledby': attributes.id + '-label',
'aria-valuemin': 0,
'aria-valuemax': 100,
'aria-valuenow': 0
}, attributes)); }, attributes));
this.elements.inputs[type] = input; this.elements.inputs[type] = input;
@@ -8222,7 +8228,9 @@ var controls = {
var progress = utils.createElement('progress', utils.extend(utils.getAttributesFromSelector(this.config.selectors.display[type]), { var progress = utils.createElement('progress', utils.extend(utils.getAttributesFromSelector(this.config.selectors.display[type]), {
min: 0, min: 0,
max: 100, max: 100,
value: 0 value: 0,
role: 'presentation',
'aria-hidden': true
}, attributes)); }, attributes));
// Create the label inside // Create the label inside
@@ -8254,16 +8262,14 @@ var controls = {
// Create time display // Create time display
createTime: function createTime(type) { createTime: function createTime(type) {
var container = utils.createElement('div', { var attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]);
class: 'plyr__time'
});
container.appendChild(utils.createElement('span', { var container = utils.createElement('div', utils.extend(attributes, {
class: this.config.classNames.hidden class: 'plyr__time ' + attributes.class,
}, i18n.get(type, this.config))); 'aria-label': i18n.get(type, this.config)
}), '0:00');
container.appendChild(utils.createElement('span', utils.getAttributesFromSelector(this.config.selectors.display[type]), '00:00'));
// Reference for updates
this.elements.display[type] = container; this.elements.display[type] = container;
return container; return container;
@@ -8289,7 +8295,7 @@ var controls = {
class: 'plyr__sr-only' class: 'plyr__sr-only'
})); }));
var faux = utils.createElement('span', { 'aria-hidden': true }); var faux = utils.createElement('span', { hidden: '' });
label.appendChild(radio); label.appendChild(radio);
label.appendChild(faux); label.appendChild(faux);
@@ -8360,11 +8366,7 @@ var controls = {
// Hide/show a tab // Hide/show a tab
toggleTab: function toggleTab(setting, toggle) { toggleTab: function toggleTab(setting, toggle) {
var tab = this.elements.settings.tabs[setting]; utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);
var pane = this.elements.settings.panes[setting];
utils.toggleHidden(tab, !toggle);
utils.toggleHidden(pane, !toggle);
}, },
@@ -8576,7 +8578,6 @@ var controls = {
// Get current selected caption language // Get current selected caption language
// TODO: rework this to user the getter in the API? // TODO: rework this to user the getter in the API?
// Set a list of available captions languages // Set a list of available captions languages
setCaptionsMenu: function setCaptionsMenu() { setCaptionsMenu: function setCaptionsMenu() {
var _this3 = this; var _this3 = this;
@@ -8671,10 +8672,6 @@ var controls = {
// Get the list to populate // Get the list to populate
var list = this.elements.settings.panes.speed.querySelector('ul'); var list = this.elements.settings.panes.speed.querySelector('ul');
// Show the pane and tab
utils.toggleHidden(this.elements.settings.tabs.speed, false);
utils.toggleHidden(this.elements.settings.panes.speed, false);
// Empty the menu // Empty the menu
utils.emptyElement(list); utils.emptyElement(list);
@@ -8711,7 +8708,7 @@ var controls = {
return; return;
} }
var show = utils.is.boolean(event) ? event : utils.is.element(form) && form.getAttribute('aria-hidden') === 'true'; var show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden');
if (utils.is.event(event)) { if (utils.is.event(event)) {
var isMenuItem = utils.is.element(form) && form.contains(event.target); var isMenuItem = utils.is.element(form) && form.contains(event.target);
@@ -8736,7 +8733,7 @@ var controls = {
} }
if (utils.is.element(form)) { if (utils.is.element(form)) {
form.setAttribute('aria-hidden', !show); utils.toggleHidden(form, !show);
utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show); utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show);
if (show) { if (show) {
@@ -8753,7 +8750,7 @@ var controls = {
var clone = tab.cloneNode(true); var clone = tab.cloneNode(true);
clone.style.position = 'absolute'; clone.style.position = 'absolute';
clone.style.opacity = 0; clone.style.opacity = 0;
clone.setAttribute('aria-hidden', false); clone.removeAttribute('hidden');
// Prevent input's being unchecked due to the name being identical // Prevent input's being unchecked due to the name being identical
Array.from(clone.querySelectorAll('input[name]')).forEach(function (input) { Array.from(clone.querySelectorAll('input[name]')).forEach(function (input) {
@@ -8799,7 +8796,7 @@ var controls = {
// Hide all other tabs // Hide all other tabs
// Get other tabs // Get other tabs
var current = menu.querySelector('[role="tabpanel"][aria-hidden="false"]'); var current = menu.querySelector('[role="tabpanel"]:not([hidden])');
var container = current.parentNode; var container = current.parentNode;
// Set other toggles to be expanded false // Set other toggles to be expanded false
@@ -8840,11 +8837,11 @@ var controls = {
} }
// Set attributes on current tab // Set attributes on current tab
current.setAttribute('aria-hidden', true); utils.toggleHidden(current, true);
current.setAttribute('tabindex', -1); current.setAttribute('tabindex', -1);
// Set attributes on target // Set attributes on target
pane.setAttribute('aria-hidden', !show); utils.toggleHidden(pane, !show);
tab.setAttribute('aria-expanded', show); tab.setAttribute('aria-expanded', show);
pane.removeAttribute('tabindex'); pane.removeAttribute('tabindex');
@@ -8979,7 +8976,7 @@ var controls = {
var form = utils.createElement('form', { var form = utils.createElement('form', {
class: 'plyr__menu__container', class: 'plyr__menu__container',
id: 'plyr-settings-' + data.id, id: 'plyr-settings-' + data.id,
'aria-hidden': true, hidden: '',
'aria-labelled-by': 'plyr-settings-toggle-' + data.id, 'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
role: 'tablist', role: 'tablist',
tabindex: -1 tabindex: -1
@@ -8989,7 +8986,6 @@ var controls = {
var home = utils.createElement('div', { var home = utils.createElement('div', {
id: 'plyr-settings-' + data.id + '-home', id: 'plyr-settings-' + data.id + '-home',
'aria-hidden': false,
'aria-labelled-by': 'plyr-settings-toggle-' + data.id, 'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
role: 'tabpanel' role: 'tabpanel'
}); });
@@ -9036,11 +9032,10 @@ var controls = {
this.config.settings.forEach(function (type) { this.config.settings.forEach(function (type) {
var pane = utils.createElement('div', { var pane = utils.createElement('div', {
id: 'plyr-settings-' + data.id + '-' + type, id: 'plyr-settings-' + data.id + '-' + type,
'aria-hidden': true, hidden: '',
'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab', 'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab',
role: 'tabpanel', role: 'tabpanel',
tabindex: -1, tabindex: -1
hidden: ''
}); });
var back = utils.createElement('button', { var back = utils.createElement('button', {
@@ -9122,17 +9117,21 @@ var controls = {
var container = null; var container = null;
this.elements.controls = null; this.elements.controls = null;
// HTML or Element passed as the option // Set template properties
var props = {
id: this.id,
seektime: this.config.seekTime,
title: this.config.title
};
var update = true;
if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) { if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) {
// String or HTMLElement passed as the option
container = this.config.controls; container = this.config.controls;
} else if (utils.is.function(this.config.controls)) { } else if (utils.is.function(this.config.controls)) {
// A custom function to build controls // A custom function to build controls
// The function can return a HTMLElement or String // The function can return a HTMLElement or String
container = this.config.controls({ container = this.config.controls.call(this, props);
id: this.id,
seektime: this.config.seekTime,
title: this.config.title
});
} else { } else {
// Create controls // Create controls
container = controls.create.call(this, { container = controls.create.call(this, {
@@ -9144,6 +9143,31 @@ var controls = {
// TODO: Looping // TODO: Looping
// loop: 'None', // loop: 'None',
}); });
update = false;
}
// Replace props with their value
var replace = function replace(input) {
var result = input;
Object.entries(props).forEach(function (_ref) {
var _ref2 = slicedToArray(_ref, 2),
key = _ref2[0],
value = _ref2[1];
result = utils.replaceAll(result, '{' + key + '}', value);
});
return result;
};
// Update markup
if (update) {
if (utils.is.string(this.config.controls)) {
container = replace(container);
} else if (utils.is.element(container)) {
container.innerHTML = replace(container.innerHTML);
}
} }
// Controls container // Controls container
@@ -9445,7 +9469,7 @@ var Listeners = function () {
}); });
// Display duration // Display duration
utils.on(this.player.media, 'durationchange loadedmetadata', function (event) { utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', function (event) {
return ui.durationUpdate.call(_this3.player, event); return ui.durationUpdate.call(_this3.player, event);
}); });
@@ -9539,7 +9563,7 @@ var Listeners = function () {
// Disable right click // Disable right click
if (this.player.supported.ui && this.player.config.disableContextMenu) { if (this.player.supported.ui && this.player.config.disableContextMenu) {
utils.on(this.player.media, 'contextmenu', function (event) { utils.on(this.player.elements.wrapper, 'contextmenu', function (event) {
event.preventDefault(); event.preventDefault();
}, false); }, false);
} }
@@ -11183,7 +11207,9 @@ var vimeo = {
utils.dispatchEvent.call(player, player.media, 'seeking'); utils.dispatchEvent.call(player, player.media, 'seeking');
// Seek after events // Seek after events
player.embed.setCurrentTime(time); player.embed.setCurrentTime(time).catch(function () {
// Do nothing
});
// Restore pause state // Restore pause state
if (paused) { if (paused) {
@@ -11363,6 +11389,15 @@ var vimeo = {
if (parseInt(data.percent, 10) === 1) { if (parseInt(data.percent, 10) === 1) {
utils.dispatchEvent.call(player, player.media, 'canplaythrough'); utils.dispatchEvent.call(player, player.media, 'canplaythrough');
} }
// Get duration as if we do it before load, it gives an incorrect value
// https://github.com/sampotts/plyr/issues/891
player.embed.getDuration().then(function (value) {
if (value !== player.media.duration) {
player.media.duration = value;
utils.dispatchEvent.call(player, player.media, 'durationchange');
}
});
}); });
player.embed.on('seeked', function () { player.embed.on('seeked', function () {
@@ -12047,8 +12082,8 @@ var Plyr = function () {
* @param {boolean} input - Whether to enable captions * @param {boolean} input - Whether to enable captions
*/ */
value: function toggleCaptions(input) { value: function toggleCaptions(input) {
// If there's no full support, or there's no caption toggle // If there's no full support
if (!this.supported.ui || !utils.is.element(this.elements.buttons.captions)) { if (!this.supported.ui) {
return; return;
} }
@@ -12441,7 +12476,7 @@ var Plyr = function () {
} }
// Set // Set
this.media.currentTime = parseFloat(targetTime.toFixed(4)); this.media.currentTime = targetTime;
// Logging // Logging
this.debug.log('Seeking to ' + this.currentTime + ' seconds'); this.debug.log('Seeking to ' + this.currentTime + ' seconds');
@@ -12498,7 +12533,7 @@ var Plyr = function () {
key: 'duration', key: 'duration',
get: function get() { get: function get() {
// Faux duration set via config // Faux duration set via config
var fauxDuration = parseInt(this.config.duration, 10); var fauxDuration = parseFloat(this.config.duration);
// True duration // True duration
var realDuration = this.media ? Number(this.media.duration) : 0; var realDuration = this.media ? Number(this.media.duration) : 0;
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+5 -4
View File
@@ -1,6 +1,6 @@
{ {
"name": "plyr", "name": "plyr",
"version": "3.2.0", "version": "3.2.4",
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player", "description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
"homepage": "https://plyr.io", "homepage": "https://plyr.io",
"main": "./dist/plyr.js", "main": "./dist/plyr.js",
@@ -37,7 +37,7 @@
"gulp-util": "^3.0.8", "gulp-util": "^3.0.8",
"prettier-eslint": "^8.8.1", "prettier-eslint": "^8.8.1",
"prettier-stylelint": "^0.4.2", "prettier-stylelint": "^0.4.2",
"rollup-plugin-babel": "^3.0.3", "rollup-plugin-babel": "^3.0.4",
"rollup-plugin-commonjs": "^9.1.0", "rollup-plugin-commonjs": "^9.1.0",
"rollup-plugin-node-resolve": "^3.3.0", "rollup-plugin-node-resolve": "^3.3.0",
"run-sequence": "^2.2.1", "run-sequence": "^2.2.1",
@@ -46,7 +46,7 @@
"stylelint-config-recommended": "^2.1.0", "stylelint-config-recommended": "^2.1.0",
"stylelint-config-sass-guidelines": "^5.0.0", "stylelint-config-sass-guidelines": "^5.0.0",
"stylelint-order": "^0.8.1", "stylelint-order": "^0.8.1",
"stylelint-scss": "^3.0.0", "stylelint-scss": "^3.0.1",
"stylelint-selector-bem-pattern": "^2.0.0" "stylelint-selector-bem-pattern": "^2.0.0"
}, },
"keywords": ["HTML5 Video", "HTML5 Audio", "Media Player", "DASH", "Shaka", "WordPress", "HLS"], "keywords": ["HTML5 Video", "HTML5 Audio", "Media Player", "DASH", "Shaka", "WordPress", "HLS"],
@@ -69,6 +69,7 @@
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",
"custom-event-polyfill": "^0.3.0", "custom-event-polyfill": "^0.3.0",
"loadjs": "^3.5.4", "loadjs": "^3.5.4",
"raven-js": "^3.24.0" "npm": "^6.0.0",
"raven-js": "^3.24.2"
} }
} }
+3 -3
View File
@@ -128,7 +128,7 @@ See [initialising](#initialising) for more information on advanced setups.
If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript, you can use the following: If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the JavaScript, you can use the following:
```html ```html
<script src="https://cdn.plyr.io/3.2.0/plyr.js"></script> <script src="https://cdn.plyr.io/3.2.4/plyr.js"></script>
``` ```
_Note_: Be sure to read the [polyfills](#polyfills) section below about browser compatibility _Note_: Be sure to read the [polyfills](#polyfills) section below about browser compatibility
@@ -144,13 +144,13 @@ Include the `plyr.css` stylsheet into your `<head>`
If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the default CSS, you can use the following: If you want to use our CDN (provided by [Fastly](https://www.fastly.com/)) for the default CSS, you can use the following:
```html ```html
<link rel="stylesheet" href="https://cdn.plyr.io/3.2.0/plyr.css"> <link rel="stylesheet" href="https://cdn.plyr.io/3.2.4/plyr.css">
``` ```
### SVG Sprite ### SVG Sprite
The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For The SVG sprite is loaded automatically from our CDN (provided by [Fastly](https://www.fastly.com/)). To change this, see the [options](#options) below. For
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.2.0/plyr.svg`. reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.2.4/plyr.svg`.
## Ads ## Ads
-5
View File
@@ -250,11 +250,6 @@ const captions = {
// Display captions container and button (for initialization) // Display captions container and button (for initialization)
show() { show() {
// If there's no caption toggle, bail
if (!utils.is.element(this.elements.buttons.captions)) {
return;
}
// Try to load the value from storage // Try to load the value from storage
let active = this.storage.get('captions'); let active = this.storage.get('captions');
+68 -47
View File
@@ -15,11 +15,6 @@ const browser = utils.getBrowser();
const controls = { const controls = {
// Webkit polyfill for lower fill range // Webkit polyfill for lower fill range
updateRangeFill(target) { updateRangeFill(target) {
// WebKit only
if (!browser.isWebkit) {
return;
}
// Get range from event if event passed // Get range from event if event passed
const range = utils.is.event(target) ? target.target : target; const range = utils.is.event(target) ? target.target : target;
@@ -28,6 +23,14 @@ const controls = {
return; return;
} }
// Set aria value for https://github.com/sampotts/plyr/issues/905
range.setAttribute('aria-valuenow', range.value);
// WebKit only
if (!browser.isWebkit) {
return;
}
// Set CSS custom property // Set CSS custom property
range.style.setProperty('--value', `${range.value / range.max * 100}%`); range.style.setProperty('--value', `${range.value / range.max * 100}%`);
}, },
@@ -52,6 +55,7 @@ const controls = {
icon, icon,
utils.extend(attributes, { utils.extend(attributes, {
role: 'presentation', role: 'presentation',
focusable: 'false',
}), }),
); );
@@ -206,7 +210,6 @@ const controls = {
// Add aria attributes // Add aria attributes
attributes['aria-pressed'] = false; attributes['aria-pressed'] = false;
attributes['aria-label'] = i18n.get(label, this.config);
} else { } else {
button.appendChild(controls.createIcon.call(this, icon)); button.appendChild(controls.createIcon.call(this, icon));
button.appendChild(controls.createLabel.call(this, label)); button.appendChild(controls.createLabel.call(this, label));
@@ -238,6 +241,7 @@ const controls = {
'label', 'label',
{ {
for: attributes.id, for: attributes.id,
id: `${attributes.id}-label`,
class: this.config.classNames.hidden, class: this.config.classNames.hidden,
}, },
i18n.get(type, this.config), i18n.get(type, this.config),
@@ -255,6 +259,12 @@ const controls = {
step: 0.01, step: 0.01,
value: 0, value: 0,
autocomplete: 'off', autocomplete: 'off',
// A11y fixes for https://github.com/sampotts/plyr/issues/905
role: 'slider',
'aria-labelledby': `${attributes.id}-label`,
'aria-valuemin': 0,
'aria-valuemax': 100,
'aria-valuenow': 0,
}, },
attributes, attributes,
), ),
@@ -281,6 +291,8 @@ const controls = {
min: 0, min: 0,
max: 100, max: 100,
value: 0, value: 0,
role: 'presentation',
'aria-hidden': true,
}, },
attributes, attributes,
), ),
@@ -314,22 +326,14 @@ const controls = {
// Create time display // Create time display
createTime(type) { createTime(type) {
const container = utils.createElement('div', { const attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]);
class: 'plyr__time',
});
container.appendChild( const container = utils.createElement('div', utils.extend(attributes, {
utils.createElement( class: `plyr__time ${attributes.class}`,
'span', 'aria-label': i18n.get(type, this.config),
{ }), '0:00');
class: this.config.classNames.hidden,
},
i18n.get(type, this.config),
),
);
container.appendChild(utils.createElement('span', utils.getAttributesFromSelector(this.config.selectors.display[type]), '00:00'));
// Reference for updates
this.elements.display[type] = container; this.elements.display[type] = container;
return container; return container;
@@ -354,7 +358,7 @@ const controls = {
}), }),
); );
const faux = utils.createElement('span', { 'aria-hidden': true }); const faux = utils.createElement('span', { hidden: '' });
label.appendChild(radio); label.appendChild(radio);
label.appendChild(faux); label.appendChild(faux);
@@ -429,11 +433,7 @@ const controls = {
// Hide/show a tab // Hide/show a tab
toggleTab(setting, toggle) { toggleTab(setting, toggle) {
const tab = this.elements.settings.tabs[setting]; utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);
const pane = this.elements.settings.panes[setting];
utils.toggleHidden(tab, !toggle);
utils.toggleHidden(pane, !toggle);
}, },
// Set the quality menu // Set the quality menu
@@ -645,7 +645,6 @@ const controls = {
// Get current selected caption language // Get current selected caption language
// TODO: rework this to user the getter in the API? // TODO: rework this to user the getter in the API?
// Set a list of available captions languages // Set a list of available captions languages
setCaptionsMenu() { setCaptionsMenu() {
// TODO: Captions or language? Currently it's mixed // TODO: Captions or language? Currently it's mixed
@@ -745,10 +744,6 @@ const controls = {
// Get the list to populate // Get the list to populate
const list = this.elements.settings.panes.speed.querySelector('ul'); const list = this.elements.settings.panes.speed.querySelector('ul');
// Show the pane and tab
utils.toggleHidden(this.elements.settings.tabs.speed, false);
utils.toggleHidden(this.elements.settings.panes.speed, false);
// Empty the menu // Empty the menu
utils.emptyElement(list); utils.emptyElement(list);
@@ -779,7 +774,7 @@ const controls = {
return; return;
} }
const show = utils.is.boolean(event) ? event : utils.is.element(form) && form.getAttribute('aria-hidden') === 'true'; const show = utils.is.boolean(event) ? event : utils.is.element(form) && form.hasAttribute('hidden');
if (utils.is.event(event)) { if (utils.is.event(event)) {
const isMenuItem = utils.is.element(form) && form.contains(event.target); const isMenuItem = utils.is.element(form) && form.contains(event.target);
@@ -804,7 +799,7 @@ const controls = {
} }
if (utils.is.element(form)) { if (utils.is.element(form)) {
form.setAttribute('aria-hidden', !show); utils.toggleHidden(form, !show);
utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show); utils.toggleClass(this.elements.container, this.config.classNames.menu.open, show);
if (show) { if (show) {
@@ -820,7 +815,7 @@ const controls = {
const clone = tab.cloneNode(true); const clone = tab.cloneNode(true);
clone.style.position = 'absolute'; clone.style.position = 'absolute';
clone.style.opacity = 0; clone.style.opacity = 0;
clone.setAttribute('aria-hidden', false); clone.removeAttribute('hidden');
// Prevent input's being unchecked due to the name being identical // Prevent input's being unchecked due to the name being identical
Array.from(clone.querySelectorAll('input[name]')).forEach(input => { Array.from(clone.querySelectorAll('input[name]')).forEach(input => {
@@ -864,7 +859,7 @@ const controls = {
// Hide all other tabs // Hide all other tabs
// Get other tabs // Get other tabs
const current = menu.querySelector('[role="tabpanel"][aria-hidden="false"]'); const current = menu.querySelector('[role="tabpanel"]:not([hidden])');
const container = current.parentNode; const container = current.parentNode;
// Set other toggles to be expanded false // Set other toggles to be expanded false
@@ -908,11 +903,11 @@ const controls = {
} }
// Set attributes on current tab // Set attributes on current tab
current.setAttribute('aria-hidden', true); utils.toggleHidden(current, true);
current.setAttribute('tabindex', -1); current.setAttribute('tabindex', -1);
// Set attributes on target // Set attributes on target
pane.setAttribute('aria-hidden', !show); utils.toggleHidden(pane, !show);
tab.setAttribute('aria-expanded', show); tab.setAttribute('aria-expanded', show);
pane.removeAttribute('tabindex'); pane.removeAttribute('tabindex');
@@ -1054,7 +1049,7 @@ const controls = {
const form = utils.createElement('form', { const form = utils.createElement('form', {
class: 'plyr__menu__container', class: 'plyr__menu__container',
id: `plyr-settings-${data.id}`, id: `plyr-settings-${data.id}`,
'aria-hidden': true, hidden: '',
'aria-labelled-by': `plyr-settings-toggle-${data.id}`, 'aria-labelled-by': `plyr-settings-toggle-${data.id}`,
role: 'tablist', role: 'tablist',
tabindex: -1, tabindex: -1,
@@ -1064,7 +1059,6 @@ const controls = {
const home = utils.createElement('div', { const home = utils.createElement('div', {
id: `plyr-settings-${data.id}-home`, id: `plyr-settings-${data.id}-home`,
'aria-hidden': false,
'aria-labelled-by': `plyr-settings-toggle-${data.id}`, 'aria-labelled-by': `plyr-settings-toggle-${data.id}`,
role: 'tabpanel', role: 'tabpanel',
}); });
@@ -1115,11 +1109,10 @@ const controls = {
this.config.settings.forEach(type => { this.config.settings.forEach(type => {
const pane = utils.createElement('div', { const pane = utils.createElement('div', {
id: `plyr-settings-${data.id}-${type}`, id: `plyr-settings-${data.id}-${type}`,
'aria-hidden': true, hidden: '',
'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`, 'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`,
role: 'tabpanel', role: 'tabpanel',
tabindex: -1, tabindex: -1,
hidden: '',
}); });
const back = utils.createElement( const back = utils.createElement(
@@ -1202,17 +1195,21 @@ const controls = {
let container = null; let container = null;
this.elements.controls = null; this.elements.controls = null;
// HTML or Element passed as the option // Set template properties
const props = {
id: this.id,
seektime: this.config.seekTime,
title: this.config.title,
};
let update = true;
if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) { if (utils.is.string(this.config.controls) || utils.is.element(this.config.controls)) {
// String or HTMLElement passed as the option
container = this.config.controls; container = this.config.controls;
} else if (utils.is.function(this.config.controls)) { } else if (utils.is.function(this.config.controls)) {
// A custom function to build controls // A custom function to build controls
// The function can return a HTMLElement or String // The function can return a HTMLElement or String
container = this.config.controls({ container = this.config.controls.call(this, props);
id: this.id,
seektime: this.config.seekTime,
title: this.config.title,
});
} else { } else {
// Create controls // Create controls
container = controls.create.call(this, { container = controls.create.call(this, {
@@ -1224,6 +1221,30 @@ const controls = {
// TODO: Looping // TODO: Looping
// loop: 'None', // loop: 'None',
}); });
update = false;
}
// Replace props with their value
const replace = input => {
let result = input;
Object.entries(props).forEach(([
key,
value,
]) => {
result = utils.replaceAll(result, `{${key}}`, value);
});
return result;
};
// Update markup
if (update) {
if (utils.is.string(this.config.controls)) {
container = replace(container);
} else if (utils.is.element(container)) {
container.innerHTML = replace(container.innerHTML);
}
} }
// Controls container // Controls container
+1 -1
View File
@@ -56,7 +56,7 @@ const defaults = {
// Sprite (for icons) // Sprite (for icons)
loadSprite: true, loadSprite: true,
iconPrefix: 'plyr', iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/3.2.0/plyr.svg', iconUrl: 'https://cdn.plyr.io/3.2.4/plyr.svg',
// Blank video (used to prevent errors on source change) // Blank video (used to prevent errors on source change)
blankVideo: 'https://cdn.plyr.io/static/blank.mp4', blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
+7 -7
View File
@@ -55,7 +55,7 @@ class Fullscreen {
// Get prefix // Get prefix
this.prefix = Fullscreen.prefix; this.prefix = Fullscreen.prefix;
this.name = Fullscreen.name; this.property = Fullscreen.property;
// Scroll position // Scroll position
this.scrollPosition = { x: 0, y: 0 }; this.scrollPosition = { x: 0, y: 0 };
@@ -70,7 +70,7 @@ class Fullscreen {
// Fullscreen toggle on double click // Fullscreen toggle on double click
utils.on(this.player.elements.container, 'dblclick', event => { utils.on(this.player.elements.container, 'dblclick', event => {
// Ignore double click in controls // Ignore double click in controls
if (this.player.elements.controls.contains(event.target)) { if (utils.is.element(this.player.elements.controls) && this.player.elements.controls.contains(event.target)) {
return; return;
} }
@@ -90,7 +90,7 @@ class Fullscreen {
static get prefix() { static get prefix() {
// No prefix // No prefix
if (utils.is.function(document.exitFullscreen)) { if (utils.is.function(document.exitFullscreen)) {
return false; return '';
} }
// Check for fullscreen support by vendor prefix // Check for fullscreen support by vendor prefix
@@ -113,7 +113,7 @@ class Fullscreen {
return value; return value;
} }
static get name() { static get property() {
return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen'; return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';
} }
@@ -138,7 +138,7 @@ class Fullscreen {
return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback); return utils.hasClass(this.target, this.player.config.classNames.fullscreen.fallback);
} }
const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.name}Element`]; const element = !this.prefix ? document.fullscreenElement : document[`${this.prefix}${this.property}Element`];
return element === this.target; return element === this.target;
} }
@@ -176,7 +176,7 @@ class Fullscreen {
} else if (!this.prefix) { } else if (!this.prefix) {
this.target.requestFullscreen(); this.target.requestFullscreen();
} else if (!utils.is.empty(this.prefix)) { } else if (!utils.is.empty(this.prefix)) {
this.target[`${this.prefix}Request${this.name}`](); this.target[`${this.prefix}Request${this.property}`]();
} }
} }
@@ -196,7 +196,7 @@ class Fullscreen {
(document.cancelFullScreen || document.exitFullscreen).call(document); (document.cancelFullScreen || document.exitFullscreen).call(document);
} else if (!utils.is.empty(this.prefix)) { } else if (!utils.is.empty(this.prefix)) {
const action = this.prefix === 'moz' ? 'Cancel' : 'Exit'; const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
document[`${this.prefix}${action}${this.name}`](); document[`${this.prefix}${action}${this.property}`]();
} }
} }
+2 -2
View File
@@ -253,7 +253,7 @@ class Listeners {
utils.on(this.player.media, 'timeupdate seeking', event => ui.timeUpdate.call(this.player, event)); utils.on(this.player.media, 'timeupdate seeking', event => ui.timeUpdate.call(this.player, event));
// Display duration // Display duration
utils.on(this.player.media, 'durationchange loadedmetadata', event => ui.durationUpdate.call(this.player, event)); utils.on(this.player.media, 'durationchange loadeddata loadedmetadata', event => ui.durationUpdate.call(this.player, event));
// Check for audio tracks on load // Check for audio tracks on load
// We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point // We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point
@@ -334,7 +334,7 @@ class Listeners {
// Disable right click // Disable right click
if (this.player.supported.ui && this.player.config.disableContextMenu) { if (this.player.supported.ui && this.player.config.disableContextMenu) {
utils.on( utils.on(
this.player.media, this.player.elements.wrapper,
'contextmenu', 'contextmenu',
event => { event => {
event.preventDefault(); event.preventDefault();
+12 -1
View File
@@ -134,7 +134,9 @@ const vimeo = {
utils.dispatchEvent.call(player, player.media, 'seeking'); utils.dispatchEvent.call(player, player.media, 'seeking');
// Seek after events // Seek after events
player.embed.setCurrentTime(time); player.embed.setCurrentTime(time).catch(() => {
// Do nothing
});
// Restore pause state // Restore pause state
if (paused) { if (paused) {
@@ -320,6 +322,15 @@ const vimeo = {
if (parseInt(data.percent, 10) === 1) { if (parseInt(data.percent, 10) === 1) {
utils.dispatchEvent.call(player, player.media, 'canplaythrough'); utils.dispatchEvent.call(player, player.media, 'canplaythrough');
} }
// Get duration as if we do it before load, it gives an incorrect value
// https://github.com/sampotts/plyr/issues/891
player.embed.getDuration().then(value => {
if (value !== player.media.duration) {
player.media.duration = value;
utils.dispatchEvent.call(player, player.media, 'durationchange');
}
});
}); });
player.embed.on('seeked', () => { player.embed.on('seeked', () => {
+5 -5
View File
@@ -1,6 +1,6 @@
// ========================================================================== // ==========================================================================
// Plyr // Plyr
// plyr.js v3.2.0 // plyr.js v3.2.4
// https://github.com/sampotts/plyr // https://github.com/sampotts/plyr
// License: The MIT License (MIT) // License: The MIT License (MIT)
// ========================================================================== // ==========================================================================
@@ -452,7 +452,7 @@ class Plyr {
} }
// Set // Set
this.media.currentTime = parseFloat(targetTime.toFixed(4)); this.media.currentTime = targetTime;
// Logging // Logging
this.debug.log(`Seeking to ${this.currentTime} seconds`); this.debug.log(`Seeking to ${this.currentTime} seconds`);
@@ -498,7 +498,7 @@ class Plyr {
*/ */
get duration() { get duration() {
// Faux duration set via config // Faux duration set via config
const fauxDuration = parseInt(this.config.duration, 10); const fauxDuration = parseFloat(this.config.duration);
// True duration // True duration
const realDuration = this.media ? Number(this.media.duration) : 0; const realDuration = this.media ? Number(this.media.duration) : 0;
@@ -845,8 +845,8 @@ class Plyr {
* @param {boolean} input - Whether to enable captions * @param {boolean} input - Whether to enable captions
*/ */
toggleCaptions(input) { toggleCaptions(input) {
// If there's no full support, or there's no caption toggle // If there's no full support
if (!this.supported.ui || !utils.is.element(this.elements.buttons.captions)) { if (!this.supported.ui) {
return; return;
} }
+1 -1
View File
@@ -1,6 +1,6 @@
// ========================================================================== // ==========================================================================
// Plyr Polyfilled Build // Plyr Polyfilled Build
// plyr.js v3.2.0 // plyr.js v3.2.4
// https://github.com/sampotts/plyr // https://github.com/sampotts/plyr
// License: The MIT License (MIT) // License: The MIT License (MIT)
// ========================================================================== // ==========================================================================
+2 -7
View File
@@ -48,11 +48,6 @@ const ui = {
this.listeners.controls(); this.listeners.controls();
} }
// If there's no controls, bail
if (!utils.is.element(this.elements.controls)) {
return;
}
// Remove native controls // Remove native controls
ui.toggleNativeControls.call(this); ui.toggleNativeControls.call(this);
@@ -277,10 +272,10 @@ const ui = {
} }
// Always display hours if duration is over an hour // Always display hours if duration is over an hour
const displayHours = utils.getHours(this.duration) > 0; const forceHours = utils.getHours(this.duration) > 0;
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
target.textContent = utils.formatTime(time, displayHours, inverted); target.textContent = utils.formatTime(time, forceHours, inverted);
}, },
// Handle time change event // Handle time change event
+21 -15
View File
@@ -375,6 +375,25 @@ const utils = {
return attributes; return attributes;
}, },
// Toggle hidden
toggleHidden(element, hidden) {
if (!utils.is.element(element)) {
return;
}
let hide = hidden;
if (!utils.is.boolean(hide)) {
hide = !element.hasAttribute('hidden');
}
if (hide) {
element.setAttribute('hidden', '');
} else {
element.removeAttribute('hidden');
}
},
// Toggle class on an element // Toggle class on an element
toggleClass(element, className, toggle) { toggleClass(element, className, toggle) {
if (utils.is.element(element)) { if (utils.is.element(element)) {
@@ -393,19 +412,6 @@ const utils = {
return utils.is.element(element) && element.classList.contains(className); return utils.is.element(element) && element.classList.contains(className);
}, },
// Toggle hidden attribute on an element
toggleHidden(element, toggle) {
if (!utils.is.element(element)) {
return;
}
if (toggle) {
element.setAttribute('hidden', '');
} else {
element.removeAttribute('hidden');
}
},
// Element matches selector // Element matches selector
matches(element, selector) { matches(element, selector) {
const prototype = { Element }; const prototype = { Element };
@@ -462,8 +468,8 @@ const utils = {
// Display // Display
this.elements.display = { this.elements.display = {
buffer: utils.getElement.call(this, this.config.selectors.display.buffer), buffer: utils.getElement.call(this, this.config.selectors.display.buffer),
duration: utils.getElement.call(this, this.config.selectors.display.duration),
currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime), currentTime: utils.getElement.call(this, this.config.selectors.display.currentTime),
duration: utils.getElement.call(this, this.config.selectors.display.duration),
}; };
// Seek tooltip // Seek tooltip
@@ -752,7 +758,7 @@ const utils = {
return null; return null;
} }
return array.reduce((prev, curr) => Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev); return array.reduce((prev, curr) => (Math.abs(curr - value) < Math.abs(prev - value) ? curr : prev));
}, },
// Get the provider for a given URL // Get the provider for a given URL
+7 -2
View File
@@ -23,7 +23,12 @@
// Hide sound controls on iOS // Hide sound controls on iOS
// It's not supported to change volume using JavaScript: // It's not supported to change volume using JavaScript:
// https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html // https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html
.plyr--is-ios .plyr__volume, .plyr--is-ios .plyr__volume {
.plyr--is-ios [data-plyr='mute'] { display: none !important;
}
// Vimeo has no toggle mute method so hide mute button
// https://github.com/vimeo/player.js/issues/236#issuecomment-384663183
.plyr--is-ios.plyr--vimeo [data-plyr='mute'] {
display: none !important; display: none !important;
} }
-9
View File
@@ -2,15 +2,6 @@
// Hiding content nicely // Hiding content nicely
// -------------------------------------------------------------- // --------------------------------------------------------------
// Attributes
.plyr--full-ui [hidden] {
display: none;
}
.plyr--full-ui [aria-hidden='true'] {
display: none;
}
// Screen reader only elements // Screen reader only elements
.plyr__sr-only { .plyr__sr-only {
clip: rect(1px, 1px, 1px, 1px); clip: rect(1px, 1px, 1px, 1px);
+1473 -68
View File
File diff suppressed because it is too large Load Diff