Menu toggle

This commit is contained in:
Sam Potts 2017-05-21 17:50:07 +10:00
parent e1a19faf26
commit 857dfe838c
7 changed files with 141 additions and 77 deletions

View File

@ -2,9 +2,6 @@
Please use this issue template as it makes replicating and fixing the issue easier! Please use this issue template as it makes replicating and fixing the issue easier!
---> --->
- [ ] Issue does not already exist
- [ ] Issue observed on https://plyr.io
### Expected behaviour ### Expected behaviour
### Actual behaviour ### Actual behaviour
@ -16,13 +13,5 @@ Please use this issue template as it makes replicating and fixing the issue easi
- Operating System: - Operating System:
- Version: - Version:
Players affected:
- [ ] HTML5 Video
- [ ] HTML5 Audio
- [ ] YouTube
- [ ] Vimeo
### Steps to reproduce ### Steps to reproduce
- -
### Relevant links

2
demo/dist/demo.js vendored

File diff suppressed because one or more lines are too long

View File

@ -37,6 +37,7 @@
'airplay' 'airplay'
] ]
}); });
window.loadSprite('dist/demo.svg', 'demo-sprite'); window.loadSprite('dist/demo.svg', 'demo-sprite');
// Setup type toggle // Setup type toggle

4
dist/plyr.js vendored

File diff suppressed because one or more lines are too long

View File

