Work on playback rate changes

This commit is contained in:
Sam Potts 2017-07-31 09:58:30 +10:00
parent 7b60e473fa
commit a9957211f4
3 changed files with 120 additions and 148 deletions

4
dist/plyr.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,84 +0,0 @@
### Todo
#### To finish
[x] Get list of subtitles/captions available (HTML5, Vimeo)
[x] Add preferred quality option into config
[ ] Update quality options on YouTube play
[ ] Update speed options on YouTube load
[ ] Handle quality change for YouTube
[ ] Handle speed change for YouTube
[ ] Set quality when loading YouTube vid
[ ] Set default values
[ ] Hide unsupported menu items on source change
[ ] Test PiP (need MacOS Sierra)
[ ] Test AirPlay (need MacOS Sierra)
[ ] Add `controlshidden` and `controlsshown` events
[ ] Test custom controls still works (without settings support for now)
[ ] Tidy up small UI for iOS inline
[ ] Finish new loop setup and display in seek bar
[ ] Update docs for removal of setup
#### Later
[ ] Wistia player
[ ] Inlined sprite option
[ ] Start / end time options for all players?
[ ] Get quality options for HTML5 somehow (multi source?)
[ ] Download button - grab first <source> or src attribute (or maybe use currentSrc?) for HTML5 and links for embedded players
[ ] Scale captions size based on video size (in lieu of element queries)
[ ] Allow passing YouTube/Vimeo iframe to setup
#### Bugs
[ ] Fix audio setup bug when calling `.setup()` again
[ ] Fix events on unsupported devices (iOS, old IE)
[x] Fix YouTube rights blocking (origin perhaps?)
### Release notes
- No quality HTML5 support (yet)
- No Vimeo quality support
- No YouTube caption support
- Added Vimeo captions support
- No PiP or AirPlay for Vimeo/YouTube
- Settings won't be supported for custom controls (coming soon, need to work on templating)
- Added `playsinline` support for iOS 10
- Embed setup now accepts an <iframe> as the target element for true progressive enhancement
## Changes
### Config changes
- videoWrapper -> video
- embedWrapper -> embed
- setup and ready classes removed
### API changes
- Can now chain most functions (need to document which can)
- support -> supports
- isFullscreen -> fullscreen.active
- new 'language'
- getType -> type
- getEmbed -> embed
- getContainer removed
- getMedia -> media
- getCurrentTime -> media.currentTime
- getVolume -> media.volume
- isMuted -> media.muted
- isLoading -> media.loading
- isPaused -> media.paused
- updatePoster -> poster
- setVolume -> volume
- increaseVolume (new)
- decreaseVolume (new)
- togglePictureInPicture (new)
- airPlay (new)
- Added `.off` API method
#### Other breaking changes
- New config options for loop
- Selectors changes (new `input` and `display` object) - DOCUMENT
- Custom HTML option now `controls` which accepts a string (HTML), a function (your own template engine) or array (use built in controls)
- `.setup()` is removed in favour of a constructor
- `.loadSprite` removed
- `.support` removed
#### Added
- Seek i8n label
- Loop related i8n labels

View File

