Hey folks. I'm trying to change a few things on my site using CSS based on the section being viewed. I am sectioning off my site using taxonomy. I've used the taxonomy theme module in the past, but because I only want to change a couple CSS values, that's very inefficient and difficult to deal with.

After looking for a good solution, I discovered that it's fairly easy to give the body tag a class based upon which taxonomy is being viewed (I grabbed this code snippit from http://drupal.org/node/67587 ). The following code placed in the template.php file accomplishes this basic task:

<?php
function _phptemplate_variables($hook, $vars) {
  if ($hook == 'page') {
    $prefix = ' b-tax-';
  }
  if ($hook == 'node') {
    $prefix = ' tax-';
  }
  if (module_exists('taxonomy') && $vars['node']->nid) {
    foreach (taxonomy_node_get_terms($vars['node']->nid) as $term) {
      $vars['node_terms'] = $vars['node_terms'] . $prefix . eregi_replace('[^a-z0-9]', '-', $term->name);
    }
  }
  return $vars;
}
?>

All I need to do then is add class="<?php print $node_terms; ?>" to the body tag and I have a body class based on taxonomy. Awesome, right?

So here's what I need help with. I know 0 PHP and I'd like to extend this code a bit to include checking for the front page as well as having it hook into pages made with views.

My front page consists of no direct content and instead I use blocks generated by views to display only a few teasers from each taxonomy group.

If anyone could help me out with this, I'd love them forever :)

Thanks!

Comments

kulfi’s picture

From the Zen theme:

