GithubHelp home page GithubHelp logo

omridevk / ng-keyboard-shortcuts Goto Github PK

View Code? Open in Web Editor NEW
145.0 5.0 34.0 7.52 MB

Dead Simple Keyboard Shortcuts Management for Angular

Home Page: https://ng-keyboard-shortcuts.vercel.app/

JavaScript 2.66% TypeScript 89.98% HTML 5.57% SCSS 1.79%
angular javascript angular2-service angular2 keyboard-shortcuts ng-keyboard-shortcuts shortcut angular7 angular8 keyboard

ng-keyboard-shortcuts's Introduction

ng-keyboard-shortcuts

An Angular module that provides a declarative API using components/directive to manage Keyboard shortcuts in scalable way.

This documentation is for version 7.0.0+ (8,9) and any future versions. For older versions (2.0.0/6.0.0) please click here

See demo here:
demo

important note

We recommend to update to version 7.0.0 and above and use the new component API which has a better memory management than previous version.

Compatible with Angular 5+

Install:

NPM
Angular latest

npm install --save ng-keyboard-shortcuts

Angular 8/9

npm install --save ng-keyboard-shortcuts@^9.0.0

Angular 7

npm install --save ng-keyboard-shortcuts@^7.0.0

Yarn
Angular latest

yarn add ng-keyboard-shortcuts

Angular 8/9

npm add ng-keyboard-shortcuts@^9.0.0

Angular 7

yarn add ng-keyboard-shortcuts@^7.0.0

Setup:

import { KeyboardShortcutsModule }     from 'ng-keyboard-shortcuts';  
  
@NgModule({  
    declarations: [  
    ],  
    imports: [  
        BrowserModule,  
        KeyboardShortcutsModule.forRoot()  
    ],  
    bootstrap: [AppComponent]  
})  
export class AppModule {  
}  

Usage:

Combinations

key combinations are used with meta keys like control, shift, command, etc... and are defined using plus(+) sign as a separator. there can be multiple combinations for the same command, so either of the key combination will trigger the callback. Since combinations uses the plus sign as a seperator, if you want to bind to the actual + charachater, you will need to use "plus" instead.

Examples:

   [
       {
            key: ["cmd + a"],
            command: (output: ShortcutEventOutput) => console.log("command + a", output),
        },
        {
            key: "ctrl + a",
            preventDefault: true,
            command: (output: ShortcutEventOutput) => console.log("control + a", output),
            
        },
        {
            key: "ctrl + plus",
            preventDefault: true,
            command: (output: ShortcutEventOutput) => console.log("control + plus key", output),
        }
    ]

Sequences

Sequences can be used to support gmail like actions where you click "g" then "a", or "g" then "o" to perform certain actions.

Important note

The library can get very confused if you have a single key handler that uses the same key that a sequence starts with. This is because it can't tell if you are starting the sequence or if you are pressing that key on its own.

