npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@peter.naydenov/shortcuts

v3.1.1

Published

Context control of shortcuts based on keyboard and mouse events

Downloads

43

Readme

Shortcuts (@peter.naydenov/shortcuts)

version license GitHub issues npm bundle size

Describe all page activities as list of shortcuts wrapped in contexts. Switch among available contexts. Library has a plugin system to extend the possible shortcut names/event coverage. Plugins role is to convert DOM events to shortcut strings, then the core part will trigger the action functions related to the shortcut. At the moment we have 2 plugins:

  • key - converts keyboard events to shortcut names;
  • click - converts mouse events to shortcut names;

Planned work on the plugins for scroll, drag-drop, input-change, etc...

Shortcut Description Rules

The shortcuts definition includes a context name and a set of rules(object). The rules are a set of key-value pairs. The key is a shortcut name and the value is a function or array of functions, to be executed when the shortcut is triggered (action function).

// { context: { shortcutName: actionFunction } }
// or
// { context: { shortcutName: [ actionFunction1, actionFunction2 ] }}

// Shortcut definition object:
{
    contextName : {
                    shortcutName : function () {
                                                // do something
                                        }
                    , shortcutName : [ 
                                              function action1() {
                                                        // do something
                                                }
                                            , function action2() {
                                                        // do something
                                                }
                                    ]
                }
}
// shortcutName after v.3.0.0 have a plugin prefix. - 'pluginPrefix:shortcutName'. 
// For example:  'key:s+alt'   - for 's+alt' shortcut that is handled by 'key' plugin.

Load a shortcut definition by calling load method.

// for es6 module projects:
include { shortcuts, pluginKey, pluginClick } from '@peter.naydenov/shortcuts'
// for commonjs projects:
const { shortcuts, pluginKey, pluginClick } = require('@peter.naydenov/shortcuts')



const short = shortcuts ();
// Load a needed plugins
// short.enablePlugin ( pluginCode, ?pluginOptions )
short.enablePlugin ( pluginKey ) 
short.enablePlugin ( pluginClick )
// Load a shortcut definition
short.load ( shortcutDefinition )

Shortcuts are working only if contex is active. To activate a context call changeContext method.

short.changeContext ( contextName )

To deactivate a context without starting other context, call changeContext method without arguments.

short.changeContext ()

Shortcuts context has note that works like sub-contexts. Every shortcut function receives a context and note as arguments, so you can have fine control over the context.

short.setNote ( 'special' ) // set note to 'special'
short.setNote () // remove the note

The idea of note is to minimize the number of contexts if they are very simular. You can use same context but change the note and control the shortcut execution from inside of the action function by checking the note.

{
    contextName : {
                    shortcutName : function ( {context, note} ) {
                                        if ( note === 'special' ) {
                                                        // do something
                                            }
                                    }
                }
}

Context and notes are available inside action functions but you can check them from outside too. Check current context by calling getContext method.

short.getContext ()

Check notes by calling getNote method.

short.getNote ()

Plugin 'click' Shortcut Descriptions

Mouse event name is build from the following parts:

 // click:<mouse button>-<number of clicks>-<modifier key>-<modifier key>-<modifier key>
 // example:
 // click: left-2 -> for double click with left mouse button
 // click: right-3 -> for triple click with right mouse button

 // mouse button options: left, right, middle

The modifier keys ctrl, alt, and shift are supported. They are added to the mouse event by sign -:

 // example:
 // click: left-1-ctrl -> for single click with left mouse button and ctrl key pressed

Order of describing click event and modifier keys is not important.

 // example:
 // click: ctrl-left-1 -> same as above

 // These 3 descriptions are equal:
 // click: left-1-ctrl-alt-shift
 // click: alt-shift-left-1-ctrl
 // click: left-1-shift-ctrl-alt

Multiple clicks are detected automatically by time interval between clicks. The default interval is 320ms but you can change it by setting mouseWait click plugin option.

 short.enablePlugin ( pluginClick, { mouseWait: 500 }) // set the interval to 500ms

Read more in section Options.

Define a Click Targets

Target HTML elements for shortcuts are defined by data-click attribute. The value of the attribute is the name of the target. Example:

