angular2-hotkeys icon indicating copy to clipboard operation
angular2-hotkeys copied to clipboard

Cannot selectively allow shortcuts in INPUT.RANGE while keeping them disabled in INPUT.*

Open mikekov opened this issue 6 years ago • 3 comments

Current library behavior lets me allow/disallow shortcuts to fire when certain elements have focus. I'd like a shortcut to fire if slider on a page (INPUT RANGE element) has focus, but not when edit box (INPUT NUMBER) has it. This is not possible, as both of them are INPUT elements.

To accomplish this I modified this.mousetrap.bind callback in hotkeys.service.ts to distinguish them. I read type property of target element and enhanced allowIn test to cover "RANGE.<TYPE>" elements using extName.

            if(event) {
                let target: HTMLElement = <HTMLElement>(event.target || event.srcElement); // srcElement is IE only
                let nodeName: string = target.nodeName.toUpperCase();
                const extName = nodeName + '.' + ((target as HTMLInputElement).type || '').toUpperCase();

                // check if the input has a mousetrap class, and skip checking preventIn if so
                if((' ' + target.className + ' ').indexOf(' mousetrap ') > -1) {
                    shouldExecute = true;
                } else if(this._preventIn.indexOf(nodeName) > -1 &&
                    !(<Hotkey>hotkey).allowIn.map(allow => allow.toUpperCase()).some(el => el === nodeName || el === extName)) {
                    // don't execute callback if the event was fired from inside an element listed in preventIn but not in allowIn
                    shouldExecute = false;
                }
            }

Note: I use some in place of indexOf as it is just as well supported and useful here.

My hotkey registration now specifies ["INPUT.RANGE"] for allowIn parameter.

mikekov avatar Apr 04 '18 17:04 mikekov

This looks pretty good to me. I'd like to run some tests before integrating it into the project though. It does seem to be a pretty targeted fix, I'm not sure when else type might be set. But then again we're only really considering INPUT, TEXTAREA and SELECT elements.

Would it have worked to add the mousetrap class to the range element instead? Not that it would mean this shouldn't be included, just wondering if there's a use case I can't think of where it wouldn't work.

wittlock avatar Apr 05 '18 17:04 wittlock

I didn't occur to me to add "mousetrap" to a slider element. However my slider already has other classes assigned, plus I don't know what it means for mousetrap lib to decorate controls with "mousetrap".

The safest route seemed to be testing for a type. Now, if it wasn't existing library code, then I'd consider regex for such tests. Another possibility is for library to offer some reasonable defaults (there are many range types in HTML5), but that would be change in behavior, so I opted for letting users decide.

mikekov avatar Apr 06 '18 03:04 mikekov

The Mousetrap library (and angular2-hotkeys) only use the class to override any "stopCallback" logic. So it's a way to whitelist all hotkeys in some INPUT-elements whereas the allowIn setting for a hotkey will whitelist a single hotkey in all INPUT/TEXTAREA/SELECT-elements. So it shouldn't have any unexpected side effects from using that.

I still see the option of using types in allowIn as a valid request though, sometimes adding the class to the elements aren't practical, or maybe you only want one particular hotkey to work there instead of all.

wittlock avatar Apr 06 '18 16:04 wittlock