To counter this, there is a 500ms delay(only when single key is used in the beginning of another sequence, so it won't affect performance) . This gives the library time to wait for a more complete sequence, otherwise the single sequence will be triggered.

for example: binding both "? a" and "?", then clicking "?" will trigger the "?" callback, but only after 500ms delay. However, in all other cases there's no delay in execution of the callback (unless debounceTime is provided)

Examples:

This library supports gmail style sequences:

   [{
        key: ["g a"],
        command: (output: ShortcutEventOutput) => console.log("? a", output),
    }]

konami code:

    [{
         key: ["up up down down left right left right b a enter"],
         label: "Sequences",
         description: "Konami code!",
         command: (output: ShortcutEventOutput) => console.log("Konami code!!!", output),
    }]

Sequences can be used inside components or directives and are declared without the plus(+) sign, for example: key: ["a b c"] will require clicking, a, then b, then c.

Components:

ng-keyboard-shortcuts

Component that can be used across the app to bind to various shortcuts

Inputs:

Name Type Default Description
shortcuts ShortcutInput / ShortcutInput[] [] List of shortcut inputs types see types
disabled boolean false disable the shortcuts for the component

Methods:

Name Input Return Description
select string - key to listen to events (example: 'cmd + e') Observable<ShortcutEventOutput> Listen to specific key events (will only work for registered keys)
  
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from "@angular/core";  
import { ShortcutInput, ShortcutEventOutput, KeyboardShortcutsComponent } from "ng-keyboard-shortcuts";  
  
@Component({  
    selector: 'demo-component',  
    template: "<ng-keyboard-shortcuts [shortcuts]="shortcuts"></ng-keyboard-shortcuts>"  
})  
export class DemoComponent implements AfterViewInit {  
  
    shortcuts: ShortcutInput[] = [];  
    @ViewChild('input') input: ElementRef;  
  
    ngAfterViewInit(): void {  
        this.shortcuts.push(  
            {  
                key: "ctrl + t",  
                preventDefault: true,  
                allowIn: [AllowIn.Textarea, AllowIn.Input],  
                command: e => console.log("clicked " , e.key)  
            },
           {
                key: ["? a"],
                label: "Sequences",
                description: "Sequence ? and a",
                command: (output: ShortcutEventOutput) => console.log("? a", output),
                preventDefault: true
            },            
            {
                key: ["up up down down left right left right b a enter"],
                label: "Sequences",
                description: "Konami code!",
                command: (output: ShortcutEventOutput) => console.log("Konami code!!!", output),
            },
            {  
                key: "cmd + shift + f",  
                command: (output: ShortcutEventOutput) => console.log(output),  
                preventDefault: true,  
                throttleTime: 250,  
                target: this.input.nativeElement  
            },  
            {  
                key: ["cmd + =", "cmd + z"],  
                command: (output: ShortcutEventOutput) => console.log(output),  
                preventDefault: true  
            },  
            {  
                key: "cmd + f",  
                command: (output: ShortcutEventOutput) => console.log(output),  
                preventDefault: true  
            }  
        );  
  
        this.keyboard.select("cmd + f").subscribe(e => console.log(e));  
    }  
  
    @ViewChild(KeyboardShortcutsComponent) private keyboard: KeyboardShortcutsComponent;  
  
}  

ng-keyboard-shortcuts-help

  1. Make sure to install @angular/animations ( npm install --save @angular/animations or yarn add @angular/animations
  2. Add BrowserAnimationsModule to your app.module imports

Can be used to show an help screen ( will be attached to body and be shown as a modal)

Should be placed in the root of your app, preferably in app.component.html

Inputs

Name Type default description
key string none The key to show/hide the help modal
keyDescription string none Description to show in the menu shortcut list for the toggle shortcut
keyLabel string none Label that can be used to group shortcuts together in the help menu
closeKey string none Close key to be used to close the modal
closeKeyDescription string none Description to show in the menu shortcut list for closing the modal shortcut
closeKeyLabel string none Label that can be used to group shortcuts together in the help menu
title string "Keyboard shortcuts" The title of the help screen
emptyMessage string "No shortcuts available" What message to show when no commands are registered when help modal is opened.
disableScrolling boolean true Whether to disable body scrolling when modal help screen is opened.

Methods:

Name Input Return Description
hide void KeyboardShortcutsHelpComponent Programmatically hide the modal
reveal void KeyboardShortcutsHelpComponent Programmatically hide the modal
visible void boolean Check whether the modal is visible or not.
toggle void KeyboardShortcutsHelpComponent Programmatically toggle the modal visibility

Methods:

Name Input Return Description
select string - key to listen to events (example: 'cmd + e') Observable<ShortcutEventOutput> Listen to specific key events (will only work for registered keys)

app.component.ts

import { Component } from "@angular/core";  
  
@Component({  
  selector: "app-root",  
  template: "./app.component.html",  
  styleUrls: ["./app.component.css"]  
})  
export class AppComponent {  
  title = "Hello";  
}  
  

app.component.html

<div style="text-align:center">  
   <h1>  
      Welcome to {{ title }}!  
   </h1>  
   <ng-keyboard-shortcuts-help [key]="'f1'" [closeKey]="'escape'" [title]="'Help'"></ng-keyboard-shortcuts-help>  
</div>  
  

Directive

ngKeyboardShortcuts

Directive can only be used for focusable elements, such as textarea, select, input, etc...

Important:

The shortcut then will only be active while the element is in focus.

Inputs

Name Type default description
ngKeyboardShortcuts Shortcut / Shortcut [] List of shortcuts see types
disabled boolean false disable the shortcuts for the directive
disableScrolling boolean true disable body scrolling while modal is open

Example

import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from "@angular/core";  
import { ShortcutInput, ShortcutEventOutput, KeyboardShortcutsComponent } from "ng-keyboard-shortcuts";  
  
@Component({  
    selector: 'demo-component',  
    template: "<input [ngKeyboardShortcuts]="shortcuts" />"  
})  
export class DemoComponent implements AfterViewInit {  
  
    shortcuts: ShortcutInput[] = [];  
    @ViewChild('input') input: ElementRef;  
  
    ngAfterViewInit(): void {  
        this.shortcuts.push({  
            key: "cmd + e",  
            label: "test",  
            description: "hello world",  
            command: () => console.log('directive cmd + e'),  
            preventDefault: true  
        });  
  
        this.keyboard.select("cmd + f").subscribe(e => console.log(e));  
    }  
  
    @ViewChild(KeyboardShortcutsComponent) private keyboard: KeyboardShortcutsComponent;  
  
}  

Service

KeyboardShortcutsHelpService

Singleton service that can be used to render a custom help screen. (used to build the Built in help component)
Provides access to all registered shortcuts in the app using Observable that updates on shortcuts changes.
Since shortcuts can be added or removed during the lifecycle of the app, an observable data structure needed to be used.

properties type description
shortcuts$ Observable<{ key: string, label: string, description: string }[]> Array of registered shortcuts across the whole app

KeyboardShortcutsSelectService

A singleton service that can be used globally to listen to any registered shortcut:

Name Input Return Description
select string - key to listen to events (example: 'cmd + e') Observable<ShortcutEventOutput> Listen to specific key events (will only work for registered keys)

API:

Types:

AllowIn

export enum AllowIn {  
    Textarea = 'TEXTAREA',  
    Input = 'INPUT',  
    Select = "SELECT"  
}  

Shortcut

Used for Directive input

export interface Shortcut {  
  
    key: string | string[];  
  
    /**  
     * callback to be called when shortcut is pressed.  
     * @param event - the event out  
     */  
    command(event: ShortcutEventOutput): any;  
  
    /**  
     * Description for the command can be used for rendering help menu.  
     */  
    description?: string;  
  
    /**  
     * How much time to throttle in ms.  
     */  
    throttleTime?: number;  
  
    /**  
     * Label, can be used for grouping commands.  
     */  
    label?: string;  
  
    /**  
     * Prevent browser default, default: false  
     */  
    preventDefault?: boolean;  
}  

ShortcutInput

Used for the component as input.

export interface ShortcutInput extends Shortcut {  
    /**  
     * textarea, select and input are ignored by default, this is used to override  
     * this behavior.  
     * allow in node names, accepts: ["TEXTAREA", "SELECT", "INPUT]  
     */  
    allowIn?: AllowIn[];  
    /**  
     * Only trigger the command when the target is in focus.  
     */  
    target?: HTMLElement;  
}  

ShortcutEventOutput

type = ShortcutEventOutput {  
    event: KeyboardEvent;  
    key: string | string[];  
}  
  

Building

npm run build-lib

Publishing

  1. npm run build-lib
  2. npm publish dist/ng-keyboard-shortcuts

License

This project is licensed under the MIT License - see the LICENSE file for details

ng-keyboard-shortcuts's People

Contributors

dependabot-preview[bot] avatar dependabot[bot] avatar domdeger avatar ffried avatar gitter-badger avatar hunzaboy avatar memcardio avatar miguelchico avatar omridevk avatar stu01509 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

ng-keyboard-shortcuts's Issues

Please update the peerDependencies to support Angular 8 (and later versions)

Your major package.json seems to be updated to support Angular 8 (churn #32)

After installing version 8.2.3, i do get the npm warnings.

npm WARN [email protected] requires a peer of @angular/common@^7.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of core-js@^2.5.4 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of @angular/core@^7.0.0 but none is installed. You must install peer dependencies yourself.

Can we just go ahead and consider it safe to ignore the npm warnings ?

Prevent Default not working as expected

Describe the bug
I have created a single character shortcut (F). But when press e.g Ctrl+ F, it triggers both of them. However, I don't want it to trigger my custom shortcut, as its not the complete shortcut.

this.shortcuts.push({ key: ['f'], label: 'Label', description: 'shortcut description', command: e => { }, preventDefault: false });

To Reproduce
Steps to reproduce the behavior:

  1. Create a Shortcut for Character F
  2. Press Ctrl + F
  3. It will open the normal find of the browser AND additionally, it runs my shortcut afterward.

Expected behavior
It should not run my shortcut.

Additional context
Add any other context about the problem here.

Do not display help causes one event too many after disabled

Hello! I started to use this package in order to implement special navigation in my app. In this app, I have a custom table with a selected object by index : ArrowDown to increase index, ArrowUp to decrease. When an event occurs and disables the shortcuts, these work once too more.
Here an example of the problem : https://codesandbox.io/s/ng-keyboard-shortcuts-issue-with-problem-ey691

To bypass this problem, we just need to add the help component : https://codesandbox.io/s/ng-keyboard-shortcuts-issue-81hgk. (the only changed file is app.component.html).

We shouldn't be forced to display the help component I think. Do you have any idea about that ?

PS : Thanks for your very useful package!

I would like to use KeyboardShortcutsService by itself

Is your feature request related to a problem? Please describe.
I would like to use KeyboardShortcutsService by itself

Describe the solution you'd like

import { KeyboardShortcutsService } from 'ng-keyboard-shortcuts.service';

// ...
  constructor(private readonly keyboardShortcutsService: KeyboardShortcutsService) {}

  ngAfterViewInit(): void {
    const shortcuts = [
      {
        key: 'left',
        label: 'Pagination',
        description: 'Go to previous page',
        preventDefault: true,
        command: () => this.goBack()
      },
      {
        key: 'right',
        label: 'Pagination',
        description: 'Go to next page',
        preventDefault: true,
        command: () => this.goToNext()
      },
      {
        key: '?',
        label: 'Menu',
        description: 'Show keyboard shortcuts menu',
        preventDefault: true,
        command: () => this.openShortcutsMenu()
      }
    ];
    this.shortcutIds = this.keyboardShortcutsService.add(shortcuts);
  }

  ngOnDestroy(): void {
    this.keyboardShortcutsService.remove(this.shortcutIds);
  }
// ...

This way, my app bundle only includes the code for KeyboardShortcutsService

Describe alternatives you've considered
copy/paste the service code in my app

Additional context
I am happy to issue mr if you're ok with exposing the service

Support for Angular 11

The current version for Angular 10 is warning when using Angular 11.
Although it works perfectly, aparently, on ng11, you can't do anything without using the npm flag --legacy-peer-deps.
I think it would be simply update de dependency requiriments to solve the problem

Thanks,
And congrats for the project. It's being realy useful.

[closeKey]="'escape'" seems to be broken in 7.1.2

Describe the bug (minor problem ;)
[closeKey]="'escape'" does not work on <ng-keyboard-shortcuts-help [key]="'?'" [closeKey]="'escape'"></ng-keyboard-shortcuts-help>

To Reproduce
Steps to reproduce the behavior:

  1. Insert [closeKey]="'escape'" in your help element
  2. Open the keyboard shortcuts modal
  3. Click the escape key

Expected behavior
The modal is supposed to close on escape press

Screenshots
N/A

Desktop (please complete the following information):

  • OS: Linux Ubuntu
  • Browser Chrome, Firefox
  • Version, latest

Smartphone (please complete the following information):

  • N/A

Additional context
This is a minor detail as clicking the help key (? in this case) again or clicking the backdrop works like a charm

And thanks for the lightning fast upgrade to 7.1.2 👍

Shortcut modal overflows and does not scroll

Describe the bug
The modal does not scroll when higher than vh (and is not responsive)

To Reproduce
Adjust the vh to be less than the modal height or increase the number of shortcuts to overflow the vh

Expected behavior
The modal should be visible in its entirety in order for the user to see all shortcuts

Screenshots
ng-keyboard-shortcuts

Desktop

  • OS: Linux
  • Browser chrome, chromium, firefox and codesandbox.io
  • Version latest (Chrome: Version 74.0.3729.157 (Official Build) (64-bit))

Smartphone

  • NIL

Additional context
I am not able to find where to override the styling of the modal in order to fix it that way.
From Chrome console on scroll [Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See <URL>
<URL> === https://www.chromestatus.com/features/6662647093133312

Unable to use browser shortcuts

Describe the bug
Hi
I use a shortcut on c key, the linked command is very simple : just navigate on a specific url. The problem is that when I tried to use a copy (Command|CTLR + C), this shortcut is fired and my application navigate to this url, and my clipboard stay empty :'(
Is it a way to use « c » as a shortcut and keep the possibility to keep copy/paste behavior ?

{
    key: ['c'],
    label: 'Global shortcuts',
    description: 'Open my custom page',
    preventDefault: true,
    command: () => this._router.navigate([‘/my_url', ‘page'])
}

It's the same if I defined a shortcut on s or q key. the corresponding "command + S" (save) and "command + q" (quit) are unusable.

Minor Issue : Typo on the ReadMe Page

Describe the bug
Just checking some snippets codes haven't check all yet.

To Reproduce
Npm js page.

KeyboardShortcutsModule.foRoot()

Expected behavior
should be
KeyboardShortcutsModule.forRoot()

Screenshots
Capture

Not running with Angular 10

Describe the bug
After adding the required code in app.module.ts I have an error message from the compiler:
`
ERROR in ./node_modules/ng-keyboard-shortcuts/ivy_ngcc/fesm2015/ng-keyboard-shortcuts.js
Module build failed: Error: ENOENT: no such file or directory, open '....\node_modules\ng-keyboard-shortcuts_ivy_ngcc_\fesm2015\ng-keyboard-shortcuts.js'
at Object.openSync (fs.js:440:3)
at Object.readFileSync (fs.js:342:35)
at Storage.provideSync (.....\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:109:13)
at CachedInputFileSystem.readFileSync (.....\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:289:32)
at Observable._subscribe (.....\node_modules@ngtools\webpack\src\webpack-input-host.js:36:51)
at Observable._trySubscribe (.....\node_modules@ngtools\webpack\node_modules\rxjs\internal\Observable.js:44:25)
at Observable.subscribe (.....\node_modules@ngtools\webpack\node_modules\rxjs\internal\Observable.js:30:22)
at SyncDelegateHost._doSyncCall (.....\node_modules@angular-devkit\core\src\virtual-fs\host\sync.js:25:20)
at SyncDelegateHost.read (.....\node_modules@angular-devkit\core\src\virtual-fs\host\sync.js:48:21)
at WebpackCompilerHost.readFileBuffer (.....\node_modules@ngtools\webpack\src\compiler_host.js:166:44)
at VirtualFileSystemDecorator.readFile (.....\node_modules@ngtools\webpack\src\virtual_file_system_decorator.js:43:54)
at processResource (.....\node_modules\loader-runner\lib\LoaderRunner.js:202:11)
at iteratePitchingLoaders (.....\node_modules\loader-runner\lib\LoaderRunner.js:158:10)
at runLoaders (.....\node_modules\loader-runner\lib\LoaderRunner.js:365:2)
at NormalModule.doBuild (.....\node_modules\webpack\lib\NormalModule.js:295:3)
at NormalModule.build (.....\node_modules\webpack\lib\NormalModule.js:446:15)

ERROR in node_modules/ng-keyboard-shortcuts/lib/ng-keyboard-shortcuts.module.d.ts:2:22 - error NG6002: Appears in the NgModule.imports of AppModule, but could not be resolved to an NgModule class.

This likely means that the library (ng-keyboard-shortcuts) which declares KeyboardShortcutsModule has not been processed correctly by ngcc, or is not compatible with Angular Ivy. Check if a newer version of the library is available, and update if so. Also consider checking with the library's authors to see if the library is expected to be compatible with Ivy.

2 export declare class KeyboardShortcutsModule {

`

To Reproduce
Steps to reproduce the behavior:
1.Create an Angular v10 project and install the library
2. Compile the project

Expected behavior
A running version ??

Desktop (please complete the following information):

  • OS: Windows 10
  • Browser : chrome
  • Angular Version: 10.0.12

Some keys do not get recognized on non-US keyboard layouts

Describe the bug

After the fix for #40, some keys still don't get through, for example the German ä. I tracked it down to all keys which are in the _KEYCODE_MAP and different from the US layout. The ä key has keycode 222, which is ' on US keyboards, so that's what the library maps it to due to characterFromEvent(...) using event.which before accessing event.key.

I believe _KEYCODE_MAP should no longer be necessary and now does more harm than good, since event.key properly handles all special character transformations in a layout-aware fashion. There may be some edge cases I have missed, though.

Expected behavior:

Registering this shortcut should work when pressing the "ä" key on a German keyboard:

{ key: "ä", command: () => alert('test') }

Desktop (please complete the following information):

  • OS: Windows 10
  • Browser: Firefox 71
  • Version: 8.2.0

Multiple imports to make it work

Hi,

Firstly thank you for the great library.

Secondly, I have an application with multiple modules so importing it to app.module doesn't work globally.

I have to import it in every single module. Is this supposed to work like this or is this a bug?

Thanks :)

cmd + b Not Working

I was try this plugins and work for some combinations.
But when I tried cmd / ctrl + b is not working

[FEATURE REQUEST] Use regex or negative sentences to define shortcut keys

I would like to use negative sentences for setting the shortcut keys, or better, a regex option.

For example: In the latest version, I can define shortcuts for all numbers

{
    key: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
    preventDefault: true,
    allowIn: [AllowIn.Input],
    command: e => { console.log("number pressed") }
}

I would like to define a rule to fire an event if I press any key that is not a number, as I'm suggesting:

{
    key: !["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
    ...
    ...
}

Or better, using regex, it would be very easy:

{
    key: ^(?!.*[0-9]).*$,
    ...
    ...
}

Or simply, key: [a-zA-Z]

Sequence with key modifiers

Describe the bug
Creating a sequence with modifier keys does not trigger the shortcut command.

To Reproduce
Steps to reproduce the behavior:

  1. Register a keyboard shortcut with a sequence containing a key modifier (CTRL, ALT, etc...)
    public shortcuts: ShortcutInput[] = [];

    constructor() {
        this.shortcuts.push(
            {
                label: 'Test',
                key: ['a b'],
                description: 'Testing no modifier',
                command: (event) => console.log(event.key),
                preventDefault: true
            },
            {
                label: 'Test',
                key: ['alt + a alt + b'],
                description: 'Testing modifier',
                command: (event) => console.log(event.key),
                preventDefault: true
            }
        );
    }
  1. The normal sequence will print the key combination to the console but the modifier sequence will not.

Expected behavior
The command should be invoked when entering the sequence with the correct key modifiers applied.

Versions

  • OS: Windows 10 64bit
  • Browser Chrome 76.0.3809.132 64bit
  • Package Version 8.0.0

Additional Context
The command will also not be invoked even if the sequence only contains one modifier key; for instance you cannot have a keyboard shortcut key: ['ctrl + a b']

cmd/ctrl + t not working in chrome

Hi all,

probably desired behavior, but is it possible to "overwrite" chrome's shortcuts? (cmd + t / cmd + n)? Was not able to figure out a way, prevendDefault seems to

{      key: ["cmd + t"],
      label: "Commands",
      description: "sth",
      command: e => console.log(e),
      preventDefault: true
    },

is not working for me, a new tab is opened instead.

Thanks in advance!

A shortcut works either in INPUT or outside of it, but never for both cases

Describe the bug
Current implementation of "isAllowed" function prevents single shortcut to work globally. What I mean is that if you define global shortcut for top-level component, it works for all contents of the page, except of INPUT/TEXTAREA/SELECT, which is explained in docs - we need explicit config option to be set to make it work. Problem is that if I provide all 3 input types in "allowIn" array, then this shortcut does not work anymore outside of these inputs.

        if (shortcut.allowIn.length) {
            return shortcut.allowIn.includes(target.nodeName);
        }
        return !this._ignored.includes(target.nodeName);

The problem with this condition is that when anyone defines ANY content of allowIn array, then only these become valid. It's no longer allowed to handle that shortcut in any other node types.

To Reproduce

*.ts:

   this.keyboard.add([
         {
             key: 'alt enter',
             //allowIn: ['TEXTAREA', 'INPUT', 'SELECT'],
             command: () => console.log('xxx ')
         }
    ]);

In html just have few non-input fields and some input fields.
Depending on commented/uncommented line of allowIn, only input fields react to the input, or in other case all except the inputs.

Expected behavior
The allowIn option should complement the default list of allowed elements, not overwrite it and limit to just these few. For limiting scope we already have the target property.

Desktop (please complete the following information):

  • OS: Windows
  • Browser Chrome
  • Version 67.0.3396.99

Problem with navigator and Angular Universal

I'm trying to set up an Angular Universal and I have a problem with call to navigator in keys.ts:

node .\dist\server.js
D:\repo\Budget\SRC\Trunk\Budget.Api\UI\dist\server.js:300301
var isMac = (navigator.userAgent.indexOf('Mac OS') !== -1);

ReferenceError: navigator is not defined

I tried using domino and MockBrowser as a workaround but with no result.

const MockBrowser = require('mock-browser').mocks.MockBrowser;
    const mock = new MockBrowser();


    global['navigator'] = mock.getNavigator();

Danish keyboard layout support

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Steps to reproduce the behavior:
I’m working on a project in foreign country(Denmark) and of course with danish keyboard layout.
I’m trying to make keyboard shortcut like “alt + +” but unfortunately I had no luck.

Expected behavior
The shortcut should work as expected

Desktop (please complete the following information):

  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]

Smartphone (please complete the following information):

  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]

BUG: Onclick events bugged

Describe the bug
After executing a shortcode onclick events become unresponsive nad you need to click 2 times to restore to normal behavior

To Reproduce
Steps to reproduce the behavior:

  1. use a shortcut
  2. Click on button
  3. it doesn't work
  4. you need to push the button again

Expected behavior
for a shortcut to not alter onclick behavior

Desktop (please complete the following information):

  • OS: Ubuntu 18.04
  • Browser Chorme, Firefox

Additional context
Add any other context about the problem here.

Introduce 'standard' web shortcuts?

Is your feature request related to a problem? Please describe.
More and more sites have the same set of shortcuts that are not included in this great plug-in. For instance it is not possible to call the help modal with key ? like GitHub uses.

Describe the solution you'd like
It would be great to have the option of using the 'standard' set of web shortcuts. GitHub as an example:

  • ? gives you the help modal
  • g + c Go to the Code tab
  • g + i Go to the Issues tab
  • and so forth always with g as the first key to navigate (go to) different tabs in the app

Describe alternatives you've considered
See above where ? opens the help modal and key combinations starting with g are possible

Additional context
Not much else to be said :) Thx

Allow to differentiate between pressing key and modifier + key

In my use case, the user should be able to create a shortcut for a specific key (e.g. 'n') and another shortcut for the same key with a shift modifier (e.g. 'shift + n').

While using the package I was not able to make it work.

Here's a simplified example where both shortcuts will be triggered at the same time when the user enters 'shift + n'. The user would only want action B to be triggered.

 ngAfterViewInit() {
    this.shortcuts.push(
      {
        key: "n",
        label: "Actions",
        description: "An action A",
        command: e => console.log("n clicked", { e }),
        preventDefault: true
      },
      {
        key: "shift + n",
        label: "Actions",
        description: "An action B",
        command: (output: ShortcutEventOutput) =>
          console.log("Shift + n clicked", output)
      }
    );
  }

I don't know if there's a way to achieve that that I didn't find or if it's impossible currently.

Anyway, thanks for this package, it's really useful :)

When CapLock is on and Shift is pressed, shortcuts with alphabetic key are not triggered

Hey there, I think I found a bug. When CapLock is on and Shift is pressed, shortcuts with alphabetic keys are not triggered. This seems not to effect combination/sequence key shortcuts. So it works for a shortcut with key "t a" but not for one with key "k".

I used addEventListener to check how JS normally reacts and there it triggers just fine:

addEventListener('keypress', (e)=> {
      console.log(e);
    }))

