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

Using Layout Templates - 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

Most real web sites will require far more complex layout templates than the simple wrapper we saw in Example 2-16. A common practice is to use HTML tables to place different elements such as headers, footers, and menus in a consistent position and formatting style. These elements may themselves be built using tables and other HTML elements, perhaps nested several times over. This can quickly lead to confus ing markup that is hard to read and even harder to update.

Consider the following example, which illustrates how difficult nested tables can be to write and maintain:

<table border="0" cellpadding="0" cellspacing="0">
  <tr valign="top">
    <td>
      <table border="0">
        <tr>
          <td>
            Oh Dear!
          </td>
          <td>
            This is not a good example
            of a layout template...
          </td>
          <td>
            <table>
              ...etc...
            </table>
          </tr>
        </table>
      </td>
      <td>
        <table>
          ...etc...
        </table>
      </td>
      .
      .
      .

The sensible formatting helps to make the structure clearer through use of indenting. However, it is still difficult to match rows and cells with their correspondingn tables, and there is little indication of what the different tables contribute to the overall layout.

A better approach is to build the layout using several different templates. For example, we can simplify the preceding template by moving the inner tables to separate
templates:

<table border="0" cellpadding="0" cellspacing="0">
  <tr valign="top">
  <td>
    [% PROCESS sidebar %]
  </td>
  <td>
    [% PROCESS topmenu %]
  </td>
  .
  .
  .

Now we can easily see the high-level structure without getting bogged down in the detail of the nested tables. Furthermore, by giving our templates names that reflect their purpose (e.g., sidebar and topmenu), we effectively have a self-documenting template that shows at a glance what it does. Another benefit is that the individual elements, the sidebar and topmenu in this example, will themselves be much easier to write and maintain in isolation. They also become reusable, allowing you to incorporate them into another part of the site (or perhaps another site) with a PROCESS or similar directive.

Layout Example

Let’s work through a complete example now, applying this principle to the presentation framework for our web site. Example 2-17 shows an alternate version of the wrapper template that delegates the task to two further templates, html and layout.

Example 2-17. lib/wrapper2

[% WRAPPER html + layout;
     content;
   END
-%]

The two wrapper templates, html and layout, are both specified in the one WRAPPER directive, separated using the + character in the same way that we used it with the PROCESS directive in Example 2-9. In this case, the page content will be processed first, then the layout template, and finally the html template. Remember that the
WRAPPER directive works “inside out” by processing the wrapped content first, and then the wrapping templates.

If we unwrap the preceding directive into two separate WRAPPER calls, it should become more obvious why the WRAPPER directive processes the templates in the reverse order to how they’re specified:

[% WRAPPER html;
    WRAPPER layout;
      content;
    END;
  END
%]

The end result is that it does what you would expect, regardless of the slightly counterintuitive order in which it does it. The html template ends up wrapping the layout template, which in turn wraps the value of the content variable, which in this case is the output from processing the main page template.

Side-effect wrappers

The WRAPPER directive can also be used in side-effect notation. Consider the following fragment:

[% WRAPPER layout;
     content;
   END
%]

You can simplify this by writing it as follows:

[% content WRAPPER layout %]

The wrapper template shown in Example 2-17 can be rewritten in the same way, as shown in Example 2-18.


Example 2-18. lib/wrapper3

[% content WRAPPER html + layout -%]

Separating layout concerns

Using two separate layout templates, html and layout, allows us to make a clear separation between the different kinds of markup that we’re adding to each page. The html template adds the <head> and <body> elements required to make each page valid HTML. The layout template deals with the overall presentation of the visible page
content, adding a header, footer, menu, and other user interface components.

Example 2-19 shows the html template.

Example 2-19. lib/html

<html>
  <head>
    <title>[% author %]: [% template.title %]</title>
  </head>

  <body bgcolor="[% bgcol %]">
    [% content %]
  </body>
</html>

Example 2-20 shows the layout template.

Example 2-20. lib/layout

<table border="0" width="100%">
  <tr>
    <td colspan="2">
      [% PROCESS pagehead %]
    </td>
  </tr>
  <tr valign="top">
    <td width="150">
      [% PROCESS menu %]
    </td>
    <td>
      [% content %]
    </td>
  </tr>
  <tr>
    <td colspan="2" align="center">
      [% PROCESS pageinfo %]
    </td>
  </tr>
</table>

We’ve created a new header template, pagehead, shown in Example 2-21, which generates a headline for the page. It’s simple for now, but we can easily change it to something more complicated at a later date.

Example 2-21. lib/pagehead

[% template.title %]

We’re also using another template, menu, to handle the generation of a menu for the site. We’ll be looking at this shortly.

Example 2-22 shows the final template used in the layout, pageinfo. This incorporates the copyright message and some information about the page template being processed.

Example 2-22. lib/pageinfo

[% USE Date %]

&copy; [% copyr %]

<br />

[% template.name -% ]
last modified
[%- Date.format(template.modtime) %]

Notice how we’re using the template.name and template.modtime variables to access the filename and modification time of the current page template. The template.modtime value is returned as a large number that means something to computers* but not a great deal to humans. To turn this into something more meaningful, we’re using the Date plugin to format the number as a human-readable string.

Plugins and the USE directive

Plugins are a powerful feature of the Template Toolkit that allow you to load and use complex functionality in your templates, but without having to worry about any of the underlying implementation detail. Plugins are covered in detail in Chapter 6, but there’s not much you need to know to start using them.

In Example 2-22, we first load the Date plugin with the USE directive:

[% USE Date %]

This creates a Date template variable that contains a reference to a plugin object (of the Template::Plugin::Date class, but you don’t need to know that). We can then call the format method against the Date object using the dot operator, passing the value for template.modtime as an argument:

[%- Date.format(template.modtime) %]

The output generated would look something like this:

17:43:35 14-Jul-2003

* It’s the number of seconds that have elapsed since January 1, 1970, known as the the Unix epoch.

That’s all we need to do to load and use the Date plugin. Dozens of plugins are avail able for doing all kinds of different tasks, described in detail in Chapter 6. 

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: