Hi

I'm trying to find a way to add a separator or delimiter between the main menu items in D7.

Has anyone managed to achieve this ?

Appreciate any replies.

G.

Comments

Drave Robber’s picture

joshua.stout’s picture

I took this person's D6 code: http://browse-tutorials.com/snippet/menu-delimiters-drupal
and ported it to D7.


/**
 * Return a themed set of links delimitated by "|"
 * An override of theme_links()
 *
 * @see theme_links
 */
function THEME_NAME_links($links, $attributes = array('class' => 'links')) { //replace THEME_NAME
  // 1. Change the delimiter to what you want.
  $delimiter = ' | ';

  // 2. Change the menu to the one you're targeting.
  if (($links['attributes']['id']) == 'main-menu') {

    // 3. I turned off the heading. You can kill this line.
    hide($links['heading']);

    $output = '';
    if (count($links['links']) > 0) {
      $link_classes = implode(' ', $links['attributes']['class']);
      $output = '<ul id="' . $links['attributes']['id'] . '" class="' . $link_classes . '">';

      $num_links = count($links['links']);
      $i = 1;

      foreach ($links['links'] as $key => $link) {
        $class = $key;

        // Add first, last and active classes to the list of links to help out themers.
        if ($i == 1) {
          $class .= ' first';
        }
        if ($i == $num_links) {
          $class .= ' last';
        }
        if (isset($link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page()))) {
          $class .= ' active';
        }
        $output .= '<li' . drupal_attributes(array('class' => $class)) . '>';

        if (isset($link['href'])) {

          // Pass in $link as $options, they share the same keys.

          $output .= l($link['title'], $link['href'], $link);
        } else if (!empty($link['title'])) {

          // Some links are actually not links, but we wrap these in <span> for adding title and class attributes

          if (empty($link['html'])) {

            $link['title'] = check_plain($link['title']);
          }
          $span_attributes = '';

          if (isset($link['attributes'])) {

            $span_attributes = drupal_attributes($link['attributes']);
          }

          $output .= '<span' . $span_attributes . '>' . $link['title'] . '</span>';
        }



        if ($i == $num_links) {
          $delimiter = '';
        }

        $i++;

        $output .= "</li>" . $delimiter;
      }

      $output .= '</ul>';
    }

    return $output;
  }
}
codesidekick’s picture

For those getting a 'Notice: Undefined index' message when using this piece of code try using

  isset($links['attributes']['id'])

in the if statement so that it looks like

  if (isset($links['attributes']['id']) && ($links['attributes']['id']) == 'main-menu') {

Otherwise great piece of code for those wanting to use delimiters that can't be accomplished with CSS.

......................................................................................................
Marton Bodonyi
http://www.codesidekick.com
.........................................................

tike012’s picture

It seems like this code should fix the undefined id problem but doesn't. What's stranger is that the variable is defined and I can theme all my menus correctly, but the error still persists. Any ideas?

A temporary fix that doesn't get to the bottom of the problem:

Replace this line:

$output = '<ul id="' . $links['attributes']['id'] . '" class="' . $link_classes . '">';

with this:

$output = '<ul';
if (isset($links['attributes']['id'])) { $output .= ' id="' . $links['attributes']['id'] . '"'; }
$output .= ' class="' . $link_classes . '">';

Very strange, since even with this code the menu ul's still get their ids.

tike012’s picture

It seems like the first if statement in your code checks for the correct menu and applies the correct delimiter, but ignores all other menus.

I've modified your code to the following:

  $delimiter = '';
  if (isset($links['attributes']['id'])) {
    if ($links['attributes']['id'] == 'top-nav') {
      // 1. Change the delimiter to what you want.
      $delimiter = ' | ';
    }
  }

The rest of the code is moved to outside of the if statement.

However, with this code I am still getting the error:

Notice: Undefined index: id in...

$links['attributes']['id'] is defined so I'm not sure what the problem is. All my menus are output correctly. Any help would be appreciated.

missWilder’s picture

you could target the menu items and add a right border, then target the last item to remove the border.

LSU_JBob’s picture

missWilder++ This was the easiest thing to do.

shaneonabike’s picture

I totally agree although I'm having issues since Drupal doesn't output class="last" on the last item. So did you just use a theme hook to change the output?

kris_mcl’s picture

Hi, this is kind of an old thread now, but I thought this might help someone. Here's an easy way to add a delimiter to main menu items using theme_menu_link()

function MYTHEME_menu_link(array $variables) {
  $delimiter = '';
  // Only add delimiter to the main menu
  if (strpos($variables['element']['#theme'], 'main_menu') !== FALSE ) {
    // Only add delimiter if item is not the last one
    if (!in_array('last', $variables['element']['#attributes']['class'])) {
      $delimiter = '<span class="delimiter">/</span>';
    }
  }
  $element = $variables['element'];
  $sub_menu = '';

  if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  }
  $output = l($element['#title'], $element['#href'], $element['#localized_options']);
  // Add delimiter just before the closing </li> tag
  return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . $delimiter. "</li>\n";
}

