Bric::HTMLTemplate(3p)User Contributed Perl DocumentatioBric::HTMLTemplate(3p)



NAME
       Bric::HTMLTemplate - Writing HTML::Template scripts and templates

INTRODUCTION
       This document describes how to use Bricolage's HTML::Template
       templating system. To get the most out of this document you'll need to
       have some familiarity with Bricolage templating using Mason -- see
       Bric::Templates and Bric::AdvTemplates for details. I'll try to keep
       the overlap between the those documents and this one to a minimum. It
       also helps to have an idea of how HTML::Template works outside of
       Bricolage -- for that you can refer to HTML::Template's documentation.

TEMPLATES IN BRICOLAGE
       Bricolage uses templates to produce output for stories when they are
       previewed and published. Most likely you'll be creating templates to
       format your stories as XHTML pages but you can also use HTML::Template
       to output WML, XML, email and more.

       Templates are created in the same category tree as your stories and
       media.  When a story is published the category tree is searched for
       templates starting in the primary category for the story. The search
       proceeds up the tree until a matching template is found.

       Bricolage allows you to create three types of templates: element
       templates, category templates, and utility templates. Element templates
       are assigned to a single element (e.g., Article, Page, Pull Quote,
       etc.). Category templates are assigned to the category. Utility
       templates must be placed into a category, but otherwise have no
       relationship to elements or categories.

SCRIPTS AND TEMPLATES
       HTML::Template works by separating Perl code from HTML design. In
       Bricolage this results in two types of template files -- .pl script
       files and .tmpl template files. The script files contain Perl code. The
       template files contain a mix of HTML tags and HTML::Template's
       "<TMPL_*>" tags.

       This divide between programming and design allows for a division of
       labor between programmers and designers. First, the programmer can
       create a set of elements and scripts (.pl files). Usually the
       programmer will also create some bare-bones example templates (.tmpl
       files). Next the designers can edit the template files to match the
       desired design.

       As an additional benefit, if per-category design changes are required,
       a designer can create template files in each category that will
       automatically be used by the existing scripts in the root category. Of
       course, the same is true of script files, but it is much more common to
       tweak the design by category than the code.

CHOOSING A BURNER
       Bricolage decides which burner module to use -- Mason, HTML::Template,
       Template Toolkit, or PHP -- by looking at the burner setting for the
       top-level story element being published. To start using HTML::Template
       to publish a story type go to Admin -> Elements, find the story element
       and set its burner to HTML::Template.

       When you're creating templates you'll also see a pull-down called
       "Burner".  This determines whether you're creating a Mason story.mc, an
       HTML::Template story.pl script, an HTML::Template story.tmpl or some
       other templating architecture template.

AN EXAMPLE STORY TYPE
       We'll examine a simple example story type called "Story". Here's the
       element tree for "Story":

          Story
               - Deck             (textbox field)
               + Page             (repeatable element)
                    - Paragraph   (repeatable textbox field)
                    - Pull Quote  (repeatable textbox field)

       The Story element has one field called Deck and can contain any number
       of Page elements. Pages are composed of Paragraph fields and Pull Quote
       subelements, both of which can be repeated.

       If this doesn't immediately make sense then you should probably go
       check out Bric::ElementAdmin before continuing -- it's hard to write
       templates if you don't understand elements!

CHOOSING A STRATEGY
       Bricolage is an exceedingly flexible system and the HTML::Template
       burner is no exception; there are a number of different ways you can
       write scripts and templates for the Story element tree. I'll start with
       what I think is the easiest to understand and proceed to more
       complicated approaches pointing out the advantages and drawbacks along
       the way.

STRATEGY 1: ONE SCRIPT, ONE TEMPLATE
       For a simple element tree you can often get away with just a single
       pair of files -- a script and a template for the top-level element.
       Here's an example script file that could be used to setup variables and
       loops for the example story above.

   THE SCRIPT: story.pl
           # get our template
           my $template = $burner->new_template(autofill => 0);

           # setup story title
           $template->param(title => $story->get_title);

           # get deck and assign it to a var
           $template->param(deck => $element->get_value('deck'));

           # setup the page break variable
           $template->param(page_break => $burner->page_break);

           # loop through pages building up @page_loop
           my @page_loop;
           for my $page ($element->get_elements('page')) {

               # build per-page element loop
               my @element_loop;
               foreach my $e ($page->get_elements) {
                   # push on a row for this element
                   push @element_loop, { $e->get_key_name => $e->get_value };
               }

               # push element_loop and a page_count on this loop
               push @page_loop, {
                   element_loop => \@element_loop,
                   page_count   => $e->get_object_order,
               };
           }

           # finish the page_loop
           $template->param(page_loop => \@page_loop);

           # call output and return the results
           return $template->output;

       There's a lot going on in the script above so we'll take it step by
       step. The first thing the script does is get a new $template object:

           # get our template
           my $template = $burner->new_template(autofill => 0);

       You may be wondering where $burner came from. Every script has access
       to three global variables: $burner, $story and $element. The $burner
       object is an instance of the Bric::Util::Burner::Template class. The
       $story and $element variables are the same as in the Mason system --
       check out Bric::Templates for details.

       The new_template() method (like all the $burner method calls) is
       documented in Bric::Util::Burner::Template. I've turned off autofill
       since we're doing all the hard work ourselves here. With autofill on,
       the script would be two lines long which wouldn't teach you much about
       writing HTML::Template scripts! More on autofill later.

       So, now that we have a template object we'll start by setting up some
       variables:

           # setup story title
           $template->param(title => $story->get_title);

           # get deck and assign it to a var
           $template->param(deck => $element->get_value('deck'));

           # setup the page break variable
           $template->param(page_break => $burner->page_break);

       The title variable assignment should be fairly self-explanatory -- it
       gets the story's title and makes it available to the template. Next the
       deck field is retrieved from $element using the get_value() method.
       Since there can only be one deck field -- it's not marked as repeatable
       in the element tree -- it's safe to assign it to a single variable.
       Finally, a special variable is setup to paginate the story;
       "$burner->page_break" returns a value that can be inserted into the
       output to break pages.

       The next step should look very familiar if you've ever setup a nested
       loop in HTML::Template. If you haven't then it probably looks
       frightening. I'll try to ease you in slow:

           # loop through pages building up @page_loop
           my @page_loop;
           for my $page ($element->get_elements('page')) {

       These lines setup the variables we'll need to build the page_loop. We
       need to use a loop for pages since there can be more than one inside
       the story element.

       The call to "$element->get_elements('page')" returns container elements
       of the 'page' type. What's a container element? Well, unfortunately
       Bricolage is a bit confused about what to call things internally --
       what the external system refers to simply as an "element" the guts
       refer to as "container elements." To make matters worse, fields are
       internally referred to as "field elements." That said, calling elements
       "container elements" is nicely descriptive since only container
       elements can contain other elements.

       Now that the loop is setup it's time to extract the page data:

               # build per-page element loop
               my @element_loop;
               foreach my $e ($page->get_elements) {
                   # push on a row for this element
                   push @element_loop, { $e->get_key_name => $e->get_value };
               }

       First the code creates a new array to hold the element variables from
       this page. Next we loop through all the elements in the page with the
       get_elements() call -- these elements will be paragraphs and pull
       quotes. Each element gets turned into a single row in the
       "element_loop" containing a single variable with the same key name as
       the element.

       For example, let's say we have a page with three paragraphs and a pull
       quote.  After this loop is finished @element_loop will look something
       like:

           @element_loop = (
               { "paragraph"  => "text of paragraph one..."   },
               { "pull_quote" => "text of pull quote one..."  },
               { "paragraph"  => "text of paragraph two..."   },
               { "paragraph"  => "text of paragraph three..." },
           );

       As you know from your knowledge of HTML::Template, this is the
       structure for a "TMPL_LOOP". Once we've got this structure, we push it
       onto the outer "page_loop" along with the object count.

              # push element_loop and a page_count on this loop
              push @page_loop, {
                  element_loop => \@element_loop,
                  page_count   => $e->get_object_order,
              };
           }

       A completed @page_loop for a two-page story might look something like:

           @page_loop = (
             {
               element_loop => [
                 { "paragraph"  => "text of paragraph one..."   },
                 { "pull quote" => "text of pull quote one..."  },
                 { "paragraph"  => "text of paragraph two..."   },
                 { "paragraph"  => "text of paragraph three..." },
               ],
               page_count => 1
             },
             {
               element_loop => [
                 { "paragraph"  => "text of paragraph one..."   },
                 { "paragraph"  => "text of paragraph two..." },
               ],
               page_count => 2
             }
           );

       Which, as you might know, is just the array of hashes of arrays of
       hashes structure that HTML::Template expects for nested loops.

           # finish the page_loop
           $template->param(page_loop => \@page_loop);

           # call output and return the results
           return $template->output;

       Finally, we send the @page_loop data to the template and return the
       results of running the template.

   THE TEMPLATE: story.tmpl
       The template for our script matches the variables and loops setup in
       the script. It adds a very small amount of HTML formatting just so you
       can see where formatting might be added:

           <tmpl_loop page_loop>

              <html>

              <head>
            <title><tmpl_var title></title>
              </head>
              <body>

            <tmpl_if __first__>
               <h1><tmpl_var title></h1>
               <b><tmpl_var deck></b>
            </tmpl_if>

            <tmpl_loop element_loop>
               <tmpl_if paragraph>
                 <p><tmpl_var paragraph></p>
               </tmpl_if>
               <tmpl_if name="pull_quote">
                 <blockquote><p>
                       <tmpl_var name="pull_quote">
                     </p></blockquote>
               </tmpl_if>
            </tmpl_loop>

                <tmpl_unless __first__>
            <a href=<tmpl_var expr="prev_page_link(page_count)">>Previous Page</a>
            </tmpl_unless>

            <tmpl_unless __last__>
            <a href=<tmpl_var expr="next_page_link(page_count)">>Next Page</a>
            </tmpl_unless>


              </body>
              </html>

              <tmpl_var page_break>

           </tmpl_loop>

       Most of this should be pretty self-explanatory but I'll highlight some
       of the more interesting bits. First, the template makes use of
       HTML::Template's "loop_context_vars" option which is on by default in
       Bricolage. This allows the template to make decisions based on the
       automatic loop variables "__first__" and "__last__":

            <tmpl_if __first__>
               <h1><tmpl_var title></h1>
               <b><tmpl_var deck></b>
            </tmpl_if>

       This snippet is used to put the title line and deck on the first page
       only.  This mysterious section sets up the next and previous links:

          <tmpl_unless __first__>
             <a href=<tmpl_var expr="prev_page_link(page_count)">>Previous Page</a>
          </tmpl_unless>

          <tmpl_unless __last__>
             <a href=<tmpl_var expr="next_page_link(page_count)">>Next Page</a>
          </tmpl_unless>

       The use of "__first__" and "__last__" should be obvious enough: the
       first page doesn't get a previous page link and the last page doesn't
       get a next page link. This section also makes use of some helper
       functions provided to make linking between pages easier. We could do
       this without them though; something like this would produce equivalent
       results:

            <tmpl_unless __first__>
               <tmpl_if expr="page_count == 2">
                 <a href="index.html">Previous Page</a>
               <tmpl_else>
                 <a href="index<tmpl_var expr="page_count - 2">.html">
                        Previous Page
                     </a>
               </tmpl_if>
            </tmpl_unless>

            <tmpl_unless __last__>
               <a href="index<tmpl_var page_count>.html">Next Page</a>
            </tmpl_unless>

       Although that would only work if your output channel was setup to
       output files with names like index.html and index1.html. The
       next_page_link() and prev_page_link() functions will work with any
       output channel settings.

       The final bit of mystery in this template is the use of the magic
       page_break variable:

          <tmpl_var page_break>

       If you remember back in the script this was setup with a call to
       "$burner->page_break". Inserting this value in your output will tell
       Bricolage to insert a page break. Also, Bricolage is smart enough not
       to output a trailing blank page so you don't have to worry about the
       spacing after "page_break" in the loop.

   CONCLUSION
       This first example has shown how a simple story type can be formatted
       using a single script and a single template. The script is responsible
       for setting up the variables and loops that the template uses to format
       the story.

       Here's an analysis of this approach:

       Advantages
           o   Everything is in one place. This gives the HTML designer one-
               stop-shopping for making changes to the way a story looks.
               Also, the programmer doesn't have to hunt around for the right
               place to add some code for a new feature.

           o   The script is explicit about what variables and loops are being
               setup in the template. This can aid in maintenance of the
               scripts and templates.

       Disadvantages
           o   The template is quite complex -- loops within loops can be
               difficult For less experienced designers to understand.

           o   The script is fairly long considering how little work it is
               actually doing.

           o   The individual elements are treated directly and thus do not
               have any independent formatting associated with them. If
               another story type element wants to use Page elements then the
               same work will need to be duplicated.

