This commit is contained in:
Sam Potts 2018-06-11 16:19:11 +10:00
parent 7c6d4666e9
commit 38f10d4cc6
9 changed files with 112 additions and 59 deletions

View File

@ -2,9 +2,9 @@
This is the markup that is rendered for the Plyr controls. You can use the default controls or provide a customized version of markup based on your needs. You can pass the following to the `controls` option:
* `Array` of options (this builds the default controls based on your choices)
* `String` containing the desired HTML
* `Function` that will be executed and should return one of the above
- `Array` of options (this builds the default controls based on your choices)
- `String` containing the desired HTML
- `Function` that will be executed and should return one of the above
## Using default controls
@ -81,14 +81,14 @@ The classes and data attributes used in your template should match the `selector
You need to add several placeholders to your HTML template that are replaced when rendering:
* `{id}` - the dynamically generated ID for the player (for form controls)
* `{seektime}` - the seek time specified in options for fast forward and rewind
* `{title}` - the title of your media, if specified
- `{id}` - the dynamically generated ID for the player (for form controls)
- `{seektime}` - the seek time specified in options for fast forward and rewind
- `{title}` - the title of your media, if specified
### Limitations
* Currently the settings menus are not supported with custom controls HTML
* AirPlay and PiP buttons can be added but you will have to manage feature detection
- Currently the settings menus are not supported with custom controls HTML
- AirPlay and PiP buttons can be added but you will have to manage feature detection
### Example
@ -131,13 +131,13 @@ const controls = `
<div class="plyr__volume">
<input data-plyr="volume" type="range" min="0" max="1" step="0.05" value="1" autocomplete="off" aria-label="Volume">
</div>
<button type="button" class="plyr__control" aria-label="Enable captions" data-plyr="captions">
<button type="button" class="plyr__control" data-plyr="captions">
<svg class="icon--pressed" role="presentation"><use xlink:href="#plyr-captions-on"></use></svg>
<svg class="icon--not-pressed" role="presentation"><use xlink:href="#plyr-captions-off"></use></svg>
<span class="label--pressed plyr__tooltip" role="tooltip">Disable captions</span>
<span class="label--not-pressed plyr__tooltip" role="tooltip">Enable captions</span>
</button>
<button type="button" class="plyr__control" aria-label="Enter fullscreen" data-plyr="fullscreen">
<button type="button" class="plyr__control" data-plyr="fullscreen">
<svg class="icon--pressed" role="presentation"><use xlink:href="#plyr-exit-fullscreen"></use></svg>
<svg class="icon--not-pressed" role="presentation"><use xlink:href="#plyr-enter-fullscreen"></use></svg>
<span class="label--pressed plyr__tooltip" role="tooltip">Exit fullscreen</span>

53
dist/plyr.js vendored
View File

