Merge branch 'master' into develop
This commit is contained in:
commit
24d833a5d1
18
changelog.md
18
changelog.md
@ -1,3 +1,21 @@
|
||||
## 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)
|
||||
|
@ -121,7 +121,8 @@ const controls = `
|
||||
<progress class="plyr__progress--buffer" min="0" max="100" value="0">% buffered</progress>
|
||||
<span role="tooltip" class="plyr__tooltip">00:00</span>
|
||||
</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">
|
||||
<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>
|
||||
|
2
demo/dist/demo.css
vendored
2
demo/dist/demo.css
vendored
File diff suppressed because one or more lines are too long
72
demo/dist/demo.js
vendored
72
demo/dist/demo.js
vendored
@ -245,7 +245,13 @@ function objectFrozen(obj) {
|
||||
}
|
||||
|
||||
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) {
|
||||
var maxLength = 40;
|
||||
|
||||
if (typeof value === 'string') {
|
||||
return value.length <= maxLength ? value : value.substr(0, maxLength - 1) + '\u2026';
|
||||
var maxLength = 40;
|
||||
return truncate(value, maxLength);
|
||||
} else if (
|
||||
typeof value === 'number' ||
|
||||
typeof value === 'boolean' ||
|
||||
@ -1777,7 +1782,7 @@ Raven.prototype = {
|
||||
// webpack (using a build step causes webpack #1617). Grunt verifies that
|
||||
// this value matches package.json during build.
|
||||
// See: https://github.com/getsentry/raven-js/issues/465
|
||||
VERSION: '3.24.0',
|
||||
VERSION: '3.24.2',
|
||||
|
||||
debug: false,
|
||||
|
||||
@ -2066,7 +2071,11 @@ Raven.prototype = {
|
||||
*/
|
||||
_promiseRejectionHandler: function(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]
|
||||
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) || '';
|
||||
|
||||
if (
|
||||
@ -3004,17 +3021,30 @@ Raven.prototype = {
|
||||
status_code: null
|
||||
};
|
||||
|
||||
return origFetch.apply(this, args).then(function(response) {
|
||||
fetchData.status_code = response.status;
|
||||
return origFetch
|
||||
.apply(this, args)
|
||||
.then(function(response) {
|
||||
fetchData.status_code = response.status;
|
||||
|
||||
self.captureBreadcrumb({
|
||||
type: 'http',
|
||||
category: 'fetch',
|
||||
data: fetchData
|
||||
self.captureBreadcrumb({
|
||||
type: 'http',
|
||||
category: 'fetch',
|
||||
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
|
||||
@ -3027,7 +3057,7 @@ Raven.prototype = {
|
||||
if (_document.addEventListener) {
|
||||
_document.addEventListener('click', self._breadcrumbEventHandler('click'), false);
|
||||
_document.addEventListener('keypress', self._keypressEventHandler(), false);
|
||||
} else {
|
||||
} else if (_document.attachEvent) {
|
||||
// IE8 Compatibility
|
||||
_document.attachEvent('onclick', self._breadcrumbEventHandler('click'));
|
||||
_document.attachEvent('onkeypress', self._keypressEventHandler());
|
||||
@ -3750,7 +3780,11 @@ Raven.prototype = {
|
||||
},
|
||||
|
||||
_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
|
||||
Function.prototype.apply.call(
|
||||
this._originalConsoleMethods[level],
|
||||
@ -3823,11 +3857,11 @@ var singleton = Raven$1;
|
||||
* const someAppReporter = new Raven.Client();
|
||||
* const someOtherAppReporter = new Raven.Client();
|
||||
*
|
||||
* someAppReporter('__DSN__', {
|
||||
* someAppReporter.config('__DSN__', {
|
||||
* ...config goes here
|
||||
* });
|
||||
*
|
||||
* someOtherAppReporter('__OTHER_DSN__', {
|
||||
* someOtherAppReporter.config('__OTHER_DSN__', {
|
||||
* ...config goes here
|
||||
* });
|
||||
*
|
||||
|
2
demo/dist/demo.js.map
vendored
2
demo/dist/demo.js.map
vendored
File diff suppressed because one or more lines are too long
2
demo/dist/demo.min.js
vendored
2
demo/dist/demo.min.js
vendored
File diff suppressed because one or more lines are too long
2
demo/dist/demo.min.js.map
vendored
2
demo/dist/demo.min.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.css
vendored
2
dist/plyr.css
vendored
File diff suppressed because one or more lines are too long
153
dist/plyr.js
vendored
153
dist/plyr.js
vendored
@ -77,7 +77,7 @@ var defaults = {
|
||||
// Sprite (for icons)
|
||||
loadSprite: true,
|
||||
iconPrefix: 'plyr',
|
||||
iconUrl: 'https://cdn.plyr.io/3.2.1/plyr.svg',
|
||||
iconUrl: 'https://cdn.plyr.io/3.2.3/plyr.svg',
|
||||
|
||||
// Blank video (used to prevent errors on source change)
|
||||
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
|
||||
toggleClass: function toggleClass(element, className, toggle) {
|
||||
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
|
||||
matches: function matches(element, selector) {
|
||||
var prototype = { Element: Element };
|
||||
@ -1194,8 +1200,8 @@ var utils = {
|
||||
// Display
|
||||
this.elements.display = {
|
||||
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
|
||||
@ -1952,7 +1958,7 @@ var Fullscreen = function () {
|
||||
|
||||
// Get prefix
|
||||
this.prefix = Fullscreen.prefix;
|
||||
this.name = Fullscreen.name;
|
||||
this.property = Fullscreen.property;
|
||||
|
||||
// Scroll position
|
||||
this.scrollPosition = { x: 0, y: 0 };
|
||||
@ -1967,7 +1973,7 @@ var Fullscreen = function () {
|
||||
// Fullscreen toggle on double click
|
||||
utils.on(this.player.elements.container, 'dblclick', function (event) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -2016,7 +2022,7 @@ var Fullscreen = function () {
|
||||
} else if (!this.prefix) {
|
||||
this.target.requestFullscreen();
|
||||
} 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);
|
||||
} else if (!utils.is.empty(this.prefix)) {
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -2121,7 +2127,7 @@ var Fullscreen = function () {
|
||||
return value;
|
||||
}
|
||||
}, {
|
||||
key: 'name',
|
||||
key: 'property',
|
||||
get: function get$$1() {
|
||||
return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';
|
||||
}
|
||||
@ -2480,11 +2486,6 @@ var ui = {
|
||||
this.listeners.controls();
|
||||
}
|
||||
|
||||
// If there's no controls, bail
|
||||
if (!utils.is.element(this.elements.controls)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove native controls
|
||||
ui.toggleNativeControls.call(this);
|
||||
|
||||
@ -2725,10 +2726,10 @@ var ui = {
|
||||
}
|
||||
|
||||
// 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
|
||||
target.textContent = utils.formatTime(time, displayHours, inverted);
|
||||
target.textContent = utils.formatTime(time, forceHours, inverted);
|
||||
},
|
||||
|
||||
|
||||
@ -2935,7 +2936,6 @@ var browser$1 = utils.getBrowser();
|
||||
var controls = {
|
||||
// Webkit polyfill for lower fill range
|
||||
updateRangeFill: function updateRangeFill(target) {
|
||||
|
||||
// Get range from event if event passed
|
||||
var range = utils.is.event(target) ? target.target : target;
|
||||
|
||||
@ -3127,7 +3127,6 @@ var controls = {
|
||||
|
||||
// Add aria attributes
|
||||
attributes['aria-pressed'] = false;
|
||||
attributes['aria-label'] = i18n.get(label, this.config);
|
||||
} else {
|
||||
button.appendChild(controls.createIcon.call(this, icon));
|
||||
button.appendChild(controls.createLabel.call(this, label));
|
||||
@ -3229,16 +3228,14 @@ var controls = {
|
||||
|
||||
// Create time display
|
||||
createTime: function createTime(type) {
|
||||
var container = utils.createElement('div', {
|
||||
class: 'plyr__time'
|
||||
});
|
||||
var attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]);
|
||||
|
||||
container.appendChild(utils.createElement('span', {
|
||||
class: this.config.classNames.hidden
|
||||
}, i18n.get(type, this.config)));
|
||||
|
||||
container.appendChild(utils.createElement('span', utils.getAttributesFromSelector(this.config.selectors.display[type]), '00:00'));
|
||||
var container = utils.createElement('div', utils.extend(attributes, {
|
||||
class: 'plyr__time ' + attributes.class,
|
||||
'aria-label': i18n.get(type, this.config)
|
||||
}), '0:00');
|
||||
|
||||
// Reference for updates
|
||||
this.elements.display[type] = container;
|
||||
|
||||
return container;
|
||||
@ -3264,7 +3261,7 @@ var controls = {
|
||||
class: 'plyr__sr-only'
|
||||
}));
|
||||
|
||||
var faux = utils.createElement('span', { 'aria-hidden': true });
|
||||
var faux = utils.createElement('span', { hidden: '' });
|
||||
|
||||
label.appendChild(radio);
|
||||
label.appendChild(faux);
|
||||
@ -3335,11 +3332,7 @@ var controls = {
|
||||
|
||||
// Hide/show a tab
|
||||
toggleTab: function toggleTab(setting, toggle) {
|
||||
var tab = this.elements.settings.tabs[setting];
|
||||
var pane = this.elements.settings.panes[setting];
|
||||
|
||||
utils.toggleHidden(tab, !toggle);
|
||||
utils.toggleHidden(pane, !toggle);
|
||||
utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);
|
||||
},
|
||||
|
||||
|
||||
@ -3551,7 +3544,6 @@ var controls = {
|
||||
// Get current selected caption language
|
||||
// TODO: rework this to user the getter in the API?
|
||||
|
||||
|
||||
// Set a list of available captions languages
|
||||
setCaptionsMenu: function setCaptionsMenu() {
|
||||
var _this3 = this;
|
||||
@ -3646,10 +3638,6 @@ var controls = {
|
||||
// Get the list to populate
|
||||
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
|
||||
utils.emptyElement(list);
|
||||
|
||||
@ -3686,7 +3674,7 @@ var controls = {
|
||||
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)) {
|
||||
var isMenuItem = utils.is.element(form) && form.contains(event.target);
|
||||
@ -3711,7 +3699,7 @@ var controls = {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (show) {
|
||||
@ -3728,7 +3716,7 @@ var controls = {
|
||||
var clone = tab.cloneNode(true);
|
||||
clone.style.position = 'absolute';
|
||||
clone.style.opacity = 0;
|
||||
clone.setAttribute('aria-hidden', false);
|
||||
clone.removeAttribute('hidden');
|
||||
|
||||
// Prevent input's being unchecked due to the name being identical
|
||||
Array.from(clone.querySelectorAll('input[name]')).forEach(function (input) {
|
||||
@ -3774,7 +3762,7 @@ var controls = {
|
||||
|
||||
// Hide all 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;
|
||||
|
||||
// Set other toggles to be expanded false
|
||||
@ -3815,11 +3803,11 @@ var controls = {
|
||||
}
|
||||
|
||||
// Set attributes on current tab
|
||||
current.setAttribute('aria-hidden', true);
|
||||
utils.toggleHidden(current, true);
|
||||
current.setAttribute('tabindex', -1);
|
||||
|
||||
// Set attributes on target
|
||||
pane.setAttribute('aria-hidden', !show);
|
||||
utils.toggleHidden(pane, !show);
|
||||
tab.setAttribute('aria-expanded', show);
|
||||
pane.removeAttribute('tabindex');
|
||||
|
||||
@ -3954,7 +3942,7 @@ var controls = {
|
||||
var form = utils.createElement('form', {
|
||||
class: 'plyr__menu__container',
|
||||
id: 'plyr-settings-' + data.id,
|
||||
'aria-hidden': true,
|
||||
hidden: '',
|
||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
|
||||
role: 'tablist',
|
||||
tabindex: -1
|
||||
@ -3964,7 +3952,6 @@ var controls = {
|
||||
|
||||
var home = utils.createElement('div', {
|
||||
id: 'plyr-settings-' + data.id + '-home',
|
||||
'aria-hidden': false,
|
||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
|
||||
role: 'tabpanel'
|
||||
});
|
||||
@ -4011,11 +3998,10 @@ var controls = {
|
||||
this.config.settings.forEach(function (type) {
|
||||
var pane = utils.createElement('div', {
|
||||
id: 'plyr-settings-' + data.id + '-' + type,
|
||||
'aria-hidden': true,
|
||||
hidden: '',
|
||||
'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab',
|
||||
role: 'tabpanel',
|
||||
tabindex: -1,
|
||||
hidden: ''
|
||||
tabindex: -1
|
||||
});
|
||||
|
||||
var back = utils.createElement('button', {
|
||||
@ -4097,17 +4083,21 @@ var controls = {
|
||||
var container = 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)) {
|
||||
// String or HTMLElement passed as the option
|
||||
container = this.config.controls;
|
||||
} else if (utils.is.function(this.config.controls)) {
|
||||
// A custom function to build controls
|
||||
// The function can return a HTMLElement or String
|
||||
container = this.config.controls({
|
||||
id: this.id,
|
||||
seektime: this.config.seekTime,
|
||||
title: this.config.title
|
||||
});
|
||||
container = this.config.controls.call(this, props);
|
||||
} else {
|
||||
// Create controls
|
||||
container = controls.create.call(this, {
|
||||
@ -4119,6 +4109,31 @@ var controls = {
|
||||
// TODO: Looping
|
||||
// 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
|
||||
@ -4420,7 +4435,7 @@ var Listeners = function () {
|
||||
});
|
||||
|
||||
// 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);
|
||||
});
|
||||
|
||||
|
2
dist/plyr.js.map
vendored
2
dist/plyr.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.min.js
vendored
2
dist/plyr.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.min.js.map
vendored
2
dist/plyr.min.js.map
vendored
File diff suppressed because one or more lines are too long
153
dist/plyr.polyfilled.js
vendored
153
dist/plyr.polyfilled.js
vendored
@ -5117,7 +5117,7 @@ var defaults = {
|
||||
// Sprite (for icons)
|
||||
loadSprite: true,
|
||||
iconPrefix: 'plyr',
|
||||
iconUrl: 'https://cdn.plyr.io/3.2.1/plyr.svg',
|
||||
iconUrl: 'https://cdn.plyr.io/3.2.4/plyr.svg',
|
||||
|
||||
// Blank video (used to prevent errors on source change)
|
||||
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
|
||||
toggleClass: function toggleClass(element, className, toggle) {
|
||||
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
|
||||
matches: function matches(element, selector) {
|
||||
var prototype = { Element: Element };
|
||||
@ -6228,8 +6234,8 @@ var utils = {
|
||||
// Display
|
||||
this.elements.display = {
|
||||
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
|
||||
@ -6986,7 +6992,7 @@ var Fullscreen = function () {
|
||||
|
||||
// Get prefix
|
||||
this.prefix = Fullscreen.prefix;
|
||||
this.name = Fullscreen.name;
|
||||
this.property = Fullscreen.property;
|
||||
|
||||
// Scroll position
|
||||
this.scrollPosition = { x: 0, y: 0 };
|
||||
@ -7001,7 +7007,7 @@ var Fullscreen = function () {
|
||||
// Fullscreen toggle on double click
|
||||
utils.on(this.player.elements.container, 'dblclick', function (event) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -7050,7 +7056,7 @@ var Fullscreen = function () {
|
||||
} else if (!this.prefix) {
|
||||
this.target.requestFullscreen();
|
||||
} 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);
|
||||
} else if (!utils.is.empty(this.prefix)) {
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -7155,7 +7161,7 @@ var Fullscreen = function () {
|
||||
return value;
|
||||
}
|
||||
}, {
|
||||
key: 'name',
|
||||
key: 'property',
|
||||
get: function get() {
|
||||
return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';
|
||||
}
|
||||
@ -7514,11 +7520,6 @@ var ui = {
|
||||
this.listeners.controls();
|
||||
}
|
||||
|
||||
// If there's no controls, bail
|
||||
if (!utils.is.element(this.elements.controls)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove native controls
|
||||
ui.toggleNativeControls.call(this);
|
||||
|
||||
@ -7759,10 +7760,10 @@ var ui = {
|
||||
}
|
||||
|
||||
// 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
|
||||
target.textContent = utils.formatTime(time, displayHours, inverted);
|
||||
target.textContent = utils.formatTime(time, forceHours, inverted);
|
||||
},
|
||||
|
||||
|
||||
@ -7969,7 +7970,6 @@ var browser$1 = utils.getBrowser();
|
||||
var controls = {
|
||||
// Webkit polyfill for lower fill range
|
||||
updateRangeFill: function updateRangeFill(target) {
|
||||
|
||||
// Get range from event if event passed
|
||||
var range = utils.is.event(target) ? target.target : target;
|
||||
|
||||
@ -8161,7 +8161,6 @@ var controls = {
|
||||
|
||||
// Add aria attributes
|
||||
attributes['aria-pressed'] = false;
|
||||
attributes['aria-label'] = i18n.get(label, this.config);
|
||||
} else {
|
||||
button.appendChild(controls.createIcon.call(this, icon));
|
||||
button.appendChild(controls.createLabel.call(this, label));
|
||||
@ -8263,16 +8262,14 @@ var controls = {
|
||||
|
||||
// Create time display
|
||||
createTime: function createTime(type) {
|
||||
var container = utils.createElement('div', {
|
||||
class: 'plyr__time'
|
||||
});
|
||||
var attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]);
|
||||
|
||||
container.appendChild(utils.createElement('span', {
|
||||
class: this.config.classNames.hidden
|
||||
}, i18n.get(type, this.config)));
|
||||
|
||||
container.appendChild(utils.createElement('span', utils.getAttributesFromSelector(this.config.selectors.display[type]), '00:00'));
|
||||
var container = utils.createElement('div', utils.extend(attributes, {
|
||||
class: 'plyr__time ' + attributes.class,
|
||||
'aria-label': i18n.get(type, this.config)
|
||||
}), '0:00');
|
||||
|
||||
// Reference for updates
|
||||
this.elements.display[type] = container;
|
||||
|
||||
return container;
|
||||
@ -8298,7 +8295,7 @@ var controls = {
|
||||
class: 'plyr__sr-only'
|
||||
}));
|
||||
|
||||
var faux = utils.createElement('span', { 'aria-hidden': true });
|
||||
var faux = utils.createElement('span', { hidden: '' });
|
||||
|
||||
label.appendChild(radio);
|
||||
label.appendChild(faux);
|
||||
@ -8369,11 +8366,7 @@ var controls = {
|
||||
|
||||
// Hide/show a tab
|
||||
toggleTab: function toggleTab(setting, toggle) {
|
||||
var tab = this.elements.settings.tabs[setting];
|
||||
var pane = this.elements.settings.panes[setting];
|
||||
|
||||
utils.toggleHidden(tab, !toggle);
|
||||
utils.toggleHidden(pane, !toggle);
|
||||
utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);
|
||||
},
|
||||
|
||||
|
||||
@ -8585,7 +8578,6 @@ var controls = {
|
||||
// Get current selected caption language
|
||||
// TODO: rework this to user the getter in the API?
|
||||
|
||||
|
||||
// Set a list of available captions languages
|
||||
setCaptionsMenu: function setCaptionsMenu() {
|
||||
var _this3 = this;
|
||||
@ -8680,10 +8672,6 @@ var controls = {
|
||||
// Get the list to populate
|
||||
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
|
||||
utils.emptyElement(list);
|
||||
|
||||
@ -8720,7 +8708,7 @@ var controls = {
|
||||
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)) {
|
||||
var isMenuItem = utils.is.element(form) && form.contains(event.target);
|
||||
@ -8745,7 +8733,7 @@ var controls = {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (show) {
|
||||
@ -8762,7 +8750,7 @@ var controls = {
|
||||
var clone = tab.cloneNode(true);
|
||||
clone.style.position = 'absolute';
|
||||
clone.style.opacity = 0;
|
||||
clone.setAttribute('aria-hidden', false);
|
||||
clone.removeAttribute('hidden');
|
||||
|
||||
// Prevent input's being unchecked due to the name being identical
|
||||
Array.from(clone.querySelectorAll('input[name]')).forEach(function (input) {
|
||||
@ -8808,7 +8796,7 @@ var controls = {
|
||||
|
||||
// Hide all 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;
|
||||
|
||||
// Set other toggles to be expanded false
|
||||
@ -8849,11 +8837,11 @@ var controls = {
|
||||
}
|
||||
|
||||
// Set attributes on current tab
|
||||
current.setAttribute('aria-hidden', true);
|
||||
utils.toggleHidden(current, true);
|
||||
current.setAttribute('tabindex', -1);
|
||||
|
||||
// Set attributes on target
|
||||
pane.setAttribute('aria-hidden', !show);
|
||||
utils.toggleHidden(pane, !show);
|
||||
tab.setAttribute('aria-expanded', show);
|
||||
pane.removeAttribute('tabindex');
|
||||
|
||||
@ -8988,7 +8976,7 @@ var controls = {
|
||||
var form = utils.createElement('form', {
|
||||
class: 'plyr__menu__container',
|
||||
id: 'plyr-settings-' + data.id,
|
||||
'aria-hidden': true,
|
||||
hidden: '',
|
||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
|
||||
role: 'tablist',
|
||||
tabindex: -1
|
||||
@ -8998,7 +8986,6 @@ var controls = {
|
||||
|
||||
var home = utils.createElement('div', {
|
||||
id: 'plyr-settings-' + data.id + '-home',
|
||||
'aria-hidden': false,
|
||||
'aria-labelled-by': 'plyr-settings-toggle-' + data.id,
|
||||
role: 'tabpanel'
|
||||
});
|
||||
@ -9045,11 +9032,10 @@ var controls = {
|
||||
this.config.settings.forEach(function (type) {
|
||||
var pane = utils.createElement('div', {
|
||||
id: 'plyr-settings-' + data.id + '-' + type,
|
||||
'aria-hidden': true,
|
||||
hidden: '',
|
||||
'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab',
|
||||
role: 'tabpanel',
|
||||
tabindex: -1,
|
||||
hidden: ''
|
||||
tabindex: -1
|
||||
});
|
||||
|
||||
var back = utils.createElement('button', {
|
||||
@ -9131,17 +9117,21 @@ var controls = {
|
||||
var container = 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)) {
|
||||
// String or HTMLElement passed as the option
|
||||
container = this.config.controls;
|
||||
} else if (utils.is.function(this.config.controls)) {
|
||||
// A custom function to build controls
|
||||
// The function can return a HTMLElement or String
|
||||
container = this.config.controls({
|
||||
id: this.id,
|
||||
seektime: this.config.seekTime,
|
||||
title: this.config.title
|
||||
});
|
||||
container = this.config.controls.call(this, props);
|
||||
} else {
|
||||
// Create controls
|
||||
container = controls.create.call(this, {
|
||||
@ -9153,6 +9143,31 @@ var controls = {
|
||||
// TODO: Looping
|
||||
// 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
|
||||
@ -9454,7 +9469,7 @@ var Listeners = function () {
|
||||
});
|
||||
|
||||
// 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);
|
||||
});
|
||||
|
||||
|
2
dist/plyr.polyfilled.js.map
vendored
2
dist/plyr.polyfilled.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.polyfilled.min.js
vendored
2
dist/plyr.polyfilled.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/plyr.polyfilled.min.js.map
vendored
2
dist/plyr.polyfilled.min.js.map
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "plyr",
|
||||
"version": "3.2.1",
|
||||
"version": "3.2.4",
|
||||
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
|
||||
"homepage": "https://plyr.io",
|
||||
"main": "./dist/plyr.js",
|
||||
@ -37,7 +37,7 @@
|
||||
"gulp-util": "^3.0.8",
|
||||
"prettier-eslint": "^8.8.1",
|
||||
"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-node-resolve": "^3.3.0",
|
||||
"run-sequence": "^2.2.1",
|
||||
@ -46,7 +46,7 @@
|
||||
"stylelint-config-recommended": "^2.1.0",
|
||||
"stylelint-config-sass-guidelines": "^5.0.0",
|
||||
"stylelint-order": "^0.8.1",
|
||||
"stylelint-scss": "^3.0.0",
|
||||
"stylelint-scss": "^3.0.1",
|
||||
"stylelint-selector-bem-pattern": "^2.0.0"
|
||||
},
|
||||
"keywords": ["HTML5 Video", "HTML5 Audio", "Media Player", "DASH", "Shaka", "WordPress", "HLS"],
|
||||
@ -69,6 +69,7 @@
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"custom-event-polyfill": "^0.3.0",
|
||||
"loadjs": "^3.5.4",
|
||||
"raven-js": "^3.24.0"
|
||||
"npm": "^6.0.0",
|
||||
"raven-js": "^3.24.2"
|
||||
}
|
||||
}
|
||||
|
32
readme.md
32
readme.md
@ -39,13 +39,13 @@ Check out the [changelog](changelog.md) to see what's new with Plyr.
|
||||
|
||||
Some awesome folks have made plugins for CMSs and Components for JavaScript frameworks:
|
||||
|
||||
| Type | Maintainer | Link |
|
||||
| --------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
||||
| WordPress | Ryan Anthony Drake ([@iamryandrake](https://github.com/iamryandrake)) | [https://wordpress.org/plugins/plyr/](https://wordpress.org/plugins/plyr/) |
|
||||
| React | Jose Miguel Bejarano ([@xDae](https://github.com/xDae)) | [https://github.com/xDae/react-plyr](https://github.com/xDae/react-plyr) |
|
||||
| Vue | Gabe Dunn ([@redxtech](https://github.com/redxtech)) | [https://github.com/redxtech/vue-plyr](https://github.com/redxtech/vue-plyr) |
|
||||
| Neos | Jon Uhlmann ([@jonnitto](https://github.com/jonnitto)) | [https://packagist.org/packages/jonnitto/plyr](https://packagist.org/packages/jonnitto/plyr) |
|
||||
| Kirby | Dominik Pschenitschni ([@dpschen](https://github.com/dpschen)) | [https://github.com/dpschen/kirby-plyrtag](https://github.com/dpschen/kirby-plyrtag) |
|
||||
| Type | Maintainer | Link |
|
||||
| --------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
||||
| WordPress | Brandon Lavigne ([@drrobotnik](https://github.com/drrobotnik)) | [https://wordpress.org/plugins/plyr/](https://wordpress.org/plugins/plyr/) |
|
||||
| React | Jose Miguel Bejarano ([@xDae](https://github.com/xDae)) | [https://github.com/xDae/react-plyr](https://github.com/xDae/react-plyr) |
|
||||
| Vue | Gabe Dunn ([@redxtech](https://github.com/redxtech)) | [https://github.com/redxtech/vue-plyr](https://github.com/redxtech/vue-plyr) |
|
||||
| Neos | Jon Uhlmann ([@jonnitto](https://github.com/jonnitto)) | [https://packagist.org/packages/jonnitto/plyr](https://packagist.org/packages/jonnitto/plyr) |
|
||||
| Kirby | Dominik Pschenitschni ([@dpschen](https://github.com/dpschen)) | [https://github.com/dpschen/kirby-plyrtag](https://github.com/dpschen/kirby-plyrtag) |
|
||||
|
||||
## Quick setup
|
||||
|
||||
@ -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:
|
||||
|
||||
```html
|
||||
<script src="https://cdn.plyr.io/3.2.1/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
|
||||
@ -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:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="https://cdn.plyr.io/3.2.1/plyr.css">
|
||||
<link rel="stylesheet" href="https://cdn.plyr.io/3.2.4/plyr.css">
|
||||
```
|
||||
|
||||
### 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
|
||||
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.2.1/plyr.svg`.
|
||||
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.2.4/plyr.svg`.
|
||||
|
||||
## Ads
|
||||
|
||||
@ -668,8 +668,10 @@ Plyr is developed by [@sam_potts](https://twitter.com/sam_potts) / [sampotts.me]
|
||||
|
||||
## Donate
|
||||
|
||||
Plyr costs money to run, not only my time - I donate that for free but domains, hosting and more. Any help is appreciated...
|
||||
[Donate to support Plyr](https://www.paypal.me/pottsy/20usd)
|
||||
Plyr costs money to run, not only my time. I donate my time for free as I enjoy building Plyr but unfortunately have to pay for domains, hosting, and more. Any help with costs is appreciated...
|
||||
|
||||
* [Donate via Patron](https://www.patreon.com/plyr)
|
||||
* [Donate via PayPal](https://www.paypal.me/pottsy/20usd)
|
||||
|
||||
## Mentions
|
||||
|
||||
@ -707,10 +709,14 @@ Credit to the PayPal HTML5 Video player from which Plyr's caption functionality
|
||||
|
||||
## Thanks
|
||||
|
||||
[](https://www.fastly.com/)
|
||||
[](https://www.fastly.com/)
|
||||
|
||||
Massive thanks to [Fastly](https://www.fastly.com/) for providing the CDN services.
|
||||
|
||||
[](https://sentry.io/)
|
||||
|
||||
Massive thanks to [Sentry](https://sentry.io/) for providing the logging services for the demo site.
|
||||
|
||||
## Copyright and License
|
||||
|
||||
[The MIT license](license.md)
|
||||
|
94
src/js/controls.js
vendored
94
src/js/controls.js
vendored
@ -15,8 +15,6 @@ const browser = utils.getBrowser();
|
||||
const controls = {
|
||||
// Webkit polyfill for lower fill range
|
||||
updateRangeFill(target) {
|
||||
|
||||
|
||||
// Get range from event if event passed
|
||||
const range = utils.is.event(target) ? target.target : target;
|
||||
|
||||
@ -212,7 +210,6 @@ const controls = {
|
||||
|
||||
// Add aria attributes
|
||||
attributes['aria-pressed'] = false;
|
||||
attributes['aria-label'] = i18n.get(label, this.config);
|
||||
} else {
|
||||
button.appendChild(controls.createIcon.call(this, icon));
|
||||
button.appendChild(controls.createLabel.call(this, label));
|
||||
@ -329,22 +326,14 @@ const controls = {
|
||||
|
||||
// Create time display
|
||||
createTime(type) {
|
||||
const container = utils.createElement('div', {
|
||||
class: 'plyr__time',
|
||||
});
|
||||
const attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]);
|
||||
|
||||
container.appendChild(
|
||||
utils.createElement(
|
||||
'span',
|
||||
{
|
||||
class: this.config.classNames.hidden,
|
||||
},
|
||||
i18n.get(type, this.config),
|
||||
),
|
||||
);
|
||||
|
||||
container.appendChild(utils.createElement('span', utils.getAttributesFromSelector(this.config.selectors.display[type]), '00:00'));
|
||||
const container = utils.createElement('div', utils.extend(attributes, {
|
||||
class: `plyr__time ${attributes.class}`,
|
||||
'aria-label': i18n.get(type, this.config),
|
||||
}), '0:00');
|
||||
|
||||
// Reference for updates
|
||||
this.elements.display[type] = container;
|
||||
|
||||
return container;
|
||||
@ -369,7 +358,7 @@ const controls = {
|
||||
}),
|
||||
);
|
||||
|
||||
const faux = utils.createElement('span', { 'aria-hidden': true });
|
||||
const faux = utils.createElement('span', { hidden: '' });
|
||||
|
||||
label.appendChild(radio);
|
||||
label.appendChild(faux);
|
||||
@ -444,11 +433,7 @@ const controls = {
|
||||
|
||||
// Hide/show a tab
|
||||
toggleTab(setting, toggle) {
|
||||
const tab = this.elements.settings.tabs[setting];
|
||||
const pane = this.elements.settings.panes[setting];
|
||||
|
||||
utils.toggleHidden(tab, !toggle);
|
||||
utils.toggleHidden(pane, !toggle);
|
||||
utils.toggleHidden(this.elements.settings.tabs[setting], !toggle);
|
||||
},
|
||||
|
||||
// Set the quality menu
|
||||
@ -660,7 +645,6 @@ const controls = {
|
||||
// Get current selected caption language
|
||||
// TODO: rework this to user the getter in the API?
|
||||
|
||||
|
||||
// Set a list of available captions languages
|
||||
setCaptionsMenu() {
|
||||
// TODO: Captions or language? Currently it's mixed
|
||||
@ -760,10 +744,6 @@ const controls = {
|
||||
// Get the list to populate
|
||||
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
|
||||
utils.emptyElement(list);
|
||||
|
||||
@ -794,7 +774,7 @@ const controls = {
|
||||
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)) {
|
||||
const isMenuItem = utils.is.element(form) && form.contains(event.target);
|
||||
@ -819,7 +799,7 @@ const controls = {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (show) {
|
||||
@ -835,7 +815,7 @@ const controls = {
|
||||
const clone = tab.cloneNode(true);
|
||||
clone.style.position = 'absolute';
|
||||
clone.style.opacity = 0;
|
||||
clone.setAttribute('aria-hidden', false);
|
||||
clone.removeAttribute('hidden');
|
||||
|
||||
// Prevent input's being unchecked due to the name being identical
|
||||
Array.from(clone.querySelectorAll('input[name]')).forEach(input => {
|
||||
@ -879,7 +859,7 @@ const controls = {
|
||||
|
||||
// Hide all 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;
|
||||
|
||||
// Set other toggles to be expanded false
|
||||
@ -923,11 +903,11 @@ const controls = {
|
||||
}
|
||||
|
||||
// Set attributes on current tab
|
||||
current.setAttribute('aria-hidden', true);
|
||||
utils.toggleHidden(current, true);
|
||||
current.setAttribute('tabindex', -1);
|
||||
|
||||
// Set attributes on target
|
||||
pane.setAttribute('aria-hidden', !show);
|
||||
utils.toggleHidden(pane, !show);
|
||||
tab.setAttribute('aria-expanded', show);
|
||||
pane.removeAttribute('tabindex');
|
||||
|
||||
@ -1069,7 +1049,7 @@ const controls = {
|
||||
const form = utils.createElement('form', {
|
||||
class: 'plyr__menu__container',
|
||||
id: `plyr-settings-${data.id}`,
|
||||
'aria-hidden': true,
|
||||
hidden: '',
|
||||
'aria-labelled-by': `plyr-settings-toggle-${data.id}`,
|
||||
role: 'tablist',
|
||||
tabindex: -1,
|
||||
@ -1079,7 +1059,6 @@ const controls = {
|
||||
|
||||
const home = utils.createElement('div', {
|
||||
id: `plyr-settings-${data.id}-home`,
|
||||
'aria-hidden': false,
|
||||
'aria-labelled-by': `plyr-settings-toggle-${data.id}`,
|
||||
role: 'tabpanel',
|
||||
});
|
||||
@ -1130,11 +1109,10 @@ const controls = {
|
||||
this.config.settings.forEach(type => {
|
||||
const pane = utils.createElement('div', {
|
||||
id: `plyr-settings-${data.id}-${type}`,
|
||||
'aria-hidden': true,
|
||||
hidden: '',
|
||||
'aria-labelled-by': `plyr-settings-${data.id}-${type}-tab`,
|
||||
role: 'tabpanel',
|
||||
tabindex: -1,
|
||||
hidden: '',
|
||||
});
|
||||
|
||||
const back = utils.createElement(
|
||||
@ -1217,17 +1195,21 @@ const controls = {
|
||||
let container = 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)) {
|
||||
// String or HTMLElement passed as the option
|
||||
container = this.config.controls;
|
||||
} else if (utils.is.function(this.config.controls)) {
|
||||
// A custom function to build controls
|
||||
// The function can return a HTMLElement or String
|
||||
container = this.config.controls({
|
||||
id: this.id,
|
||||
seektime: this.config.seekTime,
|
||||
title: this.config.title,
|
||||
});
|
||||
container = this.config.controls.call(this, props);
|
||||
} else {
|
||||
// Create controls
|
||||
container = controls.create.call(this, {
|
||||
@ -1239,6 +1221,30 @@ const controls = {
|
||||
// TODO: Looping
|
||||
// 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
|
||||
|
@ -56,7 +56,7 @@ const defaults = {
|
||||
// Sprite (for icons)
|
||||
loadSprite: true,
|
||||
iconPrefix: 'plyr',
|
||||
iconUrl: 'https://cdn.plyr.io/3.2.1/plyr.svg',
|
||||
iconUrl: 'https://cdn.plyr.io/3.2.4/plyr.svg',
|
||||
|
||||
// Blank video (used to prevent errors on source change)
|
||||
blankVideo: 'https://cdn.plyr.io/static/blank.mp4',
|
||||
|
@ -55,7 +55,7 @@ class Fullscreen {
|
||||
|
||||
// Get prefix
|
||||
this.prefix = Fullscreen.prefix;
|
||||
this.name = Fullscreen.name;
|
||||
this.property = Fullscreen.property;
|
||||
|
||||
// Scroll position
|
||||
this.scrollPosition = { x: 0, y: 0 };
|
||||
@ -70,7 +70,7 @@ class Fullscreen {
|
||||
// Fullscreen toggle on double click
|
||||
utils.on(this.player.elements.container, 'dblclick', event => {
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ class Fullscreen {
|
||||
return value;
|
||||
}
|
||||
|
||||
static get name() {
|
||||
static get property() {
|
||||
return this.prefix === 'moz' ? 'FullScreen' : 'Fullscreen';
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ class Fullscreen {
|
||||
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;
|
||||
}
|
||||
@ -176,7 +176,7 @@ class Fullscreen {
|
||||
} else if (!this.prefix) {
|
||||
this.target.requestFullscreen();
|
||||
} 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);
|
||||
} else if (!utils.is.empty(this.prefix)) {
|
||||
const action = this.prefix === 'moz' ? 'Cancel' : 'Exit';
|
||||
document[`${this.prefix}${action}${this.name}`]();
|
||||
document[`${this.prefix}${action}${this.property}`]();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,7 +253,7 @@ class Listeners {
|
||||
utils.on(this.player.media, 'timeupdate seeking', event => ui.timeUpdate.call(this.player, event));
|
||||
|
||||
// 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
|
||||
// We can't use `loadedmetadata` as it doesn't seem to have audio tracks at that point
|
||||
|
@ -1,6 +1,6 @@
|
||||
// ==========================================================================
|
||||
// Plyr
|
||||
// plyr.js v3.2.1
|
||||
// plyr.js v3.2.4
|
||||
// https://github.com/sampotts/plyr
|
||||
// License: The MIT License (MIT)
|
||||
// ==========================================================================
|
||||
|
@ -1,6 +1,6 @@
|
||||
// ==========================================================================
|
||||
// Plyr Polyfilled Build
|
||||
// plyr.js v3.2.1
|
||||
// plyr.js v3.2.4
|
||||
// https://github.com/sampotts/plyr
|
||||
// License: The MIT License (MIT)
|
||||
// ==========================================================================
|
||||
|
@ -48,11 +48,6 @@ const ui = {
|
||||
this.listeners.controls();
|
||||
}
|
||||
|
||||
// If there's no controls, bail
|
||||
if (!utils.is.element(this.elements.controls)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove native controls
|
||||
ui.toggleNativeControls.call(this);
|
||||
|
||||
@ -277,10 +272,10 @@ const ui = {
|
||||
}
|
||||
|
||||
// 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
|
||||
target.textContent = utils.formatTime(time, displayHours, inverted);
|
||||
target.textContent = utils.formatTime(time, forceHours, inverted);
|
||||
},
|
||||
|
||||
// Handle time change event
|
||||
|
@ -375,6 +375,25 @@ const utils = {
|
||||
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
|
||||
toggleClass(element, className, toggle) {
|
||||
if (utils.is.element(element)) {
|
||||
@ -393,19 +412,6 @@ const utils = {
|
||||
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
|
||||
matches(element, selector) {
|
||||
const prototype = { Element };
|
||||
@ -462,8 +468,8 @@ const utils = {
|
||||
// Display
|
||||
this.elements.display = {
|
||||
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),
|
||||
duration: utils.getElement.call(this, this.config.selectors.display.duration),
|
||||
};
|
||||
|
||||
// Seek tooltip
|
||||
@ -752,7 +758,7 @@ const utils = {
|
||||
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
|
||||
|
@ -23,7 +23,12 @@
|
||||
// Hide sound controls on iOS
|
||||
// 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
|
||||
.plyr--is-ios .plyr__volume,
|
||||
.plyr--is-ios [data-plyr='mute'] {
|
||||
.plyr--is-ios .plyr__volume {
|
||||
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;
|
||||
}
|
||||
|
@ -2,15 +2,6 @@
|
||||
// Hiding content nicely
|
||||
// --------------------------------------------------------------
|
||||
|
||||
// Attributes
|
||||
.plyr--full-ui [hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.plyr--full-ui [aria-hidden='true'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Screen reader only elements
|
||||
.plyr__sr-only {
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
|
Loading…
x
Reference in New Issue
Block a user