Ajax; Templating; and the Separation of Layout and Logic

[[innerindex]]

The Background

I have often mentioned my process of expanding my proficiency of Ajax. Through my journey I have made a number of wrong turns and hit my share of stumbling blocks. All of that has been a learning experience and I’m learning still. I began fiddling with XMLHttpRequest as many do – blissfully ignorant of the many frameworks that exist to make Ajax super easy. My code was bloated with some neat…’features’ (pronounced: bugs).

Then I discovered the Simple Ajax Toolkit (SAJAX), which was simpler than doing raw XMLHttpRequest but really not all that simple. My latest step into the world of Ajax, and the toolkit that holds my love (currently) is Prototype…and I like my Prototype served with a side of Script.aculo.us. *drool* UPDATE: I now use jQuery for all my Ajax and DOM manipulation goodness.

While Ajax is the cause for the article, the heavy focus is on templating. For the past few years I have been using XTemplate as my templating library (I’m a PHP buff) and have been happily separating my logic from my layout…unitl I ran smack dab into the power of Javascript. My PHP still kept its separation from HTML as is the purpose of XTemplate, but it was my HTML that became littered with little nuggets of Javascript all over the place. No matter the method to my Ajax madness, this was my problem.

What Exactly Is Templating And Why Do It?

Templating is definately not new and its use has been debated back and forth for quite some time. But like I stated above, the goal of templating is to keep logic separate from layout which is a good thing for a couple of reasons:

  1. Less clutter. Face it, HTML and whatever server-side scripting language you choose to use are two different beasts. Mixing them together is visually unappealing making code hard to read…and hard to read code is hard to debug.
  2. Coders can develop code. Designers can develop layout. With templating, you are able to achieve this separation and avoid the need for a developer to butcher a designer’s layout to make it function with an application. Each can design/code on their own then combine their efforts with ease.
  3. With separation such as this, applications are more easily skinned and/or receptive to complete UI overhauls.
  4. Did I mention less clutter?

Let me give you an example of what I mean with a simple Goodbye Cruel World application:

Here’s the PHP script: goodbye.php

< ?php
include('xtemplates.php');

$tpl=new XTemplate('goodbye.tpl');
$tpl->assign('CHEEZEWHIZ','Bork, bork, bork!');

$tpl->parse('main');
$tpl->out('main');
?>

Here’s the Template: goodbye.tpl

<!-- BEGIN: main -->
  <div style="font-size:18px;font-weight:bold;">Goodbye Cruel World! {CHEEZEWHIZ}</div>
<!-- END: main -->

Here’s the output:

Goodbye Cruel World! Bork, bork, bork!

Obviously that is an extremely simplistic example. With XTemplates I can get pretty complex and include files, loop over and parse out some complex block structures, assign arrays into template variables, etc. If you want to see a more complex example of a template, check it out here.

Templating Seems Sexy, How Does It Work In An Ajax-ified Environment?

I thought you’d never ask. For this, I have created a diagram to detail how I combine Ajax, PHP, and Templating all in one.


ajax_with_templating.gif

It all works like this:

  1. A User makes a request to view a page
  2. The server-side script calls a series of application functions that generate blocks of templates
    1. Each section that can be updated/rendered by Ajax calls are separated into their own templates, which enables them to be called on initial page load and separate Ajax-triggered calls from the client.
  3. The complete template blocks are sent to the user as a rendered page.
  4. As the user interacts with the interface, two specific things can occur:
    1. An Ajax.Updater (see Script.aculo.us) is triggered, which makes an Ajax callout. The callout is sent to the Ajax Handler (which is a PHP script) which handles the call and invokes the appropriate application functions. Those functions initialize template blocks and output HTML. The HTML output by the server is received by the client and inserted into the User Interface.
    2. An Ajax.Request (see Script.aculo.us) is triggered, which makes an Ajax callout. The callout is sent to the Ajax Handler (which is a PHP script) which handles the call and invokes the appropriate application functions. No templates are initialized or output to the client…instead, the client manipulates the DOM on its own to give proper feedback to the user.
  5. Rinse and repeat as needed.