@ -1789,7 +1789,6 @@ var i18n = {
var browser = utils.getBrowser();
var controls = {
// Get icon URL
getIconUrl: function getIconUrl() {
var url = new URL(this.config.iconUrl, window.location);
@ -2168,6 +2167,23 @@ var controls = {
},
// Format a time for display
formatTime: function formatTime() {
var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var inverted = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
// Bail if the value isn't a number
if (!utils.is.number(time)) {
return time;
}
// Always display hours if duration is over an hour
var forceHours = utils.getHours(this.duration) > 0;
return utils.formatTime(time, forceHours, inverted);
},
// Update the displayed time
updateTimeDisplay: function updateTimeDisplay() {
var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
@ -2179,11 +2195,8 @@ var controls = {
return;
}
// Always display hours if duration is over an hour
var forceHours = utils.getHours(this.duration) > 0;
// eslint-disable-next-line no-param-reassign
target.innerText = utils.formatTime(time, forceHours, inverted);
target.innerText = controls.formatTime(time, inverted);
},
@ -2286,8 +2299,20 @@ var controls = {
return;
}
// Set aria value for https://github.com/sampotts/plyr/issues/905
// Set aria values for https://github.com/sampotts/plyr/issues/905
if (utils.matches(range, this.config.selectors.inputs.seek)) {
range.setAttribute('aria-valuenow', this.currentTime);
var currentTime = controls.formatTime(this.currentTime);
var duration = controls.formatTime(this.duration);
var format = i18n.get('seekLabel', this.config);
range.setAttribute('aria-valuetext', format.replace('{currentTime}', currentTime).replace('{duration}', duration));
} else if (utils.matches(range, this.config.selectors.inputs.volume)) {
var percent = range.value * 100;
range.setAttribute('aria-valuenow', percent);
range.setAttribute('aria-valuetext', percent + '%');
} else {
range.setAttribute('aria-valuenow', range.value);
}
// WebKit only
if (!browser.isWebkit) {
@ -2373,11 +2398,16 @@ var controls = {
// Show the duration on metadataloaded or durationchange events
durationUpdate: function durationUpdate() {
// Bail if no ui or durationchange event triggered after playing/seek when invertTime is false
// Bail if no UI or durationchange event triggered after playing/seek when invertTime is false
if (!this.supported.ui || !this.config.invertTime && this.currentTime) {
return;
}
// Update ARIA values
if (utils.is.element(this.elements.inputs.seek)) {
this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);
}
// If there's a spot to display duration
var hasDuration = utils.is.element(this.elements.display.duration);
@ -3218,7 +3248,6 @@ var controls = {
Array.from(labels).forEach(function (label) {
utils.toggleClass(label, _this7.config.classNames.hidden, false);
utils.toggleClass(label, _this7.config.classNames.tooltip, true);
label.setAttribute('role', 'tooltip');
});
}
}
@ -3659,6 +3688,7 @@ var defaults$1 = {
pause: 'Pause',
fastForward: 'Forward {seektime}s',
seek: 'Seek',
seekLabel: '{currentTime} of {duration}',
played: 'Played',
buffered: 'Buffered',
currentTime: 'Current time',
@ -3673,6 +3703,7 @@ var defaults$1 = {
frameTitle: 'Player for {title}',
captions: 'Captions',
settings: 'Settings',
menuBack: 'Go back to previous menu',
speed: 'Speed',
normal: 'Normal',
quality: 'Quality',
@ -4223,9 +4254,6 @@ var ui = {
// If there's a media title set, use that for the label
if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) {
label += ', ' + this.config.title;
// Set container label
this.elements.container.setAttribute('aria-label', this.config.title);
}
// If there's a play button, set label
@ -7080,9 +7108,6 @@ var Plyr = function () {
utils.wrap(this.media, this.elements.container);
}
// Allow focus to be captured
this.elements.container.setAttribute('tabindex', 0);
// Add style hook
ui.addStyleHook.call(this);

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

62
src/js/controls.js vendored
View File

@ -12,8 +12,6 @@ import utils from './utils';
const browser = utils.getBrowser();
const controls = {
// Get icon URL
getIconUrl() {
const url = new URL(this.config.iconUrl, window.location);
@ -359,10 +357,14 @@ const controls = {
createTime(type) {
const attributes = utils.getAttributesFromSelector(this.config.selectors.display[type]);
const container = utils.createElement('div', utils.extend(attributes, {
const container = utils.createElement(
'div',
utils.extend(attributes, {
class: `plyr__time ${attributes.class}`,
'aria-label': i18n.get(type, this.config),
}), '00:00');
}),
'00:00',
);
// Reference for updates
this.elements.display[type] = container;
@ -403,6 +405,19 @@ const controls = {
list.appendChild(item);
},
// Format a time for display
formatTime(time = 0, inverted = false) {
// Bail if the value isn't a number
if (!utils.is.number(time)) {
return time;
}
// Always display hours if duration is over an hour
const forceHours = utils.getHours(this.duration) > 0;
return utils.formatTime(time, forceHours, inverted);
},
// Update the displayed time
updateTimeDisplay(target = null, time = 0, inverted = false) {
// Bail if there's no element to display or the value isn't a number
@ -410,11 +425,8 @@ const controls = {
return;
}
// Always display hours if duration is over an hour
const forceHours = utils.getHours(this.duration) > 0;
// eslint-disable-next-line no-param-reassign
target.innerText = utils.formatTime(time, forceHours, inverted);
target.innerText = controls.formatTime(time, inverted);
},
// Update volume UI and storage
@ -509,8 +521,20 @@ const controls = {
return;
}
// Set aria value for https://github.com/sampotts/plyr/issues/905
// Set aria values for https://github.com/sampotts/plyr/issues/905
if (utils.matches(range, this.config.selectors.inputs.seek)) {
range.setAttribute('aria-valuenow', this.currentTime);
const currentTime = controls.formatTime(this.currentTime);
const duration = controls.formatTime(this.duration);
const format = i18n.get('seekLabel', this.config);
range.setAttribute('aria-valuetext', format.replace('{currentTime}', currentTime).replace('{duration}', duration));
} else if (utils.matches(range, this.config.selectors.inputs.volume)) {
const percent = range.value * 100;
range.setAttribute('aria-valuenow', percent);
range.setAttribute('aria-valuetext', `${percent}%`);
} else {
range.setAttribute('aria-valuenow', range.value);
}
// WebKit only
if (!browser.isWebkit) {
@ -599,11 +623,16 @@ const controls = {
// Show the duration on metadataloaded or durationchange events
durationUpdate() {
// Bail if no ui or durationchange event triggered after playing/seek when invertTime is false
// Bail if no UI or durationchange event triggered after playing/seek when invertTime is false
if (!this.supported.ui || (!this.config.invertTime && this.currentTime)) {
return;
}
// Update ARIA values
if (utils.is.element(this.elements.inputs.seek)) {
this.elements.inputs.seek.setAttribute('aria-valuemax', this.duration);
}
// If there's a spot to display duration
const hasDuration = utils.is.element(this.elements.display.duration);
@ -1126,9 +1155,11 @@ const controls = {
const progress = utils.createElement('div', utils.getAttributesFromSelector(this.config.selectors.progress));
// Seek range slider
progress.appendChild(controls.createRange.call(this, 'seek', {
progress.appendChild(
controls.createRange.call(this, 'seek', {
id: `plyr-seek-${data.id}`,
}));
}),
);
// Buffer progress
progress.appendChild(controls.createProgress.call(this, 'buffer'));
@ -1182,13 +1213,15 @@ const controls = {
};
// Create the volume range slider
volume.appendChild(controls.createRange.call(
volume.appendChild(
controls.createRange.call(
this,
'volume',
utils.extend(attributes, {
id: `plyr-volume-${data.id}`,
}),
));
),
);
this.elements.volume = volume;
@ -1463,7 +1496,6 @@ const controls = {
Array.from(labels).forEach(label => {
utils.toggleClass(label, this.config.classNames.hidden, false);
utils.toggleClass(label, this.config.classNames.tooltip, true);
label.setAttribute('role', 'tooltip');
});
}
},

View File

@ -169,6 +169,7 @@ const defaults = {
pause: 'Pause',
fastForward: 'Forward {seektime}s',
seek: 'Seek',
seekLabel: '{currentTime} of {duration}',
played: 'Played',
buffered: 'Buffered',
currentTime: 'Current time',
@ -183,6 +184,7 @@ const defaults = {
frameTitle: 'Player for {title}',
captions: 'Captions',
settings: 'Settings',
menuBack: 'Go back to previous menu',
speed: 'Speed',
normal: 'Normal',
quality: 'Quality',

View File

@ -260,9 +260,6 @@ class Plyr {
utils.wrap(this.media, this.elements.container);
}
// Allow focus to be captured
this.elements.container.setAttribute('tabindex', 0);
// Add style hook
ui.addStyleHook.call(this);

View File

@ -127,9 +127,6 @@ const ui = {
// If there's a media title set, use that for the label
if (utils.is.string(this.config.title) && !utils.is.empty(this.config.title)) {
label += `, ${this.config.title}`;
// Set container label
this.elements.container.setAttribute('aria-label', this.config.title);
}
// If there's a play button, set label