Account Options

  1. Sign in
The old Google Groups will be going away soon.
Switch to the new Google Groups.
Google Groups Home
« Groups Home
Looping Case Question
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  15 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
David Nolen  
View profile  
 More options Jan 31 2010, 2:48 pm
From: David Nolen <dnolen.li...@gmail.com>
Date: Sun, 31 Jan 2010 11:48:22 -0800 (PST)
Local: Sun, Jan 31 2010 2:48 pm
Subject: Looping Case Question
When using traditional templating solutions it's common that you'll
see something like the following:

{% for x in coll %}
<h>{{ x.heading }}</h>
<p>{{ x.content }}</p>
{% endfor %]

Note that there is no containing element for the <h> and <p> elements.
How would one loop over something like this using Enlive snippets +
templates? If there was a container element it would be simple, but
without it I don't see anything obvious. Is there a way to support
this case easily?

Thanks,
David


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Robert Campbell  
View profile  
 More options Feb 1 2010, 6:43 am
From: Robert Campbell <rrc...@gmail.com>
Date: Mon, 1 Feb 2010 12:43:01 +0100
Local: Mon, Feb 1 2010 6:43 am
Subject: Re: [enlive] Looping Case Question
Hi David,

I think you're looking for clone-for:

(at node [:option]
   (clone-for [option options]
      (do-> (set-attr :value (option :value))
         #(if (option :selected)
            ((set-attr :selected "selected") %) %)
         (content (option :name)))))))

Here you can see that I only ever reference the <option> element, but
obviously it could be any standalone node.

Rob


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Chas Emerick  
View profile  
 More options Feb 1 2010, 7:56 am
From: Chas Emerick <cemer...@snowtide.com>
Date: Mon, 1 Feb 2010 07:56:47 -0500
Local: Mon, Feb 1 2010 7:56 am
Subject: Re: [enlive] Looping Case Question
Further, go to http://wiki.github.com/cgrand/enlive/getting-started  
and search for clone-for, as Rob mentioned.

- Chas

On Feb 1, 2010, at 6:43 AM, Robert Campbell wrote:


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Christophe Grand  
View profile  
 More options Feb 1 2010, 4:53 pm
From: Christophe Grand <christo...@cgrand.net>
Date: Mon, 1 Feb 2010 22:53:16 +0100
Local: Mon, Feb 1 2010 4:53 pm
Subject: Re: [enlive] Looping Case Question
Hi David,

On Sun, Jan 31, 2010 at 8:48 PM, David Nolen <dnolen.li...@gmail.com> wrote:
> When using traditional templating solutions it's common that you'll
> see something like the following:

> {% for x in coll %}
> <h>{{ x.heading }}</h>
> <p>{{ x.content }}</p>
> {% endfor %]

> Note that there is no containing element for the <h> and <p> elements.

Indeed there's no facility to transform a group of adjacent nodes
without a container.
Off the top of my head:

