add "active" class to menus <li> tags in addition to <a>

barneson - June 12, 2005 - 03:53
Project:PHPTemplate
Component:Code
Category:feature request
Priority:normal
Assigned:Unassigned
Status:closed
Description

I would like to use the Sliding Doors technique documented at http://www.alistapart.com/articles/slidingdoors2/, but to fully realize the effect, the <li> tag containing the <a class="active"> containing the active menu item must also be marked with some sort of class or id.

My request is, then, that the phptemplate primary and secondary links code produces markup something like this:

<ul>
<li class="active"><a class="active" href="#">home</a>
<li><a href="#">page2</a>
<li><a href="#">page3</a>
<li><a href="#">page4</a>
<li><a href="#">page5</a>
</ul>

Note that both the <li> and <a> elements of the current page have the class="active" attribute.

#1

eferraiuolo - July 20, 2005 - 15:55

I am trying to attempt the exact same thing, using the sliding-doors approach to create a tabbed primary links. I submitted a support request (http://drupal.org/node/26846) to try to find a way to override PHPTemplate's functions to create the primary links.

Hopefully we can get this feature/issue worked out, as sliding-doors is an effective way to create a nice tabbed navigation.

#2

beley - July 23, 2005 - 00:22

What was found out about this? I know it can be done in some way becaue ubuntu.com's top navigation sets the current section to a different class than the other tabs.

Any idea how to accomplish this w/ Drupal?

#3

eferraiuolo - July 26, 2005 - 13:32

beley,

Good call on pointing out http://www.ubuntu.com this is exactly the result I am after. Some more information about this is posted in an issue support request I started, but still no exact solution on how to make primary links behave like http://www.ubuntu.com

Here is the link to another issue with the same topic:
http://drupal.org/node/26846

I would like to sort this out and figure out how we can make this type of Primary Links navigation work; maybe if all of us that are waiting for these support issues to be resolved work together we might be able to find a good working solution without hacking but using APIs.

Eric

#4

adrian - July 26, 2005 - 13:45

Edit your template where it says :

<?php
   
<?php if (count($primary_links)) :
?>

    <?php
    foreach ($primary_links as $link):
    ?>
  • <?php
    print $link
    ?>
  • <?php
    endforeach;
    ?>

<?php
endif;
?>

?]

And turn it into :

<?php
  
<ul id="primary">
     <?
