This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-08-27
Channels
- # admin-announcements (5)
- # cider (4)
- # cljs-dev (20)
- # cljsjs (2)
- # cljsrn (6)
- # clojure (126)
- # clojure-austin (2)
- # clojure-berlin (1)
- # clojure-brasil (5)
- # clojure-japan (1)
- # clojure-russia (14)
- # clojure-spec (2)
- # clojure-uk (3)
- # clojurescript (11)
- # cursive (19)
- # datomic (5)
- # editors (1)
- # emacs (10)
- # funcool (5)
- # hoplon (170)
- # instaparse (4)
- # jobs (1)
- # om (1)
- # onyx (1)
- # re-frame (14)
- # reagent (1)
- # testing (14)
- # yada (1)
Hi. I am looking for a way to handle the "input" event on a textfield with some delay, to achieve or simulate a "user stopped typing" event. Is there any support from hoplon for this? Example:
(input :type "text"
:input #(reset! filtered-customers (search customers (.-value (.-target %)))))
Use async/core? That's the answer on the server side, but for clients I'm finding it slows load time significantly. If that is not a concern, then you have your answer.
@roti: i use a debounce function with the keyup
event:
https://github.com/hoplon/ui/blob/master/src/hoplon/ui.cljs#L47-L54
https://github.com/hoplon/ui/blob/master/src/hoplon/ui.cljs#L375
@jumblerg thanks. so basically the function given to debounce is called only once there is a 800ms or greater delay between two keyup events, right?
i doubt this is the optimal interval to use. i set it once based on a particular usage case and haven’t tuned it since. adjust as necessary.
this is a common problem i typically encounter when trying create a better user experience by (a) validating content on a per-field basis or (b) omitting the submit button given a scenario where an atomic transaction containing the values of multiple fields is unnecessary
maybe we should have some sort of abstraction to assist with this problem in hoplon itself, at a minimum some throttle
and debounce
fns in a utils ns.
@jumblerg i’d love to see throttle and debounce javelin cells
@thedavidmeister: think the debounce fn i linked to was actually stripped from a javelin throttle cell micha wrote; there’s one floating around in a gist somewhere. i personally haven’t found a need for them, however, since i rarely have cells on the “command side” of my applications which is where i’ve done all my throttling and debouncing.
i’ve got something dialing out to my server on keypress, so it would be nice
@roti i made another exampel just now using a cool debounce
function i found, https://gist.github.com/alandipert/71a11fcd688d016333838dcade8dbf78
@alandipert: yeah, that’s the sauce: https://gist.github.com/alandipert/71a11fcd688d016333838dcade8dbf78#file-index-cljs-hl-L14-L17
why not have a throttle-cell=
?
@thedavidmeister: typically, the user generates some input which invokes a callback. that callback in turn invokes a stack of additional functions which ultimately update my model. i haven’t found many cases where i benefit from cells in this case.
i think cells already do what most people use debounce for
like in jq/underscore at least, it's used to dedup many identical events, which is one thing cells already do
the thing you don't have with cells automatically though is a callback after the "last" value was added for some time window length
made a demo, https://dl.dropboxusercontent.com/u/12379861/hoplon-debounce-example/index.html
yeah that’s cool
it would be nice to have something in hoplon
whether it’s a cell or just one of these examples
well with throttle you should trigger straight away
and then trigger at most X times per second after that
debounce is different
debounce is kinda the opposite maybe?
like after the "batch" that throttle made, fire an event
this is a good demo
well, an example above is not showing error text immediately
or you might have a really expensive calculation
for like, window resize, maybe
or maybe it has an animation that you don’t want to trigger many times, like masonry style
but i agree that throttle is what you normally want
spellcheck is another example, want to run it n secs after user stopped inputting
it depends on your ui
it doesn't always make sense to constantly show the invalid state flash/ui
debouncing is an expedient way to not show ephemeral input warnings
i’m not entirely clear what the difference between the two happens to be, since everyone with a blog and a keyboard seems to suggest differing definitions. i thought what micha is calling a throttle was a debounce.
well the word “throttle” in other contexts means what it means in that codepen
you rate limit something, but you still allow it to happen as much as it can within that limit
i don’t know if “debounce” means anything elsewhere
so, if we have event X that triggers Y, throttle = Y cannot trigger faster than a certain rate, debounce = Y can only be triggered after “enough” time has passed after the last time X happened
my case for the debounce was filtering a list when the user typed; due to the size of the list the computation was a bit expensive, so i wanted to wait until the user paused to assume some valid atomic state within the input string itself.
yeah that’s a debounce
i have a very similar use case
i haven’t gotten around to optimising it yet though
throttle is useful when you want something expensive to happen in “real time” but actually, the thing that triggers it commonly occurs faster than the calculation can keep up
like without the dependency graph javelin would use it to wait for the dependencies of a formula to settle down before recomputing it's own value
but debounce is also used to try and infer “intent” from users
like hover intent
debounce is a bad name for it, imo
but it’s what we have to work with
yeah it comes from signals like where the voltage needs to ramp up and stabilize in a circuit
close the switch and the voltage bounces for a while before it settles down on the steady value
i just learned something 🙂
i would find it useful
cells are awesome, but sometimes they can be a little too responsive
from so:
Throttle: the original function be called at most once per specified period.
Debounce: the original function be called after the caller stops calling the decorated function after a specified period.
and you actually want things to chill out a bit
i think @thedavidmeister had really good explanation
the concept is to approximate real time even when the input rate exceeds the rate at which you can process the signal
agreed. i have yet to need these functions for use with javelin though, i would find them more useful without the cells as hoplon utils.
vs debouncibg, where you expect a lot of useless values and you only care about the last one
does the throttling implementation guarantee you’ll always get the last input from the user?
and like if you want to validate only when done if have a formula that can compute when done
here’s an example of window resize where you want debounce
the animation is very obvious
incidentally, i started using that lib once, then i realized it was a wrapper around https://github.com/metafizzy/outlayer that added no additional value as best i could tell.
now i do this with hoplon ui as follows:
(elem :sh (b (r 1 1) md (- (r 1 1) 258)) :sv (r 1 1) :g 8 :c :transparent
(let [n (b 1 sm 2 md 3 lg 4)]
(for-tpl [col (cell= (apply map vector (partition n projects)))]
(elem :sh (cell= (r 1 n)) :gv 8
(for-tpl [{i :id n :name {m :key} :#contact d :_txt u :image} col]
(project :id i :name n :manufacturer m :description d :url u)))))))))
although it doesn’t handle the additional case of distributing all the elements across the columns at the end of a long scroll where the heights of the various elements don’t always average out
incidentally, i’ve been wondering if it might make sense to add a standard :let
attribute to hoplon
the problem with the standard let expression, such as in the example above, is that it will only return the last expression, but in hoplon, it would be convenient if we could do something like:
(elem :sh (b (r 1 1) md (- (r 1 1) 258)) :sv (r 1 1) :g 8 :c :transparent :let [n (b 1 sm 2 md 3 lg 4)]
(elem :sh n "some other thing")
(for-tpl [col (cell= (apply map vector (partition n projects)))]
(elem :sh (cell= (r 1 n)) :gv 8
(for-tpl [{i :id n :name {m :key} :#contact d :_txt u :image} col]
(project :id i :name n :manufacturer m :description d :url u)))))))))
it also has the added benefit of being a bit more expressive by permitting the indentation of the elements to better communicate the semantics of how the returned elements will be nested in the dom.
i haven’t thought it through enough to decide whether i think this really a good idea, but figured i’d toss it out there.
maybe there could also be a :bind
that utilizes your bound-fn implementation to make css-style-inheritance explicit
(elem :s (r 1 1)
:let [h1 {:f 26 :ft :500 :fh 25 :fw 2 :fc (c 0xCCC)}
h2 {:f 21 :ft :300 :fh 23 :fw 2 :fc (c 0xCCC)}]
(elem h1 :sh (r 1 1) "one thing")
(elem h2 :sh (r 1 1) "another thing”))
we support that sort of syntax on doseq
, for
, and by extension the tpls, so it would be consistent. but probably not worth losing apply over.
incidentally, i’ve learned through practice that hoplon becomes more composeable when you define groups of attributes that are commonly used together (let’s call them styles) as maps assigned to variables, which i then pass in as the first arguments to any element i want them applied to.
before i was creating separate h1
, h2
functions, but i find this approach works better.
eg
;;; styles ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;-- breakpoints ----------------------------------------------------------------
(def sm 760)
(def md 1240)
(def lg 1480)
;-- colors ---------------------------------------------------------------------
(def grey (c 0xF6F8FA))
(def orange (c 0xFFC160))
(def black (c 0x1F1F1F))
(def blue (c 0x4394CD))
;-- palettes -------------------------------------------------------------------
(def success {:c (c 0xdff0d8) :bc (c 0xd6e9c6) :fc (c 0x3c763d)})
(def warning {:c (c 0xfcf8e3) :bc (c 0xfaebcc) :fc (c 0x8a6d3b)})
(def danger {:c (c 0xf2dede) :bc (c 0xebccd1) :fc (c 0xa94442)})
(def info {:c (c 0xd9edf7) :bc (c 0xBCE8F1) :fc (c 0x31708f)})
;-- text -----------------------------------------------------------------------
(def banner-title-font {:f 84 :ff "kaushan" :ft :500 :fc orange :fh 100 :fw 3})
(def banner-subtitle-font {:f 22 :ff "core-sans" :ft :300 :fc :white :fw 14})
(def section-title-font {:f 21 :ff "geometos" :ft :500 :fc black :fw 6})
(def section-subtitle-font {:f 18 :ff "avenir" :ft :300 :fc black :fi :italic})
^ speaking of dynamic scope, I cleaned up my (almost pretty) binding’s example, thanks to @micha this model has worked wonders for me! https://github.com/flyboarder/blaze/blob/master/src/index.cljs.hl
Hi guys!
I am having memory problems
heroku says my app uses 520M but is set to 512M
was wondering if, regular hoplon apps could easily require more than 512M dyno
hmm, well I upload a jar that inside has my cljs and my clj code
I guess yes, when doing make-war it compiles js
I use ring, so I guess jetty
ok perfect thanks.
How can I easily see what fn cause memory to climb up?
Thanks!