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
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
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
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
Edit your template where it says :
<?php
<?php if (count($primary_links)) :
?>
<?phpforeach ($primary_links as $link):
?>
<?phpprint $link
?>
<?phpendforeach;
?>
<?phpendif;
?>
?]
And turn it into :
<?php<ul id="primary">
<?php foreach ($primary_links as $link):
?>
<?phpprint $link
?>
<?phpendforeach;
?>
<?phpendif;
?>
?]
#5
i hate this stupid php filter.
Anyway... i attached the solution as a text file.
#6
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
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
for the example above
<?phpfunction _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
*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
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.
#11
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
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
in HEAD we use menus to render these links. You can now do this with a simple theme function!
#14