Fork me on GitHub
#clojurescript
<
2016-07-07
>
johanatan04:07:20

anyone have experience exposing clojurescript modules to javascript via webpack (with or without use of closure-loader)?

rauh05:07:28

@blance: Just read the css string in with a macro and store it in some def. Then inject the CSS with goog.style on startup.

dev-hartmann09:07:40

hey fellow clojurians, i'm working working on building a linechart with the help of d3 but have a question translating javascript into clojurescript code relevant snippets: js

var valueline = d3.svg.line()
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y(d.close); });

dev-hartmann09:07:09

var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]); 

dev-hartmann09:07:37

and that's my cljs code

(defn create-svg-value-line [data]
  (-> (js/d3.svg.line)
      (.x (clj->js (:date data) ))
      (.y (clj->js  (:close data))) 

dev-hartmann09:07:59

ideas suggestions will be accepted thanksfully

rohit09:07:21

@dev-hartmann: x and y in cljs would be

(def x (-> js/d3
           .-time
           .scale
           (.range #js [0 width])))

rohit09:07:44

(def y (-> js/d3
           .-scale
           .linear
           (.range #js [height 0])))

rohit09:07:02

regarding create-svg-value-line, I am assuming that data is a cljs data structure rather than a js one.

rohit09:07:17

I think you are missing calls to x and y (the two scales) in your create-svg-value-line

tjg10:07:01

@turbopape: Hope I'm not being annoying (as opposed to "showing pleasant enthusiasm"), but still no TOC nor sample. 😕 https://www.packtpub.com/web-development/learning-clojurescript

turbopape10:07:54

Ah sorry. I'll share a Toc asap (I am out now)

dev-hartmann10:07:23

@rohit: thnaks a lot, got that defined, but how du i call them with data in the create-svg-line function,x and y defs i mean

rohit10:07:26

@dev-hartmann: i think you were almost there. (.x (x (clj->js (:date data)))). note that extra call to x.

dev-hartmann10:07:44

ah, now i get it

rohit10:07:55

@dev-hartmann: just double check what is data. i have a feeling that its a js datastructure and in that case, the code won’t work.

dev-hartmann10:07:09

no, it's a clojure map

rohit10:07:17

all good then!

rohit10:07:20

@dev-hartmann: another thing, if (:date data) returns a primitive data type, then you don’t need to a clj->js on it.

rohit10:07:47

same thing for (:close data)

dev-hartmann10:07:02

@rohit: thank you very much

dev-hartmann10:07:15

still having issues

dev-hartmann10:07:46

(def chart-margins {:top 20 :right 20 :bottom 30 :left 50})

(def days ["Mo" "Di" "Mi" "Do" "Fr" "Sa" "So"])

(defn calc-width [base-width {:keys [left right]}]
  (- base-width left right))

(defn calc-height [base-height {:keys [top bottom]}]
  (- base-height top bottom))

(defn calc-x [width ordinal-domain]
  (-> (js/d3.scale.ordinal)
      (.domain (clj->js ["Mo" "Di" "Mi" "Do" "Fr" "Sa" "So"] ))
      (.rangePoints (clj->js [0 width]))))

(defn calc-y [height]
  (-> (js/d3.scale.linear)
      (.range (clj->js [height 0]))
      (.domain (clj->js [0 500]))))

(defn calculate-axis [axis-def orientation]
  (-> (js/d3.svg.axis)
      (.scale axis-def)
      (.orient orientation)))

(defn create-svg-value-line [identifier y-scale x-scale data]
  (-> (js/d3.svg.line)
      (.x  (x-scale (clj->js (((keyword identifier) data)))))
      (.y  (y-scale (clj->js (:day data))))))

(defn create-line-chart-svg [id height x y]
  (->  (js/d3.select id)
       (.append "g" )
       (.attr "class" "y-axis")
       (.call (clj->js y) )
       (.append "g" )
       (.attr "class" "x-axis")
       (.attr (clj->js ["transform" (str "(translate(0," height ")")]))
       (.call (clj->js x))))

(defn create-panel-svg [base-width base-height id]
  (let [height (calc-height base-height chart-margins)
        width (calc-width base-width chart-margins)
        y-scale (calc-y height)
        x-scale (calc-x width days)
        y-axis (calculate-axis y-scale "left")
        x-axis (calculate-axis x-scale "bottom")]
    [:svg {:id "line-chart" :width 1000 :height 200}
   [:g {:transform (str "translate(" (/ 1000 2) "," (/ 200 2) ") scale(1) rotate(0,200,200)")}
    [:path {:d ((create-svg-value-line "vuln-high" y-scale x-scale dummy-data))}]
    [:text {:font-size "80px" :fill "white" :text-anchor "middle" :y 20  }]]]

  (create-line-chart-svg id height x-axis y-axis)))
 

dev-hartmann10:07:15

at the moment it looks very ugly, sry, but i'm in desperate experimenting mode -.-

dev-hartmann10:07:58

forgot dummy data

))

dev-hartmann10:07:21

(def dummy-data [ {:vuln-high 50 :day "Mo"} {:vuln-high 50 :day "Di"} {:vuln-high 50 :day "Mi"}])

rohit10:07:20

@dev-hartmann: btw, are you using #C0620C0C8?

dev-hartmann10:07:27

Mean :face_with_rolling_eyes:

rohit10:07:54

@dev-hartmann: in that case, i think the approach you are taking may not be a good one. jump onto #C0620C0C8. also look at http://zachcp.org/blog/2015/reagent-d3/

mfikes11:07:07

@aengelberg: Your re-seq issue may have been exacerbated by a lack of locals clearing. For more see http://blog.fikesfarm.com/posts/2016-01-15-clojurescript-head-holding.html

dev-hartmann11:07:51

@rohit: yeah, i know what mean, i just wanted to get the graph done with dummy data first, to see if i got everything right and then put all of that into a reagent component. but thee blogpost looks promissing, so i'll try that

akiel12:07:27

Hi, is there a JWT lib like buddy for CLJS?

dev-hartmann12:07:28

@rohit: btw did you see anything else, that did prevent my code from working? still couldn't find whats going wrong

rohit12:07:47

@dev-hartmann: actually i can’t figure out how you are running it etc. if you can share a project or something, i can have a look

dev-hartmann12:07:14

@rohit: damn, i can't it's a work project

rohit12:07:38

@dev-hartmann: i understand that. my 2 cent advice: remove all the code and then start adding code which works till you reach points of failure.

dominicm12:07:23

Sometimes you solve it yourself that way too ^^

dev-hartmann12:07:45

@rohit: thanks again! your help is very much appreciated. almost done with the component

rohit12:07:13

@dev-hartmann: sweet. :thumbsup::skin-tone-4:

dev-hartmann12:07:56

(defn line-chart-compnent [id bwidth bheight]
  (reagent/create-class
    {:reagent-render (fn []  [:div [:svg {:id id :width bwidth :height bheight}]])
     :component-did-mount (fn []
                            (let [d3data (clj->js dummy-data)
                                  height (calc-height bheight chart-margins)
                                  width (calc-width bwidth chart-margins)
                                  y-scale (calc-y height)
                                  x-scale (calc-x width days)
                                  y-axis (calculate-axis y-scale "left")
                                  x-axis (calculate-axis x-scale "bottom")]
                              (.. js/d3
                                  (select id)
                                  (append "g")
                                  (attr "transform" (str "translate(" (/ 1000 2) "," (/ 200 2) ") scale(1) rotate(0,200,200)"))
                                  (append "path")
                                  (attr "d" (create-svg-value-line "vuln-high" y-scale x-scale d3data))
                                  (append "g")
                                  (attr "class" "x-axis")
                                  (call  x-axis )
                                  (append "g")
                                  (attr "class" "y-axis")
                                  (call  y-axis ))))}))

dev-hartmann12:07:07

that's the component btw

dev-hartmann12:07:20

interestingly that one doesn't get rendered at all :thinking_face:

dominicm12:07:55

As an aside, because I've seen people do this a lot. Your use of "id" for referring to the svg isn't necessary.

dominicm12:07:09

React has a function that let's you get the dom node of the component.

dominicm12:07:36

It might also need to be (select (str "#" id))

dev-hartmann12:07:59

thought of that too, thank you very much!

dominicm12:07:53

(-> (dom-node this) (.childNodes) (first)) might be a more specific way of referring to what you intend.

dominicm12:07:11

That would also remove ambiguity regarding the id problem too.

dev-hartmann12:07:49

@rohit: i guess i found the issue:

(defn create-svg-value-line [identifier y-scale x-scale data]
  (-> (js/d3.svg.line)
      (.x  (x-scale (((keyword identifier) data))))
      (.y  (y-scale ((:day data)))))) 

dev-hartmann12:07:52

that function gives me the error: component.cljs?rel=1467895555146:47 Uncaught TypeError: Cannot read property 'call' of null

rohit12:07:20

@dev-hartmann: you may have an extra pair of parens around arguments to the two scales

dev-hartmann13:07:12

@rohit: that's very true 😉 now i get component.cljs?rel=1467896362930:52 Uncaught TypeError: Cannot read property 'x' of undefined

rohit13:07:29

@dev-hartmann: try writing (js/d3.svg.line) more idiomatically

dev-hartmann13:07:39

@rohit:

(defn create-svg-value-line [identifier y-scale x-scale data]
  (-> js/d3
      .-svg
      .line
      (.x  (x-scale (fn [d] ((keyword identifier) d)) data))
      (.y  (y-scale (fn [d](:day d)) data)))) 

dev-hartmann13:07:05

now i get cannot d3.inc.js:8124 Uncaught TypeError: Cannot read property 'length' of undefined

rohit13:07:49

@dev-hartmann: now you are very much in d3 land.

dev-hartmann13:07:26

is that a good or bad thing 😛

rohit13:07:53

@dev-hartmann: just a different problem. 😉

rohit13:07:27

btw, if i am doing deep js interop, i always look at the js clojurescript compiler generates

dev-hartmann13:07:10

i guess you meant this

return d3.svg.line().x(cljs.core.clj__GT_js.call(null,(function (d){
return x_scale.call(null,cljs.core.keyword.call(null,identifier),d).call(null);
}).call(null,data))).y(cljs.core.clj__GT_js.call(null,(function (d){
return y_scale.call(null,new cljs.core.Keyword(null,"day","day",-274800446).cljs$core$IFn$_invoke$arity$1(d));
}).call(null,data)));

dev-hartmann13:07:34

what it should resemble is this

var valueline = d3.svg.line()
        .x(function(d) {
            return x_scale(d[identifier]); })
        .y(function(d) {
            return y_scale(d.day);});

dnolen13:07:08

@dev-hartmann: this sounds like you’re passing something to D3 which is not array-like

dev-hartmann13:07:19

@dnolen: it's an array of maps

dnolen13:07:04

you may believe you are doing that, but that’s not what the error says 🙂

dnolen13:07:16

you might want to enable source mapping and poke around in the stacktrace.

dev-hartmann13:07:18

@dnolen: point taken 😉

dev-hartmann13:07:02

@dnolen: being a noob sucks. how exactly would i do that?

dnolen13:07:29

are you using lein-cljsbuild? boot?

dev-hartmann13:07:56

lein-cljsbuild

dev-hartmann14:07:34

#js [#js {:vuln-high 50, :day Mo} #js {:vuln-high 50, :day Di} #js {:vuln-high 50, :day Mi}]... that's what mit data looks like

dev-hartmann14:07:52

seems about right, javascript array and javascript maps inside

dev-hartmann14:07:23

and not this code looks about right

frontend.dashboard.component.create_svg_value_line = (function frontend$dashboard$component$create_svg_value_line(identifier, y_scale, x_scale, data) {
    cljs.core.println.call(null , data);
    return d3.svg.line().x((function(d) {
        return x_scale.call(null , cljs.core.keyword.call(null , identifier).call(null , d));
    }
    ).call(null , data)).y((function(d) {
        return y_scale.call(null , new cljs.core.Keyword(null ,"day","day",-274800446).cljs$core$IFn$_invoke$arity$1(d));
    }
    ).call(null , data));

dev-hartmann14:07:53

but still i get d3.inc.js:8124 Uncaught TypeError: Cannot read property 'length' of undefined

rohit14:07:02

@dev-hartmann: whats data like?

rohit14:07:32

most likely it should be a js object

dev-hartmann14:07:55

#js [#js {:vuln-high 50, :day Mo} #js {:vuln-high 50, :day Di} #js {:vuln-high 50, :day Mi}]

dev-hartmann14:07:26

(def dummy-data [
                 {:vuln-high 50 :day "Mo"}
                 {:vuln-high 50 :day "Di"}
                 {:vuln-high 50 :day "Mi"}])

dev-hartmann14:07:36

that's the original clojure map

dev-hartmann14:07:00

and i do

let [d3data (clj->js dummy-data)] 

rohit14:07:20

@dev-hartmann: ok. if its a js object then you can’t do a lookup by keyword for the scales.

rohit14:07:33

you’ll have to use goog.object/get

dev-hartmann14:07:11

like here

(defn create-svg-value-line [identifier y-scale x-scale data]
  (-> js/d3
      .-svg
      .line
      (.x  (x-scale (fn [d] ((keyword identifier) d)) data))
      (.y  (y-scale (fn [d](:day d)) data)))) 

rohit14:07:06

you’ll have to do something like

(.y  (y-scale (goog.object/get data "day”)))

dnolen14:07:22

the x-scale stuff also needs to change

dnolen14:07:31

if you have JS data you need to use JS operations

dev-hartmann14:07:18

ah, ok that makes sense

dev-hartmann14:07:29

that's how the code creating the scales

(defn calc-x [width]
  (-> js/d3
      .-scale
      .ordinal
      (.domain #js ["Mo" "Di" "Mi" "Do" "Fr" "Sa" "So"] )
      (.rangePoints #js [0 width])))

(defn calc-y [height]
  (-> js/d3
             .-scale
             .linear
             (.range #js [height 0])
             (.domain #js [0 500])))


(defn calculate-axis [axis-def orientation]
  (-> js/d3
      .-svg
      .axis
      (.scale axis-def)
      (.orient orientation)))

dev-hartmann14:07:55

the js created looks pretty much like the example code i found

rohit14:07:34

@dev-hartmann: thats good! 🙂

dev-hartmann14:07:33

(defn create-svg-value-line [identifier y-scale x-scale data]
  (-> js/d3
      .-svg
      .line
      (.x  (fn [d](x-scale (goog.object/get d identifier ) )) data)
      (.y  (fn [d](y-scale (goog.object/get d "day" ) )) data))) 

dev-hartmann14:07:49

but still i get d3.inc.js:8124 Uncaught TypeError: Cannot read property 'length' of undefined

dev-hartmann14:07:34

that's kinda hard to get, but thank you both @rohit and @dnolen for helping out!

rohit14:07:22

@dev-hartmann: i’ve created a very simple example of creating a svg line using d3 here: https://github.com/ducky427/testd3

rohit14:07:28

Hope this is helpful to you

dev-hartmann14:07:01

And i can See what i did wrong spot on ;)

dev-hartmann14:07:35

Thx! Will try it when i hit The Train

dev-hartmann15:07:27

@rohit: works! I get path etc ;)

nha16:07:32

Anyone has strong opinions for clojurescript configuration ? I have seen https://www.martinklepsch.org/posts/parameterizing-clojurescript-builds.html and https://github.com/adzerk-oss/env (but I already use environ)

nha16:07:13

I want to use it for things like server-url etc. not for debugging purposes.

pesterhazy16:07:42

personally I don't like having the cljs build depend on env variables

pesterhazy16:07:37

it introduces a hidden build-time dependency, and it's hard to figure out for new team members

pesterhazy16:07:21

I know that's how many people do it though, so take this with a grain of salt

pesterhazy16:07:21

how about prepending a javascript configuration file (binding a JSON to a global var) to the bundle output?

pesterhazy16:07:48

it's not particularly elegant

pesterhazy16:07:56

but it works 🙂

nha16:07:02

Ah not in my case - I do not want to "pollute" the global namespace

nha16:07:11

As the resulting js file is meant to be distributed

nha16:07:20

But good point about the build though. I don't really care about team members (for the time being it's me myself and I) but I am clumsy enough that I could set env vars when building locally and forget about them

nha16:07:59

(or is that how it would work with aot ? not even completely sure)

pesterhazy16:07:52

you're right about the polluted namespace

rohit16:07:20

@nha: i’ve personally used goog.define approach @martinklepsch mentions in his blog post. it works really well when used with leiningen profiles.

nha16:07:54

I forgot to mention that I use boot, but I see that it could play well.

pesterhazy16:07:12

you could also require different configuration namespaces depending on the environment (production, staging, local)

nha16:07:20

I just found this also: https://groups.google.com/forum/#!topic/clojurescript/YV-051DmdFE looks like a simplified version of adzerk/env

pesterhazy16:07:58

@nha, what's stopping you from just calling System/getenv in a macro?

nha16:07:02

I could do something like that right

nha16:07:54

I'll play around a bit - probably with adzerk.env first. Thanks for the thoughts !

nha16:07:50

Seems like the macro there doesn't do nested properties: https://groups.google.com/forum/#!topic/clojurescript/YV-051DmdFE

nha16:07:01

modifying it with get-in seems to break it - return nil (but I'm not completely comfortable with macros)

blance16:07:49

@rauh: That's a great idea! Can you help explain a bit on how to read local file at compile time(I'm assuming through clj? ) and use the content at runtime (like you said in some def)?

kenny19:07:45

Is there a changelog for transit-cljs somewhere?

Alex Miller (Clojure team)19:07:53

I don’t think there is a maintained changelog, but commits are here: https://github.com/cognitect/transit-cljs/commits/master

dnolen20:07:45

@kenny: there isn’t and I just do not have time for that. Sorry for that.

kenny20:07:15

@dnolen: Understandable, thanks.

dnolen20:07:42

we’re also not currently taking PRs on the transit projects - would happily offload such a task to the community

dnolen20:07:17

I recommend starting a discussion on the transit mailing list about that if you’re serious about getting some movement on that.

Alex Miller (Clojure team)20:07:30

I'd be happy to take care of the last mile of commiting that to the readme

dnolen21:07:41

Should ClojureScript emit a warning or throw an error if trying to use something marked private, thoughts?

dnolen21:07:14

I’m leaning warning since it’s easily circumventable in Clojure if need be

dnolen21:07:23

feel free to leave your thoughts here if you have them ^

danielcompton21:07:53

Warning seems right to me too

hueyp22:07:42

sorry, not immediately finding this — but is there a rational / statement on what browsers cljs wants to support?

dnolen22:07:37

we only generate ECMA-262 JS (circa 2001) and we rely on Google Closure so technically we support browsers all the way back to IE6 still.

ethangracer22:07:46

is it possible to refactor requires in this format

[app.package1.ns1 :as ns1]
[app.package1.ns2 :as ns2]
[app.package2.ns3 :as ns3]
into
[app
 [package1
  [ns1 :as ns1]
  [ns2 :as ns2]]
 [package2
  [ns3 :as ns3]]]

ethangracer22:07:11

I know it is in clojure, I’m getting compiler errors in cljs so I assume the answer is no, just wanted to be sure I wasn’t missing something