javascripteventsclojurescriptclojure-java-interop

Binding Resize event to Clojurescript using Jayq


I am trying to create a simple clojurescript which'll display the width of the browser window.

My app.cljs look like the following:

(ns acme.frontend.app
(:use [jayq.core :only [$]])
(:require-macros [hiccups.core :as hiccups :refer [html]])
(:require [hiccups.runtime :as hiccupsrt]))

(def $body ($ :body))

(def window-width (atom nil))

(defn on_window_resize
  []
  (reset! window-width (.-innerWidth ($ :window)))
  (println window-width))


(defn init []
  (set! (.-onload ($ :document))
    ((fn []
       (set! (. ($ :window) -resize) (())))))
  (let [$dyncontent ($ :#svgcontent)]
    (.html $dyncontent @window-width))
  (println "ScriptLoaded"))

My Shadow-cljs.edn looks as follows:

{:source-paths
 ["src/dev"
  "src/main"
  "src/test"]

 :dependencies [[cider/cider-nrepl "0.25.10"]
            [jayq "2.5.4"]
            [hiccups "0.3.0"]]
 :builds
 {:frontend
   {:target :browser
    :modules {:main {:init-fn acme.frontend.app/init}}
    :devtools {:http-root "public"
          :http-port 8081}
    :optimizations :advanced
    :externs ["externs/jquery.js"]}}}

The code compiles and I see main.js in the public/js folder.

However this does nothing. I can resize the window as much as I like nothing happens.

I am very new to clojure/script so I maybe doing something silly. But what am I doing wrong?

As a side note is there a way to run browser-repl on the same index.html file that we are currently hosting? When I run shadow-cljs browser-repl a new window opens hosted at a different port. How can they be the same so that the development is on the same page?

UPDATE I've since updated my code slightly. Now the init & onDOMLoad functions looks as follows:

(defn onDOMLoad
 []
 (.resize ($ :window) on_window_resize))

(defn init []
 (.ready ($ :document) onDOMLoad))

This fails to do anything when resizing.

However the js version works, as shown below:

(defn onDOMLoad
 []
 (.addEventListener js/window "resize" on_window_resize))

from this I am assuming jayq doesn't let you bind to resize events. Am I barking up the wrong tree?

UPDATE: I have now given up on using jayq on clojurescript. Instead I find goog.dom to be much more user friendly. I am following learn clojurescript book for guidance on this. I am closing this question accordingly. Many thanks.


Solution

  • In your (defn init [] ...) you are creating a anonymous function and then immediately call it by having the extra parens ((fn [] ...)). So the result of that function call is what you set! as the onload instead of the function itself. Just remove one pair of parens.

    In your config you are setting :optimizations and :externs in the wrong level. They need to be under the :compiler-options key. You do not need to set :optimizations at all though, they default to :advanced for browser release builds.

    browser-repl starts a standalone browser REPL independenct of any build. If you want a REPL into your build use shadow-cljs cljs-repl frontend.