Merge pull request #490 from platformpurple/develop
Playback speed and looping controls
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -6,3 +6,6 @@ aws.json | ||||
| *.mp4 | ||||
| index-*.html | ||||
| notes.txt | ||||
| .idea | ||||
| .DS_Store | ||||
| npm-debug.log | ||||
							
								
								
									
										4
									
								
								dist/plyr.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								dist/plyr.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -257,7 +257,7 @@ Note the single quotes encapsulating the JSON and double quotes on the object ke | ||||
|     <tr> | ||||
|       <td><code>controls</code></td> | ||||
|       <td>Array</td> | ||||
|       <td><code>['play-large', 'play', 'speed-up', 'progress', 'current-time', 'mute', 'volume', 'captions', 'fullscreen']</code></td> | ||||
|       <td><code>['play-large', 'play', 'progress', 'current-time', 'mute', 'volume', 'captions', 'fullscreen']</code></td> | ||||
|       <td>Toggle which control elements you would like to display when using the default controls html. If you specify a <code>html</code> option, this is redundant. The default value is to display everything.</td> | ||||
|     </tr> | ||||
|     <tr> | ||||
| @ -402,6 +402,12 @@ Note the single quotes encapsulating the JSON and double quotes on the object ke | ||||
|       <td>[1.0, 1.5, 2.0, 0.5]</td> | ||||
|       <td>Playback speed list.</td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>loops</code></td> | ||||
|       <td>Array</td> | ||||
|       <td>[Loop All, Loop in, Loop out, No Loop]</td> | ||||
|       <td>Playback loop list.</td> | ||||
|     </tr> | ||||
|   </tbody> | ||||
| </table> | ||||
|  | ||||
|  | ||||
							
								
								
									
										170
									
								
								src/js/plyr.js
									
									
									
									
									
								
							
							
						
						
									
										170
									
								
								src/js/plyr.js
									
									
									
									
									
								
							| @ -38,13 +38,15 @@ | ||||