STRATEGY 2: NO SCRIPT, ONE TEMPLATE
       As I hinted at above, "new_template()"'s "autofill" parameter can do a
       lot of work for you. Combined with the default script creation you can
       often get away with creating no scripts at all.

   THE DEFAULT SCRIPT
       The default script is used if Bricolage needs to publish an element for
       which no script file (.pl) exists but for which there is a template
       file (.tmpl). It consists of:

          return $burner->new_template->output;

       Since no options are specified to new_template(), the "autofill"
       parameter defaults to on. In autofill mode, new_template()
       automatically fills in variables and loops for your element tree.

       Several types of variables and loops are created by autofill:

       o   A single variable is created for every element with the same key
           name as the element. For fields, this variable contains the value
           of the field.  For container elements, the variable contains the
           output of the execution of the script and/or template for that
           element (more on this in strategy 3).

           The "<tmpl_var deck>" variable in the previous example is an
           example of this type of variable.

       o   A loop is created for every element with the key name of the
           element followed by "_loop". The rows of the loop contain instances
           of the variables described above and a "_count" variable for each.

           The "<tmpl_loop page_loop>" loop is an example of this type of
           loop.

       o   A loop called "element_loop" is created with a row for every
           subelement. The values are the same as for the loop above with the
           addition of a boolean "is_" variable.

           The "<tmpl_loop element_loop>" loop used within the "<tmpl_loop
           page_loop>" loop is this type of loop.

       o   A variable for the total number of elements with the element key
           name and a trailing "_total".

       o   A variable named for each attribute of the story, including
           "title", "uri", description", and so on.

       o   A variable called "page_break" containing the return value of
           "$burner->page_break".

   THE TEMPLATE: story.tmpl
       The template for use with this strategy is almost exactly the same as
       for strategy 1 (sneaky, huh?). The only change is that the autofill
       code provides "is_$key_name" variables inside the element_loops to make
       testing for the type of the row more obvious and more fool-proof. In
       STRATEGY 1 a paragraph with the sole contents "0" wouldn't have been
       printed! The horror!

          <tmpl_loop page_loop>

              <html>

              <head>
            <title><tmpl_var title></title>
              </head>
              <body>

            <tmpl_if __first__>
               <h1><tmpl_var title></h1>
               <b><tmpl_var deck></b>
            </tmpl_if>

            <tmpl_loop element_loop>
               <tmpl_if is_paragraph>
                 <p><tmpl_var paragraph></p>
               </tmpl_if>
               <tmpl_if is_pull_quote>
                 <blockquote><p>
                       <tmpl_var pull_quote>
                     </p></blockquote>
               </tmpl_if>
            </tmpl_loop>

                <tmpl_unless __first__>
            <a href=<tmpl_var expr="prev_page_link(page_count)">>Previous Page</a>
            </tmpl_unless>

            <tmpl_unless __last__>
            <a href=<tmpl_var expr="next_page_link(page_count)">>Next Page</a>
            </tmpl_unless>

              </body>
              </html>

              <tmpl_var page_break>

           </tmpl_loop>

   CONCLUSION
       This example demonstrates the real power of Bricolage's HTML::Template
       system.  Here's a breakdown of this strategy:

       Advantages
           o   No code required! You can take the day off if all the designer
               needs is access to the data in the story and the elements.

           o   Consistency. The template designer always gets access to the
               variables and loops in the same way. Once they've learned the
               setup they can create templates just by looking at the element
               tree.

       Disadvantages
           o   Understanding how all this works requires a good understanding
               of autofill.  Hopefully this document will get you there but
               sometimes its still nice to be able to see the code that's
               really executing.

           o   The template is still pretty complicated.

STRATEGY THREE: NO SCRIPTS, MANY TEMPLATES
       Sometimes a little extra work can go a long way. If you're building an
       element that will be used as a sub-element in a number of trees, then
       it pays to split out the functionality into separate pieces. Bricolage
       supports this by allowing you to create a script (.pl) and a template
       (.tmpl) for every element.

       This strategy will deal with just templates, relying on autofill to
       setup variables and loops. The next strategy will deal with customizing
       the scripts for multiple elements.

   TEMPLATE: story.tmpl
       Here's a revised story.tmpl to makes a call to the page element
       script/template:

          <tmpl_loop page_loop>

              <html>

              <head>
            <title><tmpl_var title></title>
              </head>
              <body>

            <tmpl_if __first__>
               <h1><tmpl_var title></h1>
               <b><tmpl_var deck></b>
            </tmpl_if>

                <tmpl_var page>

                <tmpl_unless __first__>
            <a href=<tmpl_var expr="prev_page_link(page_count)">>Previous Page</a>
            </tmpl_unless>

            <tmpl_unless __last__>
            <a href=<tmpl_var expr="next_page_link(page_count)">>Next Page</a>
            </tmpl_unless>

              </body>
              </html>

              <tmpl_var page_break>

           </tmpl_loop>

       Notice that instead of the inner "element_loop" there's a single
       "TMPL_VAR" called "page". This tells autofill to make a call to the
       element script for the page element -- page.pl. Of course, as we saw
       earlier, if this script doesn't exist then the default script is used:

           return $burner->new_template->output;

   TEMPLATE: page.tmpl
       Here's the page template that outputs the body of the page:

           <tmpl_loop element_loop>
           <tmpl_if is_paragraph>
             <p><tmpl_var paragraph></p>
           </tmpl_if>
           <tmpl_if is_pull_quote>
             <blockquote><p>
               <tmpl_var pull_quote>
                 </p></blockquote>
           </tmpl_if>
           </tmpl_loop>

       This should look pretty familiar -- it's exactly the same markup that
       was in the original story.tmpl! Autofill sets up the same loops and
       variables whether you're in an original template or a sub-template.

       One thing to note is that you can't just move the header- and footer-
       generating code into the page template. Since the "__first__" and
       "__last__" variables are only valid inside the loop in story.tmpl, they
       can't be used in "page.tmpl". This might be addressed in the future but
       until then see the next strategy for a solution.

   CONCLUSION
       This strategy is a good one when you have elements that will be shared
       between template trees. Here's a breakdown:

       Advantages
           o   Element templates can be reused across template trees.

           o   Element template complexity is reduced -- only a single loop is
               used in each.

           o   No code required! (just like Strategy 2)

       Disadvantages
           o   The formatting for a story is spread across multiple templates
               which may make it harder for designers to make changes.

           o   Autofill behavior may be hard for programmers to understand.
               (just like Strategy 2)

