lib/resources/assets/revealjs-redhat/lib/js/debug/reveal.js in hyla-1.0.7 vs lib/resources/assets/revealjs-redhat/lib/js/debug/reveal.js in hyla-1.0.8
- old
+ new
@@ -1,9 +1,10 @@
/*!
* reveal.js
* http://lab.hakim.se/reveal-js
* MIT licensed
+ * Version 3.1.0
*
* Copyright (C) 2015 Hakim El Hattab, http://hakim.se
*/
(function( root, factory ) {
if( typeof define === 'function' && define.amd ) {
@@ -28,25 +29,21 @@
var SLIDES_SELECTOR = '.slides section',
HORIZONTAL_SLIDES_SELECTOR = '.slides>section',
VERTICAL_SLIDES_SELECTOR = '.slides>section.present>section',
HOME_SLIDE_SELECTOR = '.slides>section:first-of-type',
- // Configurations defaults, can be overridden at initialization time
+ // Configuration defaults, can be overridden at initialization time
config = {
// The "normal" size of the presentation, aspect ratio will be preserved
// when the presentation is scaled to fit different resolutions
width: 960,
height: 700,
// Factor of the display size that should remain empty around the content
margin: 0.1,
- // Top and Left margins to reposition the slides
- marginTop: '',
- marginLeft: '',
-
// Bounds for smallest/largest possible scale to apply to content
minScale: 0.2,
maxScale: 1.5,
// Display controls in the bottom right corner
@@ -240,18 +237,22 @@
checkCapabilities();
if( !features.transforms2d && !features.transforms3d ) {
document.body.setAttribute( 'class', 'no-transforms' );
- // Since JS won't be running any further, we need to load all
- // images that were intended to lazy load now
- var images = document.getElementsByTagName( 'img' );
- for( var i = 0, len = images.length; i < len; i++ ) {
- var image = images[i];
- if( image.getAttribute( 'data-src' ) ) {
- image.setAttribute( 'src', image.getAttribute( 'data-src' ) );
- image.removeAttribute( 'data-src' );
+ // Since JS won't be running any further, we load all lazy
+ // loading elements upfront
+ var images = toArray( document.getElementsByTagName( 'img' ) ),
+ iframes = toArray( document.getElementsByTagName( 'iframe' ) );
+
+ var lazyLoadable = images.concat( iframes );
+
+ for( var i = 0, len = lazyLoadable.length; i < len; i++ ) {
+ var element = lazyLoadable[i];
+ if( element.getAttribute( 'data-src' ) ) {
+ element.setAttribute( 'src', element.getAttribute( 'data-src' ) );
+ element.removeAttribute( 'data-src' );
}
}
// If the browser doesn't support core features we won't be
// using JavaScript to control the presentation
@@ -288,20 +289,20 @@
* should only happens once per runtime.
*/
function checkCapabilities() {
features.transforms3d = 'WebkitPerspective' in document.body.style ||
- 'MozPerspective' in document.body.style ||
- 'msPerspective' in document.body.style ||
- 'OPerspective' in document.body.style ||
- 'perspective' in document.body.style;
+ 'MozPerspective' in document.body.style ||
+ 'msPerspective' in document.body.style ||
+ 'OPerspective' in document.body.style ||
+ 'perspective' in document.body.style;
features.transforms2d = 'WebkitTransform' in document.body.style ||
- 'MozTransform' in document.body.style ||
- 'msTransform' in document.body.style ||
- 'OTransform' in document.body.style ||
- 'transform' in document.body.style;
+ 'MozTransform' in document.body.style ||
+ 'msTransform' in document.body.style ||
+ 'OTransform' in document.body.style ||
+ 'transform' in document.body.style;
features.requestAnimationFrameMethod = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
features.requestAnimationFrame = typeof features.requestAnimationFrameMethod === 'function';
features.canvas = !!document.createElement( 'canvas' ).getContext;
@@ -733,18 +734,18 @@
// Create a hash for this combination of background settings.
// This is used to determine when two slide backgrounds are
// the same.
if( data.background || data.backgroundColor || data.backgroundImage || data.backgroundVideo || data.backgroundIframe ) {
element.setAttribute( 'data-background-hash', data.background +
- data.backgroundSize +
- data.backgroundImage +
- data.backgroundVideo +
- data.backgroundIframe +
- data.backgroundColor +
- data.backgroundRepeat +
- data.backgroundPosition +
- data.backgroundTransition );
+ data.backgroundSize +
+ data.backgroundImage +
+ data.backgroundVideo +
+ data.backgroundIframe +
+ data.backgroundColor +
+ data.backgroundRepeat +
+ data.backgroundPosition +
+ data.backgroundTransition );
}
// Additional and optional background properties
if( data.backgroundSize ) element.style.backgroundSize = data.backgroundSize;
if( data.backgroundColor ) element.style.backgroundColor = data.backgroundColor;
@@ -1134,11 +1135,11 @@
document.getElementsByTagName( 'head' )[0].appendChild( tag );
}
/**
- * Measures the distance in pixels between point a and point b.
+ * Converts various color input formats to an {r:0,g:0,b:0} object.
*
* @param {String} color The string representation of a color,
* the following formats are supported:
* - #000
* - #000000
@@ -1531,25 +1532,19 @@
}
else {
// Prefer zooming in desktop Chrome so that content remains crisp
if( !isMobileDevice && /chrome/i.test( navigator.userAgent ) && typeof dom.slides.style.zoom !== 'undefined' ) {
dom.slides.style.zoom = scale;
- dom.slides.style.marginTop = config.marginTop;
- dom.slides.style.marginLeft = config.marginLeft;
transformSlides( { layout: '' } );
}
// Apply scale transform as a fallback
else {
- // dom.slides.style.left = '50%';
- // dom.slides.style.top = '44%';
- // dom.slides.style.bottom = 'auto';
- // dom.slides.style.right = 'auto';
- dom.slides.style.marginTop = config.marginTop;
- dom.slides.style.marginLeft = config.marginLeft;
- dom.slides.style.marginBottom = 'auto';
- dom.slides.style.marginRight = 'auto';
- transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +') translate(50%, 50%)' } );
+ dom.slides.style.left = '50%';
+ dom.slides.style.top = '50%';
+ dom.slides.style.bottom = 'auto';
+ dom.slides.style.right = 'auto';
+ transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } );
}
}
// Select all slides, vertical and horizontal
var slides = toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) );
@@ -1633,11 +1628,11 @@
presentationWidth: presentationWidth || dom.wrapper.offsetWidth,
presentationHeight: presentationHeight || dom.wrapper.offsetHeight
};
// Reduce available space by margin
- size.presentationWidth -= ( size.presentationHeight * config.margin );
+ size.presentationWidth -= ( size.presentationWidth * config.margin );
size.presentationHeight -= ( size.presentationHeight * config.margin );
// Slide width may be a percentage of available width
if( typeof size.width === 'string' && /%$/.test( size.width ) ) {
size.width = parseInt( size.width, 10 ) / 100 * size.presentationWidth;
@@ -2201,10 +2196,11 @@
updateBackground( true );
updateSlideNumber();
updateSlidesVisibility();
formatEmbeddedContent();
+ startEmbeddedContent( currentSlide );
if( isOverview() ) {
layoutOverview();
}
@@ -2483,16 +2479,14 @@
// Check if a custom slide number format is available
if( typeof config.slideNumber === 'string' ) {
format = config.slideNumber;
}
- var totalSlides = getTotalSlides();
-
dom.slideNumber.innerHTML = format.replace( /h/g, indexh )
.replace( /v/g, indexv )
- .replace( /c/g, Math.round( getProgress() * totalSlides ) + 1 )
- .replace( /t/g, totalSlides + 1 );
+ .replace( /c/g, getSlidePastCount() + 1 )
+ .replace( /t/g, getTotalSlides() );
}
}
/**
@@ -2729,11 +2723,11 @@
// Show the slide element
slide.style.display = 'block';
// Media elements with data-src attributes
- toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src], iframe[data-src]' ) ).forEach( function( element ) {
+ toArray( slide.querySelectorAll( 'img[data-src], video[data-src], audio[data-src]' ) ).forEach( function( element ) {
element.setAttribute( 'src', element.getAttribute( 'data-src' ) );
element.removeAttribute( 'data-src' );
} );
// Media elements with <source> children
@@ -2876,25 +2870,26 @@
/**
* Enforces origin-specific format rules for embedded media.
*/
function formatEmbeddedContent() {
+ var _appendParamToIframeSource = function( sourceAttribute, sourceURL, param ) {
+ toArray( dom.slides.querySelectorAll( 'iframe['+ sourceAttribute +'*="'+ sourceURL +'"]' ) ).forEach( function( el ) {
+ var src = el.getAttribute( sourceAttribute );
+ if( src && src.indexOf( param ) === -1 ) {
+ el.setAttribute( sourceAttribute, src + ( !/\?/.test( src ) ? '?' : '&' ) + param );
+ }
+ });
+ };
+
// YouTube frames must include "?enablejsapi=1"
- toArray( dom.slides.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) {
- var src = el.getAttribute( 'src' );
- if( !/enablejsapi\=1/gi.test( src ) ) {
- el.setAttribute( 'src', src + ( !/\?/.test( src ) ? '?' : '&' ) + 'enablejsapi=1' );
- }
- });
+ _appendParamToIframeSource( 'src', 'youtube.com/embed/', 'enablejsapi=1' );
+ _appendParamToIframeSource( 'data-src', 'youtube.com/embed/', 'enablejsapi=1' );
// Vimeo frames must include "?api=1"
- toArray( dom.slides.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) {
- var src = el.getAttribute( 'src' );
- if( !/api\=1/gi.test( src ) ) {
- el.setAttribute( 'src', src + ( !/\?/.test( src ) ? '?' : '&' ) + 'api=1' );
- }
- });
+ _appendParamToIframeSource( 'src', 'player.vimeo.com/', 'api=1' );
+ _appendParamToIframeSource( 'data-src', 'player.vimeo.com/', 'api=1' );
}
/**
* Start playback of any embedded content inside of
@@ -2910,34 +2905,52 @@
el.setAttribute( 'src', el.getAttribute( 'src' ) );
} );
// HTML5 media elements
toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
- if( el.hasAttribute( 'data-autoplay' ) ) {
+ if( el.hasAttribute( 'data-autoplay' ) && typeof el.play === 'function' ) {
el.play();
}
} );
- // iframe embeds
- toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) {
- el.contentWindow.postMessage( 'slide:start', '*' );
- });
+ // Normal iframes
+ toArray( slide.querySelectorAll( 'iframe[src]' ) ).forEach( function( el ) {
+ startEmbeddedIframe( { target: el } );
+ } );
- // YouTube embeds
- toArray( slide.querySelectorAll( 'iframe[src*="youtube.com/embed/"]' ) ).forEach( function( el ) {
- if( el.hasAttribute( 'data-autoplay' ) ) {
- el.contentWindow.postMessage( '{"event":"command","func":"playVideo","args":""}', '*' );
+ // Lazy loading iframes
+ toArray( slide.querySelectorAll( 'iframe[data-src]' ) ).forEach( function( el ) {
+ if( el.getAttribute( 'src' ) !== el.getAttribute( 'data-src' ) ) {
+ el.removeEventListener( 'load', startEmbeddedIframe ); // remove first to avoid dupes
+ el.addEventListener( 'load', startEmbeddedIframe );
+ el.setAttribute( 'src', el.getAttribute( 'data-src' ) );
}
- });
+ } );
+ }
- // Vimeo embeds
- toArray( slide.querySelectorAll( 'iframe[src*="player.vimeo.com/"]' ) ).forEach( function( el ) {
- if( el.hasAttribute( 'data-autoplay' ) ) {
- el.contentWindow.postMessage( '{"method":"play"}', '*' );
- }
- });
+ }
+
+ /**
+ * "Starts" the content of an embedded iframe using the
+ * postmessage API.
+ */
+ function startEmbeddedIframe( event ) {
+
+ var iframe = event.target;
+
+ // YouTube postMessage API
+ if( /youtube\.com\/embed\//.test( iframe.getAttribute( 'src' ) ) && iframe.hasAttribute( 'data-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' ) ) {
+ iframe.contentWindow.postMessage( '{"method":"play"}', '*' );
+ }
+ // Generic postMessage API
+ else {
+ iframe.contentWindow.postMessage( 'slide:start', '*' );
+ }
}
/**
* Stop playback of any embedded content inside of
@@ -2946,47 +2959,55 @@
function stopEmbeddedContent( slide ) {
if( slide && slide.parentNode ) {
// HTML5 media elements
toArray( slide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
- if( !el.hasAttribute( 'data-ignore' ) ) {
+ if( !el.hasAttribute( 'data-ignore' ) && typeof el.pause === 'function' ) {
el.pause();
}
} );
- // iframe embeds
+ // Generic postMessage API for non-lazy loaded iframes
toArray( slide.querySelectorAll( 'iframe' ) ).forEach( function( el ) {
el.contentWindow.postMessage( 'slide:stop', '*' );
+ el.removeEventListener( 'load', startEmbeddedIframe );
});
- // YouTube embeds
+ // YouTube postMessage API
toArray( slide.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 embeds
+ // Vimeo postMessage API
toArray( slide.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 ) {
+ // 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' );
+ el.removeAttribute( 'src' );
+ } );
}
}
/**
- * Returns a value ranging from 0-1 that represents
- * how far into the presentation we have navigated.
+ * Returns the number of past slides. This can be used as a global
+ * flattened index for slides.
*/
- function getProgress() {
+ function getSlidePastCount() {
var horizontalSlides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
- // The number of past and total slides
- var totalCount = getTotalSlides();
+ // The number of past slides
var pastCount = 0;
// Step through all slides and count the past ones
mainLoop: for( var i = 0; i < horizontalSlides.length; i++ ) {
@@ -3014,10 +3035,24 @@
pastCount++;
}
}
+ return pastCount;
+
+ }
+
+ /**
+ * Returns a value ranging from 0-1 that represents
+ * how far into the presentation we have navigated.
+ */
+ function getProgress() {
+
+ // The number of past and total slides
+ var totalCount = getTotalSlides();
+ var pastCount = getSlidePastCount();
+
if( currentSlide ) {
var allFragments = currentSlide.querySelectorAll( '.fragment' );
// If there are fragments in the current slide those should be
@@ -3498,17 +3533,20 @@
autoSlide = config.autoSlide;
}
// If there are media elements with data-autoplay,
// automatically set the autoSlide duration to the
- // length of that media
- toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
- if( el.hasAttribute( 'data-autoplay' ) ) {
- if( autoSlide && el.duration * 1000 > autoSlide ) {
- autoSlide = ( el.duration * 1000 ) + 1000;
+ // length of that media. Not applicable if the slide
+ // is divided up into fragments.
+ if( currentSlide.querySelectorAll( '.fragment' ).length === 0 ) {
+ toArray( currentSlide.querySelectorAll( 'video, audio' ) ).forEach( function( el ) {
+ if( el.hasAttribute( 'data-autoplay' ) ) {
+ if( autoSlide && el.duration * 1000 > autoSlide ) {
+ autoSlide = ( el.duration * 1000 ) + 1000;
+ }
}
- }
- } );
+ } );
+ }
// Cue the next auto-slide if:
// - There is an autoSlide value
// - Auto-sliding isn't paused by the user
// - The presentation isn't paused
\ No newline at end of file