background image
HomeRecent PostsDrupalSearchTagsRSSContactAboutAccount
Eric.London's picture

The Devel module has a great feature called Theme Developer which makes theming a breeze. When enabled, you'll see a box in the bottom left of your browser window, themer info. This functionality helps answer the question: how do I change the way this piece of my theme looks? If you enable the themer info checkbox and moveover your theme, you'll noticed that various html structures will be highlighted in red, very much like the essential Firefox plugin, Firebug.

Let's say you wanted to redesign the appearance of the search form in your theme. If you click on search form using the themer info, you'll get a window full of useful information, similar to this:

This window tells you which functions and templates are used to create the html, and which functions and templates you can define to override the themable output. Check out the section called "File used". It should tell you that the search form uses it's own template file found here: modules/search/search-theme-form.tpl.php. In this case, we're in luck. You can simply copy that file into your theme directory and modify it as necessary.

In other situations, a function is used instead of a template tpl.php file. If you use the themer info tool and click on the navigation menu you'll notice a function was used (theme_menu_tree):

To modify the themable output, you'll have to create a function in your template.php called YOURTHEME_menu_tree. Before you go any further, read the API documentation for the function your are replacing. For this example, browse to: http://api.drupal.org/api/function/theme_menu_tree. Since Drupal will be passing a predefined set of arguments to our new function, it's best practice to use the same number and name of arguments that Drupal uses. Check out the sections in the API documentation called definition and code. You'll see that the theme_menu_tree function accepts one argument ($tree):

<?php
theme_menu_tree
($tree);
?>

So, in your template.php file, define your new function. The first thing you should do it get acquainted with the structure of the arguments and what the function returns (array, object, html, etc). In the code below, I'm using the PHP function print_r to show the structure of the argument. Now, you can modify to your heart's content.

<?php
function MYTHEME_menu_tree($tree) {
  print
"<pre>" . print_r($tree, true) . "</pre>";
}
?>

Now, you should be on your way to overriding the themable output of any piece of your site.

Eric.London's picture

At some point, you may need to change a link in the breadcrumbs. I put this function in my theme's template.php file to overrides the theming of the breadcrumbs and manually replace one of the links.

<?php
function MYTHEME_breadcrumb($breadcrumb) {
  if (!empty(
$breadcrumb)) {
   
// loop through breadcrumbs
   
foreach ($breadcrumb as $k => $v) {
     
// convert a tag into xml
     
$o = simplexml_load_string($v);

     
// replace link
     
if ($o['href']=='/OLDLINK') {
       
// create new link
       
$breadcrumb[$k] = l($o, 'NEWLINK');
      }
    }

    return
'<div class="breadcrumb">'. implode(' » ', $breadcrumb) .'</div>';
  }
}
?>

Eric.London's picture

Here's a quick snippet to add the current page to the breadcrumbs. I added this code to my template.php file.

<?php
function MYTHEME_breadcrumb($breadcrumb) {
  if (!empty(
$breadcrumb)) {
   
// add current page
   
$breadcrumb[] = l(drupal_get_title(), $_REQUEST['q']);
    return
'<div class="breadcrumb">'. implode(' » ', $breadcrumb) .'</div>';
  }
}
?>

Today I wanted to add a unique identifier to each menu item in the primary links so I could theme each one individually. In this example, I added a incrementing class to each menu item so I could add an image via css. Here's a snippet of my theme function (found in template.php):

<?php
function MYTHEME_preprocess_page(&$variables) {
 
$linkCount = 0;
  foreach (
$variables['primary_links'] as $k => $v) {
   
$linkCount++;
   
$class = trim($v['attributes']['class'] . " nav$linkCount");
   
$variables['primary_links'][$k]['attributes']['class'] .= $class;
  }
}
?>

Adding this code to your Drupal site can improve two sections of a YSlow report, "Make fewer HTTP requests" and "Minify JS". This function minifies and aggregates your javascript into a single file. It requires the Google code library jsmin-php (http://code.google.com/p/jsmin-php/).

Stick this function in your template.php file in your theme directory:

<?php
function minify_scripts($scripts) {

 
// define paths
 
$jsMinFileName = 'jsmin_minified.js';
 
$jsMinAbsolutePathDir = getcwd() . '/' . file_directory_path();
 
$jsMinAbsolutePath = $jsMinAbsolutePathDir . '/' . $jsMinFileName;
 
$jsMinRelativePath = base_path() . file_create_path($jsMinFileName);   
   
 
// check to see if file is writable
 
if (
    (!
file_exists($jsMinAbsolutePath) && !is_writable($jsMinAbsolutePathDir))
    ||
    (
file_exists($jsMinAbsolutePath) && !is_writable($jsMinAbsolutePath))
    ) {
    return
$scripts;   
  }
   
 
// include js minify library
 
require_once('jsmin-1.1.1.php');

 
// split $scripts on new line
 
$exploded = explode("\n", trim($scripts));

 
$minifiedJS = "";
  foreach (
$exploded as $k => $v) {

   
// ensure this line is javascript
   
if (!(substr($v,0,7)=='<script' && substr($v,-9)=='</script>')) continue;
       
   
// convert <script> to xml
   
$xml = simplexml_load_string($v);
       
    if (
$xml['type']=='text/javascript' && strlen($xml['src'])) {

     
// define path to old file
     
$oldFile = getcwd() . $xml['src'];
           
     
// minify javascript
     
$minifiedJS .= JSMin::minify(file_get_contents($oldFile));

     
// unset exploded array entry
     
unset($exploded[$k]);
           
    }
       
  }
   
 
// check to see if javascript has not been minified
 
if (strlen($minifiedJS)==0) return $scripts;

 
// write file
 
file_put_contents($jsMinAbsolutePath, $minifiedJS);
   
 
// re-index array
 
sort($exploded);

 
// add entry
 
$exploded[] = "<script type='text/javascript' src='$jsMinRelativePath'></script>";
   
  return
implode("\n", $exploded);
   
}
?>

In your page.tpl.php theme file, replace this line...

<?php
print $scripts
?>

with
<?php
print minify_scripts($scripts);
?>

You can also improve your score in the "Put JS at the bottom" section by ensuring this line of code resides at the bottom of your page.tpl.php file. I insert it just before this line:

<?php
print $closure;
?>

Syndicate content