Work on playback rate changes
This commit is contained in:
parent
7b60e473fa
commit
a9957211f4
4
dist/plyr.js
vendored
4
dist/plyr.js
vendored
File diff suppressed because one or more lines are too long
84
notes.md
84
notes.md
@ -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
|
|
180
src/js/plyr.js
180
src/js/plyr.js
@ -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
|
// Find all elements
|
||||||
function getElements(selector) {
|
function getElements(selector) {
|
||||||
return player.elements.container.querySelectorAll(selector);
|
return player.elements.container.querySelectorAll(selector);
|
||||||
@ -1280,6 +1305,7 @@
|
|||||||
return getElements(selector)[0];
|
return getElements(selector)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove an element
|
||||||
function removeElement(element) {
|
function removeElement(element) {
|
||||||
// Remove reference from player.elements cache
|
// Remove reference from player.elements cache
|
||||||
if (utils.is.string(element)) {
|
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
|
// Get icon URL
|
||||||
function getIconUrl() {
|
function getIconUrl() {
|
||||||
return {
|
return {
|
||||||
@ -1972,7 +1973,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set a list of available captions languages
|
// Set a list of available captions languages
|
||||||
function setSpeedMenu(options) {
|
function setSpeedMenu() {
|
||||||
var list = player.elements.settings.panes.speed.querySelector('ul');
|
var list = player.elements.settings.panes.speed.querySelector('ul');
|
||||||
|
|
||||||
// Show the pane and tab
|
// Show the pane and tab
|
||||||
@ -1982,12 +1983,8 @@
|
|||||||
// Empty the menu
|
// Empty the menu
|
||||||
utils.emptyElement(list);
|
utils.emptyElement(list);
|
||||||
|
|
||||||
// If there's no captions, bail
|
// Create items
|
||||||
if (!utils.is.array(options)) {
|
player.config.speed.options.forEach(function(speed) {
|
||||||
options = player.config.speed.options;
|
|
||||||
}
|
|
||||||
|
|
||||||
options.forEach(function(speed) {
|
|
||||||
var item = utils.createElement('li');
|
var item = utils.createElement('li');
|
||||||
|
|
||||||
var label = utils.createElement('label', {
|
var label = utils.createElement('label', {
|
||||||
@ -2000,15 +1997,42 @@
|
|||||||
value: speed,
|
value: speed,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (speed === player.config.speed.selected) {
|
|
||||||
radio.checked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
label.appendChild(radio);
|
label.appendChild(radio);
|
||||||
label.insertAdjacentHTML('beforeend', getSpeedLabel(speed));
|
label.insertAdjacentHTML('beforeend', getSpeedLabel(speed));
|
||||||
item.appendChild(label);
|
item.appendChild(label);
|
||||||
list.appendChild(item);
|
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
|
// Setup fullscreen
|
||||||
@ -2622,7 +2646,17 @@
|
|||||||
var quality = instance.getPlaybackQuality();
|
var quality = instance.getPlaybackQuality();
|
||||||
|
|
||||||
// var set = player.setPlaybackQuality();
|
// 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) {
|
'onReady': function(event) {
|
||||||
// Get the instance
|
// Get the instance
|
||||||
@ -2647,10 +2681,9 @@
|
|||||||
player.media.muted = instance.isMuted();
|
player.media.muted = instance.isMuted();
|
||||||
|
|
||||||
// Get available speeds
|
// Get available speeds
|
||||||
var speed = instance.getPlaybackRate();
|
player.config.speed.selected = instance.getPlaybackRate();
|
||||||
var speedOptions = instance.getAvailablePlaybackRates();
|
player.config.speed.options = instance.getAvailablePlaybackRates();
|
||||||
//var set = instance.setPlaybackRate();
|
setSpeedMenu();
|
||||||
console.warn(speed, speedOptions);
|
|
||||||
|
|
||||||
// Set title
|
// Set title
|
||||||
player.config.title = instance.getVideoData().title;
|
player.config.title = instance.getVideoData().title;
|
||||||
@ -3834,7 +3867,7 @@
|
|||||||
// Settings - Language
|
// Settings - Language
|
||||||
if (utils.matches(event.target, player.config.selectors.inputs.language)) {
|
if (utils.matches(event.target, player.config.selectors.inputs.language)) {
|
||||||
handlerProxy.call(this, event, player.config.listeners.language, function() {
|
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);
|
}, 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
|
// Proxy events to container
|
||||||
// Bubble up key events for Edge
|
// Bubble up key events for Edge
|
||||||
utils.on(player.media, player.config.events.concat(['keyup', 'keydown']).join(' '), function(event) {
|
utils.on(player.media, player.config.events.concat(['keyup', 'keydown']).join(' '), function(event) {
|
||||||
@ -4562,7 +4609,6 @@
|
|||||||
|
|
||||||
// Embeds
|
// Embeds
|
||||||
if (utils.inArray(types.embed, player.type)) {
|
if (utils.inArray(types.embed, player.type)) {
|
||||||
// YouTube
|
|
||||||
switch (player.type) {
|
switch (player.type) {
|
||||||
case 'youtube':
|
case 'youtube':
|
||||||
player.embed[player.media.muted ? 'mute' : 'unMute']();
|
player.embed[player.media.muted ? 'mute' : 'unMute']();
|
||||||
@ -4599,22 +4645,26 @@
|
|||||||
speed = 2.0;
|
speed = 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!utils.is.array(player.config.speed.options)) {
|
if (!utils.inArray(player.config.speed.options, speed)) {
|
||||||
player.core.warn('Invalid speeds format');
|
player.core.warn('Unsupported speed (' + speed + ')');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store current speed
|
// Set media speed
|
||||||
player.config.speed.selected = speed;
|
switch (player.type) {
|
||||||
|
case 'youtube':
|
||||||
|
player.embed.setPlaybackRate(speed);
|
||||||
|
break;
|
||||||
|
|
||||||
// Set HTML5 speed
|
case 'vimeo':
|
||||||
// TODO: set YouTube
|
// Vimeo not supported (https://github.com/vimeo/player.js)
|
||||||
player.media.playbackRate = speed;
|
player.core.warn('Vimeo playback rate change is not supported');
|
||||||
|
break;
|
||||||
|
|
||||||
// Save speed to localStorage
|
default:
|
||||||
player.core.updateStorage({
|
player.media.playbackRate = speed;
|
||||||
speed: speed
|
break;
|
||||||
});
|
}
|
||||||
|
|
||||||
// Allow chaining
|
// Allow chaining
|
||||||
return player;
|
return player;
|
||||||
@ -4794,18 +4844,19 @@
|
|||||||
return player;
|
return player;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Select active caption
|
// Set caption language
|
||||||
Plyr.prototype.language = function(language) {
|
Plyr.prototype.setLanguage = function(language) {
|
||||||
var player = this;
|
var player = this;
|
||||||
|
|
||||||
if (utils.is.string(language)) {
|
// Nothing specified
|
||||||
// Update config
|
if (!utils.is.string(language)) {
|
||||||
player.config.captions.language = language.toLowerCase();
|
player.core.warn('Language is required');
|
||||||
} else {
|
return;
|
||||||
// If no language passed, return current language
|
|
||||||
return player.config.captions.language;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update config
|
||||||
|
player.config.captions.language = language.toLowerCase();
|
||||||
|
|
||||||
// Clear caption
|
// Clear caption
|
||||||
player.core.setCaption();
|
player.core.setCaption();
|
||||||
|
|
||||||
@ -4816,6 +4867,11 @@
|
|||||||
return player;
|
return player;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Get current language
|
||||||
|
Plyr.prototype.getLanguage = function() {
|
||||||
|
return this.config.captions.language;
|
||||||
|
};
|
||||||
|
|
||||||
// Toggle fullscreen
|
// Toggle fullscreen
|
||||||
// Requires user input event
|
// Requires user input event
|
||||||
Plyr.prototype.toggleFullscreen = function(event) {
|
Plyr.prototype.toggleFullscreen = function(event) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user