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
1 changed files with 43 additions and 35 deletions
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 ) {
|
||||
|
||||
var previousVideo = previousBackground.querySelector( 'video' );
|
||||
if( previousVideo ) previousVideo.pause();
|
||||
stopEmbeddedContent( previousBackground );
|
||||
|
||||
}
|
||||
|
||||
// Start content in the current background
|
||||
if( currentBackground ) {
|
||||
|
||||
// Start video playback
|
||||
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 );
|
||||
}
|
||||
|
||||
}
|
||||
startEmbeddedContent( currentBackground, true );
|
||||
|
||||
var backgroundImageURL = currentBackground.style.backgroundImage || '';
|
||||
|
||||
|
@ -3189,11 +3172,12 @@
|
|||
* Start playback of any embedded content inside of
|
||||
* the given element.
|
||||
*
|
||||
* @param {HTMLElement} slide
|
||||
* @param {HTMLElement} element
|
||||
*/
|
||||
function startEmbeddedContent( element ) {
|
||||
|
||||
if( element && !isSpeakerNotes() ) {
|
||||
|
||||
// Restart GIFs
|
||||
toArray( element.querySelectorAll( 'img[src$=".gif"]' ) ).forEach( function( el ) {
|
||||
// Setting the same unchanged source like this was confirmed
|
||||
|
@ -3207,8 +3191,27 @@
|
|||
return;
|
||||
}
|
||||
|
||||
if( el.hasAttribute( 'data-autoplay' ) && typeof el.play === 'function' ) {
|
||||
el.play();
|
||||
// Autoplay is always on for slide backgrounds
|
||||
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' ) );
|
||||
}
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3249,12 +3253,14 @@
|
|||
|
||||
if( iframe && iframe.contentWindow ) {
|
||||
|
||||
var autoplay = iframe.hasAttribute( 'data-autoplay' ) || !!closestParent( iframe, '.slide-background' );
|
||||
|
||||
// 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":""}', '*' );
|
||||
}
|
||||
// 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"}', '*' );
|
||||
}
|
||||
// Generic postMessage API
|
||||
|
@ -3270,40 +3276,42 @@
|
|||
* Stop playback of any embedded content inside of
|
||||
* 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
|
||||
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' ) {
|
||||
el.pause();
|
||||
}
|
||||
} );
|
||||
|
||||
// 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.removeEventListener( 'load', startEmbeddedIframe );
|
||||
});
|
||||
|
||||
// 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' ) {
|
||||
el.contentWindow.postMessage( '{"event":"command","func":"pauseVideo","args":""}', '*' );
|
||||
}
|
||||
});
|
||||
|
||||
// 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' ) {
|
||||
el.contentWindow.postMessage( '{"method":"pause"}', '*' );
|
||||
}
|
||||
});
|
||||
|
||||
// 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
|
||||
// in all browsers (Firefox) so we set it to blank first
|
||||
el.setAttribute( 'src', 'about:blank' );
|
||||
|
@ -3900,7 +3908,7 @@
|
|||
// If there are media elements with data-autoplay,
|
||||
// automatically set the autoSlide duration to the
|
||||
// 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.
|
||||
if( currentSlide.querySelectorAll( '.fragment' ).length === 0 ) {
|
||||
toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
|
||||
|
|
Loading…
Reference in a new issue