Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at CFUNITED 2009 (Lansdowne, VA) with:

jQuery Template Markup Language (JTML) AJAX Demo

By Ben Nadel on

After publishing the jQuery Template Markup Language (JTML) project with a basic, single-page demo, I thought I'd put together a simple AJAX demo. In this example, the JTML template is still defined on the main page; but, the JSON data used to populate the template is being pulled down from the server using jQuery AJAX. Once the data is pulled down, it is merged with the template and appended to the page. I am not using the full breadth of JTML tags - neither the template nor the data is all that complex. This is simply meant to demonstrate the pulling of remote data to populate the template.

 
 
 
 
 
 
 
 
 
 

For the demo, I set up a very simple ColdFusion page on the server that generates a random Girl object and returns it in JSON format. The code for this is listed farther down, but essentially, it returns a struct with randomly selected name, hair, eyes, weight, etc. values. This struct is then merged with the JTML Girl template and appended to the page:

  • <!DOCTYPE HTML>
  • <html>
  • <head>
  • <title>jQuery Template Markup Language (JTML) AJAX Demo</title>
  • <style type="text/css">
  •  
  • #girls {
  • list-style-type: none ;
  • margin-left: 0px ;
  • padding-left: 0px ;
  • }
  •  
  • li.girl {
  • border-bottom: 1px dotted #CCCCCC ;
  • padding-bottom: 14px ;
  • }
  •  
  • li.girl h4 {
  • margin-bottom: 4px ;
  • }
  •  
  • li.girl p.description {
  • margin: 0px 0px 7px 0px ;
  • }
  •  
  • li.girl p.age {
  • font-size: 90% ;
  • margin: 0px 0px 7px 0px ;
  • }
  •  
  • li.girl p.note {
  • color: #999999 ;
  • font-size: 90% ;
  • font-style: italic ;
  • }
  •  
  • </style>
  • <script type="text/javascript" src="jquery-1.4.2.js"></script>
  • <script type="text/javascript" src="jquery.jtml.js"></script>
  • <script type="text/javascript">
  •  
  • // When the DOM is ready, initialize scripts.
  • jQuery(function( $ ){
  •  
  • // Create a new JTML template renderer.
  • var girlTemplate = new JTMLTemplate(
  • $( "script.template.girlTemplate" )
  • );
  •  
  • // Get a reference to the output.
  • var girls = $( "#girls" );
  •  
  • // Get a reference to the 'create' link.
  • var createGirl = $( "#createGirl" );
  •  
  •  
  • // Bind the create link to make a new girl (via AJAX).
  • createGirl.click(
  • function( event ){
  • // Cancel the event since this isn't a real link.
  • event.preventDefault();
  •  
  • // Make the call to the server to get a new girl.
  • // This will come back as JSON data.
  • $.getJSON(
  • "./random_girl.cfm",
  • function( girl ){
  •  
  • // Given the girl data, populate a girl
  • // template and then just append to girls
  • // output list.
  • girls.append(
  • girlTemplate.render( girl )
  • );
  •  
  • }
  • );
  • }
  • );
  •  
  • });
  •  
  • </script>
  • </head>
  • <body>
  •  
  • <h1>
  • jQuery Template Markup Language (JTML) AJAX Demo
  • </h1>
  •  
  • <h2>
  • Random Girls
  • </h2>
  •  
  • <p>
  • <a id="createGirl" href="#">Create another girl</a> already!
  • </p>
  •  
  • <ul id="girls">
  • <!-- To be populated dynamically. -->
  • </ul>
  •  
  •  
  • <!-- --------------------------------------------------- -->
  • <!-- --------------------------------------------------- -->
  •  
  •  
  • <!---
  • Define the girl template.
  •  
  • NOTE: I am using UPPER case javascript keys because I am
  • communicating with a ColdFusion server (which uses upper-
  • case values). This has *nothing* to do with JTML.
  • --->
  • <script type="text/jtml" class="template girlTemplate">
  •  
  • <li class="girl">
  •  
  • <h4>
  • ${NAME}
  • </h4>
  •  
  • <p class="description">
  • ${NAME}, affectionately known as "${NICKNAME}",
  • has ${HAIRCOLOR} hair and ${EYECOLOR} eyes.
  • </p>
  •  
  • <p class="age">
  • Published Age:
  • ${Math.floor( AGE - (7 * Math.random()) )}
  • </p>
  •  
  • <!--
  • For certain body types, I'm gonna borrow a phrase
  • from the Flight of the Conchords.
  • YouTube: http://www.youtube.com/watch?v=JT5AQIlmM0I
  • -->
  • <jtml:if test="(BODYTYPE == 'Athletic') || (BODYTYPE == 'Plump')">
  •  
  • <p class="note">
  • She's so hot, she's making me sexist!
  • </p>
  •  
  • </jtml:if>
  •  
  • </li>
  •  
  • </script>
  •  
  • </body>
  • </html>