@ -3,15 +3,16 @@
#### To build #### To build
[x] Get list of subtitles/captions available (HTML5, Vimeo) [x] Get list of subtitles/captions available (HTML5, Vimeo)
[x] Add preferred quality option into config [x] Add preferred quality option into config
[ ] Update quality options on YouTube play (can't get up front?!) [ ] Update quality options on YouTube play
[ ] Update speed options on YouTube load [ ] Update speed options on YouTube load
[ ] Finish and test PiP (need MacOS Sierra) [ ] Hide unsupported menu items
[ ] Finish and test AirPlay (need MacOS Sierra) [ ] Test PiP (need MacOS Sierra)
[ ] Controls hide/show events [ ] Test AirPlay (need MacOS Sierra)
[ ] Test custom controls still works [ ] Add controlshidden controlsshown events
[ ] Test custom controls (with settings support for now)
[ ] Tidy up small UI for iOS inline [ ] Tidy up small UI for iOS inline
[ ] Finish new loop setup and UI [ ] Finish new loop setup and display in seek bar
[ ] Toggle settings menu [ ] Update docs for removal of setup
#### Later #### Later
[ ] Get quality options for HTML5 somehow (multi source?) [ ] Get quality options for HTML5 somehow (multi source?)

View File

@ -977,7 +977,27 @@
xhr.send(); xhr.send();
} }
},
// Get the transition end event
transitionEnd: (function() {
var element = document.createElement('span');
var events = {
WebkitTransition: 'webkitTransitionEnd',
MozTransition: 'transitionend',
OTransition: 'oTransitionEnd otransitionend',
transition: 'transitionend'
} }
for (var type in events) {
if (element.style[type] !== undefined) {
return events[type];
}
}
return false;
})()
}; };
// Fullscreen API // Fullscreen API
@ -1160,7 +1180,11 @@
// Touch // Touch
// Remember a device can be moust + touch enabled // Remember a device can be moust + touch enabled
touch: 'ontouchstart' in document.documentElement touch: 'ontouchstart' in document.documentElement,
// Detect transitions and if user has iOS & MacOS "Reduced motion" setting off
// https://webkit.org/blog/7551/responsive-design-for-motion/
transitions: utils.transitionEnd !== false && (!('matchMedia' in window) || !window.matchMedia('(prefers-reduced-motion)').matches)
}; };
// Player instance // Player instance
@ -1615,9 +1639,9 @@
// Settings button / menu // Settings button / menu
if (utils.inArray(config.controls, 'settings')) { if (utils.inArray(config.controls, 'settings')) {
var menu = utils.createElement('span', utils.extend(utils.getAttributesFromSelector(config.selectors.buttons.settings), { var menu = utils.createElement('div', {
class: 'plyr__menu' class: 'plyr__menu'
})); });
menu.appendChild(createButton('settings', { menu.appendChild(createButton('settings', {
id: 'plyr-settings-toggle-' + data.id, id: 'plyr-settings-toggle-' + data.id,
@ -1716,6 +1740,8 @@
controls.appendChild(menu); controls.appendChild(menu);
player.elements.settings.form = form;
player.elements.settings.menu = menu; player.elements.settings.menu = menu;
} }
@ -3292,42 +3318,75 @@
} }
} }
// Toggle Menu // Show/hide menu
function toggleMenu(event) { function toggleMenu(event) {
var menu = player.elements.settings.menu.parentNode; var form = player.elements.settings.form;
var toggle = event.target; var button = player.elements.buttons.settings;
var target = document.getElementById(toggle.getAttribute('aria-controls'));
var show = (toggle.getAttribute('aria-expanded') === 'false');
// Nothing to show, bail // If the click was inside the form, do nothing
if (!utils.is.htmlElement(target)) { if (form.contains(event.target)) {
return;
}
// Prevent the toggleMenu being fired twice
if (event.target === player.elements.buttons.settings) {
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);
button.setAttribute('aria-expanded', show);
if (show) {
form.removeAttribute('tabindex');
} else {
form.setAttribute('tabindex', -1);
}
}
// Toggle Menu
function showTab(event) {
var menu = player.elements.settings.menu;
var tab = event.target;
var show = tab.getAttribute('aria-expanded') === 'false';
var pane = document.getElementById(tab.getAttribute('aria-controls'));
// Nothing to show, bail
if (!utils.is.htmlElement(pane)) {
return;
}
// Are we targetting a tab? If not, bail
var isTab = pane.getAttribute('role') === 'tabpanel';
if (!isTab) {
return; return;
} }
// Are we targetting a tab?
var isTab = target.getAttribute('role') === 'tabpanel';
var targetWidth; var targetWidth;
var targetHeight; var targetHeight;
var container; var container;
// Hide all other tabs // Hide all other tabs
if (isTab) {
// Get other tabs // Get other tabs
var current = menu.querySelector('[role="tabpanel"][aria-hidden="false"]'); var current = menu.querySelector('[role="tabpanel"][aria-hidden="false"]');
container = current.parentNode; container = current.parentNode;
// Set other toggles to be expanded false
[].forEach.call(menu.querySelectorAll('[aria-controls="' + current.getAttribute('id') + '"]'), function(toggle) { [].forEach.call(menu.querySelectorAll('[aria-controls="' + current.getAttribute('id') + '"]'), function(toggle) {
toggle.setAttribute('aria-expanded', false); toggle.setAttribute('aria-expanded', false);
}); });
// If we can do fancy animations, we'll animate the height/width
if (support.transitions) {
// Set the current width as a base
container.style.width = current.scrollWidth + 'px'; container.style.width = current.scrollWidth + 'px';
container.style.height = current.scrollHeight + 'px'; container.style.height = current.scrollHeight + 'px';
current.setAttribute('aria-hidden', true); // Get the natural element size of the target pane
current.setAttribute('tabindex', -1); var clone = pane.cloneNode(true);
// Get the natural element size
var clone = target.cloneNode(true);
clone.style.position = "absolute"; clone.style.position = "absolute";
clone.style.opacity = 0; clone.style.opacity = 0;
clone.setAttribute('aria-hidden', false); clone.setAttribute('aria-hidden', false);
@ -3335,21 +3394,39 @@
targetWidth = clone.scrollWidth; targetWidth = clone.scrollWidth;
targetHeight = clone.scrollHeight; targetHeight = clone.scrollHeight;
utils.removeElement(clone); utils.removeElement(clone);
// Restore auto height/width
var restore = function(event) {
// We're only bothered about height and width on the container
if (event.target !== container ||
!utils.inArray(['width', 'height'], event.propertyName)) {
return;
} }
target.setAttribute('aria-hidden', !show); // Revert back to auto
toggle.setAttribute('aria-expanded', show);
target.removeAttribute('tabindex');
if (isTab) {
container.style.width = targetWidth + 'px';
container.style.height = targetHeight + 'px';
window.setTimeout(function() {
container.style.width = ''; container.style.width = '';
container.style.height = ''; container.style.height = '';
}, 300);
// Only listen once
utils.off(container, utils.transitionEnd, restore)
} }
// Listen for the transtion finishing and restore auto height/width
utils.on(container, utils.transitionEnd, restore);
// Set dimensions to target
container.style.width = targetWidth + 'px';
container.style.height = targetHeight + 'px';
}
// Set attributes on current tab
current.setAttribute('aria-hidden', true);
current.setAttribute('tabindex', -1);
// Set attributes on target
pane.setAttribute('aria-hidden', !show);
tab.setAttribute('aria-expanded', show);
pane.removeAttribute('tabindex');
} }
// Mute // Mute
@ -4275,23 +4352,16 @@
}); });
// Settings menu // Settings menu
utils.on(player.elements.settings.menu, 'click', toggleMenu); utils.on(player.elements.buttons.settings, 'click', toggleMenu);
// Click anywhere closes menu // Click anywhere closes menu
utils.on(document.body, 'click', function(event) { utils.on(document.body, 'click', toggleMenu);
var menu = player.elements.settings.menu;
var form = menu.querySelector('form');
if (form.getAttribute('aria-hidden') === 'true' || menu.contains(event.target)) { // Show tab in menu
return; utils.on(player.elements.settings.form, 'click', showTab);
}
// TODO: This should call some sort of menuToggle function?
form.setAttribute('aria-hidden', true);
});
// Settings menu items - use event delegation as items are added/removed // Settings menu items - use event delegation as items are added/removed
utils.on(player.elements.settings.menu, 'click', function(event) { utils.on(player.elements.settings.form, 'click', function(event) {
// Settings - Language // Settings - Language
if (utils.matches(event.target, config.selectors.inputs.language)) { if (utils.matches(event.target, config.selectors.inputs.language)) {
handlerProxy.call(this, event, config.listeners.language, setLanguage); handlerProxy.call(this, event, config.listeners.language, setLanguage);

View File

@ -336,7 +336,9 @@
background: transparent; background: transparent;
border-radius: 3px; border-radius: 3px;
cursor: pointer; cursor: pointer;
transition: background .3s ease, color .3s ease, opacity .3s ease; transition: background .3s ease,
color .3s ease,
opacity .3s ease;
color: inherit; color: inherit;
svg { svg {
@ -515,7 +517,8 @@
> div { > div {
overflow: hidden; overflow: hidden;
transition: height .35s cubic-bezier(.4,0,.2,1), width .35s cubic-bezier(.4,0,.2,1); transition: height .35s cubic-bezier(.4, 0, .2, 1),
width .35s cubic-bezier(.4, 0, .2, 1);
} }
// Arrow // Arrow