Gizra/elm-keyboard-event/1.0.0

NOTE: this package is not compatible with Elm 0.19.1

Keyboard.Event

Most Elm keyboard-related packages (such as elm-lang/keyboard, and others which build on it) only decode the KeyCode from Javascript's keyboard event (possiby building up some additional state from the sequence of keycodes).

This ignores some potentially useful information reported in Javascript's keyboard event:

  • the state of modifier keys (such as the shift key)

  • whether the event is a "repeated" keyboard event (due to a key being held down)

This package provides decoders for that additional information, and examples of using those decoders when listening for keyboard events on HTML elements, or the window object itself (as elm-lang/keyboard does).

To listen for keyboard events on HTML elements, you can do something like this:

div
    [ on "keydown" <|
        Json.Decode.map HandleKeyboardEvent decodeKeyboardEvent
    , tabindex 0
    , id "id-for-auto-focus"
    , style [ ( "outline", "none" ) ]
    ]
    []

See the examples directory in the source code for complete examples.

Note that an HTML element must be focused in order to receive keyboard events (unlike in elm-lang/keyboard, since it attaches a listener to the Javascript window object). This is either an advantage or a disadvantage, depending on your circumstances. If you want to handle keyboard events differently depending on what is focused, it is an advantage. Otherwise, you can work around the need to focus, in this way:

  • provide the element with a tabindex attribute (as demonstrated above), so that it is focusable

  • possibly give it a style of outline: none; to avoid the default outline that would be drawn when the element is focused

  • possibly use elm-lang/dom to automatically focus the element when you initialize the page

Alternatively, the examples directory also contains an example of subscribing to keyboard events on the window object, as elm-lang/keyboard does, but supplying your own decoder instead of just getting the KeyCode. In that case, you can avoid the need to focus on any particular HTML element.

KeyboardEvent

type alias KeyboardEvent =
{ altKey : Bool
, ctrlKey : Bool
, key : Maybe String
, keyCode : Key
, metaKey : Bool
, repeat : Bool
, shiftKey : Bool
}

A representation of a keyboard event.

The key field may or may not be present, depending on the listener ("keydown" vs. "keypress" vs. "keyup"), browser, and key pressed (character key vs. special key). If not present, it will be Nothing here.

The keyCode is normalized by decodeKeyboardEvent to use whichever of which, keyCode or charCode is provided, and made type-safe via Keyboard.Key (see the excellent SwiftsNamesake/proper-keyboard for further manipulation of a Key).

decodeKeyboardEvent : Decoder KeyboardEvent

Decodes a KeyboardEvent from a keyboard event.

considerKeyboardEvent : (KeyboardEvent -> Maybe msg) -> Decoder msg

You provide a function which, given a KeyboardEvent, turns it into a message your update function can handle. You get back a Decoder for those messages.

When your function returns Nothing, the decoder will fail. This means that the event will simply be ignored -- that is, it will not reach your update function at all.

Essentially, this allows you to filter keyboard events inside the decoder itself, rather than in the update function. Whether this is a good idea or not will depend on your scenario.

Helpers

Some lower-level helpers that you might find useful.

type alias KeyCode =
Int

A type alias for Int.

decodeKeyCode : Decoder KeyCode

Decodes keyCode, which or charCode from a keyboard event to get a numeric code for the key that was pressed.

decodeKey : Decoder (Maybe String)

Decodes the key field from a keyboard event. Results in Nothing if the key field is not present, or blank.