Menu toggle
This commit is contained in:
		
							
								
								
									
										25
									
								
								.github/issue_template.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								.github/issue_template.md
									
									
									
									
										vendored
									
									
								
							| @ -1,28 +1,17 @@ | |||||||
| <!---  | <!--- | ||||||
| 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 | ### Expected behaviour | ||||||
| - [ ] Issue observed on https://plyr.io |  | ||||||
|  |  | ||||||
| ### Expected behaviour  |  | ||||||
|  |  | ||||||
| ### Actual behaviour | ### Actual behaviour | ||||||
|  |  | ||||||
| ### Environment | ### Environment | ||||||
|  |  | ||||||
| - Browser: | - Browser: | ||||||
| - Version:   | - Version: | ||||||
| - Operating System: | - Operating System: | ||||||
| - Version:  | - Version: | ||||||
|  |  | ||||||
| Players affected: | ### Steps to reproduce | ||||||
| - [ ] HTML5 Video | - | ||||||
| - [ ] HTML5 Audio |  | ||||||
| - [ ] YouTube |  | ||||||
| - [ ] Vimeo |  | ||||||
|  |  | ||||||
| ### Steps to reproduce  |  | ||||||
| -  |  | ||||||
|  |  | ||||||
| ### Relevant links |  | ||||||
							
								
								
									
										2
									
								
								demo/dist/demo.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								demo/dist/demo.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -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
									
									
								
							
							
						
						
									
										4
									
								
								dist/plyr.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										15
									
								
								notes.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								notes.md
									
									
									
									
									
								
							| @ -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?) | ||||||
|  | |||||||
							
								
								
									
										164
									
								
								src/js/plyr.js
									
									
									
									
									
								
							
							
						
						
									
										164
									
								
								src/js/plyr.js
									
									
									
									
									
								
							| @ -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; |  | ||||||
|  |  | ||||||
|                 [].forEach.call(menu.querySelectorAll('[aria-controls="' + current.getAttribute('id') + '"]'), function(toggle) { |             // Set other toggles to be expanded false | ||||||
|                     toggle.setAttribute('aria-expanded', false); |             [].forEach.call(menu.querySelectorAll('[aria-controls="' + current.getAttribute('id') + '"]'), function(toggle) { | ||||||
|                 }); |                 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); | ||||||
|             } |  | ||||||
|  |  | ||||||
|             target.setAttribute('aria-hidden', !show); |                 // Restore auto height/width | ||||||
|             toggle.setAttribute('aria-expanded', show); |                 var restore = function(event) { | ||||||
|             target.removeAttribute('tabindex'); |                     // We're only bothered about height and width on the container | ||||||
|  |                     if (event.target !== container || | ||||||
|  |                         !utils.inArray(['width', 'height'], event.propertyName)) { | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |  | ||||||
|             if (isTab) { |                     // Revert back to auto | ||||||
|                 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); | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user