I want to make the primary and secondry links looks like this format: links1 | links2 | links3 | link4

There are tons of solutions for drupal4 and drupal5, but none for drupal 6.

Is there any one knows how to make it work? Thanks!!

Plus: I don't like the CSS solution for the reason of IE7 and IE6 problem!!

Comments

luisfeng’s picture

Give me a hand! Guys!!

luisfeng’s picture

Anybody? How to make a "links1 | links2 | links3 | link4" style primary links?

dman’s picture

Being patient is good.
Even better is explaining what you have tried so far and perhaps a link to the documentation you have already read and saying what's unclear or not working with it. That way we can fix the docs!

OK.

step 1

If you look at your page.tpl.php you will see
print theme('links', $primary_links, array('class' => 'links primary-links'))

- that tells us that the function currently making the links look like they do is called
theme_links()
There is magic that takes theme('links', and looks for theme_links() ... or yourtemplate_links() from your theme where possible. This is basic Drupal theming.

step 2

- find the basic theme_links() function in your drupal files. Do a search. But it's probably in includes/theme.inc today. Yes.

step 3

- copy ALL of

function theme_links($links, $attributes = array('class' => 'links')) {
...[all the function stuff]
}

from the source file into your current themes template.php file.
And rename it after your theme. If your theme is called 'woosh' then the function becomes

function woosh_links($links, $attributes = array('class' => 'links')) {
...
}

step 4

- change it as needed.

... That's the basic process for ALL theme modifications you want to make.

BUT be careful because the them_links() function is used in many many places throughout Drupal, and making this change here will probably affect other places where lists of displays are shown also. So you need to be clever.

An example (not too clever, but pretty simple for you today) might be:

/**
 * Return a themed set of links.
 * An override of theme_links()
 * Modified to use simple text styling instead of HTML & CSS
 *
 * @see theme_links
 */
function mytheme_links($links, $attributes = array('class' => 'links')) {
  $output = '';

  // Change the way primary links are rendered
  if($attributes['class'] == 'links primary-links') {
    $linklist = array();
    foreach ((array)$links as $key => $link) {
        $linklist[] = l($link['title'], $link['href'], $link);
    }
    // Return the links joined by a '|' character
    return join(' |', $linklist);
  }
  // Normal theming continued below:

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

:-B

This is not tested - may have a typo as it's just out of my head. And It's Drupal 6. The same PROCESS with different code will work for all versions.

Nor is it the best formatting - you will loose the LI styles that it used to have. You can try to put them back if you can handle the CSS. But it's what you asked for, and LIs do not like being joined with characters like that.
Anyway, that's a lot of guidelines on how to proceed.

There are other approaches - eg you can instead just stop using print theme('links', ...) at all and just do the rendering in-page if you find that easier. But this theme-override is the generic way of changing anything you see.

If anyone thinks this is a useful instruction and it works we can add it to The handbook page on "Changing the delimiter on primary/secondary links" so it can be used later.
This is why links to the incomplete docs are useful!

.dan.
How to troubleshoot Drupal | http://www.coders.co.nz/

lionstone’s picture

Just whipped this up... just stick this in template.php and you should be good to go.

/**
* Return a themed set of links delimitated by "|"
* An override of theme_links()
*
* @see theme_links
*/
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'] || ($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>';
      }

			$delimiter = '<li class="delimiter">|</li>';

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

      $i++;

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

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

  return $output;
}


ocelotspot86’s picture

Thank you so much for this code snippet! It works great. I am trying to do something similar. I have an image that I would like to use as a delimiter. I have replaced the following:

$delimiter = '<li class="delimiter">|</li>';
<

with

$delimiter = '<li class="delimiter"><img src="http://ocelot.stonesharkdesign.com/sites/ocelot.stonesharkdesign.com/themes/ocelotspot/small-orange-pawprint.png" /></li>';

because I want to display an image as opposed to a "|" as a delimiter. However, I'm having trouble getting it to work when I use anything other than the absolute path. For example, I tried using just the image name since it's in the same folder, but no luck. The image I want is called "small-orange-pawprint.png" and is in my "ocelotspot" theme folder. I would like to use this as a theme, and therefore need it to be set up with the relative path.

Any suggestions? Any help at all would be appreciated.

bigjim’s picture