<button data-click="id">Click me</button>
<!-- target name is 'id' -->

Attribute is customizable by setting clickTarget click plugin option. Read more in section Options.

If current shortcuts context contain definition for 2 or more clicks, this may slow down the execution of single shortcuts because shortcuts will wait for the time interval to detect multiple clicks. To avoid this for specific targets, you can set data-quick-click attribute to the target element. Example:

<button data-click="id" data-quick-click>Click me</button>
<!-- target name is 'id' and will not wait for more then 1 click -->

Using a tag is a special case. It's always recognized as a target, and always with attribute data-quick-click. No need to set it manually. Example:

<a href="#">Click me</a>
<!-- Recognized as a target and will not wait for more then 1 click -->
<!-- Take care for the action from shortcut `click: left-1`. -->

Clicking on tag will execute default browser behaviour. In your click:left-1 action function you can take the control. Example:

{
    contextName : {
                    'click:left-1' : function ( {target, event} ) {
                                        if ( target.tagName === 'A' ) { // To prevent default action on <a> tag
                                                  event.preventDefault ()
                                                  // do something...
                                            }
                                    }
                }
}

Plugin 'key' Event Descriptions

Keyboard event description contains a key name and a modifier keys if they are used. The modifier keys ctrl, alt, and shift are supported. They are added to the keyboard event by sign +:

 // example:
 // key: ctrl+alt+shift+a -> for key 'a' with ctrl, alt and shift keys pressed

Keyboard event description support a shortcut sequenses. These means that you can press a sequence of keys to trigger a shortcut. The sequence elements are separated by sign "," ( coma ):

 // example:
 // key: a,b,c -> for key 'a' then key 'b' then key 'c'

 // key: g+shift,o,t,o -> for key 'g' with shift, then key 'o', then key 't' then key 'o'

Order of describing keyboard event and modifier keys is not important, but sequence elements are:

 // example:
 // key: a+ctrl,l,o,t -> a with ctrl, then l, then o, then t
 // this is equal to:
 // key: ctrl+a,l,o,t
 // but not equal to:
 // key: ctrl+a,o,t,l

Keyboard sequence is detected automatically by time interval between key presses. The default interval is 480ms but you can change it by setting keyWait key plugin option. Read more in section Options.

There is a way to disable automatic sequence detection and mark the begining and the end of the sequense by using a keyboard action functions. Read more in section Keyboard Action Functions.

Special characters that are available for your shortcut descriptions:

  • 'left' - left arrow key
  • 'right' - right arrow key
  • 'up' - up arrow key
  • 'down' - down arrow key
  • 'enter' - enter key
  • 'space' - space key
  • 'esc' - escape key
  • 'tab' - tab key
  • 'backspace' - backspace key
  • '=' - equal key
  • F1 - F12 - function keys
  • '/' - slash key
  • '\' - backslash key
  • '[' - open square bracket key
  • ']' - close square bracket key
  • '`' - backtick key

Warning: For keys with two symbols(look at the keyboard), in shortcut description use the lower one. Examples: Use '=' instead of '+', use '/' instead of '?', etc. Modifier keys are available for special characters too.

Warining: Some of the shortcuts are used by OS and the browswer, so they are not available.

Action Functions

Action functions are called when a shortcut is triggered. There is a difference among plugin action functions. Arguments are slightly different.

Keyboard Action Functions

Description of key plugin action functions is:

function myKeyHandler ({
                  context   // (string) Name of the current context;
                , note      // (string) Name of the note or null if note isn't set;
                , dependencies // (object) Object with dependencies that you have set by calling `setDependencies` method;
                , wait      // (function). Call it to stop a sequence timer and write shortcut sequence without a timer.
                , end       // (function). Recover the sequence timer;
                , ignore    // (function). Call it to ignore the current shortcut from the sequence;
                , isWaiting // (boolean). True if the sequence timer is active;
                        }) {
    // Body of the handler. Do something...
}

Mouse Action Functions

Click plugin action functions can be described like:

