« How to Customize Default Styles in MT4 | Main | Creating a Google Toolbar Button for Your Blog »

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

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.

Comments (2)

Just a reminder to newcomers, the random use of case in the MT tags in the examples given are inconsequential. MT can handle any case in the tags, but the 'proper' tag formatting looks like this:

{mt:TagName}

The format lowercase followed by a colon and then the tag name in camel case.

Cool macro! Only one thing missing and that's the ability to stick the image asset's label (mt:AssetLabel) or tags into the image's 'alt' tag. If your label all your photos or tag them in the Manage Assets screen it would be nice to pull that info in.

Ex: "cape cod".

i.e. img src="www.zzz.com" alt="cape cod"

Tried modifying the macro with no success.

suggestions on how to add mt:AssetLabel or mt:AssetTags to this macro?

TIA.

Post a comment

(If you haven't left a comment here before, your comment may need to be approved before will appear on the entry. Thanks for waiting.)