Introduction
This article will present a model for development of pure client-side applications where all processing logic is implemented using jQuery and information
is presented to the user directly on the client side using JavaScript View Engines. In this application model, there is no server-side code except the Web Services
that provide data. The only communication between the client side and the server-side code is done using AJAX calls that provide data and all the processing
is done in the client-side code. This model is most suitable for JavaScript plugins but can be applied in pure JavaScript applications.
JavaScript view engines are a new and interesting concept in web development. Classic web application development uses the same logic when pages are shown
to the user - content that should be shown in the client’s browser is generated on the server side, and HTML, CSS, JavaScript, and other content is sent to the
browser and presented to the user. If we take a look at the standard Model-View-Controller model, applications take data from some persistent storage (Model),
perform some processing (Controller), and pass data to some rendering component (View) where the model is rendered. Regardless of what technology is used on the
server-side (ASP.NET, J2EE, PHP), this logic is more or less applied in all application frameworks.
The logic behind this approach is an assumption that we
have powerful and scalable servers, farms, clusters, or clouds on the server-side that can handle any number of requests, and that the client browser is weak and
should not have a lot of processing. However, knowing that client computers have become more powerful and that browsers are getting faster, you might consider moving
some logic to the browser. If you are using jQuery, processing logic is encapsulated in jQuery plug-ins that perform actions in the browser. JavaScript view engines
introduce a new concept in web application development. Using JavaScript view engines, you can generate the view directly in the browser instead of on the server.
If JavaScript view engines are used, server-side components (Controllers) send JavaScript objects represented in JSON notation (these JSON objects are Models),
and these objects are rendered in the browser (in this case, the browser is a View component). The communication between the client-side code and server-side code
is performed via AJAX calls. There are a lot of JavaScript view engines such as jQuery
template, Pure, noTemplate,
jsTemplate, Populate that can be used to transform
JSON to HTML – in this article, we will use the loadJSON plug-in.
The general usage of the client-side view engines will be shown in the following example. I will assume that the following JavaScript is sent from the server
and used as a model on the client side:
var data = {
"Name":"Emkay Entertainments",
"Address":"Nobel House, Regent Centre",
"Contact":"Phone"
}
This JavaScript object can be directly generated from the server-side, returned via a Web Service call, or loaded via some AJAX call.
To show this object in the browser, we would need to have some kind of template – the following template can be used with
the loadJSON plug-in:
<div id="data">
<h1 id="Name"></h1>
<label for="Address">Address:</label>
<span id="Address"></span>
<label for="Contact">Contact by:</label>
<span id="Contact"></span>
</div>
In this template, we have classes that match properties on the JavaScript object by name. The jQuery loadJSON plug-in matches the JavaScript object with classes, ID, and names of the HTML elements and loads the JSON object into
the template using the following call in the JavaScript code:
("#data").loadJSON(data);
The result of this call is a template populated with information from the JavaScript object. An example is shown below:
<div id="data">
<h1 id="Name">Emkay Entertainments</h1>
<label for="Address">Address:</label>
<span id="Address">Nobel House, Regent Centre</span>
<label for="Contact">Contact by:</label>
<span id="Contact">Phone</span>
</div>
More details about the loadJSON plug-in can be obtained on the plug-in site. I have described how JavaScript
view engines can be used with ASP.NET MVC applications
in the “Using
JavaScript View Engines in ASP.NET MVC” article, where I describe
how you can generate a list, display details, populate a form used for editing, or generate a hierarchical report. If you want to see how JavaScript view engines
can be used, you might take a look at this article. In this article, I will present a new concept of usage of JavaScript engines – integration with third party applications
directly in the browser.
Background
JavaScript view engines enable you to create fully functional client-side applications without server-side code that generates HTML. If you are using
JavaScript view engines and AJAX, you can make queries to Web Services that return
a response that can be handled on the client side. If you have some
public Web Service that provides information via JSON format, you can create pure JavaScript code that calls this service and uses JavaScript view engines
to generate content directly in the browser window. The concept of using Web Services from client-side code is shown in the following figure:
Although everything is done on the client side, you will need to have a web server where the page will be placed and loaded in the browser using a standard HTTP
GET or POST request. The web server should return an initial HTML of the web page. Once the page is loaded, the application
that works with the JavaScript view engines can take all the necessary information from the Web Services. Using AJAX calls, you can send requests back
to the server or even to third party services, take a response, and show it in the browser window using JavaScript view engines. If AJAX calls are sent
to the original server, a standard JSON object will be returned; however, if AJAX calls are sent to other servers,
the JSONP protocol should be used (you can find more information
about JSON/JSONP AJAX calls below).
As you can see, once the page is loaded in the browser, AJAX is the basic communication protocol between the client and server.
In this article, we will use Bing Maps as a public service, and we will see how to create a pure JavaScript application
that calls Bing Maps using AJAX calls, take JSON response, and show it in the page. For converting JSON to HTML, we will use the loadJSON plug-in but any other view
engine can be used instead. If we use the MVC model to describe the application structure, in this type of application, we have the following components:
- Model - The model represents the information structure taken from the remote service. In this example, the model is a JSON object retrieved
from the Bing Maps Web Service. The information in the model objects will be shown to the user in the browser.
- Controller – In this application model, the controller is also moved to the client-side. The Controller has functionalities implemented
in JavaScript using the jQuery library that reacts on client events, takes model data from the services, and sends them to the view engine.
- View is the JavaScript view engine that generates the HTML based on the JSON model. In this example, the loadJSON plug-in is used as the view engine.
As you can see, this is the application model for a fat-client application where both the controller and view are implemented as JavaScript components.
In this code example, we will create a JavaScript application with the following features:
- It will enable the user to search locations by keyword - the results will be shown in the list and on the map.
- The user will be able to position any result in the center of the map.
- The user will be able to adjust the zoom level of the map.
Bing Maps REST API
Bing Maps provide a set of web services you can use to search addresses, generate maps, display routes between two points, etc. The only thing you need
is a Bing Maps key you can get on the Microsoft Bing Maps site (it is free). Once you have a key, you can
send various queries to the Bing Maps server. Bing Maps provides both SOAP and REST Web Services. In this example, we will use
the REST web services provided by Bing Maps because they can be easily integrated
with JavaScript code (SOAP Web Services are better for server-side calls). Examples of some requests you can send
to the Bing Maps REST Web Services are:
- If you want to find objects on the address or use a keyword, you can open the following
URL: http://dev.virtualearth.net/REST/v1/Locations/US/WA/98052/
Redmond/1 Microsoft Way?o=xml&key=BingMapsKey.
- You can also get the map of an area using the following call: http://dev.virtualearth.net/REST/v1/Imagery/Map/Road/47.619048,-122.35384/15?mapSize=500,500&pp=47.620495,-122.34931;21;AA&pp=47.619385,-122.351485;;AB&pp=47.616295,-122.3556;22&mapVersion=v1&key=BingMapsKey.
As mentioned above, the only thing you need is a Bing Maps key
that should be placed instead of BingMapsKey
in the examples shown above.
I will not describe the details of the Bing Maps REST API but you can find more information at this link
where you can also find more examples.
Instead of Bing Maps, you can use any other public service - the only prerequisite is that the service supports the JSONP protocol.
Calling Services using AJAX Calls
Once you know what you can get from the external Web Service (Bing Maps in this case), you will need to make AJAX calls to this service. jQuery provides
an easy way to send AJAX requests to the server-side page using the following code:
$.ajax({
url: "<<URL>>",
success: function (data) { }
});
Instead of <<URL>>, you should place the real address of the web page or Web Service you want to call, and if the request succeeds, a success function fill be called.
This works fine when you make AJAX calls to the same server where your page is loaded, however, if the URL is on third party sites, the browser
blocks the call. In most browsers, cross-site AJAX calls are not allowed and the result of the AJAX call will be an empty string.
However, there is a way to perform cross-site AJAX calls if you are using the JSONP protocol. An example of the jQuery call to the URL using JSONP is shown in the following listing:
$.ajax({
url: "<<URL>>",
dataType: "jsonp",
jsonp: "jsonp",
success: function (data) { }
});
If the server-side application accepts JSONP calls, a success functional will be called even if this is a cross-side call. You can find more information
about creating JSONP requests on the jQuery site. The Bing Maps service allows the JSONP protocol so it can be used in this example.
Loading the Response into the Page
Once you perform an AJAX call and get a JSON object from the server-side, you can load it into the template using a JavaScript view engine (loadJSON plug-in
in this example). As described above, if you have a template that matches the JSON structure, you can load it easily into the page using the following code:
$("#template").loadJSON(data);
This code should be placed in the success handler of the AJAX call. Once the JSON object is loaded into the page, you can attach the event handlers
to the elements and perform additional AJAX calls to get new information if needed – without any server-side code.
In this section, basic concepts of the usage of JavaScript view engines with third party public services is described. In the following section, an example
of how you can create a simple Bing Maps application with pure JavaScript logic is shown.
Using the Code
This example shows how you can use the loadJSON plug-in to generate a simple Bing Maps interface. Note that this is just a case study that shows how you can use
JavaScript view engines to integrate third party data – if you need a Bing Maps interface, it would be better to use some existing component such as Bing Maps
JavaScript control or some jQuery Bing Maps plug-in.
In this example, I will create a simple application that enables you to search for location based on query, display results in the HTML list and map, and enable
some simple interaction with map (setting the center of the map, zoom-in, and zoom-out). The displayed results are shown in the following figure:
In the list and map are displayed all locations that match the search condition; the coordinates of the locations are placed
in the links, and when you click on the link, the selected location will be placed in the center. You can see a live version of this application
on the loadJSON demo page.
The following sections describe the model, view, and controller code used to implement this example.
Model
As described above, the model is a JSON object returned by the Bing Maps service. In the following listing is shown JSON code returned by the
Bing Maps service when a query that returns the location is executed:
{
"brandLogoUri" : "http://dev.virtualearth.net/Branding/logo_powered_by.png",
"resourceSets" : [ {
"resources" : [ {
"name" : "Regent Street, London NW10 5",
"point" : { "coordinates" : [ 51.528781000000002,-0.216583] }
},
{ "name" : "Regent Street, London W1S 2",
"point" : { "coordinates" : [ 51.511755000000001,-0.139491] }
},
{ "name" : "Regent Street, London W4 3",
"point" : { "coordinates" : [ 51.488630999999998,-0.28262900000000002] }
}
]
} ]
}
Within the resources array is placed a list of location objects that contains
the name of the location and the point where the location is placed.
Point
contains a coordinates object that has latitude and longitude information. This information structure will be loaded using the view engine.
View
The view is responsible for the user interface and if you are using JavaScript view engines, this is pure static HTML. In this example, we need a form where
the user
can enter an address and run a search. This is the HTML code shown in the following listing:
<div id="searchDiv">
<label for="searchBox">Search: </label>
<input id="searchBox" /><button id="search">Search</button>
</div>
When the user performs a search, JSON results returned from the Bing Maps service will be loaded into the template. The structure HTML template matches
the structure of the JSON object. The HTML template used in this example is shown in the listing below:
<div id="data" style="display:none">
<img src="#" id="brandLogoUri" />
<div id="copyright"></div>
<div id="slider"></div>
<img src="#" id="searchmap" />
<ol class="resourceSets">
<li class="resources">
<span class="name"></span>
<span class="point">
(<a href="#" class="coordinates">
<span rel="0"></span>,<span rel="1"></span>
</a>)
</span>
</li>
</ol>
<a href="BingMapsSearch.html">New search</a>
</div>
In the HTML structure can be found empty elements with classes brandLogoUrl
, name
, and
the coordinates where JSON properties will
be loaded. Elements with classes resourceSet
and resource
are placed just to match the structure of the JSON object.
In the element with the class “point
” are placed two elements with
rel
attributes 0
and 1
where the first
and second element of the coordinates array will be placed. In this structure can be loaded elements from the JSON object that represents a model.
The JSON object will be loaded into the template using the following JavaScript call:
$("#data").ladJSON(data);
The variable data
will be returned as a response from the Bing Maps
AJAX call.
Controller
The controller is implemented on the client side as a set of jQuery event handlers. In this application,
the controller has the following functions:
- Finding a location that matches the search query and displaying results in the list and map
- Setting some of the locations returned in the center of the map
- Zooming in and out map
Finding locations based on query
When the user enters an address in the searchBox
text box and presses the search button,
an AJAX call is sent to Bing Maps with a query and an authentication key.
When the request is successfully completed, the result of the AJAX call is loaded into the template,
the search form is hidden, and the template is shown. In addition,
the center of the map is set and the map is shown. The code for this action is shown in the following listing:
$("#search").click( function () {
$.ajax({
url: "http://dev.virtualearth.net/REST/v1/Locations",
dataType: "jsonp",
data: {
key: key,
q: $("#searchBox").val()
},
jsonp: "jsonp",
success: function (data) {
$("#searchDiv").hide();
$("#data").loadJSON(data).fadeIn("slow");
center = $($(".point .coordinates")[0]).text();
showMap();
}
});
});
In the AJAX call is sent value entered in the searchBox
text input so Bing Maps service can return locations that match this search query.
The most important processing is placed in the success handler. When request is successfully completed search box is hidden, JSON results are loaded into
the template and shown in the page, coordinates of the first point are found and set as a center of the map, and function for showing a map is called (this function
fill be described later). Variable center
is globally defined variable that is used in all functions described in this section.
Setting the position of the map
In this example, when the user clicks on any link containing coordinates, the selected location is placed as
the center of the map. In the links with class "coordinates
"
are loaded coordinates of each location, so when the user clicks on any of these links,
the text will be set as the center of the map as shown in the following listing:
$("a.coordinates").live("click", function(event){
center = $(this).text();
showMap();
});
Once the center variable is set, the map is refreshed using the showMap()
method.
The variable center
is the same
as that used in the previous function.
Adjusting the zoom level of the image
In this example application, the user is able to change the zoom level of the map. Changing the zoom level enables using a jQuery UI slider where
the user
can change the value of the zoom level between 1 and 19. The code for setting
the jQuery UI slide is shown in the following listing:
$( "#slider" ).slider({
value:12,
min: 1,
max: 19,
step: 1,
slide: function( event, ui ) {
zoom = ui.value;
showMap();
}
});
The slider is placed in the empty DIV
with an id "slider
" and it is initialized as a
jQuery UI slider control with value ranging
from 1
to 19
(these are set as zoom levels). When a slider value is changed in the slide event handler,
the zoom
value is set to
the current value of the slider and a map is shown again. The variable zoom
is defined as a global variable.
Utility function for showing the map
The last part of the jQuery code is a utility function that shows a map. The
function is shown in the following listing:
function showMap(){
var pushpins = "";
var i = 1;
$("a.coordinates").each(function(){
pushpins += "&pp="+$(this).text()+";;"+(i++); } );
$("#searchmap").attr("src",
"http://dev.virtualearth.net/REST/V1/Imagery/Map/road/"+center+"/"+
zoom+"?mapSize=600,400&ml=TrafficFlow&mapVersion=v1&key="+
key+pushpins);
}
This function takes all coordinates from the links and formats pushpins that will be placed on the map.
The global variables center
and zoom
are set
in the previous functions. A map is shown when the src
attribute of the image is set to the URL that returns
the image with pushpins from the Bing Maps server.
Conclusion
I have shown in this article how you can use a JavaScript view engine to create pure JavaScript components that use third party services (Bing Maps, in this example).
View engines enable you to move all processing to the client side and this is perfect if you are creating UI components such as
jQuery plug-ins that should generate HTML based on JSON data. View engines enable you to easily handle generating HTML and to focus on the logic of your plug-in or client-side code.
Shown here are the basic concepts of creating fat-client JavaScript applications or plug-ins using
jQuery, making cross-site calls to external sites,
and generating a view on the client side using the loadJSON JavaScript view engine. This new application model is different from a classic server-side model
where everything is generated on the server. Knowing that client computers get more powerful with more faster browsers that can handle
a lot of JavaScript
processing, it is reasonable to consider moving some processing to the client side if this would improve
the performances of the overall application.
Although it is shown here how the Bing Maps service can be integrated in your site, this is not a guideline for using Bing Maps. If you want to integrate
Bing Maps into your site, you should use something like the Bing Maps AJAX Control, Version 7.0. You will use
the code described in this article if you want to create your own plug-ins
or maybe if you need a simpler or customized look for the Bing Maps control.
To see how this works, you can either download the code example or go to the
live demo page.