Azure + Bing Maps: Displaying structured data in rich HTML applications with jQuery Templates

This is the 8th article in our "Bring the clouds together: Azure + Bing Maps"
series. You can find a preview of live demonstration on

https://sqlazurebingmap.cloudapp.net/. For a list of articles in the series,
please refer to

https://blogs.msdn.com/b/windows-azure-support/archive/2010/08/11/bring-the-clouds-together-azure-bing-maps.aspx.


Introduction

Our previous post described how to work with Bing Maps in a rich HTML
application. A map provides a modern representation of geography related
data. It also allows you to do a lot of work that you formerly did using
lists. You can, for example, popup a form when user clicks a pushpin, to
collect data about that particular location.

But we have to admit lists (or similar representations) are still very
useful, even when working with geography data. For example, when
planning a trip across the global, a list can potentially help you to quickly find a
particular data without navigating around the map. Additionally, some
users may simply prefer to work with lists.

This post introduces how to use jQuery Templates to easily create a list
to represent structured data in a rich HTML application. You will see
how it helps you to reduce efforts compared to a traditional solution,
such as creating DOM elements in JavaScript. We assume the audiences have basic knowledge of HTML
4, JavaScript, CSS, and jQuery. No HTML
5 knowledge is used.


Traditional solutions to display lists

There're two solutions to display lists in a HTML web application:
Server side solution and client side solution.

Most web developers using Microsoft technologies know how to display
lists with a server side solution, using ASP.NET server controls like
ListView. Those server controls provide a rich programming model with
rich data binding support. You can define a template for a single data
item, associate the template with a list of data source, and the
template will be automatically applied to all data items. ASP.NET MVC
developers can also take advantage of foreach loop and html helpers to
display a list without too much efforts.

But as more and more web applications move towards client driven
(especially consumer oriented web applications), developers have to
begin to investigate JavaScript. Traditionally, Microsoft doesn't
provide a JavaScript framework that is as easy to use as server side
framework such as ASP.NET. So developers have the following options:

  • Use ASP.NET UpdatePanel (or partial view in MVC) to create the list on
    the server side. This simulates AJAX behavior, but since every request
    requires a round trip to the server, performance will be impacted.
  • Write JavaScript code: Work with DOM, create lots of elements, combine
    various strings, and so on... This takes a lot of efforts. See the below
    appendix for an idea.
  • Use a third party JavaScript framework. Since currently there's no
    standard framework, developers may have a hard time to figure out which
    framework to use for which project.

Appendix: Create a list using JavaScript without jQuery Templates.

 $(datasource).each(function ()

{

DisplayItem(this);

});

function DisplayItem(item)

{

var li = $('<li/>');

var divPlace = $('<div/>');

divPlace.append(item.Place);

divPlace.addClass('LeftColumn');

li.append(divPlace);

// Latitude

li.append('<div>' + item.Latitude + '</div>');

// Longitude

li.append('<div>' + item.Longitude + '</div>');

var divTime = $('<div/>');

var textTime = $('<input/>');

textTime[0].type = 'text';

textTime[0].value = $.datepicker.formatDate('yy-mm-dd', item.Time);

textTime[0].readOnly = true;

textTime.datepicker({ onSelect: DateChanged, dateFormat: 'yy-mm-dd' });

divTime.append(textTime);

li.append(divTime);

var deleteButton = $('<input type="button" value="Delete"/>');

deleteButton.click(DeleteItem);

var divDelete = $('<div/>');

divDelete.append(deleteButton);

li.append(divDelete);

li.append('<input type="hidden" value="' + item.ID + '"/>');

li.click(SelectItem);

$('#LocationList').append(li);

}


Introduce jQuery Templates

To avoid the problems in traditional client driven web application
development, Microsoft and jQuery had a joint investment. The result is
jQuery
Templates
, which is currently in Beta. If you have experience with
WPF/Silverlight DataTemplate, you can roughly think jQuery Templates
plays the same role as Silverlight DataTemplate. If you have experience
in ASP.NET, you can roughly think it is a ListView control, except
everything is done on the client side. We will not describe what jQuery
Templates is with further text, instead, let's see it in action.

