Building a left menu

Wednesday 26 January 2011 6:42:01 am

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!

Powered by eZ Publish™ CMS Open Source Web Content Management. Copyright © 1999-2014 eZ Systems AS (except where otherwise noted). All rights reserved.

eZ debug

Timing: Jan 18 2025 01:16:40
Script start
Timing: Jan 18 2025 01:16:40
Module start 'layout'
Timing: Jan 18 2025 01:16:40
Module start 'content'
Timing: Jan 18 2025 01:16:40
Module end 'content'
Timing: Jan 18 2025 01:16:40
Script end

Main resources:

Total runtime0.1132 sec
Peak memory usage6,144.0000 KB
Database Queries42

Timing points:

CheckpointStart (sec)Duration (sec)Memory at start (KB)Memory used (KB)
Script start 0.00000.0056 587.8906152.6094
Module start 'layout' 0.00560.0036 740.500039.4219
Module start 'content' 0.00920.1026 779.9219432.1016
Module end 'content' 0.11180.0014 1,212.023419.7031
Script end 0.1132  1,231.7266 

Time accumulators:

 Accumulator Duration (sec) Duration (%) Count Average (sec)
Ini load
Load cache0.00302.6647150.0002
Check MTime0.00121.0873150.0001
Mysql Total
Database connection0.00070.618210.0007
Mysqli_queries0.036432.1849420.0009
Looping result0.00030.2693400.0000
Template Total0.080571.120.0403
Template load0.00201.789220.0010
Template processing0.078569.295020.0392
Template load and register function0.00010.076810.0001
states
state_id_array0.00131.186810.0013
state_identifier_array0.00141.200920.0007
Override
Cache load0.00191.71401200.0000
Sytem overhead
Fetch class attribute name0.00171.537630.0006
class_abstraction
Instantiating content class attribute0.00000.005130.0000
General
dbfile0.00060.5464100.0001
String conversion0.00000.009540.0000
Note: percentages do not add up to 100% because some accumulators overlap

Templates used to render the page:

UsageRequested templateTemplateTemplate loadedEditOverride
1node/view/full.tplblog_entry/full.tplextension/community_design/design/suncana/override/templates/blog_entry/full.tplEdit templateOverride template
2content/datatype/view/ezxmltext.tpl<No override>extension/community_design/design/suncana/templates/content/datatype/view/ezxmltext.tplEdit templateOverride template
22content/datatype/view/ezxmltags/paragraph.tpl<No override>extension/ezwebin/design/ezwebin/templates/content/datatype/view/ezxmltags/paragraph.tplEdit templateOverride template
26content/datatype/view/ezxmltags/emphasize.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/emphasize.tplEdit templateOverride template
22content/datatype/view/ezxmltags/li.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/li.tplEdit templateOverride template
7content/datatype/view/ezxmltags/ul.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/ul.tplEdit templateOverride template
15content/datatype/view/ezxmltags/strong.tpl<No override>design/standard/templates/content/datatype/view/ezxmltags/strong.tplEdit templateOverride template
3content/datatype/view/ezxmltags/literal.tpl<No override>extension/community/design/standard/templates/content/datatype/view/ezxmltags/literal.tplEdit templateOverride template
1content/datatype/view/ezkeyword.tpl<No override>extension/community_design/design/suncana/templates/content/datatype/view/ezkeyword.tplEdit templateOverride template
1print_pagelayout.tpl<No override>extension/community/design/community/templates/print_pagelayout.tplEdit templateOverride template
 Number of times templates used: 100
 Number of unique templates used: 10

Time used to render debug report: 0.0001 secs