function myMouseHandler ({
                  context     // (string) Name of the current context;
                , note        // (string) Name of the note or null if note isn't set;
                , dependencies // (object) Object with dependencies that you have set by calling `setDependencies` method;
                , target      // (DOM element). Target element of the mouse event;
                , targetProps // (object). Coordinates of the target element (top, left, right, bottom, width, height) or null if target element is not available;
                , x           // (number). X coordinate of the target element;
                , y           // (number). Y coordinate of the target element;
                , event       // (object). Original mouse event object;
          }) {
    // Body of the handler. Do something...
}

Methods

Description of the methods of shortcut instance:

  load            : 'Load and extend a shortcut definition.'
, unload          : 'Remove a shortcut context with all its shortcuts.'

, enablePlugin    : 'Enable a plugin.'
, disablePlugin   : 'Disable a plugin.'
, mutePlugin      : 'Mute a plugin. All events for the plugin will be ignored.'
, unmutePlugin    : 'Unmute a plugin. All events for the plugin will be listened again.'

, changeContext   : 'Switch to existing shortcut context or shitch off the context(if no argument).'
, getContext      : 'Return a name of current context or null if there is no context selected'
, emit            : 'Trigger a shortcut or custom event programmatically.'
, pause           : 'Stop listening for shortcuts.'
, resume          : 'Resume listening for shortcuts.'
, listContexts    : 'Return list of available contexts.'
, listShortcuts   : 'Return list of shortcuts per context.'
, getNote         : `Return a name of current note or null if note isn't set`
, setNote         : 'Set a note to current context.'
, setDependencies : 'Set dependencies that will be available in action functions.'
, getDependencies : 'Return a dependencies object.'

How to 'pause' and 'resume'?

When you want to stop execution of shortcuts, call short.pause(). It's equal to short.pause('*'). Will stop all shortcuts in the active context. Stop for single shortcut is by calling short.pause('shortcutName'). To resume shortcuts execution call short.resume(). It's equal to short.resume('*'). Will resume all shortcuts in the active context. Resume for single shortcut is by calling short.resume('shortcutName').

// pause all shortcuts in the active context
short.pause () // will stop all shortcuts in the active context
short.resume ( 'shift+a' ) // will resume only 'shift+a' shortcut

short.resume ('*') // will resume all shortcuts

Options

Shortcut receives options during the start. Here is the list of available options:

 onShortcut    : 'Callback function that is called when a shortcut is triggered. Default value - false'
const short = shortcut ({onShortcut: (shortcut) => console.log(shortcut) }) // Log in console each triggered shortcut

Plugin 'key' options

  keyWait       : 'Timeout for entering shortcut sequence in ms. Default value - 480'
, streamKeys    : 'False or a callback function that is called when a key is pressed. Default value - false'

Plugin 'click' options

  mouseWait     : 'Timeout for entering multiple mouse events. Default value - 320.'
, clickTarget   : 'Data attribute name to recognize click items in HTML. Default value - click' // data attribute 'click' means attribute ( data-click='someName' )

Plugin options are provided as a second argument during the plugin enabling. It's look like this:

  short.enablePlugin ( pluginKey, {
                             keyWait: 500 // set the interval to 500ms
                           , streamKeys: (key) => console.log(key)   // Log in console each pressed key
                      })

  short.enablePlugin ( pluginClick, {
                             mouseWait: 200     // set the interval between multiple clicks to 200ms
                           , clickTarget: 'puk' // data attribute 'puk' means attribute ( data-puk='someName' )
                      })

onShortcut option

 function onShortcut ({ shortcut, context, note, dependencies }) {
        // shortcut - (string) Triggered shortcut name
        // context - (string) Name of the current context
        // note - (string) Name of the note or null if note isn't set
        // dependencies - (object) Object with dependencies that you have set by calling `setDependencies` method
    }

streamKeys option

 function streamKeys ({ key, context, note, dependencies }) {
        // key - (string) Pressed key name
        // context - (string) Name of the current context
        // note - (string) Name of the note or null if note isn't set
        // dependencies - (object) Object with dependencies that you have set by calling `setDependencies` method
    }

Links

Credits

'@peter.naydenov/shortcuts' was created and supported by Peter Naydenov.

License

'@peter.naydenov/shortcuts' is released under the MIT License.