image

Any idea why this happens?

Lose focus when 'escape' key is pressed

Hello,

I try to implement a basic shortcut on "escape" key. When this key was pressed, I would like that the element with focus, lose this focus (any input elements, on any pages of my application). I tried to implements this behavior like this :

{
  key: ['escape'],
  label: 'Shortcuts list'
  description: 'Lose focus on the current field',
  allowIn: [AllowIn.Select, AllowIn.Input, AllowIn.Textarea],
  preventDefault: true,
  command: (output: ShortcutEventOutput) => output.event.target.blur()
}

This works but Angular isn't happy with this synthax when I run my tests with the following error message :
Property 'blur' does not exist on type 'EventTarget'.

I also tried with

@ViewChild('input', { static: false}) input: ElementRef;
...

{
  key: ['escape'],
  label: 'Shortcuts list'
  description: 'Lose focus on the current field',
  allowIn: [AllowIn.Select, AllowIn.Input, AllowIn.Textarea],
  preventDefault: true,
  target: this.input.nativeElement,
  command: (output: ShortcutEventOutput) => console.log(output)
}

But it also failed with the following error : Cannot read property 'nativeElement' of undefined

Do I miss something into the my configuration ?

Compatibility with angular 9

I tested to update an application to angular 9 via ng update @angular/cli @angular/core, turns out it's impossible. Here's the error message :
Package "ng-keyboard-shortcuts" has an incompatible peer dependency to "zone.js" (requires "^0.9.1", would install "0.10.2").

