Merge branch 'dev' into master
This commit is contained in:
429
js/reveal.js
429
js/reveal.js
@ -3,7 +3,7 @@
|
||||
* http://revealjs.com
|
||||
* MIT licensed
|
||||
*
|
||||
* Copyright (C) 2017 Hakim El Hattab, http://hakim.se
|
||||
* Copyright (C) 2018 Hakim El Hattab, http://hakim.se
|
||||
*/
|
||||
(function( root, factory ) {
|
||||
if( typeof define === 'function' && define.amd ) {
|
||||
@ -88,6 +88,10 @@
|
||||
// Enable the slide overview mode
|
||||
overview: true,
|
||||
|
||||
// Disables the default reveal.js slide layout so that you can use
|
||||
// custom CSS layout
|
||||
disableLayout: false,
|
||||
|
||||
// Vertical centering of slides
|
||||
center: true,
|
||||
|
||||
@ -106,6 +110,10 @@
|
||||
// Turns fragments on and off globally
|
||||
fragments: true,
|
||||
|
||||
// Flags whether to include the current fragment in the URL,
|
||||
// so that reloading brings you to the same fragment position
|
||||
fragmentInURL: false,
|
||||
|
||||
// Flags if the presentation is running in an embedded mode,
|
||||
// i.e. contained within a limited portion of the screen
|
||||
embedded: false,
|
||||
@ -139,6 +147,11 @@
|
||||
// Use this method for navigation when auto-sliding (defaults to navigateNext)
|
||||
autoSlideMethod: null,
|
||||
|
||||
// Specify the average time in seconds that you think you will spend
|
||||
// presenting each slide. This is used to show a pacing timer in the
|
||||
// speaker view
|
||||
defaultTiming: null,
|
||||
|
||||
// Enable slide navigation via mouse wheel
|
||||
mouseWheel: false,
|
||||
|
||||
@ -177,6 +190,12 @@
|
||||
// Parallax background size
|
||||
parallaxBackgroundSize: '', // CSS syntax, e.g. "3000px 2000px"
|
||||
|
||||
// Parallax background repeat
|
||||
parallaxBackgroundRepeat: '', // repeat/repeat-x/repeat-y/no-repeat/initial/inherit
|
||||
|
||||
// Parallax background position
|
||||
parallaxBackgroundPosition: '', // CSS syntax, e.g. "top left"
|
||||
|
||||
// Amount of pixels to move the parallax background per slide step
|
||||
parallaxBackgroundHorizontal: null,
|
||||
parallaxBackgroundVertical: null,
|
||||
@ -295,7 +314,10 @@
|
||||
'B , .': 'Pause',
|
||||
'F': 'Fullscreen',
|
||||
'ESC, O': 'Slide overview'
|
||||
};
|
||||
},
|
||||
|
||||
// Holds custom key code mappings
|
||||
registeredKeyBindings = {};
|
||||
|
||||
/**
|
||||
* Starts up the presentation if the client is capable.
|
||||
@ -397,13 +419,13 @@
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the dependencies of reveal.js. Dependencies are
|
||||
* defined via the configuration option 'dependencies'
|
||||
* and will be loaded prior to starting/binding reveal.js.
|
||||
* Some dependencies may have an 'async' flag, if so they
|
||||
* will load after reveal.js has been started up.
|
||||
*/
|
||||
/**
|
||||
* Loads the dependencies of reveal.js. Dependencies are
|
||||
* defined via the configuration option 'dependencies'
|
||||
* and will be loaded prior to starting/binding reveal.js.
|
||||
* Some dependencies may have an 'async' flag, if so they
|
||||
* will load after reveal.js has been started up.
|
||||
*/
|
||||
function load() {
|
||||
|
||||
var scripts = [],
|
||||
@ -421,7 +443,7 @@
|
||||
}
|
||||
|
||||
function loadScript( s ) {
|
||||
head.ready( s.src.match( /([\w\d_\-]*)\.?js$|[^\\\/]*$/i )[0], function() {
|
||||
head.ready( s.src.match( /([\w\d_\-]*)\.?js(\?[\w\d.=&]*)?$|[^\\\/]*$/i )[0], function() {
|
||||
// Extension may contain callback functions
|
||||
if( typeof s.callback === 'function' ) {
|
||||
s.callback.apply( this );
|
||||
@ -871,6 +893,8 @@
|
||||
|
||||
dom.background.style.backgroundImage = 'url("' + config.parallaxBackgroundImage + '")';
|
||||
dom.background.style.backgroundSize = config.parallaxBackgroundSize;
|
||||
dom.background.style.backgroundRepeat = config.parallaxBackgroundRepeat;
|
||||
dom.background.style.backgroundPosition = config.parallaxBackgroundPosition;
|
||||
|
||||
// Make sure the below properties are set on the element - these properties are
|
||||
// needed for proper transitions to be set on the element via CSS. To remove
|
||||
@ -919,7 +943,7 @@
|
||||
|
||||
if( data.background ) {
|
||||
// Auto-wrap image urls in url(...)
|
||||
if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)([?#]|$)/gi.test( data.background ) ) {
|
||||
if( /^(http|file|\/\/)/gi.test( data.background ) || /\.(svg|png|jpg|jpeg|gif|bmp)([?#\s]|$)/gi.test( data.background ) ) {
|
||||
slide.setAttribute( 'data-background-image', data.background );
|
||||
}
|
||||
else {
|
||||
@ -1156,13 +1180,8 @@
|
||||
window.addEventListener( 'resize', onWindowResize, false );
|
||||
|
||||
if( config.touch ) {
|
||||
dom.wrapper.addEventListener( 'touchstart', onTouchStart, false );
|
||||
dom.wrapper.addEventListener( 'touchmove', onTouchMove, false );
|
||||
dom.wrapper.addEventListener( 'touchend', onTouchEnd, false );
|
||||
|
||||
// Support pointer-style touch interaction as well
|
||||
if( window.navigator.pointerEnabled ) {
|
||||
// IE 11 uses un-prefixed version of pointer events
|
||||
if( 'onpointerdown' in window ) {
|
||||
// Use W3C pointer events
|
||||
dom.wrapper.addEventListener( 'pointerdown', onPointerDown, false );
|
||||
dom.wrapper.addEventListener( 'pointermove', onPointerMove, false );
|
||||
dom.wrapper.addEventListener( 'pointerup', onPointerUp, false );
|
||||
@ -1173,6 +1192,12 @@
|
||||
dom.wrapper.addEventListener( 'MSPointerMove', onPointerMove, false );
|
||||
dom.wrapper.addEventListener( 'MSPointerUp', onPointerUp, false );
|
||||
}
|
||||
else {
|
||||
// Fall back to touch events
|
||||
dom.wrapper.addEventListener( 'touchstart', onTouchStart, false );
|
||||
dom.wrapper.addEventListener( 'touchmove', onTouchMove, false );
|
||||
dom.wrapper.addEventListener( 'touchend', onTouchEnd, false );
|
||||
}
|
||||
}
|
||||
|
||||
if( config.keyboard ) {
|
||||
@ -1234,24 +1259,19 @@
|
||||
document.removeEventListener( 'keypress', onDocumentKeyPress, false );
|
||||
window.removeEventListener( 'hashchange', onWindowHashChange, false );
|
||||
window.removeEventListener( 'resize', onWindowResize, false );
|
||||
|
||||
dom.wrapper.removeEventListener( 'pointerdown', onPointerDown, false );
|
||||
dom.wrapper.removeEventListener( 'pointermove', onPointerMove, false );
|
||||
dom.wrapper.removeEventListener( 'pointerup', onPointerUp, false );
|
||||
|
||||
dom.wrapper.removeEventListener( 'MSPointerDown', onPointerDown, false );
|
||||
dom.wrapper.removeEventListener( 'MSPointerMove', onPointerMove, false );
|
||||
dom.wrapper.removeEventListener( 'MSPointerUp', onPointerUp, false );
|
||||
|
||||
dom.wrapper.removeEventListener( 'touchstart', onTouchStart, false );
|
||||
dom.wrapper.removeEventListener( 'touchmove', onTouchMove, false );
|
||||
dom.wrapper.removeEventListener( 'touchend', onTouchEnd, false );
|
||||
|
||||
// IE11
|
||||
if( window.navigator.pointerEnabled ) {
|
||||
dom.wrapper.removeEventListener( 'pointerdown', onPointerDown, false );
|
||||
dom.wrapper.removeEventListener( 'pointermove', onPointerMove, false );
|
||||
dom.wrapper.removeEventListener( 'pointerup', onPointerUp, false );
|
||||
}
|
||||
// IE10
|
||||
else if( window.navigator.msPointerEnabled ) {
|
||||
dom.wrapper.removeEventListener( 'MSPointerDown', onPointerDown, false );
|
||||
dom.wrapper.removeEventListener( 'MSPointerMove', onPointerMove, false );
|
||||
dom.wrapper.removeEventListener( 'MSPointerUp', onPointerUp, false );
|
||||
}
|
||||
|
||||
if ( config.progress && dom.progress ) {
|
||||
dom.progress.removeEventListener( 'click', onProgressClicked, false );
|
||||
}
|
||||
@ -1267,6 +1287,38 @@
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom key binding with optional description to
|
||||
* be added to the help screen.
|
||||
*/
|
||||
function addKeyBinding( binding, callback ) {
|
||||
|
||||
if( typeof binding === 'object' && binding.keyCode ) {
|
||||
registeredKeyBindings[binding.keyCode] = {
|
||||
callback: callback,
|
||||
key: binding.key,
|
||||
description: binding.description
|
||||
};
|
||||
}
|
||||
else {
|
||||
registeredKeyBindings[binding] = {
|
||||
callback: callback,
|
||||
key: null,
|
||||
description: null
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified custom key binding.
|
||||
*/
|
||||
function removeKeyBinding( keyCode ) {
|
||||
|
||||
delete registeredKeyBindings[keyCode];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend object a with the properties of object b.
|
||||
* If there's a conflict, object b takes precedence.
|
||||
@ -1754,6 +1806,13 @@
|
||||
html += '<tr><td>' + key + '</td><td>' + keyboardShortcuts[ key ] + '</td></tr>';
|
||||
}
|
||||
|
||||
// Add custom key bindings that have associated descriptions
|
||||
for( var binding in registeredKeyBindings ) {
|
||||
if( registeredKeyBindings[binding].key && registeredKeyBindings[binding].description ) {
|
||||
html += '<tr><td>' + registeredKeyBindings[binding].key + '</td><td>' + registeredKeyBindings[binding].description + '</td></tr>';
|
||||
}
|
||||
}
|
||||
|
||||
html += '</table>';
|
||||
|
||||
dom.overlay.innerHTML = [
|
||||
@ -1798,76 +1857,80 @@
|
||||
|
||||
if( dom.wrapper && !isPrintingPDF() ) {
|
||||
|
||||
var size = getComputedSlideSize();
|
||||
if( !config.disableLayout ) {
|
||||
|
||||
// Layout the contents of the slides
|
||||
layoutSlideContents( config.width, config.height );
|
||||
var size = getComputedSlideSize();
|
||||
|
||||
dom.slides.style.width = size.width + 'px';
|
||||
dom.slides.style.height = size.height + 'px';
|
||||
// Layout the contents of the slides
|
||||
layoutSlideContents( config.width, config.height );
|
||||
|
||||
// Determine scale of content to fit within available space
|
||||
scale = Math.min( size.presentationWidth / size.width, size.presentationHeight / size.height );
|
||||
dom.slides.style.width = size.width + 'px';
|
||||
dom.slides.style.height = size.height + 'px';
|
||||
|
||||
// Respect max/min scale settings
|
||||
scale = Math.max( scale, config.minScale );
|
||||
scale = Math.min( scale, config.maxScale );
|
||||
// Determine scale of content to fit within available space
|
||||
scale = Math.min( size.presentationWidth / size.width, size.presentationHeight / size.height );
|
||||
|
||||
// Don't apply any scaling styles if scale is 1
|
||||
if( scale === 1 ) {
|
||||
dom.slides.style.zoom = '';
|
||||
dom.slides.style.left = '';
|
||||
dom.slides.style.top = '';
|
||||
dom.slides.style.bottom = '';
|
||||
dom.slides.style.right = '';
|
||||
transformSlides( { layout: '' } );
|
||||
}
|
||||
else {
|
||||
// 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;
|
||||
// Respect max/min scale settings
|
||||
scale = Math.max( scale, config.minScale );
|
||||
scale = Math.min( scale, config.maxScale );
|
||||
|
||||
// Don't apply any scaling styles if scale is 1
|
||||
if( scale === 1 ) {
|
||||
dom.slides.style.zoom = '';
|
||||
dom.slides.style.left = '';
|
||||
dom.slides.style.top = '';
|
||||
dom.slides.style.bottom = '';
|
||||
dom.slides.style.right = '';
|
||||
transformSlides( { layout: '' } );
|
||||
}
|
||||
// Apply scale transform as a fallback
|
||||
else {
|
||||
dom.slides.style.zoom = '';
|
||||
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 ) );
|
||||
|
||||
for( var i = 0, len = slides.length; i < len; i++ ) {
|
||||
var slide = slides[ i ];
|
||||
|
||||
// Don't bother updating invisible slides
|
||||
if( slide.style.display === 'none' ) {
|
||||
continue;
|
||||
// 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 = '';
|
||||
dom.slides.style.bottom = '';
|
||||
dom.slides.style.right = '';
|
||||
transformSlides( { layout: '' } );
|
||||
}
|
||||
// Apply scale transform as a fallback
|
||||
else {
|
||||
dom.slides.style.zoom = '';
|
||||
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 +')' } );
|
||||
}
|
||||
}
|
||||
|
||||
if( config.center || slide.classList.contains( 'center' ) ) {
|
||||
// Vertical stacks are not centred since their section
|
||||
// children will be
|
||||
if( slide.classList.contains( 'stack' ) ) {
|
||||
slide.style.top = 0;
|
||||
// Select all slides, vertical and horizontal
|
||||
var slides = toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) );
|
||||
|
||||
for( var i = 0, len = slides.length; i < len; i++ ) {
|
||||
var slide = slides[ i ];
|
||||
|
||||
// Don't bother updating invisible slides
|
||||
if( slide.style.display === 'none' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if( config.center || slide.classList.contains( 'center' ) ) {
|
||||
// Vertical stacks are not centred since their section
|
||||
// children will be
|
||||
if( slide.classList.contains( 'stack' ) ) {
|
||||
slide.style.top = 0;
|
||||
}
|
||||
else {
|
||||
slide.style.top = Math.max( ( size.height - slide.scrollHeight ) / 2, 0 ) + 'px';
|
||||
}
|
||||
}
|
||||
else {
|
||||
slide.style.top = Math.max( ( size.height - slide.scrollHeight ) / 2, 0 ) + 'px';
|
||||
slide.style.top = '';
|
||||
}
|
||||
}
|
||||
else {
|
||||
slide.style.top = '';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -2198,25 +2261,33 @@
|
||||
*/
|
||||
|
||||
function locationHash() {
|
||||
var url = '/';
|
||||
|
||||
// Attempt to create a named link based on the slide's ID
|
||||
var id = currentSlide ? currentSlide.getAttribute( 'id' ) : null;
|
||||
if( id ) {
|
||||
id = id.replace( /[^a-zA-Z0-9\-\_\:\.]/g, '' );
|
||||
}
|
||||
|
||||
var url = '/';
|
||||
|
||||
// If the current slide has an ID, use that as a named link
|
||||
if( typeof id === 'string' && id.length ) {
|
||||
url = '/' + id;
|
||||
}
|
||||
// Otherwise use the /h/v index (adding 1 to match slide label)
|
||||
else {
|
||||
if( indexh > 0 || indexv > 0 ) url += indexh + config.hashOneBasedIndex;
|
||||
if( indexv > 0 ) url += '/' + (indexv + config.hashOneBasedIndex);
|
||||
}
|
||||
|
||||
return url;
|
||||
// Attempt to create a named link based on the slide's ID
|
||||
var id = currentSlide ? currentSlide.getAttribute( 'id' ) : null;
|
||||
if( id ) {
|
||||
id = encodeURIComponent( id );
|
||||
}
|
||||
|
||||
var indexf;
|
||||
if( config.fragmentInURL ) {
|
||||
indexf = getIndices().f;
|
||||
}
|
||||
|
||||
// If the current slide has an ID, use that as a named link,
|
||||
// but we don't support named links with a fragment index
|
||||
if( typeof id === 'string' && id.length && indexf === undefined ) {
|
||||
url = '/' + id;
|
||||
}
|
||||
// Otherwise use the /h/v index
|
||||
else {
|
||||
if( indexh > 0 || indexv > 0 || indexf !== undefined ) url += indexh + config.hashOneBasedIndex;
|
||||
if( indexv > 0 || indexf !== undefined ) url += '/' + (indexv + config.hashOneBasedIndex);
|
||||
if( indexf !== undefined ) url += '/' + indexf;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2443,16 +2514,7 @@
|
||||
|
||||
// Dispatch an event if the slide changed
|
||||
var slideChanged = ( indexh !== indexhBefore || indexv !== indexvBefore );
|
||||
if( slideChanged ) {
|
||||
dispatchEvent( 'slidechanged', {
|
||||
'indexh': indexh,
|
||||
'indexv': indexv,
|
||||
'previousSlide': previousSlide,
|
||||
'currentSlide': currentSlide,
|
||||
'origin': o
|
||||
} );
|
||||
}
|
||||
else {
|
||||
if (!slideChanged) {
|
||||
// Ensure that the previous slide is never the same as the current
|
||||
previousSlide = null;
|
||||
}
|
||||
@ -2460,7 +2522,7 @@
|
||||
// Solves an edge case where the previous slide maintains the
|
||||
// 'present' class when navigating between adjacent vertical
|
||||
// stacks
|
||||
if( previousSlide ) {
|
||||
if( previousSlide && previousSlide !== currentSlide ) {
|
||||
previousSlide.classList.remove( 'present' );
|
||||
previousSlide.setAttribute( 'aria-hidden', 'true' );
|
||||
|
||||
@ -2480,6 +2542,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
if( slideChanged ) {
|
||||
dispatchEvent( 'slidechanged', {
|
||||
'indexh': indexh,
|
||||
'indexv': indexv,
|
||||
'previousSlide': previousSlide,
|
||||
'currentSlide': currentSlide,
|
||||
'origin': o
|
||||
} );
|
||||
}
|
||||
|
||||
// Handle embedded content
|
||||
if( slideChanged || !previousSlide ) {
|
||||
stopEmbeddedContent( previousSlide );
|
||||
@ -3237,8 +3309,7 @@
|
||||
|
||||
|
||||
// Show the corresponding background element
|
||||
var indices = getIndices( slide );
|
||||
var background = getSlideBackground( indices.h, indices.v );
|
||||
var background = getSlideBackground( slide );
|
||||
if( background ) {
|
||||
background.style.display = 'block';
|
||||
|
||||
@ -3254,7 +3325,7 @@
|
||||
|
||||
// Images
|
||||
if( backgroundImage ) {
|
||||
background.style.backgroundImage = 'url('+ backgroundImage +')';
|
||||
background.style.backgroundImage = 'url('+ encodeURI( backgroundImage ) +')';
|
||||
}
|
||||
// Videos
|
||||
else if ( backgroundVideo && !isSpeakerNotes() ) {
|
||||
@ -3325,8 +3396,7 @@
|
||||
slide.style.display = 'none';
|
||||
|
||||
// Hide the corresponding background element
|
||||
var indices = getIndices( slide );
|
||||
var background = getSlideBackground( indices.h, indices.v );
|
||||
var background = getSlideBackground( slide );
|
||||
if( background ) {
|
||||
background.style.display = 'none';
|
||||
}
|
||||
@ -3356,13 +3426,27 @@
|
||||
verticalSlides = dom.wrapper.querySelectorAll( VERTICAL_SLIDES_SELECTOR );
|
||||
|
||||
var routes = {
|
||||
left: indexh > 0 || config.loop,
|
||||
right: indexh < horizontalSlides.length - 1 || config.loop,
|
||||
left: indexh > 0,
|
||||
right: indexh < horizontalSlides.length - 1,
|
||||
up: indexv > 0,
|
||||
down: indexv < verticalSlides.length - 1
|
||||
};
|
||||
|
||||
// reverse horizontal controls for rtl
|
||||
// Looped presentations can always be navigated as long as
|
||||
// there are slides available
|
||||
if( config.loop ) {
|
||||
if( horizontalSlides.length > 1 ) {
|
||||
routes.left = true;
|
||||
routes.right = true;
|
||||
}
|
||||
|
||||
if( verticalSlides.length > 1 ) {
|
||||
routes.up = true;
|
||||
routes.down = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse horizontal controls for rtl
|
||||
if( config.rtl ) {
|
||||
var left = routes.left;
|
||||
routes.left = routes.right;
|
||||
@ -3461,9 +3545,16 @@
|
||||
|
||||
if( autoplay && typeof el.play === 'function' ) {
|
||||
|
||||
// If the media is ready, start playback
|
||||
if( el.readyState > 1 ) {
|
||||
startEmbeddedMedia( { target: el } );
|
||||
}
|
||||
// Mobile devices never fire a loaded event so instead
|
||||
// of waiting, we initiate playback
|
||||
else if( isMobileDevice ) {
|
||||
el.play();
|
||||
}
|
||||
// If the media isn't loaded, wait before playing
|
||||
else {
|
||||
el.removeEventListener( 'loadeddata', startEmbeddedMedia ); // remove first to avoid dupes
|
||||
el.addEventListener( 'loadeddata', startEmbeddedMedia );
|
||||
@ -3728,12 +3819,15 @@
|
||||
var element;
|
||||
|
||||
// Ensure the named link is a valid HTML ID attribute
|
||||
if( /^[a-zA-Z][\w:.-]*$/.test( name ) ) {
|
||||
// Find the slide with the specified ID
|
||||
element = document.getElementById( name );
|
||||
try {
|
||||
element = document.getElementById( decodeURIComponent( name ) );
|
||||
}
|
||||
catch ( error ) { }
|
||||
|
||||
if( element ) {
|
||||
// Ensure that we're not already on a slide with the same name
|
||||
var isSameNameAsCurrentSlide = currentSlide ? currentSlide.getAttribute( 'id' ) === name : false;
|
||||
|
||||
if( element && !isSameNameAsCurrentSlide ) {
|
||||
// Find the position of the named slide and navigate to it
|
||||
var indices = Reveal.getIndices( element );
|
||||
slide( indices.h, indices.v );
|
||||
@ -3745,11 +3839,19 @@
|
||||
}
|
||||
else {
|
||||
// Read the index components of the hash
|
||||
var h = (parseInt( bits[0], 10 ) || 0) - config.hashOneBasedIndex,
|
||||
v = (parseInt( bits[1], 10 ) || 0) - config.hashOneBasedIndex;
|
||||
|
||||
if( h !== indexh || v !== indexv ) {
|
||||
slide( h, v );
|
||||
var h = parseInt( bits[0], 10 ) || 0 - config.hashOneBasedIndex,
|
||||
v = parseInt( bits[1], 10 ) || 0 - config.hashOneBasedIndex,
|
||||
f;
|
||||
if( config.fragmentInURL ) {
|
||||
f = parseInt( bits[2], 10 );
|
||||
if( isNaN( f ) ) {
|
||||
f = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if( h !== indexh || v !== indexv || f !== undefined ) {
|
||||
slide( h, v, f );
|
||||
}
|
||||
}
|
||||
|
||||
@ -3877,13 +3979,14 @@
|
||||
* defined, have a background element so as long as the
|
||||
* index is valid an element will be returned.
|
||||
*
|
||||
* @param {number} x Horizontal background index
|
||||
* @param {mixed} x Horizontal background index OR a slide
|
||||
* HTML element
|
||||
* @param {number} y Vertical background index
|
||||
* @return {(HTMLElement[]|*)}
|
||||
*/
|
||||
function getSlideBackground( x, y ) {
|
||||
|
||||
var slide = getSlide( x, y );
|
||||
var slide = typeof x === 'number' ? getSlide( x, y ) : x;
|
||||
if( slide ) {
|
||||
return slide.slideBackgroundElement;
|
||||
}
|
||||
@ -4108,6 +4211,9 @@
|
||||
|
||||
updateControls();
|
||||
updateProgress();
|
||||
if( config.fragmentInURL ) {
|
||||
writeURL();
|
||||
}
|
||||
|
||||
return !!( fragmentsShown.length || fragmentsHidden.length );
|
||||
|
||||
@ -4347,7 +4453,17 @@
|
||||
|
||||
// Prioritize revealing fragments
|
||||
if( nextFragment() === false ) {
|
||||
if( availableRoutes().down ) {
|
||||
|
||||
var routes = availableRoutes();
|
||||
|
||||
// When looping is enabled `routes.down` is always available
|
||||
// so we need a separate check for when we've reached the
|
||||
// end of a stack and should move horizontally
|
||||
if( routes.down && routes.right && config.loop && Reveal.isLastVerticalSlide( currentSlide ) ) {
|
||||
routes.down = false;
|
||||
}
|
||||
|
||||
if( routes.down ) {
|
||||
navigateDown();
|
||||
}
|
||||
else if( config.rtl ) {
|
||||
@ -4417,7 +4533,7 @@
|
||||
|
||||
// If there's a condition specified and it returns false,
|
||||
// ignore this event
|
||||
if( typeof config.keyboardCondition === 'function' && config.keyboardCondition() === false ) {
|
||||
if( typeof config.keyboardCondition === 'function' && config.keyboardCondition(event) === false ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4482,7 +4598,31 @@
|
||||
|
||||
}
|
||||
|
||||
// 2. System defined key bindings
|
||||
// 2. Registered custom key bindings
|
||||
if( triggered === false ) {
|
||||
|
||||
for( key in registeredKeyBindings ) {
|
||||
|
||||
// Check if this binding matches the pressed key
|
||||
if( parseInt( key, 10 ) === event.keyCode ) {
|
||||
|
||||
var action = registeredKeyBindings[ key ].callback;
|
||||
|
||||
// Callback function
|
||||
if( typeof action === 'function' ) {
|
||||
action.apply( null, [ event ] );
|
||||
}
|
||||
// String shortcuts to reveal.js API
|
||||
else if( typeof action === 'string' && typeof Reveal[ action ] === 'function' ) {
|
||||
Reveal[ action ].call();
|
||||
}
|
||||
|
||||
triggered = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. System defined key bindings
|
||||
if( triggered === false ) {
|
||||
|
||||
// Assume true and try to prove false
|
||||
@ -5213,7 +5353,7 @@
|
||||
// Returns true if we're currently on the last slide
|
||||
isLastSlide: function() {
|
||||
if( currentSlide ) {
|
||||
// Does this slide has next a sibling?
|
||||
// Does this slide have a next sibling?
|
||||
if( currentSlide.nextElementSibling ) return false;
|
||||
|
||||
// If it's vertical, does its parent have a next sibling?
|
||||
@ -5225,6 +5365,19 @@
|
||||
return false;
|
||||
},
|
||||
|
||||
// Returns true if we're on the last slide in the current
|
||||
// vertical stack
|
||||
isLastVerticalSlide: function() {
|
||||
if( currentSlide && isVerticalSlide( currentSlide ) ) {
|
||||
// Does this slide have a next sibling?
|
||||
if( currentSlide.nextElementSibling ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
// Checks if reveal.js has been loaded and is ready for use
|
||||
isReady: function() {
|
||||
return loaded;
|
||||
@ -5242,6 +5395,12 @@
|
||||
}
|
||||
},
|
||||
|
||||
// Adds a custom key binding
|
||||
addKeyBinding: addKeyBinding,
|
||||
|
||||
// Removes a custom key binding
|
||||
removeKeyBinding: removeKeyBinding,
|
||||
|
||||
// Programatically triggers a keyboard event
|
||||
triggerKey: function( keyCode ) {
|
||||
onDocumentKeyDown( { keyCode: keyCode } );
|
||||
|
Reference in New Issue
Block a user