Home arrow Perl Programming arrow Page 12 - Building a Complete Website using the Template Toolkit

Menu Components - Perl

See how the Template Toolkit simplifies the process of building and managing web site content. Examples illustrate the use of template variables and template components that allow web content to be constructed in a modular fashion. Other topics include managing the site structure, generating menus and other navigation components, and defining and using complex data. (From Perl Template Toolkit, Darren Chamberlain, Dave Cross, and Andy Wardley, O'Reilly Media, 2004, ISBN: 0596004761.)

TABLE OF CONTENTS:
  1. Building a Complete Website using the Template Toolkit
  2. A “Hello World” HTML Template
  3. Benefits of Modularity
  4. Loading the Configuration Template
  5. Creating a Project Directory
  6. A Place for Everything, and Everything in Its Place
  7. Adding Headers and Footers Automatically
  8. More Template Components
  9. Setting Default Values
  10. Wrapper and Layout Templates
  11. Using Layout Templates
  12. Menu Components
  13. Structured Configuration Templates
  14. Layered Configuration Templates
  15. Assessment
By: O'Reilly Media
Rating: starstarstarstarstar / 33
September 15, 2004

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

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.



 
 
>>> More Perl Programming Articles          >>> More By O'Reilly Media
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PERL PROGRAMMING ARTICLES

- Perl Turns 25
- Lists and Arguments in Perl
- Variables and Arguments in Perl
- Understanding Scope and Packages in Perl
- Arguments and Return Values in Perl
- Invoking Perl Subroutines and Functions
- Subroutines and Functions in Perl
- Perl Basics: Writing and Debugging Programs
- Structure and Statements in Perl
- First Steps in Perl
- Completing Regular Expression Basics
- Modifiers, Boundaries, and Regular Expressio...
- Quantifiers and Other Regular Expression Bas...
- Parsing and Regular Expression Basics
- Hash Functions

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: