Hope I'm posting this in the correct place.

I've researched this problem for days now and have found several forum posts that relate to this issue as well as my own posts have not yielded a good solution so I thought it might warrant a change to the Drupal core. I'm no expert with Drupal, but I would imagine this is a very minor fix.

Currently the HTML output for the View / Edit tabs that content managers can see is:

<ul class="tabs primary">
<li class="active">
<a class="active" href="#">View</a>
</li>
<li>
<a href="/node/1/edit">Edit</a>
</li>
</ul>

While its possible to differentiate between active and non-active tabs, you can't easily style a View tab differently than an Edit tab. I've looked at the API and using the theme engine with no success. The only suggestion I could find was a forum post where the poster wanted to avoid a brute force method using regexp's.

The easy solution I think would be to give each <li> in the tabs list a unique ID or Class in the core.

For instance:

<ul class="tabs primary">
<li id="view" class="active">
<a class="active" href="#">View</a>
</li>
<li id="edit">
<a href="/node/1/edit">Edit</a>
</li>
</ul>

This would allow easy customisation of these links. For example CSS could be used to give one icon for edit, and another for view.

Comments

dman’s picture

Whatchoo talking about core?
That's a theme job.
print theme('links', $primary_links, array('class' => 'links primary-links'))
means you can tweak your own theme_links() function as much as you want.

Theme_links looks a bit more complicated that I'd expect, but still ... Copy and replace it.


/**
 * Return a themed set of links.
 *
 * @param $links
 *   A keyed array of links to be themed.
 * @param $attributes
 *   A keyed array of attributes
 * @return
 *   A string containing an unordered list of links.
 */
function yourtheme_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 = '';

      // Automatically add a class to each link and also to each LI
      if (isset($link['attributes']) && isset($link['attributes']['class'])) {
        $link['attributes']['class'] .= ' ' . $key;
        $class = $key;
      }
      else {
        $link['attributes']['class'] = $key;
        $class = $key;
      }

      // Add first and last classes to the list of links to help out themers.
      $extra_class = '';
      if ($i == 1) {
        $extra_class .= 'first ';
      }
      if ($i == $num_links) {
        $extra_class .= 'last ';
      }

/// Slight modification here - add an ID also for CSS
$id = 'menu-'.preg_replace(strtolower("/[^a-z0-9]+/","-",$link['title']));

      $output .= '<li class="'. $extra_class . $class .'" id="'. $id .'" >';
/// ... to here

      // Is the title HTML?
      $html = isset($link['html']) && $link['html'];

      // Initialize fragment and query variables.
      $link['query'] = isset($link['query']) ? $link['query'] : NULL;
      $link['fragment'] = isset($link['fragment']) ? $link['fragment'] : NULL;

      if (isset($link['href'])) {
        $output .= l($link['title'], $link['href'], $link['attributes'], $link['query'], $link['fragment'], FALSE, $html);
      }
      else if ($link['title']) {
        //Some links are actually not links, but we wrap these in <span> for adding title and class attributes
        if (!$html) {
          $link['title'] = check_plain($link['title']);
        }
        $output .= '<span'. drupal_attributes($link['attributes']) .'>'. $link['title'] .'</span>';
      }

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

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

  return $output;
}

Beware that, among other things, having multiple identical IDs in the page makes it invalid XHTML. Trivial, but annoying.

dman’s picture

Whoops, I was thinking primary links when you said tabs ...
The real func for you to theme is, um:

theme_menu_local_tasks()
menu_primary_local_tasks
menu_local_tasks()
theme_menu_local_task()

and ... hm. The link is already HTML-ed by then.

You have a point. Could be themed, but only by copying each of the above functions into your own version.
Sorry.

monkeybeach’s picture

Hm, well if I use that code it just generates another version of my primary links with extra identical (and therefore invalid ) ID's as you warned.

But that's not the menu I want to amend - in fact I wouldn't want to because its links have unique identifying classes already. After a bit of experimentation altering the code doesn't help me change the menu output in page.tpl.php by the $tabs variable, where there is no way to differentiate between the two links it contains.

Sorry, I might be misunderstanding the code here. I'm not an expert Drupal/PHPer by any means - thanks for the reply though! I've not had one on the support forum for this issue.

monkeybeach’s picture

Oops, think we cross-posted. Yeah it is tricky! I'll keep trying to hack round it but I would think just altering Drupal to give them classes by default would be really helpful :)

keesje’s picture

I'm having the same needs; individual styling of (edit and view) tabs.

This is the hack I use in my page.tpl.php:

    $tabs = str_replace('>Edit</a></li>', ' id="edit_tab">Edit</a></li>', $tabs) ;
    $tabs = str_replace('>View</a></li>', ' id="view_tab">View</a></li>', $tabs) ;

It's plain dumb replacemement, and does not work for other languages unless you add more replacement code.
But still, it's better than theming 4 different core functions to me.

Adding ID's or classes to tabs would increase Drupal's user experience dramaticaly.
Please provide it in core.

dvessel’s picture

Version: 5.1 » 6.x-dev
Component: base system » theme system
Priority: Minor » Normal

Here's a solution for Drupal 5. http://drupal.org/node/155418#comment-255822

How about something for D6 so we don't have to override anything?

dvessel’s picture

keesje’s picture

Thanks for pointing to discussion and providing patch for 6.x.

sun’s picture

Status: Active » Closed (duplicate)

Thanks for taking the time to report this issue.

However, marking as duplicate of #164608: Supply classes to local tasks (tabs).. You can follow up on that issue to track its status instead. If any information from this issue is missing in the other issue, please make sure you provide it over there.

For D6 and below, this cannot be changed anymore.