DOM Template Fantasy

Created 2006-05-05 / Edited 2006-05-06

I have this fantasy. You may have heard it before, it's pretty common. One day I'm designing this website for some people. Actually, I'm not designing it, I'm coding it -- I'm doing all the dynamic programming stuff. My partner in crime is a Designer (mainly graphic design, but also HTML, no programming) named Sarah, and she is doing the actual design. Together we talk to the client and she sketches some things that they like and I talk about the newest headlines showing up on their homepage, and so on.

Sarah goes off and starts doing her thing and I set up a server and get my tools together and even build up an ugly prototype. Then Sarah brings over her HTML and graphics and such. Here is where the fantasy kicks in. Pay attention. She brings over her stuff and gives it to me. She points at the screen and says "See that? That's where your headlines go".

Lets digress a bit. Many people in my position would, at this point, take her HTML file, rename it .php (or similar), rip out the HTML where she pointed and replace it with some inline code. Hopefully they wouldn't put database accesses and such there, but if nothing else they have maybe a loop that prints out each element in an array wrapped in some HTML tags.

OK, un-digress. Pay attention again. I look at her HTML and see that the tag she points at is already labeled with an ID, #headlines. I need to grab the headlines from a database, but I already did that and now have them in an array.

I close the HTML file she gave me.

Back in my code I add this...

# ... $doc already defined ...
# ... @headlines already defined ...
$rules = [
  '#headlines' => sub {
    my $tag = shift;
    # Turn the headline array into an HTML unordered list
    @headlines = map { "<li>$_</li>" } @headlines;
    my $headlines = "<ul>@headlines</ul>";
    $tag->replace_content($headlines);
  },
];
$doc->apply($rules);

...and attain the desired affect. The headlines are turned into an HTML list and replace the content of the named tag.

Later that day the client calls and tells us that they want the headlines on five other pages. Sarah makes the change, and gives me the HTML. I do nothing.

Sarah has this cool navigation bar she set up for them... but it is tedious to add it to each page and even more tedious to differentiate each snippet so that the currently-viewed page is highlighted. "No problem", I tell her. "Give me one page with the navigation bar as you like it," I say. A few more twitches of the keyboard and I make all the pages inherit the key piece of HTML. For highlighting the current page, I do something like:

my $rules = [
  '#navbar a' => sub {
    my ($node) = @_;
    my $href = $node->attr('href');
    $href =~ s/^.*?\.com//; # Chop off the http://bleh.com/ part
    if($real_path =~ /$href/) { # If this link is like this path
      $node->add_class('selected'); # We highlight this link
    }
  },
];  

Sarah never looks at my code. She doesn't have to see it, doesn't have to dodge it or carefully copy/paste it in her WYSIWYG designer. I don't have to cry over < turned into &lt;. She removes some of the headlines, I do nothing. She adds a link to the navigation menu, I do nothing.

It's not much of a fantasy because I've already implemented it. Taking inspiration from behaviour.js, along with the wonders that CPAN provides (namely cpan:HTML::TreeBuilder) it is not a very difficult task. Others, in fact, are already using DOM manipulation for templating systems (TAL and its relatives, cpan:HTML::Seamstress)... but none quite this way.