Is there any way I can control the way a menu is printed so it will print like this:

<ul id="navigation">
	<li><a href="#" >Home<span>Introduction</span></a></li>
	<li><a href="#" >Features<span>The feature tour</span></a></li>
	<li><a href="#" >Pricing<span>Our fee made clear</span></a></li>
	<li><a href="#" >Support<span>Help when needed</span></a></li>
	<li><a href="#" >Blog<span>Stay informed</span></a></li>
</ul>

I am using Drupal 7, and this will be part of a custom theme. Thank you.

Comments

pobster’s picture

I would assume this works exactly the same as D6.x - you should be able to put this into your template.php file for the theme you're using;

function YOURTHEMENAME_menu_item_link($link) {
  if (empty($link['localized_options'])) {
    $link['localized_options'] = array();
  }
  $link['localized_options']['html'] = TRUE; // Let l function know that our link title includes html.
  return l('<span>' . $link['title'] . '</span>', $link['href'], $link['localized_options']);
  // Or perhaps;
  // return '<span>' . l($link['title'], $link['href'], $link['localized_options']) . '</span>';
  // It depends on what you're actually trying to achieve.
}

Pobster

akael’s picture

Pobster,

Thanks for the reply. This is not much different than what I tried, but it doesn't seem to make any changes to the Main Menu.

dqd’s picture

exactly, it doesn't affect main-menu, but all other menus.

akael’s picture

I am a little bit closer:

<?php
function THEMENAME_menu_link(array $variables) {
  $element = $variables['element'];
  $sub_menu = '';

  if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  }
  $output = l('<span>' . $element['#title'] . '</span>', $element['#href'], $element['#localized_options']);
  return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
?>

This puts the span tags around the title, but I think I might have asked my question wrong. I want the title to stay the link, and the description of the menu item to be in the span, is this possible?

Also, the above code did inject the span tags, but it displayed them on the screen.

pobster’s picture

Hiya!

You've missed the comment I made;

$link['localized_options']['html'] = TRUE; // Let l function know that our link title includes html.

Which is why the link tags show as text as not as 'html' (hence the parameter!)

Thanks,

Pobster

akael’s picture

That was slightly different than what I was trying for, but it worked and fits the need.

Heres what I added to the template.php:

/**
 * Override function so we can allow html in menu titles
 */
function projectutilities_menu_link(array $variables) {
  $element = $variables['element'];
  $sub_menu = '';

  if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  }
  $output = l($element['#title'], $element['#href'], $element['#localized_options'] += array('html' => TRUE));
  return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
?>

The only change for core code was to add:

+= array('html' => TRUE)

at the end of the line that starts with $output = l(

Then to add the span code in the title box of each link I put text like this:

Home<span>go home</span>

Couple very small css tweaks and I am gold.

pobster’s picture

Just out of pure curiosity;

> That was slightly different than what I was trying for...

Apologies if I misunderstood - what were you trying for?

Thanks,

Pobster

drunkencelt’s picture

Hi Akael,

I have the following in my template.tpl as you suggested but it doesn't seem to be working for me:

function dcwsv2_menu_item_link(array $variables) {
  $element = $variables['element'];
  $sub_menu = '';

  if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  }
  $output = l($element['#title'], $element['#href'], $element['#localized_options'] += array('html' => TRUE));
  return '<li>' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}

(I had to refer to the function as "dcwsv2_menu_item_link" because "dcwsv2_menu_link" did not seem to override it.)

This produces a "Fatal error: Unsupported operand types in C:\Users\DCWS\wamp\www\dcws_v2\sites\all\themes\dcwsv2\template.php on line 165" which clears when I remove the "+" from the line "$element['#localized_options'] += array('html' => TRUE".

The "li" element part of the return is then output but nothing else.

Any other suggestions that may help?

Thanks a lot.

Server: Apache/2.2.11 (Win32) PHP/5.3.0
PHP: 5.3.0
MySQL: 5.1.36
Drupal: 6.19

pobster’s picture

It's a bit frustrating that no-one is just copying and pasting my snippet...

You can only use += when both sides are an array, hence I put this;

if (empty($link['localized_options'])) {
  $link['localized_options'] = array();
}

Pay more attention to the very first code snippet posted.

Pobster

drunkencelt’s picture

Thanks Pobster,

You are right. Sometimes we can't see what's in front of us...

I have used your first snippet and changed only the function name to reflect my theme and the return line by adding '$link['description']' and moving the span tags to where I want. Perfect.

return l($link['title'] . ' <span>' . $link['description'] . '</span>', $link['href'], $link['localized_options']);

Works a treat.

Thanks a lot

drunkencelt’s picture

Just another query Pobster,

How do I get this to apply to only a particular menu? I've just realised it reproduces the description for all menus except primary, secondary etc. I want to be specific about the menus that get rendered in this way, say by the menu name. I've tried various combinations utilising $menu_name without much success.

Thanks

drunkencelt’s picture

The $link['description'] does not output anything and I can't get the function to automatically inject span tags based on the menu name so this will have to do. It affects all the user added menus by the look of it.

Still got alot to learn...

function dcwsv2_menu_item_link($link) {
    
      if (empty($link['localized_options'])) {
      $link['localized_options'] = array();
     }
      $link['localized_options']['html'] = TRUE; // Let l function know that our link title includes html.
      return l($link['title'], $link['href'], $link['localized_options']);
	 }

Cheers

dqd’s picture

drunkencelt, this is for D6. D7 uses menu_link instead of menu_item_link and doesn't affect main-menu anyway, as far as I know ...

akael’s picture

I was hoping to do the same thing but using the description field text in the span. This way works fine, I am still not sure if I am going to release this theme to the public. It is in my opinion the best looking drupal theme I have seen. This may be because I made it!

pobster’s picture

Hiya!

Ah okay, well maybe try doing a var_dump of what is available to you? You may find you actually do have access to the description field at that point?!

Thanks,

Pobster

dqd’s picture

akael,

did you found a solution?

greetings from Berlin,
Digidog