Pārlūkot izejas kodu

iframe background preload behavior now matches inline iframes + adheres to the new 'preloadIframes' config option

Hakim El Hattab 5 gadi atpakaļ
vecāks
revīzija
1766e37a63
3 mainītis faili ar 130 papildinājumiem un 11 dzēšanām
  1. 2 0
      README.md
  2. 24 11
      js/reveal.js
  3. 104 0
      test/test-iframe-backgrounds.html

+ 2 - 0
README.md

@@ -778,6 +778,8 @@ Embeds a web page as a slide background that covers 100% of the reveal.js width
 </section>
 ```
 
+Iframes are lazy-loaded when they become visible. If you'd like to preload iframes aehad of time, you can append a `data-preload` attribute to the slide `<section>`. You can also enable preloading globally for all iframes using the `preloadIframes` configuration option.
+
 #### Background Transitions
 
 Backgrounds transition using a fade animation by default. This can be changed to a linear sliding transition by passing `backgroundTransition: 'slide'` to the `Reveal.initialize()` call. Alternatively you can set `data-background-transition` on any section with a background to override that specific transition.

+ 24 - 11
js/reveal.js

@@ -1217,6 +1217,8 @@
 		if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor;
 		if( data.backgroundTransition ) element.setAttribute( 'data-background-transition', data.backgroundTransition );
 
+		if( slide.hasAttribute( 'data-preload' ) ) element.setAttribute( 'data-preload', '' );
+
 		// Background image options are set on the content wrapper
 		if( data.backgroundSize ) contentElement.style.backgroundSize = data.backgroundSize;
 		if( data.backgroundRepeat ) contentElement.style.backgroundRepeat = data.backgroundRepeat;
@@ -3625,7 +3627,7 @@
 		// Stop content inside of previous backgrounds
 		if( previousBackground ) {
 
-			stopEmbeddedContent( previousBackground );
+			stopEmbeddedContent( previousBackground, { unloadIframes: !shouldPreload( previousBackground ) } );
 
 		}
 
@@ -3804,6 +3806,7 @@
 			background.style.display = 'block';
 
 			var backgroundContent = slide.slideBackgroundContentElement;
+			var backgroundIframe = slide.getAttribute( 'data-background-iframe' );
 
 			// If the background contains media, load it
 			if( background.hasAttribute( 'data-loaded' ) === false ) {
@@ -3812,8 +3815,7 @@
 				var backgroundImage = slide.getAttribute( 'data-background-image' ),
 					backgroundVideo = slide.getAttribute( 'data-background-video' ),
 					backgroundVideoLoop = slide.hasAttribute( 'data-background-video-loop' ),
-					backgroundVideoMuted = slide.hasAttribute( 'data-background-video-muted' ),
-					backgroundIframe = slide.getAttribute( 'data-background-iframe' );
+					backgroundVideoMuted = slide.hasAttribute( 'data-background-video-muted' );
 
 				// Images
 				if( backgroundImage ) {
@@ -3854,14 +3856,7 @@
 					iframe.setAttribute( 'mozallowfullscreen', '' );
 					iframe.setAttribute( 'webkitallowfullscreen', '' );
 
-					// Only load autoplaying content when the slide is shown to
-					// avoid having it play in the background
-					if( /autoplay=(1|true|yes)/gi.test( backgroundIframe ) ) {
-						iframe.setAttribute( 'data-src', backgroundIframe );
-					}
-					else {
-						iframe.setAttribute( 'src', backgroundIframe );
-					}
+					iframe.setAttribute( 'data-src', backgroundIframe );
 
 					iframe.style.width  = '100%';
 					iframe.style.height = '100%';
@@ -3872,6 +3867,19 @@
 				}
 			}
 
+			// Start loading preloadable iframes
+			var backgroundIframeElement = backgroundContent.querySelector( 'iframe[data-src]' );
+			if( backgroundIframeElement ) {
+
+				// Check if this iframe is eligible to be preloaded
+				if( shouldPreload( background ) && !/autoplay=(1|true|yes)/gi.test( backgroundIframe ) ) {
+					if( backgroundIframeElement.getAttribute( 'src' ) !== backgroundIframe ) {
+						backgroundIframeElement.setAttribute( 'src', backgroundIframe );
+					}
+				}
+
+			}
+
 		}
 
 	}
@@ -3891,6 +3899,11 @@
 		var background = getSlideBackground( slide );
 		if( background ) {
 			background.style.display = 'none';
+
+			// Unload any background iframes
+			toArray( background.querySelectorAll( 'iframe[src]' ) ).forEach( function( element ) {
+				element.removeAttribute( 'src' );
+			} );
 		}
 
 		// Reset lazy-loaded media elements with src attributes

+ 104 - 0
test/test-iframe-backgrounds.html

@@ -0,0 +1,104 @@
+<!doctype html>
+<html lang="en">
+
+	<head>
+		<meta charset="utf-8">
+
+		<title>reveal.js - Test Iframe Backgrounds</title>
+
+		<link rel="stylesheet" href="../css/reveal.css">
+		<link rel="stylesheet" href="qunit-2.5.0.css">
+	</head>
+
+	<body style="overflow: auto;">
+
+		<div id="qunit"></div>
+		<div id="qunit-fixture"></div>
+
+		<div class="reveal" style="display: none;">
+
+			<div class="slides">
+
+				<section data-background-iframe="#1">1</section>
+				<section data-background-iframe="#2">2</section>
+				<section data-background-iframe="#3" data-preload>3</section>
+				<section data-background-iframe="#4">4</section>
+				<section data-background-iframe="#5">5</section>
+				<section data-background-iframe="#6">6</section>
+
+			</div>
+
+		</div>
+
+		<script src="../js/reveal.js"></script>
+		<script src="qunit-2.5.0.js"></script>
+
+		<script>
+
+
+			Reveal.addEventListener( 'ready', function() {
+
+				function getIframe( index ) {
+					return document.querySelectorAll( '.slide-background' )[index].querySelector( 'iframe' );
+				}
+
+				QUnit.module( 'Iframe' );
+
+				QUnit.test( 'Using default settings', function( assert ) {
+
+					Reveal.slide(0);
+					assert.strictEqual( getIframe(1).hasAttribute( 'src' ), false, 'not preloaded when within viewDistance' );
+
+					Reveal.slide(1);
+					assert.strictEqual( getIframe(1).hasAttribute( 'src' ), true, 'loaded when slide becomes visible' );
+
+					Reveal.slide(0);
+					assert.strictEqual( getIframe(1).hasAttribute( 'src' ), false, 'unloaded when slide becomes invisible' );
+
+				});
+
+				QUnit.test( 'Using data-preload', function( assert ) {
+
+					Reveal.slide(1);
+					assert.strictEqual( getIframe(2).hasAttribute( 'src' ), true, 'preloaded within viewDistance' );
+					assert.strictEqual( getIframe(1).hasAttribute( 'src' ), true, 'loaded when slide becomes visible' );
+
+					Reveal.slide(0);
+					assert.strictEqual( getIframe(3).hasAttribute( 'src' ), false, 'unloads outside of viewDistance' );
+
+				});
+
+				QUnit.test( 'Using preloadIframes: true', function( assert ) {
+
+					Reveal.configure({ preloadIframes: true });
+
+					Reveal.slide(1);
+					assert.strictEqual( getIframe(0).hasAttribute( 'src' ), true, 'preloaded within viewDistance' );
+					assert.strictEqual( getIframe(1).hasAttribute( 'src' ), true, 'preloaded within viewDistance' );
+					assert.strictEqual( getIframe(2).hasAttribute( 'src' ), true, 'preloaded within viewDistance' );
+
+				});
+
+				QUnit.test( 'Using preloadIframes: false', function( assert ) {
+
+					Reveal.configure({ preloadIframes: false });
+
+					Reveal.slide(0);
+					assert.strictEqual( getIframe(1).hasAttribute( 'src' ), false, 'not preloaded within viewDistance' );
+					assert.strictEqual( getIframe(2).hasAttribute( 'src' ), false, 'not preloaded within viewDistance' );
+
+					Reveal.slide(1);
+					assert.strictEqual( getIframe(1).hasAttribute( 'src' ), true, 'loaded when slide becomes visible' );
+
+
+				});
+
+			} );
+
+			Reveal.initialize({
+				viewDistance: 3
+			});
+		</script>
+
+	</body>
+</html>