I have no idea if the compatibility to angular 9 of your package is trivial or complex but that feature would be really useful very soon.

Thanks in advance, and thanks for your work on this package.

A shortcut backspace does not working

Describe the bug
I like to use shortcuts with key "backspace", but apparently its does not work.

To Reproduce
Define in the component.ts

    private shortcuts: ShortcutInput[] = [];

    ngAfterViewInit(): void {
        this.shortcuts.push(
            {
                key: ["backspace", "cmd + j"],
                preventDefault: true,
                allowIn: [AllowIn.Input],
                command: e => console.log("backspace")
            }
        );
    }

In html source:
<ng-keyboard-shortcuts [shortcuts]="shortcuts"></ng-keyboard-shortcuts>

Expected behavior
The behavior expected when backspace key is pressed is executed the command function, as when the combination key "cmd + j" is executed, its works.

Desktop (please complete the following information):

  • OS: Windows 10 64bits
  • Browser: chrome
  • Version: 74.0.3729.131

Additional context
ng-keyboard-shortcuts: "^7.0.9",
@angular/core: "^7.2.4"

How to use shortcuts with key "backspace"?

Support non-English keyboards and characters by using KeyboardEvent.key

Describe the bug
Trying to register shortcuts for special characters (for example #) does not work with a non-US keyboard layout.
Registering letters not in the English alphabet (for example the German "ä") is completely impossible.

Cause
Currently this library seems to use the deprecated KeyboardEvent.which property with some manual mappings for special characters.

Suggested fix
I suggest switching to KeyboardEvent.key, which correctly handles foreign keyboard layouts and automatically assigns standardized names to non-printable characters such as arrow keys, home, end, etc.

It also handles characters only reachable by pressing Shift (e.g. to obtain '?' from Shift+/ on a US keyboard) automatically: When the combination is pressed, the key property will contain "?", so no manual mapping will be necessary and it will work across all layouts.

Browser support for that property is quite consistent nowadays, so compared to the current behavior it would be a big improvement. You can still use String.fromCharCode(e.which) if 'key' is unavailable as a fallback.

Choose how you handle multiple bindings for the same shortcut

First of all, great library! Sababa ;) ! I changed from another one I was using and I'm glad I did, so thanks for that.

