Template question: Model elements

99 views
Skip to first unread message

David Nolen

unread,
Oct 21, 2009, 2:55:42 PM10/21/09
to Enlive
Say I have a template like this:

<html>
<ul id="links" class="widget">
<li><a>Link A</a></li>
<li><a>Link B</a></li>
<li><a>Link C</a></li>
</ul>
</html>

In my template I extract this as a snippet with defsnippet. However
when adding links to this snippet I don't want all 3 li tags. One li
tag is the model. The extra ones are just there so that the template
looks "nice" when viewed as a normal page.

So how can express that I want to remove them and just use one as a
model and loop creating as many links as actually required?

Meikel Brandmeyer

unread,
Oct 21, 2009, 3:48:15 PM10/21/09
to enliv...@googlegroups.com
Hi,

I came up with this (untested) code...

(deftemplate template
"template.html"
[link-map]
[:ul#links (nth-child 1)] nil
[:ul#links (nth-child 1)] nil
[:ul#links first-child] (clone-for [[link href] link-map]
[:a] (do->
(content link)
(set-attr :href href))))

However it's ugly, that the number of childrens to delete is
hardwired. Is there also a "not"? My first idea was this:

(deftemplate template
"template.html"
[link-map]
[:ul#links first-child] (set-attr :first "true")
[:ul#links :> any-node (not (attr? :first))] nil
[:ul#links first-child] (do->
(remove-attr :first)
(clone-for [[link href] link-map]
[:a] (do->
(content link)
(set-attr :href href)))))

But there is no "not".

One could also replicate the <li> tag:

(defsnippet link-model
"template.html"
[:ul#links first-child :> any-node]
[text href]
[:a] (do->
(content text)
(set-attr :href href)))

(deftemplate template
"template.html"
[link-map]
[:ul#links] (content {:tag :li :attr {} :content []})
[:ul#links :> :li] (clone-for [[text href] link-map]
(content (link-model text href))))

However, one has to replicate all attributes for the <li> tag....

These are the ideas I came up with, and none is really satisfying...
(I'm not even sure the above code is correct....)

Sincerely
Meikel

Christophe Grand

unread,
Oct 22, 2009, 1:56:30 AM10/22/09
to enliv...@googlegroups.com
Hi David and Meikel,


This is a good idea but you need to insert :> after each :ul#links otherwise you remove all elements that are 1st child of their parent.
Btw CSS indexing is 1-based so (nth-child 1) is equivalent to first-child (it's even its definition).

However it's ugly, that the number of childrens to delete is hardwired. Is there also a "not"?

There's a not but to not clash with core's not it's named "but":
(defsnippet links-list "sandbox/dnolen1.html" [:ul#links] [links]
 [[:li (but first-child)]] nil
 [:li] (clone-for [[link href] links]

         [:a] (do->
                (content link)
                (set-attr :href href))))



One could also replicate the <li> tag:

(defsnippet link-model
 "template.html"
 [:ul#links first-child :> any-node]
 [text href]
 [:a] (do->
        (content text)
        (set-attr :href href)))

(deftemplate template
 "template.html"
 [link-map]
 [:ul#links]        (content {:tag :li :attr {} :content []})
 [:ul#links :> :li] (clone-for [[text href] link-map]
                      (content (link-model text href))))

However, one has to replicate all attributes for the <li> tag....

I prefer your first idea to this one. There's no need still to replicate all attributes:
(defsnippet link-model  "template.html"  [:ul#links :> first-child] ; select the 1st LI
 [[text href]]

 [:a] (do->
        (content text)
        (set-attr :href href)))

(deftemplate template
 "template.html"
 [link-map]
 [:ul#links]        (content (map link-model link-map)))



To me, the first solution is the best but if one doesn't want to remove the extra li nodes every time, another solution would be to massage the resource:

(def massaged-resource
  (flatmap #(at % [[:li (but first-child)]] nil)
    (html-resource "sandbox/dnolen1.html")))

(defsnippet links-list massaged-resource [:ul#links] [links]
  [:li] (clone-for [[link href] links]

         [:a] (do->
                (content link)
                (set-attr :href href))))


Christophe

--
Professional: http://cgrand.net/ (fr)
On Clojure: http://clj-me.blogspot.com/ (en)

Christophe Grand

unread,
Oct 29, 2009, 7:26:11 AM10/29/09
to enliv...@googlegroups.com
Repost with gmail rich-text formatting disabled (which should make it
easier to read):

Hi David and Meikel ,

This is a good idea but you need to insert :> after each :ul#links otherwise


you remove all elements that are 1st child of their parent.
Btw CSS indexing is 1-based so (nth-child 1) is equivalent to first-child
(it's even its definition).

> However it's ugly, that the number of childrens to delete is hardwired. Is


> there also a "not"?

There's a "not" but to not clash with core's "not" it's named "but":


(defsnippet links-list "sandbox/dnolen1.html" [:ul#links] [links]
[[:li (but first-child)]] nil
[:li] (clone-for [[link href] links]

[:a] (do->
(content link)
(set-attr :href href))))

> One could also replicate the <li> tag:


>
> (defsnippet link-model
>  "template.html"
>  [:ul#links first-child :> any-node]
>  [text href]
>  [:a] (do->
>         (content text)
>         (set-attr :href href)))
>
> (deftemplate template
>  "template.html"
>  [link-map]
>  [:ul#links]        (content {:tag :li :attr {} :content []})
>  [:ul#links :> :li] (clone-for [[text href] link-map]
>                       (content (link-model text href))))
>
> However, one has to replicate all attributes for the <li> tag....

I prefer your first idea to this one. There's no need still to replicate all
attributes:
(defsnippet link-model "template.html"
[:ul#links :> first-child] ; select the 1st LI
[[text href]]


[:a] (do->
(content text)
(set-attr :href href)))

(deftemplate template
"template.html"
[link-map]


[:ul#links] (content (map link-model link-map)))

To me, the first solution is the best but if one doesn't want to remove the
extra li nodes every time, another solution would be to massage the
resource:

(def massaged-resource
(flatmap #(at % [[:li (but first-child)]] nil)
(html-resource "sandbox/dnolen1.html")))

(defsnippet links-list massaged-resource [:ul#links] [links]
[:li] (clone-for [[link href] links]

[:a] (do->
(content link)
(set-attr :href href))))

Christophe

Reply all
Reply to author
Forward
0 new messages