aboutsummaryrefslogtreecommitdiff
path: root/js/reveal.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/reveal.js')
-rw-r--r--js/reveal.js167
1 files changed, 116 insertions, 51 deletions
diff --git a/js/reveal.js b/js/reveal.js
index 2c92954..0b1cad7 100644
--- a/js/reveal.js
+++ b/js/reveal.js
@@ -25,6 +25,9 @@
var Reveal;
+ // The reveal.js version
+ var VERSION = '3.2.0';
+
var SLIDES_SELECTOR = '.slides section',
HORIZONTAL_SLIDES_SELECTOR = '.slides>section',
VERTICAL_SLIDES_SELECTOR = '.slides>section.present>section',
@@ -78,6 +81,9 @@
// Change the presentation direction to be RTL
rtl: false,
+ // Randomizes the order of slides each time the presentation loads
+ shuffle: false,
+
// Turns fragments on and off globally
fragments: true,
@@ -103,6 +109,9 @@
// Stop auto-sliding after user input
autoSlideStoppable: true,
+ // Use this method for navigation when auto-sliding (defaults to navigateNext)
+ autoSlideMethod: null,
+
// Enable slide navigation via mouse wheel
mouseWheel: false,
@@ -292,30 +301,36 @@
*/
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;
+ isMobileDevice = /(iphone|ipod|ipad|android)/gi.test( navigator.userAgent );
+
+ var testElement = document.createElement( 'div' );
- 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;
+ features.transforms3d = 'WebkitPerspective' in testElement.style ||
+ 'MozPerspective' in testElement.style ||
+ 'msPerspective' in testElement.style ||
+ 'OPerspective' in testElement.style ||
+ 'perspective' in testElement.style;
+
+ features.transforms2d = 'WebkitTransform' in testElement.style ||
+ 'MozTransform' in testElement.style ||
+ 'msTransform' in testElement.style ||
+ 'OTransform' in testElement.style ||
+ 'transform' in testElement.style;
features.requestAnimationFrameMethod = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
features.requestAnimationFrame = typeof features.requestAnimationFrameMethod === 'function';
features.canvas = !!document.createElement( 'canvas' ).getContext;
- features.touch = !!( 'ontouchstart' in window );
-
// Transitions in the overview are disabled in desktop and
- // mobile Safari due to lag
+ // Safari due to lag
features.overviewTransitions = !/Version\/[\d\.]+.*Safari/.test( navigator.userAgent );
- isMobileDevice = /(iphone|ipod|ipad|android)/gi.test( navigator.userAgent );
+ // Flags if we should use zoom instead of transform to scale
+ // up slides. Zoom produces crisper results but has a lot of
+ // xbrowser quirks so we only use it in whitelsited browsers.
+ features.zoom = 'zoom' in testElement.style && !isMobileDevice &&
+ ( /chrome/i.test( navigator.userAgent ) || /Version\/[\d\.]+.*Safari/.test( navigator.userAgent ) );
}
@@ -395,8 +410,8 @@
// Listen to messages posted to this window
setupPostMessage();
- // Prevent iframes from scrolling the slides out of view
- setupIframeScrollPrevention();
+ // Prevent the slides from being scrolled out of view
+ setupScrollPrevention();
// Resets all vertical slides so that only the first is visible
resetVerticalSlides();
@@ -627,22 +642,22 @@
}
/**
- * This is an unfortunate necessity. Iframes can trigger the
- * parent window to scroll, for example by focusing an input.
+ * This is an unfortunate necessity. Some actions – such as
+ * an input field being focused in an iframe or using the
+ * keyboard to expand text selection beyond the bounds of
+ * a slide – can trigger our content to be pushed out of view.
* This scrolling can not be prevented by hiding overflow in
- * CSS so we have to resort to repeatedly checking if the
- * browser has decided to offset our slides :(
+ * CSS (we already do) so we have to resort to repeatedly
+ * checking if the slides have been offset :(
*/
- function setupIframeScrollPrevention() {
+ function setupScrollPrevention() {
- if( dom.slides.querySelector( 'iframe' ) ) {
- setInterval( function() {
- if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) {
- dom.wrapper.scrollTop = 0;
- dom.wrapper.scrollLeft = 0;
- }
- }, 500 );
- }
+ setInterval( function() {
+ if( dom.wrapper.scrollTop !== 0 || dom.wrapper.scrollLeft !== 0 ) {
+ dom.wrapper.scrollTop = 0;
+ dom.wrapper.scrollLeft = 0;
+ }
+ }, 1000 );
}
@@ -886,6 +901,10 @@
dom.progress.style.display = config.progress ? 'block' : 'none';
dom.slideNumber.style.display = config.slideNumber && !isPrintingPDF() ? 'block' : 'none';
+ if( config.shuffle ) {
+ shuffle();
+ }
+
if( config.rtl ) {
dom.wrapper.classList.add( 'rtl' );
}
@@ -1586,10 +1605,10 @@
transformSlides( { layout: '' } );
}
else {
- // Use zoom to scale up in desktop Chrome so that content
- // remains crisp. We don't use zoom to scale down since that
- // can lead to shifts in text layout/line breaks.
- if( scale > 1 && !isMobileDevice && /chrome/i.test( navigator.userAgent ) && typeof dom.slides.style.zoom !== 'undefined' ) {
+ // Prefer zoom for scaling up so that content remains crisp.
+ // Don't use zoom to scale down since that can lead to shifts
+ // in text layout/line breaks.
+ if( scale > 1 && features.zoom ) {
dom.slides.style.zoom = scale;
dom.slides.style.left = '';
dom.slides.style.top = '';
@@ -2318,6 +2337,23 @@
}
/**
+ * Randomly shuffles all slides in the deck.
+ */
+ function shuffle() {
+
+ var slides = toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) );
+
+ slides.forEach( function( slide ) {
+
+ // Insert this slide next to another random slide. This may
+ // cause the slide to insert before itself but that's fine.
+ dom.slides.insertBefore( slide, slides[ Math.floor( Math.random() * slides.length ) ] );
+
+ } );
+
+ }
+
+ /**
* Updates one dimension of slides by showing the slide
* with the specified index.
*
@@ -2722,8 +2758,20 @@
// Start video playback
var currentVideo = currentBackground.querySelector( 'video' );
if( currentVideo ) {
- if( currentVideo.currentTime > 0 ) currentVideo.currentTime = 0;
- currentVideo.play();
+
+ 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 || '';
@@ -2870,6 +2918,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' );
// Images
@@ -2884,6 +2933,10 @@
video.setAttribute( 'loop', '' );
}
+ if( backgroundVideoMuted ) {
+ video.muted = true;
+ }
+
// Support comma separated lists of video sources
backgroundVideo.split( ',' ).forEach( function( source ) {
video.innerHTML += '<source src="'+ source +'">';
@@ -3688,7 +3741,10 @@
// - The overview isn't active
// - The presentation isn't over
if( autoSlide && !autoSlidePaused && !isPaused() && !isOverview() && ( !Reveal.isLastSlide() || availableFragments().next || config.loop === true ) ) {
- autoSlideTimeout = setTimeout( navigateNext, autoSlide );
+ autoSlideTimeout = setTimeout( function() {
+ typeof config.autoSlideMethod === 'function' ? config.autoSlideMethod() : navigateNext();
+ cueAutoSlide();
+ }, autoSlide );
autoSlideStartTime = Date.now();
}
@@ -3834,10 +3890,6 @@
}
}
- // If auto-sliding is enabled we need to cue up
- // another timeout
- cueAutoSlide();
-
}
/**
@@ -4364,8 +4416,9 @@
function Playback( container, progressCheck ) {
// Cosmetics
- this.diameter = 50;
- this.thickness = 3;
+ this.diameter = 100;
+ this.diameter2 = this.diameter/2;
+ this.thickness = 6;
// Flags if we are currently playing
this.playing = false;
@@ -4383,6 +4436,8 @@
this.canvas.className = 'playback';
this.canvas.width = this.diameter;
this.canvas.height = this.diameter;
+ this.canvas.style.width = this.diameter2 + 'px';
+ this.canvas.style.height = this.diameter2 + 'px';
this.context = this.canvas.getContext( '2d' );
this.container.appendChild( this.canvas );
@@ -4433,10 +4488,10 @@
Playback.prototype.render = function() {
var progress = this.playing ? this.progress : 0,
- radius = ( this.diameter / 2 ) - this.thickness,
- x = this.diameter / 2,
- y = this.diameter / 2,
- iconSize = 14;
+ radius = ( this.diameter2 ) - this.thickness,
+ x = this.diameter2,
+ y = this.diameter2,
+ iconSize = 28;
// Ease towards 1
this.progressOffset += ( 1 - this.progressOffset ) * 0.1;
@@ -4449,7 +4504,7 @@
// Solid background color
this.context.beginPath();
- this.context.arc( x, y, radius + 2, 0, Math.PI * 2, false );
+ this.context.arc( x, y, radius + 4, 0, Math.PI * 2, false );
this.context.fillStyle = 'rgba( 0, 0, 0, 0.4 )';
this.context.fill();
@@ -4474,14 +4529,14 @@
// Draw play/pause icons
if( this.playing ) {
this.context.fillStyle = '#fff';
- this.context.fillRect( 0, 0, iconSize / 2 - 2, iconSize );
- this.context.fillRect( iconSize / 2 + 2, 0, iconSize / 2 - 2, iconSize );
+ this.context.fillRect( 0, 0, iconSize / 2 - 4, iconSize );
+ this.context.fillRect( iconSize / 2 + 4, 0, iconSize / 2 - 4, iconSize );
}
else {
this.context.beginPath();
- this.context.translate( 2, 0 );
+ this.context.translate( 4, 0 );
this.context.moveTo( 0, 0 );
- this.context.lineTo( iconSize - 2, iconSize / 2 );
+ this.context.lineTo( iconSize - 4, iconSize / 2 );
this.context.lineTo( 0, iconSize );
this.context.fillStyle = '#fff';
this.context.fill();
@@ -4516,6 +4571,8 @@
Reveal = {
+ VERSION: VERSION,
+
initialize: initialize,
configure: configure,
sync: sync,
@@ -4546,6 +4603,9 @@
// Forces an update in slide layout
layout: layout,
+ // Randomizes the order of slides
+ shuffle: shuffle,
+
// Returns an object with the available routes as booleans (left/right/top/bottom)
availableRoutes: availableRoutes,
@@ -4669,6 +4729,11 @@
// Programatically triggers a keyboard event
triggerKey: function( keyCode ) {
onDocumentKeyDown( { keyCode: keyCode } );
+ },
+
+ // Registers a new shortcut to include in the help overlay
+ registerKeyboardShortcut: function( key, value ) {
+ keyboardShortcuts[key] = value;
}
};