Add unique IDs to menu items
Last modified: August 25, 2009 - 02:44
This adds unique IDs (using the link's text) to any menu items so you can style them uniquely in your CSS.
In your template.php:
<?php
function phptemplate_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
$class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
if (!empty($extra_class)) {
$class .= ' '. $extra_class;
}
if ($in_active_trail) {
$class .= ' active-trail';
}
$id = preg_replace("/[^a-zA-Z0-9]/", "", strip_tags($link));
return '<li id="'.$id.'" class="'. $class .'">'. $link . $menu ."</li>\n";
}
?>
Can't seem to get this to work
Do I simply copy this into the header of my page.tpl.php file or do I copy it into a different file.
It says template.php
It says template.php
i copied it into
*for drupal 6*
i copied it into template.php
other functions such as phptemplate_menu_local_tasks are there
but i dont see a phptemplate_menu_item function
after i updated template.php
it doesnt seem to work
how is the function called ?
i looked in page.tpl.php
this is the part which renders the menu but i dont see how it gets linked to phptemplate_menu_item
<?phpif (isset($primary_links)) {
?>
<?phpprint theme('links', $primary_links, array('class' =>'links', 'id' => 'navlist'))
?>
<?php}
?>
This is not technically unique
This is not technically accurate since you could have the same menu items on different menus or even the same menu. The following is actually unique.
This makes each item unique and adds the semi-unique as a class instead.
<?php
/**
* Theme override for theme_menu_item()
*/
function phptemplate_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
$class = ($menu ? 'expanded' : ($has_children ? 'collapsed' : 'leaf'));
if (!empty($extra_class)) {
$class .= ' '. $extra_class;
}
if ($in_active_trail) {
$class .= ' active-trail';
}
// Add unique identifier
static $item_id = 0;
$item_id += 1;
$id .= ' ' . 'menu-item-custom-id-' . $item_id;
// Add semi-unique class
$class .= ' ' . preg_replace("/[^a-zA-Z0-9]/", "", strip_tags($link));
return '<li class="'. $class .'" id="' . $id . '">'. $link . $menu ."</li>\n";
}
?>
--
zzolo
Chicago Technology Cooperative
AlanPalazzolo.com
Very helpful, thank you.
Very helpful, thank you.
I was looking for this
I was looking for this everywhere for this functionality, and it works perfectly, thank you
I also needed the same functionality for Drupal 5, here's what I used
<?phpfunction phptemplate_menu_item($mid, $children = '', $leaf = TRUE, $extraclass = '') {
// Add unique identifier
static $item_id = 0;
$item_id += 1;
$id .= 'menu-item-custom-id-' . $item_id;
return '<li id="' . $id . '" class="'. ($leaf ? 'leaf' : ($children ? 'expanded' : 'collapsed')) . ($extraclass ? ' ' . $extraclass : '') . '">'. menu_item_link($mid, TRUE, $extraclass) . $children ."</li>\n";
}
?>
- Vivian
I found a few glitches with
I found a few glitches with the code used above for Drupal 5, here's a better version I found here and adapted for D5: http://drupal.org/node/267231#comment-873005
<?php
function getMenuItemCounter($case=null){
static $counter = 1;
return ($case == 'reset') ? $counter=1 : $counter++ ;
}
function YOURTHEME_menu_tree($pid = 1) {
getMenuItemCounter("reset");
if ($tree = menu_tree($pid)) {
return "\n<ul class=\"menu\">\n". $tree ."\n</ul>\n";
}
}
function phptemplate_menu_item($mid, $children = '', $leaf = TRUE, $extraclass = '') {
$counter = getMenuItemCounter();
return '<li id="menu-item-custom-id-' . $counter . '" class="'. ($leaf ? 'leaf' : ($children ? 'expanded' : 'collapsed')) . ($extraclass ? ' ' . $extraclass : '') . '">'. menu_item_link($mid, TRUE, $extraclass) . $children ."</li>\n";
}
?>
- Vivian
$item_id to Node ID
Hello.
// Add unique identifierstatic $item_id = 0;
$item_id += 1;
$id .= ' ' . 'menu-item-custom-id-' . $item_id;
How can replace $item_id to Node ID?
item id counter
the item_id counter gets incremented too many times. seems like it gets incremented even if the link is not part of the given menu. how can I test to see if the menu_item belongs to a given menu before incrementing it?
Alternate solution using javascript
I know these posts are about theming but I think this could help.
In my page I need to have unique IDs for navigation menu items AND the IDs must be in ascending order 1, 2, 3, 4, ... (I have to link a background img depending on item position so the second item must have id 2).
The solutions I've found here, although they guarantee an unique ID, can result in unordered IDs in case of submenus. E.g. a father node has ID 3 while the two children 1 and 2.
I was able to fix the issue adding this javascript that makes use of jquery:
Drupal.behaviors.doIt = function(context) {$("#navigation-menu").children().attr("id", function(index) {
return "item-id-" + index;
});
}
Just created a js file and added it to the mytheme.info file, and that's it.
Hope this helps.
yougo
Primary likns
It seems I can only get this to work on the "navigation" menu. How do I implement unique IDs on the Primary menu links?
How to add/link icons from CSS
Could some one help me on the next step. It is explained of how to create unique ID's for menu items but how to add icons for those unique ID's?.
How do i know which ID is for which menu item? Sample code/example please.
Thanks
Greatness!
This is just what I was looking for, many thanks.
Keepin' it creature
Zen
If you are using a Zen-based theme you can use the Zen function zen_id_safe
replace line
$id = preg_replace("/[^a-zA-Z0-9]/", "", strip_tags($link));with
$id = zen_id_safe(strip_tags($link));It is a damn poor day when you don't learn something!
so close...
So, I need to add a unique class to each secondary menu ul. If that doesn't make sense, here's an example
I have one menu. My menu has 4 primary items and about 6 secondary items under each primary.
My page design shows all primary items and the expanded secondary menu for that section.
I need to be able to style (through css) the secondary menu items differently for each section. So for sectionA, the secondary menu has a margin of 100px. For sectionB, the secondary menu has a margin of 300px and on...
There is currently only an id="secondary-links" on my ul tag. I need to add a unique class or id for each secondary ul based on the primary link.
Using the genesis theme starter if that makes a difference. Help appreciated!
Hi, Njacobson. I don't know
Hi, Njacobson.
I don't know what exacltly are you trying to achieve but you can use jQuery to do what you want.
The jQuery code should by added to your script.js file, in your theme directory.
First let's select all the 'li' elements of the menu, but without selecting their children 'li' elements (only top-level li elements).
Also for each selected 'li' tag select it's first 'a' child tag, and check it's value of "title" parameter (configurable via admin interface Admin -> Build -> Menus).
We save the 'title' value in a variable parentATitle (and optionally we remove the title parameter from the 'a' tag).
$(document).ready(function() {$('#secondary-links ul li').not($('#secondary-links ul li li').each(function() {
var parentLi = $(this);
var parentATitle = $(parentLi + ' a:first').attr('title').removeAttr('title');
});
});
Now we will add more code, which will use the parent 'a' tag value to add a new class to the child 'ul' tag.
$(document).ready(function() {
$('#secondary-links ul li').not($('#secondary-links ul li li').each(function() {
var parentLi = $(this);
var parentATitle = $(parentLi + ' a:first').attr('title').removeAttr('title');
$(parentLi + ' ul').not(parentLi + ' ul ul').addClass('class-' + parentATitle);
});
});
So now if you have a structure like:
<ul id="secondary-links"><li>
<a href="" title="main">X</a>
<u>
<li><a href="">A</a></li>
<li><a href="">B</a></li>
<li><a href="">C</a></li>
</ul>
</li>
<li>
<a href="" title="second">Y</a>
<u>
<li><a href="">D</a></li>
<li><a href="">E</a></li>
<li><a href="">F</a></li>
</ul>
</li>
</ul>
and you use the above jQuery code, it will first select the X link, read it's title and apply this title as a part of a new class for the 'ul' containing link A, B and C (it's class will be "class-main"). The same will happen for the Y link. So the class of the 'ul' containg link D, E, F will be "class-second".
I hope it will help you somehow. jQuery is a nice javascript library :-)
Cheers!
Unique <ul>s
njacobson, did you find a solution to get unique UL s?
Sorry the JQuery above does not work for my situation. Really need unique IDs for the ULs in the secondary menu.
Thanks for any help.