indentlabs/notebook

View on GitHub
app/assets/javascripts/keyboardControls.js

Summary

Maintainability
A
2 hrs
Test Coverage
// want to add new keyboard controls? Go to keyboardControllsMapping.js

function keyboardControlManager ( keyboardControls ) {
    /**
     * Listens to the keyboard events and pushes items into the stack
     *
     * @param {KeyboardEvent} event
     */
    function keyListener ( event ) {
        // must ignore modifier keys
        var ignored_keys = [
            16, // shift
            17, // osx control
            18, // osx alt/option
            91 // osx CMD / win CTRL
        ];

        if( ignored_keys.indexOf(event.keyCode) !== -1 ){
            return;
        }

        // must ignore if currently focused into a text field
        if ( document.querySelector("input[type=\"text\"]:focus, textarea:focus") ){
            return;
        }

        // if not modifier, continue
        stackManager.add({
            "key" : event.keyCode,
            "shiftKey" : event.shiftKey,
            "ctrlKey" : event.ctrlKey
        });
    }

    /**
     * on every stack update, we compare against our keyboardControls object
     *
     * @param {any} keyStackArray
     *
     * @returns boolean;
     */
    function onStackUpdate ( keyStackArray ){
        for ( var i in keyboardControls ){
            var kc = keyboardControls[i];

            if(_.isEqual(kc.input, keyStackArray)){
                kc.result();
                return true;
            }
        };

        return false;
    }

    document.addEventListener("keyup", keyListener);
    var stackManager = KeyboardControlStackManager(1000, onStackUpdate);
}

/**
 *
 *
 * @param {number} entryTime The time required between keypresses
 * @param {function} stackEvaluationFunction the function to evaluate the stack once it's finalized. should return TRUE if a match is found
 *
 */
function KeyboardControlStackManager( entryTime, stackEvaluationFunction ) {
    var entryTime = entryTime;
    var timer = undefined;
    var currentStack = [];
    var stackEvaluationFunction = stackEvaluationFunction;

    /**
     * Adds an element to the currentStack
     *
     * @param {{key : number, shiftKey : boolean, ctrlKey : boolean}} standardKeyStructure
     *
     */
    function add ( standardKeyStructure ) {
        currentStack.push( standardKeyStructure );
        if( timer ){
            clearTimeout(timer);
            timer = undefined;
        }
        timer = setTimeout(function () {
            timerComplete();
        },entryTime);

        // if it's found, clear the timer & stack
        if(stackEvaluationFunction(currentStack)){
            this.timerComplete();
        }
    }

    /**
     * handles the completion of the timer and clears the stack
     *
     *
     * @memberOf KeyboardControlStackManager
     */
    function timerComplete () {
        currentStack = [];
        timer = undefined;
    }

    return {
        add : add,
        timerComplete : timerComplete
    }
}
$(document).ready( function () {
    if (document.querySelector("body[data-in-app]")) {
        if ((typeof DISABLE_KEYBOARD_SHORTCUTS === 'undefined' || !DISABLE_KEYBOARD_SHORTCUTS)) {
            keyboardControlManager(default_keyboard_controls);
            console.log('Keyboard shortcuts are enabled on this page');
        } else {
            console.log('Keyboard shortcuts are disabled on this page.');
        }
    }
});