Fork me on GitHub
#hoplon
<
2016-06-25
>
chromalchemy01:06:21

@jumblerg: Hi! I've got Hoplon/UI up and running and have been poking around. I'm enjoying applying style attributes more directly in clojure data, rather than bounce back and forth between the ':class' and ':css' attributes, funging around with the values wrapped in strings.

chromalchemy01:06:02

This is helping with my general Hoplon aha moments. The value of having the dynamic environment is so mindboggling compared to the static page context. I can continue to appreciate it more with the advanced visual design code patterns being more apparent and accessible.

chromalchemy01:06:46

More invititing for Javelin functional play! clj :

chromalchemy01:06:14

at least to weave it into declarative styling.

jumblerg02:06:31

@chromalchemy: glad to hear it! we’ve still got a lot of work to do, but i think this approach holds a lot of promise.

adamw08:06:11

@jumblerg: I've been playing with hoplon/ui a little; my background in hoplon is generally pretty limited so apologies this will probably be pretty obvious. How should I go about putting in place HTML elements that can't be wrapped in a box? For instance I'm trying to get <ul><li></li></ul>. I can't wrap h/li in box as they cannot be wrapped in a div. If I just pass in h/li directly as a child element of (elem) I get an error on initialisation in swap-elems!:

Uncaught Error: Invalid child of type function HTMLUListElement() { [native code] } with values (#<Cell: :middle>).

adamw08:06:32

this is what I tried to do:

adamw08:06:37

(def vul    (-> h/ul  hui/parse-args))
(def vli    (-> h/li  hui/parse-args))
...
        (elem :fc c/white :h (r 1 1) :av :middle :ah :right :ph 15
          (vul
            (vli "List Element 1")))

adamw08:06:55

^ or should I not try to add <ul><li> and entirely fake it using elems appropriately laid out?

jumblerg14:06:50

@adamw: g’evening adam

jumblerg14:06:41

my suggestion would be to only use elems, at least, until it becomes clear that we need to introduce another component.

jumblerg14:06:13

you shouldn’t ever have to drop down into hoplon html primitives, unless, that is, there’s a deficiency in hoplon/ui and we need to introduce another ui primitive, so to speak.

jumblerg15:06:04

based on the code you’ve shown me, it appears you’re mucking around with the ui internals, which isn’t something you should have to do normally.

jumblerg15:06:37

(they’re also going to be refactored in a big way, and if you depend on them instead of the external api, your code is going to break. i haven’t added any private metadata yet because it gets in the way of my own refactoring, but most of these fns you’re calling should be made private.

jumblerg15:06:39

are there any additional semantics you need (exposed, perhaps, as kwargs to the elem), that the approach below does not provide?

(elem :w (r 1 1) :pl 15 
  (elem “List Element 1”)
  (elem “List Element 2”))

jumblerg15:06:46

my goal is to have an api with a very small service area, to expose the fewest types of things possible. if all the tetris blocks were squares, everything would compose quite nicely and the game would be much easier.

adamw15:06:35

Nope, thanks. Your logic makes sense and the only reason I exposed the internals was because I wasn't sure if they just weren't 'work in Progress' The only benefit of lists is bullet points and alignment of text new lines in bullets, probably doable with elems but harder.

jumblerg15:06:39

ok, so the case is a bulleted list with the associated indentation. let me think about the best way to do this (there are css properties, for example, that could be exposed as ui attributes) and i’ll circle back with you later on.

micha15:06:50

i like the tetris analogy

micha15:06:09

makes me think of like the anti-tetris game, where it's really easy to make a horizontal line, but you lose points when you do it

dm318:06:31

so the goal of the game is to cover the biggest percentage of screen space in figures without making lines? 🙂

micha18:06:04

yeah maybe instead of being a fixed size the tetris board keeps growing upward

micha18:06:11

and you get points the higher it goes

dm318:06:24

sounds like consulting

jumblerg19:06:10

questions like @adamw’s have gotten me thinking about when it is appropriate to introduce a new element name, and specifically, semantic html.

jumblerg19:06:28

i guess the thing i wonder is “semantic to who?"

jumblerg19:06:56

i think it lends clarity to consider who the various actors are when thinking about how and whether we tag our elements.

micha19:06:57

yeah i'm skeptical of semantic html

micha19:06:28

i don't know of anything that actually uses that

micha19:06:33

i mean consumes that

micha19:06:46

especially in a single page app

jumblerg19:06:57

so there’s (1) the platform. the name of the tag we pass createElement carries behavioral meaning to the browser, but so do the various css styles. in most cases we can achieve the same behavior as another element my simply applying the right css attributes to a div. the browser doesn't seem to care in most cases.

micha19:06:15

yeah that's what i'm referring to

jumblerg19:06:46

(2) the developer. symbols in our code are designed for this purpose, although it could be useful, at at development time, to generate custom tags that correspond to the names of our abstractions to make it easier to debug layouts.

micha19:06:16

you can add metadata in other ways

micha19:06:19

via an attribute

jumblerg19:06:36

(3) the human user: the ornaments we hang on our data structures to make the interface more pleasant should be chosen for this purpose.

micha19:06:48

i think KISS is the thing here

micha19:06:19

like there is no real significance to <li> vs <div>

jumblerg19:06:50

and (4) the machine user. apis are made for this purpose, our application is not. however, we may need to pragmatically support (a) web crawlers for seo (b) maybe other scrapers, but we probably don’t want these most of the time. (c) accessibility agents (4) other third party tools. but the lowest common denominator is large enough with ie 8 in play, to what extent do we care about other tools like brower plugin that implement only part of the browser's standard.

jumblerg19:06:52

yeah, i’ve been looking around wrt <li> vs <div> and can’t find any advantage to incorporating the tag names specifically.

jumblerg19:06:02

there’s a css style to introduce bullets, however.

micha19:06:41

the things where point (4) is relevant is form controls, basically

jumblerg19:06:52

wrt #3, @chromalchemy has been giving me some awesome feedback.

micha19:06:53

which we don't intend to do away with anyway

jumblerg19:06:35

it’s awesome to have a real designer engaged in the process.

micha19:06:43

excellent yes

jumblerg19:06:59

was explaining the value of hsl over rgb to me last night.

jumblerg19:06:21

and why that should probably be the default way we specify our colors.

jumblerg19:06:36

will probably add a util conversion fn for rgb instead.

jumblerg19:06:20

i think, wrt #3, that having outer tag names that correspond to our defelems will be helpful.

jumblerg19:06:38

but we’ll probably need to namespace them or something similar

jumblerg19:06:17

otherwise, they will inevitably collide with primitive names and certain ones will be magically bestowed with new behaviors.

micha19:06:53

you could use an attribute to carry that info

micha19:06:05

instead of messing with the tag name

micha19:06:55

i never found that to be necessary though, since dev tools highlight the thing when you mouseover it

jumblerg19:06:11

yeah, they have the data-* things, but i think given the audience, in this case the developer, i think it would be easiest to parse something like <hoplon.ui/table>

micha19:06:28

you can't have slashes in the tag name unfortunately

jumblerg19:06:38

well, we can munge it

micha19:06:44

that's why hlisp uses dots

micha19:06:58

hoplon.ui.table is what hlisp thing does

jumblerg19:06:12

perfect. so that 🙂

micha19:06:36

are there performance implications?

micha19:06:51

i guess if you're not using css selectors probably not

jumblerg19:06:55

i think it is still helpful, even with dev tools, when you’re trying to match a certain thing to code in your editor. there are no sourcemaps for html i’m aware of.

jumblerg19:06:20

esp when there are three elements for every elem.

micha19:06:53

perhaps the shadow dom is a thing

micha19:06:57

for dev anyway

micha19:06:25

ah nm thats a rabbit hole

micha19:06:30

a stinky one

jumblerg19:06:05

i’ve been looking at this

jumblerg19:06:37

and plan to implement it, but later on, i think that is an optimization we introduce for newer browsers, essentially.

micha19:06:16

it's only real in late model chrome

micha19:06:31

i don't think ie or ff plan to implement it at all

jumblerg19:06:20

i was reading they’re starting to

jumblerg19:06:06

ff has an implementation, but you have to explicitly enable it

jumblerg19:06:57

opera has it

micha19:06:52

basically it's like 10 years away from being usable

jumblerg19:06:39

cross browser, yeah.

jumblerg19:06:22

maybe once ie 8 is out of the picture, stuff will get updated faster since everyone is “evergreening" it now.

jumblerg19:06:46

@micha: have you thought about the defmuli-tpl implementation yet?

micha19:06:20

you can use a multimethod there already, no?

micha19:06:39

(for-tpl [item items]
  (my-multimethod item))

onetom19:06:11

i almost told adam that he doesnt need to define ul/li but then it occurred to me that those list-style-* attributes are not exposed yet in any way in hoplon ui. but then im not sure how useful are they really, since most of the time i just see them being turned off anyway by css reset "frameworks", like http://meyerweb.com/eric/tools/css/reset/

onetom19:06:56

+1 for hoplon.ui.table dom element names

jumblerg20:06:01

@onetom: i’ll add them in a bit

jumblerg22:06:13

@micha et. al: api design question. what do you think about defining “truthy” default values for certain elem attributes in ui? consider my favorite attribute, :fu, as an example. font underline is implemented through the css text-decoration property. the options are [:overline, :line-through, :underline nil false]. but 90% of the time, it is easier for the user to (elem :f 21 :fu true) rather than lookup the attribute. more importantly (elem :fu query/selected “some menu item”)` is more concise than (elem :fu (cell= (when query/selected :underline “some menu item”)).

jumblerg22:06:13

one downside is that validation cannot be quite as strict for such truthy attributes, but this is consistent with clojure’s philosophy i think.

micha22:06:41

yeah i would have made that a map instead of a vector

micha22:06:57

a map is the real thing though

micha22:06:09

if you have options you're enabling or disabling

jumblerg22:06:23

eg, if i pass :fu with a truthy default of :underline some garbage value, it will underline the text instead of throwing an exception.

jumblerg22:06:04

sorry - i was just listing the options as a vector, it can only take one argument.

jumblerg22:06:31

which i believe is the way the underlying css works

micha22:06:52

ah so you have an attribute that can have one of a set of possible values

jumblerg22:06:16

can’t underline and line through the same text with that attribute, anyway.

micha22:06:29

you would still have a map in there somewhere, like to translate to the css property

micha22:06:55

{:underline "underline" :line-through "strike-out" ...

jumblerg22:06:10

i actually just call name on the keywords atm

micha22:06:10

then if a bogus value is passed in it's just nil

jumblerg22:06:30

i also validate the keywords to throw an exception if not one of the expected values

micha22:06:39

the name function is a pain because it's a null pointer footgun

jumblerg22:06:14

yeah, i have that handled though

micha22:06:59

i would still use the map

micha22:06:12

you can have a default when you use the map as a function

jumblerg22:06:54

that’s a default for nil though, right?

jumblerg22:06:22

if a key isn’t found, rather

micha22:06:24

(defn foop [arg]
  (let [valid-things #{:foo :bar}]
    (doit (valid-things arg :foo))))

micha22:06:39

defaults to :foo there

jumblerg22:06:04

that defaults to :foo both in the case of nil and true.

micha22:06:54

(defn foop [arg]
  (let [valid-things #{:foo :bar nil true}]
    (doit (valid-things arg :foo))))

jumblerg22:06:59

i’m proposing that nil, false, the falsey values, equate to false, true, :somegarbage default to :underline.

micha22:06:07

yeah whatever

micha22:06:16

you can add whatever is valid to the set

jumblerg22:06:47

gotcha, implemenation aside, sounds like that api choice seems sensible to you then?

micha22:06:59

what does true and false mean?

jumblerg22:06:49

is this a philosophical/religious question? 🙂

jumblerg22:06:51

what is truth?

jumblerg22:06:59

or in the context of ui

jumblerg22:06:04

truth is what me make it

micha22:06:14

in the context of an attribute that has a set of possible values that translate to css properties

jumblerg22:06:16

i’m trying to figure the truth out here.

micha22:06:30

there is no true/false in css as far as i know

micha22:06:36

so what does it mean?

jumblerg22:06:54

gotcha. they typically connote “off”.

jumblerg22:06:15

there’s a binary suggestion to many of the attributes

jumblerg22:06:29

jquery, for example, uses false this way.

jumblerg22:06:36

or at least nil

micha22:06:41

like text-decoration: off?

micha22:06:12

yeah in jquery (and in hoplon) passing false means remove the attribute

jumblerg22:06:12

that would be :initial

jumblerg22:06:29

which is what :initial does

jumblerg22:06:37

often mapped to :auto

micha22:06:37

passing true means give the attribute the same value as the attribute name

jumblerg22:06:54

yeah, that’s what i’m thinking, at least what the name suggests

micha22:06:13

makes sense to me

micha22:06:24

although true doesn't really mean anything

micha22:06:30

other than possibly use the default

micha22:06:41

because css properties with no values aren't a thing

micha22:06:24

can you actually remove a css property?

micha22:06:38

i guess you can set it to auto or something

jumblerg22:06:43

yeah, by setting it to ””

jumblerg22:06:49

or :initial

jumblerg22:06:06

certain browsers will display “initial” though

jumblerg22:06:23

if you look at the source

jumblerg22:06:31

if we didn’t set it, we don’t want it there

jumblerg22:06:51

so false, nil will mean hidden, true will mean the hoplon/ui default.

jumblerg22:06:44

the hoplon/ui default for true, on, that is.

micha22:06:49

might be good to have anything truthy that isn't a valid value can be the default

jumblerg22:06:19

that’s why i mentioned it will weaken the validation a bit

micha22:06:19

so you don't need a special dispatch for true

micha22:06:37

anything that's not false or nil is the valid value or default

jumblerg22:06:45

:fu :garbage will underline the thing

jumblerg22:06:06

ok, cool, just wanted a sounding board before i went crazy, thanks!

jumblerg22:06:27

oh, wrt the map...

jumblerg22:06:33

we have a lot of keywords

jumblerg22:06:06

(s/def ::colors   #{:transparent :antiquewhite :aqua :aquamarine :azure :beige
                    :bisque :black :blanchedalmond :blue :blueviolet :brown
                    :burlywood :cadetblue :chartreuse :chocolate :coral
                    :cornflowerblue :cornsilk :crimson :darkblue :darkcyan
                    :darkgoldenrod :darkgray :darkgreen :darkgrey :darkkhaki
                    :darkmagenta :darkolivegreen :darkorange :darkorchid :darkred
                    :darksalmon :darkseagreen :darkslateblue :darkslategray
                    :darkslategrey :darkturquoise :darkviolet :deeppink
                    :deepskyblue :dimgray :dimgrey :dodgerblue :firebrick
                    :floralwhite :forestgreen :fuchsia :gainsboro :ghostwhite
                    :gold :goldenrod :gray :green :greenyellow :grey :honeydew
                    :hotpink :indianred :indigo :ivory :khaki :lavender
                    :lavenderblush :lawngreen :lemonchiffon :lightblue :lightcoral
                    :lightcyan :lightgoldenrodyellow :lightgray :lightgreen
                    :lightgrey :lightpink :lightsalmon :lightseagreen
                    :lightskyblue :lightslategray :lightslategrey :lightsteelblue
                    :lightyellow :lime :limegreen :linen :maroon :mediumaquamarine
                    :mediumblue :mediumorchid :mediumpurple :mediumseagreen
                    :mediumslateblue :mediumspringgreen :mediumturquoise
                    :mediumvioletred :midnightblue :mintcream :mistyrose :moccasin
                    :navajowhite :navy :oldlace :olive :olivedrab :orange :orangered
                    :orchid :palegoldenrod :palegreen :paleturquoise
                    :palevioletred :papayawhip :peachpuff :peru :pink :plum
                    :powderblue :purple :rebeccapurple :red :rosybrown :royalblue
                    :saddlebrown :salmon :sandybrown :seagreen :seashell :sienna
                    :silver :skyblue :slateblue :slategray :slategrey :snow
                    :springgreen :steelblue :tan :teal :thistle :tomato :turquoise
                    :violet :wheat :white :whitesmoke :yellow :yellowgreen})

jumblerg22:06:57

disarming the nil shotgun via (def safename [x] (when x (name x)) seems like the way to go for this reason.

micha22:06:21

except when it

micha22:06:56

my safename is (defn safe-name [x] (try (name x) (catch js/Error _)))

micha22:06:24

not to be confused with my safeword

micha22:06:32

which is "harder"

jumblerg22:06:16

you nearly ruined my laptop, btw, i choked on the ice in my coffee i just inhaled from laughing.