Conditional loops

Hi folks,

I’ve finally managed to find a not-too-inelegant solution to a problem I’ve encountered quite a bit recently and though I’d post it here to see if anyone has any suggestions that might improve it.

The problem is this: most of our projects built using have hierarchical menu structures and designs that require generating navigation menus listing each ‹ sector › and the sub-menu for the current sector. An example might help clarify my meaning.

  1. Home
  2. Stores
  3. Events
    3.1. Current Events

3.2. Events Archive

  1. Contact

Might result in the following code being generated on the « Stores » page:

and the following code on the « Events » page, or a sub-page:

My current solution uses #SET, #GET, |==, and |? to remember the « exposed » #ID_RUBRIQUE and compare it with the current rubrique in the outer loop:

#SET{curr, #ENV{id_rubrique}}

<BOUCLE_nav(RUBRIQUES){id_parent=0}{par num titre}{1,n}>
#SET{sub, #ID_RUBRIQUE|=={#GET{curr}}|?{#ID_RUBRIQUE, -1}}
// …

#GET{sub} is now either -1 or the #ID_RUBRIQUE of the current rubrique (which is also the « exposed » rubrique).

Then when it comes time to generate the submenu I loop over the rubriques where id_parent=#GET{sub}. As #GET{sub} is -1 when we shouldn’t display the sub-menu and is the correct id_parent otherwise, the loop only has output when it ‹ should ›.

// …

// …

