Git Product home page Git Product logo

keyboardjs's Introduction

KeyboardJS


Note Please Note: I've create a new libary called Keystrokes which serves the same purpose as KeyboardJS, but is more refined, and takes full advantage of modern browsers. If you are considering using KeyboardJS in a new project, I recommend checking out Keystrokes first.


Build Status NPM Version Downloads This Week License

KeyboardJS is a library for use in the browser (node.js compatible). It Allows developers to easily setup key bindings. Use key combos to setup complex bindings. KeyboardJS also provides contexts. Contexts are great for single page applications. They allow you to scope your bindings to various parts of your application. Out of the box keyboardJS uses a US keyboard locale. If you need support for a different type of keyboard KeyboardJS provides custom locale support so you can create with a locale that better matches your needs.

KeyboardJS is available as a NPM module. If you're not using a build system like webpack, simply add keyboard.js or keyboard.min.js from the dist folder in this repo to your project via a script tag.

npm install keyboardjs

Note that all key names can be found in ./locales/us.js.

Setting up bindings is easy

keyboardJS.bind('a', (e) => {
  console.log('a is pressed');
});
keyboardJS.bind('a + b', (e) => {
  console.log('a and b is pressed');
});
keyboardJS.bind('a + b > c', (e) => {
  console.log('a and b then c is pressed');
});
keyboardJS.bind(['a + b > c', 'z + y > z'], (e) => {
  console.log('a and b then c or z and y then z is pressed');
});
keyboardJS.bind('', (e) => {
  console.log('any key was pressed');
});
//alt, shift, ctrl, etc must be lowercase
keyboardJS.bind('alt + shift > a', (e) => {
  console.log('alt, shift and a is pressed');
});

// keyboardJS.bind === keyboardJS.on === keyboardJS.addListener

keydown vs a keyup

keyboardJS.bind('a', (e) => {
  console.log('a is pressed');
}, (e) => {
  console.log('a is released');
});
keyboardJS.bind('a', null, (e) => {
  console.log('a is released');
});

Prevent keydown repeat

keyboardJS.bind('a', (e) => {
  // this will run once even if a is held
  e.preventRepeat();
  console.log('a is pressed');
});

Unbind things

keyboardJS.unbind('a', previouslyBoundHandler);
// keyboardJS.unbind === keyboardJS.off === keyboardJS.removeListener

Using contexts

  // these will execute in all contexts
  keyboardJS.bind('a', (e) => {});
  keyboardJS.bind('b', (e) => {});
  keyboardJS.bind('c', (e) => {});

  // these will execute in the index context
  keyboardJS.setContext('index');
  keyboardJS.bind('1', (e) => {});
  keyboardJS.bind('2', (e) => {});
  keyboardJS.bind('3', (e) => {});

  // these will execute in the foo context
  keyboardJS.setContext('foo');
  keyboardJS.bind('x', (e) => {});
  keyboardJS.bind('y', (e) => {});
  keyboardJS.bind('z', (e) => {});

  // if we have a router we can activate these contexts when appropriate
  myRouter.on('/', (e) => {
    keyboardJS.setContext('index');
  });
  myRouter.on('/foo', (e) => {
    keyboardJS.setContext('foo');
  });

  // you can always figure out your context too
  const contextName = keyboardJS.getContext();

  // you can also set up handlers for a context without losing the current context
  keyboardJS.withContext('bar', ()  =>{
    // these will execute in the bar context
    keyboardJS.bind('7', (e) => {});
    keyboardJS.bind('8', (e) => {});
    keyboardJS.bind('9', (e) => {});
  });

pause, resume, and reset

// the keyboard will no longer trigger bindings
keyboardJS.pause();

// the keyboard will once again trigger bindings
keyboardJS.resume();

// all active bindings will released and unbound,
// pressed keys will be cleared
keyboardJS.reset();

pressKey, releaseKey, and releaseAllKeys

// pressKey
keyboardJS.pressKey('a');
// or
keyboardJS.pressKey(65);

// releaseKey
keyboardJS.releaseKey('a');
// or
keyboardJS.releaseKey(65);

// releaseAllKeys
keyboardJS.releaseAllKeys();

watch and stop

// bind to the window and document in the current window
keyboardJS.watch();

// or pass your own window and document
keyboardJS.watch(myDoc);
keyboardJS.watch(myWin, myDoc);

// or scope to a specific element
keyboardJS.watch(myForm);
keyboardJS.watch(myWin, myForm);

// detach KeyboardJS from the window and document/element
keyboardJS.stop();

keyboardjs's People

