jQuery Template Markup Language (JTML) AJAX Demo

Posted April 29, 2010 at 9:46 AM by Ben Nadel

Tags: Javascript / DHTML

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

Apr 29, 2010 at 10:16 AM // reply »
29 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?


Apr 29, 2010 at 10:20 AM // reply »
11,238 Comments

@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.


Apr 29, 2010 at 10:26 AM // reply »
2 Comments

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.


Apr 29, 2010 at 10:29 AM // reply »
11,238 Comments

@Chris,

Thanks my man - I really appreciate the positive feedback.


May 4, 2010 at 9:15 PM // reply »
1 Comments

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) :)


May 4, 2010 at 9:25 PM // reply »
11,238 Comments

@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.


May 11, 2010 at 11:36 AM // reply »
1 Comments

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


May 16, 2010 at 10:09 PM // reply »
11,238 Comments

@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


May 16, 2010 at 10:12 PM // reply »
11,238 Comments

@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.


Sep 8, 2010 at 10:57 AM // reply »
1 Comments

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.


Sep 9, 2010 at 10:52 AM // reply »
11,238 Comments

@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?


Oct 25, 2012 at 2:42 AM // reply »
2 Comments

nice post ! but i wonder use j template is faster than bind from server !


Jan 9, 2013 at 3:24 AM // reply »
1 Comments

Thanks



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 20, 2013 at 11:45 AM
Using jQuery's Animate() Step Callback Function To Create Custom Animations
This is really useful. I found out that you don't actually have to use a dummy css property (surprisingly). To animate a property in a linear-gradient for instance I did this this.css('someLinearGra ... read »
May 20, 2013 at 10:51 AM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Josh, Oh snap! You're totally right! I'm not sure I've ever tried that. I did know that you can call a number of other array-methods on ColdFusion query columns: http://www.bennadel.com/blog/167 ... read »
May 20, 2013 at 10:45 AM
Using A Dynamic Column Name With ValueList() In ColdFusion
@Ben - I believe you can achieve the same functionality with ColdFusion's built in ArrayToList() function. ArrayToList( users[ "id" ] ); ... read »
May 20, 2013 at 10:21 AM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
Is there any error logging and handling framework in angularjs, if not then in what way I can do this. ... read »
May 19, 2013 at 2:31 PM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
It's funny really just how well that image describes the way I would imagine most people that go with angular for some project is. I have had a similar roller-coaster ride with it as well, but not qu ... read »
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools