Fork me on GitHub
#hoplon
<
2016-11-10
>
flyboarder00:11:07

Hey guys, I took a stab at the mk! multimethod, not sure how we feel about it, any thoughts?

flyboarder00:11:20

The idea is that the mk! multimethod returns a function that is used as an element constructor

jjttjj04:11:31

@flyboarder don't really wanna keep clogging the github up with my idiocy, but wait so it's not actually correct to pass to an element two consecutive sibling children unless they are in a vector or list? so

(div (p "a") (p "b"))
is wrong and should be
(div [(p "a") (p "b")])

flyboarder05:11:45

@jjttjj: it's not so much that it's wrong, more that it's different internal behavior

flyboarder07:11:52

From your example tho usually you would use the vector form when you are building up a collection of children to display, your PR should solve this tho

onetom10:11:52

@jumblerg there is a form *data* binding problem if combined with if-tpl:

(form
  (text :key ...)
  (if-tpl can-submit-yet?
    (submit "GO" :submit js/console.debug)
    (spinner)))
if can-submit-yet? is false at creation time of the form elem then the creation of the submit elem would happen later when *data* is not bound to the form's data cell anymore.

onetom10:11:23

do you have a recommended idiom to get around this? in hoplon i could just do

(submit :toggle can-submit-yet? ...)
(spinner :toggle (cell= (not can-submit-yet?)))

onetom10:11:31

but there is no equivalent of :toggle in hopon ui, or is there? (i only found (bind-in! img [.-style .-display] :block) in hoplon/ui.cljs)

onetom10:11:01

i got around it with:

(form
  (text :key ...)
  (let [submit-btn (submit "GO" :submit js/console.debug)]
    (if-tpl can-submit-yet?
      submit-btn
      (spinner))))
but it's not helping understanding...

jumblerg12:11:19

@onetom: :v is for visibility.

onetom13:11:26

Yeah I just remembered that on the way home

onetom13:11:00

Hmm but the visibility hidden doesn't take the element out of the layout so I can't use it instead of if-tpl, can I?

tbrooke13:11:09

Hats off to @micha for a great Hoplon walk through at TriCojure - nice presentation

jumblerg13:11:50

@onetom: in practice, from a ux perspective, i have found it more effective to disable buttons while preserving their position on the page until the required form fields are populated, so i haven't run into this particular issue myself. i don't like to shift the layout around by injecting elements like buttons into the view after some amount of validation has been completed.

jumblerg13:11:33

certainly there might be cases where this scenario makes sense, however. dynamic binding often comes up short as a mechanism for propagating references from parents to children, even with micha's bound-fn implementation.

onetom13:11:39

And how do you disable a button? You would need an alternate set of styles, right?

jumblerg13:11:33

