diff --git a/README.md b/README.md index 4160ebd..4954495 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,7 @@ angular.module('myApp', ['cfp.hotkeys']) - `callback`: The function to execute when the key(s) are pressed. Passes along two arguments, `event` and `hotkey` - `action`: [OPTIONAL] The type of event to listen for, such as `keypress`, `keydown` or `keyup`. Usage of this parameter is discouraged as the underlying library will pick the most suitable option automatically. This should only be necessary in advanced situations. - `allowIn`: [OPTIONAL] an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA') +- `inContentEditable`: [OPTIONAL] Wether to allow this combo in a contenteditable element. Defaults to false. ```js hotkeys.add({ @@ -243,6 +244,19 @@ hotkeys.add({ }); ``` +### Allowing hotkeys in contenteditable elements +By default, Mousetrap prevents hotkey callbacks from firing when their event originates from an element with contenteditable="true". To enable hotkeys in these elements, you must set `inContentEditable` to `true`: +```js +hotkeys.add({ + combo: 'ctrl+w', + description: 'Description goes here', + inContentEditable: true + callback: function(event, hotkey) { + event.preventDefault(); + } +}); +``` + ## Credits: Muchas gracias to Craig Campbell for his [Mousetrap](https://github.com/ccampbell/mousetrap) library, which provides the underlying library for handling keyboard shortcuts. diff --git a/build/hotkeys.js b/build/hotkeys.js index 7eb55f4..c6ced78 100644 --- a/build/hotkeys.js +++ b/build/hotkeys.js @@ -91,18 +91,13 @@ // monkeypatch Mousetrap's stopCallback() function // this version doesn't return true when the element is an INPUT, SELECT, or TEXTAREA - // (instead we will perform this check per-key in the _add() method) + // (instead we will perform this check per-key in the _add() method). Idem for contenteditable elements. Mousetrap.prototype.stopCallback = function(event, element) { if (!mouseTrapEnabled) { return true; } - // if the element has the class "mousetrap" then no need to stop - if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) { - return false; - } - - return (element.contentEditable && element.contentEditable == 'true'); + return false; }; /** @@ -142,14 +137,15 @@ /** * Hotkey object used internally for consistency * - * @param {array} combo The keycombo. it's an array to support multiple combos - * @param {String} description Description for the keycombo - * @param {Function} callback function to execute when keycombo pressed - * @param {string} action the type of event to listen for (for mousetrap) - * @param {array} allowIn an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA') - * @param {Boolean} persistent Whether the hotkey persists navigation events + * @param {array} combo The keycombo. it's an array to support multiple combos + * @param {String} description Description for the keycombo + * @param {Function} callback function to execute when keycombo pressed + * @param {string} action the type of event to listen for (for mousetrap) + * @param {array} allowIn an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA') + * @param {Boolean} persistent Whether the hotkey persists navigation events + * @param {boolean} inContentEditable Wether to allow combo in contenteditable elements */ - function Hotkey (combo, description, callback, action, allowIn, persistent) { + function Hotkey (combo, description, callback, action, allowIn, persistent, inContentEditable) { // TODO: Check that the values are sane because we could // be trying to instantiate a new Hotkey with outside dev's // supplied values @@ -160,6 +156,7 @@ this.action = action; this.allowIn = allowIn; this.persistent = persistent; + this.inContentEditable = inContentEditable; this._formated = null; } @@ -328,14 +325,15 @@ /** * Creates a new Hotkey and creates the Mousetrap binding * - * @param {string} combo mousetrap key binding - * @param {string} description description for the help menu - * @param {Function} callback method to call when key is pressed - * @param {string} action the type of event to listen for (for mousetrap) - * @param {array} allowIn an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA') - * @param {boolean} persistent if true, the binding is preserved upon route changes + * @param {string} combo mousetrap key binding + * @param {string} description description for the help menu + * @param {Function} callback method to call when key is pressed + * @param {string} action the type of event to listen for (for mousetrap) + * @param {array} allowIn an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA') + * @param {boolean} persistent if true, the binding is preserved upon route changes + * @param {boolean} inContentEditable Wether to allow combo in contenteditable elements */ - function _add (combo, description, callback, action, allowIn, persistent) { + function _add (combo, description, callback, action, allowIn, persistent, inContentEditable) { // used to save original callback for "allowIn" wrapping: var _callback; @@ -347,12 +345,13 @@ var objType = Object.prototype.toString.call(combo); if (objType === '[object Object]') { - description = combo.description; - callback = combo.callback; - action = combo.action; - persistent = combo.persistent; - allowIn = combo.allowIn; - combo = combo.combo; + description = combo.description; + callback = combo.callback; + action = combo.action; + persistent = combo.persistent; + allowIn = combo.allowIn; + inContentEditable = combo.inContentEditable; + combo = combo.combo; } // no duplicates please @@ -411,6 +410,11 @@ if ((' ' + target.className + ' ').indexOf(' mousetrap ') > -1) { shouldExecute = true; } else { + // By default prevent execution of callback if in contenteditable + if (target.contentEditable && target.contentEditable == 'true') { + shouldExecute = inContentEditable || false; + } + // don't execute callback if the event was fired from inside an element listed in preventIn for (var i=0; i