Skip to content

Instantly share code, notes, and snippets.

@carlows
Last active September 26, 2016 19:34
Show Gist options
  • Save carlows/0dc5c375e51cce8fbed7483460827464 to your computer and use it in GitHub Desktop.
Save carlows/0dc5c375e51cce8fbed7483460827464 to your computer and use it in GitHub Desktop.

Disclaimer

WIP

Author

Carlos Martinez

Problem Overview

To enhance the user experience, we want them to be able to send any form in Denbora using a hotkey, this would include starting and stoping the timer.

Constraints

  • hotkey for windows ctrl + enter
  • hotkey for osx cmd + enter

Background

As we are using turbolinks, we use on turbolinks:load to add javascript to the pages. If we bind events inside that function, we would be binding and unbinding them on each visit (this is pretty much negligible for this case) but it would be cool to avoid doing this in the project.

Considering that I'm going to use event delegation, binding the keydown event to the document and then listening for the specific key that was pressed.

Theory of operation

Goals

We should be able to:

  • Send any form in the application using the hotkey
  • Start/Stop the timer using the hotkey

The hotkey for windows will be [ctrl + enter]. For OSX the hotkey will be [cmd + enter].

Functional Specification

As we're using turbolinks, we want to avoid as much as possible to register event listeners directly to elements in the page body. So we're going to use event delegation outside of the turbolinks:load callback:

app/assets/javascripts/main.js

(function () {
  $(document).on('keydown', 'form', function () {
    // we add the event listener for any form in the page
  });

  $(document).on('turbolinks:load', function () {
    // loads on every visit and on the first request
  });
});

Listening to the command key is possible using the metaKey, the ctrl key by using ctrlKey and the enter key using the keycode 13, so to listen to our hotkey:

app/assets/javascripts/main.js

$(document).on('keydown', 'form', function () {
  const ENTER_KEYCODE = 13;
  const hotkeyPressed = ((e.metaKey || e.ctrlKey) && (e.which === ENTER_KEYCODE));

  if (hotkeyPressed) {
    // submit form using $(this)
  }
});

For the timer we won't be able to do the same, as we need to modify its state and not just send a form. I'm going to use the react event onKeyDown for the timer input field and select field.

Within this event, I will look for the cmd + enter combination explained before:

app/assets/javascripts/components/timer_form.js

class TimerForm extends React.Component {
  keyDown() {
    if (hotkeyPressed) {
      this.toggleTimer();
    }
  }

  render() {
    return (
      <input onKeyDown={this.keyDown} />
      <select onKeyDown={this.keyDown} />
    );
  }
}

If the combination is the hotkey, we toggle the timer.

Open Issues

N/A

@duranmla
Copy link

Carlos solo asegurate de que asi como bindeas los eventos los quitas con WillUnmount, aunque creo que para el EventHandler nunca pasara que se quite, but creo que me sentiria bien sabiendo que tenemos eso alli. Por otro lado esta cool lo del EventHandler es como un shared component que todos pueden usar para escuchar eventos y reaccionar a ellos no? So, ye creo que esto looks cool

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment