4

I have asked exactly this question on Stack Overflow, but it makes more sense to ask it here.

I'm trying to make the text between my tag not display by wrapping it in a and then styling that.

I've added the following function to my template.php file, but I cannot see any difference on the front end; the span just does not appear. (I have cleared my cache.)

Am I using the right function? What am I doing wrong?

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

6 Answers 6

8

Rather than building the anchor tag, and passing the result of url() to check_plain(), you should call l(), which builds the tag for you.
Remember to set $options['html'] to TRUE (where $options is the last parameter passed to l()), when the string you pass as first argument to l() contains HTML tags; by default the function assumes $options['html'] is FALSE.

4

Have a look at http://drupal.org/node/457740 / http://drupal.org/node/988842 and the devel / theme developer module might be useful too.

I think the function your using is for Links in general and is non specific to any menu..

function THEMENAME_links__system_MENUNAME_menu($variables) {
  $output = '';
  foreach ($variables['links'] as $link) {
    $output .= l('<span>'. check_plain($link['title']) .'</span>', $link['href'], $link);
  }
  return $output;
}

EDIT: included span.

8
  • Thanks, I sort of follow what you are saying, but I think my issue is that I have to add the <span> tags inside the <a> tag, so that I can make the text in the <a> tag not appeary, but still have the hyperlink. So I need to override the function that actually ouputs the final html snippet. Commented Mar 31, 2011 at 9:22
  • Are you trying to make the text disappear simply for aesthetics, such as using an image button?
    – WestieUK
    Commented Mar 31, 2011 at 9:24
  • yes, that is exactly what I am trying to do. Commented Mar 31, 2011 at 9:26
  • Tried css text-indent:-9999em; ?
    – WestieUK
    Commented Mar 31, 2011 at 9:29
  • 1
    You need also to report to l() that the first parameter contains HTML tags; this is done adding 'html' => TRUE in the array passed as last parameter.
    – avpaderno
    Commented Mar 31, 2011 at 17:21
2

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

  $title = $element['#title'];

// I put the span tags in the title.
  $element['#title'] = '<span class="yourclass1"></span><span class="yourclass2">' . $title . '</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";
}
2

This outputs the same result than the code shown by Taerno, and it works fine in Drupal 7.12.

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

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

  $element['#localized_options']['html'] = TRUE;
  $linktext = '<span class="your_class">' . $element['#title'] . '</span>';

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

You could add in the following code, where "menu_link__menu_block__1" is the name of your menu.

if ($element['#theme']['0'] == 'menu_link__menu_block__1') {

}

I found the name of the menu by printing $element['#theme']['0'] for my menu.

I am trying to add the span to the parent link only, so I will post when I have done that.

1
  • I think this is the cleaneast solution so far, but two more things: 1. For security reasons you should use check_plain($element['title']) to sanitize the title before echoing it 2. You could use the hook yourtheme_menu_link__menu_block__1 to avoid the if condition
    – Nebel54
    Commented Apr 27, 2012 at 15:52
1

You might be interested in the Theme Developer module. It lets you click on elements of a Drupal page to discover which theme function/template generated them, what arguments were passed in, which alternatives are available, etc.

1
  • Thanks, I have that installed already. When I click on a menu item I get the following: parent links__system_main_menu and Function called: Them_link() - Hence me trying to override the link function. Commented Mar 31, 2011 at 9:10
1

Most of the cases where you would have needed an extra span before can now be solved with css only:

li {
  position: relative;
  padding-left: 25px;
}

li:before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 20px;
  height: 20px;
  background: url('../images/icons.png') no-repeat;
  background-position: 0 0;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.