new controls module for navigation arrows
parent
2a06e0d1e5
commit
c50ec00419
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,250 @@
|
||||||
|
import { toArray } from '../utils/util.js'
|
||||||
|
import { isMobile, isAndroid } from '../utils/device.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export default class Controls {
|
||||||
|
|
||||||
|
constructor( Reveal ) {
|
||||||
|
|
||||||
|
this.Reveal = Reveal;
|
||||||
|
|
||||||
|
this.onNavigateLeftClicked = this.onNavigateLeftClicked.bind( this );
|
||||||
|
this.onNavigateRightClicked = this.onNavigateRightClicked.bind( this );
|
||||||
|
this.onNavigateUpClicked = this.onNavigateUpClicked.bind( this );
|
||||||
|
this.onNavigateDownClicked = this.onNavigateDownClicked.bind( this );
|
||||||
|
this.onNavigatePrevClicked = this.onNavigatePrevClicked.bind( this );
|
||||||
|
this.onNavigateNextClicked = this.onNavigateNextClicked.bind( this );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
const rtl = this.Reveal.getConfig().rtl;
|
||||||
|
const revealElement = this.Reveal.getRevealElement();
|
||||||
|
|
||||||
|
this.element = document.createElement( 'aside' );
|
||||||
|
this.element.className = 'controls';
|
||||||
|
this.element.innerHTML =
|
||||||
|
`<button class="navigate-left" aria-label="${ rtl ? 'next slide' : 'previous slide' }"><div class="controls-arrow"></div></button>
|
||||||
|
<button class="navigate-right" aria-label="${ rtl ? 'previous slide' : 'next slide' }"><div class="controls-arrow"></div></button>
|
||||||
|
<button class="navigate-up" aria-label="above slide"><div class="controls-arrow"></div></button>
|
||||||
|
<button class="navigate-down" aria-label="below slide"><div class="controls-arrow"></div></button>`;
|
||||||
|
|
||||||
|
this.Reveal.getRevealElement().appendChild( this.element );
|
||||||
|
|
||||||
|
// There can be multiple instances of controls throughout the page
|
||||||
|
this.controlsLeft = toArray( revealElement.querySelectorAll( '.navigate-left' ) );
|
||||||
|
this.controlsRight = toArray( revealElement.querySelectorAll( '.navigate-right' ) );
|
||||||
|
this.controlsUp = toArray( revealElement.querySelectorAll( '.navigate-up' ) );
|
||||||
|
this.controlsDown = toArray( revealElement.querySelectorAll( '.navigate-down' ) );
|
||||||
|
this.controlsPrev = toArray( revealElement.querySelectorAll( '.navigate-prev' ) );
|
||||||
|
this.controlsNext = toArray( revealElement.querySelectorAll( '.navigate-next' ) );
|
||||||
|
|
||||||
|
// The left, right and down arrows in the standard reveal.js controls
|
||||||
|
this.controlsRightArrow = this.element.querySelector( '.navigate-right' );
|
||||||
|
this.controlsLeftArrow = this.element.querySelector( '.navigate-left' );
|
||||||
|
this.controlsDownArrow = this.element.querySelector( '.navigate-down' );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the reveal.js config is updated.
|
||||||
|
*/
|
||||||
|
configure( config, oldConfig ) {
|
||||||
|
|
||||||
|
this.element.style.display = config.controls ? 'block' : 'none';
|
||||||
|
|
||||||
|
this.element.setAttribute( 'data-controls-layout', config.controlsLayout );
|
||||||
|
this.element.setAttribute( 'data-controls-back-arrows', config.controlsBackArrows );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bind() {
|
||||||
|
|
||||||
|
// Listen to both touch and click events, in case the device
|
||||||
|
// supports both
|
||||||
|
let pointerEvents = [ 'touchstart', 'click' ];
|
||||||
|
|
||||||
|
// Only support touch for Android, fixes double navigations in
|
||||||
|
// stock browser
|
||||||
|
if( isAndroid ) {
|
||||||
|
pointerEvents = [ 'touchstart' ];
|
||||||
|
}
|
||||||
|
|
||||||
|
pointerEvents.forEach( eventName => {
|
||||||
|
this.controlsLeft.forEach( el => el.addEventListener( eventName, this.onNavigateLeftClicked, false ) );
|
||||||
|
this.controlsRight.forEach( el => el.addEventListener( eventName, this.onNavigateRightClicked, false ) );
|
||||||
|
this.controlsUp.forEach( el => el.addEventListener( eventName, this.onNavigateUpClicked, false ) );
|
||||||
|
this.controlsDown.forEach( el => el.addEventListener( eventName, this.onNavigateDownClicked, false ) );
|
||||||
|
this.controlsPrev.forEach( el => el.addEventListener( eventName, this.onNavigatePrevClicked, false ) );
|
||||||
|
this.controlsNext.forEach( el => el.addEventListener( eventName, this.onNavigateNextClicked, false ) );
|
||||||
|
} );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
unbind() {
|
||||||
|
|
||||||
|
[ 'touchstart', 'click' ].forEach( eventName => {
|
||||||
|
this.controlsLeft.forEach( el => el.removeEventListener( eventName, this.onNavigateLeftClicked, false ) );
|
||||||
|
this.controlsRight.forEach( el => el.removeEventListener( eventName, this.onNavigateRightClicked, false ) );
|
||||||
|
this.controlsUp.forEach( el => el.removeEventListener( eventName, this.onNavigateUpClicked, false ) );
|
||||||
|
this.controlsDown.forEach( el => el.removeEventListener( eventName, this.onNavigateDownClicked, false ) );
|
||||||
|
this.controlsPrev.forEach( el => el.removeEventListener( eventName, this.onNavigatePrevClicked, false ) );
|
||||||
|
this.controlsNext.forEach( el => el.removeEventListener( eventName, this.onNavigateNextClicked, false ) );
|
||||||
|
} );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the state of all control/navigation arrows.
|
||||||
|
*/
|
||||||
|
update() {
|
||||||
|
|
||||||
|
let routes = this.Reveal.availableRoutes();
|
||||||
|
|
||||||
|
// Remove the 'enabled' class from all directions
|
||||||
|
[...this.controlsLeft, ...this.controlsRight, ...this.controlsUp, ...this.controlsDown, ...this.controlsPrev, ...this.controlsNext].forEach( node => {
|
||||||
|
node.classList.remove( 'enabled', 'fragmented' );
|
||||||
|
|
||||||
|
// Set 'disabled' attribute on all directions
|
||||||
|
node.setAttribute( 'disabled', 'disabled' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Add the 'enabled' class to the available routes; remove 'disabled' attribute to enable buttons
|
||||||
|
if( routes.left ) this.controlsLeft.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
||||||
|
if( routes.right ) this.controlsRight.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
||||||
|
if( routes.up ) this.controlsUp.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
||||||
|
if( routes.down ) this.controlsDown.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
||||||
|
|
||||||
|
// Prev/next buttons
|
||||||
|
if( routes.left || routes.up ) this.controlsPrev.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
||||||
|
if( routes.right || routes.down ) this.controlsNext.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
||||||
|
|
||||||
|
// Highlight fragment directions
|
||||||
|
let currentSlide = this.Reveal.getCurrentSlide();
|
||||||
|
if( currentSlide ) {
|
||||||
|
|
||||||
|
let fragmentsRoutes = this.Reveal.fragments.availableRoutes();
|
||||||
|
|
||||||
|
// Always apply fragment decorator to prev/next buttons
|
||||||
|
if( fragmentsRoutes.prev ) this.controlsPrev.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
||||||
|
if( fragmentsRoutes.next ) this.controlsNext.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
||||||
|
|
||||||
|
// Apply fragment decorators to directional buttons based on
|
||||||
|
// what slide axis they are in
|
||||||
|
if( this.Reveal.isVerticalSlide( currentSlide ) ) {
|
||||||
|
if( fragmentsRoutes.prev ) this.controlsUp.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
||||||
|
if( fragmentsRoutes.next ) this.controlsDown.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if( fragmentsRoutes.prev ) this.controlsLeft.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
||||||
|
if( fragmentsRoutes.next ) this.controlsRight.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this.Reveal.getConfig().controlsTutorial ) {
|
||||||
|
|
||||||
|
let indices = this.Reveal.getIndices();
|
||||||
|
|
||||||
|
// Highlight control arrows with an animation to ensure
|
||||||
|
// that the viewer knows how to navigate
|
||||||
|
if( !this.Reveal.hasNavigatedVertically() && routes.down ) {
|
||||||
|
this.controlsDownArrow.classList.add( 'highlight' );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.controlsDownArrow.classList.remove( 'highlight' );
|
||||||
|
|
||||||
|
if( this.Reveal.getConfig().rtl ) {
|
||||||
|
|
||||||
|
if( !this.Reveal.hasNavigatedHorizontally() && routes.left && indices.v === 0 ) {
|
||||||
|
this.controlsLeftArrow.classList.add( 'highlight' );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.controlsLeftArrow.classList.remove( 'highlight' );
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if( !this.Reveal.hasNavigatedHorizontally() && routes.right && indices.v === 0 ) {
|
||||||
|
this.controlsRightArrow.classList.add( 'highlight' );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.controlsRightArrow.classList.remove( 'highlight' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handlers for navigation control buttons.
|
||||||
|
*/
|
||||||
|
onNavigateLeftClicked( event ) {
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
this.Reveal.onUserInput();
|
||||||
|
|
||||||
|
if( this.Reveal.getConfig().navigationMode === 'linear' ) {
|
||||||
|
this.Reveal.prev();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.Reveal.left();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onNavigateRightClicked( event ) {
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
this.Reveal.onUserInput();
|
||||||
|
|
||||||
|
if( this.Reveal.getConfig().navigationMode === 'linear' ) {
|
||||||
|
this.Reveal.next();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.Reveal.right();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onNavigateUpClicked( event ) {
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
this.Reveal.onUserInput();
|
||||||
|
|
||||||
|
this.Reveal.up();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onNavigateDownClicked( event ) {
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
this.Reveal.onUserInput();
|
||||||
|
|
||||||
|
this.Reveal.down();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onNavigatePrevClicked( event ) {
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
this.Reveal.onUserInput();
|
||||||
|
|
||||||
|
this.Reveal.prev();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onNavigateNextClicked( event ) {
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
this.Reveal.onUserInput();
|
||||||
|
|
||||||
|
this.Reveal.next();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ export default class Fragments {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called whenever the reveal.js config is updated.
|
* Called when the reveal.js config is updated.
|
||||||
*/
|
*/
|
||||||
configure( config, oldConfig ) {
|
configure( config, oldConfig ) {
|
||||||
|
|
||||||
|
@ -331,7 +331,8 @@ export default class Fragments {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Reveal.updateControls();
|
this.Reveal.controls.update();
|
||||||
|
|
||||||
this.Reveal.updateProgress();
|
this.Reveal.updateProgress();
|
||||||
|
|
||||||
if( this.Reveal.getConfig().fragmentInURL ) {
|
if( this.Reveal.getConfig().fragmentInURL ) {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { extend, toArray } from '../utils/util.js'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Handles the showing and
|
||||||
*/
|
*/
|
||||||
export default class Notes {
|
export default class Notes {
|
||||||
|
|
||||||
|
@ -81,7 +79,7 @@ export default class Notes {
|
||||||
*
|
*
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
isSpeakerNotes() {
|
isSpeakerNotesWindow() {
|
||||||
|
|
||||||
return !!window.location.search.match( /receiver/gi );
|
return !!window.location.search.match( /receiver/gi );
|
||||||
|
|
||||||
|
|
190
js/reveal.js
190
js/reveal.js
|
@ -6,13 +6,14 @@ import Fragments from './controllers/fragments.js'
|
||||||
import Overview from './controllers/overview.js'
|
import Overview from './controllers/overview.js'
|
||||||
import Keyboard from './controllers/keyboard.js'
|
import Keyboard from './controllers/keyboard.js'
|
||||||
import Location from './controllers/location.js'
|
import Location from './controllers/location.js'
|
||||||
|
import Controls from './controllers/controls.js'
|
||||||
import Plugins from './controllers/plugins.js'
|
import Plugins from './controllers/plugins.js'
|
||||||
import Print from './controllers/print.js'
|
import Print from './controllers/print.js'
|
||||||
import Touch from './controllers/touch.js'
|
import Touch from './controllers/touch.js'
|
||||||
import Notes from './controllers/notes.js'
|
import Notes from './controllers/notes.js'
|
||||||
import Playback from './components/playback.js'
|
import Playback from './components/playback.js'
|
||||||
import defaultConfig from './config.js'
|
import defaultConfig from './config.js'
|
||||||
import { isMobile, isChrome, isAndroid, supportsZoom } from './utils/device.js'
|
import { isMobile, isChrome, supportsZoom } from './utils/device.js'
|
||||||
import {
|
import {
|
||||||
SLIDES_SELECTOR,
|
SLIDES_SELECTOR,
|
||||||
HORIZONTAL_SLIDES_SELECTOR,
|
HORIZONTAL_SLIDES_SELECTOR,
|
||||||
|
@ -58,10 +59,12 @@ export default function( revealElement, options ) {
|
||||||
currentSlide,
|
currentSlide,
|
||||||
|
|
||||||
// Remember which directions that the user has navigated towards
|
// Remember which directions that the user has navigated towards
|
||||||
hasNavigatedHorizontally = false,
|
navigationHistory = {
|
||||||
hasNavigatedVertically = false,
|
hasNavigatedHorizontally: false,
|
||||||
|
hasNavigatedVertically: false
|
||||||
|
},
|
||||||
|
|
||||||
// Slides may hold a data-state attribute which we pick up and apply
|
// Slides may have a data-state attribute which we pick up and apply
|
||||||
// as a class to the body. This list contains the combined state of
|
// as a class to the body. This list contains the combined state of
|
||||||
// all current slides.
|
// all current slides.
|
||||||
state = [],
|
state = [],
|
||||||
|
@ -80,6 +83,7 @@ export default function( revealElement, options ) {
|
||||||
overview = new Overview( Reveal ),
|
overview = new Overview( Reveal ),
|
||||||
keyboard = new Keyboard( Reveal ),
|
keyboard = new Keyboard( Reveal ),
|
||||||
location = new Location( Reveal ),
|
location = new Location( Reveal ),
|
||||||
|
controls = new Controls( Reveal ),
|
||||||
plugins = new Plugins( Reveal ),
|
plugins = new Plugins( Reveal ),
|
||||||
print = new Print( Reveal ),
|
print = new Print( Reveal ),
|
||||||
touch = new Touch( Reveal ),
|
touch = new Touch( Reveal ),
|
||||||
|
@ -223,45 +227,22 @@ export default function( revealElement, options ) {
|
||||||
dom.wrapper.classList.remove( 'no-hover' );
|
dom.wrapper.classList.remove( 'no-hover' );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slide backgrounds
|
|
||||||
backgrounds.render();
|
|
||||||
|
|
||||||
// Progress bar
|
// Progress bar
|
||||||
dom.progress = createSingletonNode( dom.wrapper, 'div', 'progress', '<span></span>' );
|
dom.progress = createSingletonNode( dom.wrapper, 'div', 'progress', '<span></span>' );
|
||||||
dom.progressbar = dom.progress.querySelector( 'span' );
|
dom.progressbar = dom.progress.querySelector( 'span' );
|
||||||
|
|
||||||
// Arrow controls
|
backgrounds.render();
|
||||||
dom.controls = createSingletonNode( dom.wrapper, 'aside', 'controls',
|
|
||||||
`<button class="navigate-left" aria-label="${ config.rtl ? 'next slide' : 'previous slide' }"><div class="controls-arrow"></div></button>
|
|
||||||
<button class="navigate-right" aria-label="${ config.rtl ? 'previous slide' : 'next slide' }"><div class="controls-arrow"></div></button>
|
|
||||||
<button class="navigate-up" aria-label="above slide"><div class="controls-arrow"></div></button>
|
|
||||||
<button class="navigate-down" aria-label="below slide"><div class="controls-arrow"></div></button>` );
|
|
||||||
|
|
||||||
// Slide number
|
|
||||||
slideNumber.render();
|
slideNumber.render();
|
||||||
|
controls.render();
|
||||||
// Slide notes
|
|
||||||
notes.render();
|
notes.render();
|
||||||
|
|
||||||
// Overlay graphic which is displayed during the paused mode
|
// Overlay graphic which is displayed during the paused mode
|
||||||
dom.pauseOverlay = createSingletonNode( dom.wrapper, 'div', 'pause-overlay', config.controls ? '<button class="resume-button">Resume presentation</button>' : null );
|
dom.pauseOverlay = createSingletonNode( dom.wrapper, 'div', 'pause-overlay', config.controls ? '<button class="resume-button">Resume presentation</button>' : null );
|
||||||
|
|
||||||
dom.wrapper.setAttribute( 'role', 'application' );
|
|
||||||
|
|
||||||
// There can be multiple instances of controls throughout the page
|
|
||||||
dom.controlsLeft = toArray( dom.wrapper.querySelectorAll( '.navigate-left' ) );
|
|
||||||
dom.controlsRight = toArray( dom.wrapper.querySelectorAll( '.navigate-right' ) );
|
|
||||||
dom.controlsUp = toArray( dom.wrapper.querySelectorAll( '.navigate-up' ) );
|
|
||||||
dom.controlsDown = toArray( dom.wrapper.querySelectorAll( '.navigate-down' ) );
|
|
||||||
dom.controlsPrev = toArray( dom.wrapper.querySelectorAll( '.navigate-prev' ) );
|
|
||||||
dom.controlsNext = toArray( dom.wrapper.querySelectorAll( '.navigate-next' ) );
|
|
||||||
|
|
||||||
// The left, right and down arrows in the standard reveal.js controls
|
|
||||||
dom.controlsRightArrow = dom.controls.querySelector( '.navigate-right' );
|
|
||||||
dom.controlsLeftArrow = dom.controls.querySelector( '.navigate-left' );
|
|
||||||
dom.controlsDownArrow = dom.controls.querySelector( '.navigate-down' );
|
|
||||||
|
|
||||||
dom.statusElement = createStatusElement();
|
dom.statusElement = createStatusElement();
|
||||||
|
|
||||||
|
dom.wrapper.setAttribute( 'role', 'application' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -423,12 +404,8 @@ export default function( revealElement, options ) {
|
||||||
dom.wrapper.setAttribute( 'data-transition-speed', config.transitionSpeed );
|
dom.wrapper.setAttribute( 'data-transition-speed', config.transitionSpeed );
|
||||||
dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition );
|
dom.wrapper.setAttribute( 'data-background-transition', config.backgroundTransition );
|
||||||
|
|
||||||
dom.controls.style.display = config.controls ? 'block' : 'none';
|
|
||||||
dom.progress.style.display = config.progress ? 'block' : 'none';
|
dom.progress.style.display = config.progress ? 'block' : 'none';
|
||||||
|
|
||||||
dom.controls.setAttribute( 'data-controls-layout', config.controlsLayout );
|
|
||||||
dom.controls.setAttribute( 'data-controls-back-arrows', config.controlsBackArrows );
|
|
||||||
|
|
||||||
if( config.shuffle ) {
|
if( config.shuffle ) {
|
||||||
shuffle();
|
shuffle();
|
||||||
}
|
}
|
||||||
|
@ -511,9 +488,10 @@ export default function( revealElement, options ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
notes.configure( config, oldConfig );
|
notes.configure( config, oldConfig );
|
||||||
|
controls.configure( config, oldConfig );
|
||||||
|
keyboard.configure( config, oldConfig );
|
||||||
fragments.configure( config, oldConfig );
|
fragments.configure( config, oldConfig );
|
||||||
slideNumber.configure( config, oldConfig );
|
slideNumber.configure( config, oldConfig );
|
||||||
keyboard.configure( config, oldConfig );
|
|
||||||
|
|
||||||
sync();
|
sync();
|
||||||
|
|
||||||
|
@ -531,6 +509,7 @@ export default function( revealElement, options ) {
|
||||||
|
|
||||||
if( config.touch ) touch.bind();
|
if( config.touch ) touch.bind();
|
||||||
if( config.keyboard ) keyboard.bind();
|
if( config.keyboard ) keyboard.bind();
|
||||||
|
controls.bind();
|
||||||
|
|
||||||
if( config.progress && dom.progress ) {
|
if( config.progress && dom.progress ) {
|
||||||
dom.progress.addEventListener( 'click', onProgressClicked, false );
|
dom.progress.addEventListener( 'click', onProgressClicked, false );
|
||||||
|
@ -542,25 +521,6 @@ export default function( revealElement, options ) {
|
||||||
document.addEventListener( 'visibilitychange', onPageVisibilityChange, false );
|
document.addEventListener( 'visibilitychange', onPageVisibilityChange, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listen to both touch and click events, in case the device
|
|
||||||
// supports both
|
|
||||||
let pointerEvents = [ 'touchstart', 'click' ];
|
|
||||||
|
|
||||||
// Only support touch for Android, fixes double navigations in
|
|
||||||
// stock browser
|
|
||||||
if( isAndroid ) {
|
|
||||||
pointerEvents = [ 'touchstart' ];
|
|
||||||
}
|
|
||||||
|
|
||||||
pointerEvents.forEach( eventName => {
|
|
||||||
dom.controlsLeft.forEach( el => el.addEventListener( eventName, onNavigateLeftClicked, false ) );
|
|
||||||
dom.controlsRight.forEach( el => el.addEventListener( eventName, onNavigateRightClicked, false ) );
|
|
||||||
dom.controlsUp.forEach( el => el.addEventListener( eventName, onNavigateUpClicked, false ) );
|
|
||||||
dom.controlsDown.forEach( el => el.addEventListener( eventName, onNavigateDownClicked, false ) );
|
|
||||||
dom.controlsPrev.forEach( el => el.addEventListener( eventName, onNavigatePrevClicked, false ) );
|
|
||||||
dom.controlsNext.forEach( el => el.addEventListener( eventName, onNavigateNextClicked, false ) );
|
|
||||||
} );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -572,6 +532,7 @@ export default function( revealElement, options ) {
|
||||||
|
|
||||||
touch.unbind();
|
touch.unbind();
|
||||||
keyboard.unbind();
|
keyboard.unbind();
|
||||||
|
controls.unbind();
|
||||||
|
|
||||||
window.removeEventListener( 'hashchange', onWindowHashChange, false );
|
window.removeEventListener( 'hashchange', onWindowHashChange, false );
|
||||||
window.removeEventListener( 'resize', onWindowResize, false );
|
window.removeEventListener( 'resize', onWindowResize, false );
|
||||||
|
@ -582,15 +543,6 @@ export default function( revealElement, options ) {
|
||||||
dom.progress.removeEventListener( 'click', onProgressClicked, false );
|
dom.progress.removeEventListener( 'click', onProgressClicked, false );
|
||||||
}
|
}
|
||||||
|
|
||||||
[ 'touchstart', 'click' ].forEach( eventName => {
|
|
||||||
dom.controlsLeft.forEach( el => el.removeEventListener( eventName, onNavigateLeftClicked, false ) );
|
|
||||||
dom.controlsRight.forEach( el => el.removeEventListener( eventName, onNavigateRightClicked, false ) );
|
|
||||||
dom.controlsUp.forEach( el => el.removeEventListener( eventName, onNavigateUpClicked, false ) );
|
|
||||||
dom.controlsDown.forEach( el => el.removeEventListener( eventName, onNavigateDownClicked, false ) );
|
|
||||||
dom.controlsPrev.forEach( el => el.removeEventListener( eventName, onNavigatePrevClicked, false ) );
|
|
||||||
dom.controlsNext.forEach( el => el.removeEventListener( eventName, onNavigateNextClicked, false ) );
|
|
||||||
} );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1397,9 +1349,9 @@ export default function( revealElement, options ) {
|
||||||
// Announce the current slide contents to screen readers
|
// Announce the current slide contents to screen readers
|
||||||
announceStatus( getStatusText( currentSlide ) );
|
announceStatus( getStatusText( currentSlide ) );
|
||||||
|
|
||||||
updateControls();
|
|
||||||
updateProgress();
|
updateProgress();
|
||||||
|
|
||||||
|
controls.update();
|
||||||
notes.update();
|
notes.update();
|
||||||
backgrounds.update();
|
backgrounds.update();
|
||||||
backgrounds.updateParallax();
|
backgrounds.updateParallax();
|
||||||
|
@ -1461,7 +1413,8 @@ export default function( revealElement, options ) {
|
||||||
|
|
||||||
fragments.sortAll();
|
fragments.sortAll();
|
||||||
|
|
||||||
updateControls();
|
controls.update();
|
||||||
|
|
||||||
updateProgress();
|
updateProgress();
|
||||||
updateSlidesVisibility();
|
updateSlidesVisibility();
|
||||||
|
|
||||||
|
@ -1770,84 +1723,6 @@ export default function( revealElement, options ) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the state of all control/navigation arrows.
|
|
||||||
*/
|
|
||||||
function updateControls() {
|
|
||||||
|
|
||||||
let routes = availableRoutes();
|
|
||||||
let fragmentsRoutes = fragments.availableRoutes();
|
|
||||||
|
|
||||||
// Remove the 'enabled' class from all directions
|
|
||||||
[...dom.controlsLeft, ...dom.controlsRight, ...dom.controlsUp, ...dom.controlsDown, ...dom.controlsPrev, ...dom.controlsNext].forEach( node => {
|
|
||||||
node.classList.remove( 'enabled', 'fragmented' );
|
|
||||||
|
|
||||||
// Set 'disabled' attribute on all directions
|
|
||||||
node.setAttribute( 'disabled', 'disabled' );
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Add the 'enabled' class to the available routes; remove 'disabled' attribute to enable buttons
|
|
||||||
if( routes.left ) dom.controlsLeft.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
|
||||||
if( routes.right ) dom.controlsRight.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
|
||||||
if( routes.up ) dom.controlsUp.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
|
||||||
if( routes.down ) dom.controlsDown.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
|
||||||
|
|
||||||
// Prev/next buttons
|
|
||||||
if( routes.left || routes.up ) dom.controlsPrev.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
|
||||||
if( routes.right || routes.down ) dom.controlsNext.forEach( el => { el.classList.add( 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
|
||||||
|
|
||||||
// Highlight fragment directions
|
|
||||||
if( currentSlide ) {
|
|
||||||
|
|
||||||
// Always apply fragment decorator to prev/next buttons
|
|
||||||
if( fragmentsRoutes.prev ) dom.controlsPrev.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
|
||||||
if( fragmentsRoutes.next ) dom.controlsNext.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
|
||||||
|
|
||||||
// Apply fragment decorators to directional buttons based on
|
|
||||||
// what slide axis they are in
|
|
||||||
if( isVerticalSlide( currentSlide ) ) {
|
|
||||||
if( fragmentsRoutes.prev ) dom.controlsUp.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
|
||||||
if( fragmentsRoutes.next ) dom.controlsDown.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if( fragmentsRoutes.prev ) dom.controlsLeft.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
|
||||||
if( fragmentsRoutes.next ) dom.controlsRight.forEach( el => { el.classList.add( 'fragmented', 'enabled' ); el.removeAttribute( 'disabled' ); } );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if( config.controlsTutorial ) {
|
|
||||||
|
|
||||||
// Highlight control arrows with an animation to ensure
|
|
||||||
// that the viewer knows how to navigate
|
|
||||||
if( !hasNavigatedVertically && routes.down ) {
|
|
||||||
dom.controlsDownArrow.classList.add( 'highlight' );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dom.controlsDownArrow.classList.remove( 'highlight' );
|
|
||||||
|
|
||||||
if( config.rtl ) {
|
|
||||||
|
|
||||||
if( !hasNavigatedHorizontally && routes.left && indexv === 0 ) {
|
|
||||||
dom.controlsLeftArrow.classList.add( 'highlight' );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dom.controlsLeftArrow.classList.remove( 'highlight' );
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if( !hasNavigatedHorizontally && routes.right && indexv === 0 ) {
|
|
||||||
dom.controlsRightArrow.classList.add( 'highlight' );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dom.controlsRightArrow.classList.remove( 'highlight' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine what available routes there are for navigation.
|
* Determine what available routes there are for navigation.
|
||||||
*
|
*
|
||||||
|
@ -2322,7 +2197,7 @@ export default function( revealElement, options ) {
|
||||||
|
|
||||||
function navigateLeft() {
|
function navigateLeft() {
|
||||||
|
|
||||||
hasNavigatedHorizontally = true;
|
navigationHistory.hasNavigatedHorizontally = true;
|
||||||
|
|
||||||
// Reverse for RTL
|
// Reverse for RTL
|
||||||
if( config.rtl ) {
|
if( config.rtl ) {
|
||||||
|
@ -2339,7 +2214,7 @@ export default function( revealElement, options ) {
|
||||||
|
|
||||||
function navigateRight() {
|
function navigateRight() {
|
||||||
|
|
||||||
hasNavigatedHorizontally = true;
|
navigationHistory.hasNavigatedHorizontally = true;
|
||||||
|
|
||||||
// Reverse for RTL
|
// Reverse for RTL
|
||||||
if( config.rtl ) {
|
if( config.rtl ) {
|
||||||
|
@ -2365,7 +2240,7 @@ export default function( revealElement, options ) {
|
||||||
|
|
||||||
function navigateDown() {
|
function navigateDown() {
|
||||||
|
|
||||||
hasNavigatedVertically = true;
|
navigationHistory.hasNavigatedVertically = true;
|
||||||
|
|
||||||
// Prioritize revealing fragments
|
// Prioritize revealing fragments
|
||||||
if( ( overview.isActive() || fragments.next() === false ) && availableRoutes().down ) {
|
if( ( overview.isActive() || fragments.next() === false ) && availableRoutes().down ) {
|
||||||
|
@ -2413,8 +2288,8 @@ export default function( revealElement, options ) {
|
||||||
*/
|
*/
|
||||||
function navigateNext() {
|
function navigateNext() {
|
||||||
|
|
||||||
hasNavigatedHorizontally = true;
|
navigationHistory.hasNavigatedHorizontally = true;
|
||||||
hasNavigatedVertically = true;
|
navigationHistory.hasNavigatedVertically = true;
|
||||||
|
|
||||||
// Prioritize revealing fragments
|
// Prioritize revealing fragments
|
||||||
if( fragments.next() === false ) {
|
if( fragments.next() === false ) {
|
||||||
|
@ -2525,16 +2400,6 @@ export default function( revealElement, options ) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Event handler for navigation control buttons.
|
|
||||||
*/
|
|
||||||
function onNavigateLeftClicked( event ) { event.preventDefault(); onUserInput(); config.navigationMode === 'linear' ? navigatePrev() : navigateLeft(); }
|
|
||||||
function onNavigateRightClicked( event ) { event.preventDefault(); onUserInput(); config.navigationMode === 'linear' ? navigateNext() : navigateRight(); }
|
|
||||||
function onNavigateUpClicked( event ) { event.preventDefault(); onUserInput(); navigateUp(); }
|
|
||||||
function onNavigateDownClicked( event ) { event.preventDefault(); onUserInput(); navigateDown(); }
|
|
||||||
function onNavigatePrevClicked( event ) { event.preventDefault(); onUserInput(); navigatePrev(); }
|
|
||||||
function onNavigateNextClicked( event ) { event.preventDefault(); onUserInput(); navigateNext(); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for the window level 'hashchange' event.
|
* Handler for the window level 'hashchange' event.
|
||||||
*
|
*
|
||||||
|
@ -2697,7 +2562,7 @@ export default function( revealElement, options ) {
|
||||||
// State checks
|
// State checks
|
||||||
isPaused,
|
isPaused,
|
||||||
isAutoSliding,
|
isAutoSliding,
|
||||||
isSpeakerNotes: notes.isSpeakerNotes.bind( notes ),
|
isSpeakerNotes: notes.isSpeakerNotesWindow.bind( notes ),
|
||||||
isOverview: overview.isActive.bind( overview ),
|
isOverview: overview.isActive.bind( overview ),
|
||||||
isPrintingPDF: print.isPrintingPDF.bind( print ),
|
isPrintingPDF: print.isPrintingPDF.bind( print ),
|
||||||
|
|
||||||
|
@ -2751,6 +2616,9 @@ export default function( revealElement, options ) {
|
||||||
hasHorizontalSlides,
|
hasHorizontalSlides,
|
||||||
hasVerticalSlides,
|
hasVerticalSlides,
|
||||||
|
|
||||||
|
hasNavigatedHorizontally: () => navigationHistory.hasNavigatedHorizontally,
|
||||||
|
hasNavigatedVertically: () => navigationHistory.hasNavigatedVertically,
|
||||||
|
|
||||||
// Adds/removes a custom key binding
|
// Adds/removes a custom key binding
|
||||||
addKeyBinding: keyboard.addKeyBinding.bind( keyboard ),
|
addKeyBinding: keyboard.addKeyBinding.bind( keyboard ),
|
||||||
removeKeyBinding: keyboard.removeKeyBinding.bind( keyboard ),
|
removeKeyBinding: keyboard.removeKeyBinding.bind( keyboard ),
|
||||||
|
@ -2800,6 +2668,7 @@ export default function( revealElement, options ) {
|
||||||
getStatusText,
|
getStatusText,
|
||||||
|
|
||||||
print,
|
print,
|
||||||
|
controls,
|
||||||
location,
|
location,
|
||||||
overview,
|
overview,
|
||||||
fragments,
|
fragments,
|
||||||
|
@ -2808,7 +2677,6 @@ export default function( revealElement, options ) {
|
||||||
|
|
||||||
onUserInput,
|
onUserInput,
|
||||||
closeOverlay,
|
closeOverlay,
|
||||||
updateControls,
|
|
||||||
updateProgress,
|
updateProgress,
|
||||||
updateSlidesVisibility,
|
updateSlidesVisibility,
|
||||||
layoutSlideContents,
|
layoutSlideContents,
|
||||||
|
|
Loading…
Reference in New Issue