following code in my template.php file:

<?php
function THEMENAME_link($variables) {
  return '<a href="' . check_plain(url($variables['path'], $variables['options'])) . '"' . drupal_attributes($variables['options']['attributes']) . '><span>' . ($variables['options']['html'] ? $variables['text'] : check_plain($variables['text'])) . '</span></a>';
}
?>

However, this wraps span tag around EVERY menu item.... I would like to just specifically do this to my main menu (primary links).

Doing this
<?php function THEMENAME_links__system_main_menu($variables) ?> Results in a big fat error....

So any ideas on how to use the above code to specifically change the main menu would be fantastical help. ;)

Comments

francort’s picture

You may have been close to the solution.
I've tried on template.php this code:

function THEMENAME_links__system_main_menu($variables){
  $links = $variables['links'];
  $attributes = $variables['attributes'];
  $heading = $variables['heading'];
  global $language_url;
  $output = '';

  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>';
      }

      $i++;
      $output .= "</li>\n";
    }

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

  return $output;
}

... and I don't have any errors from it. (remember to clear cache)

I hope this can be a good start point

Cheers

timothymahoney’s picture

Hi francort - this worked GREAT for me. Thank you so much; I've been unable to find a solution for a couple of days now.

saitanay’s picture

theme_link and theme_links are both different functions.

xxx_link__main_menu() or xxx_link__main_menu__system_main_menu() doesnt seem to work.
it however works for theme_links!

mrtoner’s picture

francort's solution seems a bit much. After much trial and error, I came up with this:

function THEME_preprocess_page(&$variables) {
  global $theme_path;
  foreach ($variables['main_menu'] as $key => $value) {
    $variables['main_menu'][$key]['html'] = TRUE;
    $variables['main_menu'][$key]['title'] = '<span>'. $variables['main_menu'][$key]['title'] .'</span>';
  }
}
Taesto’s picture

I found the solution to this problem after a lot of searching. By the way this works to customize the output of the links of any specific menu.

Let me just say first that customizing the primary or main menu links is something essential to any theming, and the only reason I can think of why Drupal programmers made it so hard to do is so that professional Drupal themers can keep their jobs!

I saw solutions using the theme_link function : bad idea because this will alter the output of ALL your links, which will break your site's layout.

So my approach is to you override the theme_menu_link function. I add a condition to use the override only on the specific menu I want. In this example I chose the primary links. To know the name of the menu you want to theme you have to put dsm($variables) and usse the Devel module.

function yourtheme_menu_link(array $variables) {

  $element = $variables['element'];
  $sub_menu = '';
//replace 'menu_link__menu_block__1' with the name of the menu you want to theme
if ($element['#theme']['0']=='menu_link__menu_block__1') {
if ($element['#below']) {
    $sub_menu = drupal_render($element['#below']);
  }
   $titre= $element['#title'];
//I put the Span tags in the title
$element['#title']='<span class="yourclass1"></span><span class="yourclass2">'.$titre. '</span><span class="yourclass3"></span>';
//I tell the l() function to keep the HTML tags
  $element['#localized_options'] += array(
    'attributes' => array(), 
    'html' => TRUE,
  );
$output = l($element['#title'], $element['#href'], $element['#localized_options']);
  return '<li' . drupal_attributes($element['#attributes']) . '>' . $output . $sub_menu . "</li>\n";
}
//the function renders the links from all the other menus without modification
  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";
}

If anyone knows of a more simple way let me know. I'm no expert just pieced together this solution after a lot of trial and error.

navi85sin’s picture

function themename_links__system_main_menu($variables) {
$html = " <ul class='main-menu'>";
foreach ($variables['links'] as $k => $link) {
$html .= "<li>".l($link['title'], $link['href'], array('attributes' => array('class' => 'reflect '.$k.'')))."</li>";
}
$html .= " </ul>";
return $html;
}

Article taken from http://www.webmediahutch.com/customizing-primary-menu-links-drupal-7