Customizing the Drupal 6 LiteJazz Theme - Custom Content Type Template

Submitted by nigel on Sunday 4th October 2009

Creating a custom content type in Drupal with additional fields requires the add-on CCK module, although at some stage (release 7?) it will be bundled in the Drupal release. CCK will be one of the first add-on modules you will install during any Drupal build, so I will assume you are familiar with the process. Similarly, creating a new content type is a trivial exercise requiring a little patience and numerous button clicks. Again, it is not worthy of further discussion here.

The problem with CCK is its node output functionality is extremely restrictive. If you want your page to display anything beyond a list of titles and fields, you need to look further. Thankfully, the module Content Templates (Contemplate) comes to the rescue. Install this and we can make a start with an example on how to create a customized template for the body and teaser of our Book Review content type. But first we have a dependency to resolve - for our content type we need to be able to display book covers in jpg format - so we need a module to upload an image, store it in a suitable place (NOT the Drupal site root directory!) and be accessible by CCK. For that, we'll use filefield

If you take a quick peek at one of my book reviews you'll notice that I have saved various fields associated with books, such as ISBN, author, publisher etc. These have been saved in my book_review content type. In addition, I have used the filefield module to save a path to my jpg cover picture.

Go to admin/content/types/templates and select the 'edit template' option against the book_review content type. Now, you will see the default templates for displaying the teaser and the body of the book reviews. Lets work on the body first, so copy all the PHP code in the body section into your clipboard for later use. Editing this PHP code would soon become a pain in the proverbial if we were constrained to editing in the small region on this page, so instead we need to set it up so it can be edited on disk. To do this you need to create a directory under sites/all called contemplates, and create a template file with the format node-[content type]-[content element] .tpl.php

$ mkdir sites/all/contemplates
$ touch sites/all/contemplates/node-book_review-body.tpl.php

Then open the node-book_review-body.tpl.php file in your favourite editor, and paste the template PHP code you previously copied into the clipboard.

Contemplates now knows to use the disk version of the template file rather than the database version, so any edits to the disk file will be used to output to the screen.

Ok - now lets sort out the template. I want the picture of the review book cover to float either left or right with text flowing around it. The left or right criterion adds a little bit of fun and requires the use of the PHP rand() function. The following block of code in the template file will achieve this - insert it at the top.

<div class='cover-<?php print (rand()&1) == 0 ? 'left' : 'right'; ?>'>
  <div class="field field-type-filefield field-field-cover">
  <div class="field-items">
      <div class="field-item"><img src="<?php print $node->field_cover[0]['filepath']; ?>" /></div>
  </div>
</div>
</div>
Also worthy of note is the variable reference $node->field_cover[0]['filepath'] which holds the path to the image of the cover jpg. This can be obtained, along with all the other variables pertaining to the node, back at admin/content/types/templates again. We also need the accompanying css code - so add the following blocks to the style.css file.
.cover-right {
  float:right;
  margin-top: 0px;
  margin-right: 0px;
  margin-bottom: 10px;
  margin-left: 10px;
  clear:none;
}
 
.cover-left {
  float:left;
  margin-top: 0px;
  margin-right: 10px;
  margin-bottom: 10px;
  margin-left: 0px;
  clear:none;
}
 
.cover-left img, .cover-right img {
  width:200px;
  border-width:1px;
  border-style: solid;
  border-color:black;
}
The template file has a sequence of automatically generated blocks of CSS/PHP code for each of the CCK fields. They require little modification for my use, apart from swapping a few divs and spans as I would like the content displayed inline. So each block looks like the segment below, only changing the variable name for each field. The publisher field is shown.
<div id="thmr_97" class="thmr_call">
  <span class="field field-type-text field-field-publisher">
  <span class="field-label">Publisher:</span>
  <span class="field-items">
      <span class="field-item"><?php print $node->field_publisher[0]['view'] ?></span>
  </span>
</span>
</div>
So far so good. Until we get to the Rating field which uses the fivestar module to draw the star ratings. This is not displayed inline - further explanation is given at http://drupal.org/node/317456 but basically this inability to display inline is a feature/shortcoming of the module. Time to think up a workaround. Ideally, it would be good to come up with an elegant css solution, but therein lies a problem. We are now into the realm of float within float which is a notorious prickly area and different browsers handle this in different ways. After five hours of experimentation with Opera/Firefox/Internet Explorer/Konqueror it became evident there was no one-size-fits-all solution. Sometimes for the sake of expedience, tough decisions need to be made, and I did not shirk that decision. Abandon the idea of nested floats and fall back on a good old HTML table to draw the stars. Inelegant? For sure! Timely? You betcha! A balance needs to be struck between crafting the most beautiful code and actually getting the work done. So, the table code is reproduced below.
<table border="0" cellpadding="0" cellspacing="0">
  <tr><td>
    <div id="thmr_100" class="thmr_call">
      <span class="field field-type-text field-field-rating">
       <span class="field-label">Rating:
       </span>
      </span>
     </div>
  </td><td>
     <span class="field-items">
       <?php print $node->field_rating[0]['view'] ?>
    </span>
  </td></tr>
</table>
We now need to repeat some of this to create a customized teaser for this content type. Again, we'll make editing easy for ourselves by creating a disk template.
$ cp sites/all/contemplates/node-book_review-body.tpl.php sites/all/contemplates/node-book_review-teaser.tpl.php
Note that our starting point is a copy of the body template. It requires little work - firstly crop all the unwanted blocks of code to display items such as the authors, publishers etc - all we need is the cover and the review, and while we are at it we'll rip out the randomize code so the image doesn't flip between left and right.
<div class='cover-left-teaser'>
  <div class="field field-type-filefield field-field-cover">
  <div class="field-items">
      <div class="field-item"><img src="<?php print $node->field_cover[0]['filepath']; ?>" /></div>
  </div>
</div>
</div>
 
<div id="thmr_3" class="thmr_call">
  <span class="field field-type-text field-field-body">
  <span class="field-items">
      <span class="field-item"><?php print $node->content['body']['#value'] ?></span>
  </span>
</span>
</div>
Secondly, we need to rescale the cover jpg because the body size of 200px is too large for a teaser. So, modify the cover-left tag with:
.cover-left, .cover-left-teaser {
  float:left;
  margin-top: 0px;
  margin-right: 10px;
  margin-bottom: 10px;
  margin-left: 0px;
  clear:none;
}
and add a new block of css for cover-left-teaser images
.cover-left-teaser img {
  width:100px;
  border-width:1px;
  border-style: solid;
  border-color:black;
}
Finished!
blog terms
Drupal Drupal 6 Litejazz