App-revealup
view release on metacpan or search on metacpan
share/revealjs/js/controllers/controls.js view on Meta::CPAN
}
/**
* 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' );
}
}
}
}
}
destroy() {
this.unbind();
this.element.remove();
}
/**
* 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();
}
( run in 1.104 second using v1.01-cache-2.11-cpan-b16cb0d3907 )