autoplay support for content inside of fragments
This commit is contained in:
		
							
								
								
									
										64
									
								
								js/reveal.js
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								js/reveal.js
									
									
									
									
									
								
							| @@ -1242,6 +1242,42 @@ | |||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Find the closest parent that matches the given | ||||||
|  | 	 * selector. | ||||||
|  | 	 * | ||||||
|  | 	 * @param {HTMLElement} target The child element | ||||||
|  | 	 * @param {String} selector The CSS selector to match | ||||||
|  | 	 * the parents against | ||||||
|  | 	 * | ||||||
|  | 	 * @return {HTMLElement} The matched parent or null | ||||||
|  | 	 * if no matching parent was found | ||||||
|  | 	 */ | ||||||
|  | 	function closestParent( target, selector ) { | ||||||
|  |  | ||||||
|  | 		var parent = target.parentNode; | ||||||
|  |  | ||||||
|  | 		while( parent ) { | ||||||
|  |  | ||||||
|  | 			// There's some overhead doing this each time, we don't | ||||||
|  | 			// want to rewrite the element prototype but should still | ||||||
|  | 			// be enough to feature detect once at startup... | ||||||
|  | 			var matchesMethod = parent.matches || parent.matchesSelector || parent.msMatchesSelector; | ||||||
|  |  | ||||||
|  | 			// If we find a match, we're all set | ||||||
|  | 			if( matchesMethod && matchesMethod.call( parent, selector ) ) { | ||||||
|  | 				return parent; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Keep searching | ||||||
|  | 			parent = parent.parentNode; | ||||||
|  |  | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		return null; | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Converts various color input formats to an {r:0,g:0,b:0} object. | 	 * Converts various color input formats to an {r:0,g:0,b:0} object. | ||||||
| 	 * | 	 * | ||||||
| @@ -3046,32 +3082,44 @@ | |||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Start playback of any embedded content inside of | 	 * Start playback of any embedded content inside of | ||||||
| 	 * the targeted slide. | 	 * the given element. | ||||||
| 	 */ | 	 */ | ||||||
| 	function startEmbeddedContent( slide ) { | 	function startEmbeddedContent( element ) { | ||||||
|  |  | ||||||
| 		if( slide && !isSpeakerNotes() ) { | 		if( element && !isSpeakerNotes() ) { | ||||||
| 			// Restart GIFs | 			// Restart GIFs | ||||||
| 			toArray( slide.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( function( el ) { | 			toArray( element.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( function( el ) { | ||||||
| 				// Setting the same unchanged source like this was confirmed | 				// Setting the same unchanged source like this was confirmed | ||||||
| 				// to work in Chrome, FF & Safari | 				// to work in Chrome, FF & Safari | ||||||
| 				el.setAttribute( 'src', el.getAttribute( 'src' ) ); | 				el.setAttribute( 'src', el.getAttribute( 'src' ) ); | ||||||
| 			} ); | 			} ); | ||||||
|  |  | ||||||
| 			// HTML5 media elements | 			// HTML5 media elements | ||||||
| 			toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { | 			toArray( element.querySelectorAll( 'video, audio' ) ).forEach( function( el ) { | ||||||
|  | 				if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  |  | ||||||
| 				if( el.hasAttribute( 'data-autoplay' ) && typeof el.play === 'function' ) { | 				if( el.hasAttribute( 'data-autoplay' ) && typeof el.play === 'function' ) { | ||||||
| 					el.play(); | 					el.play(); | ||||||
| 				} | 				} | ||||||
| 			} ); | 			} ); | ||||||
|  |  | ||||||
| 			// Normal iframes | 			// Normal iframes | ||||||
| 			toArray( slide.querySelectorAll( 'iframe[src]' ) ).forEach( function( el ) { | 			toArray( element.querySelectorAll( 'iframe[src]' ) ).forEach( function( el ) { | ||||||
|  | 				if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  |  | ||||||
| 				startEmbeddedIframe( { target: el } ); | 				startEmbeddedIframe( { target: el } ); | ||||||
| 			} ); | 			} ); | ||||||
|  |  | ||||||
| 			// Lazy loading iframes | 			// Lazy loading iframes | ||||||
| 			toArray( slide.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) { | 			toArray( element.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) { | ||||||
|  | 				if( closestParent( el, '.fragment' ) && !closestParent( el, '.fragment.visible' ) ) { | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  |  | ||||||
| 				if( el.getAttribute( 'src' ) !== el.getAttribute( 'data-src' ) ) { | 				if( el.getAttribute( 'src' ) !== el.getAttribute( 'data-src' ) ) { | ||||||
| 					el.removeEventListener( 'load', startEmbeddedIframe ); // remove first to avoid dupes | 					el.removeEventListener( 'load', startEmbeddedIframe ); // remove first to avoid dupes | ||||||
| 					el.addEventListener( 'load', startEmbeddedIframe ); | 					el.addEventListener( 'load', startEmbeddedIframe ); | ||||||
| @@ -3622,6 +3670,7 @@ | |||||||
|  |  | ||||||
| 						if( i === index ) { | 						if( i === index ) { | ||||||
| 							element.classList.add( 'current-fragment' ); | 							element.classList.add( 'current-fragment' ); | ||||||
|  | 							startEmbeddedContent( element ); | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 					// Hidden fragments | 					// Hidden fragments | ||||||
| @@ -3631,7 +3680,6 @@ | |||||||
| 						element.classList.remove( 'current-fragment' ); | 						element.classList.remove( 'current-fragment' ); | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
|  |  | ||||||
| 				} ); | 				} ); | ||||||
|  |  | ||||||
| 				if( fragmentsHidden.length ) { | 				if( fragmentsHidden.length ) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user