This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-03-23
Channels
- # admin-announcements (6)
- # aleph (3)
- # beginners (38)
- # boot (119)
- # braid-chat (15)
- # braveandtrue (1)
- # clara (4)
- # cljs-dev (56)
- # cljsfiddle (12)
- # cljsjs (15)
- # cljsrn (6)
- # clojars (4)
- # clojure (113)
- # clojure-art (1)
- # clojure-berlin (1)
- # clojure-dusseldorf (3)
- # clojure-india (15)
- # clojure-new-zealand (3)
- # clojure-poland (1)
- # clojure-russia (83)
- # clojure-uk (18)
- # clojurescript (97)
- # community-development (9)
- # cursive (1)
- # data-science (1)
- # datomic (12)
- # emacs (14)
- # hoplon (350)
- # immutant (2)
- # jobs (2)
- # jobs-discuss (23)
- # keechma (74)
- # liberator (1)
- # off-topic (1)
- # om (127)
- # onyx (54)
- # parinfer (74)
- # pedestal (1)
- # proton (5)
- # re-frame (6)
- # reagent (4)
- # remote-jobs (17)
- # ring-swagger (1)
- # slack-help (5)
- # untangled (16)
- # yada (21)
@micha "the cond-tpl macro that's going to be merged seems like it would be ideal for that use case”
Whoa, someone’s working on cond-tpl? I was just about to work on it, but will give way if someone else is on it.
Sooo, something that I faced, was a third party script that was heavy
so I only wanted to load it into the page after an event had triggered
so I did event-triggered?
in a cell
then (cell= (if event-triggered? (script …)))
which seemed to work, but my problem is the performance issues i see haven’t lined up with my understanding of “building a complex tree"
as in, I’d build the DOM, the DOM looked like it had finished building (which I would have expected to be all the computation required) but then all my events and functions from that point onwards run waaaay slower
so it would be a permanent slowdown of the whole site
it’s also sporadic and hard to reproduce
I think it may have gotten better when i moved from Hoplon alpha10 to alpha13, but I also might be imagining that >.<
I’ll just keep everyone posted as I have info/examples...
I somehow doubt that the same functions will take slower after the DOM loaded than before
that’s what was happening
like, so obvious...
like the app nearly crashed
i had one tab open running master
and one running my branch
master had more data in it and was silky fast
the other branch had very little data and was sluggish
the only thing i changed was creating a (cell= (if foo bar baz))
at first i thought it was my routing implementation
but i set it back to default hoplon route-cell
i have an event triggering on :input
on form inputs
if i mashed the keys, i’d see multiple second delays
buuuut i threw it all away and went with :toggle
so i’ll just keep an eye on things, and if i see it again, i’ll flag it
side question
for attributes on elements
are on!
and do!
the only options?
i’m trying to improve the docs
so i want to know i’ve covered the right stuff
@dm3: when i started swapping elements in the DOM based on an if
in a cell=
, i got weird performance
that’s the best way i can describe it
sorry!
i did a tiny bit of profiling and jquery adding events was really high in time
@dm3: so yes, on!
and do!
are the only options for attributes?
i worked on this yesterday https://github.com/hoplon/hoplon/wiki/API-Documentation
but i got some of the details about attributes wrong
so i want to update that
OK cool
and any function values will go to on!
and all other values go to do!
yeah?
or just create an attribute
i think the bit that i was missing was that do!
also handles adding HTML attributes
i’m going to actually put the things implemented by do!
that are not the default attribute creation in the wiki
because, as cool as hoplon is, it’s not fun poking around in core to find this stuff
custom events probably
something jquery supports
but it’s probably not useful for simple apps or hoplon core
as in, you might want a custom event that does something to all elements
without you needing to stick your own handler on everything
i don’t see any harm in it, and there would be some edge cases where it could help
even if just for debugging
(defmethod on! :my-event [elem event callback]
;; register your callback in some specific way?)
(defmethod on! :my-event [elem event callback]
(prn elem))
the event handler version of (cell= (prn my-cell))
?
if I do your code above, for a :click
event
does it run when the thing is clicked, or when the click event is bound to the element?
but you can still do
(defmethod on! :my-event [e ev cb]
(.on (js/jQuery e) ev (fn [e] (prn e) (cb e))))
are you sure?
that doesn’t seem that useful
neither do i
but i didn’t write it
i won’t pretend to know anything about it 😛
well, Hoplon is designed from the point of providing small and general abstractions for creating a DSL for writing your application
on!
is useful if you don’t want to use the default jquery stuff.
it also helps you define some custom stuff. For example, for my own app, i define :drag
clojure
(defmethod on! :drag
[elem event callback]
(let [mousedown? (atom false)
down-ev (atom nil)]
(when-dom elem
(fn []
(.mousedown (js/jQuery elem)
(fn [ev]
(reset! mousedown? true)))
(.mouseup (js/jQuery elem)
(fn [ev]
(reset! mousedown? false)))
#_(.mouseout (js/jQuery elem)
(fn [ev]
(reset! mousedown? false)
(reset! down-ev nil)))
(.mousemove (js/jQuery elem)
(fn [ev]
(if @mousedown?
(callback ev))))))))
oh yeah, i need to do drag and drop re-ordering of form inputs at some point
i’ll need a hand with that >.<
well there you have it 😄
i will definitely forget that
I’ll make a post in the cookbook for you
https://github.com/hoplon/hoplon/wiki/Cookbook#dragging-and-other-custom-behaviorsevents
here you go, @thedavidmeister 😄
hang on
just writing up ^^
Any **attributes** that have function values will be handled by the `on!` multimethod. Hoplon core only implements the default case for the multimethod, which will simply bind the passed function to the jQuery event with the same name as the attribute key.
When the event triggers the bound event, the first argument will be the jQuery event. Hoplon implements `IDeref` for the jQuery event to call jQuery's own `.val` on the event's original target element.
As an example, we can use `on!` to respond to the user clicking (triggering the `:click` event) on an `input` by alerting the current text value of the input:
`(input :type "text" :click #(js/alert @%))`
Even though `on!` is provided only with a default case, the multimethod exists so that custom function binding outside of what jQuery provides can be handled in a standard way.
does that look right?
As far as i know, input is a special case for the IDeref. Can anyone confirm this?
Or is it that it’s always IDeref, and only a few elements like input actually have anything useful to put in there?
In which case, your writeup looks good, @thedavidmeister!
(extend-type js/jQuery.Event
cljs.core/IDeref
(-deref [this] (-> this .-target js/jQuery .val)))
Oh! nice
could someone walk me through this one?
(defmethod do! :class
[elem _ kvs]
(let [elem (js/jQuery elem)
->map #(zipmap % (repeat true))
clmap (if (map? kvs)
kvs
(->map (if (string? kvs) (.split kvs #"\s+") (seq kvs))))]
(doseq [[c p?] clmap] (.toggleClass elem (name c) (boolean p?)))))
does it just take a map of classes and converts to a string?
or is it more than that?
well, not converts to a string
ensures that those classes are on the element
and if a string is passed, also handles that?
so you need to do
:class {:my-class true :another-class true}
?
so I can do :class “my-class another-class”
and have both of those appear
or i can do
:class {:my-class true :another-class true :not-this-class false}
to make sure that third class is removed if present?
but, if you have (input :class (cell= "a b")
and then cell value changes to (input :class (cell= "a"))
, the "b" class won't disappear
unless i specifically set it to false
does this work?
:class {:add-me :and-me}
have we considered a generic :trigger
for do!
?
(div :trigger :click)
trigger a click event on div
(div :trigger :select)
= (div :select true)
which allows (div :trigger :select :select #(js/alert “selected!”))
otherwise how do you facilitate triggering and handling events on one element?
no, with a (cell= )
controlling the timing/conditions, of course
i worked around this like
:select (cell= (and (= list-id select-list-id) (= id select-id)))
:focusin #(in/clear-select! in/conn)
you can probably guess what those functions do
but not everything has a counterpart with a different name
like :click
:trigger {:select (cell= (and (= list-id select-list-id) (= id select-id)))} :select #(in/clear-select! in/conn)
it’s ugly, but I don’t know a better way to trigger and also bind to an event?
OK, but what about :click
?
I guess you have different types of attributes:
1. properties, like selected
or class
where you might want a dynamic value
2. actions, like click
, which you want to trigger at certain times using do!
3. event handlers, like click
(really on-click
), which you want to attach to an element during constructions
well yes
it’s just weird because you can have name conflicts
where do I put that?
i don’t think i’ve used with-let yet
@dm3: would you mind reading over the attributes section here? https://github.com/hoplon/hoplon/wiki/API-Documentation
is it possible to redefine the behavior of (a :href ....) with a do method to automatically perform some action like say, posting an event to GA before performing the default behavior?
@raywillig: I do believe that is the case.
(defmethod do! :href
[elem event callback]
(.preventDefault event)
;; post to GA
;; execute default behavior)
haha i was already typing the above after my first message 😛
very interesting. now suppose i wanted :target "_blank" even if the stupid coder (me) left that out of the function
(defmethod do! :href
[elem key val]
(.preventDefault event)
;; post to GA
(.open js/window val))
hang on
my first code block is a confused one 😛 it’s conflating on!
and do!
and it’s leaking into my second one
there should be no “event” necessary
so really, all you’d need to do is:
(defmethod do! :href
[elem key val]
;; post to GA
(.open js/window val))
it just has to be called before you render it
so i guess you can just put it in a util
and then require it in your index
but i’d advise you to put it in your index first just to see
i could be forgetting some stuff
is it possible for the do method to access other attributes defined on the same element?
afaik, no. what usage do you have in mind?
maybe there’s another way
actually
i think i may have thought of another way. since i'm overriding the behavior of href, I could pass a more complex structure with whatever addition data i need right?
maybe you’d be able to use the usual js attr accessing
because you have elem
and yes, you could expect that href takes a hashmap
(defmethod do! :href
[elem key val]
;; post to GA
(do-something {:extra val})
(.open js/window {:url val}))
you might have to deref val
i just realized tho that this may clobber other things that use href like css stuff
i think you should be able to do:
(defmethod do! :href
[elem key val]
;; post to GA
(let [attrval (.attr (js/jQuery elem) “extra”)]
(do-something-to attrval))
(.open js/window val))
this tries to get the value of :extra if it’s defined
will this code open the window as soon as the thing is rendered or wait until the link is clicked?
as for determining the tag, you can do this:
(.prop (js/jQuery elem) “tagName”)
and test that against “a"
rather, against “A"
it’ll wait until it is clicked
actually
i’m not sure 😛
actually
something you can do is defined its :click
and inside the :click, (.preventDefault ev)
and then do your GA and new window stuff
and leave href alone
you can extend click 😛
(defmethod on! :click [elem event callback]
…
(let [tagname (.prop (js/jQuery elem) "tagName”)]
(when (= tagname “A”)
(.preventDefault event)
(.open js/window (.attr (js/jQuery elem) “href”))))
^ edited
and then copy paste the rest of the original :click into a when-not
hmm this seems viable, so even if there's no :click attribute there's an implicit click handler. for most things i guess it does nothing but a's are different obv
You have such an interesting problem. Hahaha
I want to explore extending :href for some reason
I think extending :click is crazy
Or...
What if
You just went the old fashioned way?
Whatever it would have done if it wasn't an A
Anyway, a sure fire way would be if you did:
(.click (js/jQuery "a") (fn [] ...))
In other words, you can skip the fancy extension stuff
And simply target all the a's, add a click handler, and add your preventDefault stuff
Another thing you can do is create a custom "a" element that already has the :click predefined
This is even cleaner
So it wraps around the default "a"
I do some stuff that adds stuff to the dom on the fly. those wouldn't get handled by the jquery thing if they're added to the dom after the call right?
Yeah, those wouldn't.
I think your best bet is to create a custom anchor element.
(defelem a-ga [{:keys [href] :as attrs} kids]
...)
thanks @levitanong !
Hurrah! Happy to help, @raywillig :D
does javelin have a way to force propagation for when values dont change?
@flyboarder: you can try doing something like https://github.com/hoplon/javelin/blob/master/src/javelin/core.cljs#L43
thanks! @dm3
I noticed hlisp re-renders the UI only when there is a cell bound to an html attributes or content
So I need to write (div :style (cell= (if menu-visible "" "display:none")))
instead of (div :style (if @menu-visible "" "display:none"))
i would create the DOM the content for all menu selections, and just don't show the ones that aren't active
but, isn't this a little bit heavy? I mean loading everything at the beginning and then just showing and hiding stuff. I already am loading at the beginning some dialogs which I show only later (or may not show at all). didn't you have issues with this?
the reason why you want to statically allocate dom elements like this is because then you are freed from the manual memory management you'd need otherwise
like if you're creating and destroying whole subtrees you will need to have a lot of code to manage that
i was very interested in exploring the standalone animation libraries, like velocity.js for example