@ -1270,6 +1270,31 @@
}));
}
// Trap focus inside container
function focusTrap() {
var tabbables = getElements('input:not([disabled]), button:not([disabled])');
var first = tabbables[0];
var last = tabbables[tabbables.length - 1];
function checkFocus(event) {
// If it is tab
if (event.which === 9 && player.fullscreen.active) {
if (event.target === last && !event.shiftKey) {
// Move focus to first element that can be tabbed if Shift isn't used
event.preventDefault();
first.focus();
} else if (event.target === first && event.shiftKey) {
// Move focus to last element that can be tabbed if Shift is used
event.preventDefault();
last.focus();
}
}
}
// Bind the handler
utils.on(player.elements.container, 'keydown', checkFocus, false);
}
// Find all elements
function getElements(selector) {
return player.elements.container.querySelectorAll(selector);
@ -1280,6 +1305,7 @@
return getElements(selector)[0];
}
// Remove an element
function removeElement(element) {
// Remove reference from player.elements cache
if (utils.is.string(element)) {
@ -1303,31 +1329,6 @@
}
}
// Trap focus inside container
function focusTrap() {
var tabbables = getElements('input:not([disabled]), button:not([disabled])');
var first = tabbables[0];
var last = tabbables[tabbables.length - 1];
function checkFocus(event) {
// If it is TAB
if (event.which === 9 && player.fullscreen.active) {
if (event.target === last && !event.shiftKey) {
// Move focus to first element that can be tabbed if Shift isn't used
event.preventDefault();
first.focus();
} else if (event.target === first && event.shiftKey) {
// Move focus to last element that can be tabbed if Shift is used
event.preventDefault();
last.focus();
}
}
}
// Bind the handler
utils.on(player.elements.container, 'keydown', checkFocus, false);
}
// Get icon URL
function getIconUrl() {
return {
@ -1972,7 +1973,7 @@
}
// Set a list of available captions languages
function setSpeedMenu(options) {
function setSpeedMenu() {
var list = player.elements.settings.panes.speed.querySelector('ul');
// Show the pane and tab
@ -1982,12 +1983,8 @@
// Empty the menu
utils.emptyElement(list);
// If there's no captions, bail
if (!utils.is.array(options)) {
options = player.config.speed.options;
}
options.forEach(function(speed) {
// Create items
player.config.speed.options.forEach(function(speed) {
var item = utils.createElement('li');
var label = utils.createElement('label', {
@ -2000,15 +1997,42 @@
value: speed,
}));
if (speed === player.config.speed.selected) {
radio.checked = true;
}
label.appendChild(radio);
label.insertAdjacentHTML('beforeend', getSpeedLabel(speed));
item.appendChild(label);
list.appendChild(item);
});
setSelectedSpeed(list);
}
// Update the UI
function setSelectedSpeed(list) {
var speed = player.config.speed.selected;
// Unsupported speed
if (!utils.inArray(player.config.speed.options, speed)) {
return;
}
// Get the list if we need to
if (!utils.is.htmlElement(list)) {
list = player.elements.settings.panes.speed.querySelector('ul');
}
// Find the radio option
var target = list.querySelector('[value="' + speed + '"]');
if (!utils.is.htmlElement(target)) {
return;
}
// Check it
target.checked = true;
// Find the label
var label = player.elements.settings.tabs.speed.querySelector('.' + player.config.classes.menu.value);
label.innerHTML = getSpeedLabel(speed);
}
// Setup fullscreen
@ -2622,7 +2646,17 @@
var quality = instance.getPlaybackQuality();
// var set = player.setPlaybackQuality();
console.warn(quality);
console.warn('quality change', quality);
},
'onPlaybackRateChange': function(event) {
// Get the instance
var instance = event.target;
// Get current speed
player.media.playbackRate = instance.getPlaybackRate();
// Trigger timeupdate
trigger(player.media, 'ratechange');
},
'onReady': function(event) {
// Get the instance
@ -2647,10 +2681,9 @@
player.media.muted = instance.isMuted();
// Get available speeds
var speed = instance.getPlaybackRate();
var speedOptions = instance.getAvailablePlaybackRates();
//var set = instance.setPlaybackRate();
console.warn(speed, speedOptions);
player.config.speed.selected = instance.getPlaybackRate();
player.config.speed.options = instance.getAvailablePlaybackRates();
setSpeedMenu();
// Set title
player.config.title = instance.getVideoData().title;
@ -3834,7 +3867,7 @@
// Settings - Language
if (utils.matches(event.target, player.config.selectors.inputs.language)) {
handlerProxy.call(this, event, player.config.listeners.language, function() {
player.language(event.target.value.toLowerCase());
player.setLanguage(event.target.value.toLowerCase());
});
}
@ -4024,6 +4057,20 @@
}, false);
}
// Speed change
utils.on(player.media, 'ratechange', function(event) {
// Store current speed
player.config.speed.selected = player.media.playbackRate;
// Update UI
setSelectedSpeed();
// Save speed to localStorage
updateStorage({
speed: player.config.speed.selected
});
});
// Proxy events to container
// Bubble up key events for Edge
utils.on(player.media, player.config.events.concat(['keyup', 'keydown']).join(' '), function(event) {
@ -4562,7 +4609,6 @@
// Embeds
if (utils.inArray(types.embed, player.type)) {
// YouTube
switch (player.type) {
case 'youtube':
player.embed[player.media.muted ? 'mute' : 'unMute']();
@ -4599,22 +4645,26 @@
speed = 2.0;
}
if (!utils.is.array(player.config.speed.options)) {
player.core.warn('Invalid speeds format');
if (!utils.inArray(player.config.speed.options, speed)) {
player.core.warn('Unsupported speed (' + speed + ')');
return;
}
// Store current speed
player.config.speed.selected = speed;
// Set media speed
switch (player.type) {
case 'youtube':
player.embed.setPlaybackRate(speed);
break;
// Set HTML5 speed
// TODO: set YouTube
player.media.playbackRate = speed;
case 'vimeo':
// Vimeo not supported (https://github.com/vimeo/player.js)
player.core.warn('Vimeo playback rate change is not supported');
break;
// Save speed to localStorage
player.core.updateStorage({
speed: speed
});
default:
player.media.playbackRate = speed;
break;
}
// Allow chaining
return player;
@ -4794,18 +4844,19 @@
return player;
};
// Select active caption
Plyr.prototype.language = function(language) {
// Set caption language
Plyr.prototype.setLanguage = function(language) {
var player = this;
if (utils.is.string(language)) {
// Update config
player.config.captions.language = language.toLowerCase();
} else {
// If no language passed, return current language
return player.config.captions.language;
// Nothing specified
if (!utils.is.string(language)) {
player.core.warn('Language is required');
return;
}
// Update config
player.config.captions.language = language.toLowerCase();
// Clear caption
player.core.setCaption();
@ -4816,6 +4867,11 @@
return player;
};
// Get current language
Plyr.prototype.getLanguage = function() {
return this.config.captions.language;
};
// Toggle fullscreen
// Requires user input event
Plyr.prototype.toggleFullscreen = function(event) {