function _phptemplate_variables($hook, $vars = array()) {
 ...
  switch ($hook) {
    case 'page':
 ...
      $body_classes = array();
      $body_classes[] = ($vars['is_front']) ? 'front' : 'not-front';
      $body_classes[] = ($vars['logged_in']) ? 'logged-in' : 'not-logged-in';
      if ($vars['node']->type) {
        // If on an individual node page, put the node type in the body classes
        $body_classes[] = 'ntype-'. zen_id_safe($vars['node']->type);
      }
      if ($vars['sidebar_left'] && $vars['sidebar_right']) {
        $body_classes[] = 'both-sidebars';
      }
      elseif ($vars['sidebar_left']) {
        $body_classes[] = 'sidebar-left';
      }
      elseif ($vars['sidebar_right']) {
        $body_classes[] = 'sidebar-right';
      }

/** including some of the snippet in your post **/
  if (module_exists('taxonomy') && $vars['node']->nid) {
    foreach (taxonomy_node_get_terms($vars['node']->nid) as $term) {
      $vars['node_terms'] = $vars['node_terms'] . 'b-tax-' . eregi_replace('[^a-z0-9]', '-', $term->name);
    }
  }
/** /including some of the snippet in your post **/

      $vars['body_classes'] = implode(' ', $body_classes); // implode with spaces

      break;
 ...
}

and in page.tpl.php

<body class="<?php print $body_classes; ?>">

Hope that works!

MichaelJohnston’s picture

Oh my gosh, thanks! I think I'll just go with the Zen theme, actually. It seems like it's made for this type of thing moreso than Bluemarine.

Thanks dude, you rock!

td540’s picture

This the exact type of function i need, but alas, it doesn't work in Zen Theme 6.x-1.0-beta3
Can somebody help me?

kulfi’s picture

Look at the handbooks regarding theming Drupal 6. The _phptemplate_variables function has been replaced with multiple preprocess functions.

td540’s picture

This is the original zen (6.x-1.0-beta3) preprocess page function with the same code I copied from the first post.
I need the taxonomy terms to be listed in the body class=""

function mythemename_preprocess_page(&$vars, $hook) {

  if (theme_get_setting('zen_breadcrumb_title') && $vars['breadcrumb']) {
    $vars['breadcrumb'] = substr($vars['breadcrumb'], 0, -6) . $vars['title'] . '</div>';
  }

  // Add conditional stylesheets.
  if (!module_exists('conditional_styles')) {
    $vars['styles'] .= $vars['conditional_styles'] = variable_get('conditional_styles_' . $GLOBALS['theme'], '');
  }

  // Classes for body element. Allows advanced theming based on context
  // (home page, node of certain type, etc.)
  $body_classes = array($vars['body_classes']);
  if (!$vars['is_front']) {
    // Add unique classes for each page and website section
    $path = drupal_get_path_alias($_GET['q']);
    list($section, ) = explode('/', $path, 2);


    $body_classes[] = zen_id_safe('page-' . $path);
    $body_classes[] = zen_id_safe('section-' . $section);
    if (arg(0) == 'node') {
      if (arg(1) == 'add') {
        if ($section == 'node') {
          array_pop($body_classes); // Remove 'section-node'
        }
        $body_classes[] = 'section-node-add'; // Add 'section-node-add'
      }
      elseif (is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
        if ($section == 'node') {
          array_pop($body_classes); // Remove 'section-node'
        }
        $body_classes[] = 'section-node-' . arg(2); // Add 'section-node-edit' or 'section-node-delete'
      }
    }
  }

  if (theme_get_setting('zen_wireframes')) {
    $body_classes[] = 'with-wireframes'; // Optionally add the wireframes style.
  }


/** ↓↓↓ NOT WORKING ↓↓↓  **/

  if (module_exists('taxonomy') && $vars['node']->nid) {
    foreach (taxonomy_node_get_terms($vars['node']->nid) as $term) {
      $vars['node_terms'] = $vars['node_terms'] . 'b-tax-' . eregi_replace('[^a-z0-9]', '-', $term->name);
    }
    $body_classes[] = $vars['node_terms'];
  }

/** ↑↑↑ NOT WORKING ↑↑↑ **/



  $vars['body_classes'] = implode(' ', $body_classes); // Concatenate with spaces
}
td540’s picture

it's the foreach thing that doesn't seem to be working...

    foreach (taxonomy_node_get_terms($vars['node']->nid) as $term) {
      $vars['node_terms'] = $vars['node_terms'] . 'b-tax-' . eregi_replace('[^a-z0-9]', '-', $term->name);
    }
td540’s picture

Ok... figured it out.

People who want to use taxonomy terms listed in the zen theme,
put this code into your template.php file.

function yourthemename_preprocess_page(&$vars, $hook) {
  // Add an optional title to the end of the breadcrumb.
  if (theme_get_setting('zen_breadcrumb_title') && $vars['breadcrumb']) {
    $vars['breadcrumb'] = substr($vars['breadcrumb'], 0, -6) . $vars['title'] . '</div>';
  }

  // Add conditional stylesheets.
  if (!module_exists('conditional_styles')) {
    $vars['styles'] .= $vars['conditional_styles'] = variable_get('conditional_styles_' . $GLOBALS['theme'], '');
  }

  // Classes for body element. Allows advanced theming based on context
  // (home page, node of certain type, etc.)
  $body_classes = array($vars['body_classes']);
  if (!$vars['is_front']) {
    // Add unique classes for each page and website section
    $path = drupal_get_path_alias($_GET['q']);
    list($section, ) = explode('/', $path, 2);

    $body_classes[] = zen_id_safe('page-' . $path);
    $body_classes[] = zen_id_safe('section-' . $section);
    if (arg(0) == 'node') {
      if (arg(1) == 'add') {
        if ($section == 'node') {
          array_pop($body_classes); // Remove 'section-node'
        }
        $body_classes[] = 'section-node-add'; // Add 'section-node-add'
      }
      elseif (is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
        if ($section == 'node') {
          array_pop($body_classes); // Remove 'section-node'
        }
        $body_classes[] = 'section-node-' . arg(2); // Add 'section-node-edit' or 'section-node-delete'
      }
    }
  }

  if (theme_get_setting('zen_wireframes')) {
    $body_classes[] = 'with-wireframes'; // Optionally add the wireframes style.
  }


  if (module_exists('taxonomy') && $vars['node']->nid) {
    foreach (taxonomy_node_get_terms($vars['node']) as $term) {
    $body_classes[] = 'tax-' . eregi_replace('[^a-z0-9]', '-', $term->name);
    }
  }

  $vars['body_classes'] = implode(' ', $body_classes); // Concatenate with spaces
}

schefz’s picture

thanks that works great!

drupal_jon’s picture

In Drupal 6 taxonomy_node_get_terms no longer takes a nid argument, it expects the node object instead. The quickest way to fix is to load the node object and then pass that to taxonomy_node_get_terms.

E.g.


$node = node_load($vars['node']->nid);
foreach (taxonomy_node_get_terms($node) as $term) {
$vars['node_terms'] = $vars['node_terms'] . 'b-tax-' . eregi_replace('[^a-z0-9]', '-', $term->name);
}

bmango’s picture

Hi there,

I'm trying to do the same thing as MichaelJohnston. I have different sections on my website which need to be themed differently. I was looking for an easy solution (my PHP is fairly basic) and they all seem fairly complex. However I have found two approaches that work for me and are easy to implement and don't entail more than 10 lines of code.

The first is to use the taxonomy approach and add a taxonomy term to the body class. This works well except for views. The other approach is to use part of the URL - I use Pathauto where each section has a different prefix for the URL which can then be extracted and added to the body class.

With the help of drupal_jon above, my code for the taxonomy which I put into template.php was:

function yourtheme_preprocess_page(&$vars, $hook) {
	$node = node_load($vars['node']->nid);
	foreach (taxonomy_node_get_terms_by_vocabulary($node,1) as $term) {
		$vars['body_class'] = $vars['body_class'] . ' ' . strtolower(eregi_replace('[^a-z0-9]', '', $term->name));
	}	
}

In taxonomy_node_get_terms_by_vocabulary($node,1), "1" is the vocabulary I'm using to denote the section style.

Using the URL approach, the code I used is:

function ben_preprocess_page(&$vars) {
			$alias=drupal_get_path_alias($_GET['q']);
			$alias=explode('/',$alias);
			if ($alias[0]=="") {$alias[0]="home";}
			$vars['body_class'] = $alias[0];
} 

This gets the first section after the main URL.

For both methods I then updated the body class line in page.tpl.php to

<body class="<?php print $body_classes . ' ' . $body_class; ?>">

I thought it might be helpful to other people to add these as snippets? As my PHP is basic if anyone has a minute to see if I have missed anything, otherwise I could add them.

miro.log’s picture

In Zen 6.x-2.0 I had it working by modifying the above body class line in page.tpl.php to

<body class="<?php print $classes . $body_class; ?>">

thinkingcap’s picture

I think that it should be:

<?php
function yourtheme_preprocess_page(&$vars, $hook) {
    $node = node_load($vars['node']->nid);
    foreach (taxonomy_node_get_terms_by_vocabulary($node,1) as $term) {
        $vars['body_classes'] = $vars['body_classes'] . ' ' . strtolower(eregi_replace('[^a-z0-9]', '', $term->name));
    }   
}
?>