Quantcast
Channel: Bit of Technology » jQuery
Viewing all articles
Browse latest Browse all 2

Boost UI Rendering with Client Side Templating

$
0
0

Previous week I was preparing for internal Tech. session for my work colleagues; It was mainly about how we can Improve UI rendering experience for heavy pages and how we can move the UI heavy lifting from the server to the client. Let the server get busy with Data retrieval only.

You can download the demo application using the following link.

In typical client server architecture, the server sends the HTML and CSS to the browser, and the browser is responsible for just rendering it. The client is not doing anything except rendering the HTML, more over the size of the response transferred over the wire is very big, it will contain formatted HTML tags, CSS and the data itself.

To overcome the typical architecture, we need to return the data only from the server to the client using the lightweight JSON format, then the client will be responsible to manipulate the DOM elements with the data returned then rendering the final result.

Let’s take a look on the figure below to illustrate how this pattern works:

To achieve this pattern we need to do the following:

  1. Client should request data from server using AJAX.
  2. Data should be sent from the server as JSON response.
  3. Once the data received we need to render it (Convert it to HTML) using Client Side Template.

What is Client Side Templating?

It is a front end technique which helps the developer to separate markup and logic, maximize code maintainability and re-usability. By using this technique you will implement the Separation of Concerns design principle.

To define a template I would like to quote a simple definition found here.

A document that contains parameters, identified by some special syntax, that are replaced by actual arguments by the template processing system.

As a basic example let’s consider the below template which contains HTML tags with certain places holder where they will get replaced by data