STRATEGY 4: SCRIPTS AND TEMPLATES
       The Bricolage system is all about flexibility. In Strategy 1 you got an
       up-close look at a script that handles the entire template setup
       process.  Fortunately you don't need to do all that work just to add a
       small enhancement. For an example, let's fix the problem I mentioned at
       the end of Strategy 3 -- the header and footer for the Page element
       were stuck in story.tmpl by their reliance on "__first__" and
       "__last__".

   TEMPLATE: story.tmpl
       Here's the desired story.tmpl:

          <tmpl_loop page_loop>

              <html>

              <head>
            <title><tmpl_var title></title>
              </head>
              <body>

                <tmpl_var page>

              </body>
              </html>

              <tmpl_var page_break>

           </tmpl_loop>

   TEMPLATE: page.tmpl
       And the new Page template:

           <tmpl_if first>
           <h1><tmpl_var title></h1>
           <b><tmpl_var deck></b>
           </tmpl_if>

           <tmpl_loop element_loop>
           <tmpl_if is_paragraph>
             <p><tmpl_var paragraph></p>
           </tmpl_if>
           <tmpl_if is_pull_quote>
             <blockquote><p>
               <tmpl_var pull_quote>
                 </p></blockquote>
           </tmpl_if>
           </tmpl_loop>

           <tmpl_unless first>
              <a href=<tmpl_var expr="prev_page_link(page_count)">>Previous Page</a>
           </tmpl_unless>

           <tmpl_unless last>
              <a href=<tmpl_var expr="next_page_link(page_count)">>Next Page</a>
           </tmpl_unless>

       You'll notice that the element loop is unchanged. The header and footer
       expressions are the same except that "__first__" and "__last__" are now
       just plain "first" and "last". This was done to emphasize that we're
       not using HTML::Template's automatic loop variables here.

   SCRIPT: story.pl
       The problem here is simple -- we've got some variables in the Story
       that need to be made available to the Page. Also, we'd like to do this
       without having to do all the work of Strategy 1. Here's the first half
       of the solution in story.pl:

           my $template = $burner->new_template;

           my @pages = $element->get_elements('page');
           my $total = @pages;

           # build @page_loop by calling run_script with page_count and
           # page_total arguments.
           my @page_loop;
           foreach my $page (@pages) {
             push @page_loop, { page => $burner->run_script(
                                    $page,
                                    $page->get_object_order,
                                    $total)
             };
           }

           # replace autofilled page_loop with new one
           $template->param(page_loop => \@page_loop);

           # return the output
           return $template->output;

       Basically this script does the same thing that autofill does but only
       for a single loop -- "page_loop". Additionally, instead of calling
       "run_script()" with just the element parameter it also supplies two
       arguments, the object order, which corresponds to a page count, and the
       total number of pages (computed from @pages).

   SCRIPT: page.pl
       Now that we've setup story.pl to pass parameters to the Page element,
       we'll need a script that does something with them.

          my ($page_count, $page_total) = @_;
          my $template = $burner->new_template;

          # setup params
          $template->param(first => 1) if $page_count == 1;
          $template->param(last => 1)  if $page_count == $page_total;
          $template->param(page_count => $page_count);

          # return output
          return $template->output;

       As you can see, arguments are passed to scripts just as they are to
       Perl subroutines -- through @_. The script uses these parameters to
       setup the template params it needs.

   CONCLUSION
       This Strategy uses the full set of Bricolage HTML::Template tools we've
       seen so far -- scripts, templates, autofill, and run_script().

       Advantages
           o   This style is very flexible -- the programmer can add
               functionality to the autofilled content without having to re-
               invent the wheel.

           o   Elements that are broken out into discrete scripts and
               templates can be reused between element trees.

           o   In this particular case, bending the rules a bit allows the
               page formatting to be more logically grouped and easier to
               edit.

       Disadvantages
           o   Requires coding.

           o   Requires communication between template programmer and template
               designer since the variables and loops are somewhat different
               from the normal autofill setup.

