This commit is contained in:
Sam Potts 2018-04-27 00:47:51 +10:00
parent fec7a77d6f
commit a812650fea
28 changed files with 1586 additions and 164 deletions

View File

@ -1,3 +1,12 @@
## 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)

View File

@ -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

File diff suppressed because one or more lines are too long

72
demo/dist/demo.js vendored
View File

@ -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
* });
*

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/plyr.css vendored

File diff suppressed because one or more lines are too long

75
dist/plyr.js vendored
View File

@ -77,7 +77,7 @@ var defaults = {
// Sprite (for icons)
loadSprite: true,
iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/3.2.2/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',
@ -1200,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
@ -1973,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;
}
@ -2486,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);
@ -2731,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);
},
@ -3132,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));
@ -3234,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;
@ -4091,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, {
@ -4113,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
@ -4414,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

File diff suppressed because one or more lines are too long

2
dist/plyr.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5117,7 +5117,7 @@ var defaults = {
// Sprite (for icons)
loadSprite: true,
iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/3.2.3/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',
@ -6234,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
@ -7007,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;
}
@ -7520,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);
@ -7765,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);
},
@ -8166,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));
@ -8268,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;
@ -9125,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, {
@ -9147,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
@ -9448,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);
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{
"name": "plyr",
"version": "3.2.3",
"version": "3.2.4",
"description": "A simple, accessible and customizable HTML5, YouTube and Vimeo media player",
"homepage": "https://plyr.io",
"main": "./dist/plyr.js",
@ -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"
}
}

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:
```html
<script src="https://cdn.plyr.io/3.2.3/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.3/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.3/plyr.svg`.
reference, the CDN hosted SVG sprite can be found at `https://cdn.plyr.io/3.2.4/plyr.svg`.
## Ads

61
src/js/controls.js vendored
View File

@ -210,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));
@ -327,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;
@ -1204,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, {
@ -1226,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

View File

@ -56,7 +56,7 @@ const defaults = {
// Sprite (for icons)
loadSprite: true,
iconPrefix: 'plyr',
iconUrl: 'https://cdn.plyr.io/3.2.3/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',

View File

@ -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;
}

View File

@ -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

View File

@ -1,6 +1,6 @@
// ==========================================================================
// Plyr
// plyr.js v3.2.3
// plyr.js v3.2.4
// https://github.com/sampotts/plyr
// License: The MIT License (MIT)
// ==========================================================================

View File

@ -1,6 +1,6 @@
// ==========================================================================
// Plyr Polyfilled Build
// plyr.js v3.2.3
// plyr.js v3.2.4
// https://github.com/sampotts/plyr
// License: The MIT License (MIT)
// ==========================================================================

View File

@ -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

View File

@ -468,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

View File

@ -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;
}

1392
yarn.lock

File diff suppressed because it is too large Load Diff