aboutsummaryrefslogtreecommitdiff
path: root/js/reveal.js
diff options
context:
space:
mode:
authorHakim El Hattab <hakim.elhattab@gmail.com>2020-03-16 13:53:23 +0100
committerHakim El Hattab <hakim.elhattab@gmail.com>2020-03-16 13:53:23 +0100
commitc50ec00419d8abfcfb1e5a2075f28d87fb83232b (patch)
treecbe914f5f7ddf0d44b9dfa1dee690f149b61b880 /js/reveal.js
parent2a06e0d1e5de95ecf3b5f1a8ae80b72975a44632 (diff)
downloadfosdem-2021-minimalism-presentation-c50ec00419d8abfcfb1e5a2075f28d87fb83232b.tar
fosdem-2021-minimalism-presentation-c50ec00419d8abfcfb1e5a2075f28d87fb83232b.tar.gz
new controls module for navigation arrows
Diffstat (limited to 'js/reveal.js')
-rw-r--r--js/reveal.js190
1 files changed, 29 insertions, 161 deletions
diff --git a/js/reveal.js b/js/reveal.js
index 44e009b..9509fea 100644
--- a/js/reveal.js
+++ b/js/reveal.js
@@ -6,13 +6,14 @@ import Fragments from './controllers/fragments.js'
import Overview from './controllers/overview.js'
import Keyboard from './controllers/keyboard.js'
import Location from './controllers/location.js'
+import Controls from './controllers/controls.js'
import Plugins from './controllers/plugins.js'
import Print from './controllers/print.js'
import Touch from './controllers/touch.js'
import Notes from './controllers/notes.js'
import Playback from './components/playback.js'
import defaultConfig from './config.js'
-import { isMobile, isChrome, isAndroid, supportsZoom } from './utils/device.js'
+import { isMobile, isChrome, supportsZoom } from './utils/device.js'
import {
SLIDES_SELECTOR,
HORIZONTAL_SLIDES_SELECTOR,
@@ -58,10 +59,12 @@ export default function( revealElement, options ) {
currentSlide,
// Remember which directions that the user has navigated towards
- hasNavigatedHorizontally = false,
- hasNavigatedVertically = false,
+ navigationHistory = {
+ 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
// all current slides.
state = [],
@@ -80,6 +83,7 @@ export default function( revealElement, options ) {
overview = new Overview( Reveal ),
keyboard = new Keyboard( Reveal ),
location = new Location( Reveal ),
+ controls = new Controls( Reveal ),
plugins = new Plugins( Reveal ),
print = new Print( Reveal ),
touch = new Touch( Reveal ),
@@ -223,45 +227,22 @@ export default function( revealElement, options ) {
dom.wrapper.classList.remove( 'no-hover' );
}
- // Slide backgrounds
- backgrounds.render();
// Progress bar
dom.progress = createSingletonNode( dom.wrapper, 'div', 'progress', '<span></span>' );
dom.progressbar = dom.progress.querySelector( 'span' );
- // Arrow controls
- 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
+ backgrounds.render();
slideNumber.render();
-
- // Slide notes
+ controls.render();
notes.render();
// 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.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.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-background-transition', config.backgroundTransition );
- dom.controls.style.display = config.controls ? '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 ) {
shuffle();
}
@@ -511,9 +488,10 @@ export default function( revealElement, options ) {
}
notes.configure( config, oldConfig );
+ controls.configure( config, oldConfig );
+ keyboard.configure( config, oldConfig );
fragments.configure( config, oldConfig );
slideNumber.configure( config, oldConfig );
- keyboard.configure( config, oldConfig );
sync();
@@ -531,6 +509,7 @@ export default function( revealElement, options ) {
if( config.touch ) touch.bind();
if( config.keyboard ) keyboard.bind();
+ controls.bind();
if( config.progress && dom.progress ) {
dom.progress.addEventListener( 'click', onProgressClicked, false );
@@ -542,25 +521,6 @@ export default function( revealElement, options ) {
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();
keyboard.unbind();
+ controls.unbind();
window.removeEventListener( 'hashchange', onWindowHashChange, false );
window.removeEventListener( 'resize', onWindowResize, false );
@@ -582,15 +543,6 @@ export default function( revealElement, options ) {
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
announceStatus( getStatusText( currentSlide ) );
- updateControls();
updateProgress();
+ controls.update();
notes.update();
backgrounds.update();
backgrounds.updateParallax();
@@ -1461,7 +1413,8 @@ export default function( revealElement, options ) {
fragments.sortAll();
- updateControls();
+ controls.update();
+
updateProgress();
updateSlidesVisibility();
@@ -1771,84 +1724,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.
*
* @return {{left: boolean, right: boolean, up: boolean, down: boolean}}
@@ -2322,7 +2197,7 @@ export default function( revealElement, options ) {
function navigateLeft() {
- hasNavigatedHorizontally = true;
+ navigationHistory.hasNavigatedHorizontally = true;
// Reverse for RTL
if( config.rtl ) {
@@ -2339,7 +2214,7 @@ export default function( revealElement, options ) {
function navigateRight() {
- hasNavigatedHorizontally = true;
+ navigationHistory.hasNavigatedHorizontally = true;
// Reverse for RTL
if( config.rtl ) {
@@ -2365,7 +2240,7 @@ export default function( revealElement, options ) {
function navigateDown() {
- hasNavigatedVertically = true;
+ navigationHistory.hasNavigatedVertically = true;
// Prioritize revealing fragments
if( ( overview.isActive() || fragments.next() === false ) && availableRoutes().down ) {
@@ -2413,8 +2288,8 @@ export default function( revealElement, options ) {
*/
function navigateNext() {
- hasNavigatedHorizontally = true;
- hasNavigatedVertically = true;
+ navigationHistory.hasNavigatedHorizontally = true;
+ navigationHistory.hasNavigatedVertically = true;
// Prioritize revealing fragments
if( fragments.next() === false ) {
@@ -2526,16 +2401,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.
*
* @param {object} [event]
@@ -2697,7 +2562,7 @@ export default function( revealElement, options ) {
// State checks
isPaused,
isAutoSliding,
- isSpeakerNotes: notes.isSpeakerNotes.bind( notes ),
+ isSpeakerNotes: notes.isSpeakerNotesWindow.bind( notes ),
isOverview: overview.isActive.bind( overview ),
isPrintingPDF: print.isPrintingPDF.bind( print ),
@@ -2751,6 +2616,9 @@ export default function( revealElement, options ) {
hasHorizontalSlides,
hasVerticalSlides,
+ hasNavigatedHorizontally: () => navigationHistory.hasNavigatedHorizontally,
+ hasNavigatedVertically: () => navigationHistory.hasNavigatedVertically,
+
// Adds/removes a custom key binding
addKeyBinding: keyboard.addKeyBinding.bind( keyboard ),
removeKeyBinding: keyboard.removeKeyBinding.bind( keyboard ),
@@ -2800,6 +2668,7 @@ export default function( revealElement, options ) {
getStatusText,
print,
+ controls,
location,
overview,
fragments,
@@ -2808,7 +2677,6 @@ export default function( revealElement, options ) {
onUserInput,
closeOverlay,
- updateControls,
updateProgress,
updateSlidesVisibility,
layoutSlideContents,