ClojureScript: require "goog.dom query" as q - clojurescript

I'm a bit confused with the import and require semantics..
I'm trying to use the query function inside the dom section of Google's clojure library.
(import '(goog.dom query))
(def q query)
Unfortunately it's not working with require :as :
(require '(goog.dom [query :as q]))
By this chance, I found out that the query function is deprecated. I don't quite get why. I'm just looking for a simple un-fancy abstraction (rather convenient simplification) to make dom manipulations/selections. I know there are tons, I just need a shortcut for not writing helpers like by-id select for every small project.

You are on the right path. You should use require in this case. Import is for a class that you want to construct.
(ns foo
(:require [goog.dom :as dom])
(:import [goog History]))
(dom/getElement "app")
(History.)
If you are using a figwheel repl, you can do this instead
(require 'goog.dom)
(goog.dom/getElement "app")
or
(require '[goog.dom :refer [getElement]])
(getElement "app")
or similar.
query is no longer avaliable, but there are plenty of useful functions like getElement getElementByClass getElementsByTagNameAndClass etc
For repl interaction you might be better using querySelector https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector instead:
(js/document.querySelector ".myclass")

Related

CLJS: Setting a JS property to the result of calling a method on it

I'm looking to modify some existing text in a web app, which I'm accessing with expressions like this:
(.-innerHTML (.getElementById js/document "myElementId"))
What I specifically want to do is mutate that text via a search/replace:
(set! (^that whole thing) (.replace (^that whole thing) "old" "new"))
And I'd ideally like to do that without having to repeat the property-access expression. Is there any existing shortcut for this? I'm envisioning something like Raku's object .= method(args) shorthand for object = object.method(args); maybe a good clj name/pattern would be (.set! (access-expression) method & args). I can always write a macro, but was wondering if I'd overlooked something already there.
I was curious too and looked in the CLJS CheatSheet and they link to the CLJS Oops library which provides similarly looking functions.
It seems to be that the most robust solution would be to just rely on the Google Closure Library (which is always at hand) and use a combination of goog.object/get and goog.object/set (no need for a macro), something like:
(require 'goog.object)
(defn update-obj! [obj field f & args]
(let [old-val (goog.object/get obj field)
new-val (apply f old-val args)]
(goog.object/set obj field new-val)))
;; Example:
(update-obj! (.getElementById js/document "my-div") "innerHTML" (partial str "it works: "))
This should work in both development and optimized output.

How to fix "clojure.test.check.generators never required" when exercising a function in clojurescript?

In a Clojurescript environment when I run the following code I get the error Var clojure.test.check.generators/simple-type-printable does not exist, clojure.test.check.generators never required.
cljs.user=> (require '[clojure.spec.alpha :as spec])
nil
cljs.user=> (require '[clojure.spec.test.alpha :as stest])
nil
cljs.user=> (defn jp-a [n] n)
#'cljs.user/jp-a
cljs.user=> (spec/fdef jp-a :args (spec/cat :n int?))
cljs.user/jp-a
cljs.user=> (spec/exercise-fn `jp-a)
#object[Error Error: Var clojure.test.check.generators/simple-type-printable does not exist, clojure.test.check.generators neverrequired]
This error is related to this issue.
You only need to define [org.clojure/test.check "0.10.0"] (or a newer version) as a dependency in your project.clj.
This is actually documented here
spec generators rely on the Clojure property testing library test.check. However, this dependency is dynamically loaded and you can use the parts of spec other than gen, exercise, and testing without declaring test.check as a runtime dependency. When you wish to use these parts of spec (typically during testing), you will need to declare a dev dependency on test.check.
In Leiningen add this to project.clj:
:profiles {:dev {:dependencies [[org.clojure/test.check "0.9.0"]]}}

Block until a DOM event occurs with core.async

I've got a Clojurescript project where i need to block the whole thread execution until an DOM event occurs.
In this case, the event is DOMContentLoaded, which fire when the initial HTML document has been completely loaded and parsed. But it could be extended to any DOM (or non-DOM) event.
As i'm new to Clojurescript and async i wasn't sure how to solve this problem. My first guess was to use the core.async library. After some doc scraping, i came with that function:
(defn wait-dom-loading
[]
(let [c (async/chan)]
{1} (.addEventListener js/document "DOMContentLoaded" (fn [] (async/go (async/>! c true))))
{2} (async/go (async/<! c))))
The way i understand it is that {2} takes from chan c and is parked until the listener in {1} evaluates the function and puts a value in chan c.
As i barely understand how to do unit tests on asynchronous code (beside puting it in an (async done) expression and calling done when done) i can't verify if what i did is correct. I tried this snippet:
(do
(wait-dom-loading)
(-> (dommy/sel1 :p)
(dommy/set-text! "Loaded !")))
With a p block inside an html page, and noticed that the console complains about the js code trying to manipulate a DOM object that don't yet exists. That confirms that what i did didn't work as planned.
What does seems wrong in this example ?
Is this overkill ? Could i solve that with a smaller solution or even gasp a built-in funtion ?
Is putting my script at the bottom of my html page a not so bad practice ?
As this was my first question on stack overflow, i hope it is well-written enough.
This is how i would do it:
(ns domevent.core
(:require [cljs.core.async :as async :refer [chan]])
(:require-macros [cljs.core.async.macros :refer [go]]))
(enable-console-print!)
(def ch (chan))
(go
(pr "i am waiting")
(pr (<! ch))
(dommy/set-text! (dommy/sel1 :p) "Loaded !"))
(.addEventListener js/document "DOMContentLoaded" (fn [] (go (>! ch "hello"))))
Or more simply:
(let [ch (chan)]
(go
(pr "i am waiting")
(<! ch)
(dommy/set-text! (dommy/sel1 :p) "Loaded !"))
(.addEventListener js/document "DOMContentLoaded" #(close! ch)))
)
The point here is the ch, which is shared by reader and writer. When (<! ch) happens, there is nothing in ch yet, so this thread is parked (i.e. stops and waits for anything to appear in ch). Meanwhile, the DOMContentLoaded occurs, and the handler writes to the channel. Then the former thread continues.

Can name munging be avoided for an interop call in ClojureScript?

In advanced compilation
(js/console.log "HELLO"
js/window.navigator.msSaveBlob
(.. js/window -navigator -msSaveBlob)
(aget js/window "navigator" "msSaveBlob")
js/console.log)
=>
HELLO undefined undefined function function
I think this means that js/console has some provided externs, but navigator does not (or at least not the ms specific stuff).
AFAIK the only way to avoid this is to create some externs? But this seems unnecessarily obtuse; why would you ever want js/anything to be munged?? Wouldn't it make make more sense to never munge js/anything interop?
System functions are not munged; only your own functions are. You probably want (.log js/console ...) ?
For de-munging your own functions, place ^:export between the defn and the function name to export its name intact.
Here is more information.
All see the section called "munging" here.

Clojure: re-export vars

Is there a way to re-export some namespace's vars from another namespace? I'd like to be able to do this:
(ns mine.core
(:use [incanter core charts datasets io]))
; re-export Incanter somehow
Then in the REPL I would be able to use Incanter's functions by just use-ing mine.core.
user=> (use 'mine.core)
nil
user=> (view (histogram (sample-normal 1000)))
Thanks!
I used to accomplish this by putting the commonly REPLd use expressions in a separate file that I can load-file when I start my REPL. This worked fairly well because I could put everything in there and then get at more than just one namespace.
Later I switched to defining an 'everything' namespace and starting my repl in that using leiningend :main directive like in this SO question which was like my first approach but seemed more elegant.
my ways continued to change and i now always switch to the namespace containing the code. This has worked well because on larger project It helps keep track of what code goes where and I think this practice helps me learn the layout of the code faster. Of course everyone's experiences are different and personal, YMMV :)
Try http://code.google.com/p/clj-nstools/
I suggest to consider importing all necessary dependencies explicitly as suggested in other answers. This usually leads to less complex code.
However if you do want this, e.g. to present a consistent interface, then you can do this with clojure.core/intern function that makes any symbol "native" to given namespace. For example:
(ns user)
(intern 'user 'map clojure.core/map)
(ns new-ns)
(require 'user)
(user/map inc [1 2 3])
; => [2 3 4]
(use 'user)
; => WARNING: map already refers to: #'clojure.core/map in namespace: new-ns,
; being replaced by: #'user/map
(map inc [1 2 3])
; => [2 3 4]
Note that changes in symbol's original namespace will not be reflected until you re-intern the symbol.