ocelotspot86

try this

$delimiter = '<img class="delimiter" src="'.drupal_get_path('theme', 'mytheme').'/images/main_nav_divider.png" />';
ocelotspot86’s picture

Thank you for helping me out with this! I couldn't seem to find a working example anywhere. Here is what I ended up using (I had to add an extra forward slash):

$delimiter = '<li class="delimiter"><img class="delimiter" src="/'.drupal_get_path('theme', 'ocelotspot').'/images/small-orange-pawprint.png" /></li>';

where ocelotspot is the name of my theme.

dagomar’s picture

I have a slightly different approach. Sometimes I have to alter a menu in such a fashion that it is not a good idea to use an override for "theme_links", because the use of conditional statements results in a lot of code and it can be a bit confusing. So I created a tiny little module that adds a new theme hook to drupal, which can then be called from within the theme. so instead of calling theme('links', $primary_links, array('id' => 'nav', 'class' => 'links')); I can use theme('myCustomModuleLinksTheme', etc etc). This will then leave theme_links intact, so there won't be any problems with menu's in other places. I'll post the code for my module, which is called "menuminimodule":

first the file menuminimodule/menuminimodule.info

; $Id$
name = Menu Mini Module
description = This module adds an extra theme_links hook to drupal, can be called with theme('menuminimodule', $linksarray, $options);
core = 6.x

and the file menuminimodule/menuminimodule.module

function menuminimodule_theme () { 
	return array(
    'menuminimodule' => array( 
      'arguments' => array('links' => NULL, 'attributes' => NULL),
    ),
  );
	
}

function theme_menuminimodule ($links, $attributes = array('class' => 'links')) { 
/**
 * 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.
 */

  global $language;
  $output = '';

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

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

    foreach ($links as $key => $link) {
      $class = $key;
$class .= ' linknr' . $i;
      // 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->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);
      }
      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;
}

If you need to have more menu's, you can just duplicate the module. I like this solution because it makes it portable, whenever I start a new site I only have to copy the module and have the new theme_hook available.

Dagomar Paulides
B.A. Digital Media Design
Partner @ Online Agency

sdmaxey’s picture

I'm trying to figure out how to adapt the instructions here to make a more thorough change to the primary links.

In short, because IE7 doesn't recognize the CSS display: table-cell; (or any of the related table item display settings in CSS), I need to convert the primary links (and only the primary links) to a table.

I can overwrite theme_links with sitename_links theming so that ALL links are displayed in a table.

But when I try to adapt the instructions above and identify the primary links by their class or by their id of primary, both the primary links and the inline-links inside the node content disappear completely, but the secondary links display properly as an unordered list using theme_links

I feel like I'm missing something obvious.

The primary links are built from taxonomy terms using taxonomy menu and reside in the theme's navbar region, and navbar itself is turned off in the theme preferences.

ellieelectrons’s picture

Hi All

I tried to implement a number of the solutions above but I'm guessing that my custom template CSS was conflicting with the drupal's CSS and I couldn't get it to work. No matter what I did, I could not get the delimeter to display.

I used this web page:
http://www.alistapart.com/articles/taminglists/
to develop a different solution.

It only works if you want to use a | (pipe) symbol as it uses borders to emulate the pipe.

I wanted the pipe delimiter to separate the items in my secondary links section which appears at the top of my page.

On my site, the HTML for the secondary links menu looks like this:

I added the following to my template's CSS

#header #header-links ul#subnavlist{
margin-left: 0;
padding-left: 0;
display: inline;
}

#header #header-links ul li{
margin-left: 0;
padding: 0px 5px;
border-left: 1px solid #838181;
list-style: none;
display: inline;
}

#header #header-links ul li.first{
margin-left: 0;
border-left: none;
list-style: none;
display: inline;
}

It works by:
(i) displaying the list horizontally (using the display:inline command)
(ii) adding a border to the left of each item in the list (border-left: 1px solid #838181;)
(iii) not displaying any border for the list item tagged as being first (border-left: none;)

I'm not a drupal expert nor a CSS expert. This solution seems to work for me in firefox and IE. If it's not cross-browser appropriate or anything, please let me know.

I think my client would think I'm nuts if they knew how long it took me to get the pipe symbol displaying!

yours in drupal

ellie electrons.