This will add a span-wrapped delimiter to each menu item except the last one. It works well for me, hopefully it helps you too.

Faux’s picture

how can i combine this code with a seperator only for the secondary menu??

<?php
/**
* Add unique class (mlid) to all menu items.
*/
function themename_menu_link(array $variables) {
$element = $variables['element'];
$sub_menu = '';
$delimiter = '';

$element['#attributes']['class'][] = 'menu-' . $element['#original_link']['mlid'];

if ($element['#below']) {
$sub_menu = drupal_render($element['#below']);
}

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

?>
lasseitorp’s picture


function YOUR_THEME_links($variables) {
  $links = $variables['links'];
  $attributes = $variables['attributes'];
  $heading = $variables['heading'];
  global $language_url;
  $output = '';
  $delimiter = '';
  
 if (isset($attributes['id'])) {
    if ($attributes['id'] == 'main-menu') {
      // 1. Change the delimiter to what you want.
      $delimiter = ' | ';
    	}
 	}

  if (count($links) > 0) {
    $output = '';

    // Treat the heading first if it is present to prepend it to the
    // list of links.
    if (!empty($heading)) {
      if (is_string($heading)) {
        // Prepare the array that will be used when the passed heading
        // is a string.
        $heading = array(
          'text' => $heading,
          // Set the default level of the heading. 
          'level' => 'h2',
        );
      }
      $output .= '<' . $heading['level'];
      if (!empty($heading['class'])) {
        $output .= drupal_attributes(array('class' => $heading['class']));
      }
      $output .= '>' . check_plain($heading['text']) . '</' . $heading['level'] . '>';
    }

    $output .= '<ul' . drupal_attributes($attributes) . '>';

    $num_links = count($links);
    $i = 1;

    foreach ($links as $key => $link) {
      $class = array($key);

      // Add first, last and active classes to the list of links to help out themers.
      if ($i == 1) {
        $class[] = 'first';
      }
      if ($i == $num_links) {
        $class[] = 'last';
      }
      if (isset($link['href']) && ($link['href'] == $_GET['q'] || ($link['href'] == '<front>' && drupal_is_front_page()))
           && (empty($link['language']) || $link['language']->language == $language_url->language)) {
        $class[] = 'active';
      }
      $output .= '<li' . drupal_attributes(array('class' => $class)) . '>';

      if (isset($link['href'])) {
        // Pass in $link as $options, they share the same keys.
        $output .= l($link['title'], $link['href'], $link);
      }
      elseif (!empty($link['title'])) {
        // Some links are actually not links, but we wrap these in <span> for adding title and class attributes.
        if (empty($link['html'])) {
          $link['title'] = check_plain($link['title']);
        }
        $span_attributes = '';
        if (isset($link['attributes'])) {
          $span_attributes = drupal_attributes($link['attributes']);
        }
        $output .= '<span' . $span_attributes . '>' . $link['title'] . '</span>';
      }

	
		if ($i == $num_links) {
          $delimiter = '';
        }
        
      $i++;
      $output .= "</li>" . $delimiter . "\n";
    }

    $output .= '</ul>';
  }

  return $output;
}
vchen’s picture

Thank you so much for this code snippet!! Been at it for hours...

zakir.gori’s picture

Hi,
i want to add delimiter image in my Main-menu but when i added the code into my template.php its added delimiter into my Management-menu.

zakir.gori

ergunk’s picture

I think there is no need any coding etc. My suggestion:

Use Menu attributes module and give special ID or classes to your menu items. Then you can do anything with CSS.

Example:
I used it in my main menu to make list items have different background images:

http://www.mediasaur.com/en


Mediasaur | http://www.mediasaur.com/en | http://twitter.com/mediasaur


Before asking for help, please read this http://slash7.com/2006/12/22/vampires/ and don't be a "Help Vampire". :)
mbahlol’s picture

i've tried this http://drupal.org/node/1214026#comment-5700174, and target my custom menu

if ($attributes['id'] == 'menu-menu-tab') {

but no result (|) shows.