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.

Comments

knalstaaf’s picture

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

Summit’s picture

Bookmarking.

Greetings,
Martijn
if you appreciate e-development work, please place a link from your site to www.trekking-world.com

8w_gremlin’s picture

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

knalstaaf’s picture

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.

8w_gremlin’s picture

						<?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

mafaz’s picture

I used this forum to figure out how the primary menu can be themed to match my need. However, I can't understand how the children can be printed. Even though the template file is provided, I'd appreciate having some explanation and doing it with some understanding, if someone would care to humour me.

thanks in advance

timoffei’s picture

to output a tree of primary links and its subitems:
$primary_links_tree = menu_tree_all_data('primary-links');
print menu_tree_output($primary_links_tree);
Since this can be the full tree including hidden items, the data returned may be used for generating an an admin interface or a select.
menu_tree_all_data() function reference
OR
$primary_links_tree = menu_tree_page_data('primary-links');
print menu_tree_output($primary_links_tree);
The tree is expanded based on the current path and dynamic paths are also changed according to the defined to_arg functions (for example the 'My account' link is changed from user/% to a link with the current user's uid).
menu_tree_page_data() function reference

dcolumbus’s picture

...with your code, I am so close to customizing the navigation and yet so far. My menu is set up like so:

--Home
--About
----Mission
----Members
--Services
----Design
----Development
----Print
--Contact

This is within the Primary links with the child pages set to "expanded" ... but all I'm getting is the parent links. How can I expand your code so that it's printing out the children too? In other words, all I'm seeing is:

--Home
--About
--Services
--Contact

UGH! I beg of you!

mooffie’s picture

$href = $link['href'] == "" ? base_path() : base_path() . drupal_get_path_alias($link['href']);

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'])

mafaz’s picture

Hi, I've been looking for some thing similar to this, and it was a really helpful tute by you. However, i can't seem to figure out how to print the children if any of the links. Could you help me out with this?

Thanks

shv_rk’s picture

hello

i need to customize my menu, so that active class to be in the list item rather than a element
so should be something like this:

<ul id="navlist">
                <li class="active parent"><a href="#">Item one</a>
                    <ul id="subnavlist">
                        <li class="active parent"><a href="#">Subitem one</a></li>
                        <li><a href="#">Subitem two</a></li>
                        <li><a href="#">Subitem three</a></li>
                        <li><a href="#">Subitem four</a></li>
                    </ul>

                </li>

curently menu inserts the active class like this:

<li ><a class="active" href="#">Subitem one</a></li>

Please help me in this issue.

knalstaaf’s picture

Have you considered the Menutrails module? I think this is what you're looking for. It adds "active"-classes throughout your menu structure, so it would look like this:

<ul id="navlist">
 <li><a href="#" class="active">Item one</a>
  <ul id="subnavlist">
    <li><a href="#" class="active">Subitem one</a></li>
    <li><a href="#">Subitem two</a></li>
    <li><a href="#">Subitem three</a></li>
    <li><a href="#">Subitem four</a></li>
  </ul>
 </li>
</ul>

Or in design it could look like this:

(Active items in underlined italic)

shv_rk’s picture

Hi knalstaaf,

Thnaks for the reply, yes i have tested it with menutrail module.
hiwver, for some reasons it does not work for me.
I am assume because my menu is generated by taxonomy menu module.
there is also a plugin taxonomy menu trail which does not work for me I asked the author!

anyway, for time being I am doing it with a simple javascript code until F find the better way of
doing it!

wiliam_steven’s picture

hello sir,

Acctually how you do that, i mean to make an active menu to have class like,

<li ><a class="active" href="#">Subitem one</a></li>

actually i want to make my primary menu and also secondary menu to have menu structur like

<li><a class="selected" href="#" title="">home</a></li>
<li><a href="#" title="">about</a></li>

when it the link is active it have a selected class to be adding in the element.

please help me this,

Thanks before

knalstaaf’s picture

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.

knalstaaf’s picture

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.

knalstaaf’s picture

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] = menublok

to 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.

d------’s picture

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

silurius’s picture

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).

d------’s picture

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

pauln600’s picture

I'm looking at using one of the many existing menu modules (e.g., nice menus).

pauln600’s picture

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.

mclinn’s picture

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.

ginga8’s picture

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; ?>
rpadua’s picture

so did anyone find out how that could be done? I have the same problem here..

cheers

anthonylicari’s picture

Edit: Bad code.

Bilmar’s picture

I'm interested in learning how to make this work on a custom menu link.

mooffie’s picture

I assume you have a working piece of code.

In your code there's some variable that holds the links. I assume it's called $primary_links.

At the start of your code add the following line to load that variable with links from a different menu:

$primary_links = menu_navigation_links('MY-CUSTOM-MENU');

(Replace MY-CUSTOM-MENU with the "machine name" of your custom menu.)

(Additionaly, you may wish to rename the "$primary_links" variable to something more appropriate, but this isn't necessary.)

Haidee’s picture

how do i get the current active link or link that being click, coz i wanted to add class something like: <li class="sliding-element THIS-IS-THE-ACTIVE-LINK">link</li>

knalstaaf’s picture

Consider the Menu Trails module. Combined with the Menu Block module it's quite a powerful tool.

Install the module, configure it and check its classes in the source of your pages. You'll see what you're looking for.