<h3>{{movie}}</h3>
<ul>
 {{#actors}}
 <li>{{actor}}</li>
 {{/actors}}
</ul>

Example for simple JSON data as below:


{
 "movie": "The Bourne Ultimatum",
 "actors": [
 {"actor": "Matt Damon"},
 {"actor": "Joan Allen"},
 {"actor": "Julia Stiles"}
 ]
}

So the final results after replacing the placeholders with the data would look like the below HTML. It will be easy to maintain the HTML in future without touching the data returned:


<h3>The Bourne Ultimatum</h3>
<ul>
 <li>Matt Damon</li>
 <li>Joan Allen</li>
 <li>Julia Stiles</li>
</ul>

Which Templates are available? Which one should I use?

There are many client side templating engines available in the market, the most popular ones are: underscore.jsjQuery templatesmustache, dust.js, and handlebars.js choosing the right template for your application depends on different factors such as:

  1. Logic-less templates; which depends how much logic you want to use in the template, less logic always force developers to separate presentation layer from business logic.
  2. The clarity and cleanliness of template syntax.
  3. Whether if the template is compiled or interpreted.
  4. Community and code documentation.
  5. The performance of the template, how long does it take to render data on the browser.

There are two links which might be useful to decide which template engine is suitable for your application, the first link discusses deeply how LinkedIn decided to use dust.js over other 26 templates. The second link helps you selecting the appropriate template using some filters.

Let’s have a concrete example which covers this technique…

First of all I need to decide which template I want to use, my concerns on this demo application are top-performance and logic less template, the winner is handlebars.js. You can use the following link which benchmarks different template engines against your browser scope.

After selecting the template we need to find a RESTful API which returns JSON data. As a movies’ lover I chose a simple API which is the unofficial API for IMDB, it allows search by movie names, and movie IDs, special thanks goes to @imdbapi for making this API available.

Basically my example will do the below:

  1. User searches for a movie title.
  2. GET HTTP request is sent to the API, response is received in JSON format. Using the API is pretty simple, you need only to make a GET request to http://imdbapi.org/?title=spiderman&type=json&plot=simple&episode=1&limit=5&yg=0&mt=none&lang=en-US&offset=&aka=simple&release=simple&business=0&tech=0 
  3. handlebars.js template engine will be responsible for parsing the data returned and displaying search results in a neat way.

Building server side logic.

Basically I will create a generic handler (.ashx) which will be responsible for communicating with the IMDB API then returning the JSON data to the client, the handler will accept a query string containing the movie title, the code will be as the below:

Note: Always use .ashx files when you make GET requests as they perform better than .aspx pages; there is no page life events (int, load, render, etc…) we do not need these events in our case.


Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

context.Response.Expires = -1
 context.Response.ContentType = "application/json"

Dim _MovieTitle As String = String.Empty
 Dim _JSONResponse As String = String.Empty

If Not String.IsNullOrEmpty(context.Request.QueryString("t")) Then

_MovieTitle = context.Request.QueryString("t").ToString

Dim _URI As UriBuilder = Nothing

Dim _URL As String = String.Format("http://imdbapi.org/?title={0}&type=json&plot=simple&episode=1&limit=5&yg=0&mt=none&lang=en-US&offset=&aka=simple&release=simple&business=0&tech=0",
 HttpUtility.UrlEncode(_MovieTitle))
 _URI = New UriBuilder(_URL)

Dim _AbsoulteURI = _URI.Uri.AbsoluteUri

Dim _Request As Net.HttpWebRequest = Net.WebRequest.Create(_AbsoulteURI)

_Request.Method = "GET"
 _Request.ContentType = "application/json"

Try

Using _Response As Net.HttpWebResponse = TryCast(_Request.GetResponse(), Net.HttpWebResponse)

Dim _Reader As New IO.StreamReader(_Response.GetResponseStream())

_JSONResponse = _Reader.ReadToEnd

End Using

context.Response.Write(_JSONResponse)

Catch ex As Exception
 Throw ex
 End Try

End If
 End Sub

Client side Markup and Handlebars Template.

The basic markup for the search page is straightforward, it will contain a search box, progress indicator, and a placeholder for search results, the HTML will look like the below:


<div id="container">
 <div id="searchContext">
 <div id="searchbox">
 <input id="search" type="text" placeholder="Search by Movie Title..." />
 <input id="submit" type="submit" value="Search" />
 </div>
 <div id="progress">
 <img src="images/ajaxbarloader.gif" />
 </div>
 <div id="searchResults">
 </div>
 </div>
 </div>

The fun part comes here, where we prepare the handlebars template, basically we will include a <script> tag with type “text/x-handlebars-template” at the bottom of our html page, by keeping the template in the same html page; we will avoid requesting it using AJAX in case it was in separate file. Let’s take a look on how the template look like:


<script id="movieTemplate" type="text/x-handlebars-template">

 <ul>
 {{#movies}}
 <li>
 <div id="poster">
 <a href="{{imdb_url}}" target="_blank">
 <img id="posterImg" alt="{{title}}" src="{{poster}}" /></a>
 </div>
 <div id="movieDetails">
 <h4>{{title}} (<a target="_blank" href="http://www.imdb.com/year/{{year}}">{{year}}</a>)</h4>
 <span>{{runtime.0.this}}
 {{#each genres}}
 <a target="_blank" href="http://www.imdb.com/genre/{{this}}">{{this}}</a>
 {{/each}}
 </span>
 <hr />
 <p><span class="bold">Ratings: </span><span>{{rating}}/10 from {{rating_count}} users</span></p>
 <hr />
 <p>{{plot_simple}}</p>
 <p><span class="bold">Director: </span><span>{{directors.0.this}}</span></p>
 <p><span class="bold">Stars: </span><span>{{actors.0.this}}, {{actors.1.this}}, {{actors.2.this}}</span></p>
 <p><span class="bold">Locations: </span><span>{{filming_locations}}</span></p>
 </div>
 <div style="clear: both;"></div>

</li>
 {{/movies}}
 </ul>

</script>

What I’m doing here is building unordered list based on the movies array returned by the JSON response, then plotting some movie properties such as title, year, poster, etc…

Sending the JSON response to handlebars.js will take place on the success event of the AJAX call as in the code below:


function OnSearchAjaxSucceeded(data) {
 var templateSource = $("#movieTemplate").html();
 var compiledTemplate = Handlebars.compile(templateSource);
 $('#searchResults').html(compiledTemplate({ movies: data }));
}

Looking at the code snippet above, at line no. 2 I’m referencing the script tag (template), then at line no. 3 I’m calling the handlebars API “compile” so the template will be compiled into a JavaScript function at run-time. Finally at line no. 4 I’m passing the JSON data to the compiled template and doing a little trick; which is wrapping the response with “movies” object because the response from the API contains an array without a name.

How the handlebars template will translate JSON data to HTML?

  • The placeholder {{#movies}} will create for each loop on every movie received in the movies array.
  • Once there is a reference to a single movie, we can access it’s properties directly as in {{imdb_url}}, {{title}}, and {{year}}, etc…
  • Accessing another array inside the movie object is simple, we need to do another for each by using {{#each genres}}, we will have a reference for the genre object by calling {{this}}.
  • The dot notation is the way to access array by index, so if we want to select the second director from directors array we need to do it like this {{directors.1.this}}.

Finally, displaying the results in a neat way.

We need to add some CSS to our IMDB search page to have the final results as the image below, I’ve used a pretty search box which uses CSS3, you can find reference for it here.

movie

You can download the demo application using the following link.

Thanks for reading this post and hopefully it will be useful in your coming projects.



Viewing all articles
Browse latest Browse all 2

Latest Images

Trending Articles





Latest Images