With appropriate <B_foo> tags, this works and even generates decent mark-up. It’s certainly better than what I’ve been doing until now (using #EXPOSE to comment out the unnecessary sub-menu HTML), but it strikes me as a bit of a « hack ». Does anyone have any suggestions for improvement or alternate techniques?

If my slight misgivings are mistaken, would it be useful to have a short article describing it (a complement to the « Highlighting an item in a list » article about #EXPOSE on SPIP.net, perhaps).

Regards,

Thomas Sutton
Web Developer
bouncingorange
graphic + web design

Hi,

of source you can !!
Your solution is elegant because it doesn't generate non-visible code,
I like it

Personnaly, I have a different approach :

I generally choose to generate the whole menu and hide/display
sub-menus with #EXPOSE.
I think that it's better for referencing the content of the site,
because it increases the number of internal links.
I don't use comments, but simply a little CSS class defined like this
.hiddeMe {display:none}

and my code looks like :

<B_nav>
  <ul>
<BOUCLE_nav(RUBRIQUES){id_parent=0}{par num titre}>
     <li>#TITRE
     <B_submenu>
        <ul class="#EXPOSE{,hiddeMe}">
     <BOUCLE_submenu(RUBRIQUES){id_parent}{par num titre}>
            <li> ... </li>
     </BOUCLE_submenu>
       </ul>
     <B_submenu>
     </li>
</BOUCLE_nav>
  </ul>
</B_nav>

For more than 1 sub-menu level, I add a recursive loop inside (on
BOUCLE_submenu).

When I really doesn't want to generate non-displaid sub-menus, I use a
separate template that is inserted (or not) with spip comments :

<B_nav>
  <ul>
<BOUCLE_nav(RUBRIQUES){id_parent=0}{par num titre}>
     <li>#TITRE
[(#EXPOSE{' ',''})
    [(#INCLURE{fond=inc/sub_menu}{env})]
]
     </li>
</BOUCLE_nav>
  </ul>
</B_nav>

So that makes 3 different "design patterns" for a pb :
This is ideal for an article because it introduces a lot of concepts :
- #GET / #SET
- operators
- #EXPOSE
- spip comments
- recursive loops
- inclusion of a template (statically or dynamically)

I think you should write it on spip-contrib.net, there is a lack of
examples here.
I can help you if you want.

And other people on this list certainly use other solutions too !!

.Gilles

--

.Gilles
---

On Jan 17, 2008 9:22 AM, Thomas Sutton <thomas@bouncingorange.com> wrote:

Hi folks,

I've *finally* managed to find a not-too-inelegant solution to a problem
I've encountered quite a bit recently and though I'd post it here to see if
anyone has any suggestions that might improve it.

The problem is this: most of our projects built using have hierarchical menu
structures and designs that require generating navigation menus listing each
'sector' and the sub-menu for the current sector. An example might help
clarify my meaning.

1. Home
2. Stores
3. Events
3.1. Current Events
3.2. Events Archive
4. Contact

Might result in the following code being generated on the "Stores" page:

<ul>
<li><a href="-Home-.html">Home</a></li>
<li><span>Stores</span></li>
<li><a href="-Events-.html">Events</a></li>
<li><a href="-Contact-.html">Contact</a></li>
</ul>

and the following code on the "Events" page, or a sub-page:

<ul>
<li><a href="-Home-.html">Home</a></li>
<li><a href="-Stores-.html">Stores</a></li>
<li>
<span>Events</span>
<ul>
<li><a href="-Current-Events-.html">Current Events</a></li>
<li><a href="-Events-Archive-.html">Events Archive</a></li>
</ul>
</li>
<li><a href="-Contact-.html">Contact</a></li>
</ul>

My current solution uses #SET, #GET, |==, and |? to remember the "exposed"
#ID_RUBRIQUE and compare it with the current rubrique in the outer loop:

#SET{curr, #ENV{id_rubrique}}
<BOUCLE_nav(RUBRIQUES){id_parent=0}{par num titre}{1,n}>
#SET{sub, #ID_RUBRIQUE|=={#GET{curr}}|?{#ID_RUBRIQUE, -1}}
// ...

#GET{sub} is now either -1 or the #ID_RUBRIQUE of the current rubrique
(which is also the "exposed" rubrique).

Then when it comes time to generate the submenu I loop over the rubriques
where id_parent=#GET{sub}. As #GET{sub} is -1 when we shouldn't display the
sub-menu and is the correct id_parent otherwise, the loop only has output
when it 'should'.

// ...

<ul><BOUCLE_sub(RUBRIQUES){id_parent=#GET{sub}}{par num titre}>
<li id="sect#ID_RUBRIQUE"><a
href="#URL_RUBRIQUE">[(#TITRE|supprimer_numero)]</a></li></BOUCLE_sub>
</ul>
// ...

With appropriate <B_foo> tags, this works and even generates decent mark-up.
It's certainly better than what I've been doing until now (using #EXPOSE to
comment out the unnecessary sub-menu HTML), but it strikes me as a bit of a
"hack". Does anyone have any suggestions for improvement or alternate
techniques?

If my slight misgivings are mistaken, would it be useful to have a short
article describing it (a complement to the "Highlighting an item in a list"
article about #EXPOSE on SPIP.net, perhaps).

Regards,

Thomas Sutton
Web Developer
bouncingorange
graphic + web design
_______________________________________________
spip-en@rezo.net - http://listes.rezo.net/mailman/listinfo/spip-en

Hi Thomas,

this is a presentation that seems "natural" to do and is sadly not straightforward in SPIP loops.

I had solved the problem for:
http://www-users.cs.york.ac.uk/~suresh/
before the GET and SET where introduced.
There is an article in French about the solution I found on spip-contrib:

The idea is the following:
1- BOUCLE_menu loops over all top level sections
2- BOUCLE_current checks if the section we are visiting is subsumed by the current section, and if it's the case:
   a- BOUCLE_hier shows the path to the section level and open li ul that are needed (this is needed if we have more than 2 levels of sections)
   b- BOUCLE_sister_before shows all sibling sections that should go before the current section
   c- show the current section with subsections (BOUCLE_sub_rub)
   d- BOUCLE_sister_after show all sibling sections that come after the current section
   e- BOUCLE_hier_close close the li ul of the path we created
3- if it's not subsumed by the current section, show only the title of the top level section.

Here is the code:
<div id="menu">

<B_menu>
<ul id="sections">
<BOUCLE_menu(RUBRIQUES) {par num titre}{racine}>
<BOUCLE_current(RUBRIQUES) {id_rubrique=#ENV{id_rubrique}} {id_secteur}>
<BOUCLE_hier(HIERARCHIE) {id_rubrique}>
<li><a href="#URL_RUBRIQUE" title="#DESCRIPTIF">[(#TITRE|supprimer_numero)]</a><ul>
</BOUCLE_hier>
<BOUCLE_sister_before(RUBRIQUES) {meme_parent} {par num titre} {titre<=#TITRE} {exclus}>
<li><a href="#URL_RUBRIQUE" title="#DESCRIPTIF">[(#TITRE|supprimer_numero)]</a></li>
</BOUCLE_sister_before>
</B_hier>

<li><a href="#URL_RUBRIQUE" title="#DESCRIPTIF" [class="(#EXPOSE{current})"]>[(#TITRE|supprimer_numero)]</a>

<B_sub_rub>
<ul>
<BOUCLE_sub_rub(RUBRIQUES) {id_parent}>
<li><a href="#URL_RUBRIQUE" title="#DESCRIPTIF">[(#TITRE|supprimer_numero)]</a></li>
</BOUCLE_sub_rub>
</ul>
</B_sub_rub>
</li>

<B_hier_close>
<BOUCLE_sister_after(RUBRIQUES) {meme_parent} {par num titre} {titre>#TITRE} {exclus}>
<li><a href="#URL_RUBRIQUE" title="#DESCRIPTIF">[(#TITRE|supprimer_numero)]</a></li>
</BOUCLE_sister_after>
<BOUCLE_hier_close(HIERARCHIE) {id_rubrique}>
</ul></li>
</BOUCLE_hier_close>
</BOUCLE_current>
<li><a href="#URL_RUBRIQUE" title="#DESCRIPTIF" [class="(#EXPOSE{current})"]>[(#TITRE|supprimer_numero)]</a></li>
<//B_current>
</BOUCLE_menu>
</ul>
</B_menu>

</div>

I am not really sure this is more elegant than the solution you have. It's a lot more loops though.
But, in your solution, I am not sure to see how it would deal with what BOUCLE_hier is doing. I.E. what would happen if the site has more than 1 sub-level? maybe putting the whole thing in a recursion would be enough.

You are welcome to submit your solution on spip-contrib in a short article explaining it. It's always good to have examples of uses and solutions to common problems.

Pierre

Thomas Sutton wrote:

Hi folks,

I've *finally* managed to find a not-too-inelegant solution to a problem I've encountered quite a bit recently and though I'd post it here to see if anyone has any suggestions that might improve it.

The problem is this: most of our projects built using have hierarchical menu structures and designs that require generating navigation menus listing each 'sector' and the sub-menu for the current sector. An example might help clarify my meaning.

1. Home
2. Stores 3. Events
3.1. Current Events
3.2. Events Archive
4. Contact

Might result in the following code being generated on the "Stores" page:

<ul>
<li><a href="-Home-.html">Home</a></li>
<li><span>Stores</span></li>
<li><a href="-Events-.html">Events</a></li>
<li><a href="-Contact-.html">Contact</a></li>
</ul>

and the following code on the "Events" page, or a sub-page:

<ul>
<li><a href="-Home-.html">Home</a></li>
<li><a href="-Stores-.html">Stores</a></li>
<li>
<span>Events</span>
<ul>
<li><a href="-Current-Events-.html">Current Events</a></li>
<li><a href="-Events-Archive-.html">Events Archive</a></li>
</ul>
</li>
<li><a href="-Contact-.html">Contact</a></li>
</ul>

My current solution uses #SET, #GET, |==, and |? to remember the "exposed" #ID_RUBRIQUE and compare it with the current rubrique in the outer loop:

#SET{curr, #ENV{id_rubrique}}
<BOUCLE_nav(RUBRIQUES){id_parent=0}{par num titre}{1,n}>
*#SET{sub, #ID_RUBRIQUE|=={#GET{curr}}|?{#ID_RUBRIQUE, -1}}*
// ...

#GET{sub} is now either -1 or the #ID_RUBRIQUE of the current rubrique (which is also the "exposed" rubrique).

Then when it comes time to generate the submenu I loop over the rubriques where id_parent=#GET{sub}. As #GET{sub} is -1 when we shouldn't display the sub-menu and is the correct id_parent otherwise, the loop only has output when it 'should'.

// ...
<ul><BOUCLE_sub(RUBRIQUES){*id_parent=#GET{sub}*}{par num titre}>
<li id="sect#ID_RUBRIQUE"><a href="#URL_RUBRIQUE">[(#TITRE|supprimer_numero)]</a></li></BOUCLE_sub>
</ul>
// ...

With appropriate <B_foo> tags, this works and even generates decent mark-up. It's certainly better than what I've been doing until now (using #EXPOSE to comment out the unnecessary sub-menu HTML), but it strikes me as a bit of a "hack". Does anyone have any suggestions for improvement or alternate techniques?

If my slight misgivings are mistaken, would it be useful to have a short article describing it (a complement to the "Highlighting an item in a list" article about #EXPOSE on SPIP.net, perhaps).

Regards,

Thomas Sutton
Web Developer
*bouncing*orange
/graphic/*/ + /*/web/*/ design/*