Coder Social home page Coder Social logo

ccampbell / mousetrap Goto Github PK

View Code? Open in Web Editor NEW
11.6K 179.0 965.0 461 KB

Simple library for handling keyboard shortcuts in Javascript

Home Page: https://craig.is/killing/mice

License: Apache License 2.0

JavaScript 97.67% HTML 1.96% CSS 0.36%
mousetrap javascript keyboard-shortcuts keyboard

mousetrap's Introduction

Mousetrap

CDNJS

Mousetrap is a simple library for handling keyboard shortcuts in Javascript.

It is licensed under the Apache 2.0 license.

It is around 2kb minified and gzipped and 4.5kb minified, has no external dependencies, and has been tested in the following browsers:

  • Internet Explorer 6+
  • Safari
  • Firefox
  • Chrome

It has support for keypress, keydown, and keyup events on specific keys, keyboard combinations, or key sequences.

Getting started

  1. Include mousetrap on your page before the closing </body> tag

    <script src="/path/to/mousetrap.min.js"></script>

    or install mousetrap from npm and require it

    var Mousetrap = require('mousetrap');
  2. Add some keyboard events to listen for

    <script>
        // single keys
        Mousetrap.bind('4', function() { console.log('4'); });
        Mousetrap.bind("?", function() { console.log('show shortcuts!'); });
        Mousetrap.bind('esc', function() { console.log('escape'); }, 'keyup');
    
        // combinations
        Mousetrap.bind('command+shift+k', function() { console.log('command shift k'); });
    
        // map multiple combinations to the same callback
        Mousetrap.bind(['command+k', 'ctrl+k'], function() {
            console.log('command k or control k');
    
            // return false to prevent default browser behavior
            // and stop event from bubbling
            return false;
        });
    
        // gmail style sequences
        Mousetrap.bind('g i', function() { console.log('go to inbox'); });
        Mousetrap.bind('* a', function() { console.log('select all'); });
    
        // konami code!
        Mousetrap.bind('up up down down left right left right b a enter', function() {
            console.log('konami code');
        });
    </script>

Why Mousetrap?

There are a number of other similar libraries out there so what makes this one different?

  • There are no external dependencies, no framework is required
  • You are not limited to keydown events (You can specify keypress, keydown, or keyup or let Mousetrap choose for you).
  • You can bind key events directly to special keys such as ? or * without having to specify shift+/ or shift+8 which are not consistent across all keyboards
  • It works with international keyboard layouts
  • You can bind Gmail like key sequences in addition to regular keys and key combinations
  • You can programatically trigger key events with the trigger() method
  • It works with the numeric keypad on your keyboard
  • The code is well documented/commented

Tests

Unit tests are run with mocha.

Running in browser

View it online to check your browser compatibility. You may also download the repo and open tests/mousetrap.html in your browser.

Running with Node.js

  1. Install development dependencies

    cd /path/to/repo
    npm install
  2. Run tests

    npm test

Documentation

Full documentation can be found at https://craig.is/killing/mice

mousetrap's People

Contributors

bdougherty avatar blowery avatar bobthecow avatar ccampbell avatar chrisjshull avatar crabmusket avatar crittermike avatar davoclavo avatar deiru2k avatar dtao avatar edazdarevic avatar iongion avatar jakubbuszynski avatar kleinfreund avatar mortonfox avatar nosir avatar pmusaraj avatar pvnr0082t avatar rstacruz avatar satchamo avatar spencerlynn avatar wzutz avatar zeke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mousetrap's Issues

Support method chaining

If you return Mousetrap from functions, they could be chained together. One call to bind them all!

ctrl + num + num

Mousetrap.bind('ctrl+1', function() { console.log('ctrl 1'); return false;});

Mousetrap.bind('ctrl+1+1', function() { console.log('ctrl+11');return false; });

If I press ctrl+1,
then both the event occurs..
Instead, I need both the above as different event..
help me..

Default more keys to use keypress

See #36

I'm not sure why, but there are some keyCode mappings forcing certain keys to use keydown events. I think these can be updated to default to keypress and then only do the lookups if you explicitly bind a keydown or keyup event to them.

Character Mapping problems

I'm seeing some strange character mapping problems. For example, this code alerts 'm' when '-' is pressed.

Mousetrap.bind('-', function (e) {
    var charCode = typeof e.which == "number" ? e.which : e.keyCode;
    alert(String.fromCharCode(charCode)); //alerts 'm'
});

FWIW, This is on OSX & using FF so I don't know if there's a difference for browsers or oses.

Here's the full set from 32 to 200... I can see a few differences between this and MT's mappings.

