aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHakim El Hattab <hakim.elhattab@gmail.com>2016-09-20 13:41:38 +0200
committerHakim El Hattab <hakim.elhattab@gmail.com>2016-09-20 13:41:38 +0200
commit79728e25cd6c98193d8e6247e73a2a65a62ce04e (patch)
tree8bc3712fb08a3f20e6d4e447ec22e460950b5b7d
parentbc4fc65da475b1234b32c9eb5070138218abff76 (diff)
downloadfreenode-live-2017-presentation-79728e25cd6c98193d8e6247e73a2a65a62ce04e.tar
freenode-live-2017-presentation-79728e25cd6c98193d8e6247e73a2a65a62ce04e.tar.gz
autoplay support for content inside of fragments
-rw-r--r--js/reveal.js64
1 files changed, 56 insertions, 8 deletions
diff --git a/js/reveal.js b/js/reveal.js
index b975ff4..2fc2f78 100644
--- a/js/reveal.js
+++ b/js/reveal.js
@@ -1243,6 +1243,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.
*
* @param {String} color The string representation of a color,
@@ -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 ) {