wait for in-slide video/audio to load before playing, reuse same autoplay logic for slide backgrounds
This commit is contained in:
parent
568c7516f7
commit
a38207f1d7
78
js/reveal.js
78
js/reveal.js
|
@ -2873,34 +2873,17 @@
|
||||||
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// Stop any currently playing video background
|
// Stop content inside of previous backgrounds
|
||||||
if( previousBackground ) {
|
if( previousBackground ) {
|
||||||
|
|
||||||
var previousVideo = previousBackground.querySelector( 'video' );
|
stopEmbeddedContent( previousBackground );
|
||||||
if( previousVideo ) previousVideo.pause();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start content in the current background
|
||||||
if( currentBackground ) {
|
if( currentBackground ) {
|
||||||
|
|
||||||
// Start video playback
|
startEmbeddedContent( currentBackground, true );
|
||||||
var currentVideo = currentBackground.querySelector( 'video' );
|
|
||||||
if( currentVideo ) {
|
|
||||||
|
|
||||||
var startVideo = function() {
|
|
||||||
currentVideo.currentTime = 0;
|
|
||||||
currentVideo.play();
|
|
||||||
currentVideo.removeEventListener( 'loadeddata', startVideo );
|
|
||||||
};
|
|
||||||
|
|
||||||
if( currentVideo.readyState > 1 ) {
|
|
||||||
startVideo();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
currentVideo.addEventListener( 'loadeddata', startVideo );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var backgroundImageURL = currentBackground.style.backgroundImage || '';
|
var backgroundImageURL = currentBackground.style.backgroundImage || '';
|
||||||
|
|
||||||
|
@ -3189,11 +3172,12 @@
|
||||||
* Start playback of any embedded content inside of
|
* Start playback of any embedded content inside of
|
||||||
* the given element.
|
* the given element.
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} slide
|
* @param {HTMLElement} element
|
||||||
*/
|
*/
|
||||||
function startEmbeddedContent( element ) {
|
function startEmbeddedContent( element ) {
|
||||||
|
|
||||||
if( element && !isSpeakerNotes() ) {
|
if( element && !isSpeakerNotes() ) {
|
||||||
|
|
||||||
// Restart GIFs
|
// Restart GIFs
|
||||||
toArray( element.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
|
||||||
|
@ -3207,8 +3191,27 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( el.hasAttribute( 'data-autoplay' ) && typeof el.play === 'function' ) {
|
// Autoplay is always on for slide backgrounds
|
||||||
el.play();
|
var autoplay = el.hasAttribute( 'data-autoplay' ) || !!closestParent( el, '.slide-background' );
|
||||||
|
|
||||||
|
if( autoplay && typeof el.play === 'function' ) {
|
||||||
|
|
||||||
|
var _startVideo = function() {
|
||||||
|
// Only start playback if the containing slide is still visible
|
||||||
|
if( !!closestParent( el, '.present' ) ) {
|
||||||
|
el.currentTime = 0;
|
||||||
|
el.play();
|
||||||
|
}
|
||||||
|
el.removeEventListener( 'loadeddata', _startVideo );
|
||||||
|
};
|
||||||
|
|
||||||
|
if( el.readyState > 1 ) {
|
||||||
|
_startVideo();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
el.addEventListener( 'loadeddata', _startVideo );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -3233,6 +3236,7 @@
|
||||||
el.setAttribute( 'src', el.getAttribute( 'data-src' ) );
|
el.setAttribute( 'src', el.getAttribute( 'data-src' ) );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3249,12 +3253,14 @@
|
||||||
|
|
||||||
if( iframe && iframe.contentWindow ) {
|
if( iframe && iframe.contentWindow ) {
|
||||||
|
|
||||||
|
var autoplay = iframe.hasAttribute( 'data-autoplay' ) || !!closestParent( iframe, '.slide-background' );
|
||||||
|
|
||||||
// YouTube postMessage API
|
// YouTube postMessage API
|
||||||
if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-autoplay' ) ) {
|
if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) {
|
||||||
iframe.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' );
|
iframe.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' );
|
||||||
}
|
}
|
||||||
// Vimeo postMessage API
|
// Vimeo postMessage API
|
||||||
else if( /player\.vimeo\.com\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-autoplay' ) ) {
|
else if( /player\.vimeo\.com\//.test( iframe.getAttribute( 'src' ) ) && autoplay ) {
|
||||||
iframe.contentWindow.postMessage( '{"method":"play"}', '*' );
|
iframe.contentWindow.postMessage( '{"method":"play"}', '*' );
|
||||||
}
|
}
|
||||||
// Generic postMessage API
|
// Generic postMessage API
|
||||||
|
@ -3270,40 +3276,42 @@
|
||||||
* Stop playback of any embedded content inside of
|
* Stop playback of any embedded content inside of
|
||||||
* the targeted slide.
|
* the targeted slide.
|
||||||
*
|
*
|
||||||
* @param {HTMLElement} slide
|
* @param {HTMLElement} element
|
||||||
|
* @param {boolean} autoplay Optionally override the
|
||||||
|
* autoplay setting of media elements
|
||||||
*/
|
*/
|
||||||
function stopEmbeddedContent( slide ) {
|
function stopEmbeddedContent( element, autoplay ) {
|
||||||
|
|
||||||
if( slide && slide.parentNode ) {
|
if( element && element.parentNode ) {
|
||||||
// HTML5 media elements
|
// HTML5 media elements
|
||||||
toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
|
toArray( element.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
|
||||||
if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) {
|
if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) {
|
||||||
el.pause();
|
el.pause();
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// Generic postMessage API for non-lazy loaded iframes
|
// Generic postMessage API for non-lazy loaded iframes
|
||||||
toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) {
|
toArray( element.querySelectorAll( 'iframe' ) ).forEach( function( el ) {
|
||||||
el.contentWindow.postMessage( 'slide:stop', '*' );
|
el.contentWindow.postMessage( 'slide:stop', '*' );
|
||||||
el.removeEventListener( 'load', startEmbeddedIframe );
|
el.removeEventListener( 'load', startEmbeddedIframe );
|
||||||
});
|
});
|
||||||
|
|
||||||
// YouTube postMessage API
|
// YouTube postMessage API
|
||||||
toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) {
|
toArray( element.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) {
|
||||||
if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) {
|
if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) {
|
||||||
el.contentWindow.postMessage( '{"event":"command","func":"pauseVideo","args":""}', '*' );
|
el.contentWindow.postMessage( '{"event":"command","func":"pauseVideo","args":""}', '*' );
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Vimeo postMessage API
|
// Vimeo postMessage API
|
||||||
toArray( slide.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) {
|
toArray( element.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) {
|
||||||
if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) {
|
if( !el.hasAttribute( 'data-ignore' ) && typeof el.contentWindow.postMessage === 'function' ) {
|
||||||
el.contentWindow.postMessage( '{"method":"pause"}', '*' );
|
el.contentWindow.postMessage( '{"method":"pause"}', '*' );
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Lazy loading iframes
|
// Lazy loading iframes
|
||||||
toArray( slide.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) {
|
toArray( element.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) {
|
||||||
// Only removing the src doesn't actually unload the frame
|
// Only removing the src doesn't actually unload the frame
|
||||||
// in all browsers (Firefox) so we set it to blank first
|
// in all browsers (Firefox) so we set it to blank first
|
||||||
el.setAttribute( 'src', 'about:blank' );
|
el.setAttribute( 'src', 'about:blank' );
|
||||||
|
@ -3900,7 +3908,7 @@
|
||||||
// If there are media elements with data-autoplay,
|
// If there are media elements with data-autoplay,
|
||||||
// automatically set the autoSlide duration to the
|
// automatically set the autoSlide duration to the
|
||||||
// length of that media. Not applicable if the slide
|
// length of that media. Not applicable if the slide
|
||||||
// is divided up into fragments.
|
// is divided up into fragments.
|
||||||
// playbackRate is accounted for in the duration.
|
// playbackRate is accounted for in the duration.
|
||||||
if( currentSlide.querySelectorAll( '.fragment' ).length === 0 ) {
|
if( currentSlide.querySelectorAll( '.fragment' ).length === 0 ) {
|
||||||
toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
|
toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
|
||||||
|
|
Loading…
Reference in New Issue