Contributors

cwill avatar daniel-wer avatar daytonlowell avatar dependabot[bot] avatar dropmann avatar jdsn avatar jonathon-love avatar mcpo avatar robert-hurst-cmd avatar robertwhurst avatar toyyan avatar weltonrodrigo 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

keyboardjs's Issues

Tests are needed.

I really need to add proper tests. This is difficult as I need a way of simulating keyboard events.

Delay

Is there a way to control the delay between keys pressed? E.g. if I have a keybinding of "g + i" I have to press G then I pretty fast, but if you look at gmails shortcuts you can press g then wait and then press i about > 1.5 seconds and it will still work. Thoughts?

Use arrow keys in input text field on IE8 and IE9

I bind Left and Right keys to trigger specific events. Worked very well. However, on IE, it results in causing user unable to use these arrows when typing inside the input field.
In Chrome and Firefox, when using arrow keys when typing inside a text input field, the custom event was trigger but the text cursor is also moved (desirable result).
Is there a way to fix or work around?

undefined variable [kI] in clear.key

595:if(binding.keyCombo[kI].indexOf(keyName) > -1) {
should be
if(binding.keyCombo[cI].indexOf(keyName) > -1) {

or

590: var bI, cI, binding;
to
var bI, kI, binding;

can't disable plugin to be able to type

I'm using the exact same script from the presentation website is working very good but I have an input in my page and I can't write in it so I want to disable the script when the input is focused to be able to type and .disable(); is not working as I expected.
is there any way of doing this?

Alt or Alt GR remain active forever

Hi,

Nice library, but it seems to be very very buggy with Firefox when using it with Alt and Alg GR keys: after a few presses of Alt or Alt GR, the "alt" keycode (18) seems to be forever active, independent if the user is pressing ESC or something else.
On Firefox (with Firebug) in Console one can see this with:
console.log(KeyboardJS.activeKeys());

This seems to remain sticky until the user refreshes the pages - and this is not practicable for the today's Ajax apps.

I can also see this phenomenon with CTRL + Alt combinations too, and it's even visible on your website demo.

Or this example: https://gist.github.com/2309933

Bug when pressing Cmd

I've only tested this in Chrome (16.0.912.59) on OSX Lion, so I can't tell you if this is something occurring in other browsers.

When pressing Cmd and at least one alphanumeric key (0-9a-z), the alphanumeric keys don't fire the keyup event when they are released first and therefore are not removed from the "active keys" list. When you release the Cmd key first everything is fine.

– Wouter

command key combo behaves differently than ctrl key combo

Implementing a copy and paste function I have two key bindings:

    KeyboardJS.on('ctrl > c, command > c', function() {
        console.log('copy!');
    });

    KeyboardJS.on('ctrl > v, command > v', function() {
        console.log('paste!');
    });

On a mac in chrome the if you do command > c > v then copy fires twice. If you do ctrl > c > v then copy fires and then paste fires. Also command > c > any other key like command > c > x causes copy to fire again as many times as you like, which seems wrong. For example, doing command > c > x > x > x fires copy four times.

Second key registers twice when pressing two keys

With this code

KeyboardJS.on('1,2,3,4,5,6,7,8,9,0', function(e) {
  console.log(e.which);
});

if I type '45' quickly, where the '4' isn't released yet when the '5' is pressed, the log shows one keypress for '4' but 2 for '5'. I guess the '5' is re-triggered when the '4' is released and KeyboardJS notices a state change?
Happens in Firefox/Safari/Chrome on OS X.

What I'm trying to do is have the user enter a number (most likely 0 - 50) where after the first digit the script pauses a half second to see if there's another digit following. It works, but only if I type the digits separately - when I type 14 quickly it finds 144. Suggestions?
Edit: worked around for now by simply taking a (0,2) slice if length > 2

bindAxis does not behave as documented

The documentation says the callback will be invoked with an array containing two numbers representing the x and y axis status, but the callback is actually invoked with a single number representing an angle in degrees.

Preventing repeating events when key held down ?

Is there a way to prevent repeating events from firing when a key is being held down ? I know the Keypress library has that feature but I find the API cumbersome and would rather use KeyboardJS.

how should 'a + b > c + d' work ?

'a + b > c + d' - binds to the 'a', 'b', 'c' and 'd' keys. Pressing both the 'a' key and the 'b' key, then both the 'c' and the 'd' key will match this keyCombo.

does it mean I have to press and keep pressed all keys to fire the event ?
is there a way to press a+b ... all keys up ... press c+d to fire the event ?

.clear() leaves a hole in keyBindingGroups, breaking functionality

It looks like the call to clear() is leaving a hole in the internal keyBindingGroups, preventing any further binds from working correctly and throwing the following error/stack:

Uncaught TypeError: Cannot read property 'keys' of undefined
queryActiveBindingskeyboard.js:161
pruneActiveKeyBindingskeyboard.js:248
bindingStackkeyboard.js:139

due to:
281: delete keyBindingGroups[keys.length][index];

I tested locally replacing the delete call with a call to Resig's array.remove implementation and it seemed to fix the issue.

eample:
http://jsfiddle.net/KEAfs/

once pressed always executed ?

<!doctype html>
<html>
    <head>
        <title>KeyboardJS Demo</title>
        <script src="keyboard.js"></script>
    </head>
    <body>
    <pre>
Only "n" key is binded.
1. press key "a" = nothing will happen
2. press key "n" = alert("n pressed") will be executed
3. press key "a" = alert("n pressed") will be executed
4. press any key = alert("n pressed") will be executed
    </pre>
    <script type="text/javascript">
        KeyboardJS.on("n", function () {alert("n pressed");});
    </script>
    </body>
</html>

Add the ability to prevent event bubbling.

.bind.key() will allow users to return false to stop event bubbling. It will also most likely have something called .stopPropagation() that will act the same as jQuery's .stopPropagation().

Firefox accepts any key after back-button, if callback had loaded a new page

I have this code:

KeyboardJS.on('e', function() {
  location.href = location.href.replace('a=view', 'a=edit');
});

This works well - it loads the edit page.

But if I then hit the backbutton instead of submitting the edit form (or clicking any other link on that page), the same function is then run on pressing any other regular key (characters, numbers, punctuation etc), not just 'e'.

This happens in Firefox 17.0.1 on OS X (ML) and Ubuntu.
Safari and Chrome work as expected on OS X, and Chromium on Ubuntu too, so it's a FF issue, looks like?

Ability to register new key event mappings

Hi,

I am developing something using the Samsung Smart TV Javascript API - its based on a webkit browser.

http://www.samsungdforum.com/Guide/GuideList

The keyboard/remote handling uses custom event codes (defined in their API, in Common.API) for the keybinds, eg via things like this:

var tvKey = new Common.API.TVKeyValue();

then its used like this:

Main.keyDown = function()
{
    var keyCode = event.keyCode;
    alert("Key pressed: " + keyCode);

    switch(keyCode)
    {
        case tvKey.KEY_RETURN:
        case tvKey.KEY_PANEL_RETURN:
            alert("RETURN");
            Player.stopVideo();
            widgetAPI.sendReturnEvent(); 
            break;    
            break;

        case tvKey.KEY_PLAY:
            alert("PLAY");

            this.handlePlayKey();
            break;
            ...

So, having used keyboardjs previously, I am thinking this is something quite similar to what it can handle.

Is there a way to register new key mappings (or plans to allow such?) I am thinking of a method to register a key like registerkey('play',tvKey.KEY_PLAY) which would add it to the current locale. Perhaps a version registerKeys that takes a map for registering several at once.

I can see that I could just create a new locale and add that - eg a 'tv' locale. It doesnt seem like the correct/best way - but given that (at least in my app), it will only be handling the remote control keys, it might be the best way forward.

Thanks,
Chris

How best to switch between keybindings between views?

Hi,

For my Smart TV app, I have a single page web app with 2 views - a channel list and then a detailed channel view - showing available episodes.

I'd like the key bindings to be done separately for each view.

Eg "enter" key on channel list, selects a channel but on detail view, the same key plays the highlighted/selected episode.

Any tips on how to handle this?

Looks like I should unbind/bind keys as I switch views, but wondering if there was an alternative.

Thanks,
Chris

Different Keycodes in different browsers

I would like my colon, dash and equal sign keys to work on Firefox (they currently don't).

There are different ways to do this:

  1. the script can modify the usLocale when a test for Firefox passes. Then when the script needs a different locale, they can also find out whether some keys have a different keycode in some browsers by testing, and then use another conditional to modify it when it is such browser.
  2. I've also commented on a previous pull request by dwi2 (sorry if it notifies you twice) that maybe we can add another property to locales called "exceptions" (or whatever you like to call it), and let KeyboardJS (by adding a few lines of code) modify the map/macros when the "test" function inside an element inside the exceptions (it's an array) returns true. I've forked your (wonderful) project and added some lines to it (well, I couldn't resist adding a few more synonyms to the keys like "minus" for dash key).

So, what do you think? Web browsers can have different keycodes. The problem is that they might fix or change them in the future, so we may need to test individual versions of web browsers in the code, making it longer.

Make it easy to bind to "?"

The only way to bind to ? currently is to bind to "shift-slash," which only works on some keyboards. The trouble is that the only way to do a real binding to ? is to use onKeyPress, instead of onKeyUp, which doesn't work in other cases. This is a known problem area for nearly all keybinding libraries. I'd love to hear your thoughts on how to do this elegantly.

Add filter hook

Add a method to a keyboard js instance to allow global hooks to filter and modify combos as they are triggered. This should function in a similar style to connect middleware.

key press event

I was wondering how one would go about the "key pressed" event (holding the key)? My code usually runs fine it I just quickly tap a button on the keyboard and immediately release it. My function get started and I have a chance to stop it on the "key down" event.
However, if I keep pressing a button the "key up" event does not fire as it should. Maybe this has to do with all the other crap I have a javascript do in the background…
I am very interested in your opinion to the topic and would appreciate your help greatly.

Demo + seperation of locale and processing logic needed

I'm considering writing a Belgian locale for your project. I'd be more inclined to actually do so if you shipped your project with a working demo that would allow me to just run the demo and adjust the keys with little to no setup.

What would also help, is a clear separation of your locale from the rest of your code. For example, you could load the locale from a JSON file. That way, someone could switch from one locale to the other by just loading a different JSON file into the same library.

[Firefox only] Alt and some combination, results in Alt key event being active till Alt key is pressed again.

This bug is Firefox specific. I have tested it on the latest version of Firefox 18.0.2.

Bug:

When Alt is pressed along with some other combination. Alt key event remains active till Alt is pressed again.

Steps to reproduce:

  1. Goto http://robertwhurst.github.com/KeyboardJS/
  2. Press some combination using Alt key. eg. Alt + [a...z], Alt + [0...9], Alt + Ctrl + [a-z0-9], etc.
  3. Observe the demo section. [alt, menu] event is available until [alt] is pressed again.

EDIT: Menu key is 93

Unable to define multiple, independent keys with a single string

I am working on replacing all the ugly keycodes and i came across you're awesome little library.

I ran into a snag when attempting to define multiple different keys to publish the same event:

KeyboardJS.on('space, right, pagedown, down', function(){
  $.publish("presentation:slide:next");
});

Debugging and poking around it seemed that this defined a single key hook that required me to press every single one of the keys. I wondered if I was building the command wrong.

I worked around the problem with the following:

function registerKeys(keys,keyEvent) {
  for (var i = 0; i < keys.length; i++) {
    KeyboardJS.on(keys[i], function(){
      keyEvent();
    });
  }
}

registerKeys([ 'space', 'right', 'pagedown', 'down' ],
  function() { $.publish("presentation:slide:next"); } );

keyCombos don't work as documented

I noticed this trying to bind WASD and arrow keys.

The combo w, up only fires when pressing both keys. Likewise a + b, c + d only fires when pressing all four.

I tested this in FF 19.0a1 and Chrome 22 on Linux. I tried version 0.3.0 from the downloads page and HEAD.

Add function for registering event hooks.

I will be adding a function that allows a user to register a function that will run each time the "executeActiveKeyBindings" is executed. This will allow people to watch the internal state of KeyboardJS and inject additional functionality.

I'm open to suggestions on how what kind of arguments one would expect the user's hook callback to be passed.

Add support for other keyboard locals

On my German keyboard pressing "ö, ä, ü" appear as what I am assuming are the keys on a US-Keyboard layout. I'm not sure how you would best deal with this, it's just something for your consideration.

Is it possible to bind to the spacebar?

Hi,

Trying to bind a 'pause'/'play' kind of events to the spacebar (space, ' ') but in Chrome it seems to be mapped to paging down already.

Thanks,
Chris

Event triggers on any key after first occurrence on specified key

JSBin

<!doctype html>
<html lang="en-US">

<head>
<script src="https://rawgit.com/dandv/KeyboardJS/master/keyboard.js"></script>
</head>

<body>

<script>
KeyboardJS.on('k', function () {
  alert('Pressed k');
});  
</script>

</body>
</html>

After I press k and dismiss the alert in the latest Chrome, any keypress will trigger the function. This seems like a pretty big bug, so maybe I haven't read the docs correctly, or there needs to be a gotcha for this simple usage?

Add license information

There's no licence information, other than "Feel free to fork this project and make your own changes." This makes it impossible to use in many projects.

No keyup on Fullscreen-Change

When using a key combo to initiate fullscreen-mode the keyup event fails to fire. Then the key stays in the active keys list.
Might be a Mac-only issue. I encountered it both in Chrome and Firefox.

In my quick fix I added

window.addEventListener('webkitfullscreenchange', reset, false);
window.addEventListener('mozfullscreenchange', reset, false);

to the enable function.

Should keyup event always fire after keydown...?

Time for my stupid question of the day...

keyup events should always come after keydown, right?

As mentioned previously, I am doing a small app on the Samsung Smart TV SDK.

Under SDK 3.0.0 I was getting keyup events after keydown - sort of like you'd expect.

But under their updated SDK 3.1.1, I am getting keyup events before keydown. Obviously this is confusing keyboardjs...

I am trying to raise it with them as a bug, but not holding out much hope - guess I will need to tweak keyboardjs to do all its work in keydown. Given there no modifiers (at least in my app) I think thats feasible.

Thanks,
Chris

activeKeys array doesn't update properly when debugging JS code

If you've got a breakpoint in a function that is being executed as a result of a key combination being pressed, the internal activeKeys array gets out of sync.

This makes sense, because once the breakpoint is hit, the code execution it halted and the focus is transferred to the devtools window, so the activeKeys array wouldn't have a chance to sync again.

I'm not sure if this can be fixed, but it's pretty annoying, because any time I'm debugging any of my app's operations, it starts executing the wrong command handlers if I've used the hotkeys (and my app is pretty hotkey-centric).

ALT key combinations in IE-10 comapatibility mode

ALT key combinations (Alt+a.....z) doesn't work when switch to compatibility mode in IE-10.

Here is the stack trace....

SCRIPT5007: Unable to get property 'match' of undefined or null reference
keyboard.js, line 868 character 3

Support Keyboard States

I wanted to implement multiple states within my system. Each state would have a different set of keyboard bindings. At first I was able to get away with a quick fix to the library by providing the ability to toggle enabled/disabled.

  KeyboardJS.enable = function() {
    KeyboardJS.enabled = true;
  };

  KeyboardJS.disable = function() {
    KeyboardJS.enabled = false;
  };

  KeyboardJS.toggle = function() {
    KeyboardJS.enabled = !KeyboardJS.enabled;
  };

  KeyboardJS.enabled = true;

    function keydown(event) {
      if (!KeyboardJS.enabled) { return; }
      // ...
    }

    ///...

However, I wanted to add states with names that I could toggle between. Another way that I thought I could get away with this is to try and not augment anymore of the existing library and compose multiple KeyboardJS objects with different bindings and enable/disable them as I needed. However, that is not possible with the current implementation.

So I finally came upon an ugly solution which would simply set and remove bindings when appropriate.

$(document).ready(function() {

  KeyboardJS.on('graveaccent', function(){
    $.publish("console:show");
  });

  KeyboardJS.on('space, right, pagedown, down', function(){
    $.publish("presentation:slide:next");
  });

  KeyboardJS.on('shift + space, left, pageup, up', function(){
    $.publish("presentation:slide:previous");
  });

  $.subscribe("console:show",function() {
    KeyboardJS.clear();

    KeyboardJS.on('graveaccent', function(){
      $.publish("console:hidden");
    });
  });

When the console:show event is triggered I would clear all mappings and defined only the ones that are available at the moment. In this case I receive an error:

Uncaught Error: Cannot parse "keyCombo" because its type is "undefined". It must be a "string". 

Ideally I would love to implement the second solution and will work toward that solution. But maybe you could provide an example of how I could make this work if it is already possible.

Combined global/AMD call

I noticed KeyboardJS has an AMD option, which is cool! If you wanted to consolidate the code so that you did not have to maintain two branches, this approach would allow that:

(function(context, factory) {
if (typeof define === 'function' && define.amd) {
define(function () { return factory(); });
} else {
context.KeyboardJS = factory();
}
}(this, function () {
// Do KeyboardJS setup in here

return {
    "bind": {
        "key": bindKey,
        "axis": bindAxis
    },
    "activeKeys": getActiveKeys,
    "unbind": {
        "key": unbindKey
    }
};

});

This is based on some universal module boilerplate at umdjs/umd.

Of course completely fine if you do not want to go this route. Just offering an alternative to multiple branches.

only one argument passed to onUpCallback and onUpCallback

Documentation for KeyboardJS.on states:
Both the onUpCallback and the onUpCallback are passed three arguments. The first is the key event, the second is the keys pressed, and the third is the key combo string.

But it seams that only KeyboardEvent is passed.

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.