elm / browser

Create Elm programs that run in browsers!
https://package.elm-lang.org/packages/elm/browser/latest/
BSD 3-Clause "New" or "Revised" License
313 stars 64 forks source link

Way to `preventDefault` on `Browser.Events` needed #89

Open ChristophP opened 5 years ago

ChristophP commented 5 years ago

The issue I am building an editor using Elm, so I am handling all sorts of keyboard input. I just learned that the subscriptions in Browser.Events unfortunately don't provide the possibilty to prevendDefault the browser behavior. This is unfortunate because sometime I need the tab key to do something different than switch to the next tabIndex element or intercept key strokes on inputs. Possible workaround

  1. Using Html.Events on the outermost <div>. Unfortunately this won't work if the focus gets somehow changed to the body.
  2. Ports: Works but needs JavaScript code and makes one leave the safe Elm haven.
ChristophP commented 5 years ago

related #77

r-k-b commented 3 years ago

We're also running into this issue, on a large-ish app that's replacing a desktop app. Many of the existing shortcuts that users have muscle memory of, collide with browser shortcuts such as Alt + F.

related unanswered SO question: how to use prevent default on Elm Browser.Event.onKeyDown

atlewee commented 3 years ago

I faced the same issue today but found a workaround that works like I want: Add Html.Events.preventDefaultOn "keydown" yourDecoder to the outermost div To be able to pick up all keydown you must also add Html.Attributes.tabIndex 0 to this div. Now in your decoder you can check the input before the key is sent to the browser. If you detect a keycombination your decoder should give back ( KeyCombinationMsg, True ) so that f.eks. any textbox in parts of your application with focus does not receive any characters. If no known key-combination is found your decoder should fail, letting the focused textInput get that event :)

atlewee commented 3 years ago

Update: There was a slight problem with the proposed workaround. If an input on the page gets removed/destroyed focus is lost to document.body and the outermost div will not pick up keypresses before clicking somewhere in the application. Was hoping to have a pure elm workaround, but needed to add this to index.html to get it working. ( add focus to the outermost div if focus is lost )

document.addEventListener("focusout", (e) => {
  if (e.relatedTarget == null) {
    document.getElementById("layout").focus()
  }
})
bburdette commented 3 years ago

I made a package for dealing with this issue, at least for my use case:

https://package.elm-lang.org/packages/bburdette/windowkeys/latest/