STRATEGY 5: RELATED MEDIA
       So far things have been kept pretty simple; our example story type
       contains only text. Now let's add the possibility of including images
       in our story. The new tree will look like:

          Story
               - Deck             (textbox field)
               + Page             (repeatable element)
                    - Paragraph   (repeatable textbox field)
                    - Pull Quote  (repeatable textbox field)
                    + Image       (repeatable related media element)
                       - Caption  (textbox field)

       The Image element is of the type "Related Media" and has one non-
       repeatable field called "Caption". Since it's a related media element
       it also has the ability to point to a media document. In this case the
       template will assume that referenced media document is an image.

   TEMPLATE: story.tmpl
       To keep things simple, we'll start with the template used to format the
       story in Strategy 2 with a small addition:

          <tmpl_loop page_loop>

              <html>

              <head>
            <title><tmpl_var title></title>
              </head>
              <body>

            <tmpl_if __first__>
               <h1><tmpl_var title></h1>
               <b><tmpl_var deck></b>
            </tmpl_if>

            <tmpl_loop element_loop>
               <tmpl_if is_paragraph>
                 <p><tmpl_var paragraph></p>
               </tmpl_if>
               <tmpl_if is_pull_quote>
                 <blockquote><p>
                       <tmpl_var pull_quote>
                     </p></blockquote>
               </tmpl_if>
                   <tmpl_if is_image>
                     <p><tmpl_var image></p>
                   </tmpl_if>
            </tmpl_loop>

                <tmpl_unless __first__>
            <a href=<tmpl_var expr="prev_page_link(page_count)">>Previous Page</a>
            </tmpl_unless>

            <tmpl_unless __last__>
            <a href=<tmpl_var expr="next_page_link(page_count)">>Next Page</a>
            </tmpl_unless>

              </body>
              </html>

              <tmpl_var page_break>

           </tmpl_loop>

       The addition is another conditional inside the page's element_loop:

                   <tmpl_if is_image>
                     <p><tmpl_var image></p>
                   </tmpl_if>

       This will make a call out to the Image element's script when output.

   SCRIPT: image.tmpl
       For the script we'll use the autogenerated autofill script. Here's the
       template to format the image:

           <img src="<tmpl_var rel_media_uri>">
           <tmpl_if caption>
              <br /><font size=-1><tmpl_var caption></font>
           </tmpl_if>

       By now we know to expect the "caption" variable -- this is the Caption
       field that can be defined for the Image element. The "rel_media_uri"
       variable is a new feature of autofill -- it corresponds to the
       following code:

           my $media = $element->get_related_media;
           $template->param(rel_media_uri => $media->get_uri) if $media;

       The same technique works for Related Stories elements. I'll omit a full
       example except to say that a "rel_story_uri" variable is provided and
       can be used in much the same way, for example, in an anchor ("<a>")
       tag.

       Compatibility note: The "rel_media_uri" and "rel_story_uri" variables
       were added in Bricolage 1.10.0. Earlier versions of Bricolage had only
       a "link" variable, and if an element had both a related story and a
       related media document, only the related media document was available.
       The "link" variable is still available in Bricolage 1.10.0 and later
       for backwards compatibility purposes.

   CONCLUSION
       This strategy enables the use of key Bricolage features -- related
       media and related stories. Given that users tend to like multimedia and
       hyperlinks between stories, I'll omit an Advantages and Disadvantages
       section -- you'll probably have to use this Strategy whether you like
       it or not!

