More work on the menu
This commit is contained in:
parent
857dfe838c
commit
86c9004183
2
demo/dist/demo.js
vendored
2
demo/dist/demo.js
vendored
File diff suppressed because one or more lines are too long
@ -1,12 +1,11 @@
|
||||
// ==========================================================================
|
||||
// Plyr.io demo
|
||||
// This code is purely for the plyr.io website
|
||||
// This code is purely for the https://plyr.io website
|
||||
// Please see readme.md in the root or github.com/sampotts/plyr
|
||||
// ==========================================================================
|
||||
|
||||
/*global Plyr*/
|
||||
|
||||
// General functions
|
||||
(function() {
|
||||
/*document.body.addEventListener('ready', function(event) {
|
||||
console.log(event);
|
||||
@ -186,14 +185,15 @@
|
||||
})();
|
||||
|
||||
// Google analytics
|
||||
// For demo site (http://[www.]plyr.io) only
|
||||
if (document.domain.indexOf('plyr.io') > -1) {
|
||||
// For demo site (https://plyr.io) only
|
||||
if (window.location.host === 'plyr.io') {
|
||||
(function(i, s, o, g, r, a, m) {
|
||||
i.GoogleAnalyticsObject = r;
|
||||
i[r] = i[r] || function() {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
};
|
||||
i[r].l = 1 * new Date();
|
||||
a = s.createElement(o);
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
|
2
dist/plyr.css
vendored
2
dist/plyr.css
vendored
File diff suppressed because one or more lines are too long
4
dist/plyr.js
vendored
4
dist/plyr.js
vendored
File diff suppressed because one or more lines are too long
17
notes.md
17
notes.md
@ -1,20 +1,27 @@
|
||||
### Todo
|
||||
|
||||
#### To build
|
||||
#### 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
|
||||
[ ] Hide unsupported menu items
|
||||
[ ] Handle quality change for YouTube
|
||||
[ ] Handle speed change for YouTube
|
||||
[ ] Set quality when loading YouTube vid
|
||||
[ ] Set "home" values
|
||||
[ ] Hide unsupported menu items (+ on source change)
|
||||
[ ] Test PiP (need MacOS Sierra)
|
||||
[ ] Test AirPlay (need MacOS Sierra)
|
||||
[ ] Add controlshidden controlsshown events
|
||||
[ ] Add `controlshidden` and `controlsshown` events
|
||||
[ ] Test custom controls (with 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 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
|
||||
|
||||
@ -23,7 +30,7 @@
|
||||
[ ] Fix events on unsupported devices (iOS, old IE)
|
||||
[x] Fix YouTube rights blocking (origin perhaps?)
|
||||
|
||||
# Notes
|
||||
### Release notes
|
||||
- No quality HTML5 support (yet)
|
||||
- No Vimeo quality support
|
||||
- No YouTube caption support
|
||||
@ -39,6 +46,6 @@
|
||||
- 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
|
||||
|
||||
## Added
|
||||
#### Added
|
||||
- Seek i8n label
|
||||
- Loop related i8n labels
|
167
src/js/plyr.js
167
src/js/plyr.js
@ -68,8 +68,8 @@
|
||||
|
||||
// Speed up/down
|
||||
speed: {
|
||||
selected: 1.0,
|
||||
options: [0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 2.0]
|
||||
selected: 1,
|
||||
options: [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2]
|
||||
},
|
||||
|
||||
// Keyboard shortcut settings
|
||||
@ -204,6 +204,12 @@
|
||||
'airplay',
|
||||
'fullscreen'
|
||||
],
|
||||
settings: [
|
||||
'captions',
|
||||
'quality',
|
||||
'speed',
|
||||
'loop'
|
||||
],
|
||||
|
||||
// Localisation
|
||||
i18n: {
|
||||
@ -1442,13 +1448,9 @@
|
||||
}));
|
||||
}
|
||||
|
||||
// Add the icon
|
||||
button.appendChild(createIcon(iconDefault));
|
||||
|
||||
// Add the label
|
||||
button.appendChild(createLabel(labelKey));
|
||||
|
||||
// Set element attributes
|
||||
utils.setAttributes(button, attributes);
|
||||
|
||||
player.elements.buttons[type] = button;
|
||||
@ -1668,13 +1670,16 @@
|
||||
role: 'tabpanel'
|
||||
});
|
||||
|
||||
// Create the tab list
|
||||
var tabs = utils.createElement('ul', {
|
||||
role: 'tablist'
|
||||
});
|
||||
|
||||
['captions', 'quality', 'speed', 'loop'].forEach(function(type) {
|
||||
// Build the tabs
|
||||
config.settings.forEach(function(type) {
|
||||
var tab = utils.createElement('li', {
|
||||
role: 'tab'
|
||||
role: 'tab',
|
||||
hidden: ''
|
||||
});
|
||||
|
||||
var button = utils.createElement('button', utils.extend(utils.getAttributesFromSelector(config.selectors.buttons.settings), {
|
||||
@ -1694,25 +1699,24 @@
|
||||
value.innerHTML = data[type];
|
||||
|
||||
button.appendChild(value);
|
||||
|
||||
tab.appendChild(button);
|
||||
|
||||
tabs.appendChild(tab);
|
||||
|
||||
player.elements.settings.tabs[type] = tab;
|
||||
});
|
||||
|
||||
home.appendChild(tabs);
|
||||
|
||||
inner.appendChild(home);
|
||||
|
||||
['captions', 'quality', 'speed', 'loop'].forEach(function(type) {
|
||||
// Build the panes
|
||||
config.settings.forEach(function(type) {
|
||||
var pane = utils.createElement('div', {
|
||||
id: 'plyr-settings-' + data.id + '-' + type,
|
||||
'aria-hidden': true,
|
||||
'aria-labelled-by': 'plyr-settings-' + data.id + '-' + type + '-tab',
|
||||
role: 'tabpanel',
|
||||
tabindex: -1
|
||||
tabindex: -1,
|
||||
hidden: ''
|
||||
});
|
||||
|
||||
var back = utils.createElement('button', {
|
||||
@ -1728,20 +1732,16 @@
|
||||
var options = utils.createElement('ul');
|
||||
|
||||
pane.appendChild(options);
|
||||
|
||||
inner.appendChild(pane);
|
||||
|
||||
player.elements.settings.panes[type] = pane;
|
||||
});
|
||||
|
||||
form.appendChild(inner);
|
||||
|
||||
menu.appendChild(form);
|
||||
|
||||
controls.appendChild(menu);
|
||||
|
||||
player.elements.settings.form = form;
|
||||
|
||||
player.elements.settings.menu = menu;
|
||||
}
|
||||
|
||||
@ -1774,6 +1774,10 @@
|
||||
function setQualityMenu(options, current) {
|
||||
var list = player.elements.settings.panes.quality.querySelector('ul');
|
||||
|
||||
// Show the pane and tab
|
||||
player.elements.settings.tabs.quality.removeAttribute('hidden');
|
||||
player.elements.settings.panes.quality.removeAttribute('hidden');
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
|
||||
@ -1833,19 +1837,17 @@
|
||||
var item = utils.createElement('li');
|
||||
|
||||
var label = utils.createElement('label', {
|
||||
class: config.classes.control,
|
||||
for: 'plyr-quality-' + quality
|
||||
class: config.classes.control
|
||||
});
|
||||
|
||||
var radio = utils.createElement('input', utils.extend(utils.getAttributesFromSelector(config.selectors.inputs.quality), {
|
||||
type: 'radio',
|
||||
id: 'plyr-quality-' + quality,
|
||||
name: 'plyr-quality',
|
||||
value: quality,
|
||||
}));
|
||||
|
||||
if (quality === config.quality.selected) {
|
||||
radio.setAttribute('checked', '');
|
||||
radio.checked = true;
|
||||
}
|
||||
|
||||
label.appendChild(radio);
|
||||
@ -1857,7 +1859,6 @@
|
||||
}
|
||||
|
||||
item.appendChild(label);
|
||||
|
||||
list.appendChild(item);
|
||||
});
|
||||
}
|
||||
@ -1868,6 +1869,10 @@
|
||||
var options = ['start', 'end', 'all', 'reset'];
|
||||
var list = player.elements.settings.panes.loop.querySelector('ul');
|
||||
|
||||
// Show the pane and tab
|
||||
player.elements.settings.tabs.loop.removeAttribute('hidden');
|
||||
player.elements.settings.panes.loop.removeAttribute('hidden');
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
|
||||
@ -1881,12 +1886,11 @@
|
||||
}), config.i18n[option]);
|
||||
|
||||
if (utils.inArray(['start', 'end'], option)) {
|
||||
var badge = createBadge('0:00');
|
||||
var badge = createBadge('00:00');
|
||||
button.appendChild(badge);
|
||||
}
|
||||
|
||||
item.appendChild(button);
|
||||
|
||||
list.appendChild(item);
|
||||
});
|
||||
}
|
||||
@ -1895,6 +1899,10 @@
|
||||
function setCaptionsMenu() {
|
||||
var list = player.elements.settings.panes.captions.querySelector('ul');
|
||||
|
||||
// Show the pane and tab
|
||||
player.elements.settings.tabs.captions.removeAttribute('hidden');
|
||||
player.elements.settings.panes.captions.removeAttribute('hidden');
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
|
||||
@ -1923,19 +1931,17 @@
|
||||
var item = utils.createElement('li');
|
||||
|
||||
var label = utils.createElement('label', {
|
||||
class: config.classes.control,
|
||||
for: 'plyr-language-' + track.language
|
||||
class: config.classes.control
|
||||
});
|
||||
|
||||
var radio = utils.createElement('input', utils.extend(utils.getAttributesFromSelector(config.selectors.inputs.language), {
|
||||
type: 'radio',
|
||||
id: 'plyr-language-' + track.language,
|
||||
name: 'plyr-language',
|
||||
value: track.language,
|
||||
}));
|
||||
|
||||
if (track.language === config.captions.language.toLowerCase()) {
|
||||
radio.setAttribute('checked', '');
|
||||
if (track.language.toLowerCase() === config.captions.language.toLowerCase()) {
|
||||
radio.checked = true;
|
||||
}
|
||||
|
||||
label.appendChild(radio);
|
||||
@ -1946,7 +1952,6 @@
|
||||
}
|
||||
|
||||
item.appendChild(label);
|
||||
|
||||
list.appendChild(item);
|
||||
});
|
||||
}
|
||||
@ -1955,6 +1960,10 @@
|
||||
function setSpeedMenu(options) {
|
||||
var list = player.elements.settings.panes.speed.querySelector('ul');
|
||||
|
||||
// Show the pane and tab
|
||||
player.elements.settings.tabs.speed.removeAttribute('hidden');
|
||||
player.elements.settings.panes.speed.removeAttribute('hidden');
|
||||
|
||||
// Empty the menu
|
||||
utils.emptyElement(list);
|
||||
|
||||
@ -1967,26 +1976,22 @@
|
||||
var item = utils.createElement('li');
|
||||
|
||||
var label = utils.createElement('label', {
|
||||
class: config.classes.control,
|
||||
for: 'plyr-speed-' + speed.toString().replace('.', '-')
|
||||
class: config.classes.control
|
||||
});
|
||||
|
||||
var radio = utils.createElement('input', utils.extend(utils.getAttributesFromSelector(config.selectors.inputs.speed), {
|
||||
type: 'radio',
|
||||
id: 'plyr-speed-' + speed.toString().replace('.', '-'),
|
||||
name: 'plyr-speed',
|
||||
value: speed,
|
||||
}));
|
||||
|
||||
if (speed === config.speed.selected) {
|
||||
radio.setAttribute('checked', '');
|
||||
radio.checked = true;
|
||||
}
|
||||
|
||||
label.appendChild(radio);
|
||||
label.insertAdjacentHTML('beforeend', '×' + speed);
|
||||
|
||||
label.insertAdjacentHTML('beforeend', getSpeedLabel(speed));
|
||||
item.appendChild(label);
|
||||
|
||||
list.appendChild(item);
|
||||
});
|
||||
}
|
||||
@ -2259,7 +2264,7 @@
|
||||
controls = createControls({
|
||||
id: player.id,
|
||||
seektime: config.seekTime,
|
||||
speed: getSpeed(),
|
||||
speed: getSpeedLabel(),
|
||||
// TODO: Get current quality
|
||||
quality: 'HD',
|
||||
captions: getLanguage(),
|
||||
@ -3136,8 +3141,16 @@
|
||||
}
|
||||
|
||||
// Get the current speed value
|
||||
function getSpeed() {
|
||||
return config.speed.selected.toFixed(1).toString().replace('.0', '') + '×'
|
||||
function getSpeedLabel(speed) {
|
||||
if (!utils.is.number(speed)) {
|
||||
speed = config.speed.selected;
|
||||
}
|
||||
|
||||
if (speed === 1) {
|
||||
return 'Normal';
|
||||
}
|
||||
|
||||
return speed + '×';
|
||||
}
|
||||
|
||||
// Rewind
|
||||
@ -3322,19 +3335,24 @@
|
||||
function toggleMenu(event) {
|
||||
var form = player.elements.settings.form;
|
||||
var button = player.elements.buttons.settings;
|
||||
var show = utils.is.boolean(event) ? event : form.getAttribute('aria-hidden') === 'true';
|
||||
|
||||
// If the click was inside the form, do nothing
|
||||
if (form.contains(event.target)) {
|
||||
if (utils.is.event(event)) {
|
||||
var isMenuItem = form.contains(event.target);
|
||||
var isButton = event.target === player.elements.buttons.settings;
|
||||
|
||||
// If the click was inside the form or if the click
|
||||
// wasn't the button or menu item and we're trying to
|
||||
// show the menu (a doc click shouldn't show the menu)
|
||||
if (isMenuItem || (!isMenuItem && !isButton && show)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent the toggleMenu being fired twice
|
||||
if (event.target === player.elements.buttons.settings) {
|
||||
// Prevent the toggle being caught by the doc listener
|
||||
if (isButton) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
// Do we need to show it?
|
||||
var show = form.getAttribute('aria-hidden') === 'true';
|
||||
}
|
||||
|
||||
// Set form and button attributes
|
||||
form.setAttribute('aria-hidden', !show);
|
||||
@ -3347,6 +3365,38 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Get the natural size of a tab
|
||||
function getTabSize(tab) {
|
||||
var width;
|
||||
var height;
|
||||
|
||||
var clone = tab.cloneNode(true);
|
||||
clone.style.position = "absolute";
|
||||
clone.style.opacity = 0;
|
||||
clone.setAttribute('aria-hidden', false);
|
||||
|
||||
// Prevent input's being unchecked due to the name being identical
|
||||
[].forEach.call(clone.querySelectorAll('input[name]'), function(input) {
|
||||
var name = input.getAttribute('name');
|
||||
input.setAttribute('name', name + '-clone');
|
||||
});
|
||||
|
||||
// Append to parent so we get the "real" size
|
||||
tab.parentNode.appendChild(clone);
|
||||
|
||||
// Get the sizes before we remove
|
||||
width = clone.scrollWidth;
|
||||
height = clone.scrollHeight;
|
||||
|
||||
// Remove from the DOM
|
||||
utils.removeElement(clone);
|
||||
|
||||
return {
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
}
|
||||
|
||||
// Toggle Menu
|
||||
function showTab(event) {
|
||||
var menu = player.elements.settings.menu;
|
||||
@ -3365,14 +3415,10 @@
|
||||
return;
|
||||
}
|
||||
|
||||
var targetWidth;
|
||||
var targetHeight;
|
||||
var container;
|
||||
|
||||
// Hide all other tabs
|
||||
// Get other tabs
|
||||
var current = menu.querySelector('[role="tabpanel"][aria-hidden="false"]');
|
||||
container = current.parentNode;
|
||||
var container = current.parentNode;
|
||||
|
||||
// Set other toggles to be expanded false
|
||||
[].forEach.call(menu.querySelectorAll('[aria-controls="' + current.getAttribute('id') + '"]'), function(toggle) {
|
||||
@ -3385,15 +3431,8 @@
|
||||
container.style.width = current.scrollWidth + 'px';
|
||||
container.style.height = current.scrollHeight + 'px';
|
||||
|
||||
// Get the natural element size of the target pane
|
||||
var clone = pane.cloneNode(true);
|
||||
clone.style.position = "absolute";
|
||||
clone.style.opacity = 0;
|
||||
clone.setAttribute('aria-hidden', false);
|
||||
container.appendChild(clone);
|
||||
targetWidth = clone.scrollWidth;
|
||||
targetHeight = clone.scrollHeight;
|
||||
utils.removeElement(clone);
|
||||
// Get potential sizes
|
||||
var size = getTabSize(pane);
|
||||
|
||||
// Restore auto height/width
|
||||
var restore = function(event) {
|
||||
@ -3415,8 +3454,8 @@
|
||||
utils.on(container, utils.transitionEnd, restore);
|
||||
|
||||
// Set dimensions to target
|
||||
container.style.width = targetWidth + 'px';
|
||||
container.style.height = targetHeight + 'px';
|
||||
container.style.width = size.width + 'px';
|
||||
container.style.height = size.height + 'px';
|
||||
}
|
||||
|
||||
// Set attributes on current tab
|
||||
@ -4355,7 +4394,7 @@
|
||||
utils.on(player.elements.buttons.settings, 'click', toggleMenu);
|
||||
|
||||
// Click anywhere closes menu
|
||||
utils.on(document.body, 'click', toggleMenu);
|
||||
utils.on(document.documentElement, 'click', toggleMenu);
|
||||
|
||||
// Show tab in menu
|
||||
utils.on(player.elements.settings.form, 'click', showTab);
|
||||
|
@ -503,7 +503,7 @@
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 100%;
|
||||
right: -5px;
|
||||
right: -3px;
|
||||
margin-bottom: 10px;
|
||||
animation: plyr-popup .2s ease;
|
||||
|
||||
@ -529,7 +529,7 @@
|
||||
right: 15px;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border: 6px solid transparent;
|
||||
border: 4px solid transparent;
|
||||
border-top-color: @plyr-menu-bg;
|
||||
}
|
||||
|
||||
@ -554,7 +554,7 @@
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
border: 5px solid transparent;
|
||||
border: 4px solid transparent;
|
||||
}
|
||||
|
||||
&--forward {
|
||||
@ -576,7 +576,7 @@
|
||||
font-weight: 500;
|
||||
|
||||
&::after {
|
||||
left: 5px;
|
||||
left: @plyr-control-padding;
|
||||
border-right-color: fade(@plyr-menu-color, 80%);
|
||||
}
|
||||
&::before {
|
||||
@ -617,12 +617,6 @@
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
// When animating between menus
|
||||
&.is-resizing {
|
||||
overflow: hidden;
|
||||
transition: height .35s cubic-bezier(.4,0,.2,1), width .35s cubic-bezier(.4,0,.2,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user