something like (elem :sh 300 :sv 60 :c (cell= (if is-complete :blue :grey)) :m :pointer :click #(when is-complete (dothedeed %)))

jumblerg13:11:58

i've also changed up the form stuff a bit since the version you're using: https://github.com/hoplon/ui/blob/master/src/hoplon/ui.cljs#L632-L640

jumblerg13:11:18

i've been experimenting with bubbling cells (on events) as a mechanism for setting up an inherited binding (inherited from parents as in css inheritance) scheme as an alterative to using dynamic vars for this. i'm not certain this is a good approach though; i really need to enumerate the various cases where there the dynamic variable model has caused issues to specify what a better abstraction for this might look like.

onetom13:11:33

Yup, I've just started reading the latest formable source before I left the office. We would need to merge with our branch and see if anything breaks

jumblerg14:11:04

@micha: incidentally, i was thinking about ns+; i wonder if it would make sense to do away with this in favor of a simple ns in a .cljs.hl file.

jumblerg14:11:31

the ns would have the same semantics, and be more tooling-friendly perhaps because it is consistent. additionally, it would maintain the contract that .cljs files start with ns.

jumblerg14:11:57

(i had this insight while thinking about deps.cljs...

micha14:11:10

i don't think it would be more tooling friendly

micha14:11:14

just like deps.cljs

micha14:11:20

it would be less tooling friendly

micha14:11:27

because it wouldn't be the real ns

micha14:11:56

tools should be able to assume that the ns form is the real one and not something else that is appropriating the name

micha14:11:12

this is the same issue as we see with .cljs files that aren't cljs namespaces

micha14:11:17

it interferes with tooling

jumblerg14:11:17

i, personally, care less about this particular aspect. but this would be an .hl ns, not a .cljs ns.

jumblerg14:11:39

hl files belong to the hoplon compiler / task.

jumblerg14:11:05

which would then create a legal cljs file with a real ns for the clojurescript task.

micha14:11:17

yeah the hoplon task alraedy adds things to the ns decl in a .cljs.hl file

jumblerg14:11:21

instead of an illegal cljs file with ns+ at the top upstream of the hoplon task.

jumblerg14:11:37

yeah, but before hoplon, we have an illegal cljs file

jumblerg14:11:31

that's why i think it should be a .hl file instead. and since it would be a .hl file, then it could use a hoplon ns.

jumblerg14:11:26

the current ns+ implementation in hoplon tinkers with a file type/contract it does not own.

jumblerg14:11:42

and typically our file extensions specify which compiler they belong to, eg .java -> javac, .cljs -> clojurescript, in this case .hl -> hoplon. i think it is analogous to invading someone else's namespace.

jumblerg14:11:54

if we do want to extend .cljs files more generally, with something like ns+ , we should do it in the cljs task i'd imagine (at least within the boot world, these files would still be illegal in the larger cljs ecosystem).

jumblerg14:11:49

i think the same principle applies to tooling; editors should be able expect an actual ns at the top of any .cljs files. i only meant to convey there might be an incidental benefit of convenience when users associated .hl files with clojurescript in their editors, since the only syntactic delta would be the addition of the :page form to the macro. an ide might not recognize ns+.

micha14:11:51

yeah it's ns+ because i'm not sure it's a good idea

micha14:11:03

it's experimental

jumblerg14:11:56

i think it is a great idea as an nsfor hoplon files. 🙂

jumblerg14:11:23

it works great now. whether or not you want to propagate it to the clojurescript task, and effectively introduce boot extensions to clojurescript, is another question.

micha14:11:58

haha i don't think juho would want that

jumblerg14:11:39

lol. yeah... i heard, somewhere, that :require-macros is no longer needed by cljs; i've not verified this, but that might negate any benefit of doing this anyway if true.

micha14:11:00

maybe i can turn it into a patch for cljs compiler though if it works well

micha14:11:16

that's sort of true

micha14:11:45

it still doesn't support refer our use though

onetom14:11:48

I've actually seen weird symbol resolution situations in cursive

jumblerg15:11:08

yeah. you should submit a patch for bound-fn too, if they can introduce your binding it in a backwards compatible way.

onetom15:11:18

Sometimes defelem is marked unresolvable

onetom15:11:59

I suspect it happens since we switched to cljs 1.9

jumblerg15:11:04

remind me what the :refer semantic was?

micha15:11:16

(:require [foo :refer :all])

jumblerg15:11:17

ah, yeah. i never use the :all because i don't like dumping a bag-o-symbols into my ns implicitly.

jumblerg15:11:46

i want to be able to look at my page and know where the things came from.

jumblerg15:11:30

if it isn't in the ns macro, it had better be clojure.core.

onetom15:11:49

Except it would be very useful for DSLs like Hoplon or cljs.test

jumblerg15:11:26

convenient. easy at first maybe. less simple. we tried that with hoplon in pages implicit :refer :all. 😕 i find in practice i either refer in a small handful of symbols (even in test), or simply namespace them with :as.

jumblerg15:11:43

there's a scenario out there, i'm sure, where i might be pragmatic enough to use :refer :all - but i've yet to encounter it.

jumblerg15:11:06

anyway, my only point is that :refer :all is an edge case so i personally don't care much about it, and i wonder if it does more harm than good. maybe the fact is is missing from cljs is a feature and not a bug because it encourages better practices.

onetom15:11:24

That's the pattern we are following but the inconvenience is that you have to remember what are the frequently used, hence referred, symbols and which ones need namespacing. On top of that you need to maintain a team wide consensus on the ns aliases too...

onetom15:11:21

But you can see the results in our fe repo. It's a workable compromise at the end...

onetom15:11:43

But still a compromise nevertheless...

onetom15:11:10

I see custom ns macros as a harm, because they break cursive, which is the best tooling really these days (for those who have super strong machines with a lot of ram.)

micha15:11:27

yeah i use :refer when it makes sense

jumblerg15:11:51

i tolerate it with bootlaces. 🙂

micha15:11:58

i feel like my code is readable enough, people will figure it out just fine

micha15:11:11

there is a bit of cargo cultimg with "best practices"

micha15:11:26

like yeah don't :refer :all everything

micha15:11:39

but h/div is not sometihng that helps me

micha15:11:59

nor is :refer [div span p input select .....

micha15:11:07

that's worse

micha15:11:47

the idea that some rando off the street should be able to jump into your codebase and start typing immediately is silly

micha15:11:01

it's a good thing that they can't lol

micha15:11:11

don't start typing till you know what's going on

micha15:11:23

and figuring out which namespace refers div is the least of it

jumblerg15:11:27

yeah, and being explicit helps with that.

micha15:11:52

i think it can obscure the important stuff with boilerplate

micha15:11:10

like seeing h/div all over the place is a distraction imo

jumblerg15:11:14

i could see a scenario where i'd use with with the core hoplon/ui ns, in the same way though.

jumblerg15:11:28

yeah, that's what i use :refer for.

micha15:11:44

yeah but needing to type 100 things into :refer is dumb

micha15:11:52

that's where :refer :all comes in

jumblerg15:11:57

without the :fing-everything.

micha15:11:28

i dunno, it seems to work well for me

jumblerg15:11:56

yeah, but when you refer in 100 things, then you get surprises because you just introduced 100 more keywords that will collide with other things, imho.

jumblerg15:11:35

so you create a header function, then you get errors. because you :refer :all'd all the html things.

micha15:11:56

i dunno, that's never been a problem for me

jumblerg15:11:07

that bites me all the time

micha15:11:11

you see a warning that you're overriding something and which namespace the thing was originally defined in

micha15:11:21

pretty simple

jumblerg15:11:56

maybe the warnings were broken for a while, but i wasn't getting them.

micha15:11:00

why not clojure.core/map and clojure.core/def then?

micha15:11:08

core has a ton of things refered

jumblerg15:11:43

because i assume that if it isn't explicitly defined, that it is a core language fn.

jumblerg15:11:58

but, to be clear, i do think there are scenarios where it makes sense.

jumblerg15:11:07

they are just rare for me.

jumblerg15:11:02

who knows, i might start using it in .hl files with ui core at some point. but interestingly, is there an :exclude :all?

micha15:11:46

interesting, there should be

jumblerg15:11:50

say i wanted to eliminate all the clojure core fns by default in a view (notwithstanding the necessary ns macro). could be useful, maybe, if i were building views where pretty much everything was a ui elem.

jumblerg15:11:13

then i could :refer :all hoplon/ui core and :exclude :all clojure.core.

dm315:11:16

(:refer-clojure :only [def defn])

dm315:11:33

personally, I like ns+, but then I don't use Cursive...

jumblerg15:11:34

i was wondering if :refer-clojure supported :exclude :all, but i guess the :only construct would work too for the same purpose if that works the way it seems it would.

jumblerg15:11:14

i really like the semantics of ns+, and i don't use cursive either. i was suggesting that it should be owned by the hoplon compiler and therefore be ns for hoplon .hl files, not .cljs files.

jumblerg15:11:52

hl files -> hoplon compiler, cljs files -> clojurescript compiler. one compiler/task should not be modifying another compilation task's files.

jumblerg15:11:22

the files should be legal regardless of the time and their position in the build pipeline.

micha15:11:45

yeah if we decide that ns+ is legit we can make that the default ns form for .hl files

jumblerg15:11:05

it is working great for me now

micha15:11:07

it should be backward compatible anyway

jjttjj15:11:26

@flyboarder the thing that got me looking at nil child values was this line of hoplon/ui: https://github.com/hoplon/ui/blob/master/src/hoplon/ui.cljs#L609 if you don't give the page a title, none of that form is nil and none of the stuff after it happens.

jumblerg15:11:32

yeah, .hl can support page or ns.

micha15:11:46

yeah the fix for the nils is a little more complicated

jjttjj15:11:59

i guess a page would pretty much always have a title, but it bit me during quick test apps

micha15:11:17

i think what we want to do is make a (remove nil? args) in the let binding before the cond

micha15:11:48

and in the places where we do flatten on seq or vector args we need to put a (remove nil? (flatten x)) too

jjttjj15:11:58

oh yeah, that makes sense

micha15:11:18

need to think about it though see what the performance implications are

micha15:11:27

making seqs in clojure is expensive

micha15:11:45

so you want to avoid doing things like remove in critical sections of code

micha15:11:03

we may want to say "don't use nil children"

micha15:11:12

and just not support that

jjttjj15:11:27

yeah that's fair enough too

micha15:11:43

that piece of program is in a critical spot

micha15:11:47

it gets called a lot

flyboarder15:11:51

@micha i had to duplicate this part twice in the patch i implemented for mk! that might be a sign there is another problem here

flyboarder15:11:26

it's hard to factor around the parse-args function

micha15:11:36

i'm not sure we want to make the low level hoplon stuff more abstract

micha15:11:52

i think that might be something for a higher layer to do

jumblerg15:11:14

yeah, i observed significant slowdowns in ui when i introduced a seq into the elem constructor.

micha15:11:23

i'm not even really sold on the INode protocol

jumblerg15:11:40

yeah, we should sync on that

micha15:11:53

like the hoplon layer maybe should just deal with dom elements

micha15:11:23

like really i think hoplon should just be the linkage between javelin cells and dom elements

micha15:11:37

and that also does imply the *-tpl forms

micha15:11:46

because of the way cells and dom elements interact

micha16:11:13

but the attribute providers and so on are really just to help you get started with some reasonably sane defaults

micha16:11:38

like you should be able to make a simple app with just hoplon if you want

jumblerg16:11:43

i actually think the attribute providers should be another library/layer entirely.

micha16:11:45

which means some kind of attribute stuff

micha16:11:10

well i think it's important that a user can get a basic thing working without other libraries

micha16:11:22

as long as they're optional

micha16:11:25

which they are now

jumblerg16:11:26

yeah, the user would pull that lib though, and get hoplon/core transitively.

flyboarder16:11:40

I think there needs to be better separation from the custom elements and primitive elements

micha16:11:49

it doesn't make sense to make that basic stuff separate

jumblerg16:11:55

basically, you could reduce hoplon/ui to an attribute scheme.

micha16:11:58

because then we have all the familiar integration issues

flyboarder16:11:14

not sure what you mean by that

micha16:11:20

like what we have now is pretty simple and sufficient i think

micha16:11:31

well like if the attribute providers were a separate dependency

micha16:11:41

then we'd have the compatibility matrix again

micha16:11:50

and it would serve no purpose

micha16:11:03

you don't gain anything by making a separate dependency

micha16:11:15

you can just use the namespace or not

flyboarder16:11:16

oh yeah not that they should be a separate library but from core

flyboarder16:11:30

the same way we do attributes

micha16:11:39

right i was referring to the attributes there

micha16:11:48

i think we're doing that the right way now

jumblerg16:11:50

you could include hoplon/ui or include hoplon/html, or whatever... and hoplon/hoplon comes as a part of those as a dependency.

micha16:11:00

yeah but what is the gain

micha16:11:12

then you have hoplon dep conflicts

micha16:11:21

so you'd need to specify which hoplon you want

micha16:11:34

it would be the same as boot-hoplon

jumblerg16:11:40

orthogonality in the libraries

micha16:11:53

they're not orthogonal

micha16:11:06

the hoplon.jquery code is tightly coupled to hoplon core

micha16:11:34

one version of hoplon.jquery isn't guaranteed to work with a different version of hoplon.core

micha16:11:51

that would just cause confusion

micha16:11:55

and for zero benefit

jumblerg16:11:02

i'm less opinionated about this issue though, nor am i convinced my suggestion is the right way to do it.

micha16:11:33

hoplon.jquery is just one implementation of custom attributes that is sufficient to get started and make some apps

micha16:11:51

it would be added overhead to make that a separately versioned library

micha16:11:04

since it is tightly coupled to hoplon core internals

micha16:11:17

if you want to do a different thing you can just not use it

micha16:11:34

but hoplon would be useless for making apps without some implementation

micha16:11:50

so it mkes sense to include at least something

micha16:11:11

@flyboarder one thing though, i think we should namespace the goog attributes

micha16:11:15

like :goog/click

micha16:11:19

or something like that

flyboarder16:11:52

otherwise its not backwards compatible

jumblerg16:11:57

could a menu of different attribute options be unnecessary though, maybe in the same sense that INode could introduce options that are undesirable?

jumblerg16:11:21

why would we want the confusion of supporting jquery attributes and goog attributes?

jumblerg16:11:35

are half our examples in documentation going to use jquery, the others goog?

jumblerg16:11:07

what comes next?

micha16:11:13

@flyboarder compatibility is the reason

jumblerg16:11:28

i get the idea of supporting one thing, i dunno about a menu of attribute providers.

micha16:11:52

libraries that are written against the jquery :click for example, won't work if jquery .goog is loaded

flyboarder16:11:53

@jumblerg we can implement both without causing issues, they are all already namespaced

jumblerg16:11:00

we should have one standard :click, imho.

micha16:11:07

that is impossible

jumblerg16:11:08

all the more reason not to support goog, imho.

flyboarder16:11:16

the standard click is browser behaviour

flyboarder16:11:28

the attribute providers extend that however they want

micha16:11:33

well you can't make aplications on the bare metal of the browser

micha16:11:42

you always need a compatibility layer

micha16:11:02

if you want to write your own compatibility layer you'd make your own attribute provider

micha16:11:20

but nobody wants to do (.registerEvent ...

micha16:11:29

you want to do (div :click ...

micha16:11:38

so that means you're no longer on the bare metal

micha16:11:57

i guess you could do (div :onclick "foo"

micha16:11:07

where you have some global function in js named foo

micha16:11:14

but nobody will ever want to do that

micha16:11:50

so i think it's fine to use goog instead of jquery, or even make your own thing

micha16:11:57

but we should namespace the kws

micha16:11:03

because they're not going to be compatible

micha16:11:25

that way we can still have libraries that use other attr providers or whatever

jumblerg16:11:31

agreed we should allow other people to hook in with goog, or whatever they want to make. i simply don't think we should have goog attribute providers in hoplon/hoplon.

jumblerg16:11:53

in forks hoplon, in effect.

micha16:11:16

i don't think it does

micha16:11:22

if we handle it properly

jumblerg16:11:35

we'll have some people building apps with jquery, others with goog, and to what benefit?

micha16:11:56

the benefit is that each has its own strengths and weaknesses

jumblerg16:11:13

i don't know that we want to encourage that.

micha16:11:09

yeah maybe we should use the IAttribute stuff

micha16:11:30

then you could refer in attrs from hoplon.jquery and/or from goog, whatever

micha16:11:57

(div goog/click #(...) jquery/css {...} ...)

micha16:11:11

and you could :refer things

micha16:11:26

so that would be just (div click #(...) css {...} ...)

jumblerg16:11:32

hoplon ui can hook in this way as well

micha16:11:15

yeah i have an idea about the IAttribute thing too

jumblerg16:11:28

i think that, as we use hoplon over time, we try lots of things, but eventually uncover best practices and idioms; these abstractions tend to get encoded into hoplon incrementally where others can use and benefit from them. we eventually settle on these best practices, and i think we should only offer the abstractions that we use ourselves, that work best for us, as part of core hoplon so we can avoid forking the community (while still giving others the opportunities/hooks to innovate themselves and perhaps find new approaches we can include).

jumblerg16:11:14

it is better to work through different approaches here as a group, and settle on a single supported approach based on our collective experience and knowledge, rather than giving people a menu of options.

jumblerg16:11:48

take goog attributes, for example. i haven't tried them. if some of us are using them, and there's a substantial benefit to them, then we should work through that here, and maybe we encourage the use of those moving forward while attaching deprecation notices to jQuery attributes for backwards compatibility.

jumblerg16:11:06

let's agree on a single approach as a group where we're well equipped to sort through these options rather than devolving the choices to individuals, esp newcomers.

micha16:11:12

that's a good point, yes

flyboarder16:11:13

@micha one issue tho is that the compatibility layer is limited to being able to convert regular elements to a compatibility type, this breaks down when elements can only be constructed

flyboarder16:11:42

for example with jquery I can always convert an element to a jquery element, but there are cases when I cannot do this, I instead must construct the element directly

micha16:11:02

how do you mean?

micha16:11:21

you can always use js/jquery function to get a jquery object

flyboarder16:11:00

like I can go (js/jQuery #some-elem) and that gives me a jquery object, but with many js libraries I must use the libraries constructor for the element

flyboarder16:11:25

like for an IDE which modifies the DOM

flyboarder16:11:46

most ide libs need to be constructed

flyboarder16:11:08

and cannot convert an existing node with each desired method call

micha16:11:24

but they must return dom elements at some point

micha16:11:31

that's where hoplon comes in

micha16:11:46

hoplon doesn't need to be involved in the ide stuff

flyboarder16:11:47

right when you first construct the element, but currently thats handled by hoplon

micha16:11:02

but you said the ide library was constructing the elements

flyboarder16:11:13

right like for a web ide

flyboarder16:11:19

residing in DOM

micha16:11:38

right but what is preventing the ide from constructing the things it needs?

micha16:11:55

like where is hoplon interfering

flyboarder17:11:57

when elements need to be constructed with their own constructor

micha17:11:17

what prevents you from using their own constructor though?

flyboarder17:11:24

nothing specifically but then I cannot construct them the same way as I do regular hl components

flyboarder17:11:15

I can't mix an external libs constructor and hoplon attributes

micha18:11:01

the usual way to accomplis that is with defelem

micha18:11:12

that's how we do jquery plugins for example

flyboarder18:11:24

but what about when the parent is required to already exist?

flyboarder18:11:52

I think the main issue is that the jquery pattern dosent always work with other libs

micha18:11:12

a concrete example would help

flyboarder18:11:43

like when using ace editor

micha18:11:16

you can still do that with defelem

micha18:11:11

(defelem ace-editor [{:keys [text]} kids]
  (let [id (str (gensym))]
    (with-let [d (div :id id :text text)]
      (with-timeout 0
        (doto (.edit js/ace id) (.setTheme "ace/theme/monokai"))))))

micha18:11:14

something like that

micha18:11:09

i've done that for some code editor before, maybe it was ace?

micha18:11:40

you can see a pretty crazy example with the google maps element

micha18:11:59

it implements the whole api almost in a really nice hoplon attribute style

micha18:11:14

and the google maps thing itself is totally oop and disgusting to work with

micha18:11:27

with all kinds of nonsense like things needing to exist with ids and so on