PURE: Generate HTML from JSON data

Friday September 16, 2011 at 19:09 | tutorial

PURE

Asynchronous requests are a big part of life nowadays. Almost every major website uses AJAX in some form to increase interactivity without having to reload the full page with every request. One of the most popular response formats for AJAX is JSON. When compared to XML or HTML, JSON has a few distinct advantages: it's fast, uses less bandwidth and is supported natively by JavaScript, so no extra parsing is needed on the client-side to interpret the data sent by the server.

There is one big problem when choosing JSON as a response format for asynchronous requests. For instance, let's say that a list of articles fetched with JSON needs to be injected into a web page. JSON doesn't define the structure of the final list, so somehow an HTML template needs to be provided to be able to generate the list from the data. There are a few possibilities to address this issue:

  1. Feed the HTML template from the JavaScript file that handles the JSON data
  2. Load the template with a separate AJAX call
  3. Embed the template in the initial HTML response from the browser

With the first option you mix presentation (HTML) with logic (JavaScript). Furthermore, if you already use HTML templates with a server side language, then this option will likely cause duplication of HTML across separate files in your folder structure. The second option is even worse, because it defeats the purpose of using JSON as a response format. You'd be better off serving your data as a single request with HTML instead of JSON.

That leaves us with the third option. Choosing this option will ensure that logic is separated from the presentation and also prevents duplication of HTML. Still, the JSON data needs to be parsed with the template somehow...

Enter PURE

This is where PURE comes in. PURE stands for Pure Unobtrusive Rendering Engine and simply generates HTML from JSON data. The philosophy behind the project is that everything within your HTML files can become a template for your JSON data. It therefore effectively removes the need for embedding HTML templates in JavaScript files.

PURE works standalone but can be combined with any popular JavaScript framework like jQuery, MooTools or dojo. The source of the project can be found on GitHub.

Twitter example

Using PURE is simple and straightforward. I use it to display tweets on the front page of LieuweJan.com, which can perfectly serve as an example to show how PURE works. First off, the HTML template for the tweets is as follows:

<ul id="twitter-updates">
  <li class="tweet"><span class="time"></span></li>
</ul>

An excerpt of the provided JSON data:

{
  {
    text: 'Some tweet content',
    created_at: 'Fri Sep 16 08:57:19 +0000 2011' 
  },
  {
    text: 'Another tweet content',
    created_at: 'Fri Sep 16 07:52:56 +0000 2011'
  },
  {
    text: 'And another tweet content',
    created_at: 'Fri Sep 16 06:57:22 +0000 2011'
  }
}

The full JSON object Twitter provides contains a lot more data, but most of it is irrelevant to the example described here. Finally, the JavaScript lines to render the JSON data to HTML, using the template above:

// The DOM element that acts as the HTML template
var template = document.getElementById('twitter-updates');

// Directives to 'guide' the JSON data into the template
var directives = {
  'li.tweet': {
    'tweet <- context': {
      '+.': 'tweet.text',
      'span.time': function(arg) {
        return ' on ' + formatTime(arg.item.created_at);
      }
    }
  }
}

// Render template
template.render(jsonData, directives);

That's it. The render method provided by the PURE script takes two arguments: the JSON data and directives to 'guide' the data into the template. Of course, the above example deserves some explanation as to what happened here.

The example explained

I mentioned using directives as a means to guide the data into the template. But what are these so called directives? Directives are used to let PURE know where to let an action take place, based on a CSS Selector. So, if we wanted to place 'this awesome text' within <p class="here"></p> we could use the directive { 'p.here': 'this awesome text' } to do so. The result:

<p class="here">this awesome text</p>

The example also illustrates that one template can be used repeatedly to loop over multiple entries. This is done using the <- notation. To loop over the tweets provided as JSON, the context keyword is used to access the root element of the JSON. So the following syntax

'li.tweet': {
  'tweet <- context': {
    // ... etc
  }
}

means: "select li.tweet within the template and iterate over the root element of the JSON using tweet as a key for the current tweet in the loop."

The plus + and ampersat @ can be used to further specify the placement of values within a template. The plus is used to either append or prepend values to existing content in the template and the ampersat can be used to place it within an attribute. The dot . is used to indicate the current HTML node when iterating data. In the example . refers to the current li.tweet node in the loop.

'span@class'     // Place value within the 'class' attribute of the span tag
'+span.here'     // Prepend value within the span tags with classname 'here'
'a@href+'        // Append value in the 'href' attribute of the a tag
'+.'             // Prepend value in the current node

Finally, a function can be used if you need more flexibility when adding values within HTML tags. This will allow you to do more complex pre-parsing of a value before adding it to the template.

'div.moo': function(arg) {
  // Do something.
  return 'Something done here';
}

In the example I use a function to transform the time indication to a more readable format. When calling a function on a directive, the argument provided is an object with four properties. Notice that the last three properties are only present when inside a loop:

  • context: the JSON passed
  • item: the current item
  • items: all items of the loop
  • pos: the current position in a loop as an integer in an array or a property in an object

With the provided example here we created a Twitter feed with AJAX and JavaScript without ever putting HTML in our JS files. First, this ensures that HTML is never duplicated when the same template needs to be used with JavaScript and the server side language. Second, JS files are kept clean because HTML isn't embedded in our carefully crafted JavaScript logic.

Give me more

If you want to know more about the reasons why duplication and mixing of logic and presentation is unwanted, take a look at Orthogonality and the DRY principle. I've mentioned a few times that both things are very bad, but explaining why is a whole other subject. Furthermore, the writers Hunt and Thomas probably do a much better job at explaining these principles than me...

Of course there is more to PURE than the provided example here, but this introductory tutorial would become too bloated to mention everything. Take a look through the documentation to learn more. Maybe I will do a follow-up of this article in the future, but you can do most of your JSON parsing with the basics provided here.

If there are any questions or remarks: feel free to add your comment to this article or contact me directly.

References

blog comments powered by Disqus