Clojure 1.2.0-master-SNAPSHOT
user=> (use 'net.cgrand.enlive-html)
nil
user=> (def src (-> "<h1>Big Title<h2>Smaller title<p>A paragraph<div
class="footer">a footer" java.io.StringReader. html-resource))
java.lang.Exception: Unable to resolve symbol: footer in this context
(NO_SOURCE_FILE:2)
user=> (def src (-> "<h1>Big Title<h2>Smaller title<p>A paragraph<div
class='footer'>a footer" java.io.StringReader. html-resource))
#'user/src
user=> src
({:tag :html, :attrs nil, :content [{:tag :body, :attrs nil, :content
[{:tag :h1, :attrs nil, :content ["Big Title"]} {:tag :h2, :attrs nil,
:content ["Smaller title"]} {:tag :p, :attrs nil, :content ["A
paragraph"]} {:tag :div, :attrs {:class "footer"}, :content ["a
footer"]}]}]})
user=> (apply str (emit* src))
"<html><body><h1>Big Title</h1><h2>Smaller title</h2><p>A
paragraph</p><div class=\"footer\">a footer</div></body></html>"
user=> (defsnippet h+p src [#{:h2 :p}] [{:keys [title text]}] [:h2]
(content title) [:p] (content text))
#'user/h+p
user=> (h+p {:title "hello" :text "world"})
({:tag :h2, :attrs nil, :content ("hello")} {:tag :p, :attrs nil,
:content ("world")})
user=> (apply str (emit* *1))
"<h2>hello</h2><p>world</p>"
user=> (deftemplate tmpl src [data] [#{:h2 :p}] nil [:h1] (after (map
h+p data)))
#'user/tmpl
user=> (apply str (tmpl [{:title "title#1" :text "paragraph#1"}
{:title "title#2" :text "paragraph#2"}]))
"<html><body><h1>Big
Title</h1><h2>title#1</h2><p>pragraph#1</p><h2>title#2</h2><p>pragraph#2</p ><div
class=\"footer\">a footer</div></body></html>"

> How would one loop over something like this using Enlive snippets +
> templates? If there was a container element it would be simple, but
> without it I don't see anything obvious. Is there a way to support
> this case easily?

If there was a container element, one could also clone it and then
strip it from the result to leave only the repeated inner nodes.

In order to support (just musing not promising anything) such cases,
how would one define a group of adjacent nodes?

Christophe


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
David Nolen  
View profile  
 More options Feb 2 2010, 5:48 pm
From: David Nolen <dnolen.li...@gmail.com>
Date: Tue, 2 Feb 2010 14:48:43 -0800 (PST)
Local: Tues, Feb 2 2010 5:48 pm
Subject: Re: Looping Case Question
On Feb 1, 4:53 pm, Christophe Grand <christo...@cgrand.net> wrote:

> If there was a container element, one could also clone it and then
> strip it from the result to leave only the repeated inner nodes.

My issue with this is that we are now offloading the problem onto the
person that is writing the markup. Ideally Enlive can just support
common cases.

I like your solution using a snippet with the #{:h2 :p} selector:

But I was thinking it would be nice to combine this with my "model"
idea from the earlier mailing list post:

 (def h+p (html/selector [:div#main :> #{[:h2 (html/nth-of-type 1)]
                                         [:p (html/nth-of-type
1)]}]))

 (html/defsnippet my-snippet source h+p
   [{:keys [title text]}]
   [:h2] (html/content title)
   [:p]  (html/content text))

This actually works pretty well from what I'm describing. And though
it's certainly more verbose than this:

 {% for x in coll %}
 <h>{{ x.heading }}</h>
 <p>{{ x.content }}</p>
 {% endfor %]

The Enlive version is composable and the above is not (beyond copy and
paste).

> In order to support (just musing not promising anything) such cases,
> how would one define a group of adjacent nodes?

> Christophe

As for making it more elegant and less verbose what about something
like the following?

 (html/defsnippet name src selector
   [ctxt]
   [:h2] :and [:p] (fn [h2 p] (...)))

I like this because preserve the idea of the selector/fn pair. If both
selectors aren't matched we just fail and move on to the next
selector/
fn pair.

David


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Christophe Grand  
View profile  
 More options Feb 3 2010, 1:32 am
From: Christophe Grand <christo...@cgrand.net>
Date: Wed, 3 Feb 2010 07:32:38 +0100
Local: Wed, Feb 3 2010 1:32 am
Subject: Re: [enlive] Re: Looping Case Question
Hello,

On Tue, Feb 2, 2010 at 3:47 AM, David Nolen <dnolen.li...@gmail.com> wrote:
> My issue with this is that we are now offloading the problem onto the
> person that is writing the markup. Ideally Enlive can just support
> common cases.

I agree.

> But I was thinking it would be nice to combine this with my "model"
> idea from the earlier mailing list post:

>  (def h+p (html/selector [:div#main :> #{[:h2 (html/nth-of-type 1)]
>                                          [:p (html/nth-of-type
> 1)]}]))

>  (html/defsnippet my-snippet source h+p
>    [{:keys [title text]}]
>    [:h2] (html/content title)
>    [:p]  (html/content text))

This is nice too but still unsatisfactory.

>> In order to support (just musing not promising anything) such cases,
>> how would one define a group of adjacent nodes?

> As for making it more elegant and less verbose what about something
> like the following?

>  (html/defsnippet name src selector
>    [ctxt]
>    [:h2] :and [:p] (fn [h2 p] (...)))

It's close to what I have in mind but I think there's more value in
being able to specify an "extent" between two selectors:

(deftemplate name src [data]
 (extent [:h2] [:p]) (clone-for [{:keys [title text]}]
                       [:h2] (content title)
                       [:p] (content text)))

An extent (if antyone has a better name please chime in) being all the
nodes between two siblings, the leftmost being selected by the first
selector, the rightmost being selected by the second selector.

What do you think?

> I like this because preserve the idea of the selector/fn pair. If both
> selectors aren't matched we just fail and move on to the next selector/
> fn pair.

What I propose is to have an new class of selectors which don't select
a single node but several *adjacent* nodes (including whitespaces and
comments) at once.
The fn would, in this case, take a seq of nodes.

Christophe

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


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
David Nolen  
View profile  
 More options Feb 3 2010, 2:07 am
From: David Nolen <dnolen.li...@gmail.com>
Date: Wed, 3 Feb 2010 02:07:37 -0500
Local: Wed, Feb 3 2010 2:07 am
Subject: Re: [enlive] Re: Looping Case Question

On Wed, Feb 3, 2010 at 1:32 AM, Christophe Grand <christo...@cgrand.net>wrote:

> (deftemplate name src [data]
>  (extent [:h2] [:p]) (clone-for [{:keys [title text]}]
>                       [:h2] (content title)
>                        [:p] (content text)))

> An extent (if antyone has a better name please chime in) being all the
> nodes between two siblings, the leftmost being selected by the first
> selector, the rightmost being selected by the second selector.

> What do you think?

Something like extent would be really fantastic!

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Chas Emerick  
View profile  
 More options Feb 3 2010, 6:54 am
From: Chas Emerick <cemer...@snowtide.com>
Date: Wed, 3 Feb 2010 06:54:39 -0500
Local: Wed, Feb 3 2010 6:54 am
Subject: Re: [enlive] Re: Looping Case Question

On Feb 3, 2010, at 1:32 AM, Christophe Grand wrote:

> It's close to what I have in mind but I think there's more value in
> being able to specify an "extent" between two selectors:

> (deftemplate name src [data]
> (extent [:h2] [:p]) (clone-for [{:keys [title text]}]
>                       [:h2] (content title)
>                       [:p] (content text)))

> An extent (if antyone has a better name please chime in) being all the
> nodes between two siblings, the leftmost being selected by the first
> selector, the rightmost being selected by the second selector.

> What do you think?

Regarding terminology, I'd call it a 'slice', which I think fits in  
with the slice operation that many people are familiar with in python,  
etc.

However...

On Tue, Feb 2, 2010 at 3:47 AM, David Nolen <dnolen.li...@gmail.com>  
wrote:

> My issue with this is that we are now offloading the problem onto the
> person that is writing the markup. Ideally Enlive can just support
> common cases.

Just out of curiosity, is this really a common case?  In my  
(admittedly limited) experience, if one is looking to emit repeated  
sequences of elements as described, then the CSS is going to almost  
certainly need some container around each such sequence anyway.  Is  
this less universal than I suspect?

- Chas


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
David Nolen  
View profile  
 More options Feb 3 2010, 11:18 am
From: David Nolen <dnolen.li...@gmail.com>
Date: Wed, 3 Feb 2010 11:18:25 -0500
Local: Wed, Feb 3 2010 11:18 am
Subject: Re: [enlive] Re: Looping Case Question

On Wed, Feb 3, 2010 at 6:54 AM, Chas Emerick <cemer...@snowtide.com> wrote:
> Regarding terminology, I'd call it a 'slice', which I think fits in with
> the slice operation that many people are familiar with in python, etc.

'extent' and 'slice' are both cool with me.

> However...

> Just out of curiosity, is this really a common case?  In my (admittedly
> limited) experience, if one is looking to emit repeated sequences of
> elements as described, then the CSS is going to almost certainly need some
> container around each such sequence anyway.  Is this less universal than I
> suspect?

You don't need a container to style repeating elements with CSS. I've seen
this pattern a lot in PHP as well as in Django templates. I've been handed
markup that looks this from designers as well. Many JavaScript accordions
expect this pattern.

http://docs.jquery.com/UI/Accordion

David


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Chas Emerick  
View profile  
 More options Feb 3 2010, 1:05 pm
From: Chas Emerick <cemer...@snowtide.com>
Date: Wed, 3 Feb 2010 13:05:06 -0500
Local: Wed, Feb 3 2010 1:05 pm
Subject: Re: [enlive] Re: Looping Case Question

On Feb 3, 2010, at 11:18 AM, David Nolen wrote:

> Just out of curiosity, is this really a common case?  In my  
> (admittedly limited) experience, if one is looking to emit repeated  
> sequences of elements as described, then the CSS is going to almost  
> certainly need some container around each such sequence anyway.  Is  
> this less universal than I suspect?

> You don't need a container to style repeating elements with CSS.  
> I've seen this pattern a lot in PHP as well as in Django templates.  
> I've been handed markup that looks this from designers as well. Many  
> JavaScript accordions expect this pattern.

> http://docs.jquery.com/UI/Accordion

Thanks very much for the clarification and reference.

- Chas


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Christophe Grand  
View profile  
 More options Feb 4 2010, 2:21 pm
From: Christophe Grand <christo...@cgrand.net>
Date: Thu, 4 Feb 2010 20:21:06 +0100
Local: Thurs, Feb 4 2010 2:21 pm
Subject: Re: [enlive] Re: Looping Case Question
What about {[:h1] [:p]} to denote the extent/slice selector?

In this html snippet: <div><h1>title</h1><p>p1</p><p>p2</p></div> do
you think that  {[:h1] [:p]} should select:
* <h1>title</h1><p>p1</p>
* <h1>title</h1><p>p1</p><p>p2</p>
* both

Right now my vote is on the first choice as it seems the least surprising.

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

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
David Nolen  
View profile  
 More options Feb 4 2010, 2:42 pm
From: David Nolen <dnolen.li...@gmail.com>
Date: Thu, 4 Feb 2010 14:42:01 -0500
Local: Thurs, Feb 4 2010 2:42 pm
Subject: Re: [enlive] Re: Looping Case Question

On Thu, Feb 4, 2010 at 2:21 PM, Christophe Grand <christo...@cgrand.net>wrote:

> What about {[:h1] [:p]} to denote the extent/slice selector?

> In this html snippet: <div><h1>title</h1><p>p1</p><p>p2</p></div> do
> you think that  {[:h1] [:p]} should select:
> * <h1>title</h1><p>p1</p>
> * <h1>title</h1><p>p1</p><p>p2</p>
> * both

> Right now my vote is on the first choice as it seems the least surprising.

What about a greedy option?

{[:h1] [:p]} defaults to not greedy

{[:h1] [:p] :greedy true}

Or something more elegant to describe the greedy option?

David


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Christophe Grand  
View profile  
 More options Feb 4 2010, 3:33 pm
From: Christophe Grand <christo...@cgrand.net>
Date: Thu, 4 Feb 2010 21:33:07 +0100
Local: Thurs, Feb 4 2010 3:33 pm
Subject: Re: [enlive] Re: Looping Case Question

It's a possibility but I'd like to pick a single option for the moment
and see if the need for the other arises.
Note that {[:h1] [:p] :greedy true} can be written {[:h1] [[last-of-type :p]]}

So, do you have a strong opinion on which option to choose?

Christophe


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
David Nolen  
View profile  
 More options Feb 4 2010, 3:42 pm
From: David Nolen <dnolen.li...@gmail.com>
Date: Thu, 4 Feb 2010 15:42:31 -0500
Local: Thurs, Feb 4 2010 3:42 pm
Subject: Re: [enlive] Re: Looping Case Question

On Thu, Feb 4, 2010 at 3:33 PM, Christophe Grand <christo...@cgrand.net>wrote:

> It's a possibility but I'd like to pick a single option for the moment
> and see if the need for the other arises.
> Note that {[:h1] [:p] :greedy true} can be written {[:h1] [[last-of-type
> :p]]}

Great, works for me.

> So, do you have a strong opinion on which option to choose?

+1 for the 1st option.

David


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Christophe Grand  
View profile  
 More options Feb 5 2010, 2:39 pm
From: Christophe Grand <christo...@cgrand.net>
Date: Fri, 5 Feb 2010 20:39:52 +0100
Local: Fri, Feb 5 2010 2:39 pm
Subject: Re: [enlive] Re: Looping Case Question
It occurred to me there already exists a commonly used term for what
{[:h1] [:p]} denotes: a fragment!

I created a kind of todo list: http://wiki.github.com/cgrand/enlive/whats-next


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »