This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-11-13
Channels
- # admin-announcements (6)
- # beginners (19)
- # boot (1)
- # cbus (2)
- # cider (3)
- # clara (24)
- # cljs-dev (4)
- # cljsrn (18)
- # clojure (168)
- # clojure-boston (1)
- # clojure-dev (55)
- # clojure-russia (199)
- # clojure-sg (2)
- # clojurescript (38)
- # clojurex (1)
- # core-async (15)
- # css (16)
- # cursive (62)
- # datomic (23)
- # editors-rus (17)
- # events (3)
- # funcool (1)
- # hoplon (360)
- # ldnclj (37)
- # lein-figwheel (11)
- # leiningen (1)
- # nginx (1)
- # off-topic (13)
- # om (361)
- # onyx (1)
- # re-frame (56)
- # reagent (24)
- # robots (1)
- # spacemacs (46)
- # yada (9)
@onetom: just because of simplicity, also I don't really want to duplicate logic on a dozen different a
elements if i can help it. It's fine for one link, but not if i have to get the logic working across what could become headers/footers/pagination/etc.
@onetom: i'd consider sticking cells inside the do!
but probably never straight on the element
(defelem a+ [{:keys [href] :as attrs} kids]
((a attrs kids) :class (cell= {:active (= href route)}))
((a :href x :class "some non-dynamic classes") :class (cell= {:active (= x route)}))
looks really interesting
i want to give that a whirl when i have the chance
then u can also extend what gets included into .hl namespaces automatically, so u wouldnt need to manually include this a+ into every other namespace
@onetom: yeah, we had a chat about a special element
i actually got really deep on this active class stuff when working on the Drupal 8 upgrade a while back
there's a bunch of reasons I prefer an attribute over a new element type
sure, but it's an already existing built-in feature of hoplon to do the addClass stuff, so i really see no benefit of doing it yourself
no, there's not
the syntax you showed me is something i didn't know about before
dont think about it as a new "element type" it's just a function which takes away boilerplate...
but i think there is a benefit to a new attribute that can add itself if needed to the DOM
u can also call it just a
too if u don't mind getting a warning about the re-definition of it
it could be a data attribute
doesn't have to be a class
yeah but it does
if i come up with a new reason
so i make a++
and does that wrap a+
?
or... do i need a+&++
someday?
what if i'm making pagination and I want "active" "next" "previous" "recommended"
or something
i made elements for that myself since the resulting code reads better using such domain specific terminology...
i wouldnt expect to see pure anchors in my code with lots of boilerplate options, but i would prefer a (next :href "x")
instead
oh well, i think i'm going to make a hybrid of what you and alandipert suggested
@onetom: i think the preference would be dictated more by the nature of the app/codebase than something you could generically say is "best"
also since you can provide a hash-map as a parameter to a dom element, i can imagine that u can compose you correlated attributes with a function, like:
(a (active-on "/path") :data "x" :target "_blank" (img ...))
that's originally what i had
basically
that's preeety close to what i was doing
and what i'm looking to simplify a bit
mmm yeah
but really, going from (active-on "/path")
to :active-attribute
is all i'm thinking
and shifting the active-on
to part of do!
it seems much of a muchness to me
except the attributes would be a bit more of a formalisation of what i'm trying to do IMO
I could put some docs together for a list of custom attributes pretty easily
i think it would be harder to explain to someone else all the functions that need to be used
i dunno though?
i still want to play around with a few different options
but it would be easier to explain to use a custom element but with standard attributes, which encapsulates such interplay between attributes (or even potentially other kids) imho
hah, have you ever used Drupal's render API?
using do!
feels too generic to me.
the meaning of an :active
attribute might vary from dom element to dom element,
yet you would need to define all these different behaviors in the same multimethod definition...
well basically, Drupal has the ability to setup custom elements
no, i was avoiding such "turn key" systems for many years now. generally pretty much anything php or even python based and i fell out of love with ruby too
attach JS and the rest
very similar to a custom element here
pretty similar tbh
based on what i've seen
but with different ways of doing things
actually, some things are better
like, i can "hook into" the rendering of other elements defined elsewhere
and some things are worse, like it's more fiddly/verbose
that's the "old stlye" jquery approach where u separate the element construction from its behaviour definition and as a result u have to assign "addresses" to the elements which u can use like C pointers later to bind behaviour to them
you can attach JS and CSS to elements
you can totally put behaviour in the element definition
that bit is beside the point
what i'm pointing out is that there's been a community effort to provide different element types
which is awesome
they all have attributes which are "standard" to the element itself
but when you try to look for patterns across different elements
like does #title
always mean the same thing?
the answer is "it depends whether the author of the element implemented it correctly"
so, my opinion is that you find yourself with a bunch of attributes you do want to be able to formalise across all elements
and also the ability to have elements that define their own behaviour and compose other elements
that's a big part of the reason why i like hoplon
Drupal has some ability to standardise attribute behaviour, but it's much weaker than the element definition framework
so you generally end up with slight inconsistencies
that tend to snowball over time
is that bad?
i'm not using drupal at all
do u know our homepage project? https://github.com/exicon/homepage
i'm saying the drupal render API is a close enough of an analogy to the specific thing we're talking about
to help me articulate a point 😛
yeah, that looks pretty useful as an example
thanks
; Workaround until/unless gets done.
(defn- get-href
[elem]
(.attr (.$ js/window elem) "href"))
(defn- set-attr!
[elem k v]
(.attr (js/jQuery elem) k v))
(defmethod c/do! :data-current-path
[elem _ _]
(if (url/current-path? (get-href elem))
(set-attr! elem "data-current-path" "")))
; All our nav links.
(def links [
(c/a "WIP" :href "/")
(c/a "Style Guide" :href "/style-guide.html")
])
(c/defelem support []
(c/nav (map #(% :data-current-path) links)))
my css can point straight at a[data-current-path]
@onetom: @alandipert @bsima thanks all, i learned a cool trick today between the three of you
@thedavidmeister: cool! btw you can put thi sin your own code to use get
on Elements:
(extend-type js/Element
cljs.core/ILookup
(-lookup
([this k] (-lookup this k nil))
([this k not-found]
(if-let (.attr (js/jQuery this) (name k))
v
not-found))))
i got it down to
(defmethod c/do! :data-current-path
[elem _ _]
(if (url/current-path? ($/attr elem "href"))
(elem :attr {"data-current-path" ""})))
; All the links for our nav menu.
(def links [
(c/a "WIP" :href "/")
(c/a "Style Guide" :href "/style-guide.html")
])
(c/defelem primary []
(c/nav (map #(% :data-current-path) links)))
@alandipert: is what you posted a way to make this work?
; If the href of an element is the current path add data-current-path
(defmethod c/do! :data-current-path
[elem _ _]
(if (url/current-path? (:href elem))
(elem :attr {"data-current-path" ""})))
@thedavidmeister: i don't think so, it's a substitute for get-href
yeah that’s all i changed i think
oh sorry, slightly different syntax in the two things i posted
so instead of
(.attr (.$ js/window elem) "href”)
can i do
(:href elem)
with your latest code?
hm, not quite: (get elem :href)
altho (:href elem) may work, not sure
i would guess that works because under the hood the keyword data type implments IFn as get
also my guess
what i dont quite get is "...it's literally impossible to store zero information in the DOM..." i might have been your experience, but in the past few years i didn't have to store anything in the DOM since i started using angularjs, then hoplon
(extend-type js/Element
cljs.core/ILookup
(-lookup
([this k] (-lookup this k nil))
([this k not-found]
(if-let [v (.attr (js/jQuery this) (name k))]
v
not-found))))
@onetom: the href
is “information” in my books
@onetom: so is whether something is a div
or a span
or anything else, it’s all information
@onetom: so is every attribute
to me store means the authorative/primary location of information within some address space
@alandipert: you had a couple of minor syntax issues, but i figured it out
the dom element attributes hold copies of such data, but thats we don't really refer to it as "store"
@onetom: mmm, i’m not
@onetom: i’m creating links, then later in my execution, i’m checking some value on the links to make a decision about something
@onetom: the a
is the store of the href
i see what u r doing, sure. it's a very imperative style thinking. with that approach u will find yourself trying to read element attributes.
you’re assuming what I’m thinking. i just don’t really understand why (my-link :foo)
is OK but (:foo my-link)
is not
the original http://hoplon.io site had a diagram of a uni-directional data flow
i haven’t seen the original http://hoplon.io site
the idea is that having data flowing in a restricted direction can greatly simplify the amount of code u need to write
and how is this not uni-directional?
going from attribute A to attribute B
but i’m getting A to make a decision about B
not getting B to make a decision about B
I wrote it, in a different part of my program
i made a link element “somewhere else"
with attribute A
now i’d like to generate attribute B
that’s nothing to do with “unidirectional flow"
in this case, it makes my program less DRY to do so
and opens an avenue for future inconsistencies and potential bugs
the reason for getting the value of A "from its original place" is that you have the chance to keep the value there on its own, without being attached to more complex data, like a DOM element, which can be mutated in many ways even by user interaction
@onetom: but “the original place” is the a
that i created
@onetom: i could make a list for the data that I make an a
from
but that really seemed like overkill for what i’m doing
i started with that approach
u will should find that it's a lot simpler and actually quite straight forward approach
comparing [(a …) (a …)]
then adding a single attribute (the same attribute, based on a condition, to every a
to building a hash map up, then processing that to build a
@onetom: i’ve been asked that a bunch of times, and every example i’ve seen makes things more complicated because it adds an extra layer of abstraction that isn’t needed here
cells look great
but i also think they’re overkill here
@onetom: i have quite a bit of experience with this particular problem in other frameworks that suggests it’s useful to be able to handle href
in a standard way for links, not tied to the definition of how you process the link for rendering/behaviour
let’s try a different tack
i have a pretty good idea of what problems
; If the href of an element is the current path add data-current-path
(defmethod c/do! :data-current-path
[elem _ _]
(if (url/current-path? (:href elem))
(elem :attr {"data-current-path" ""})))
; All the links for our nav menu.
(def links [
(c/a "WIP" :href "/")
(c/a "Style Guide" :href "/style-guide.html")
])
(c/defelem primary []
(c/nav (map #(% :data-current-path) links)))
solves, compared to trying to make a custom element
and then needing to deal with all the different things that are just like this and might want to be used to together
what concrete problems am I causing for myself?
there’s only unidirectional data flow, because it goes from attribute A to B
strictly
and “because cells” isn’t convincing, because plenty of things work just fine without cells
despite cells being a useful tool to solve problems
a different link will have the attribute
if you’re on “/“ then the first link has it, if you’re on “/style-guide.html” the second link has it
well it’s a new page
i’m not using routes
i’m going old skool
HTMLing like it’s 1990
so if i was using routes then i’d use that routing cell, looks cool
but i’m not, so KISS won out
<a href="/" data-current-path="">WIP</a>
with a data-current-path
attr when the link is to the same page that you're already on?
like that
<a href="/style-guide.html">Style Guide</a>
or that, if not the current path
i just um… a[data-current-path]
in my CSS
because yolo
too cool for classes
i mean really, a class is fine too
but alsoooo
if i make a footer menu
or “something"
use the same thing to get those links behaving in the same way
and also
i might want to do something else to any of these links based on the href
like add a click-me
mark, for CSS styling
hypothetically
and it would only be OK if i could have click-me
logic running on the same elements as active
logic
well if you're thinking in terms of organizing for extension it pays to not yolo the foundation
and i don’t know ahead of time which things will need click-me
, which will need active
and which will need both or neither
@micha: i’m just yolo-ing the difference between CSS styling based on a class or attribute
@micha: i wouldn’t be here having this convo if i was yolo-ing the whole thing 😛
like if you want the easiest thing with no overkill you will be at odds with making a thing that will be extended cleanly for years as it grows huge
based on what I just said though
i feel like “custom attribute” seems like a better idea than “custom element"
as long as i respect the one-way data thing
you can use specify!
to dynamically add protocol implementation to instances at runtime
ok, i haven’t used specify!
yet
i’ll have to look that up
i think that implementing the ILookup protocol to fetch the attr would be something we'd want to work for everyone
but it sounds like I’m still getting and setting attributes
so I’m right back to the start
which is
I don’t see the harm in (:foo elem)
when we have (elem :foo)
although, yes, i see the harm if it’s the same :foo
and the same elem
@micha: you are right, because i tried that earlier and it totally did not work, lol
(elem :foo value)
is what we have
i tihnk one problem with assuming symmetry between (:foo el)
and (el :foo)
is that there may be no sensible inverse sometimes
oh, what’s an example of that?
ah sure
i get it
cool, so
let’s see if i have this straight
if i go ahead and extend do!
then i get a custom attribute
BUT despite that attribute being intended for a
you could stick it on whatever
and end up with something that is harmless in this case, but more generally, not so harmless
BUT if i try to make a custom element
i run into issues trying to juggle all these different attribute handling things that could get pretty complex later
AND because custom elements exist, we can’t do (:foo elem)
because :foo
is not always an attribute, it could just be a parameter the element does literally whatever with
BUT because we know that a
provided by core always uses :href
as an attribute, we can extend the way a
works using this specify!
thing, to respond to the :href
this is the issue with coming from another framework
i feel like this is the very first thing i asked
but i obviously had the wrong terminology
no, it’s what i wanted to do from the start, haha
i know how to do all these things in Drupal, but they all have different names, that just makes me say the wrong thing to you guys >.<
this is what i meant by “hook into"
yeah, i don’t know about the wider hoplon stuff, but what we just talked about now is pretty familiar to me
but different names and syntax and everything 😞
is there any plan to make elements work more like collections
and make the bits you send through for side effects knowable somehow?
that’s not really why i was thinking it would be useful
i was thinking it would be useful to use clojure functions that work on collections to help with the presentation
well… that’s pretty much what i’m trying to do, lol
if you forget that i’m using a data attribute
that one line of CSS targets
and replace everything i said earlier with “and add CSS based on the href"
or something else
then say you want to map over some links, or reduce the attributes of an element to a CSS rule
yeah I can
but I basically am
the difference between a dedicated CSS rule in a file using an attribute, and an inline CSS rule
totes splitting hairs
it’s getting late here
@thedavidmeister: thanks for really digging into this and taking notes along the way
:thumbsup: 🌈
hah, np, i’m getting heaps of value from this chat
least i can do is take notes
@thedavidmeister: very interesting conversation indeed
u summarized very well what i was trying to tell u. regarding syntax sugar encouraging bad practices, i would point to the example of "web steps" bundled by default with "cucumber". people got the idea from that that they should write acceptance test using those web steps, like:
Given I visit the login page
And I fill out the user field with x
And I fill out the password field with s3crEt
When I click login
Then I should be on the dashboard page
And I should see "my name" on the menu bar
a few years later the authors said it was a big mistake to provide such helper step definitions because it polluted the whole spec by example movement and a huge masses of people misunderstood it and they indeed just wasted a lot of their time trying to maintain such brittle tests until they abandoned them and just badmouthed the whole idea.
in hoplon 5 for example you had to say :on-click
and :do-class
.
it took several hours over the course of ~2months for us to change our code base when we were transitioning to holpon 6
and it took further weeks before everyone forgot the hoplon5 "notation".
there was quite a few confusing weeks where some of our stuff was on boot1+hoplpon5 and others were already converted to boot2+hoplon6