Do you like this project? Please support my Mecha CMS project too. Thank you!

Key 3.0.0

Micro JavaScript hotkey/keymap system.


Type something…

Features

Usage

Browser

<!DOCTYPE html>
<html dir="ltr">
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <p>
      <textarea></textarea>
    </p>
    <script src="./index.min.js"></script>
    <script>
      const map = new Key;
      const self = document.querySelector('textarea');
      self.addEventListener('blur', e => map.pull()); // Reset!
      self.addEventListener('input', e => map.pull()); // Reset!
      let debounce;
      self.addEventListener('keydown', e => {
          map.push(e.key);
          console.log(map.toString());
          debounce && clearTimeout(debounce);
          debounce = setTimeout(() => map.pull(), 1000); // Reset after 1 second idle!
      });
      self.addEventListener('keyup', e => map.pull(e.key));
    </script>
  </body>
</html>

Node.js

Functions and methods in this application are mostly native JavaScript and are intended for use by the browser. Node.js doesn’t know about the DOM, so this kind of practice will probably be used more often to build new browser packages than to be used directly in the Node.js server.

CommonJS

const Key = require('@taufik-nurrohman/key').default;

const map = new Key;

ECMAScript

import Key from '@taufik-nurrohman/key';

const map = new Key;

Examples

Settings

const map = new Key(self);
Name Description
self The object that will becomes the this context in the command.

Methods and Properties

map.command()

Test if current key combination exists.

self.addEventListener('keydown', e => {
    map.push(e.key);
    let command = map.command();
    if (command) {
        console.log(command);
    }
});

Test if current key combination is Control-b.

self.addEventListener('keydown', e => {
    map.push(e.key);
    if (map.command('Control-b')) {
        console.log('Bold!');
    }
});

map.commands

List of commands to be executed on key combination match.

// Simple function
map.commands.bold = function () {
    // Your `bold` function goes here…
    return false; // Return `false` to tell the event that it has to prevent the default effect
};

// Function with argument(s)
map.commands.insertLink = function (href = 'http://') {
    // Your `insertLink` function goes here…
    // Return `void` will be normalized into `true` by `map.fire()` method.
};

Example context usage, using @taufik-nurrohman/text-editor:

import Key from '@taufik-nurrohman/key';
import TextEditor from '@taufik-nurrohman/text-editor';

const editor = new TextEditor(document.querySelector('textarea'));
const map = new Key(editor);

map.commands.bold = function () {
    return this.wrap('<b>', '</b>'), false; // `this` refers to the `editor`
};

map.fire(command)

Execute command data returned by map.command() method.

// …
let command = map.command();
if (command) {
    let value = map.fire(command);
    if (false === value) {
        e.preventDefault();
    } else if (null === value) {
        console.error('Unknown command:', command);
    }
}

map.keys

List of key combination with its command that will be returned by map.command(). Key names follow the KeyboardEvent.prototype.key specification.

// Anonymous function
map.keys['Control-b'] = function () {
    return this.wrap('<b>', '</b>'), false;
};

// Named function without argument(s)
map.keys['Control-b'] = 'bold'; // This will execute `map.commands.bold` command if available

// Named function with argument(s)
map.keys['Control-k'] = ['insertLink', ['http://']]; // This will execute `map.commands.insertLink` command if available

map.pull(key)

Remove key from the queue.

self.addEventListener('blur', e => map.pull());
self.addEventListener('input', e => map.pull());
self.addEventListener('keyup', e => map.pull(e.key));

map.push(key)

Add key to the queue.

self.addEventListener('keydown', e => map.push(e.key));

map.toString()

Return the current key combination.

self.addEventListener('keydown', e => {
    map.push(e.key);
    console.info(map + "");
});

License

Use it for free, pay if you get paid. So, you’ve just benefited financially after using this project? It’s a good idea to share a little financial support with this open source project too. Your support will motivate me to do any further development, as well as to provide voluntary support to overcome problems related to this project.

Thank you! ❤️