php foreach ($primary_links as $link):
?>

  • <?php
    print $link
    ?>
  • <?php
    endforeach;
    ?>

    <?php
    endif;
    ?>

    ?]

    #5

    adrian - July 26, 2005 - 13:51

    i hate this stupid php filter.

    Anyway... i attached the solution as a text file.

    AttachmentSize
    example_0.txt 521 bytes

    #6

    eferraiuolo - July 27, 2005 - 07:18

    adrian and to all,

    I tried you code and it didn't work. But that didn't stop me; from what you posted I could see what you were trying to do and where your code failed. variable $path isn't defined and all we have to work with is the variable $link, which is a string that contains the whole XHTML a href tag. Not being familiar with PHP but with a background in C++ the built-in PHP string functions were my friend. I have found a way to solve my issue two ways; first by adding the class="active" attribute to the LI element which holds the ANCHOR element link, the other way is to add a SPAN element around the text for the hyperlink. I feel the second way is superior as no JavaScript is needed for IE. This way when using the SlidingDoors technique to make a tabbed navigation the SPAN provides an extra hook for CSS styles, and since its nested under the ANCHOR element IE can handle the hover state for the tab. Below are the working code samples I came up with:

    Insert class="active" attribute into the LI element containing the Primary Link with the class="active" attribute:

    <!-- START Main Navigation -->
    <?php if(is_array($primary_links)): ?>
    <ul class="noPrint" id="mainNavigation">

    <?php foreach ($primary_links as $link): ?>
    <?php $link_path = substr($link, strpos($link, '"')+1, strpos($link, '"', strpos($link, '"')+1)-strpos($link, '"')-1) ?>
    <li<?php print (drupal_get_normal_path($link_path) == $_GET['q']) ? ' class="active"' : '' ?>><?php print $link ?></li>
    <?php endforeach; ?>

    </ul>
    <?php endif; ?>
    <!-- END Main Navigation -->

    Example output:
    <!-- START Main Navigation -->
    <ul class="noPrint" id="mainNavigation">
    <li class="active"><a href="" class="active">Home</a></li>
    <li><a href="about">About</a></li>
    <li><a href="contact">Contact</a></li>
    </ul>
    <!-- END Main Navigation -->

    Insert SPAN element into all Primary Links hyperlinked text:

    <!-- START Main Navigation -->
    <?php if(is_array($primary_links)): ?>
    <ul class="noPrint" id="mainNavigation">

    <?php foreach ($primary_links as $link): ?>
    <li><?php print substr($link, 0, strpos($link, '>')+1) . "<span>" . substr($link, strpos($link, '>')+1, strrpos($link, "<")-strpos($link, '>')-1) . '</span></a>' ?></li>
    <?php endforeach; ?>

    </ul>
    <?php endif; ?>
    <!-- END Main Navigation -->

    Example output:
    <!-- START Main Navigation -->
    <ul class="noPrint" id="mainNavigation">
    <li><a href="" class="active"><span>Home</span></a></li>
    <li><a href="about"><span>About</span></a></li>
    <li><a href="contact"><span>Contact</span></a></li>
    </ul>
    <!-- END Main Navigation -->

    I hope others that run into this limitation of theming Drupal find this useful to create a tab-styled navigation with Primary Links.

    #7

    micha_1977 - July 27, 2005 - 08:01

    you could make this in a more central way within the template.php
    example can be seen at the frontpage of http://www.langmi.de

    <?php
         
    /**
            * customized primary links
            * - see <a href="http://www.stunicholls.myby.co.uk/menus/snazzymenu2.html" title="http://www.stunicholls.myby.co.uk/menus/snazzymenu2.html" rel="nofollow">http://www.stunicholls.myby.co.uk/menus/snazzymenu2.html</a> for more info on this link design
            */
         
    foreach (array('primary') as $type) {

           
    //Get the data to populate the textfields, if the variable is not an array .. try to parse the old-style link format.     
           
    $value = variable_get('phptemplate_' . $type . '_links', array());

           
    //Get the amount of links to show, possibly expanding if there are more links defined than the count specifies

           
    $count = variable_get('phptemplate_' . $type . '_link_count', 5);
           
    $count = ($count > sizeof($value['link'])) ? $count : sizeof($value['link']);

            if (
    theme_get_setting('toggle_' . $type . '_links')) {
              for (
    $i =0; $i < $count; $i++) {
                unset(
    $attributes);
                if (!empty(
    $value['text'][$i])) {
                  if (!empty(
    $value['description'][$i])) {
                   
    $attributes['title'] = $value['description'][$i];
                  }
                 
    $text = $value['text'][$i];
                 
    $link = $value['link'][$i];           
                 
    // the original from phptemplate.engine changed to catch the produced links
                 
    if (substr($link, 0, 4) == 'http') {
                   
    $_templink = '<a href="'. $link .'"'. drupal_attributes($attributes) .'>'. $text .'</a>';
                  }
                  else {
                 
    $_templink = l($text, $link, $attributes);
                  }
                 
    // reproduced "l" function from includes/common.inc to get the active link, only for "primary links"
                  // classes are set acccording to my style.css, $classtext is needed for additional css logic
                 
    if ($type == 'primary') {
                    if (
    drupal_get_normal_path($link) == $_GET['q']) {
                      isset(
    $attributes['class']) ? $attributes['class'] .= ' active' : $attributes['class'] = 'active';
                     
    $classtext = 'darkblue';
                    }
                    else { 
                      isset(
    $attributes['class']) ? $attributes['class'] .= ' notactive' : $attributes['class'] = 'notactive';
                     
    $classtext = 'lightblue';
                    }
                   
    $_templink = '<a href="'. $link .'" class="menu"><b class="snazzy"><span class="boxcontent '. $attributes['class'] .'">'. $text .'</span><b class="b4 '.$classtext.'"></b><b class="b3 '.$classtext.'"></b><b class="b2 '.$classtext.'"></b><b class="b1"></b></b></a>';
                  }
                 
    $links[$type][] = $_templink;             
                }
              }
            }
           
    $vars['customized_type1_links']= $links['primary'];
          }
    ?>

    #8

    micha_1977 - July 27, 2005 - 08:05

    for the example above

    <?php
    function _phptemplate_variables($hook, $vars) {
       if (
    $hook =='page') {
         ...
    the foreach function from above
      
    }
     
    // calling function expects an array
     
    if (empty($vars)) {
       
    $vars = array();
      }
      return
    $vars;
    ?>

    #9

    micha_1977 - July 27, 2005 - 08:10

    *sigh* i need an edit function :)

    just wanted to say, that its easy to add any additional html code to the links
    you could even produce a complete primary_links block with <ul> or <div>

    #10

    adrian - July 27, 2005 - 10:11

    I have committed a new version of phptemplate for 4.6 that does one thing new , it sets the key to each of the primary secondary links as the $link.

    with this version, you will be able to do the following in the attached text file.

    I am only patching 4.6 with this, as this code will be completely removed from 4.7 .. very soon now.

    AttachmentSize
    example_1.txt 530 bytes

    #11

    eferraiuolo - July 27, 2005 - 15:06

    This got me wondering, which way of doing this is better? By better I mean the norm, or best practices of drupal. To add one attribute or SPAN tag to elements integreated with the Primary Links is it work overriding the whole function in the template.php? Or is the approach I used with keeping everything in the page.tpl.php fine and comply with how things are done with Durpal?

    When looking at it, there are alot more lines of code that need to be executed when overridding functions, but I got everything in 1 or 2 lines when searching for chars, breaking up a string and putting it back together in the page.tpl.php.

    I want to do things the right way and stay strict with the normal development practices of Drupal. If overriding functions is the "proper" way to handle this feature and the execution of more lines of code isn't a big factor then I'll work on implementing a template.php

    Just courious on your thoughts.

    #12

    micha_1977 - August 10, 2005 - 08:52

    there just cant be a "one rules them all" solution

    e.g. for my own example i need more than just the "active" info, not to mention that "active" does not work (easily) for the basic node view (to which primary link does this node belong to ?)

    so think its good to add some more info to the links, but not more html ... html is presentation and the presentation layer is up to the template

    #13

    Bèr Kessels - November 9, 2005 - 16:55
    Status:active» fixed

    in HEAD we use menus to render these links. You can now do this with a simple theme function!

    #14

    Anonymous - November 23, 2005 - 17:00
    Status:fixed» closed
     
     

    Drupal is a registered trademark of Dries Buytaert.