hakimel/reveal.js

View on GitHub
js/controllers/focus.js

Summary

Maintainability
B
4 hrs
Test Coverage
import { closest } from '../utils/util.js'

/**
 * Manages focus when a presentation is embedded. This
 * helps us only capture keyboard from the presentation
 * a user is currently interacting with in a page where
 * multiple presentations are embedded.
 */

const STATE_FOCUS = 'focus';
const STATE_BLUR = 'blur';

export default class Focus {

    constructor( Reveal ) {

        this.Reveal = Reveal;

        this.onRevealPointerDown = this.onRevealPointerDown.bind( this );
        this.onDocumentPointerDown = this.onDocumentPointerDown.bind( this );

    }

    /**
     * Called when the reveal.js config is updated.
     */
    configure( config, oldConfig ) {

        if( config.embedded ) {
            this.blur();
        }
        else {
            this.focus();
            this.unbind();
        }

    }

    bind() {

        if( this.Reveal.getConfig().embedded ) {
            this.Reveal.getRevealElement().addEventListener( 'pointerdown', this.onRevealPointerDown, false );
        }

    }

    unbind() {

        this.Reveal.getRevealElement().removeEventListener( 'pointerdown', this.onRevealPointerDown, false );
        document.removeEventListener( 'pointerdown', this.onDocumentPointerDown, false );

    }

    focus() {

        if( this.state !== STATE_FOCUS ) {
            this.Reveal.getRevealElement().classList.add( 'focused' );
            document.addEventListener( 'pointerdown', this.onDocumentPointerDown, false );
        }

        this.state = STATE_FOCUS;

    }

    blur() {

        if( this.state !== STATE_BLUR ) {
            this.Reveal.getRevealElement().classList.remove( 'focused' );
            document.removeEventListener( 'pointerdown', this.onDocumentPointerDown, false );
        }

        this.state = STATE_BLUR;

    }

    isFocused() {

        return this.state === STATE_FOCUS;

    }

    destroy() {

        this.Reveal.getRevealElement().classList.remove( 'focused' );

    }

    onRevealPointerDown( event ) {

        this.focus();

    }

    onDocumentPointerDown( event ) {

        let revealElement = closest( event.target, '.reveal' );
        if( !revealElement || revealElement !== this.Reveal.getRevealElement() ) {
            this.blur();
        }

    }

}