As you can see, I have a "create girl" link which triggers the AJAX call to the server. Once the server returns the random girl JSON data, I use it to invoke the render() method on an instance of the JTMLTemplate class. This merges the JSON into the given template and returns the resultant HTML. This HTML is then appended to the girls UL element. After clicking on the "create girl" link a few times, this is the kind of output that we get:

 
 
 
 
 
 
jQuery Template Markup Language (JTML) AJAX Demo With ColdFusion. 
 
 
 

As you can see, the JSON data was successfully combined with the JTML template and appended to the page. And, while I didn't use too much logic in the template, you can see that the note in the template was conditionally rendered based on the girl's randomly selected bodyType value.

If you want to see the ColdFusion page that generates the random girl data, here it is:

  • <!---
  • This file is meant to be used with the AJAX demo. This returns
  • a randomly created girl (ala Wierd Science) and returns it in
  • JSON format.
  • --->
  •  
  • <!--- Define possible names. --->
  • <cfset names = [
  • "Vicky",
  • "Erika",
  • "Sarah",
  • "Tricia",
  • "Joanna"
  • ] />
  •  
  • <!--- Define possible nicknames. --->
  • <cfset nickNames = [
  • "Sweetie",
  • "Pookie",
  • "Sugar Bear",
  • "Honey Bun",
  • "Baby Cakes"
  • ] />
  •  
  • <!--- Define possible hair colors. --->
  • <cfset hairColors = [
  • "Brunette",
  • "Blonde",
  • "Black",
  • "Red"
  • ] />
  •  
  • <!--- Define possible eye colors. --->
  • <cfset eyeColors = [
  • "Brown",
  • "Blue",
  • "Green",
  • "Black"
  • ] />
  •  
  • <!--- Define possible body types. --->
  • <cfset bodyTypes = [
  • "Plump",
  • "Athletic",
  • "Voluptuous",
  • "Curvey",
  • "Thin",
  • "Average"
  • ] />
  •  
  •  
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  •  
  •  
  • <!---
  • Ok, now that we have a bunch of attributes to choose from,
  • let's create a random girl. Mmaaa ha ha ha ha ha. It's Alive!
  • --->
  • <cfset girl = {
  • name = names[ randRange( 1, arrayLen( names ) ) ],
  • nickName = nickNames[ randRange( 1, arrayLen( nickNames ) ) ],
  • hairColor = hairColors[ randRange( 1, arrayLen( hairColors ) ) ],
  • eyeColor = eyeColors[ randRange( 1, arrayLen( eyeColors ) ) ],
  • bodyType = bodyTypes[ randRange( 1, arrayLen( bodyTypes ) ) ],
  • weight = randRange( 100, 200 ),
  • age = randRange( 25, 55 )
  • } />
  •  
  •  
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  •  
  •  
  • <!--- Conver the response to binary for streaming. --->
  • <cfset binaryResponse = toBinary(
  • toBase64( serializeJSON( girl ) )
  • ) />
  •  
  •  
  • <!--- Define the header for the client. --->
  • <cfheader
  • name="content-length"
  • value="#arrayLen( binaryResponse )#"
  • />
  •  
  • <!--- Stream the girl back as JSON data. --->
  • <cfcontent
  • type="text/json"
  • variable="#binaryResponse#"
  • />