So I my suggestion is that you can set the way you handle multiple bindings for the same shortcut. I basically see it as handling it in the following 3 ways when the shortcut is used:

1. Trigger all of the commands/bindings
2. Trigger the first one added
3. Trigger the last one added

Let me explain my usecase. I have a card component (kind of like a popup) that can be closed with escape. It is possible for multiple cards to be opened in a stack on top of eachother. In my usecase I would want to use option 3 because I want the last opened card to be closed with escape. Then when that is closed I want escape to close the next card and so on.

So yeah that's the suggestion, let me know what you think.

p.s. A slightly separate issue/wish I have is that the closeKey shortcut does not get "occupied" when the help menu is not open. I find it natural for it to be the escape key but I also want to use escape elsewhere in the app.

Toda raba!

add the KeyboardShortcutsService to the exported API

Is your feature request related to a problem? Please describe.
I have to add the 'ng-keyboard-shortcuts' component every time i want to subscribe to a shortcut:

<ng-keyboard-shortcuts></ng-keyboard-shortcuts>
-----
@ViewChild(KeyboardShortcutsComponent, { static: false })
private keyboard: KeyboardShortcutsComponent;
-----
this.keyboard.select('del').subscribe(_ => {
   // do something
});

Describe the solution you'd like
Inject directly the service and use it:

