Browse Source

autoplay support for content inside of fragments

Hakim El Hattab 8 years ago
parent
commit
79728e25cd
1 changed files with 56 additions and 8 deletions
  1. 56 8
      js/reveal.js

+ 56 - 8
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.
 	 *
@@ -3046,32 +3082,44 @@
 
 	/**
 	 * 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
-			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
 				// to work in Chrome, FF & Safari
 				el.setAttribute( 'src', el.getAttribute( 'src' ) );
 			} );
 
 			// 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' ) {
 					el.play();
 				}
 			} );
 
 			// 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 } );
 			} );
 
 			// 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' ) ) {
 					el.removeEventListener( 'load', startEmbeddedIframe ); // remove first to avoid dupes
 					el.addEventListener( 'load', startEmbeddedIframe );
@@ -3622,6 +3670,7 @@
 
 						if( i === index ) {
 							element.classList.add( 'current-fragment' );
+							startEmbeddedContent( element );
 						}
 					}
 					// Hidden fragments
@@ -3631,7 +3680,6 @@
 						element.classList.remove( 'current-fragment' );
 					}
 
-
 				} );
 
 				if( fragmentsHidden.length ) {