As you can see, not much going on here except for the heavy use of randRange() to select values.

As I was building this demo, I actually made a few small tweaks to the JTML library. Previously, if you wanted to perform Javascript operations inside of ${..} output, you needed to wrap the content in parenthesis. I updated the library to do that for you so you no longer need to do that directly within the template. All in all though, I hope this demonstrates the ease with which JTML might allow you to merge JSON data and HTML markup. Perhaps in the next demo, I'll fool around with loading the JTML template off the server as well (something I've never tried with any rendering engine).




Reader Comments

Haha, nice Flight of the Conchords reference!
I really dig this template concept. Thanks, this demo is really helpful.
Is this the template engine which shall become part of jQuery core one day?

@Martin,

Thanks my man. I know there is some template proposals for jQuery - this one is not even on the radar :) I'm not nearly that plugged into the jQuery world.

Hey Ben, thank you for another nice demo. I'm looking forward to the next one where you will remotely load templates. Hopefully I will find time today to play around a bit with JTML - great stuff.

Sorry to note this, but it's not a demo, Ben, it's a descrption of a demo. Why not put the script online? A picture is worth a thousand words... and a click is worth a hundred pictures (plus a couple of videos) :)

@Dave,

A couple of people have asked for "usable" demos (for lack of a better term) in the recent past. I have not philosophical issue with it; I definitely think it would add value - it's simply a time / effort thing. For the ColdFusion stuff, this makes less sense; but perhaps for the Javascript stuff, which is so much more tangible, I'll try to make some of this stuff happen.

Ben, nice post. Just starting to take a look at the actual code, but always glad to see new template engines for javascript, I much prefer this approach to the stand jquery inline string interpolation. I have to echo the requests for making the demo code easily downloadable, but I will go a step further and suggest a solution - put it on github. This is free and easy, you could have one repo for your library, and others for any examples you create. An added benefit is that you may get people contributing to your code, so you don't have to do all the work.

Another question I have is - what is the license? If you have not thought about this and want it to be open source, I woudl suggest MIT, as that is compatible with almost everything.

Lastly, you might want to add this to the jquery plugins site. I took a quick look and did not see it, so if you have already done this, feel free to disregard :) Again, great post, you write some really good content

@Jason,

I only just watched my first presentation on GIT the other week at a conference. As such, I don't know enough about GitHub to start using it just yet. Although in the future, perhaps that can be a good approach. I know that Git is really becoming a hot ticket item lately.

As far as licensing, I just post code as-is. I've never really thought of licensing. I suppose it's time that I put more thought into that. Of course, how does not one separate the code in a project vs. the code on a blog post? Do I have to up a license on each blog post?

Thanks for the jQuery plugins suggestion. I had not thought of that and you suggesting that is quite an endorsement :D

@Jason,

Holy cow! I just checked the plugin site. They have 19 pages of results for the phrase "templates". Seems like this would just be lost in the noise.

Hi,Ben. I'm a Chinese web developer. I used your jtml plugin but I found it didn't work when json object contains Chinese character in json's value field. Would you fix this bug ? I'm so glad to use your plugin. Thank you very much.

@Clive,

I'll have to experiment with high-ascii characters. I am not sure what part of it is breaking - the JSON or the string replace.

Is it actually throwing an error? Or is it simply not doing anything?

Really nice post! Thanks for posting the demo about jQuery Template Markup Language. jQuery plugin is used for loading and using templates. jQuery template is a javascript library.The advanced version of jquery is 1.9.1