Templating system
I knew when I started this project (which was a while ago, I kinda cheated on this one) that I didn’t want to write out all the HTML myself, I’m not THAT masochistic. What I wanted to do was basically say “make a text box to write the address in”.
So I started with a generic preprocessor. I’ve use preprocessors such as CPP, TeX and Make so figured I would take a generic preprocessor like M4 and define a few HTML macros… problem solved. Unfortunately it wasn’t that simple and as I added complexity it got harder to keep it all straight, particularly the quoting.
The basic text box wasn’t too bad.
dnl TEXT_Q(name, label, [length])
define('TEXT_Q', `indir(LAYOUT, '$1',
'<label for="$1_text">$2</label>',
'<input id="$1_text" name="$1">
ifelse($3, '', '', 'size="$3"')>’
But when I tried to create optional groupings it started to get messy. This is a snippit from TABULAR_OPTIONAL_ROWS and calling it.
dnl Build the heading rows
<tr class="tabular_optional_rows_heading_row">
pushdef(\`LAYOUT', “TABULAR_OPTIONAL_ROWS_HEADING_LAYOUT”)
foreach(\`XXXXX', (dquote(shift($@))), \`XXXXX')
popdef(\`LAYOUT')
</tr>
TABULAR_OPTIONAL_ROWS(3,
`TEXT_Q(salary_abn, Payers Australian business number, 11)‘, dnl TODO: Should be Payer's
…
With TABULAR_OPTIONAL_ROWS I couldn’t figure out how to have a variable number of rows and I couldn’t figure out how to pass it’s options without quoting so I decided to throw in the towel and switch to something else.
I had experimented with Template Toolkit at work using it to inject snippits of Javascript into HTML documents. In the end I stopped using it and had a static HTML page which included a fully generated Javascript file but the short exposure I had impressed me and I tried it here. I found it much cleaner, the named parameters cut out a lot of complexity and the ability to just drop back to Perl if I wanted to do something really hairy was nice.
This is the definition of a text box followed by the calling syntax of a radio box that toggles the visibility of the text box.
<tr class="text" id="[% name %]_row"
[%- IF hide -%]
style="display: none"
[%- END -%]
>
<td class="question">
<label for="[% name %]_id">[% text %]</label>
</td>
<td class="answer">
<input type="text" name="[% name %]" id="[% name %]_id">
</td>
</tr>
[% INCLUDE tax/radio
name = "surname_changed"
text = "Has any part of your name changed since completing your last tax return?"
modify = "previous_surname"
options = [{name => "Yes", action => "show"}, {name => "No", action => "hide"}]
%]
[% INCLUDE tax/text
name = "previous_surname"
text = "Previous surname"
hide = "true"
%]
The normal syntax for options is simply [“Yes”, “No”], the Perl fallback I mentioned earlier allows me to have more complex syntax when I need it but keeps things simple most of the time. I’ve since discovered there’s a Template Toolkit version three that’s a nice step forward but it’s listed as still in development and in a very Alpha state, it also smelt a bit like it was suffering from classic second project woes. I think I’m playing with enough new stuff not to add experimental Template Toolkit versions to the list.