constructor(private keyboard: KeyboardShortcutsService) {}
-----
this.keyboard.select('del')

function keys f1 to f12 not working.

function keys f1 to f12 not working.

The following does not work where as it works for all other keys
this.keyboard.add([
{
key: "f1",
command: () => console.log("f1"),
preventDefault: true
}
]);

Support angular 7 in the new versions

Describe the bug
I am using angular 7. When I installed 9.0.0. of ng-keyboard-shortcuts I got the following error when importing the module:

Uncaught TypeError: core.ɵɵdefineInjectable is not a function
    at modules.js?hash=52f736c0bde845d06d36767e97e5a9901832c3a0:172358
    at modules.js?hash=52f736c0bde845d06d36767e97e5a9901832c3a0:172366
    at modules.js?hash=52f736c0bde845d06d36767e97e5a9901832c3a0:171568
    at ng-keyboard-shortcuts.umd.js (modules.js?hash=52f736c0bde845d06d36767e97e5a9901832c3a0:171571)
    at fileEvaluate (modules-runtime.js?hash=d3c3e5d67c95f97a60888bda7373292efad3be5e:346)
    at Module.require

When I installed version 7.1.3 of ng-keyboard-shortcuts, the library works as expected.

To Reproduce
Steps to reproduce the behavior:

  1. Use Angular in version "7.2.16"
  2. install ng-keyboard-shortcuts as `npm install -S ng-keyboard-shortcuts".

Desktop (please complete the following information):
Vivaldi | 2.11.1811.38 (Stable channel) (64-bit)
Revision | 9238efe45704ece191a76e3bb210e3fe6716ccb2
OS | Linux
JavaScript | V8 8.0.426.19
User Agent | Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.107 Safari/537.36
Command Line | /usr/bin/vivaldi-stable --flag-switches-begin --flag-switches-end --disable-webrtc-apm-in-audio-service --save-page-as-mhtml
Executable Path | /opt/vivaldi/vivaldi

Additional context
The regression was introduced in version 8.2.0.

Add the help panel key into the shortcut list displayed into the help panel

Is your feature request related to a problem? Please describe.
When we use the component KeyboardShortcutsHelpComponent, we need to defined an key to open the help panel.
This key isn't added into the shortcut list.
image

Describe the solution you'd like
This key shortcut should be added to the help panel.

image

Ideally the label associated by the key should be set as component input.

<ng-keyboard-shortcuts-help 
    [key]="'?'" [keyLabel]="'open the panel'"
    [closeKey]="'escape'" [closeKeyLabel]="'close the panel'">
</ng-keyboard-shortcuts-help>

Issues using ng-keyboard-shortcuts-help component

Describe the bug
Trying to make use of the help component I ran into a couple issues related to showing lines for the open / close help keys.

  1. Appears closeKeyLabel is not working as expected. Looking at the code appears this line https://github.com/omridevk/ng-keyboard-shortcuts/blob/10.1.17/projects/ng-keyboard-shortcuts/src/lib/ng-keyboard-shortcuts-help.component.ts#L209 needs to be updated to pass the label instead of the description.
  2. The current implementation requires the the description / label attributes be defined first in order for them to work. This appears to be due to how the shortcut is added on the input value change vs an ngOnInit / ngOnChanges

Examples:

The following usage

<ng-keyboard-shortcuts-help
        key="?"
        keyDescription="Show this help menu"
        keyLabel="General"
        closeKey="escape"
        closeKeyDescription="Hide this help menu"
        closeKeyLabel="General"
        title="Keyboard shortcuts">

results in
shortcuts_not_working

The following usage

<ng-keyboard-shortcuts-help
        keyDescription="Show this help menu"
        keyLabel="General"
        key="?"
        closeKeyDescription="Hide this help menu"
        closeKeyLabel="General"
        closeKey="escape"
        title="Keyboard shortcuts">

results in

shortcuts_hide_is_off

Expected behavior:
closeKeyLabel should work as documented and order of attributes should not be required for it to work.

Version Info:
Angular 9, Chrome browser

Adding to a lazy-loaded feature module

I tried to add KeyboardShortcutsModule to a lazy-loaded feature module, It failed with the error
BrowserModule has already been loaded
how can I fix this?

Prevent Default Space Key in FireFox

Describe the bug
preventDefault on space key is not respected in FireFox

To Reproduce
Steps to reproduce the behavior:

  1. Create a button with click event
// .html
<button (click)="doStuff()"></button>

// .ts

public doStuff() {
   console.log('Button clicked');
}
  1. Generate a shortcut
{
        key: 'space',
        label: 'label',
        description: 'play/pause',
        preventDefault: true,
        command: () => console.log('shortcut space'),
},
  1. Open inspect element

  2. Make sure button has keyboard focus

  3. Press space key on keyboard

  4. Both click event and shortcut event are triggered.

Screen Shot 2019-07-04 at 11 43 05 AM

Expected behavior
The click event should be prevented

Desktop (please complete the following information):

  • OS: macOS - 10.14.5
  • Browser Firefox - 67.0.4 (64-bit)

Additional context
I believe the issue is happening because FF triggers click event on 'keyup' when space key is released.

Mousetrap

I didn't look through the source, but at least this project's README is clearly a modified version of Mousetrap's (https://github.com/ccampbell/mousetrap). It should be (and might be legally required) stated that this is the case (Apache 2).

Edit: To be fair, it seems to be mainly the part about gmail style sequences that caught my attention. Not saying all of this is just a copy!

ctrl + t is not working

Hi ,

I am implementing

{
key: "ctrl + t",
label: "test",
description: "hello world",
command: () => console.log('directive cmd + e'),
preventDefault: true
}

inside the shortcuts array , but when pressing 'ctrl + t' it is opening a new tab in browser could you please help me with it, it would be great if you can provide me a working example

Migrate to Angular 6

In order for our project to be able to migrate to Angular 6, we need all dependencies with Angular peerDependency to be at 6 too. I would like to ask you do the migration. If you don't have time for it I'll create fork, migrate myself and then create PR.

ShortcutInput "target" trigger the command even if the target element is NOT in focus

I can't get the target prop of ShortcutInput interface to limit command triggering only when the target is in focus.

I created this stackblitz in which a value is supposed to change with up and down arrow only if input has focus

here is a code snippet

{
    key: "down",
    preventDefault: true,
    command: () => --this.val,
    target: this.input.nativeElement,
}

In either case ( input focused or not ) value is still changing.

what am I doing wrong? or is this a bug?

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.