>>> for(var i = 32;i<200;i++) { console.log(i, String.fromCharCode(i)); }
32
33 !
34 "
35 #
36 $
37 %
38 &
39 '
40 (
41 )
42 *
43 +
44 ,
45 -
46 .
47 /
48 0
49 1
50 2
51 3
52 4
53 5
54 6
55 7
56 8
57 9
58 :
59 ;
60 <
61 =
62 >
63 ?
64 @
65 A
66 B
67 C
68 D
69 E
70 F
71 G
72 H
73 I
74 J
75 K
76 L
77 M
78 N
79 O
80 P
81 Q
82 R
83 S
84 T
85 U
86 V
87 W
88 X
89 Y
90 Z
91 [
92 \
93 ]
94 ^
95 _
96 `
97 a
98 b
99 c
100 d
101 e
102 f
103 g
104 h
105 i
106 j
107 k
108 l
109 m
110 n
111 o
112 p
113 q
114 r
115 s
116 t
117 u
118 v
119 w
120 x
121 y
122 z
123 {
124 |
125 }
126 ~
127 �
128 �
129 �
130 �
131 �
132 �
133 �
134 �
135 �
136 �
137 �
138 �
139 �
140 �
141 �
142 �
143 �
144 �
145 �
146 �
147 �
148 �
149 �
150 �
151 �
152 �
153 �
154 �
155 �
156 �
157 �
158 �
159 �
160  
161 ¡
162 ¢
163 £
164 ¤
165 ¥
166 ¦
167 §
168 ¨
169 ©
170 ª
171 «
172 ¬
173 ­
174 ®
175 ¯
176 °
177 ±
178 ²
179 ³
180 ´
181 µ
182 ¶
183 ·
184 ¸
185 ¹
186 º
187 »
188 ¼
189 ½
190 ¾
191 ¿
192 À
193 Á
194 Â
195 Ã
196 Ä
197 Å
198 Æ
199 Ç

Specify 'include'/'exclude' class for text-fields

You should be able to specify which class/es do not have shortcuts available when they have focus, and which ones do.

In particular, being able to specify that any object with the 'my-class' class will have shortcuts enabled, when typically they wouldn't, is very useful. This could save rewriting lots of html to add shortcuts to existing text fields etc.

Configure eventStop for input/textarea on a per-bind basis

The use case is simple: I want to be able to press e on an element to open an edit field for it, but once in the edit field, I want to be able to push 'ESC' to close the edit field. Maybe in general, special keys like ESC, CTRL+KEY, ... could bypass the input/textarea block, as they are not gonna insert content in the field anyway.

What do you think?

option+n not working?

I'm testing Moustrap in Firefox for max (FF 14.0.1) and found if I write:

 Mousetrap.reset();
 Mousetrap.bind(['option+n'], function() {
   console.log("option+n pressed...");
 });
 Mousetrap.bind(['option+m'], function() {
   console.log("option+m pressed...");
});
Mousetrap.bind(['option+f'], function() {
  console.log("option+f pressed...");
});

the only key combination that didn't work if option+n. Any clue why is this happening?

"Ctrl + K" Conflict with Google Chrome

Google Chrome binds Ctrl + K to Places a ‘?’ in the address bar..

I'm not familiar with JavaScript, so is it a event prevent bug or anything else?

Shortcut event gets passed focussed text field

I'm sure I'm doing something wrong but I can't see the answer in the doc or other issues.

Platform: Mousetrap 1.1 on Chrome 20.0.1132.47 on Mac OS X Lion.

$('#find_listing').ready(function() {
    function _focusFindListing() {
        $("#find_listing").val("");
        $("#find_listing").focus();
    }
    console.log("calling Mousetrap.bind");
    Mousetrap.bind('l', _focusFindListing);
});

Correctly focuses on my text field object "find_listing" but also inserts the 'l' as an input character.

Add object model

To support creation and reset of a subset of key bindings, e.g.,

var m1 = new Mousetrap();
m1.bind('1', ...);

var m2 = new Mousetrap();
m2.bind('2', ...);

m1.reset(); # '2' is still bound

Idea: capture integer sequences for later use

Hi! Love mousetrap.

Just today I thought of an idea for navigating enumerated pages, like a giant table of users that's been paginated. The ability to press, for example, "4 g" to go to the 4th page (like "4G" in vim), would be great. I didn't find a preexisting way to do it with mousetrap.

Perhaps they could be declared in either format string specifier style:

Mousetrap.bind( "%d g" , function(e) {} );

Or regex style:

Mousetrap.bind( "(\d)+ g" , function(e) {} );

Or maybe even a special alias:

Mousetrap.bind( "number g" , function(e) {} );

I glanced quickly through the code and I think it should be possible without too much hackery, by storing in-progress patterns inside _sequence_levels.

It might take me a few days or weeks to get to it, but I wanted to post it here to get feedback before diving in. If this is possible already, or if there's a convenient way I should go about it, please let me know!

Two-letter key combinations not working as expected

I'm working on a Backbone.js app, and I have a several different objects that register bindings with Mousetrap that don't seem to be working as expected.

I have a model on which I have registered: Mousetrap.bind('d+s', this.skipDocument);, and then I have a view on which I've registered: Mousetrap.bind('k+s', this.showKeyboardShortcuts); (yes, its a keyboard shortcut to show a list of the keyboard shortcuts for the page).

The problem I'm having, is that the key combinations don't seem to be matter at all. All I have to do on the page is hit the letter s and both functions fire. Not exactly what I was expecting. Am I doing something wrong here? Am I missing something?

International keyboard layouts do not work correctly

I tried the examples on demo page using standard Turkish (Q) layout, but some of them didn't work. (Namely, '$' and '*'.)

Now I tried them again and somehow made them work. $ character is typed using AltGr+4 combination, but it didn't work with it or the US variant Shift+4; however it works for AltGr+Shift+4.

On the other hand, asterisk character has a seperate key for itself on Turkish layout. But it also doesn't work. It works by combining Turkish and US layouts and pressing AltGr+Shift+8 --and followed by 'a', of course, for the example to work.

Command (meta) modifier works incorrectly in Safari 6

It looks like event bound to a key is also triggered if the key is pressed with a command modifier.
I am using the following test HTML file:

<html>
  <script src="mousetrap.js"></script>
  <script type="text/javascript">
    Mousetrap.bind('l', function() { console.log('l pressed'); });
  </script>
</html>

And I see the console message even when I hit "Command-l" rather than "l".

Turn Mousetrap off/on

I added two functions that permit turning Mousetrap off and on again for those times you want to dynamically do mystical things with keyboard operations on a page that are outside of keyboard input areas. Append these two functions to the return {} section at the end.

        /**
         * pauses the library by saving its current state then clearing
         * the callbacks and shortcuts
         *
         * @returns void
         */
        pause: function() {
            if (typeof _saved_callbacks != 'undefined') {
                return;
            }
            _saved_callbacks = _callbacks;
            _saved_direct_map = _direct_map;
            _callbacks = {};
            _direct_map = {};
        },

        /**
         * unpauses the library by copying the saved state back
         *
         * @returns void
         */
        unpause: function() {
            if (typeof _saved_callbacks == 'undefined') {
                return;
            }
            _callbacks = _saved_callbacks;
            _direct_map = _saved_direct_map;
            delete _saved_callbacks;
            delete _saved_direct_map;
        }

Add support for keypress events

It seems that there are some differences between how browsers handle keydown vs. keypress so some things might only be possible when using one vs. the other

Use Mousetrap in Gmail (website with many iframes?)

I'm trying to add a custom shortcut in gmail through a chrome extension.

Without Mousetrap one can add a keydown in every iframe as described here: http://stackoverflow.com/questions/9424550/how-can-i-detect-keyboard-events-in-gmail

This works fine. However if I use the same approach and do

Mousetrap.bind('4', function() { alert('343'); });

It's not working. I suspect this is because Mousetrap will only add the eventlistner to the toplevel document.

Any pointers?

Multiple method calls

Do not know if this is expected behavior or not:

Mousetrap.bind('space', function() { console.log('hi'); }, 'keydown');

I would expect that if I hold space down, I should only get one 'hi' printed but I actually get many 'hi's printed. What if I only want one? Maybe add an optional parameter to prevent re-trigger of callback if key is still in same state.

Check for scrolling with arrow keys

It would be nice if the library did not activate bound shortcuts that include arrow keys (up, down, left, and right) when the following conditions are met

  • the focus is on a scrollable element, and
  • pressing the arrow key would result in scrolling (might not be necessary).

The second criterion might not be necessary for usability reasons -- ie the user might expect that the arrow keys are always overridden in any sort of scrollable element.

Define a ctrl/command string

Define a key which is valid for either ctrl or command key presses, so it can be used either in PC or Mac.
Instead of ['command+k', 'ctrl+k'], it could be 'comctrl+k'

Synthesizes key down on modifier up

On my browser (Chrome 20.0.1132.47 on Fedora 17) and a US keyboard:

  1. Browse to the demo at http://craig.is/killing/mice
  2. Press and hold the shift key
  3. Press and hold the '4' key
  4. The "$" item correctly illuminates
  5. Release the shift key. The "4" item incorrectly illuminates. "4" was never typed.

AMD portability issue

Hi. I had some issues with getting the AMD support working. I finally traced it down to the built-in AMD support hard coding the module name to "mousetrap" but my directory structure necessitated it to be "lib/mousetrap". I changed it in my version of the code, but http://requirejs.org/docs/api.html#modulename seems to indicate that hard coding the name at all is a generally bad idea. I'm not sure if requirejs is indicative of all AMD or not, but it seems worth looking into just removing that parameter.

Thanks.

For fun: Make the logo interactive

Thanks for this!

One awesome enhancement for the website would be to make m, o, u, s, e, t, r, a, p interactive, so they highlight as you press those keys.

That would be awesome :-D

No License

Do you plan on releasing this under a license?

Can we have trigger() able to trigger the default behavior of keys?

Nice api for the most part and I have been having fun with it to make my app much more usable than before with shortcuts. But one of the features require me to trigger default space-bar behavior at runtime. I am still trying the jquery event way at the moment. I wonder if there's plan to make trigger() actually triggering the default behavior if not mapped in mousetrap. Thanks.

Allow to define the bindings as a dictionary

Instead of having to declare keys one by one, like this:

Mousetrap.bind('4', function() { highlight(2); });
Mousetrap.bind("$", function() { highlight(3); }, 'keydown');
Mousetrap.bind('x', function() { highlight(4); }, 'keyup');

To be able to declare them as:

Mousetrap.bind({
 '4': function() { highlight(2) },
 '$': function() { highlight(3) },
 'x': callbackfn
}

In this moment I don't know how the trigger event can be defined ('keydown','keyup'), but I guess someone can help.

User defined key combinations

I'd like to be able to have a few set keyboard functions, some defaults but make them over-ride-able by the user.

Things like Ctrl-S might make sense for me but that's just because I speak English and associate S with Save. For multi-lingual sites this could be big.

Bigger issues with accessibility where the assistive technology may limit what keys a user has access to.

Some shift- key combos don't work in Firefox on Mac OS

Hey, thanks for the great library. I really like the API. I've been on the lookout for something like this for a while, because I've implemented it too often for my projects.

One annoying browser bug I've run into in the past when implementing keyboard shortcuts is this Mac OS-specific Firefox bug. So, the first thing I tried with Mousetrap was to set up some of those shortcuts. It seems like Mousetrap doesn't work around this issue. For instance:

Mousetrap.bind("?", function() { alert("?") })

This works in Chrome but not Firefox (on Mac OS).

The way I've worked around this in my own projects is to special-case these shortcuts and use the keypress event and inspect event.which (instead of event.keyCode, which isn't getting set). I haven't done a lot of research here on the best way to do things, though.

Add unbind method

There should be a way to disable a single key combo, instead of using reset().

ctrl+s and the browser default action

When I bind ctrl+s using Mousetrap, the browser's default action is launched first (save the page as HTML), and only then the bound action is launched.
Would it be possible to block the browser default actions on the bound events (as I believe same will hold true for other key combinations, such as ctrl+r or ctrl+u)?

automatically bind to any link with data-shortcut

So I had this idea that I'd like mousetrap to bind to any link with a data-shortcut attribute.

The shortcut keystroke would be defined on the link itself, so it is clear on each link what it's shortcut key/sequence should be.

In my app I could then provide links with shortcuts as links as necessary.

jQuery.each(jQuery("a[data-shortcut]",function(i,v) {
  link = jQuery(v);
  Mousetrap.bind(link.data('shortcut'),function(e) {
    l = jQuery('a[data-shortcut='+e.???+']');
    window.open(l.attr('href')); // <-- link does not get figured out here (or how to get link.attr("href") here easily?)
  });
});

Can you help me figure out how i can get access to original keystroke/sequence that triggered the callback? Or perhaps suggest an alternate to the approach?

Add support for push/pop stack operations

I had actually written a similar library on my own but your sequences feature has me considering dropping it for mousetrap.

Have you considered adding support for push/pop operations? Should only require a few lines of code to add.

// with reset (good for modals)
Mousetrap.push() // implicit reset
... // register new keystrokes
Mousetrap.pop() // restore previous keystrokes
// building on existing bindings (good for context changes)
Mousetrap.push({reset: false})
... // override just a few keystrokes
Mousetrap.pop()

_MAP tab and backspace switched

Just passing through here so forgive me if I've not understood the code correctly...

in the _MAP object, you have
var _MAP = {
8: 'backspace',
9: 'tab', ...

Shouldn't that be
var _MAP = {
8: 'tab',
9: 'backspace',

keymaster?

how is this project different? at a glance it seems nearly identical, might be worth pointing out in the read me

Add method to check if key:action is bound

I want to tell a bit of code that executes on keydown "is Mousetrap handling this? if so, don't do anything." Currently there's no way to check if mousetrap has a key(s):action pair bound.

The way _direct_map keys are created may make this check difficult/impossible from this object but I haven't looked too closely.

    /**
     * check if Mousetrap currently has an action bound to this key:action pair
     *
     * @param {string} key
     * @param {string} action (optional)
     * @returns boolean
     */
    function _isBound(key, action)

and a corresponding public method.

No unit tests

This looks great, nice work!

I'd love to see unit tests for this library.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.