Code Monkey home page Code Monkey logo

ember-keyboard's People

Contributors

briarsweetbriar avatar ember-tomster avatar foo-pzu avatar null-null-null avatar twokul avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ember-keyboard's Issues

Human-readable event triggers

Event triggers will be formatted <eventType>:<modifierKey>+<additionalModifierKey>+<key>, eg keyUp:ctrl+shift+a or keyDown:b:

respondToA: on('keyUp:a', function() {
  console.log('a was pressed');
});

Keys will use the mapping of the excellent ember-keyboard-service. This will allow us to observe events from the arrow keys with listeners like keyUp:ArrowDown.

Scoped events

Events are only triggered on the currently focused component. If the currently focused component does not have a listener registered for that event, it will optionally bubble up through parent views until it successfully triggers an event or terminates at the top level.

This will allow us to have contextual key responses, such as pressing the down arrow to navigate a ul, as well as app-wide key responders, such as the s key taking you to the search bar or Escape opening the account menu dropdown.

UPDATE:

tldr, this approach is too invasive.

Until we get routable components, the top level view is still that, a view. That means to support this, we'll need to use the deprecated application view. In turn, our consuming app will have to enable legacy views. This can be done by adding _ENABLE_LEGACY_VIEW_SUPPORT: true to EmberENV.

Additionally, this will require us to reopen the View and Component class to inject observers that will alert ember-keyboard when the component gains and loses focus. This will still be the case, even with routable components.

Event stack

Let's follow the lead of ember-key-responder and leave it up to the app developer to decide when to activate and deactivate an ember-keyboard component. They'll be able to activate a component's key responders with this.get('keyboard').activate(); and correspondingly deactivate it with this.get('keyboard').deactivate();. When active, the component will try to respond to any keyboard event. If it doesn't have any listeners for that event, then it passes it on the next component on the stack.

Example:

In reports-web we might want to focus on the search-bar whenever the user presses s. (Invaluable for someone using a screen-reader, though also helpful for power-users in general. Github does this well.) To achieve this, we activate it and add a listener:

// components/search-bar/component.js
export default Ember.Component.extend({
  keyboard: Ember.inject.service(),

  activateKeyboard: Ember.on('init', function() {
    this.get('keyboard').activate();
  }),

  focusOnKeypress: Ember.on('keyUp:s', function() {
    this.$().focus();
  })
});

Now let's say we want this to coexist with a dropdown menu that navigates with the UpArrow and DownArrow keys. Its responders are activated whenever the dropdown is opened and deactivated whenever the dropdown is closed. While active, this component is the first to respond to key events, giving it a chance to handle UpArrow and DownArrow. If it can't handle the event, then it passes the event down the stack to the next active component, which in this case is the search-bar. If the user had pressed s, then the search-bar triggers its focusOnKeypress. Otherwise, it passes the event even further down the stack until it finds a responder or terminates at the bottom.

Considerations:

  • Components will be jumping on the stack from all over the place, which could make it difficult to reason about where a listener is getting registered.

Cannot read property 'toString' of undefined

I added in the service and the event listeners as described in the README, but can't seem to get across this error. Any ideas what may be happening?

Cannot read property 'toString' of undefined in keyboard.js:18

image

Here is my component file:

import Ember from 'ember';

export default Ember.Component.extend({
  keyboard: Ember.inject.service(),
  tagName: 'div',
  classNames: ['invoice'],

  activateKeyboard: Ember.on('didInsertElement', function() {
    this.get('keyboard').activate(this);
  }),


  aFunction: Ember.on('keyDown:a', function() {
    console.log('`a` was pressed');
  }),

  anotherFunction: Ember.on('keyDown:ctrl+shift+a', function() {
    console.log('`ctrl+shift+a` was pressed');
  }),
});

Use web workers with graceful fallbacks for IE9

Trawling the eventStack after every keyUp and keyDown could get expensive. If only we could offset that cost by putting it on another thread. . . .

Web workers to the rescue!

. . . . for IE10+, and everyone else.

Special handling for inputs

In most cases, we will not want our keyboard responders to trigger while in a textarea or input field. However, in other cases a developer might want to opt-in, such as with a text editor that italicizes with keyUp:ctrl+i. Perhaps we should allow key responders on components with tagName: 'input' or tagName: 'textarea', but these key responders will by default be bubble: false.

In all other cases, if the focus is in an input field, then the event listeners should not fire.

Mixins for common patterns

While creating the test app, I noticed there was a lot of common code for activating/deactivating component keyboard responders. Would be helpful to have mixins for the most common patterns.

`keyUp` and `keyDown` listener macros

Currently, developers define their key listeners directly with Ember.on, which creates a difficult situation. What if one developer orders their modifier keys like keyUp:ctrl+alt+d while another does keyUp:alt+ctrl+d. Since ember-keyboard doesn't know what order the modifier keys are defined in, it must look for all possible orders. With the above scenario, this could require as many as six iterations for each responder in the eventStack. If there are dozens of responders, each keystroke could become computationally expensive.

As an alternative, what if we created listener 'macros' that could be imported directly off ember-keyboard. Developers could declare their listener modifier keys in any order, and it would then be the macro's responsibility to sort them alphabetically and then call Ember.on on that string. We would then only have to check each responder once to see if it has a listener with the alphabetized modifier keys.

This would lead to markup like this:

import Ember from 'ember';
import { keyUp, keyDown } from 'ember-keyboard';

export default Ember.Componet.extend({
  aShift: keyUp('a+shift', function() {
    console.log('a was pressed');
  }),

  shiftB: keyUp('shift+b', function() {
    console.log('b was pressed');
  })
});

And it would also lead to more performant code.

Responder priority

We might want to give developers the ability to specify a component's priority. For instance, the developer might want their modal-menu component to always respond before their sidebar-menu component. Perhaps they could assign priority during activation: this.get('keyboard').activate({ priority: 3 });.

Opt-out of event bubbling

We might want to give developers the ability to opt-out of bubbling up the event stack. For instance, while the modal-menu component is active the developer might not want events to get passed on to the lower priority sidebar-menu. This too could be passed in as an option: this.get('keyboard').activate({ bubble: false });.

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.