Perl
  Home arrow Perl arrow Page 12 - Building a Complete Website using the ...
Dev Shed Forums 
Administration  
Apache  
BrainDump  
DHTML  
Flash  
Java  
JavaScript  
Multimedia  
MySQL  
Oracle  
Perl  
PHP  
Practices  
Python  
Reviews  
Security  
Style-Sheets  
Web Services  
XML  
Zend  
Zope  
Forums Sitemap 
IBM® developerWorks 
Dedicated Servers 
E-Commerce Hosting 
Linux Web Hosting 
Managed Hosting 
Small Business Hosting 
Download TestComplete 
VPS Hosting 
Weekly Newsletter

 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
PERL

Building a Complete Website using the Template Toolkit
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 4 stars4 stars4 stars4 stars4 stars / 29
    2004-09-15

    Table of Contents:
  • Building a Complete Website using the Template Toolkit
  • A “Hello World” HTML Template
  • Benefits of Modularity
  • Loading the Configuration Template
  • Creating a Project Directory
  • A Place for Everything, and Everything in Its Place
  • Adding Headers and Footers Automatically
  • More Template Components
  • Setting Default Values
  • Wrapper and Layout Templates
  • Using Layout Templates
  • Menu Components
  • Structured Configuration Templates
  • Layered Configuration Templates
  • Assessment

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
     
    ADVERTISEMENT

    PCmover - $15 Off with Coupon Code CJPH7Q

    Building a Complete Website using the Template Toolkit - Menu Components
    (Page 12 of 15 )

    In the layout template in Example 2-20, we delegate the task of generating a menu for the web site to the menu template. Before we look at how the template does this, let’s see an example of the kind of HTML that we would like it to generate.

    <table border="0">
      <tr>
        <td>
          <img src="/images/icon.png" width="4" height="4" />
        </td>
        <td>
          <a href="earth.html">Earth</a>
        </td>
      </tr>
      <tr>
        <td>
          <img src="/images/icon.png" width="4" height="4" />
        </td>
        <td>
          <a href="magrethea.html">Magrethea</a>
        </td>
      </tr>
    </table>

    The entire menu is defined as a <table> element, containing one <tr> row for each item, each of which holds two <td> cells, one to display an icon, the other a link to a particular page. Only two items are in this simple example, but already we can see how it gets repetitive very quickly. This suggests that we can modularize the markup into separate template components.

    Simple Menu Template

    Example 2-23 shows a menu template that defines the outer <table> elements and uses a second template, menuitem, to generate each item.

    Example 2-23. lib/menu

    <table border="0">
    [%
      PROCESS menuitem
       text = 'Earth'
       link = 'earth.html';

      PROCESS menuitem
       text = 'Magrethea'
       link = 'magrethea.html';
    %]
    </table>

    [% BLOCK menuitem %]
    <tr>
      <td>
        <img src="/images/icon.png" width="4" height="4" />
      </td>
      <td>
        <a href="[% link %]">[% text %]</a>
      </td>
    </tr>
    [% END %]

    The menuitem template block is defined at the bottom of the menu template, but that doesn’t stop us from using it earlier in the same template, before it is defined.

    The menuitem block will remain defined while the menu template is being processed. Any other templates that are called from within the menu template (e.g., by a PROCESS or INCLUDE directive) will also be able to use the menuitem block.

    Component Libraries

    When a template is loaded using the PROCESS directive, any BLOCK definitions within it will be imported and available for use in the calling template. Templates loaded using the INCLUDE directive keep to themselves and don’t export their BLOCK definitions (or any of their local variables, as described in the earlier discussion of the
    INCLUDE directive).

    This feature allows you to create single template files that contain libraries of smaller template components, defined using the BLOCK directive. This is illustrated in Example 2-24.

    Example 2-24. lib/mylib

    [% BLOCK image -%]
    <img src="[% src %]" alt="[% alt %]"
    width="[% width %]" height="[% height %]" />
    [%- END %]
    [% BLOCK link -%]
    <a href="[% link %]">[% text %]</a>
    [%- END %]
    [% BLOCK icon;
    INCLUDE image
    src = '/images/icon.png'
    alt = 'dot icon'
    width = 4
    height = 4 ;
    END
    -%]

    Notice how the icon BLOCK definition is defined within a single directive, and consists of nothing more than a call to the image template component, defined earlier in the same file. This illustrates how easy it is to reuse existing components to quickly adapt them for more specific, or alternate purposes. The BLOCK definitions can be loaded from the mylib template with a PROCESS directive. Then they can be used just like any other template component. Example 2-25 shows a variation of the menu template from Example 2-23 in which the icon and
    link components are used to generate the menu items.

    Example 2-24. lib/mylib

    [% BLOCK image -%]
      <img src="[% src %]" alt="[% alt %]"
      width="[% width %]" height="[% height %]" />
    [%- END %]

    [% BLOCK link -%]
      <a href="[% link %]">[% text %]</a>
    [%- END %]

    [% BLOCK icon;
      INCLUDE image
        src    = '/images/icon.png'
        alt    = 'dot icon'
        width  = 4
        height = 4 ;
    END
    -%]

    Example 2-25. lib/menu2

    [% PROCESS mylib %]

    <table border="0">
    [%
      PROCESS menuitem
       text = 'Earth'
       link = 'earth.html';

      PROCESS menuitem
       text = 'Magrethea'
       link = 'magrethea.html';
    %]
    </table>

    [% BLOCK menuitem %]
    <tr>
      <td>
        [% PROCESS icon %]
      </td>
      <td>
        [% PROCESS link %]
      </td>
    </tr>
    [% END %]

    The EXPOSE_BLOCKS option

    You can also set an option that allows you to use BLOCK directives without having to first PROCESS the template in which they’re defined. The expose_blocks option for ttree and the corresponding EXPOSE_BLOCKS option for the Template module can be set to make this possible.

    For example, by adding the following to the etc/ttree.cfg file:

    expose_blocks

    we can then access a BLOCK in the mylib template like so:

    [% PROCESS mylib/icon %]

    The template name, mylib, is followed by the BLOCK name, icon, separated by a / (slash) character. The notation is intentionally identical to how you would specify the icon file in the mylib directory. This is another example of how the Template Toolkit abstracts certain underlying implementation details so that you don’t tie yourself down to one particular way of doing something.

    At a later date, for example, you might decide to split the mylib template into sepa rate files, stored in the mylib directory. The same directive will continue to work because the syntax is exactly the same for blocks in files as it is for files in directories:

    [% PROCESS mylib/icon %]

    This gives you more flexibility in allowing you to change the way you organize your template components, without having to worry about how that might affect the templates that use them.

    The FOREACH Directive

    The menu component from Example 2-25 can be simplified further by first defining a list of menu items and then iterating over them using the FOREACH directive. Example 2-26 demonstrates this.

    Example 2-26. lib/menu3

    [% PROCESS mylib %]

    [% menu = [
        { text = 'Earth'
          link = 'earth.html' }
        { text = 'Magrethea'
          link = 'magrethea.html' }
      ]
    %]

    <table border="0">
    [% FOREACH item IN menu %]
    <tr>
      <td>
        [% PROCESS icon %]
      </td>
      <td>
        [% PROCESS link
          text = item.text
          link = item.link
        %]
      </td>
    </tr>
    [% END %]
    </table>

    The menu variable is defined as a list of hash arrays, each containing a text

    and link item:

    [% menu = [
        { text = 'Earth'
          link = 'earth.html' }
        { text = 'Magrethea'
          link = 'magrethea.html' }
      ]
    %]

    The main body of the template defines an HTML <table> element. Within the table, the FOREACH directive iterates through the menu list, setting the item variable to each element in turn.

    <table border="0">
    [% FOREACH item IN menu %]
    <tr>
      <td>
        [% PROCESS icon %]
      </td>
      <td>
        [% PROCESS link
          text = item.text
          link = item.link
        %]
      </td>
    </tr>
    [% END %]
    </table>

    The block following the FOREACH directive, up to the corresponding END, can contain text and other directives, even including nested FOREACH blocks. To make the code easier to read, we might prefer to define the menuitem BLOCK , as shown in Example 2-25. This allows us to simplify the FOREACH directive, merging it into a single tag.

    The FOREACH block now contains just one directive to PROCESS the menuitem component. The text and link variables are set to the item.text and item.link values, respectively.

    <table border="0">
    [% FOREACH item IN menu;
        PROCESS menuitem
          text = item.text
          link  = item.link;
      END
    %]
    </table>

    When the items in a FOREACH list are hash arrays, as they are in Example 2-26, you can omit the name of the item variable:

    <table border="0">
    [% FOREACH menu;
        PROCESS menuitem;
       END
    %]
    </table>

    In this case, the values in each hash array will be made available as local variables inside the FOREACH block. So item.text becomes the text variable, and item.link becomes link, but only within the scope of the FOREACH block. This conveniently allows us to process the menuitem template without needing to explicitly derefer ence the item variables.

    There’s one more improvement we can make by taking advantage of the Template Toolkit’s side-effect notation. Instead of writing the PROCESS menuitem directive in the FOREACH block all by itself, we can put it before the FOREACH and do away with the semicolons and END keyword:

    <table border="0">
    [% PROCESS menuitem FOREACH menu %]
    </table>

    All these enhancements to the menu template are shown in Example 2-27.

    Example 2-27. lib/menu4

      [% PROCESS mylib %]
      [% menu = [
        { text = 'Earth'
          link = 'earth.html' }
        { text = 'Magrethea'
          link = 'magrethea.html' }
      ]
    %]

    <table border="0">
      [% PROCESS menuitem FOREACH menu %]
      </table>

        [% BLOCK menuitem %]
      <tr>
      <td>
        [% PROCESS icon %]
      </td>
      <td>
        [% PROCESS link %]
      </td>
    </tr>
    [% END %]

    Defining and Using Complex Data

    The variables that we have used so far have mostly been simple scalar variables that contain just one value. The few exceptions include the tantalizing glimpses of the template variable, and the Date plugin in Example 2-22. As we saw in Chapter 1, the Template Toolkit also supports lists and hash arrays for complex data, and allows you to access Perl subroutines and objects.

    In this section, we will look more closely at defining and using complex data struc tures, and describe the different Template Toolkit directives for inspecting, presenting, and manipulating them. 

    Buy the book!If you've enjoyed what you've seen here, or to get more information, click on the "Buy the book!" graphic. Pick up a copy today!

    Visit the O'Reilly Network http://www.oreillynet.com for more online content.

       

    PERL ARTICLES

    - Perl: A Continuing Look at Hashes and Multid...
    - Perl: Another Round with Hashes
    - Perl Hashes
    - Perl Lists: A Final Look at List::Util
    - Perl Lists: Utilizing List::Util
    - Perl Lists: The Split() Function
    - SQL and CGI with Perl and DBI
    - Perl Lists: More Functions and Operators
    - SELECT Queries and Perl
    - Perl Lists: More on Manipulation
    - Creating a Database with Perl and DBI
    - Perl: Sailing the List(less) Seas
    - Perl and DBI
    - Perl: Concatenating Text and More
    - Perl Text: Quoting Without Quote Marks

     
    Accelerating Trading Partner Performance
     
    Competing on Analytics
     
    Cost Effective Scaling with Virtualization and Coyote Point Systems
     
    Five Checkpoints to Implementing IP Telephony
     
    Hosted Email Security: Staying Ahead of New Threats
     




    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 6 hosted by Hostway