Fork me on GitHub
#hoplon
<
2016-09-04
>
mac14:09:11

@flyboarder I think I have figured out how to build a reasonable version of ProseMirror, but I am having some issues figuring out how to expose it to ClojureScript.

flyboarder15:09:59

@mac good to hear! What is the current issue?

onetom15:09:03

indeed, it would be really awesome to have prose mirror available from hoplon

mac15:09:56

@flyboarder I have a file that imports all the needed parts. It contains a section that looks like this:

 = {
    ProseMirror: ProseMirror,
    schema: schema,
    exampleSetup: exampleSetup,
    buildMenuItems: buildMenuItems,
    tooltipMenu: tooltipMenu,
    menuBar: menuBar
};

mac15:09:05

At the same time I have:

(cljs :compiler-options {:foreign-libs [ {:file "src/prosemirror.js"
                                             :provides ["pm"]
                                             }
                                            ]})

mac15:09:00

@flyboarder in my build.boot. Is this the correct way to do it and what is the way to access the lib from Hoplon?

mac15:09:46

@flyboarder At the moment I am seeing a lot of weird behaviour, things changing on reload that should not etc.

flyboarder15:09:27

Ok, try generating externs for your file here http://michaelmclellan.me/javascript-externs-generator/, also I think the foreign lib setup will need to change a bit, just jumping in the shower then I'll be back :)

onetom15:09:35

@mac by reload you mean boot-reload right? 1st i wouldn't add that to the mix, because that complicates things further.

mac15:09:22

@onetom No, just saving which triggers a recompile by Hoplon. Sorry should have been more precise.

mac15:09:07

@flyboarder Tried using the externs generator from file shared on dropbox and github, nothing happens.

flyboarder15:09:25

@mac must be a file which serves it with the correct mime type, GitHub raw doesn't do this

mac15:09:41

@flyboarder Ah, Google Drive perhaps?

mac16:09:34

@flyboarder So got the file loaded using RawGit .-) It asks which object to extern?

onetom16:09:56

@mac well "save triggers a recompile by Hoplon" means the builtin watch task re-runs all the other task following it in your task pipeline:

(speak)   (hoplon)   (reload)   (cljs-repl)   (cljs)   (serve :port 8000)
out of these the reload task - which is provided by the mentioned boot-reload package - tells the browser which files to reload. since your index page probably depends on all of your other files, it will run again, triggering a regeneration of your whole page. so if you put any kind of init code there, it will run again. some external libraries complain about being loaded twice, so you probably want to avoid this

flyboarder16:09:19

@mac you probably want 'pm' as the object

mac16:09:35

@onetom I think the reload issue is a big part of the problem. I thought with-init! took care of it.

onetom16:09:22

@mac the with-init! only solves the correct initialization order problem. hot-code-reloading while your app is running in the browser is a whole different issue. that's really something which most external libraries didn't prepare for.

mac17:09:09

@onetom Is it safe to cobine with-init! and defonce?

flyboarder18:09:31

@mac I don't think that will solve the problem, when a namespace is reloaded all the things that depend on or use that ns will be reloaded, including things that are defonce per my understanding

flyboarder18:09:11

Applications don't assume parts of them will be regenerated once they are compiled

mac18:09:50

@flyboarder No, I think I have to suspend reload.

flyboarder18:09:40

Many JS things I have noticed don't work right when reloaded because they rely on Dom ready and other events which are not triggered

mac20:09:25

@flyboarder Indeed. If I have a cell that needs to be defined inside a with-init! how do I then define the output, eg (p cell-defined-in-with-init!). Right now it is just empty and remains so because it only exists after with-init! has run.

flyboarder20:09:17

You should make the cell global in the ns and set the value in with-init

mac20:09:40

@flyboarder How do that with a prop-cell?

flyboarder20:09:37

Via a lense cell, there is a section on them in the javelin read me

mac21:09:55

@flyboarder If I have a js property access expression like (. foo.bar -baz)in my with-init! how would I then go about using a Lense cell?

flyboarder21:09:18

By having it write to the global one

flyboarder21:09:56

Wait that may not actually work, what you may actually want is just an anonymous cell that updates the global one

flyboarder21:09:10

Can you post your with-unit

mac21:09:44

@flyboarder sure

(with-init!
  (enable-console-print!)
  (let [c  (array (.config js/pm.exampleSetup (js-obj "menuBar" js/true)))
        place (.querySelector js/document "#editor")
        content (.querySelector js/document "#content")]
  (defonce pmed (js/pm.ProseMirror.
                   (js-obj "place" place
                           "doc" (.parseDOM js/pm.schema content)
                           "plugins" c))))
  (set! (. js/window -pmed) pmed)
  
  (print (. pmed.selection -from))
  (def sel-from (prop-cell (. pmed.selection -from)))
  )

mac21:09:20

@flyboarder incl messy debug stuff

flyboarder21:09:41

Yeah I think just a formula cell could then update a global cell

mac21:09:05

@flyboarder Something like this (defc= updater @sel-from (set-cell! global-cell @sel-from))

mac21:09:11

@flyboarder I don't think I understand how to make with-init cell set the value of the global cell

flyboarder21:09:55

(let [reset (partial reset! global-cell)] (cell= (when prop (reset prop))) something like that

mac21:09:45

@flyboarder prop being sel-from from with-init or the property expression

mac21:09:20

@flyboarder I clearly need to read the javelin docs again tomorrow

mac22:09:36

@flyboarder 🙂 turns out (set-cell!= global-cell sel-from) in with-init! does the trick

mac22:09:03

@flyboarder Thanks for all your help, really appreciate it.

flyboarder22:09:42

@mac No prob sorry I'm running around right now, slow reply

onetom23:09:19

@flyboarder defonce does work with boot-reload as expected. see my example repo and the source code of defonce:

(core/defmacro defonce
  "defs name to have the root value of init iff the named var has no root value,
  else init is unevaluated"
  [x init]
  `(when-not (exists? ~x)
     (def ~x ~init)))
@mac don't put that defonce into with-init!. and in general putting def anything within some other scope than the root scope of the namespace is very rarely necessary. it means the symbol u want to define won't exist until the page is loaded, so you can only refer to it from code which only runs after the page is loaded...

flyboarder23:09:14

@onetom: thanks good to know

mac23:09:36

@flyboarder I know, but it appears to be necessary for ProseMirror to work.

onetom23:09:46

@mac if you look at the definition of with-init! which then calls thru add-initfn!, then you can see it's just a thin wrapper around jQuery.ready():

defn add-initfn!  [f] (js/jQuery #(with-timeout 0 (f)))
imagine when your code containing with-init! reloads, the reloaded code immediately runs again. that will run with-init! too, which becomes a simple synchronous operations, because the dom is already ready. (though as the source above shows, hoplon makes it async anyway with that with-timeout)

mac23:09:51

@onetom Got it. I have disabled reload for now. Much simpler.

onetom23:09:40

it's a very complicated booting model if you step out of the module system provided by the google closure library, so you are better of properly packaging your external lib for it

jamieorc23:09:16

@onetom thanks for the ui info