Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dadambickford/d6792fbda2ed45997f3961155704f401 to your computer and use it in GitHub Desktop.
Save dadambickford/d6792fbda2ed45997f3961155704f401 to your computer and use it in GitHub Desktop.
/**
* BatchGeoKeyboardShortcuts stores and initializes all of the keyboard shortcuts
* for the batchgeo map.
*/
window.BatchGeoKeyboardShortcuts = (function () {
/**
* _activeElements is a private state object for this module to keep track of which
* shortcut contexts are active. document and #mapWrap are active by default on
* page load.
*
* @type {Object}
*/
var _activeElements = {
document: true,
'#mapWrap': true
}
/**
* _setActiveElements takes a click event object. It uses the click event data
* to tell where the user clicks and if the click is within the element context
* of any of our shortcuts. If it is then it sets the context true in our
* _activeState object.
*
* @param {object} event - click event data.
*/
var _setActiveElements = function (event, shortcuts) {
// if the actual click target was the top search input, then we need to track that
if ($(event.target).is("#addressBox")) {
_activeElements.addressBox = true;
}
else {
_activeElements.addressBox = false;
}
// loop through our shortcuts and check if the even target is within any of
// our shortcut contexts.
shortcuts.forEach(function (shortcut) {
if (shortcut.context !== 'document') {
if ($(shortcut.context).find(event.target).length) {
_activeElements[shortcut.context] = true;
}
else {
_activeElements[shortcut.context] = false;
}
}
});
};
var _prepareShortcuts = function (shortcuts) {
// loop through our shortcuts and default global shortcut context to 'document'
// and non modifier shortcuts to always return true
shortcuts.forEach(function (shortcut) {
shortcut.context = shortcut.context || 'document';
shortcut.modifier = shortcut.modifier || function () { return true; };
});
return shortcuts;
}
/**
* `shortcuts` {array} is a collection of shortcut data. A shortcut object needs
* to have at least a `key` prop, which is the `event.which` key code, and an
* `action` callback, which is the function that will be ran when the corresponding
* key is pressed.
*
* There are 2 optional props for shortcut data, `context` and `modifier`. `context`
* is the element that must be focused for the shorcut to work. `context` is
* optional because if a `context` is not passed then the `context` is set to
* `document` and the shortcut is usable on the entire page. If the shortcut
* should only be usuable on certain parts of the page, set the `context` prop
* to the `id` or `class` of the wrapping element that the shortcut should work
* on.
*
* The `modifier` prop is for 2 key shortcuts like `cmd`+`z`. `modifier` is a
* function that takes one parameter, `e`, which is the keydown event data. In
* this function you would return whichever modifier prop from the event data
* that you would like to modify your shortcut.
*
* Here is an xample of a `modifier` function that would make a normal shortcut
* into a `shift` + `whatever` type of shortcut.
* ```
* modifier: function (e) {
* return e.shiftKey;
* },
* ```
* You can also use the modifier to prevent the shortcut from firing if a modifier
* key is pressed. An example of this is you want to put a shortcut on the letter
* 's' but don't want the shortcut to fire if the user is pressing `cmd`+`s` as
* if to save something. Use the modifier function to return `!e.shiftKey` or
* whichever modifier applies to your situation.
*
* And here is an example of a full shortcut object.
* ```
* {
* key: 77,
* context: '.myShortcutArea',
* modifier: function (e) {
* return e.metaKey || e.ctrlKey;
* },
* action: function () {
* console.log('You pressed `Ctrl`/`Cmd` + `M`!');
* }
* }
*
*/
return function shortcutInstance (shortcuts) {
shortcuts = _prepareShortcuts(shortcuts);
/**
* on click we want to set our active elements for shortcut context
* @param {object} event - click event data
*/
var _shortcutClickHandler = function (event) {
_setActiveElements(event, this.shortcuts);
};
/**
* on keydown loop through our shortcuts and fire any that match criteria
* @param {[type]} event - keydown event data
*/
var _shortcutKeydownHandler = function (event) {
// if the search input is focused get outta here.
if (_activeElements.addressBox) return;
shortcuts.forEach(function (shortcut) {
// if all criteria (key, modifier, and context) are true then fire action
if (shortcut.key == event.which && shortcut.modifier(event) && _activeElements[shortcut.context]) {
shortcut.action();
}
});
};
/**
* _initShortcuts sets up the necessary click and keydown listeners for all
* of our shortcuts to work.
*/
var _initShortcuts = function (shortcuts) {
// Check shortcut context on click
$(document).on('click.shortcut', _shortcutClickHandler);
$(document).on('keydown.shortcut', _shortcutKeydownHandler);
};
return {
/**
* enable() simply calls the `_initShortcuts` function to get everything started.
*/
enable: function () {
_initShortcuts(shortcuts);
},
/**
* disable() simply removes the event listeners. Nothing else to reset.
*/
disable: function () {
$(document).off('click.shortcut', _shortcutClickHandler);
$(document).off('keydown.shortcut', _shortcutKeydownHandler);
}
};
};
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment