Fork me on GitHub
#clojurescript
<
2016-06-28
>
cfleming00:06:31

@dnolen: I’m trying to use analyze-file using the Om project as an example, but it’s having problems resolving deps, specifically:

Connecting to local nREPL server...
Clojure 1.8.0
nREPL server started on port 58699 on host 127.0.0.1 - 
(require '[cljs.analyzer.api :as api])
=> nil
(api/analyze-file "om/dom.cljs")
ExceptionInfo No such namespace: cljsjs.react, could not locate cljsjs/react.cljs, cljsjs/react.cljc, or Closure namespace "cljsjs.react" in file /Users/colin/dev/om/src/main/om/dom.cljs  clojure.core/ex-info (core.clj:4617)

cfleming00:06:43

/Users/colin/.m2/repository/cljsjs/react/15.0.1-1/react-15.0.1-1.jar is on the classpath.

cfleming00:06:52

Is there anything else I need to do to initialise this?

cfleming00:06:25

I can analyze some others successfully, e.g. "om/next/cache.cljs"

cfleming00:06:26

Hmm, even when analysis doesn’t produce errors, I get a ton of errors like: WARNING: Use of undeclared Var om.util/seq? at line 6 /Users/colin/dev/om/src/main/om/util.cljc, and at the end of it cljs.env/*compiler* is nil - I must be missing something basic.

lwhorton00:06:07

so I can use cljsjs to import something like [cljsjs/react] into my project, but what if during runtime the react is going to be provided on the window instead? is there someway I can appease the classpath checking and not actually pull in cljsjs/react (and end up with 2 copies of react)?

cfleming03:06:48

By wrapping my call above in compiler/with-core-cljs I managed to fix the warnings, but I still get no result in cljs.env/*compiler*

cfleming04:06:49

What I ended up with:

(def result (let [opts (closure/add-implicit-options nil)
                  state (env/default-compiler-env opts)]
              (api/analyze-file state "cljs/core.cljs" opts)
              (api/analyze-file state "om/dom.cljs" opts)
              @state))

skrat05:06:19

does any one know why this would print ("MISS" ... true), ie. the keys is there but it always goes to MISS https://gist.github.com/skrat/d29203738a3e855ff7eab4df7fc9e470

henriklundahl06:06:46

@skrat: The only case I can imagine is if the stored value is identical to the value of lookup-sentinel...

skrat08:06:19

henriklundahl: it was something else http://stackoverflow.com/a/38069830/104337

plexus08:06:25

Is there a ClojureScript library that can turn a JS date into a string like "7 minutes ago", "one week ago", etc?

plexus08:06:42

ah nice, thanks @rauh (require '[goog.date.relative :refer [format]])

conaw10:06:54

Hey, anyone know if there is more idiomatic way to handle callbacks in js interop than this

(-> (.getDocument js/PDFJS "/onlisp.pdf")
     (.then 
      (fn callback1 [pdfFile] 
        (-> (.getPage pdfFile 1)
            (.then 
             (fn callback2 [page]
               (.getViewport page 1)))))))

kauko10:06:38

.then means you're using promises, right? Maybe you could use a promises library for cljs?

kauko10:06:24

Not sure if it'll help you

darwin10:06:25

usually when I expect to use the same js interop a lot, I just write idiomatic cljs wrappers and use them instead, I tend to turn callbacks into core.async channels

rauh10:06:13

@conaw: You should be able to avoid the nested .then by just returning a promise again. That makes it more linear.

kauko10:06:53

(-> (.getDocument "foo")
  (.then (fn cb1 [file] (.getPage file)))
  (.then (fn cb2 [page] (.getViewport page))))
Like this?

conaw10:06:43

nice, much appreciated!

conaw10:06:57

While I have your attention — I had just been going back to my pre-react and pre-cljs code to re-learn direct dom manipulation, since this libraries does its writing directly to the canvas.

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

var renderContext = {
    canvasContext: context,
    viewport: viewport
};

page.render(renderContext);
Anyone have any good pointers (ideally an example of someone else whose done it, or a blog post or something), on how I might build a wrapper for their UI stuff and port it to reagent

darwin11:06:06

AFAIK you have to wrap it in a react component and implement the canvas rendering via react component's life-cycle methods

conaw11:06:57

Any libs come to mind where the author may have done this?

conaw11:06:03

or example projects?

darwin11:06:11

I assume you don’t need to animate the canvas, just render it once it gets mounted

lwhorton11:06:22

@rauh thanks for that.. one piece i’m a little confused on is react-dom-server; are you familiar with the packaging here?

lwhorton11:06:46

i.e. do I need react/dom/server.cljs, too? for something like reagent that depends on all 3 r/dom/server?

conaw11:06:30

Well, what I need to do is to figure out how to wrap functions like this

var currPageNumber = 1;

var openNextPage = function() {
    var pageNumber = Math.min(pdfFile.numPages, currPageNumber + 1);
    if (pageNumber !== currPageNumber) {
        currPageNumber = pageNumber;
        openPage(pdfFile, currPageNumber);
    }
};

var openPrevPage = function() {
    var pageNumber = Math.max(1, currPageNumber - 1);
    if (pageNumber !== currPageNumber) {
        currPageNumber = pageNumber;
        openPage(pdfFile, currPageNumber);
    }
};
and other PDFjs functionality into something that can compose with my own UI

conaw11:06:56

sorry, that was bad example

conaw11:06:37

pageElement.addEventListener('touchmove', function(e) {
    if (pageElement.scrollLeft === 0 ||
        pageElement.scrollLeft === pageElement.scrollWidth - page.clientWidth) {
        reachedEdge = true;
        if (touchStart === null) {
            touchStart = e.changedTouches[0].clientX;
        }
    } else {
        reachedEdge = false;
        touchStart = null;
    }

    if (reachedEdge && touchStart) {
        var distance = e.changedTouches[0].clientX - touchStart;
        if (distance < -100) {
            touchStart = null;
            reachedEdge = false;
            openNextPage();
        } else if (distance > 100) {
            touchStart = null;
            reachedEdge = false;
            openPrevPage();
        }
    }
});

darwin11:06:41

I think you can do it the “dirty” way and use this code “as is” - attaching event listeners after react mounts your pageElement

conaw11:06:30

just say, on-swipe dispatch a re-frame event to call ‘dirty-fn

darwin11:06:50

more clean option would be to make page number input state of your component wrapping canvas and changing this input when your touch events call prev/next page switch (by re-rendering your reagent component tree)

conaw11:06:51

where dirty-fn is openPrevPage

conaw11:06:22

I mean, the thing I really want access to is the invisible text div that PDFjs creates over the view

conaw11:06:30

so I can attach things to that

conaw11:06:29

in the clean example you describe

conaw11:06:40

how would that work with the re-frame 3 component

conaw11:06:11

that does seem like exactly what I would want

darwin11:06:28

in that reframe example [x y z] are inputs, your canvas wrapper component would take [page-num …] and render given page in :reagent-render

darwin11:06:01

you would also attach touchmove event listener, in :component-did-mount

darwin11:06:47

openPrevPage would not directly touch canvas and re-render it, it would just change state of your app and decrease page-num in your app-db (which should cause re-rendering of your component)

conaw11:06:51

ok, I think I was getting more confused by this examples use of global vars actually, was just thinking how I would connect it to the appropriate element in my dom tree. in their render function they use

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var pageElement = document.getElementById('page');

conaw11:06:55

the question is more, how does one hook those places where they use the getElementById to the right reagent component

conaw11:06:29

or should I just create a div with some unique ID as the component, and render as they do

darwin11:06:53

in :component-did-mount you should have access to the root element of your component

darwin11:06:31

so you should be able to create your dom elements and append them to it

conaw11:06:50

just with like a (.appendChile … …)

conaw11:06:59

.appendChild

conaw11:06:32

so would i use

this-as
, and then call .findDOMNode, or is there a better way to access that root

dominicm12:06:48

@conaw: No problem. I'm pretty sure I used it for a similar problem to you. I was using a d3 wrapper, but it was still d3.

dnolen13:06:16

@cfleming: sorry wasn’t around yesterday for that question - seems maybe you got it sorted out?

peterschwarz15:06:50

@savelichalex: could you give an example of your then-> macro? I have tried building similar macros, but I've never quite been happy with the result..

rnandan27317:06:18

Any suggestions on choice of responsive and material design frameworks? I tried to use cljs-react-material-ui "0.2.17" but found it to be not responsive

rnandan27317:06:03

I meant using this in re-frame

ethangracer17:06:08

has anybody used cljsjs/d3 with advanced compilation? Some of my graphics have different behaviors when compared to simple or no optimizations, but there are no errors at compilation or in the console. Not sure where to start with troubleshooting

dnolen17:06:18

d3 doesn’t go through advanced compilation

dnolen18:06:03

I have seen Closure do weird stuff with more involved math ops written in ClojureScript due to bugs in order of evaluation

ethangracer18:06:35

interesting — order of eval is different between cljs and js?

dnolen18:06:50

nothing to do with ClojureScript

dnolen18:06:54

advanced compilation

dnolen18:06:00

and ClojureScript goes through it

dnolen18:06:27

that is you can replicate the problem by writing JavaScript by hand that exhibits the problem

ethangracer18:06:42

so you’re saying I should look at google closure math operations? I get your point that d3 doesn’t go through advanced comp, so I imagine it has something to do with some numerical computation

dnolen18:06:48

I encountered this when I implemented Murmur3 hashing

dnolen18:06:16

yes if your ClojureScript/JavaScript has a lot numerical stuff and it goes through advanced optimization

vinnyataide18:06:36

hola, quick question, can I use cljs 1.9 with clj 1.8 or is necessary the alpha version?

dnolen18:06:47

@vinnyataide: you can use clj 1.8 - that’s the expressed dep

dnolen18:06:56

clj 1.9 also happens to work

dnolen18:06:47

@ethangracer: it’s super annoying

dnolen18:06:19

I would look to isolate the actual computation and verify that the results look the same under both compilation modes

ethangracer18:06:21

you’ll get no argument from me! good thought on that approach, i’ll give that a go. crazy that closure is removing necessary parens

ethangracer18:06:41

then again, dead code algorithms are a pain

cfleming19:06:40

@dnolen: No worries, yes I think it’s sorted.

cfleming19:06:57

Just took a little code spelunking.

rohit19:06:04

@ethangracer: there is a small probability that the d3 externs being provided by cljsjs may not be complete.

rohit19:06:39

And that might also explain things being broken under advanced compilation.

ethangracer20:06:31

@rohit: thanks, it does seem like d3 is working but the translation and scale attributes are being set improperly

ethangracer20:06:52

if I can pin it down I’ll post here but it remains elusive

rohit20:06:51

@ethangracer: sure. that’d be great. if you suspect that its an extern issue, you could try setting the :pseudo-names compiler option. https://github.com/clojure/clojurescript/wiki/Compiler-Options#pseudo-names

rohit20:06:09

assuming that its not something deeper

ethangracer20:06:17

@rohit I’m not getting any compilation errors on d3 functions, just some for using this-as

blance21:06:31

Hey guys, what do you use for testing cljs app built on top of reagent/re-frame? I'm pretty new to (frontend) testing in general, and my mentor who works in JS suggests to take a look at lint, code coverage, jasmine, he also mentions something like mocking the api response and etc.

blance21:06:50

Is there a good testing guide/tutorial for clojurescript cover most of those stuffs?

ethangracer21:06:53

@rohit @dnolen turns out a change from (.-prop obj) to (aget obj “prop”) fixed the discrepancy

dnolen21:06:32

@ethangracer: goog.object/get is recommended over aget

dnolen21:06:43

that aget works is just a quirk of how we compile it

dnolen21:06:09

in anycase that sounds like an extern problem

ethangracer21:06:20

@dnolen good to know, thanks. if we define our own properties on a plain javascript map, do we have to declare those properties as externs so they aren’t renamed?

dnolen21:06:05

if you are treating an object as a map don’t use property access

dnolen21:06:18

use goog.object

ethangracer21:06:29

got it, thanks

dnolen21:06:29

property access is really only for things which can be optimized or foreign libraries which cannot go through optimization

blance23:06:54

does anyone know how to include foreign libs with lein-doo?

anisoptera23:06:08

i'm bashing my head against a dynamism problem

anisoptera23:06:45

i need to save a function name or symbol in some json, and then read it back out later and call that function

anisoptera23:06:00

everything i've seen suggests that you can't do that without serious hacks in cljs, which, fine

anisoptera23:06:48

any ideas about a workaround? is there a way i can refer to the compiler-munged name in my code?

anisoptera23:06:30

it's just a cache, so i could live with the saved symbols not working after a recompile

anisoptera23:06:22

i could also, i suppose, export all the functions i plan on calling this way, which at least keeps their names the same, if that would help

anisoptera23:06:53

if i'm going to end up with a dispatch table, any ideas on some macro design that would make that less gross?

anisoptera23:06:14

i thought maybe i could do something with (var ...), because it says it gives compile-time metadata, but i guess that's not actually what i'm looking for