Blogs / Henrik Gren / Building a left menu

Building a left menu

Wednesday 26 January 2011 6:42:01 am

  • Currently 4 out of 5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

By : Henrik Gren

Since the left menu is a fairly common feature of any site, in particular those corporate, I thought I could give an example of how this can be done. The level is clearly beginner, but as such it could save many hours of headache especially for somebody at terms with a first eZ project, thus flattening a little the famous steep learning curve of eZ Publish. :)

Our imaginary site is organised in a classic fashion:

Home

  • Subhome 1
    • Article 1
    • Article 2
    • Article 3
    • Article 4
  • Subhome 2
    • Article 5
  • Subhome n
    • Article n
  • Footer
    • Who we are
    • Contact us
    • Legal notice
    • Etc

Let us imagine a situation where we have navigated to Article 2. Here we want the menu to look like this:

----------------

Menu

  • Article 1
  • Article 2
  • Article 3
  • Article 4

--

Contacts

Link to anchor on who we are

Link to contact us

--

Documents

Downloadable documents related to the article

--

Related sections

Links to related sections

----------------

I will walk you through the reasoning behind and the creation of all these items.

Menu

These are links to the articles under the subhome where we currently are. Additionally, we are reading Article 2, so we want that particular menu item look a little different.

For the purpose of this menu we use the built-in treemenu function of eZ. The code goes like this:

<div id="leftmenu_top"> 
    <ul id="navigation"> 
      {def $leftMenu=treemenu( $module_result.path, ,array('subhome_type1','subhome_type2', 'article_type1', 'gallery'), 1, 1 )}
         {foreach $leftMenu as $menu}
             <li><a href={$menu.url_alias|ezurl}{if $menu.is_selected} class="current"{/if}>{$menu.text}</a></li>
         {/foreach}
    </ul>
</div>

I included some html tags that will probably be useful, when identified in your style sheet. Apart from that, note that the array in the treemenu definition contains the class identifiers of all the content items where you want this particular menu to appear. Then there is the little trick to make the menu item of the current node look different: You define a different style in your style sheet and tells the template to apply this style if that is the case (class="current).

Manually assigned navigation

Then, in order to represent a quite common scenario, let's assume that the navigation menu we just coded is the only mandatory part of the left menu. The contacts, documents and related sections could be optional. Furthermore, for some articles the contacts could contain just the link to the contact us page if there is no related email address to the article shown in the who we are page.

Did you follow that? Good! Here comes the code. The conditions could probably be written in a more elegant way. I know. But I will let somebody else improve on that part.

{def $thesecontacts=concat($node.class_identifier, '/contacts')}
{def $relatedcontactscount=fetch('content', 'related_objects_count', hash('object_id', $node.contentobject_id, 'attribute_identifier', $thesecontacts))}
{if gt($relatedcontactscount,0)}
{def $contacts=1}
{def $leftnav=1}
{/if}
{if is_set($this_node.data_map.contact_us.content)}
{def $contactus=1}
{def $leftnav=1}
{/if}
{def $thesedocuments=concat($this_node.class_identifier, '/documents')}
{def $relateddocumentscount=fetch('content', 'related_objects_count', hash('object_id', $this_node.contentobject_id, 'attribute_identifier', $thesedocuments))}
{if gt($relateddocumentscount,0)}
{def $leftnav=1}
{def $docs=1}
{/if}
{def $thesesections=concat($this_node.class_identifier, '/related_sections')}
{def $relatedsectionscount=fetch('content', 'related_objects_count', hash('object_id', $this_node.contentobject_id, 'attribute_identifier', $thesesections))}
{if gt($relatedsectionscount,0)}
{def $leftnav=1}
{def $sections=1}
{/if}

In order for this to work we need to define the attributes in the class from which Article 2 is created. So we have four custom fields:

  • contacts related objects
  • contact_us related object
  • documents related objects
  • related_sections related objects

All fields are optional and they could contain one or more attachments, except for contact_us that contains zero or one link (which is logical since it would not have sense linking to more than one contact form).

The code for the related objects attributes are all the same: Construct the name of the attribute and check how many relations there are in each. If the number is greater than zero, set a flag that later will tell eZ to print out the box. Note here that we also have a second flag (leftnav). I included it in the likely case the page should look a little different if there is no related object at all (for instance there could be an image background or some sort of a frame around the whole thing that would be useless if there as nothing to fill it with).

Next comes the nifty part that prints the result. It is quite straightforward, but it contains one real goodie, namely the howto present a link to a related document in the most common fasihon: Document_name.pdf 2,65 MB. I spent days on the forum to get my hands on this one. It was so well hidden that I cannot find the post anymore. An advice: If you want your downloadable document presented this way in eZ Publish, don't look any further. There is no other way. So, here comes the last code snippet of today:

{if eq($leftnav,1)}
    <div id="leftnav_module"> 
        <div class="top"></div>
{if or(eq($contacts,1), eq($contact_us,1))}
{def $notop=1}
           <h3 class="notop">CONTACTS</h3>        
{if eq($contacts,1)}
    <p>{attribute_view_gui attribute=$this_node.data_map.contacts}</p> 
{/if}
{if eq($contact_us,1)}
    <p>{attribute_view_gui attribute=$this_node.data_map.contact_us}</p>
{/if}
{/if}
{if eq($docs,1)}
{if eq($notop,1)}
             <h3>DOCUMENTS</h3>
{else}
{def $notop=1}
             <h3 class="notop">DOCUMENTS</h3>
{/if}
{def $relateddocuments=fetch('content', 'related_objects', hash('object_id', $this_node.contentobject_id, 'attribute_identifier', $thesedocuments))}
{foreach $relateddocuments as $related}
                <p><a href={concat("content/download/",$related.data_map.file.contentobject_id,"/",$related.data_map.file.id,"/file/",$related.data_map.file.content.original_filename|urlencode)|ezurl}>{$related.data_map.file.content.original_filename|wash(xhtml)} {$related.data_map.file.content.filesize|si(byte)}</a></p>
{/foreach}
{/if}
{if eq($sections,1)}
{if eq($notop,1)}

            <h3>RELATED SECTIONS</h3>
{else}
            <h3 class="notop">RELATED SECTIONS</h3>
{/if}
                    <p>{attribute_view_gui attribute=$this_node.data_map.related_sections}</p> 
{/if}
            <div class="bottom"></div> 
        </div>
{/if} 
        <div class="clear"></div> 
    </div>

I included some HTML that might be useful to you. The div tags serve you in order to orgnanise your left column with your style sheet. The idea is the typical image at the top and the bottom, expanding in the middle behind each menu item or H3 headline (the notop class and tag say that if there was no previous box, this particular box will be the first and it will look a little different).

Well guys, I hope I explained something useful regarding left menu, related objects and downloadable documents.

If you didn't follow, you can just copy the code, eliminate the HTML and everything will work.

Ciao!

Blog Post Discussion

Building a left menu