Template Macros: The coolest template trick you don't know about

Republished from Learning Movable Type, a great community resource to help people get the most out of Movable Type.

Recently when working on updating the Photo Gallery plugin to work with Movable Type 4.1 I found myself neck deep in some of the most complicated Movable Type templates I have ever seen. Of course, their complexity is exactly why the Photo Gallery plugin outputs such beautiful results.

Within these templates I have the need to take an arbitrary image asset of any size, and scale it proportionally to fit inside a well defined area. This could be a thumbnail, or a larger version of the photo at hand. What I found myself doing is replicating the same template code over and over again in order to produce the output I desired throughout the template set. Here is the template code I was using:

<MTSetVarBlock name="width" trim="1"><MTEntryAssets><MTAssetProperty 
    property="image_width"></MTEntryAssets></MTSetVarBlock>
<MTSetVarBlock name="height" trim="1"><MTEntryAssets><MTAssetProperty 
    property="image_height"></MTEntryAssets></MTSetVarBlock>
<mt:if name="width" gt="$height">
    <MTSetVarBlock name="img"><MTEntryAssets><mt:AssetThumbnailLink width="90" 
        regex_replace="/^<a[^>]*>(<img[^>]*>)<\/a>$/","$1" /></MTEntryAssets></MTSetVarBlock>
<mt:else>
    <MTSetVarBlock name="img"><MTEntryAssets><mt:AssetThumbnailLink height="90" 
        regex_replace="/^<a[^>]*>(<img[^>]*>)<\/a>$/","$1" /></MTEntryAssets></MTSetVarBlock>
</mt:if>

Yikes.

To complicate things further, each time I cut and pasted this code around I had to modify it slightly depending upon the size of the photo I wanted to output. This presented the following problems:

  • my template code was getting very messy.
  • my template code was getting harder and harder to update because I had the same code in multiple places

What I found myself in need of is something a developer might call a "function" or "macro." In layman's terms, I needed a way to write this template code once, and then to invoke along with a few parameters in order to change its behavior and output as needed.

Luckily, Movable Type has exactly what I needed: a little template tag called MTSetVarTemplate. This template tag allowed me to define just such a macro so that I could reduce all of the complicated template code above into something far simpler:

<MTVar name="photo" max_size="90">

Wow, what an improvement!

To achieve this I defined the following template code inside of a template module I created. I then included that module in my header to ensure that I could use it anywhere I needed within my templates I needed to:

<mt:ignore>
  This template module is responsible for outputting the associated image with the current
  photo/entry in context. You can pass in the max_size parameter to control the size of 
  the image.
  Example:
    <mt:getvar name="photo" max_size="90">
</mt:ignore>
<MTSetVarTemplate name="photo">
<MTSetVarBlock name="width" trim="1"><MTEntryAssets><MTAssetProperty property="image_width"></MTEntryAssets></MTSetVarBlock>
<MTSetVarBlock name="height" trim="1"><MTEntryAssets><MTAssetProperty property="image_height"></MTEntryAssets></MTSetVarBlock>
<mt:if name="width" gt="$height">
        <MTSetVarBlock name="img"><MTEntryAssets><mt:AssetThumbnailLink width="$max_size" regex_replace="/^<a[^>]*>(<img[^>]*>)<\/a>$/","$1" /></MTEntryAssets></MTSetVarBlock>
<mt:else>
        <MTSetVarBlock name="img"><MTEntryAssets><mt:AssetThumbnailLink height="$max_size" regex_replace="/^<a[^>]*>(<img[^>]*>)<\/a>$/","$1" /></MTEntryAssets></MTSetVarBlock>
</mt:if>
<mt:getvar name="img" trim="1">
</MTSetVarTemplate>

This is still a lot to chew on, so let me break down exactly what is going on:

  • First, I use the <mt:ignore> tag to document what I had done and allow others to more easily re-use the module I created.
  • I define the name of the macro by using the name attribute on the <mt:setvartemplate> tag.
  • I invoke the macro, by using the <mt:getvar> tag.
  • I am able to access parameters I pass into the macro using a common programming syntax, in this case using the $max_size variable.
  • I am able to pass parameters into the macro by including them in my <mt:getvar> tag like any other attribute. For example (notice the max_size attribute corresponding to the variable of the same name inside of my macro):

I can't tell you how pleasantly surprised to find this feature. Using it greatly improved the readability of my templates, and also made them much each to maintain over time. And now looking back i can think of a million places through out my templates on every site I have ever worked on where this could really help make my template simpler and easier to maintain.

Recommended Entries

No Comments

Leave a comment

what will you say?


Close