GithubHelp home page GithubHelp logo

piranha / keymage Goto Github PK

View Code? Open in Web Editor NEW
333.0 13.0 31.0 70 KB

Yet Another JS Keybinding library

License: ISC License

JavaScript 88.84% Makefile 0.90% HTML 10.27%
javascript shortcuts hotkey hotkeys shortcut

keymage's Introduction

keymage.js

Keymage is a small (1.6kb after Closure Compiler and gzip) library for handling key bindings in JavaScript. It supports nested application scopes, has a simple DSL for defining keys and can handle key chords.

Build Status - or check tests in browser

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, as an AMD module or as CommonJS module.

It worth to note that Keymage is on cdnjs which enables you to use it without downloading.

Plus, of course, it's on NPM.

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-k j', function() { alert("Nice!"); });

For this to fire you have to first press both ctrl and k, and then j. This will fire an alert.

There is something to remember: browsers have their own shortcuts, for example ctrl-j in most browsers means "open downloads". And while you can always call e.preventDefault() in usual situation, if ctrl-j is part of a sequence, it's not that easy - you'll get control over what's happening only when the whole sequence is pressed.

So keymage provides you with a means to support this use case. I do not encourage you to override browser hotkeys, but let's imagine you want 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 is a valid part of a bound sequence, including the one triggering your handler. Note that pressing only ctrl-j (without ctrl-t) will still open downloads, keymage looks for sequence of ctrl-t ctrl-j.

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.

Unbinding

And if you ever need to unbind a handler, use this:

keymage.unbind('ctrl-j k', your_handler_function);

Also, keymage(...) returns a function, which unbinds this shortcut when called:

var unbinder = keymage('ctrl-j k', your_handler_function);
unbinder();

keymage's People

Contributors

piranha avatar shvaikalesh avatar volh avatar vsolovyov avatar waldyrious 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

keymage's Issues

Return prepared unbind()-function from keymage()

It's a increasingly popular pattern to return an undo/unbind function as a result to a do/bind function call.

var unbindOk = keymage("o k", ...);

// Later
unbindOk();

The unbindOk also acts as a reflectional variable to verify whether the binding has happened before, for example to prevent duplicate bindings.

Support attaching to keypress and not only keydown

In some occasions, it's desired to be able to attach to the keypress event instead of keydown, especially since some special character combinations are not consistent across devices.

I guess the consistent place to define this in keymage would be the options object.

Use with specific DOM element, don't attach to window

I'm trying to replace combokeys with keymage in a project, since it's considerably smaller when not minified (minfied as well, OFC). However, to support the use case, keymage would need to attach to a specific DOM element and not window, and additionally support cleaning up.

Implementation should be fairly easy, it's mainly a question of what the new API should be and if this is a desired feature(?). Some solutions that come to mind will probably break existing code that assumes keymage would be attached to the window and immediately available.

Make bindings for blessed

Hey, nice library! It would be really cool if I could use this with chjj/blessed, which as you may know is a TUI library like ncurses. Is there any way to change the key listener backend to something other than the browser?

Travis-CI integration

Make tests run under phantomjs. wru supports that, but how do I have single file with tests running in both phantomjs and regular browser?

Does not fully override browser hotkeys

I found this on reddit. Keymage is a really neat tool. I was testing this out and noticed that 'defmod-j c', which you have for the index.html does not work on my browser. Ctrl + J is the native hotkey for downloads and when using that key combination it opens the downloads tab on chrome.

Keymage does work on single combinations modifier + key (e.g. ctrl-q) and it does properly executes preventDefault. When testing ctrl-j on the dummy index.html it does override the opening of the downloads tab.

Andrew

Google Chrome 23.0.1271.95 (Official Build 169798) m
OS Windows
WebKit 537.11 (@135931)
JavaScript V8 3.13.7.5
Flash 11.5.31.2
User Agent Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11

Publish to NPM

It would be great if keymage was published to NPM so Browserify can easily fetch the files.

Allow to unbind key events

Is there a way to unbind key events.

I looked into the tests and the code but didn't found anything.

Is it even possible?

Add meta

The code mentions some weird modifier called alt. For those of us still using emacs, this is an insult.

Please rename to meta so that it works cross-platform (TM).

Add a tag

Hi there, can you tag the latest commit? So we could add keymage to cdnjs. Thanks!

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.