|             debug: false, | ||||
|             autoplay: false, | ||||
|             loop: false, | ||||
|             loopin: 0, | ||||
|             loopout: null, | ||||
|             seekTime: 10, | ||||
|             volume: 10, | ||||
|             volumeMin: 0, | ||||
|             volumeMax: 10, | ||||
|             volumeStep: 1, | ||||
|             defaultSpeed: 1.0, | ||||
|             currentSpeed: 1.0, | ||||
|             currentSpeed: 1, | ||||
|             speeds: [0.5, 1.0, 1.5, 2.0], | ||||
|             duration: null, | ||||
|             displayDuration: true, | ||||
| @ -85,7 +87,9 @@ | ||||
|                     fullscreen: '[data-plyr="fullscreen"]', | ||||
|                     settings: '[data-plyr="settings"]', | ||||
|                     pip: '[data-plyr="pip"]', | ||||
|                     airplay: '[data-plyr="airplay"]' | ||||
|                     airplay: '[data-plyr="airplay"]', | ||||
|                     speed: '[data-plyr="speed"]', | ||||
|                     loop: '[data-plyr="loop"]' | ||||
|                 }, | ||||
|                 volume: { | ||||
|                     input: '[data-plyr="volume"]', | ||||
| @ -162,7 +166,12 @@ | ||||
|                 captions: 'Captions', | ||||
|                 settings: 'Settings', | ||||
|                 speed: 'Speed', | ||||
|                 quality: 'Quality' | ||||
|                 quality: 'Quality', | ||||
|                 loop: 'Loop', | ||||
|                 loopin: 'Loop in', | ||||
|                 loopout: 'Loop out', | ||||
|                 loopall: 'Loop all', | ||||
|                 loopclear: 'No Loop', | ||||
|             }, | ||||
|             types: { | ||||
|                 embed: ['youtube', 'vimeo', 'soundcloud'], | ||||
| @ -192,7 +201,8 @@ | ||||
|                 volume: null, | ||||
|                 captions: null, | ||||
|                 fullscreen: null, | ||||
|                 speed: null | ||||
|                 speed: null, | ||||
|                 loop: null | ||||
|             }, | ||||
|             // Events to watch on HTML5 media elements | ||||
|             events: ['ready', 'ended', 'progress', 'stalled', 'playing', 'waiting', 'canplay', 'canplaythrough', 'loadstart', 'loadeddata', 'loadedmetadata', 'timeupdate', 'volumechange', 'play', 'pause', 'error', 'seeking', 'seeked', 'emptied'], | ||||
| @ -987,7 +997,7 @@ | ||||
|                                         '<li role="tab">', | ||||
|                                             '<button type="button" class="plyr__control plyr__control--forward" id="plyr-settings-{id}-speed-toggle" aria-haspopup="true" aria-controls="plyr-settings-{id}-speed" aria-expanded="false">', | ||||
|                                                 config.i18n.speed + | ||||
|                                                 '<span class="plyr__menu__value">{speed}</span>', | ||||
|                                                 '<span class="plyr__menu__value" data-menu="speed">{speed}</span>', | ||||
|                                             '</button>', | ||||
|                                         '</li>', | ||||
|                                         '<li role="tab">', | ||||
| @ -996,6 +1006,12 @@ | ||||
|                                                 '<span class="plyr__menu__value">Auto</span>', | ||||
|                                             '</button>', | ||||
|                                         '</li>', | ||||
|                                         '<li role="tab">', | ||||
|                                             '<button type="button" class="plyr__control plyr__control--forward" id="plyr-settings-{id}-loop-toggle" aria-haspopup="true" aria-controls="plyr-settings-{id}-loop" aria-expanded="false">', | ||||
|                                             config.i18n.loop + | ||||
|                                                 '<span class="plyr__menu__value" data-menu="loop"></span>', | ||||
|                                             '</button>', | ||||
|                                         '</li>', | ||||
|                                     '</ul>', | ||||
|                                 '</div>', | ||||
|                                 '<div class="plyr__menu__secondary" id="plyr-settings-{id}-captions" aria-hidden="true" aria-labelled-by="plyr-settings-{id}-captions-toggle" role="tabpanel" tabindex="-1">', | ||||
| @ -1013,7 +1029,7 @@ | ||||
|                                         '</li>', | ||||
|                                     '</ul>', | ||||
|                                 '</div>', | ||||
|                                 '<div class="plyr__menu__secondary" id="plyr-settings-{id}-speed" aria-hidden="true" aria-labelled-by="plyr-settings-{id}-speed-toggle" role="tabpanel" tabindex="-1">', | ||||
|                                 '<form class="plyr__menu__secondary" id="plyr-settings-{id}-speed" aria-hidden="true" aria-labelled-by="plyr-settings-{id}-speed-toggle" role="tabpanel" tabindex="-1">', | ||||
|                                     '<ul>', | ||||
|                                         '<li role="tab">', | ||||
|                                             '<button type="button" class="plyr__control plyr__control--back" aria-haspopup="true" aria-controls="plyr-settings-{id}-primary" aria-expanded="false">', | ||||
| @ -1021,19 +1037,31 @@ | ||||
|                                             '</button>', | ||||
|                                         '</li>', | ||||
|                                         '<li>', | ||||
|                                             '<button type="button" class="plyr__control">2×</button>', | ||||
|                                             '<label class="plyr__control">', | ||||
|                                                 '<input type="radio" name="speed" data-plyr="speed" value="2.0" '+ (config.currentSpeed === 2 ? 'checked' : '') +'>', | ||||
|                                                 '2.0×', | ||||
|                                             '</label>', | ||||
|                                         '</li>', | ||||
|                                         '<li>', | ||||
|                                             '<button type="button" class="plyr__control">1.5×</button>', | ||||
|                                             '<label class="plyr__control">', | ||||
|                                                 '<input type="radio" name="speed" data-plyr="speed"  value="1.5" '+ (config.currentSpeed === 1.5 ? 'checked' : '') +'>', | ||||
|                                                 '1.5×', | ||||
|                                             '</label>', | ||||
|                                         '</li>', | ||||
|                                         '<li>', | ||||
|                                             '<button type="button" class="plyr__control">1×</button>', | ||||
|                                             '<label class="plyr__control">', | ||||
|                                                 '<input type="radio" name="speed" data-plyr="speed"  value="1.0" '+ (config.currentSpeed === 1 ? 'checked' : '') +'>', | ||||
|                                                 '1.0×', | ||||
|                                             '</label>', | ||||
|                                         '</li>', | ||||
|                                         '<li>', | ||||
|                                             '<button type="button" class="plyr__control">0.5×</button>', | ||||
|                                             '<label class="plyr__control">', | ||||
|                                                 '<input type="radio" name="speed" data-plyr="speed"  value="0.5" '+ (config.currentSpeed === 0.5 ? 'checked' : '') +'>', | ||||
|                                                 '0.5×', | ||||
|                                             '</label>', | ||||
|                                         '</li>', | ||||
|                                     '</ul>', | ||||
|                                 '</div>', | ||||
|                                 '</form>', | ||||
|                                 '<div class="plyr__menu__secondary" id="plyr-settings-{id}-quality" aria-hidden="true" aria-labelled-by="plyr-settings-{id}-quality-toggle" role="tabpanel" tabindex="-1">', | ||||
|                                     '<ul>', | ||||
|                                         '<li role="tab">', | ||||
| @ -1091,6 +1119,38 @@ | ||||
|                                         '</li>', | ||||
|                                     '</ul>', | ||||
|                                 '</div>', | ||||
|                                 '<div class="plyr__menu__secondary" id="plyr-settings-{id}-loop" aria-hidden="true" aria-labelled-by="plyr-settings-{id}-loop-toggle" role="tabpanel" tabindex="-1">', | ||||
|                                     '<ul>', | ||||
|                                         '<li role="tab">', | ||||
|                                             '<button type="button" class="plyr__control plyr__control--back" aria-haspopup="true" aria-controls="plyr-settings-{id}-primary" aria-expanded="false">', | ||||
|                                                 config.i18n.loop, | ||||
|                                             '</button>', | ||||
|                                         '</li>', | ||||
|                                         '<li>', | ||||
|                                             '<button type="button" class="plyr__control" data-plyr="loop" data-loop__type="loopall">', | ||||
|                                                 config.i18n.loopall, | ||||
|                                                 '<span data-loop__value="loopall"></span>', | ||||
|                                             '</button>', | ||||
|                                         '</li>', | ||||
|                                         '<li>', | ||||
|                                             '<button type="button" class="plyr__control" data-plyr="loop" data-loop__type="loopin">', | ||||
|                                                 config.i18n.loopin + ': ', | ||||
|                                                 '<span data-loop__value="loopin"></span>', | ||||
|                                             '</button>', | ||||
|                                         '</li>', | ||||
|                                         '<li>', | ||||
|                                             '<button type="button" class="plyr__control" data-plyr="loop" data-loop__type="loopout">', | ||||
|                                                 config.i18n.loopout + ': ', | ||||
|                                                 '<span data-loop__value="loopout"></span>', | ||||
|                                             '</button>', | ||||
|                                         '</li>', | ||||
|                                         '<li>', | ||||
|                                             '<button type="button" class="plyr__control" data-plyr="loop" data-loop__type="loopclear">', | ||||
|                                                 config.i18n.loopclear, | ||||
|                                             '</button>', | ||||
|                                         '</li>', | ||||
|                                     '</ul>', | ||||
|                                 '</div>', | ||||
|                             '</div>', | ||||
|                         '</div>', | ||||
|                     '</div>' | ||||
| @ -1643,8 +1703,8 @@ | ||||
|             // Replace seek time instances | ||||
|             html = replaceAll(html, '{seektime}', config.seekTime); | ||||
|  | ||||
|             // Replace seek time instances | ||||
|             html = replaceAll(html, '{speed}', config.currentSpeed.toFixed(1).toString().replace('.0', '') + '×'); | ||||
|             // Replace speed time instances | ||||
|             html = replaceAll(html, '{speed}', getSpeedDisplayValue()); | ||||
|  | ||||
|             // Replace current captions language | ||||
|             html = replaceAll(html, '{lang}', 'English'); | ||||
| @ -1682,6 +1742,10 @@ | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         function getSpeedDisplayValue() { | ||||
|            return config.currentSpeed.toFixed(1).toString().replace('.0', '') + '×' | ||||
|         } | ||||
|  | ||||
|         // Find the UI controls and store references | ||||
|         function findElements() { | ||||
|             try { | ||||
| @ -1697,7 +1761,9 @@ | ||||
|                     forward: getElement(config.selectors.buttons.forward), | ||||
|                     fullscreen: getElement(config.selectors.buttons.fullscreen), | ||||
|                     settings: getElement(config.selectors.buttons.settings), | ||||
|                     pip: getElement(config.selectors.buttons.pip) | ||||
|                     pip: getElement(config.selectors.buttons.pip), | ||||
|                     speed: document.querySelectorAll(config.selectors.buttons.speed), | ||||
|                     loop: document.querySelectorAll(config.selectors.buttons.loop) | ||||
|                 }; | ||||
|  | ||||
|                 // Inputs | ||||
| @ -2392,6 +2458,49 @@ | ||||
|             return toggle; | ||||
|         } | ||||
|  | ||||
|         // Toggle loop | ||||
|         function toggleLoop(toggle) { | ||||
|             if (['loopin', 'loopout', 'loopall'].indexOf(toggle) === -1) { | ||||
|                 toggle = 'loopclear'; | ||||
|             } | ||||
|  | ||||
|             var currentTime = Number(plyr.media.currentTime); | ||||
|  | ||||
|             switch(toggle) { | ||||
|               case 'loopin': | ||||
|                 if (config.loopout && config.loopout <= currentTime) { | ||||
|                     config.loopout = null; | ||||
|                 } | ||||
|                 config.loopin = currentTime; | ||||
|                 break; | ||||
|               case 'loopout': | ||||
|                 if (config.loopin >= currentTime) { | ||||
|                   return; | ||||
|                 } | ||||
|                 config.loopout = currentTime; | ||||
|                 break; | ||||
|               case 'loopall': | ||||
|                 config.loopin = 0; | ||||
|                 config.loopout = plyr.media.duration - 2; | ||||
|                 break; | ||||
|               default: | ||||
|                 config.loopin = 0; | ||||
|                 config.loopout = null; | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             //check if can loop | ||||
|             config.loop = is.number(config.loopin) && is.number(config.loopout); | ||||
|             var loopin = updateTimeDisplay(config.loopin, document.querySelector('[data-loop__value="loopin"]')); | ||||
|             var loopout = is.number(config.loopout) ? updateTimeDisplay(config.loopout + 2, document.querySelector('[data-loop__value="loopout"]')) : document.querySelector('[data-loop__value="loopout"]').innerHTML = ''; | ||||
|             if (config.loop) { | ||||
|               document.querySelector('[data-menu="loop"]').innerHTML = loopin + ' - ' + loopout; | ||||
|             } else { | ||||
|               document.querySelector('[data-menu="loop"]').innerHTML = config.i18n.loopclear; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         // Speed-up | ||||
|         function setSpeed(speed) { | ||||
|             // Load speed from storage or default value | ||||
| @ -2427,6 +2536,9 @@ | ||||
|             updateStorage({ | ||||
|                 speed: speed | ||||
|             }); | ||||
|  | ||||
|             //Update current value of menu | ||||
|             document.querySelector('[data-menu="speed"]').innerHTML = getSpeedDisplayValue(); | ||||
|         } | ||||
|  | ||||
|         // Rewind | ||||
| @ -2864,7 +2976,10 @@ | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Set values | ||||
|             if (is.number(config.loopin) && is.number(config.loopout) && plyr.media.currentTime >= config.loopout) { | ||||
|                 seek(config.loopin); | ||||
|             } | ||||
|  | ||||
|             setProgress(progress, value); | ||||
|         } | ||||
|  | ||||
| @ -2924,8 +3039,10 @@ | ||||
|             plyr.secs = ('0' + plyr.secs).slice(-2); | ||||
|             plyr.mins = ('0' + plyr.mins).slice(-2); | ||||
|  | ||||
|             var txt = (displayHours ? plyr.hours + ':' : '') + plyr.mins + ':' + plyr.secs; | ||||
|             // Render | ||||
|             element.innerHTML = (displayHours ? plyr.hours + ':' : '') + plyr.mins + ':' + plyr.secs; | ||||
|             element.innerHTML = txt; | ||||
|             return txt; | ||||
|         } | ||||
|  | ||||
|         // Show the duration on metadataloaded | ||||
| @ -3537,7 +3654,10 @@ | ||||
|             proxy(plyr.buttons.forward, 'click', config.listeners.forward, forward); | ||||
|  | ||||
|             // Speed-up | ||||
|             proxy(plyr.buttons.speed, 'click', config.listeners.speed, setSpeed); | ||||
|             proxy(plyr.buttons.speed, 'click', config.listeners.speed, function () { | ||||
|               var speedValue = document.querySelector('[data-plyr="speed"]:checked').value; | ||||
|               setSpeed(Number(speedValue)); | ||||
|             }); | ||||
|  | ||||
|             // Seek | ||||
|             proxy(plyr.buttons.seek, inputEvent, config.listeners.seek, seek); | ||||
| @ -3553,6 +3673,14 @@ | ||||
|             // Fullscreen | ||||
|             proxy(plyr.buttons.fullscreen, 'click', config.listeners.fullscreen, toggleFullscreen); | ||||
|  | ||||
|             // Loop | ||||
|             proxy(plyr.buttons.loop, 'click', config.listeners.loop, function (event) { | ||||
|                 var loopValue = event.target.getAttribute('data-loop__value') || event.target.getAttribute('data-loop__type'); | ||||
|                 if (['loopin', 'loopout', 'loopall', 'loopclear'].indexOf(loopValue) > -1) { | ||||
|                     toggleLoop(loopValue); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             // Handle user exiting fullscreen by escaping etc | ||||
|             if (support.fullscreen) { | ||||
|                 on(document, fullscreen.eventType, toggleFullscreen); | ||||
| @ -3995,6 +4123,10 @@ | ||||
|             // Set playback speed | ||||
|             setSpeed(); | ||||
|  | ||||
|  | ||||
|             // Set loop | ||||
|             toggleLoop(); | ||||
|  | ||||
|             // Reset time display | ||||
|             timeUpdate(); | ||||
|  | ||||
| @ -4037,12 +4169,16 @@ | ||||
|             isPaused: function() { | ||||
|                 return plyr.media.paused; | ||||
|             }, | ||||
|             isLooping: function() { | ||||
|                 return config.loopin && config.loopout; | ||||
|             }, | ||||
|             on: function(event, callback) { | ||||
|                 on(plyr.container, event, callback); | ||||
|                 return this; | ||||
|             }, | ||||
|             play: play, | ||||
|             pause: pause, | ||||
|             loop: toggleLoop, | ||||
|             stop: function() { | ||||
|                 pause(); | ||||
|                 seek(); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user