Hello everybody

I tried to get <span> tags inside the anchor tags of the primary links. In html I wanted it to look as follows:
<a href="URL"><span>link text</span></a>

Then I had a look at http://api.drupal.org/api/function/theme_links/6 and saw the following paragraph:

if (isset($link['href'])) {
  // Pass in $link as $options, they share the same keys.
  $output .= l($link['title'], $link['href'], $link);
}

I adjusted it to:

if (isset($link['href'])) {
  // Pass in $link as $options, they share the same keys.
  $output .= l('<span>' . $link['title'] . '</span>', $link['href'], $link['attributes'], $link['query'], $link['fragment'], FALSE, TRUE);
}

But all I got is that the <span> tags were printed out as part of the title text instead of interpreted as html code. Does anybody have any idea? Every help would be very appreciated!

Thanks in advance and best regards
phs

Comments

ipwa’s picture

Although it would be better to do it as a function, you could also go to your page.tpl.php file in the theme you are using, and add the span manually to the primary links.

HTH

Nicolas
-------------------------
http://nic.ipwa.net

Nicolas
-------------------------

phsc’s picture

Hi ipwa

Thanks for your reply, but as you already mentioned I actually want to do it as a function. ;-)

Greetings
phs

bluemuse’s picture

I'm struggling with just adding the span to the page.tpl.php file.

Right now I have:

 <?php if (isset($primary_links)) : ?>
        <?php print theme('links', $primary_links, array('class' => 'links primary-links')) ?>
        <?php endif; ?>

Where do I put the span to be inside the anchor tags? I realize this is a n00bish question. Maybe I'm missing something here?

AjK’s picture

If this is Drupal 6 add

  $links['html'] = TRUE;

for example:-

  $links[] = array(
    'title' => '<span>'. $title .'</span>',
    'href' => 'somelocalpath',
    'html' => TRUE,
    'attributes' => array(
      'title' => 'some nice hover alt text',
    ),
  );
  print theme('links', $links);

Setting the field html to TRUE ensures the title goes through a different filter to check_plain()

The other problem is that your adjustment of l() appears to be the Drupal 5 ways of doing things. If you are using Drupal 5 then don't be looking at the Drupal 6 API.

phsc’s picture

Hi AjK

Thank your for your answer. I will try it after work.
And you are right, my problem appears in Drupal 6, but previously I ran it in Drupal 5 and there it worked.

Best regards
phs

phsc’s picture

Hi AjK

This solved my problem! Thanks!

Best regards

Cocoon-1’s picture

Hi phs are you able to paste a working example here, my php is basic and I dont know what to do with the code AJK put through.

Thanks

phsc’s picture

Hi Cocoon

This is the whole function (from the file "template.php") where I had to make changes. Here you can easily see where AJKs code had to be applied.

function phptemplate_links($links, $attributes = array('class' => 'links')) {
  $output = '';

  if (count($links) > 0) {
    $output = '<ul'. drupal_attributes($attributes) .'>';

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

    foreach ($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']) {
        $class .= ' active';
      }
      $output .= '<li class="'. $class .'">';

      if (isset($link['href'])) {
        // Pass in $link as $options, they share the same keys.
        $link['html'] = TRUE;
        $output .= l('<span>'. $link['title'] .'</span>', $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>';
      }

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

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

  return $output;
}

Best regards
phs

AjK’s picture

Phs,

you've made a slight error here I think. In wanting to wrap your links in a span I was expecting the link title to be passed in as html and therefore the caller sets $link['html'] == TRUE in which case it's the callers responsibilty to do output filtering. However, I see you are actually overriding the theme_links() function in your theme layer. So, your code thus:-

      if (isset($link['href'])) {
        // Pass in $link as $options, they share the same keys.
        $link['html'] = TRUE;
        $output .= l('<span>'. $link['title'] .'</span>', $link['href'], $link);
      }

really should be done thus:-

      if (isset($link['href'])) {
        // Pass in $link as $options, they share the same keys.
        $link['html'] = TRUE;
        $output .= l('<span>'. check_plain($link['title']) .'</span>', $link['href'], $link);
      }

Notice the addition of the check_plain() function around the $link['title'] outside of the additional span html you placed in there?

The reason for that is by calling l() with the html flag true by passes it's internal security step of doing a check_plain() for you.

Why is it needed. Well, if you know the origin of every piece of text that will make a link title then it doesn't matter. But if you have any chance that untrusted user input could leak into a link title, you must close the potential XSS security hole1. And that means making sure untrusted user input is sanitized on output.

Further reading 1

adpo’s picture

Hi,
I need receive something like that:

<div id='navigation-primary'>
<li><span><span><span><span>Booby</span></span></span></span></li>
</div>

How can I insert without calling function:

Could you clean up my code:

<?php print theme('links', $primary_links, ?> '<span>'.'<span>'.'<span>'.'<span>'. <?php array('class' => 'links primary-links') '<span>'.'<span>'.'<span>'.'<span>') ?>
        <?php endif; ?>

Kind ragars,
Adrian

adpo’s picture

Hi, I have made chandes in:
1. page.tpl.php

<?php if (isset($primary_links)) : 

print theme('links', $primary_links, array('class' => 'links primary-links'))
endif;
?>

2. template.php

function theme_links($links, $attributes = array('class' => 'links')) {
  $output = '';

  if (count($links) > 0) {
    $output = '<ul'. drupal_attributes($attributes) .'>';

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

    foreach ($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 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>';
      }

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

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

  return $output;
}

but span tags are missing:

<li class="menu-115 first active">
<a class="active" title="Home Page" href="/stbrigid/node/1">Home Page</a>
</li>

I want receive:

<a class="active" href="/stbrigid/node/1">
<span class="tab">View</span>
</a>
nickbits’s picture

Hi All,

Fantastic work. I am having trouble following some of this though, specifically where the code should be going. I thought I had it, tried it, but nothing. Is there any chance of someone posting sample file(s) for this, that way I can compare excatly what I am doing and where.

Cheers,
Nick
----------------------------------
Nick Young
www.nickbits.co.uk

------------oOo----------------------
Nick Young (www.nickbits.co.uk)

jorisx’s picture

HOw can I change this code to get the "|"delimiter in the primary links

http://api.drupal.org/api/function/theme_links/6
??

in drupal 4.7 it was just one line of code>>

<?php
print theme('links', $primary_links, ' | ') 
?>

:-)

Http://www.reloadmedia.com

black2night’s picture

Thanks So much

OpenChimp’s picture

Thanks for the clear explanation on this.

danmurf’s picture

Hi

Thanks for this - it's working for me on D6. Although, it's only working for my Primary Links, not any other menu block. Is there any way to make this work on all Drupal menus (Navigation, etc)?

Many thanks
Dan

babbage’s picture

How ironic. I have some other, very similar code I obtained from a blog but it is not just putting the span tags around the titles of my primary links, but also killing the image-based links that two contrib modules I'm using have created... all I am trying to do is figure out how to restrict the effect to my primary menu! :)

beadysea’s picture

You can insert span tags on menu links by placing the following code in your themes template.php file.

<?php

function mytheme_menu_item_link($link) {
  if (empty($link['localized_options'])) {
    $link['localized_options'] = array();
  }
  $link['title'] = $link['title'] = '<span class="link">' . check_plain($link['title']) . '</span>';
  $link['localized_options'] += array('html'=> TRUE);
  return l($link['title'], $link['href'], $link['localized_options']);
}
?>

Remember to change "mytheme" to the name of your theme.

Note: The line $link['localized_options'] += array('html'=> TRUE); adds the html field to the options array and sets it to TRUE.

SeanBannister’s picture

If you use this method it won't work with the DHTML Menus Module because it won't hit theme_menu_item_link. In my case I didn't need DHTML Menus on the menu I was adding the span to so I turned it off.

randallnet’s picture

Edit your template.php file and use the preprocess_page function in D6.

function YOURTHEME_preprocess_page(&$vars) {
	
	$links = $vars['primary_links'];
	
	foreach ($links as $key => $link) {
		$links[$key]['html'] = true;
		$links[$key]['title'] = '<span>'. $link['title'] . '</span>';
	}
	
	$vars['primary_links'] = $links;
}

Change "YOURTHEME" with the name of your theme and that's all.

aldenjacobs’s picture

i have the same issue, and have spent two days on it :P

Can't figure anything out. It actually seems like my template.php isn't being recognized, because nothing i do to it (aside from improper code - like, the kind that throws errors) is recognized!

i've built the theme in question from scratch, and it's pretty bare-bones. Is there some type of code i need to put somewhere to get my template.php recognized?

FranCarstens’s picture

You've tried clearing your theme registry?

(This solution is also not working for me - no "span" tags appearing.)

-- If no-one asked Drupal questions there would be no Drupal answers --

unegro’s picture

In drupal 6, i need only to change template.php with this code?
I didn't make it work, have i missed something?

thanks!

kenorb’s picture

If you're using Superfish, use theme_superfish_menu_item_link() instead of theme_menu_link().
See: http://stackoverflow.com/questions/13477629/how-to-add-a-span-tag-to-a-c...