Replacing native code: Keyboard package

After reading Evan’s post on the matter, I thought this was a good time to go through our code base and check where we use native code or effect managers, and why.

Our code base is approx. 17K lines of Elm code, it is a realtime remote-support tool, which provides remote desktop capabilities as its most important feature.

We use native code for 5 different things. There are two of those, which I find tricky to get rid of, so I decided to follow Evan’s advice: I would like to share the specifics here in two separate threads and get advice.

This thread is about keyboard capabilities.

Basically we created a fork of the Keyboard package and the underlying Dom.LowLevel module.

Our motivations were the following:

  1. Globally subscribe to keyboard events in a way that we can set StopPropagation and PreventDefaults similarly to the Html.Events implementation
  2. The Keyboard package currently uses the keyCode property instead of the code property. Although keyCode has wider support across browsers, it is deprecated, and code seemed to be more reliable across platforms in the supported browsers (Chrome / Firefox).

Moving this logic to JavaScript via ports feels weird considering that the package exists.

Perhaps this a good case where we could contribute to an enhanced version of the Keyboard package. However, I did not feel very confident about our current solutions for either #1 or #2. I find them too ad-hoc, and are not based on enough research/discussion/experimentation, so I did not find them worthy of sharing.

(Our solution for #1 is to pass down an Options record (similarly to Html.Events). But this does not feel like such a great design for general use, since if you have more than one subscription and one of them sets StopPropagation this would result in some indeterministic behavior.
In terms of #2 we would need to do more cross browser/platform research.)

What would you suggest for this use-case?


First, I want to thank you for the clarity and specificity of this thread! This is the most useful kind of conversation we can have on this topic right now.

I have a question, and also what is possibly a very straightforward solution depending on your answer:

Is the call to stopPropagation critical to the functionality if your event handler is at the level of the document or the window? I frequently just call both out of habit, but my understanding is that stopPropagation prevents events from bubbling upward. If that is true, then it doesn’t seem important when the handler is on the document or window.

If you can test and confirm that only being able to preventDefault would be sufficient for case #1, then the good news is you can just wait until the 0.19 alpha to switch over to trying some new functionality it will provide. You’ll be able to subscribe to any event on the window or document, decode the event however you would like (so you can use code instead of keyCode), and optionally prevent default behavior.

If stopPropagation is also important to you, the solution may end up being to use ports but we can keep talking to make sure all of your concerns are understood.

The reason stopPropagation isn’t provided for these global event subscriptions is because of that understanding of what that method does. It would be useful to know if there is a use case or auxiliary behavior of stopPropagation that we don’t know about that would make it worthwhile to include. An SSCCE for that would be the most helpful thing.


Thanks, for your quick reply! I think your suggestion will work for us. I believe there is no need to call stopPropagation, but I will run some tests on that tomorrow and share the results here.


Cool! If it ends up working then don’t feel a need to use your valuable time to reply. We’ll assume that no news is good news.