Git Product home page Git Product logo

keymage's Introduction

keymage.js

Keymage is a small library for handling key bindings in JavaScript.

It was written out of the fact that no other library supported combination of all necessary features and their design made it easier to write a new one.

Test results.

Features

  • Simple language for defining bindings
  • Key sequences (a-la Emacs chords)
  • Nested scopes
  • Default modifier (defmod key which is command on OS X and control elsewhere)
  • Ability to prevent defaults for whole sequence

Usage

Include keymage.min.js in your page:

<script src="keymage.min.js"></script>

There are no dependencies. It is possible to use library as a simple JS module or as an AMD module.

Defining shortcuts

Keymage exposes a single function, keymage:

// bind on 'a'
keymage('a', function() { alert("You pressed 'a'"); });

// returning false prevents default browser reaction (you can always use
// e.preventDefault(), of course)
keymage('ctrl-e', function() { return false; });

// binding on 'defmod' binds on Command key on OS X and on Control key in other
// systems
keymage('defmod-j', function() { alert("I am fired"); });

Handler function receives two arguments: the original event and the context so you can understand what and why was fired.

The context contains those properties:

  • shortcut is a string you've originally provided for binding
  • scope is a scope which is currently active
  • definitionScope is a scope where this shortcut was defined
keymage('alt-c', function(e, ctx) {
    console.log(ctx.shortcut, ctx.scope, ctx.definitionScope);
});

// -> "alt-c", "", ""

Sequences

Keymage supports key sequences:

keymage('ctrl-j k', function() { alert("Nice!"); });

For this to fire you have to first press both ctrl and j, and then k. Here's the catch though: ctrl-j in most browsers means "open downloads". Which will break your sequence obviously.

And while I encourage you to not override browser hotkeys, let's imagine you have to do that. For this, you can pass an option object as last parameter, having 'preventDefault' property set to true:

keymage('ctrl-t ctrl-j k',
        function() { alert("wow"); },
        {preventDefault: true});

This option will prevent default on every key press which looks like a valid part of a bound sequence (including the one triggering your handler). And in this case it's perfectly legitimate - you're overriding ctrl-j in the middle of sequence, so common browser hotkey will still work.

Scopes

Keymage support nested scopes. This means that your application can have few areas where you can gradually have more and more specific shortcuts. It works like this:

// You can skip scope argument if you want global work-always shortcut
keymage('ctrl-j q', function() { alert("Default scope"); });

// This will fire after "keymage.setScope('chat')"
keymage('chat', 'ctrl-j w', function() { alert("Chat scope"); });

// This will fire after "keymage.setScope('chat.input')"
keymage('chat.input', 'ctrl-j e', function() { alert("Chat.input scope"); });

You can control scopes with helpful pushScope and popScope methods. This way your nested view (or whatever is enabling nested scope) doesn't need to know about parent scope:

keymage.pushScope('chat') // scope is 'chat'

keymage.pushScope('input') // scope is 'chat.input'

keymage.popScope() // scope is 'chat'

keymage.pushScope('deep')
keymage.pushScope('deeper') // scope is 'chat.deep.deeper'

// way to jump out of deep scoping
keymage.popScope('chat') // scope is ''

pushScope returns resulting scope and popScope returns topmost scope it removed (so with parameters it's the one you've asked to remove).

Note that calling popScope with name of a scope which is repeated few times will pop topmost one, i.e.:

keymage.setScope('this.scope.is.deep.scope')
keymage.popScope('scope') // scope is 'this'

Options

Last and optional argument to keymage function is an option object. Here is a list of possible options:

  • preventDefault: when true, calls event.preventDefault() on every key press which looks like a part of defined sequence.

  • context: binding handler will be called with provided object as a context.

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.