Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce Event Calls #144

Open
massudaw opened this issue Nov 6, 2016 · 2 comments
Open

Reduce Event Calls #144

massudaw opened this issue Nov 6, 2016 · 2 comments

Comments

@massudaw
Copy link

massudaw commented Nov 6, 2016

The way events are defined for example the selectedChange event:

selectionChange :: Element -> Event (Maybe Int)
selectionChange el = unsafeMapUI el (const $ get selection el) (click el)

we need a call after the event click trigger to read the value.
I propose a new domEventH function that receive a ffi call that is evaluated and return to the bind handler

domEventH
    :: String
        -- ^ Event name. A full list can be found at
        --   <http://www.w3schools.com/jsref/dom_obj_event.asp>.
        --   Note that the @on@-prefix is not included,
        --   the name is @click@ and so on.
    -> Element          -- ^ Element where the event is to occur.
    -> JSFunction a   -- ^ Function that return marshal event value
    -> UI (E.Event a)
domEventH name el fun = do
  w <- liftIO $getWindow el
  liftIO$ addEventIO name fun False (toJSObject el) w


selectionChange :: Element -> UI (Event (Maybe Int))
selectionChange el = domEventH "change" el (ffi "$(%1).selectedIndex" el ) 

The only problem i found when implementing this was that i couldn't find a way to keep the lazy event generation and do event result marshall.

@HeinrichApfelmus
Copy link
Owner

I'm not quite sure I understand what you are suggesting and for what purpose.

Is your intention to reduce the number of runFunction calls by performing the marshalling of event values right on the client side? I.e. have the Javascript side retrieve the result of $(source).selectedIndex right when the event happens and pass the result as value to the server side?

Or is your intention to be able to implement something like selectionChange yourself? At the moment, the unsafeMapUI function is not exported. Do you have a particular use case in mind?

@massudaw
Copy link
Author

Yes my intetion is to reduce the number of funtion calls. But we can go further and allow the user define it's own events without modifying the lib.js file.

I have a use case that can greatly benefit from this, keyboard event filtering. When i need to filter when the alt key is pressed. One event is trigerred for each keypress and if i need to get a value one more call is needed to read the value. If we use a ffi javascript function to filter the event and return the value needed. This way when the event trigger with the wrong key nothing is done, no calls to the server is made, and when the right key is pressed no server call to get the value is made.

keydownFilter :: (Int,Bool,Bool,Bool) -> Element -> UI (Event KeyCode)
keydownFilter arg el = domEventAsync "keydown"  el (ffi "if ( (%2.keyCode === %3[0]) && (%2.shiftKey === %3[1] ) && (%2.altKey === %3[2] ) && (%2.ctrlKey === %3[3]) )  { (%1)([%2.keyCode,%2.shiftKey,%2.altKey,%2.ctrlKey])}" async event arg )

We can reuse the ffi code for events, allow the user to define events. Redefine some harcoded named events in lib.js for example the selectedChange. Improve performance removing unnecessary calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants