Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojurescript Add an Event Listener

(defn domready [handler]
  (.addEventListener js/window "DOMContentLoaded" handler))

I borrowed this code from here. The problem is I don't totally understand what's going on. JS interop is still a bit of a mystery to me.

  1. .addEventListener

So this is clearly a procedure call, but it's kind of generic. It's like Clojurescript took everything that was inside an object, took it out, and you use it to call that method on "objects". As long as that "object" has the ".addEventListener" property it will call this. Is that what it's doing? Why not use a keyword instead? like (:addEventListener domElement) that seems more logical to me.

  1. js/window

What is this? Is it a namespace or an object? Are they the same thing?

  1. "DOMContentLoaded"

A string, that's familiar.

  1. handler

Also familiar, but does it have a notion of this? Not that I'm really going to miss this.

like image 311
Breedly Avatar asked Dec 18 '22 21:12

Breedly


2 Answers

.addEventListener

So this is clearly a procedure call, but it's kind of generic. It's like Clojurescript took everything that was inside an object, took it out, and you use it to call that method on "objects". As long as that "object" has the ".addEventListener" property it will call this. Is that what it's doing? Why not use a keyword instead? like (:addEventListener domElement) that seems more logical to me.

Your mental model about how this works is mostly fine. What it does when it compiles is move the function name to be run as a method on the first argument.

(.method obj ...args) get's transformed to obj.method(...args)

This type of interop comes from the parent language Clojure.

On why do we have an explicit version of calling the function that's not Clojure idiomatic, I think the idea is to have clear separation between what is native Clojure code with Clojure semantics (immutability, friendly to CLJ data structures, etc) and what is interoperating with the host environment (mutable, not friendly to CLJ data structures, etc).

In my opinion it is better to have clear separation between those two given how different the semantics of CLJS and the host platforms are. For me explicitness is better than implicit in this case (it is easy to spot looking at the code what is JS code in CLJS, and what is pure CLJS).

js/window

What is this? Is it a namespace or an object? Are they the same thing?

Both, js/ is accessing the namespace js, which is where CLJS puts the JS namespace (since there is only one and global). window is just grabbing the window variable from the js namespace.

This is no different from how you access variables in other namespaces in CLJS. If you (def a 1) in (ns cljs.test) and then run cljs.test/a that will give you 1. Same form, ns/something-in-that-ns.

"DOMContentLoaded" A string, that's familiar.

\o/

handler

Also familiar, but does it have a notion of this? Not that I'm really going to miss this.

Not sure what this has to do with handler. It is just a higher order function passed into domready as a parameter, like you would do in JS: function domready (onReady) { window.addEventListener("DOMContentLoaded", onReady) }


I hope this helps, if you want to try it out live and learn some more, maybe visit the Talking with JS on the Diving into ClojureScript tutorial, or maybe check this section of the lt-cljs-tutorial.

like image 96
Joaquin Avatar answered Mar 28 '23 14:03

Joaquin


I'm just learning clojurescript so I don't really know if it is the correct answer but I've done it in the following way:

(defn handler [] (js/console.log "ready"))
(js/document.addEventListener  "DOMContentLoaded" handler)

which is then translated to

cljs.user.handler = (function cljs$user$handler(){
  return console.log("ready");
});
document.addEventListener("DOMContentLoaded",cljs.user.handler);

to check how clojurescript translate code I've used KLIMPSE http://app.klipse.tech/

like image 38
davide andreazzini Avatar answered Mar 28 '23 13:03

davide andreazzini