First, link to the jQuery Templates script. You can download the script
from
https://plugins.jquery.com/project/jquerytemplate, or simply use AJAX
CDN.

<script
type="text/javascript"
src="https://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>

Now suppose we have a list of objects. Each object has the following
properties:

PartitionKey, RowKey, Place, Latitude, Longitude, Time


Create a template

To display the data, first create a template. A template is also a
script. But it's not JavaScript. The type is text/x-jquery-tmpl.

<script
id="travelTemplate"
type="text/x-jquery-tmpl">

<li>

<div class="ItemContainer" onclick="SelectItem(this)">

<div class="PlaceDiv">${Place}</div>

<div>Location: ${Latitude}, ${Longitude}</div>

<div>Time: <input type="text" class="DatePicker"
value="${formatDate(Time)}" readonly/></div>

<input type="button" value="Delete" onclick="DeleteItem(this)"/>

<input type="hidden" value="${PartitionKey}"/>

<input type="hidden" value="${RowKey}"/>

</div>

</li>

</script>

As you can see, most of the scripts are plain old html. You can design
the template using any tool you like, such as Expression Web.

You can see tokens like "${Place}". This means when the template is
applied, the value of the Place property on the data source object will
replace the place holder. Note if you download the source code (which
will be available soon), you will find we're actually using
"${Value.Place}", because our data source object has a property named
Value, which in turn has a property named Place. To avoid confusion, we
choose to simply list "${Place}" in the above code snip.

Template only controls the structure of data representation. It doesn't
control the style directly. But everything you know about CSS also apply
to templates.


Apply the template

Now that the template has been created, we can apply it to a list, such
as a <ul>. To do so, first clear all items in the ul. Currently jQuery
Templates does not take care of that for you (unlike Silverlight
DataTemplate). Then find the template element, invoke the tmpl method,
pass the data source as the parameter, and append the result to the ul.

// Remove old data.

$('#TravelList').children().remove();

// Apply the jQuery template to the ul.

$('#travelTemplate').tmpl(items).appendTo('#TravelList');

Here the variable items is a collection of data source object, which is
returned from our WCF Data Services. We'll cover how to invoke WCF Data
Services from a HTML client in the next post.

For Silverlight developers, please note there's no ObservableCollection
in jQuery Templates as you can find in Silverlight. So if the source
collection is modified, you need to invoke the above two lines of code
again, to reapply the template.


Additional tweaks to the template

Sometimes you may want to perform additional tasks on the data. For
example, format a date. jQuery Templates allows you to invoke functions
in the templates. You can roughly think it acts as the same role as
Silverlight binding converter. In the above template, we have seen the
TextBox associated with the Time property invoke the formatDate
function:

<input type="text" class="DatePicker" value="${formatDate(Time)}"
readonly/>

function
formatDate(date) {

return $.datepicker.formatDate('yy-mm-dd',
date);

}

If a simple function is not sufficient, you can always iterate through
the generated DOM fields, and do anything you like. For example, to
associate a jQuery UI datepicker with the TextBox, we give the TextBox
in template a style class, and search for all generated TextBoxes with
this style class later:

$.each($('.DatePicker'),
function (index, item) {

$(item).datepicker({ onSelect: DateChanged, dateFormat:
'yy-mm-dd' });

});

Now let's see a screenshot of the result (Note it may be a bit different
from what you see in the current version of live demonstration. When
writing those blog posts, we're also refining our code and design, to
create a better coding guideline and user experience. The live
demonstration will be updated in the future):

Conclusion

This post introduced jQuery Templates, and how it helps to reduce efforts
when displaying structured data in a rich HTML application. It focused on client
side only. The next post will bring the client and the cloud together. We will
introduce how to accessing WCF Data Services from a rich HTML client.