HeinrichApfelmus / threepenny-gui

GUI framework that uses the web browser as a display.

Home Page:https://heinrichapfelmus.github.io/threepenny-gui/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`on UI.valueChange` not triggered until ESC pressed

jerbaroo opened this issue · comments

Here is the code for the problem described below.

main :: IO ()
main = do
  startGUI defaultConfig setup

setup :: Window -> UI ()
setup window = do
  (event, handler) <- liftIO $ newEvent
  behavior         <- stepper "No file selected." event
  text             <- UI.div # sink UI.text behavior
  input            <- UI.input # set UI.type_ "file"
  -- input            <- UI.button # set UI.text "file"
  getBody window #+ map element [text, input]
  on UI.valueChange input $ const $ do
    liftIO $ handler "File selected."

Problem

  • Initially the text of the div is "No file selected.".
  • Click the input and select a file.
  • Observe the text of the div not change.
  • Press the ESC key.
  • Observe the text of the div change to "File selected.". (Chrome only)
  • Use a button instead of input, by using the commented line, and the problem is the same.

Reproduce

  • git clone https://github.com/barischj/threepenny-slow-valuechange
  • cd threepenny-slow-valuechange
  • stack setup && stack build && stack exec threepenny-slow-frp-exe
  • Open browser to localhost:8023 and follow problem steps.

System

  • OS X 10.11.6
  • Chrome 56.0.2924.87

Additional notes:

  • On Firefox 51.0.1 and Safari 10.0.3 the text of the div won't update even after pressing ESC.

Fix

A fix for this was not to use UI.valueChange which uses the DOM keydown event, but instead use a new event function which uses the DOM change event:

...
  on change input $ const $ do
    liftIO $ handler "File selected."

-- |change event.
change :: Element -> Event ()
change = void . domEvent "change"

The documentation for the DOM change event is very similar to that of UI.valueChange:

UI.valueChange:

Event that occurs when the user changes the value of the input element.

change:

The change event is fired for <input>, <select>, and <textarea> elements when a change to the element's value is committed by the user.

The main reason why I used the keypress event was that this makes sure that the user is the one who did the change. (This is relevant for a smooth FRP experience.) The documentation you mention indicates that the change event ensures the same thing, and I'm inclined to use it in the implementation of valueChange.

However: Do browser really follow this specification, or do they also emit a change event when the contents of the DOM element was changed programmatically, e.g. with input.val('foo') (in jQuery notation)? The latter would be undesirable.

I ran into this (or similar) problem when I wanted to use sliders (input type = range) as input.

https://gitlab.imn.htwk-leipzig.de/waldmann/matrix-game/blob/master/src/Main.hs#L101

@maweki solved it with onDomEvent "input". This is currently is not exported?