STRATEGY 6: CATEGORY SCRIPTS AND TEMPLATES
       Just as elements can have scripts and templates, each category may have
       one script and one template associated with it called category.pl and
       category.tmpl.

       Category templates are the HTML::Template equivalent of Mason's
       autohandlers, although there are some differences in behavior. For one,
       category templates are executed separately for each page of story
       output, once the pages have been split up from the output of the story
       template. For another, there is no "$burner->chain_next" method.
       Rather, the content of the page is stored in the HTML::Template
       variable "content".

       For an example, let's imagine that we want to put a blue box around
       every page in our output. Instead of putting this HTML into our
       templates we'll do it in a category template.

   THE TEMPLATE: category.tmpl
         <html>
         <head><tmpl_var title></head>
         <body>

         <div style="background:blue">
            <tmpl_var content>
         </div>

         </body>
         </html>

       Of course, now the "<head>" and "<body>" tags should be removed from
       the story template, since the category template takes care of them.
       Aside from that the only new feature is the "content" variable. Every
       "category.tmpl" must include the content variable to indicate where the
       content will be inserted for each page.

   THE SCRIPT: category.pl
       As you probably can predict, autofill will fill in all the variables in
       the above template, including all the fields and subelements of the
       story element, just like in the story template itself. So we don't
       really need a category.pl script; the default script generated by
       Bricolage will do the trick.

   CONCLUSION
       Advantages
           o   Can potentially reduce the amount of replicated text in your
               top-level templates.

           o   Could enable more complicated category-based functionality -
               navigation, bread-crumbing, etc.

       Disadvantages
           o   Requires uniformity across elements that may not be very
               uniform at all.

           o   Hides formatting from designers -- there's no way to guess that
               the header and footer are coming from category.tmpl without
               familiarity with the concept of category templates.

THE END
       Certainly there are many more ways to use HTML::Template in Bricolage
       than I've covered in this document. Your main tools -- scripts,
       templates, the Bric::Util::Burner::Template API, and the various
       objects available in Bricolage -- are now yours for the taking. Go
       forth and bend Bricolage whimpering to your task!

AUTHOR
       Sam Tregar <sam@tregar.com>. Updated for Bricolage 1.10 and later by
       David Wheeler <david@kineticode.com>.

SEE ALSO
       Bric::Util::Burner
       Bric::Templates
       Bric::AdvTemplates
       Bric::ElementAdmin



perl v5.12.2                      2005-09-21            Bric::HTMLTemplate(3p)
