Customizing primary links in Drupal 6 (adding custom classes)
I believe it's not such an easy thing to do as I can find many topics about this, but only few of them have useful replies.
For my primary links I'm using a nifty jQuery menu with its own id and class. Obviously I'd like to keep this class and id untouched. I've been looking around for this, consulted many pages that come close but not to the point when it comes to Drupal 6.
This code is working for Drupal 6, but not totally:
<?php if (is_array($primary_links)) : ?>
<ul id="sliding-navigation">
<?php foreach ($primary_links as $link): ?>
<li class="sliding-element"><?php
$href = $link['href'] == "<front>" ? base_path() : base_path() . $link['href'];
print "<a href='" . $href . "'>" . $link['title'] . "</a>";
?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>This is working fine concerning the styles. But I'm using Pathauto and whereas the Zen and Garland theme replace the default url's (node/1) to semantic url's (content/about-webdesign), the above example doesn't:
<ul id="sliding-navigation">
<li class="sliding-element"><a href='node/1'>About this</a></li>
<li class="sliding-element"><a href='node/2'>Concerning that</a></li>
<li class="sliding-element"><a href='node/3'>This much</a></li>
<li class="sliding-element"><a href='node/4'>That many</a></li>
</ul>The Zen and Garland-links do have these semantic url's, but it's not so easy to add custom classes and id's to the primary links of Zen and Garland:
Zen:
<?php if ($primary_links): ?>
<div id="primary">
<?php print theme('links', $primary_links); ?>
</div>
<?php endif; ?>Garland:
<?php if (isset($primary_links)) : ?>
<?php print theme('links', $primary_links, array('class' => 'links primary-links')) ?>
<?php endif; ?>These two options leave too little room for the proper class (sliding-element) and id (sliding-navigation) for this jQuery menu. This is what the menu should look like:
<ul id="sliding-navigation">
<li class="sliding-element"><a href='content/semantic-url'>About this</a></li>
<li class="sliding-element"><a href='content/semantic-url'>Concerning that</a></li>
<li class="sliding-element"><a href='content/semantic-url'>This much</a></li>
<li class="sliding-element"><a href='content/semantic-url'>That many</a></li>
</ul>The first code in this post actually doés this, but it misses the semantic url's.
Does anyone have an idea how to add classes to the Zen or Garland theme, òr how to add semantic url's to the first example?
Thanks in advance.

Found it
Someone on the Belgian Drupal forum came up with the answer.
The first code mentionned in the post above should be modified like this:
<?php if (is_array($primary_links)) : ?><ul id="sliding-navigation">
<?php foreach ($primary_links as $link): ?>
<li class="sliding-element"><?php
$href = $link['href'] == "<front>" ? base_path() : base_path() . drupal_get_path_alias($link['href']);
print "<a href='" . $href . "'>" . $link['title'] . "</a>";
?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
Reference: drupal_get_path_alias
Bookmarking. Greetings, Marti
Bookmarking.
Greetings,
Martijn
if you appreciate e-development work, please place a link from your site to www.trekking-world.com
Child links
I've been wracking my brain to work this out for a day now, and your post simplified matters no end.
But i have a slight variation to the problem, I need to also display the children of the primary links, just the immediate links, and no further to create a Doormat style navigation http://www.welie.com/patterns/showPattern.php?patternID=doormat.
So any ideas how I can do some kind of additional loop if they have children?
Cheers
Customizing child links primary menu
That is actually what my menu is doing as well, with the right sources set for the menus.
In the code you notice the term "$secondary_links", but they are in fact the children of the primary links (screen, all should be expanded in your case I believe), and not the "secondary links"-block in the menu section of your Drupal admin.
<?php if (is_array($secondary_links)) : ?><ul id="sliding-navigation2">
<?php foreach ($secondary_links as $link): ?>
<li class="sliding-element"><?php
$href = $link['href'] == "<front>" ? base_path() : base_path() . drupal_get_path_alias($link['href']);
print "<a href='" . $href . "'>" . $link['title'] . "</a>";
?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
So stripping the above could from its html-tags and forging it into your html-structure should work out.
Not sure I got this right
<?php if (is_array($primary_links)) : ?>
<ul id="sliding-navigation">
<?php foreach ($primary_links as $link): ?>
<li class="footer-col"><?php $href = $link['href'] == "<front>" ? base_path() : base_path() . drupal_get_path_alias($link['href']);
print "<a href='" . $href . "'>" . $link['title'] . "</a>";
?>
<ul class="sliding-navigation2">
<?php foreach ($secondary_links as $link): ?>
<li class="sliding-element"><?php
$href = $link['href'] == "<front>" ? base_path() : base_path() . drupal_get_path_alias($link['href']);
print "<a href='" . $href . "'>" . $link['title'] . "</a>";
?></li>
<?php endforeach; ?>
</ul>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
I'm a little stuck on the whole process of getting the children items displayed, the menu's are as you shown on the images, all expanded as needed and the secondary menu uses primary menu as its source...
So its a bit of basic php that I'm missing or something as all i get is an empty
<ul class="sliding-navigation2"> </ul>tag...
There's no reason to do this mumbo-jumbo yourself. Simply do
$href = url($link['href']).Or, better, replace the two lines with
print l($link['title'], $link['href'])Replacing primary links
So the code above is working perfectly for the primary links.
I created another menu called 'campagnes'. Added the region in the .info-file (
regions[campagnes] = campagnes), cleared the cache. Finally I inserted the following code in the html-page (page.tpl.php):<?php if (is_array($campagnes)) : ?><ul id="sliding-navigation">
<?php foreach ($campagnes as $link): ?>
<li class="sliding-element"><?php
$href = $link['href'] == "<front>" ? base_path() : base_path() . drupal_get_path_alias($link['href']);
print "<a href='" . $href . "'>" . $link['title'] . "</a>";
?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
As you notice, I replaced 'primary_links' with 'campagnes'. This, however, is not working.
A colleague who's more familiar with php, said the 'campagnes'-menu was not recognized as an array, and therefore not displayed. Eventhough the menu 'campagnes' has items as well (just like the working primary links-menu has) in the admin.
Where is it going wrong here (how come that he doesn't recognize the array)? Any ideas?
Btw: when I put this in the page:
<?php print $campagnes ?>The items are displayed in a default way, so it does find the 'campagnes'-menu. It's recognizing the array that's the main problem here, I think.
Easier than I thought
A colleague found the solution. The only thing that's needed in this case, are the primary links.
When going to Site-construction › Menus › Settings, apply the following:
Default menu for content: Primary links
Source primary links: Primary links
Source secondary links: Primary links
(Screen)
Then this code should be added in the html:
<?php if (is_array($secondary_links)) : ?><ul id="sliding-navigation2">
<?php foreach ($secondary_links as $link): ?>
<li class="sliding-element"><?php
$href = $link['href'] == "<front>" ? base_path() : base_path() . drupal_get_path_alias($link['href']);
print "<a href='" . $href . "'>" . $link['title'] . "</a>";
?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
And things should work out. No extra regions or features need to be added in the info-file with this method.
When you're in need of anòther extra menu, you can add another menu in Site-construction › Menus › Add menu
Then the code of the extra menu should be slightly modified. Just copying the previous codes won't help.
E.g.:
<?php$tertiary_links = menu_navigation_links(variable_get('menu_primary_links_source', 'primary-links'), 2);
print theme('links', $tertiary_links, array('id' => 'tertiary'));
?>
The '2' stands for the level.
More info here. Also check Menu Block and Local Menu.
A solution for adding multiple menus with styled links (jQuery)
Creating a custom menu (instead of using "primary links" or "secondary links") didn't work out with the method mentionned above though.
In order to do that, I had to create a custom menu, called 'servicelinks' for instance (as the machine name). After that I had to create an extra region. I decided to call it "menublok", and added
regions[menublok] = menublokto the info-file.
After that someone from the Belgian Drupal forum was so kind to provide a custom template.php for this particular jQuery-menu. This is what the template.php looks like now (in the folder of my custom theme):
<?php
function phptemplate_preprocess_page(&$vars) {
$servicelinks = menu_tree_page_data("menu-servicelinks");
$vars['servicelinks'] = my_menu_tree_output($servicelinks, "sliding-navigation");
$vars['servicesecondary'] = my_menu_tree_secondary($servicelinks, "sliding-navigation2");
}
function my_menu_tree_output($tree, $id) {
$output = '';
$items = array();
// Pull out just the menu items we are going to render so that we
// get an accurate count for the first/last classes.
foreach ($tree as $data) {
if (!$data['link']['hidden']) {
$items[] = $data;
}
}
$num_items = count($items);
foreach ($items as $i => $data) {
$extra_class = NULL;
if ($i == 0) {
$extra_class = 'first';
}
if ($i == $num_items - 1) {
$extra_class = 'last';
}
$link = theme('menu_item_link', $data['link']);
if ($data['below']) {
//$extra = my_menu_tree_output($data['below']);
$output .= my_menu_item($link, $data['link']['has_children'], '', $data['link']['in_active_trail'], $extra_class);
}
else {
$output .= my_menu_item($link, $data['link']['has_children'], '', $data['link']['in_active_trail'], $extra_class);
}
}
return $output ? my_menu_tree($output, $id) : '';
}
function my_menu_tree_secondary($tree, $id) {
$output = '';
$items = array();
// Pull out just the menu items we are going to render so that we
// get an accurate count for the first/last classes.
foreach ($tree as $data) {
if (!$data['link']['hidden']) {
$items[] = $data;
}
}
$num_items = count($items);
foreach ($items as $i => $data) {
$extra_class = NULL;
if ($i == 0) {
$extra_class = 'first';
}
if ($i == $num_items - 1) {
$extra_class = 'last';
}
$link = theme('menu_item_link', $data['link']);
if ($data['below']) {
$output .= my_menu_tree_output($data['below'], $id);
//$output .= my_menu_item($link, $data['link']['has_children'], $extra, $data['link']['in_active_trail'], $extra_class);
}
else {
//$output .= my_menu_item($link, $data['link']['has_children'], '', $data['link']['in_active_trail'], $extra_class);
}
}
return $output ;
}
function my_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';
}
return '<li class="sliding-element">'. $link . $menu ."</li>\n";
}
function my_menu_tree($tree, $id) {
return '<ul id="'.$id.'">'. $tree .'</ul>';
}
(There's no closing tag for the php-code indeed. There's no need apparently)
Then I added the code to call the menu items in the page.tpl.php, eg:
<div class="menu"><?php print $menublok; ?>
</div>
<div class="submenu">
<?php print $servicesecondary; ?>
</div>
Finally I went to Site construction » Blocks, added a new block called "Servicelinks" with this line written in the "block content"-box:
<?php print my_menu_tree_output(menu_tree_page_data("menu-servicelinks"), "sliding-navigation"); ?>Make sure the PHP-filter is selected (screen), instead of Filtered HTML and Full HTML. If this option isn't displayed yet, go to Site construction » Modules and check "PHP filter" in the optional core modules.
Then I specified on what pages this block should appear, and did the same for their respectively subitems. Make sure that these subitems aren't set to "expanded"; they should be collapsed. Otherwise they'll appear on every page.
Finally I dragged this block to the "menublok"-region (in Site construction » Blocks).
So that was it for the menu called "Servicelinks".
After all this I added another menu with the (machine-)name "homelinks". Created a new block in Site construction » Blocks, added this line in the "block content"-box (with the PHP-filter selected):
<?php print my_menu_tree_output(menu_tree_page_data("menu-homelinks"), "sliding-navigation"); ?>and specified on what pages this menu (with its submenu items) should appear. Finally I dragged this blok to the region "menublok" as well.
It works perfectly.
It's not such an easy way of making customized menus, but I must stress this is an animated jQuery menu, with its quite complex behaviour. In this case we also have multiple menus, while primary and secondary links are fair enough for most websites.
I also want to thank the people of the Belgian Drupal community for their support; seutje in particular - for his patience and willingness to share his Drupal enthousiasm.
Customize Like A "Mega Menu"
Hi All,
Caught this topic a bit late and was wondering if anyone could advise on this related dilemma. I need to integrate a "Mega Menu" into Drupal primary links menu. Basically a mega menu is a drop down menu where the child links are displayed together with headings.
An example is here -
http://www.sitepoint.com/blogs/2009/03/31/make-a-mega-drop-down-menu-wit...
Completed example:
http://www.sitepoint.com/examples/megadropdowns/completed.html
I'm trying to integrate the menu described in that blog post with Drupal. Any ideas will be much loved :D
The difficulty seems to be on the dynamic creation of the headings - I guess they will have to be pulled from somewhere in the CMS - but where?
Thanks,
Dan
Dan Gibas, HYGEN
Dan, I came here with exactly
Dan, I came here with exactly the same goal and have been lurking for a few days, after having also read Jakob's article last week. Subscribing to thread and will update here if I find anything that hasn't been mentioned yet. Personally I had considered Cluetip or a similar jQ solution, but actually favor a pure CSS solution. (Incidentally, in this case my Primary links do not need to be dynamic and I doubt that it matters much that I'm already using DHTML Menu, JQuery menu and Menu Attributes).
Mega Menu Solution Hunting
Hi Silurius,
Glad to know I'm not alone on this one... I'm playing with some code now and will let y'all know if I manage to get any worthwhile results.
Dan
Dan Gibas, HYGEN
Also working on this
I'm looking at using one of the many existing menu modules (e.g., nice menus).
An example
One of my favourite examples:
http://www.patagonia.com/web/us/home/index.jsp?OPTION=HOME_PAGE&assetid=...
Nice layout, good design of delays and rollout.
Great "mega menu" example
I recently heard the term "mega menu" for the first time. This page gives a super example -- you can see all the car models without clicking once:
http://www.porsche.com/usa/
This looks like something that can be really useful. I don't know if this kind of thing could be accomplished in Drupal -- maybe in a future version? So much has been done already I wouldn't be surprised.
custom menu altering
So how do you get this to work on a custom menu. I would like to split the menu in half so I have two columns that I can output in a block.
<?php if (is_array($menu-quick-links)) : ?><ul id="sliding-navigation">
<?php foreach ($menu-quick-links as $link): ?>
<li class="sliding-element"><?php
$href = $link['href'] == "<front>" ? base_path() : base_path() . drupal_get_path_alias($link['href']);
print "<a href='" . $href . "'>" . $link['title'] . "</a>";
?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
megamenus
so did anyone find out how that could be done? I have the same problem here..
cheers