A JavaScript library for binding keyboard combos without the pain of key codes and key combo conflicts.

Overview

KeyboardJS

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();
Comments
  • Make it easy to bind to

    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.

    Request 
    opened by jamesarosen 16
  • Whats the best option to enable/disable keys while focus in input fields?

    Whats the best option to enable/disable keys while focus in input fields?

    Hi,

    I find the keyboard bindings are still being applied even when focus is in an input field.

    Any tips/suggestions on how to handle this, eg if an input field has focus, disable/ignore the keyboardjs bindings.

    I am using the latest code on github...

    Thanks, Chris

    Question 
    opened by kimptoc 10
  • Pressing any key while holding the binded key triggers the keydown handler again

    Pressing any key while holding the binded key triggers the keydown handler again

    It only happens when preventRepeat() is not called in the callback function.

    Tested with Chromium 62 under gnu/linux debian testing.

    edit: thanks for the great lib ;)

    Bug Wonky Bindings 
    opened by jean-emmanuel 9
  • Bug when pressing Cmd

    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

    Unfixable 
    opened by aboutwout 9
  • Modernize and update the library to es6

    Modernize and update the library to es6

    This PR basically modernizes the library with the following features:

    • Code updated to es6: much more readable code taking all advantages of the latest version of the language :)
    • Uses webpack over browserify
    • Adds yarn lock
    opened by alexjoverm 8
  • How to watch and then do something with all keys...

    How to watch and then do something with all keys...

    How do I pass every pressed and released key to keyboardJS? For example:

          keyboardJS.bind(globalKey, function(e) {
              e.preventRepeat();
              console.log(globalKey+'is pressed');
          }, function(e) {
              console.log(globalKey+'is released');
          });
    
    opened by spencerthayer 7
  • Delay

    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?

    Question 
    opened by JAStanton 7
  • What is the desired behavior of preventRepeat?

    What is the desired behavior of preventRepeat?

    I used the exact sample called "Prevent keydown repeat" from Readme. Results I'm getting: after pressing the A key, "a is pressed" is printed once. Holding the key doesn't result in printing it more times - correct. But after releasing the key and pressing it again, nothing is printed - so the combo works in fact only once. Is it correct behavior or should it trigger again after releasing the key and pressing it again?

    Bug 
    opened by ianshade 6
  • Keybinding combinations - action does not change when one (not both) keys is not lifted.

    Keybinding combinations - action does not change when one (not both) keys is not lifted.

    So here's my issue:

    I use command+right to switch tabs to the right and command+left to switch to tabs to the left. If I hold down command, press command+right things work as expected. But when I press command+left (while continuing to holding down the command key) the tab to the right is again selected. Things work fine when I lift up the command key in between actions.

    Bug 
    opened by iamdevonbutler 6
  • added ability to manually remove active keys (re #63)

    added ability to manually remove active keys (re #63)

    Now active keys will be removed the only when meta key is pressed up ( #19 ). But in this case we catch a bug #63.

    I found the easy solution: manually remove handled active keys. For example:

    kb.on('cmd + c', copy);
    kb.on('cmd + v', paste);
    
    var copy = function () {
      // do copy
      kb.removeActiveKey('c');
    };
    
    var paste = function () {
      // do paste
      kb.removeActiveKey('v');
    };
    

    Of course, it's not very user friendly solution, but it's tiny and it's works just now. Can you add the PR as temporary patch?

    opened by A 6
  • Support Keyboard States

    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.

    Request 
    opened by burtlo 5
  • Question: is it possible to unbind browser default shortcut like Command + W / Control + W

    Question: is it possible to unbind browser default shortcut like Command + W / Control + W

    Hi, I'm trying to bind Command + W / Control + W to another function. I tried:

    keyboardJS.unbind("command + w");
    keyboardJS.bind("command + w", (e) => {
        // some other functions
    });
    

    but the browser will just close my page... any advice will be appreciated XD Thank you in advance

    opened by TATOAO 0
  • Bind characters with repetition

    Bind characters with repetition

    Describe the bug I am trying to bind a key combination like "k > k".

    Example code

    keyboardjs.bind("k > k", () => {
        console.log("k was pressed and then again k was pressed")
    });
    
    

    Expected behavior Event should have been triggered

    Enviroment

    • OS: Windows
    • Browser Edge
    • Version 2.7.0
    opened by vishnuvardhan-s 0
  • Secondary key symbols not firing event

    Secondary key symbols not firing event

    Describe the bug Listening secondary key symbols ([email protected]#$%^&*()_+?) not firing event. However binding primary key together with secondary will work.

    Example code

    let keys = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '?'];
    keyboardjs.on(keys, (event) => {
      console.log(event); // no output
    });
    
    keys = [...keys, '1', '/'];
    // keys = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '?', '1', '/']
    keyboardjs.on(keys, (event) => {
      console.log(event); // output from "!", "?", "/", "1"
    });
    

    Expected behavior Expecting console.log output with event data when pressing Shift + Digit or other key, but nothing in console.

    Enviroment (please include the following info):

    • OS: macOS
    • Browser Chrome
    • Version 2.6.4

    Additional context Maybe it's breaking change, but version 2.5.1 works this way.

    opened by attenzione 1
  • [BUG] callback gets call incorrectly with incorrect key

    [BUG] callback gets call incorrectly with incorrect key

    Describe the bug

    The callback gets called incorrectly on mac.

    Example code

    keyboardJS.bind('c', () => console.log('c called!'));
    
    • When I press c, it gets called, which is correct.
    • When I press shift + c, it gets called, which is incorrect.
    • When I press command + c, it gets called, which is incorrect.

    Here: https://jsfiddle.net/p7Lbz9uh/

    Expected behavior

    • When I press shift + c, the callback should not be called.
    • When I press command + c, the callback should not be called.

    Enviroment (please include the following info):

    Additional context

    When I do:

    keyboardJS.bind('c', () => console.log('c got called!'));
    keyboardJS.bind('command + c', () => console.log('command + c got called!'));
    

    The correct callback gets called, but shift + c will still say c got called!, but when I do:

    keyboardJS.bind('c', () => console.log('c got called!'));
    keyboardJS.bind('command + c', () => console.log('command + c got called!'));
    keyboardJS.bind('shift + c', () => console.log('shift + c got called!'));
    

    The bug is not existent. https://jsfiddle.net/p7Lbz9uh/1/

    opened by aprilmintacpineda 0
  • unbind keys from a specific context

    unbind keys from a specific context

    What would you like to see added to KeyboardJS?

    keyboardJS.reset('contextName');

    What problem are you trying to solve?

    How to unbind only the keys which belong to a specific context? Currently using reset() globally.

    Additional comments

    Request 
    opened by phanirithvij 0
  • Releasing a binding when another activates

    Releasing a binding when another activates

    I'm building an 3D editor in the browser and attempting to use the following bindings:

    • w a s d to move the camera forward/back/strafe-left/strafe-right
    • shift to move the camera down
    • space to move the camera up
    • mod + z to undo changes
    • shift + mod + z to redo changes

    The problem i'm facing is that moving the camera down (shift) and the redo function (shift + mod + z) conflict with each other:

    KeyboardJS.bind(
      'shift',
      () => console.log('camera: move down'),
      () => console.log('camera: stop moving down')
    )
    KeyboardJS.bind('mod + shift + z', () => console.log('redo'))
    

    Typically with undo/redo, when redoing something you would hold down mod + shift and then tap z multiple times to redo a bunch of changes in the editor. The problem is that the shift keydown bind (for moving the camera down) triggers immediately and his keyup event doesn't happen until you release all the keys. This results in the camera moving downward while you're redoing a bunch of changes.

    I think something like KeyboardJS.releaseBind('shift') would be useful, as we could put it in the mod + shift + z binding to immediately fire the keyup event for the shift binding, effectively cancelling it.

    KeyboardJS.bind(
      'shift',
      () => console.log('camera: move down'),
      () => console.log('camera: stop moving down')
    )
    KeyboardJS.bind('mod+shift+z', () => {
      KeyboardJS.releaseBind('shift')
      console.log('redo')
    })
    

    I can't seem to find any workarounds in the mean time, do you have any thoughts on this?

    By the way, KeyboardJS is the most robust library i've found so far for browser based editors and games. The others (mousetrap, hotkeys etc) are all missing essential features for this use-case, for example releasing keys on window blur, cmd keyup events etc. Kudos to you for building such a useful package.

    Request 
    opened by ashconnell 1
Releases(v2.6.2)
Owner
Robert Hurst
Lover of open source, and modern software.
Robert Hurst
Knwl.js is a Javascript library that parses through text for dates, times, phone numbers, emails, places, and more.

Knwl.js Knwl.js is a Javascript library that parses through text for dates, times, phone numbers, emails, places, and more. Project Future The future

Ben Moore 5.3k Nov 27, 2022
Pretty diff to html javascript library (diff2html)

diff2html diff2html generates pretty HTML diffs from git diff or unified diff output. Table of Contents Features Online Example Distributions Usage Di

Rodrigo Fernandes 2.3k Nov 23, 2022
JavaScript parser for FIGlet fonts

_______ _________ _______ _ _______ _________ _________ _______ ( ____ \\__ __/( ____ \( \ ( ____ \\__ __/ \__ _/(

Scott González 114 Oct 15, 2022
Clock and task scheduler for node.js applications, providing extensive control of time and callback scheduling in prod and test code

#zeit A node.js clock and scheduler, intended to take place of the global V8 object for manipulation of time and task scheduling which would be handle

David Denton 12 Dec 21, 2021
Encodes and decodes towns in clipboard (text) into various other formats

Townsclipper Townscaper clipboard data format converter. Encodes and decodes towns in clipboard (text) into various other formats. For example, it can

Álvaro Cuesta 26 Jul 18, 2022
A JavaScript library for binding keyboard combos without the pain of key codes and key combo conflicts.

KeyboardJS KeyboardJS is a library for use in the browser (node.js compatible). It Allows developers to easily setup key bindings. Use key combos to s

Robert Hurst 2k Nov 24, 2022
⚡️The Fullstack React Framework — built on Next.js

The Fullstack React Framework "Zero-API" Data Layer — Built on Next.js — Inspired by Ruby on Rails Read the Documentation “Zero-API” data layer lets y

⚡️Blitz 12.3k Nov 21, 2022
A keyboard input capturing utility in which any key can be a modifier key.

Keypress Version 2.1.5 Keypress is a robust keyboard input capturing Javascript utility focused on input for games. For details and documentation, ple

David Mauro 3.2k Nov 27, 2022
Extract the JSON payload from SHC QR codes (i.e Québec Covid Vaccination QR Codes)

shc-extractor Extract the JSON payload from SHC QR Codes (i.e Québec COVID Vaccination QR Codes) Introduction Dans les prochains jours/semaines, les q

Olivier Brassard 162 Nov 10, 2022
Discord-Bot - You can use the discord bot codes that are updated in every video of the codes I use in the discord bot making series that I have published on my youtube channel.

Discord-Bot You can use the discord bot codes that are updated in every video of the codes I use in the discord bot making series that I have publishe

Umut Bayraktar 110 Nov 24, 2022
A music NFT experience. Turning pain into art.

Music NFTs - Catalog Factory Curation as a Public Good Official submission for Zora Hackathon at ETH Global. music nfts + Zora V3. All minted music nf

Erick Martinez Jr. 12 Sep 24, 2022
Multiple Selection Combo Box using Bootstrap 3

MagicSuggest v2.1.6 Bug Fix (fix) Disabled arbitrary HTML and SCRIPT execution on input. MagicSuggest v2.1.5 (fix) prepend close button instead of app

null 1.3k Nov 16, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Remote Keyboard Tutoring System is a web-based system that can be attached to any keyboard synthesizer through a MIDI connector.

The Remote Keyboard Tutoring System is a web-based system that can be attached to any (electronic) keyboard synthesizer through a MIDI connector. Once our system is connected to the keyboard, the user can interactively learn, play or teach in combination with the web application that we provide.

Department of Computer Engineering, University of Peradeniya 3 Nov 15, 2022
Merge multiple Prisma schema files, model inheritance, resolving name conflicts and timings reports, all in a simple tool.

Prisma Util What is Prisma Util? • How to use? • The configuration file • Support What is Prisma Util? Prisma Util is an easy to use tool that merges

David Hancu 14 Nov 16, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 13 Jul 1, 2022
A Virtual Interactive Keyboard which replicates every key you press and a Text-Area in which everything is written and can be copied to the clipboard with a click of a button.

A Virtual Interactive Keyboard which replicates every key you press and a Text-Area in which everything is written and can be copied to the clipboard with a click of a button.

Devang Joshi 1 Mar 1, 2021
jQuery Hotkeys lets you watch for keyboard events anywhere in your code supporting almost any key combination.

jQuery.Hotkeys #About jQuery Hotkeys is a plug-in that lets you easily add and remove handlers for keyboard events anywhere in your code supporting al

John Resig 2.6k Nov 22, 2022
An easy peasy UI binding library.

Peasy UI This is the repository for Peasy UI, a small-ish and relatively easy to use UI binding library. Introduction Peasy UI provides uncomplicated

null 8 Nov 8, 2022