TheSpyder / rescript-webapi

ReScript bindings to the DOM and other Web APIs
http://tinymce.github.io/rescript-webapi/api/Webapi/
Other
149 stars 36 forks source link

Allow `window` and `document` to be converted into `EventTarget` #117

Closed dchambers closed 1 year ago

dchambers commented 1 year ago

First of all, thank you so much for choosing to engage in this gargantuan undertaking! I just noticed a small issue when trying to use the excellent, typed keyboard event handlers, and that was that there seems to be no way to convert window into an EventTarget.

I ended up doing this for the time being, which mitigated my issue:

open Webapi.Dom

// ...

let eventTarget = %raw(`window`)
EventTarget.addKeyDownEventListener(eventTarget, onKey(KeyDown))
EventTarget.addKeyUpEventListener(eventTarget, onKey(KeyUp))
TheSpyder commented 1 year ago

I appreciate the kind words but the bulk of this project was inherited from https://github.com/reasonml-community/bs-webapi-incubator :)

The source code doesn't make it easy to follow, but the way this works is the Webapi.Dom.Window module "includes" the EventTarget functions with the type set to Dom.window: https://github.com/tinymce/rescript-webapi/blob/c0d9b2f7120937a3c21f5c4fb10ee9ab2540d980/src/Webapi/Dom/Webapi__Dom__Window.res#L149-L156

This has the effect of copying all the functions and making them work on window references. So you can literally just call the function names from EventTarget using the Window module.

open Webapi.Dom
window->Window.addEventListener("click", _ => Js.log("clicked"))

This is a common technique used all across webapi to replicate bindings that operate at many different levels of the DOM hierarchy. Just call functions on the type you have rather than trying to convert first. We don't have a lot of documentation, but the API docs do list the EventTarget methods on the Window module. https://tinymce.github.io/rescript-webapi/api/Webapi/Dom/Window/#val-addEventListener

dchambers commented 1 year ago

the way this works is the Webapi.Dom.Window module "includes" the EventTarget functions with the type set to Dom.window [...] So you can literally just call the function names from EventTarget using the Window module.

Genius, and so my code now works 😁:

open Webapi.Dom

Window.addKeyDownEventListener(window, onKey(KeyDown))
Window.addKeyUpEventListener(window, onKey(KeyUp))

We don't have a lot of documentation, but the API docs do list the EventTarget methods on the Window module. https://tinymce.github.io/rescript-webapi/api/Webapi/Dom/Window/#val-addEventListener

That's great to know. Thank you so much for taking the time to respond to this ticket ❤️, and hopefully any others that fail to grok the same thing in the future will now find this issue.