Seeking (still work in progress)
This commit is contained in:
		
							
								
								
									
										2
									
								
								dist/plyr.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/plyr.css
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/plyr.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/plyr.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										9
									
								
								notes.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								notes.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| Loading | ||||
| -------------- | ||||
| http://stackoverflow.com/questions/8685038/tell-whether-video-is-loaded-or-not-in-javascript | ||||
| http://stackoverflow.com/questions/5181865/checking-if-a-html5-video-is-ready | ||||
|  | ||||
| Events | ||||
| -------------- | ||||
| https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement | ||||
| https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events | ||||
| @ -263,6 +263,11 @@ Here's a list of the methods supported: | ||||
|     <td>Number</td> | ||||
|     <td>Fast forwards by the provided parameter, in seconds. If no parameter is provided, the default seekInterval is used (10 seconds).</td> | ||||
|   </tr> | ||||
|   <tr> | ||||
|     <td><code>seek</code></td> | ||||
|     <td>Number</td> | ||||
|     <td>Seeks the media to the provided parameter, time in seconds.</td> | ||||
|   </tr> | ||||
|   <tr> | ||||
|     <td><code>setVolume</code></td> | ||||
|     <td>Number</td> | ||||
| @ -346,6 +351,9 @@ Plyr is developed by Sam Potts ([@sam_potts](https://twitter.com/sam_potts)) ([s | ||||
| - [The Changelog](http://thechangelog.com/plyr-simple-html5-media-player-custom-controls-webvtt-captions/) | ||||
| - [HTML5 Weekly #177](http://html5weekly.com/issues/177) | ||||
| - [Web Design Weekly #174](https://web-design-weekly.com/2015/02/24/web-design-weekly-174/) | ||||
| - [Hacker News](https://news.ycombinator.com/item?id=9136774) | ||||
| - [Web Platform Daily](http://webplatformdaily.org/releases/2015-03-04) | ||||
| - [LayerVault Designer News](https://news.layervault.com/stories/45394-plyr--a-simple-html5-media-player) | ||||
|  | ||||
| ## Used by | ||||
| - [Selz.com](https://selz.com) | ||||
| @ -356,6 +364,7 @@ Let me know on [Twitter](https://twitter.com/sam_potts) I can add you to the abo | ||||
| Credit to the PayPal HTML5 Video player from which Plyr's caption functionality is ported from: | ||||
| - [PayPal's Accessible HTML5 Video Player](https://github.com/paypal/accessible-html5-video-player) | ||||
| - The icons used in Plyr are [Vicons](https://dribbble.com/shots/1663443-60-Vicons-Free-Icon-Set) plus some ones I made | ||||
| - [An awesome guide for Plyr in Japanese!](http://syncer.jp/how-to-use-plyr-io) by [@arayutw](https://twitter.com/arayutw) | ||||
|  | ||||
| Also these links helped created Plyr: | ||||
| - [Media Events - W3.org](http://www.w3.org/2010/05/video/mediaevents.html) | ||||
|  | ||||
							
								
								
									
										100
									
								
								src/js/plyr.js
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								src/js/plyr.js
									
									
									
									
									
								
							| @ -274,7 +274,7 @@ | ||||
|  | ||||
|     // Get percentage | ||||
|     function _getPercentage(current, max) { | ||||
|         return Math.floor((current / max) * 100); | ||||
|         return ((current / max) * 100).toFixed(2); | ||||
|     } | ||||
|  | ||||
|     // Deep extend/merge two Objects | ||||
| @ -781,19 +781,7 @@ | ||||
|             if(typeof seekTime !== "number") { | ||||
|                 seekTime = config.seekTime; | ||||
|             } | ||||
|  | ||||
|             var targetTime = player.media.currentTime - seekTime; | ||||
|  | ||||
|             if (targetTime < 0) { | ||||
|                 player.media.currentTime = 0; | ||||
|             } | ||||
|             else { | ||||
|                 player.media.currentTime = targetTime; | ||||
|             } | ||||
|             // Special handling for "manual" captions | ||||
|             if (!player.isTextTracks && player.type === "video") { | ||||
|                 _adjustManualCaptions(player); | ||||
|             } | ||||
|             _seek(player.media.currentTime - seekTime); | ||||
|         } | ||||
|  | ||||
|         // Fast forward | ||||
| @ -802,15 +790,43 @@ | ||||
|             if(typeof seekTime !== "number") { | ||||
|                 seekTime = config.seekTime; | ||||
|             } | ||||
|             _seek(player.media.currentTime + seekTime); | ||||
|         } | ||||
|  | ||||
|             var targetTime = player.media.currentTime + seekTime; | ||||
|         // Seek to time | ||||
|         var _seek = function(input) { | ||||
|             //var value = config.seekTime; | ||||
|             var targetTime = 0; | ||||
|  | ||||
|             // If no event or time is passed, bail | ||||
|             if (typeof input === "undefined") { | ||||
|                 return; | ||||
|             } | ||||
|             // Explicit position | ||||
|             else if (typeof input === "number") { | ||||
|                 targetTime = input; | ||||
|             } | ||||
|             // Event | ||||
|             else if (input.type === "change" || input.type === "input") { | ||||
|                 // It's the seek slider | ||||
|                 // Seek to the selected time | ||||
|                 targetTime = ((this.value / this.max) * player.media.duration).toFixed(1); | ||||
|             } | ||||
|  | ||||
|             // Handle min and max values | ||||
|             if (targetTime > player.media.duration) { | ||||
|                 player.media.currentTime = player.media.duration; | ||||
|             } | ||||
|             else if (targetTime < 0) { | ||||
|                 player.media.currentTime = 0; | ||||
|             } | ||||
|             else { | ||||
|                 player.media.currentTime = targetTime; | ||||
|             } | ||||
|  | ||||
|             // Logging | ||||
|             _log("Seeking to " + player.media.currentTime + " seconds"); | ||||
|  | ||||
|             // Special handling for "manual" captions | ||||
|             if (!player.isTextTracks && player.type === "video") { | ||||
|                 _adjustManualCaptions(player); | ||||
| @ -939,16 +955,19 @@ | ||||
|             switch(event.type) { | ||||
|                 // Video playing | ||||
|                 case "timeupdate": | ||||
|                 case "seeking": | ||||
|                     progress    = player.progress.played.bar; | ||||
|                     text        = player.progress.played.text; | ||||
|                     value       = _getPercentage(player.media.currentTime, player.media.duration); | ||||
|  | ||||
|                     // Set seeking value | ||||
|                     player.buttons.seek.value = value; | ||||
|                     // Set seek range value only if it's a "natural" time event | ||||
|                     if(event.type == "timeupdate") { | ||||
|                         player.buttons.seek.value = value; | ||||
|                     } | ||||
|                      | ||||
|                     break; | ||||
|  | ||||
|                 // Seeking | ||||
|                 // Events from seek range | ||||
|                 case "change": | ||||
|                 case "input": | ||||
|                     progress    = player.progress.played.bar; | ||||
| @ -995,6 +1014,13 @@ | ||||
|             player.duration.innerHTML = player.mins + ":" + player.secs; | ||||
|         } | ||||
|  | ||||
|         function _timeUpdate(event) { | ||||
|             // Duration | ||||
|             _updateTimeDisplay(); | ||||
|             // Playing progress | ||||
|             _updateProgress(event); | ||||
|         } | ||||
|  | ||||
|         // Listen for events | ||||
|         function _listeners() { | ||||
|             // Play | ||||
| @ -1051,29 +1077,26 @@ | ||||
|             } | ||||
|              | ||||
|             // Time change on media | ||||
|             _on(player.media, "timeupdate", function(event) { | ||||
|                 // Duration | ||||
|                 _updateTimeDisplay(); | ||||
|                 // Playing progress | ||||
|                 _updateProgress(event); | ||||
|             _on(player.media, "timeupdate seeking", _timeUpdate); | ||||
|  | ||||
|             // Pause and resume while seeking | ||||
|             /*_on(player.media, "seeking", function() { | ||||
|                 if(!player.media.paused && !player.seekPaused) { | ||||
|                     player.seekPaused = true; | ||||
|                     _pause(); | ||||
|                 } | ||||
|                 _log("Seeking") | ||||
|             }); | ||||
|             _on(player.media, "seeked", function() { | ||||
|                 if(player.seekPaused) { | ||||
|                     player.seekPaused = false; | ||||
|                     _play(); | ||||
|                 } | ||||
|                 _log("Seeked") | ||||
|             });*/ | ||||
|  | ||||
|             // Seek  | ||||
|             _on(player.buttons.seek, "change input", function(event) { | ||||
|                 // Update progress elements | ||||
|                 _updateProgress(event); | ||||
|  | ||||
|                 // Update the text label | ||||
|                 _updateTimeDisplay(); | ||||
|  | ||||
|                 // Seek to the selected time | ||||
|                 player.media.currentTime = ((this.value / this.max) * player.media.duration); | ||||
|  | ||||
|                 // Special handling for "manual" captions | ||||
|                 if (!player.isTextTracks && player.type === "video") { | ||||
|                     _adjustManualCaptions(player); | ||||
|                 } | ||||
|             }); | ||||
|             _on(player.buttons.seek, "change input", _seek); | ||||
|  | ||||
|             // Captions | ||||
|             _on(player.buttons.captions, "click", function() {  | ||||
| @ -1159,6 +1182,7 @@ | ||||
|             restart:            _restart, | ||||
|             rewind:             _rewind, | ||||
|             forward:            _forward, | ||||
|             seek:               _seek, | ||||
|             setVolume:          _setVolume, | ||||
|             toggleMute:         _toggleMute, | ||||
|             toggleCaptions:     _toggleCaptions | ||||
|  | ||||
| @ -66,7 +66,7 @@ | ||||
| 	outline-offset: 0; | ||||
| } | ||||
|  | ||||
| // Range styling | ||||
| // <input type="range"> styling | ||||
| // --------------------------------------- | ||||
| .volume-thumb() { | ||||
| 	height: @volume-thumb-height; | ||||
| @ -205,13 +205,13 @@ | ||||
| 				transition: fill .3s ease; | ||||
| 			} | ||||
| 		} | ||||
| 		[type="checkbox"] + label, | ||||
| 		input + label, | ||||
| 		.inverted:checked + label { | ||||
| 			color: @control-color-inactive; | ||||
| 		} | ||||
| 		button,  | ||||
| 		.inverted + label, | ||||
| 		[type="checkbox"]:checked + label { | ||||
| 		input:checked + label { | ||||
| 			color: @control-color; | ||||
| 		} | ||||
| 		button { | ||||
| @ -222,13 +222,13 @@ | ||||
| 		 | ||||
| 		button:focus, | ||||
| 		button:hover, | ||||
| 		[type="checkbox"]:focus + label, | ||||
| 		[type="checkbox"] + label:hover { | ||||
| 		input:focus + label, | ||||
| 		input + label:hover { | ||||
| 			background: @control-bg-hover; | ||||
| 			color: @control-color-hover; | ||||
| 		} | ||||
| 		button:focus, | ||||
| 		[type="checkbox"]:focus + label { | ||||
| 		input:focus + label { | ||||
| 			outline: 0; | ||||
| 		} | ||||
| 		.icon-exit-fullscreen, | ||||
| @ -258,8 +258,8 @@ | ||||
| 		height: @control-spacing; | ||||
| 		background: @progress-bg; | ||||
|  | ||||
| 		&-buffer, | ||||
| 		&-played, | ||||
| 		&-buffer[value], | ||||
| 		&-played[value], | ||||
| 		&-seek[type=range] { | ||||
| 			position: absolute; | ||||
| 			left: 0; | ||||
| @ -275,8 +275,8 @@ | ||||
| 			border: none; | ||||
| 			background: transparent; | ||||
| 		} | ||||
| 		&-buffer, | ||||
| 		&-played {	 | ||||
| 		&-buffer[value], | ||||
| 		&-played[value] {	 | ||||
| 			&::-webkit-progress-bar { | ||||
| 				background: transparent; | ||||
| 			} | ||||
| @ -284,18 +284,18 @@ | ||||
| 			// Inherit from currentColor; | ||||
| 			&::-webkit-progress-value { | ||||
| 				background: currentColor; | ||||
| 				transition: width .1s ease; | ||||
| 			} | ||||
| 			&::-moz-progress-bar { | ||||
| 				background: currentColor; | ||||
| 				transition: width .1s ease; | ||||
| 			} | ||||
| 		} | ||||
| 		&-played { | ||||
| 		&-played[value] { | ||||
| 			z-index: 2; | ||||
| 		} | ||||
| 		&-played{ | ||||
| 			color: @progress-playing-bg; | ||||
| 		} | ||||
| 		&-buffer { | ||||
| 		&-buffer[value] { | ||||
| 			color: @progress-buffered-bg; | ||||
| 		} | ||||
|  | ||||
| @ -339,7 +339,6 @@ | ||||
| 			} | ||||
|  | ||||
| 			&:focus { | ||||
| 				//.tab-focus(); | ||||
| 				outline: 0; | ||||
| 			} | ||||
| 			&::-moz-focus-outer { | ||||
|  | ||||
| @ -30,12 +30,12 @@ $progress-playing-bg: 		$blue; | ||||
| $progress-buffered-bg: 		$gray; | ||||
|  | ||||
| // Range | ||||
| $range-track-height: 		6px; | ||||
| $range-track-bg: 			$gray; | ||||
| $range-thumb-height: 		($range-track-height * 2); | ||||
| $range-thumb-width: 		($range-track-height * 2); | ||||
| $range-thumb-bg: 			$control-color; | ||||
| $range-thumb-bg-focus: 		$control-bg-hover; | ||||
| $volume-track-height: 		6px; | ||||
| $volume-track-bg: 			$gray; | ||||
| $volume-thumb-height: 		($volume-track-height * 2); | ||||
| $volume-thumb-width: 		($volume-track-height * 2); | ||||
| $volume-thumb-bg: 			$control-color; | ||||
| $volume-thumb-bg-focus: 	$control-bg-hover; | ||||
|  | ||||
| // Breakpoints | ||||
| $bp-control-split: 			560px; // When controls split into left/right | ||||
| @ -66,27 +66,37 @@ $bp-captions-large: 		768px; // When captions jump to the larger font size | ||||
| @mixin tab-focus() | ||||
| { | ||||
| 	outline: thin dotted #000; | ||||
| 	outline-offset: 1px; | ||||
| 	outline-offset: 0; | ||||
| } | ||||
|  | ||||
| // Range styling | ||||
| // <input type="range"> styling | ||||
| // --------------------------------------- | ||||
| @mixin range-thumb() | ||||
| @mixin volume-thumb() | ||||
| { | ||||
| 	height: $range-thumb-height; | ||||
| 	width: $range-thumb-width; | ||||
| 	background: $range-thumb-bg; | ||||
| 	height: $volume-thumb-height; | ||||
| 	width: $volume-thumb-width; | ||||
| 	background: $volume-thumb-bg; | ||||
| 	border: 0; | ||||
| 	border-radius: ($range-thumb-height / 2); | ||||
| 	border-radius: ($volume-thumb-height / 2); | ||||
| 	transition: background .3s ease; | ||||
| 	cursor: ew-resize; | ||||
| } | ||||
| @mixin range-track() | ||||
| @mixin volume-track() | ||||
| { | ||||
| 	height: $range-track-height; | ||||
| 	background: $range-track-bg; | ||||
| 	height: $volume-track-height; | ||||
| 	background: $volume-track-bg; | ||||
| 	border: 0; | ||||
| 	border-radius: ($volume-track-height / 2); | ||||
| } | ||||
| @mixin seek-thumb() { | ||||
| 	background: transparent; | ||||
| 	border: 0; | ||||
| 	width: 2px; | ||||
| 	height: $control-spacing; | ||||
| } | ||||
| @mixin seek-track() { | ||||
| 	background: none; | ||||
| 	border: 0; | ||||
| 	border-radius: ($range-track-height / 2); | ||||
| } | ||||
|  | ||||
| // Font smoothing | ||||
| @ -202,13 +212,13 @@ $bp-captions-large: 		768px; // When captions jump to the larger font size | ||||
| 				transition: fill .3s ease; | ||||
| 			} | ||||
| 		} | ||||
| 		[type="checkbox"] + label, | ||||
| 		input + label, | ||||
| 		.inverted:checked + label { | ||||
| 			color: $control-color-inactive; | ||||
| 		} | ||||
| 		button, | ||||
| 		.inverted + label, | ||||
| 		[type="checkbox"]:checked + label { | ||||
| 		input:checked + label { | ||||
| 			color: $control-color; | ||||
| 		} | ||||
| 		button { | ||||
| @ -216,13 +226,13 @@ $bp-captions-large: 		768px; // When captions jump to the larger font size | ||||
| 			background: transparent; | ||||
| 			overflow: hidden; | ||||
| 		} | ||||
| 		[type="checkbox"]:focus + label, | ||||
| 		input:focus + label, | ||||
| 		button:focus { | ||||
| 			@include tab-focus(); | ||||
| 			color: $control-color-focus; | ||||
| 		} | ||||
| 		button:hover, | ||||
| 		[type="checkbox"] + label:hover { | ||||
| 		input + label:hover { | ||||
| 			background: $control-bg-hover; | ||||
| 			color: $control-color-hover; | ||||
| 		} | ||||
| @ -253,8 +263,9 @@ $bp-captions-large: 		768px; // When captions jump to the larger font size | ||||
| 		height: $control-spacing; | ||||
| 		background: $progress-bg; | ||||
|  | ||||
| 		&-buffer, | ||||
| 		&-played { | ||||
| 		&-buffer[value], | ||||
| 		&-played[value], | ||||
| 		&-seek[type=range] { | ||||
| 			position: absolute; | ||||
| 			left: 0; | ||||
| 			top: 0; | ||||
| @ -263,34 +274,82 @@ $bp-captions-large: 		768px; // When captions jump to the larger font size | ||||
| 			margin: 0; | ||||
| 			vertical-align: top; | ||||
|  | ||||
| 			&[value] { | ||||
| 				-webkit-appearance: none; | ||||
| 				border: none; | ||||
| 			-webkit-appearance: none; | ||||
| 			-moz-appearance: none; | ||||
| 			border: none; | ||||
| 			background: transparent; | ||||
| 		} | ||||
|  | ||||
| 		&-buffer[value], | ||||
| 		&-played[value] {	 | ||||
| 			&::-webkit-progress-bar { | ||||
| 				background: transparent; | ||||
| 			} | ||||
|  | ||||
| 				&::-webkit-progress-bar { | ||||
| 					background: transparent; | ||||
| 				} | ||||
|  | ||||
| 				// Inherit from currentColor; | ||||
| 				&::-webkit-progress-value { | ||||
| 					background: currentColor; | ||||
| 				} | ||||
| 				&::-moz-progress-bar { | ||||
| 					background: currentColor; | ||||
| 				} | ||||
| 			// Inherit from currentColor; | ||||
| 			&::-webkit-progress-value { | ||||
| 				background: currentColor; | ||||
| 				transition: width .1s ease; | ||||
| 			} | ||||
| 			&::-moz-progress-bar { | ||||
| 				background: currentColor; | ||||
| 				transition: width .1s ease; | ||||
| 			} | ||||
| 		} | ||||
| 		&-played { | ||||
| 			z-index: 2; | ||||
| 		} | ||||
| 		&-played[value] { | ||||
| 			cursor: pointer; | ||||
| 			z-index: 2; | ||||
| 			color: $progress-playing-bg; | ||||
| 		} | ||||
| 		&-buffer[value] { | ||||
| 			color: $progress-buffered-bg; | ||||
| 		} | ||||
|  | ||||
| 		// Seek control | ||||
| 		// <input[type='range']> element | ||||
| 		// Specificity is for bootstrap compatibility | ||||
| 		&-seek[type=range] { | ||||
| 			z-index: 3; | ||||
| 			cursor: pointer; | ||||
| 			outline: 0; | ||||
|  | ||||
| 			// Webkit | ||||
| 			&::-webkit-slider-runnable-track { | ||||
| 				@include seek-track(); | ||||
| 			} | ||||
| 			&::-webkit-slider-thumb { | ||||
| 				-webkit-appearance: none; | ||||
| 				@include seek-thumb(); | ||||
| 			} | ||||
|  | ||||
| 			// Mozilla | ||||
| 			&::-moz-range-track { | ||||
| 				@include seek-track(); | ||||
| 			} | ||||
| 			&::-moz-range-thumb { | ||||
| 				-moz-appearance: none; | ||||
| 				@include seek-thumb(); | ||||
| 			} | ||||
| 			 | ||||
| 			// Microsoft | ||||
| 			&::-ms-track { | ||||
| 				color: transparent; | ||||
| 				@include seek-track(); | ||||
| 			} | ||||
| 			&::-ms-fill-lower, | ||||
| 			&::-ms-fill-upper { | ||||
| 				@include seek-track(); | ||||
| 			} | ||||
| 			&::-ms-thumb { | ||||
| 				@include seek-thumb(); | ||||
| 			} | ||||
|  | ||||
| 			&:focus { | ||||
| 				outline: 0; | ||||
| 			} | ||||
| 			&::-moz-focus-outer { | ||||
| 				border: 0; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// States | ||||
| @ -321,7 +380,7 @@ $bp-captions-large: 		768px; // When captions jump to the larger font size | ||||
| 		} | ||||
| 		&::-webkit-slider-thumb { | ||||
| 			-webkit-appearance: none; | ||||
| 			margin-top: -(($range-thumb-height - $range-track-height) / 2); | ||||
| 			margin-top: -(($volume-thumb-height - $volume-track-height) / 2); | ||||
| 			@include range-thumb(); | ||||
| 		} | ||||
|  | ||||
| @ -335,10 +394,10 @@ $bp-captions-large: 		768px; // When captions jump to the larger font size | ||||
|  | ||||
| 		// Microsoft | ||||
| 		&::-ms-track { | ||||
| 			height: $range-track-height; | ||||
| 			height: $volume-track-height; | ||||
| 			background: transparent; | ||||
| 			border-color: transparent; | ||||
| 			border-width: (($range-thumb-height - $range-track-height) / 2) 0; | ||||
| 			border-width: (($volume-thumb-height - $volume-track-height) / 2) 0; | ||||
| 			color: transparent; | ||||
| 		} | ||||
| 		&::-ms-fill-lower, | ||||
| @ -353,13 +412,13 @@ $bp-captions-large: 		768px; // When captions jump to the larger font size | ||||
| 			outline: 0; | ||||
|  | ||||
| 			&::-webkit-slider-thumb { | ||||
| 				background: $range-thumb-bg-focus; | ||||
| 				background: $volume-thumb-bg-focus; | ||||
| 			} | ||||
| 			&::-moz-range-thumb { | ||||
| 				background: $range-thumb-bg-focus; | ||||
| 				background: $volume-thumb-bg-focus; | ||||
| 			} | ||||
| 			&::-ms-thumb { | ||||
| 				background: $range-thumb-bg-focus; | ||||
| 				background: $volume-thumb-bg-focus; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
		Reference in New Issue
	
	Block a user