Search code examples
haskellthreepenny-gui

Click button on "Enter" keypress


I would like something like this:

on UI.keydown textfield $ \c -> when (c == 13) $ void $ do
    trigger UI.click button

Namely, is there something that acts like the trigger function I just inserted?


Solution

  • In order to have Enter keypresses handled as if they were button clicks you don't need to trigger a click literally. Rather, you need an event which is fired whenever either the keypress or the click happen. The easiest way to do so, specially if you are already using Threepenny's FRP combinators (which I heartily recommend), is through unionWith. With that and some other Reactive.Threepenny combinators, the code might look like this:

    -- I'm giving separate names to the events for extra clarity.
    let eClick = UI.click button
        eEnter = void $ filterE (== 13) (UI.keydown textfield)
        -- This event is fired whenever `eClick` or `eEnter` happen.
        eGo = unionWith const eClick eEnter
    

    Then you just handle eGo, using onEvent, in the way you would handle the click event.

    Note that an alternative solution in the spirit of the pseudocode in your question would be defining eGo via newEvent and then using the trigger function you get to fire the event in the on handlers of both click and keypress:

    -- Assuming you are in an `UI` do-block, thus the `liftIO`.
    (eGo, fireGo) <- liftIO newEvent
    on UI.click button $ \_ -> fireGo ()
    on UI.keydown textfield $ \c -> when (c == 13) (fireGo ())
    -- Alternatively, you might define an `eEnter` with `filterE`,
    -- as in the first example, instead of using `on` and `when`. 
    

    That is not as nice a solution as the first one, as it is somewhat messier and doesn't play quite as smoothly with FRP code. I wouldn't recommend it, except perhaps if you are not using the FRP combinators at all.