If we keep all HTML within templates and use modularized functions to initialize and render those templates, we achieve extreme layout/code reuse.

Sounds Cool…So What’s The Problem?

Well, a server-side scripting language coupled with a templating engine is all well and good. But if as we throw Ajax into the mix, suddenly we are working with a lot of Javascript in addition to the a server-side language and HTML. Through my journey in Ajax development my templates – which were havens away from code – were overrun with Javascript code! Eegad.

Now, don’t worry. I place my Javascript in separate Javascript files and include them where appropriate with ye olde <script> tag, which I have done from the beginning. No, the issue has been handling user events; onClick, onMouseOver, onMouseOut, etc. Ajax functions primarily based on user interaction, so onClicks and whatnot are core. My templates soon began to look like this:

<!-- BEGIN: stuff -->
<div>
  <div>[<a href="javascript:void(0);" onClick="Element.show('add_item');">Add</a>]</div>
  <div id="add_item" style="display:none;">
    <form id="add_item_form" onSubmit="Ajax.Request('ajax.php?'+Form.serialize('add_item_form'),{method: 'post'});return false;">
      Name: <input type="text" name="name"/> <input type="submit" value="save"/> <input type="reset" value="cancel" onClick="Element.hide('add_item');"/>
    </form>
  </div>
</div>
<!-- END: stuff -->

As you can see, the once separate layout was laden with code.

The Solution

In a fully layout separate from logic in an Ajax environment, you need to make use of Javascript event handlers. My personal choice is Behaviour which my friend, Zach, posted about yesterday.

Behaviour (coupled with Prototype) gives you easy-to-follow separation of javascript and HTML. Hugely cool. Hugely useful. Here’s an example:

The HTML:

<ul id="example">
  <li>
    <a href="/someurl">Click me to delete me</a>
  </li>
</ul>

The Javascript:

var myrules = {
  '#example li' : function(el){
    el.onclick = function(){
      Element.removeChild(this);
    }
  }
};

Behaviour.register(myrules);

That example creates a bulleted list (as is readily obvious in the HTML code). What nifty is the Behaviour Javascript logic. myrules says that any <li> tag with a parent id of #example will have an onclick that causes the li tag to be removed.

And of course, besides Behaviour there is a slew of other solutions that when combined together make for a sweet, modularized, separated solution. Here’s what I use for my PHP/Ajax applications:

Here are some standards I stick to:

  • Keep CSS (.css) styles separate from the Template files
  • Keep JavaScript (.js) files separate from Template files
  • Keep HTML in the Template, don’t spatter it around the PHP scripts
  • Modularize as much as possible
  • Heavy Code reuse

The Drawbacks

Obviously in a Templated/Event Handled environment there are some drawbacks and I’d be stupid not to mention them. Here goes:

  • There is some overhead when using a templating engine. With XTemplate, the layout engine is a PHP class that loads the template and parses through it as dictated by the application functions
  • True separation – separating out your Javascript into .js files, your CSS into .css files, your server-side scripts into various files (the initial script, a functions script, and your ajax handler(s)), and your layout into template files – generates a lot of files to deal with. The larger your application, the more you will need to micro-manage the organization of these files, which in and of itself can be a daunting task.
  • Ummm…I can’t think of any more just yet. I’m sure more will come when I’ve lived in this environment a lot longer.

Summary

Layout and Logic separation is a beautiful thing; keeping one language from another has some true value in readability. To do it half-way gains you nothing. True separation has been a blessing in my development and debugging. If you haven’t at least tried it, check it out, it may be what you were looking for (even if you didn’t know it).

Oh and a definate Kudos to Zach Tirrell for starting me down the road of templating and Gmail/Google Maps/Casey Bisson for driving me to check out Ajax.