Theming a CCK node

sivaji's picture

In this blog post i would like to cover a bit about Theming a CCK node. CCK the Content Construction Kit is a drupal contrib module, provides features to extend the fields of drupal nodes.

My goal is to create a product listing directory using CCK / Views and to theme the node similar to the wireframe shown below. I assume the readers are familiar with creating CCK node and page views to list it.

listing-wireframe.png

To proceed with this i am going to use a node type called listing and turquoise theme created by us.

The fields of the listing nodes are as below

  • Product Name - Node Title
  • Description - Node body
  • Product image - CCK Image field
  • Company Name - CCK Text Field
  • Company Address - CCK Location Field (includes phone and fax)
  • Website - CCK Link Field
  • Email - CCK E-mail Field

I have created a sample listing type node whose default theme looks as below
before-theme.png

Fields title and its values appears on below the other. My interest is to have it something similar to the wireframe above.

To override the default node theme we need to create a node-[type].tpl.php where type is machine name of node type. In our case it is "listing" so lets create a node-listing.tpl.php by duplicating node.tpl.php

$content is the variable which holds the HTML of the region (displayed within a box in above image) that we need to theme.

Now we need to replace $content with our own code which will renders the node as per our wireframe. To proceed with this we need two helper module here devel and contemplate.

contemplate module will help us to find the code that need to be replaced instead of $content and devel to find the variables which prints the HTML of individual fields.

Install devel and contemplate module. Navigate to admin/content/node-type/listing/template path. The HTML obtained from Contemplate module corresponding to full view of Listing node is as follow

<div class="field field-type-filefield field-field-listing-product-image">
  <h3 class="field-label">Product Image</h3>
  <div class="field-items">
      <div class="field-item"><?php print $node->field_listing_product_image[0]['view'] ?></div>
  </div>
</div>

<div class="field field-type-text field-field-listing-company-name">
  <h3 class="field-label">Company Name</h3>
  <div class="field-items">
      <div class="field-item"><?php print $node->field_listing_company_name[0]['view'] ?></div>
  </div>
</div>

<div class="field field-type-link field-field-listing-website">
  <h3 class="field-label">Website</h3>
  <div class="field-items">
      <div class="field-item"><?php print $node->field_listing_website[0]['view'] ?></div>
  </div>
</div>

<div class="field field-type-email field-field-listing-email">
  <h3 class="field-label">E-mail</h3>
  <div class="field-items">
      <div class="field-item"><?php print $node->field_listing_email[0]['view'] ?></div>
  </div>
</div>

<div class="field field-type-location field-field-listing-company-address">
  <h3 class="field-label">Address</h3>
  <div class="field-items">
      <div class="field-item"><?php print $node->field_listing_company_address[0]['view'] ?></div>
  </div>
</div>

Replace the above code in the place of $content i.e the above HTML should go under <div class="content"> tag

We need to make two changes in the above code

  • All the Literals in drupal need to be passed through the t() function. So make sure the field titles like website, E-mail etc. is passed through t() function.
  • In the above code Description field which is a node body is missing, add it below "Product Image".
  •   <div class="field field-type-textarea field-field-listing-description">
          <h3 class="field-label"><?php print t('Description') ?></h3>
          <div class="field-items">
              <div class="field-item"><?php print $node->content['body']['#value'] ?></div>
          </div>
        </div>

    Now we have HTML file which renders the node we can decide the order in the node elements to be rendered. And using CSS we can control the height, width and position of individual elements. Now we need to create a new CSS file say node-listing.css. The CSS file need to be loaded whenever a listing type node is displayed.

    To do this we need to add drupal_add_css() function on the top of node theme file node-listing.tpl.php.

    drupal_add_css(drupal_get_path('theme', 'turquoise') . '/node-listing.css');

    Here the final code that replaces $content

        <div class="field-image-description">
          <div class="field field-type-filefield field-field-listing-product-image">
            <h3 class="field-label"><?php print t('Product Image') ?></h3>
            <div class="field-items"><?php print $node->field_listing_product_image[0]['view'] ?></div>
          </div>
          <div class="field field-type-textarea field-field-listing-description">
            <h3 class="field-label"><?php print t('Description') ?></h3>
            <div class="field-items"><?php print $node->content['body']['#value'] ?></div>
          </div>
        </div> <!-- end field-image-description -->
        <div class="field-address-contact">
          <div class="field-address">
            <div class="field field-type-text field-field-listing-company-name">
              <h3 class="field-label"><?php print t('Company Name') ?></h3>
              <div class="field-items"><?php print $node->field_listing_company_name[0]['view'] ?></div>
            </div>
            <div class="field field-type-location field-field-listing-company-address">
              <h3 class="field-label"><?php print t('Address') ?></h3>
              <div class="field-items"><?php print $node->field_listing_company_address[0]['view'] ?></div>
            </div>
          </div> <!-- field address -->
          <div class="field-contact">
            <div class="field field-type-link field-field-listing-website">
              <h3 class="field-label"><?php print t('Website') ?></h3>
              <div class="field-items"><?php print $node->field_listing_website[0]['view'] ?></div>
            </div>
            <div class="field field-type-email field-field-listing-email">
              <h3 class="field-label"><?php print t('E-mail') ?></h3>
              <div class="field-items"><?php print $node->field_listing_email[0]['view'] ?></div>
            </div>
            <div class="field field-type-email field-field-listing-phone">
              <h3 class="field-label"><?php print t('Phone') ?></h3>
              <div class="field-items"><?php print $node->field_listing_company_address[0]['phone'] ?></div>
            </div>
            <div class="field field-type-email field-field-listing-fax">
              <h3 class="field-label"><?php print t('Fax') ?></h3>
              <div class="field-items"><?php print $node->field_listing_company_address[0]['fax'] ?></div>
            </div>
          </div> <!--end field-contact -->
        </div> <!-- end field-address-contact -->

    and the CSS file node-listing.css

    .field-image-description,
    .field-address-contact {
      overflow: hidden;
    }

    .field-address {
      float: left;
    }

    .field-field-listing-product-image {
      float: left;
      padding-right: 24px;
    }

    .field-contact {
      float: right;
    }

    Here the final output of the themed node.

    after-theme.png

    WoW !! This looks pretty Good !!

Comments

Vance Schoenberger's picture

Hi just came across your site and have been reading some of your posts and just wondering is this a Drupal site? Looks very cool, i may set one up if so.

Fidelia's picture

Hi there, I dont know if I am writing in a proper board but I have got a problem with activation, link i receive in email is not working... http://www.caucusllc.com/?b9f4f5d62fb96cb509be47b916c,

Anonymous's picture

Hi there, I dont know if I am writing in a proper board but I have got a problem with activation, link i receive in email is not working... http://www.caucusllc.com/?cfe9cee4b0b29620e1912d3d7e9,

sivaji's picture

Indeed. It's running on drupal 6.x.

Valko's picture

Hi, nice post.
What if this was teaser look, how could i full node view for this content type .. or vice versa - this is full node view and i want to do a teaser. Is there somekind of $teaser variable so i could ask my self in .tpl.php and the display diferent fields ?

sivaji's picture

That's a good question and you got the answer yourself, use boolean variables like $teaser and $page to differentiate full view and teaser view.

<?php if ($teaser): ?>
<!-- html for teaser -->
<?php endif; ?>

<?php if ($page): ?>
<!-- html for full node -->
<?php endif; ?>

You can see the list of available of node.tpl.php variables here http://drupal.org/node/11816

Valko's picture

thank you ..

Deacon's picture

Hi there! I am here for the first time and like what and how you write. Hope to hear from you soon and something new ) My rapidshare SE ( http://rapidqueen.com ) for your use