diff --git a/README.md b/README.md
index 4c720e2e..20b07f9f 100644
--- a/README.md
+++ b/README.md
@@ -316,6 +316,13 @@ Reveal.initialize({
// - false: No media will autoplay, regardless of individual setting
autoPlayMedia: null,
+ // Global override for preloading lazy-loaded iframes
+ // - null: Iframes with data-src AND data-preload will be loaded when within
+ // the viewDistance, iframes with only data-src will be loaded when visible
+ // - true: All iframes with data-src will be loaded when within the viewDistance
+ // - false: All iframes with data-src will be loaded only when visible
+ preloadIframes: null,
+
// Number of milliseconds between automatically proceeding to the
// next slide, disabled when set to 0, this value can be overwritten
// by using a data-autoslide attribute on your slides
@@ -555,10 +562,24 @@ To enable lazy loading all you need to do is change your `src` attributes to `da
```
#### Lazy Loading Iframes
+
Note that lazy loaded iframes ignore the `viewDistance` configuration and will only load when their containing slide becomes visible. Iframes are also unloaded as soon as the slide is hidden.
When we lazy load a video or audio element, reveal.js won't start playing that content until the slide becomes visible. However there is no way to control this for an iframe since that could contain any kind of content. That means if we loaded an iframe before the slide is visible on screen it could begin playing media and sound in the background.
+You can override this behavior with the `data-preload` attribute. The iframe below will be loaded
+according to the `viewDistance`.
+
+```html
+
+
+
+```
+
+You can also change the default globally with the `preloadIframes` configuration option. If set to
+`true` ALL iframes with a `data-src` attribute will be preloaded when within the `viewDistance`
+regardless of individual `data-preload` attributes. If set to `false`, all iframes will only be
+loaded when they become visible.
### API
diff --git a/js/reveal.js b/js/reveal.js
index c3ead436..de12ed7a 100644
--- a/js/reveal.js
+++ b/js/reveal.js
@@ -3671,6 +3671,26 @@
}
+ /**
+ * Should the given element be preloaded?
+ * Decides based on local element attributes and global config.
+ *
+ * @param {HTMLElement} element
+ */
+ function shouldPreload(element) {
+
+ // Prefer an explicit global preload setting
+ var preload = config.preloadIframes;
+
+ // If no global setting is available, fall back on the element's
+ // own preload setting
+ if( typeof preload !== 'boolean' ) {
+ preload = element.hasAttribute( 'data-preload' );
+ }
+
+ return preload;
+ }
+
/**
* Called when the given slide is within the configured view
* distance. Shows the slide element and loads any content
@@ -3686,10 +3706,20 @@
slide.style.display = config.display;
// Media elements with data-src attributes
- toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src]' ) ).forEach( function( element ) {
- element.setAttribute( 'src', element.getAttribute( 'data-src' ) );
- element.setAttribute( 'data-lazy-loaded', '' );
- element.removeAttribute( 'data-src' );
+ toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src], iframe[data-src]' ) ).forEach( function( element ) {
+ var load = function( el ) {
+ el.setAttribute( 'src', el.getAttribute( 'data-src' ) );
+ el.setAttribute( 'data-lazy-loaded', '' );
+ el.removeAttribute( 'data-src' );
+ };
+
+ if( element.tagName === 'IFRAME') {
+ if( shouldPreload(element) ) {
+ load(element);
+ }
+ } else {
+ load(element);
+ }
} );
// Media elements with