tags:

views:

202

answers:

4

My navigation is written in the layout.php template

It looks like this:

<ul id="nav">
  <li><a href="item1">Item 1</a></li>
  <li><a href="item1">Item 2</a></li>
  <li><a href="item1">Item 3</a></li>
  <li><a href="item1">Item 4</a></li>
</ul>

What is the best way to get a class="current" on the currently selected page?

+2  A: 

Use a helper and/or a partial to generate the menu. So lets say you have a partial _navigation.php in the module 'default':

// in layout:

<?php include_partial('default/navigation', array(
   'navigation'=>$array, 
   'active'=>has_slot('navigationActiveUrl') 
       ? get_slot('navigationActiveUrl') 
       : null)
 ); ?>

// in modules/default/templates/_navigation.php
<?php if(isset($navigation)): ?>
  <ul>
    <?php foreach($navigation as $name => $url): ?>
       <?php echo content_tag('li', link_to($name, $url), array('class' => 
         (isset($active) && $active == $url ? 'active' : null)
       )); ?>
    <?php endforeach; ?>
  </ul>
<?php endif; ?>

// in some template file:
<?php slot('navigationActiveUrl'); ?>/internal/uri<?php end_slot(); ?>

you could also just use a helper and hard code the html in there if you wont need to modify it much. using a partial simply gives you an easy way to change the markup without changing the helper function. Like wise you could make a helper function and still have it call the same partial.

prodigitalson
This requires a lot of slots in templates, which can be tedious to write for large websites. Consider instead using a component for nav and using the `preExecute()` methods in `actions.class.php` for modules to specify a `$this->nav_section` default for that module, which is passed to the component in the layout: `<?php include_component('navigation/topnav', array('nav_section' => $nav_section)); ?>`. If one or more actions in your `actions.class.php` needs a custom `$nav_section` you can simply add it to that `executeAction()` method as it will supercede the declaration in `preExecute()`
Raise
There are several ways to do this ultimately, and depending on the complexity of your nav you can choose slots, components or component slots to do this more elegantly.
Raise
Hi Raise, is there any chance you could turn your comment into an alternative answer? Thanks!
Jon Winstanley
+1  A: 

An alternative method you should consider is using JavaScript if possible. I'm going to give an example using jQuery

$('#nav li a').each(function(){
  //You might have to do some string manipulation on the line below, but you get the idea
  if($(this).attr('href') == window.location.pathname) { $(this).addClass('current'); }; 
});

I know JS is not always an option, but it works out pretty neatly and nicely. Wild guess: The rest of your php code will not care whether the link has the selected class or not, only your css or javascript code will. If this is the case, the above method isn't really a bad option

sjobe
+1  A: 

I go for a simpler approach (but it may be more resource intensive):

<ul id="nav">
  <li<?php echo ($this->getActionName('item1')) ? ' class="current"' : ''; ?>><a href="item1">Item 1</a></li>
  <li<?php echo ($this->getActionName('item2')) ? ' class="current"' : ''; ?>><a href="item1">Item 2</a></li>
  <li<?php echo ($this->getActionName('item3')) ? ' class="current"' : ''; ?>><a href="item1">Item 3</a></li>
  <li<?php echo ($this->getActionName('item4')) ? ' class="current"' : ''; ?>><a href="item1">Item 4</a></li>
</ul>
Patrick
Consider `$this->getModuleName()` and combinations of this with `$this->getActionName()` too. The only downside is a lack of cache advantage by pushing this all into the layout. You can work around this though :)
Raise
A: 

i always use slot() and is_slot to mark tabs as selected.

On each page i display in the template i 'mark' the page with a slot with the slots name

/projects -> slot('toptabs') projects end_slot() and put

if get_slot('toptabs') == 'projects' { class="selected" }

stupid solution but is quick and works fine.

Alon