0% found this document useful (0 votes)
39 views

HTML Client Side

This chapter discusses how to manipulate HTML elements on the client-side using JavaScript and jQuery. It covers selecting elements, modifying existing elements by updating attributes or styles, and generating new HTML elements. The roles of HTML, CSS, and JavaScript are defined, with HTML providing structure, CSS controlling appearance, and JavaScript enabling behavior. jQuery is introduced as a library that simplifies DOM manipulation across browsers. Techniques include selecting elements, hiding/showing content, and dynamically generating HTML on the client-side using templates.

Uploaded by

Francesco Donato
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views

HTML Client Side

This chapter discusses how to manipulate HTML elements on the client-side using JavaScript and jQuery. It covers selecting elements, modifying existing elements by updating attributes or styles, and generating new HTML elements. The roles of HTML, CSS, and JavaScript are defined, with HTML providing structure, CSS controlling appearance, and JavaScript enabling behavior. jQuery is introduced as a library that simplifies DOM manipulation across browsers. Techniques include selecting elements, hiding/showing content, and dynamically generating HTML on the client-side using templates.

Uploaded by

Francesco Donato
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 43

Chapter 7:

Manipulating
Client-Side
HTML
Introduction The Roles and
Responsibilities of Client-Side Languages

Structure, Appearance, and Behavior, Adding


Interactive Behavior to an Application I
Selecting and Manipulating Existing
HTML Elements - Selecting Elements, Using

Context, Using Data- Attributes, Modifying


Existing Elements, Showing and Hiding
Content, Updating Element Attributes I
Generating and Loading New HTML in a
Page - Generating HTML Dynamically with

JavaScript and Auery, Retrieving HTML


Fragments from the Server, Content Retrieval
Decisions in Mileage Stats, Using Templates to
Retrieve and Generate HTML, Anatomy of a
Auery Template, Server-Side Rendering and ini
ipru Tpmnintpc I RI immnrir I Mu-their

Introduction
Both hybrid and single-page interface (SPI)
web applications that do not perform fullpage post backs in order to change the
rendered user interface (Up must use clientside techniques for manipulating the
document object model (DOM). This DOM
manipulation could include updating the
content of the page, displaying new UI
elements, or loading entire pages in response
to user gestures and other events. The three
client-side technologies you can use when
implementing these techniques are HTML,
cascading style sheets (CSS) and JavaScript.
This chapter discusses how you can clearly
define the roles of HTML, CSS, and
JavaScript on the client to ensure that
developers and designers can work together
without affecting each other's code. You will
also see how to use JavaScript to manipulate
HTML effectively in the browser.
In this chapter you will learn

In this chapter you will learn:


The roles and responsibilities of HTML,
CSS, and JavaScript within a client
application.
How to use jQuery to select and
manipulate HTML elements.
How to use jQuery to generate new
HTML within the client.
- How to use jQuery Templates to
generate new HTML within the client.
How to choose the most appropriate
option when manipulating HTML.
Technologies discussed in this chapter are
HTML, CSS, and JavaScript.

The Roles and


Responsibilities of Client Side Languages
When building the client-side portion of a web
application, you generally use three
technologies that can be viewed as separate
development languages: HTML, CSS, and
JavaScript. You may not be accustomed to
thinking of these technologies as

development languages. However,


considering them in this way can help to
clarify the role that each one plays in your
application, and can help you keep their
responsibilities separate.
As with any development language, it is
possible to use these languages in a way that
makes the application harder to maintain and
extend. This can be avoided by taking
advantage of the strengths of each language,
and by keeping their responsibilities clear and
distinct.

Structure, Appearance,
and Behavior
There are three areas of responsibility within
client applications, and each client-side
language is associated with one of those
areas. The three areas are:

The structure of the UI. HTML is used to


define the logical structure of the UI.
Structure refers to the hierarchy of
objects that make up the UI, not the
visual appearance or layout of the UI.

Today, HTML is ideally used only for


the logical, non-visual structure.
The appearance of the Ul. This is the
responsibility of CSS, which applies
styling to elements and manages visual
layout (positioning and flow) for the UI.
CSS allows designers and developers to
change the layout, styling, and
appearance of the UI elements without
requiring changes to the structure
defined by the HTML,
The behavior of the UI. JavaScript is
responsible for the behavior of the
application. It is used to define or redefine how UI elements respond to
user interactions and gestures, as well
as other events not directly initiated by
the user.
HTML also has an additional responsibility
that might not be immediately obvious. It is
frequently used to transport the data that
the client requires from the server. For
example, when the Mileage Stats Reference
Implementation (Mileage Stats) renders a
page, the information about the vehicles is
stored as rnetadata in attributes within the
HTML markup. Using metadata in this way is
discussed in "Using Data- Attributes" later in

It is surprisingly easy to blur the lines of


responsibility among the client-side
languages. For example, you might be
tempted to use a CSS class to associate
semantic or structural meaning to an HTML
element. in fact, this approach was commonly
used in the past to identify elements in order
to attach some behavior.
An example of this approach would be to add
an attribute such as class="vehicleLink" to
relevant hyperlinks so that you can select
these elements in your JavaScript code.
However, using a CSS class in this way is
problematic because it muddles the
responsibilities of CSS as a language. In
particular, if you use a CSS class to specify
the style and the behavior of elements, your
designer might unintentionally break your
application by changing a class name or
relocating a CSS class to another element
when updating the layout and style of the
page.

Adding Interactive
Behavior to an

Application
When you have a simple web application, you
can rely on the web server to handle changes
to the HTML by posting back to the server so
that it can update the page, or by loading a
different page that contains the required
HTML. However, this approach limits the level
of interactivity in the application.
There are several ways that JavaScript code
can add interactivity to a page through
manipulation of the HTML structure and
content without requiring a full-page reload.
Some typical approaches are:

Using the existing page structure and


simply hiding and showing elements as
necessary. This is the simplest
approach and is appropriate in some
scenarios. For example, you might use
JavaScript code to change the CSS
properties that specify the visibility of
elements within the page as it is
loading, or in response to user actions.
Using JavaScript to modify, add, or
remove elements within the browser's
DOM. The code can also add, remove, or
update the attributes and style
classes applied to elements. For small

applications that do not require the


appearance, structure, and behavior to
change very much, this may be an
acceptable solution. For example, you
might want to add a new UI element to
the page, enable or disable controls in
the page, change the text displayed in
elements, or show a different image.
Using JavaScript to retrieve HTML
fragments from the server and add
them to the DOM. This is an ideal
approach when the server-generated
HTML fragments can be reused directly
within the client. The HTML fragments
may be generated dynamically on the
server to include data relevant to the
current state of the application, or may
be static content, perhaps read directly
from disk files.
. Using templates to generate HTML
fragments dynamically on the client,
and adding or replacing elements in
the DOM with the generated HTML.
This approach is ideal when there is a
lot of content to be generated on the
client. It can be used to combine HTML
in the template with data provided by
the server. This is the solution used in
Mileage Stats.

Using a JavaScript Library to Manipulate


the DOM
For a rich user experience, where your
application can change the U1 while avoiding
full page reloads, it is obviously necessary to
have a mechanism for manipulating the DOM.
JavaScript is the primary way to do this.
However, due to different DOM and JavaScript
implementations within different browsers,
using a JavaScript library to shield you from
cross-browser compatibility issues is the only
practical approach for anything more than very
simple interactions.
There are several libraries that do this very
well, but this chapter discusses only the
Ouery library. Mileage Stats uses the Ouery
library because it provides many powerful
methods for selecting and changing etements
in the DOM, modifying element attributes,
wrapping existing elements, and creating new
elements while remaining compatible with
almost all modern browsers.

Note:

For more information about jQuery, see


"Puery Home Page" in the 'Further
Reading" section of this chapter. For more
information about browser support for
jQuery, see "jQuery Browser Compatibility"
in the "Further Reading" section of this
chapter.

jQuery uses an element selection syntax that


is very similar to CSS, and extends it to
provide additional ways to select elements
within the HTML. This means that the same
syntax you use in style sheets to select
elements can be used to attach JavaScript
behaviors to elements. Once the elements
have been selected, the code can modify
them, remove them, or insert new elements
within them. Modifying these elements could
be as simple as adding or removing a CSS
style, or changing the contents of the element.
The remainder of this chapter focuses on how
you can select elements and modify them, and
how you can add new HTML elements to the
page rather than changing the behavior of
existing elements.

Selecting and
Manipulating Existing
HTML Elements
Many scenarios for interactive web applications
only require client-side languages such as
CSS and JavaScript to modify existing
elements. Modification usually involves
adding, removing, or updating the attributes
and style classes applied to elements. In
some cases, CSS alone may be capable of
performing the required changes, such as
changing the style of hyperiink elements as
the mouse pointer passes over them. In other
cases, JavaScript code is required to
manipulate the elements directly.
Before you can perform actions on elements,
you must specify how the CSS or JavaScript
will select them. You can select one or more
elements, as described in the following
section, and then use a range of techniques to
manipulate the elements. These techniques
are described in "Modifying Existing
Elements," later in this chapter.

Selecting Elements
There are several ways you can use selectors

within an application to select elements you


want to modify. Each approach has its own
benefits and drawbacks:
Using data- attributes. data- attributes
(pronounced data dash" attributes)
provide a simple and efficient way to
select elements based on the presence
and value of attributes whose name
starts with "data:. jOuery provides the
data method for working with dataattributes, as you will see in the next
section of this chapter. This is the
preferred approach for most element
selection scenarios.
Using the id attribute. This works
well when there is a single element in
the DOM with the specified value for its
id attribute. However, this approach
often causes jQuery to search the
entire DOM to find the element, which
can have significant impact on the
client-side performance of your
application. In addition, using the id as
a selector is not a valid approach when
you must support multiple elements on
the page that may have the same id
attribute values.
Using element name selectors. This
is a useful technique when you want to

apply an action to all elements of a


specific type (for example, all of the
<tr> elements in a table). However, it
can cause problems because it is easy
to select more elements than intended
if the element occurs elsewhere in the
page. It also means that changing the
type of elements in the HTML in the
future will require changes to the
JavaScript code.
Using class name selectors. This is a
useful technique for selecting multiple
elements across the element hierarchy,
but (as described in the introduction to
this chapter) it can cause confusion
between class names used for applying
CSS styles and class names used as
selectors to apply JavaScript behavior.
It can also lead to subtle bugs when the
JavaScript adds and removes classes on
elements; suddenly the class name you
use to find an element is no longer
there.
Using relative location. You can select
one or more elements by relative
position within the DOM with respect to
a known element. For example, you
might select all of the elements that are

the children of a target element. This


can be an efficient way to locate
elements because it is usually much
faster than searching from the root
element of the DOM. It can be
combined with the previous selection
methods. However, selectors that rely
on this approach are fragile because
they depend on the specific hierarchy
of the HTML structure.

'1 Note:
All of these selection methods run the risk
of impacting client-side performance. It is
important to ensure that you provide
additional context with the selectors to
prevent searching the entire DOM. See
"Using Context" below for more
information.

For more information on jQuery selectors, see


"jQuery Selectors" in the "Further Reading"
section of this chapter.
It is important to note that your HTML

structure becomes an unofficial contract


between the server and the client. The
JavaScript code will expect elements with
specific ids to exist as well as expecting the
presence of certain data- attributes. The more
assumptions that the JavaScript makes about
the HTML, the more fragile the application will
become.
Writing unit tests to verify that the HTML
provides the expected metadata can save
significant effort if changes to the HTML
structure are required at a later time.. For
more information on how the server can
provide the correct initial HTML to the client,
see "Providing HTML Structure" in Chapter 11,
"Server-Side Implementation."

Using Context
One of the ways to achieve maximum
performance when selecting elements is to
specify a context to search within. This
context allows searches based on a known
and referenced element. There are two ways
to provide this context. The Auenj method
can take a second parameter, a known
element, to scope the search through the
DOM. Alternatively, the find method of an

element can be used to obtain a collection of


all or specific child elements. Both techniques
are shown here.
JavaScript
If Example: select the
child // Both of the
following Um var
myLinkElements =$(1#dashl
var myLinkElementsByFind =
s(

Using Data- Attributes


HTML5 provides data- attributes as a
mechanism for applying metadata to
elements. It turns out that this metadata is
also useful when selecting elements. The
browser does not use data- attributes when
rendering the page. This means that they can
be used to select elements independently of
the element hierarchy and styling.
In addition, data- attributes can store other
arbitrary metadata, such as the state of a UI

element, because they are merely attributes


on the element. For example, the attribute
data-action="reminders" can represent
the action="reminders" name/value
pair.In Mileage Stats, data- attributes are
used to provide the client with useful
information. The client will make Ajax
requests to the server to load and save
data, so the client must know the URLs
corresponding to the endpoints for those
data requests. Rather than hard-coding the
URLs within the client-side script, the server
can provide the URLs in the HTML by using
data- attributes, and the code can extract
this value when it needs to make a request
to the server. This means that the code will
continue to work if the LiFiLs change, such
as when changing the routing in a ModelView-Controller (MVC) application or when
moving the application to a different virtual
directory on the server.
The following code shows the CSHTML code
that Mileage Stats uses to render the vehicle
list on the dashboard. Both the id attribute
and CSS class are set so that they can be used
for styling the vehicle list with CSS. There are
also two data- attributes that contain URL
metadata for use within the JavaScript that

controls the behavior of the vehicle list.


[ CS HTML

<1-- Contained in VehicleLis<div id="venicles" class="ardata-list-url="@Url.Acti(


data-sort-url="@Url.Acti(

</div>

HTML

<I-- result of VehicleList.1


<div id="vehicles" class="ardata-list-url="/Vehicle,
data-sort-url="/Vehicle,
</div>

"IL Note:
Only the first hyphen in the attribute name
is significant. Everything in the attribute
name after the first hyphen is treated as a
sinnple string value. For example, datalist-url="Nehicle/JsonList" is a dataattribute containing the metadata listurl="Nehicle/JsonList".

To select all of the elements that carry the


data-list-url attribute shown in the previous
HTML listing, you could use the following
JavaScript code.
JavaScript

/1 Example: select the demo


var myVehicleElement = myVeh:
JavaScript

If Example: get the value of


var myUrl = myVehicleElement
Because data- attributes are ideal for
selecting elements, and for getting or setting
data associated with those elements in the
DOM, you should use them wherever possible.
If your designer changes the layout and style
information in the HTML, your JavaScript
won't break. In addition, data- attributes
allow the server to easily provide the client
with useful data without the client having to
parse LI-specific HTML. Use data- attributes
wherever it is appropriate to specify metadata

in the server-generated HTML or with


JavaScript on the client.
Keep in mind that the HTML represents the
logical structure of the UI, not the visible layout
and style. The use of data- attributes provides
you with a mechanism for annotating the
structure and adding metadata without using
style class names or element identifiers.

Modifying Existing
Elements
After you select your target element or set of
elements, you can modify them as required.
The following sections provide some
examples of scenarios and solutions for
modifying existing elements within the HTML
structure of the page.

Showing and Hiding Content


When the user first navigates to your
application, the server will return the HTML for
the page. This HTML includes the locations
(LIFILs) for the resources such as images,
scripts, and HTML fragments that the browser
will download as secondary, requests in order

to create the complete page. However, there


will be a noticeable delay as the content and
scripts are downloaded, the HTML and CSS is
parsed, and any startup scripts run. While
usually short, this delay can affect the user
experience, especially if there are a large
number of secondary requests for scripts,
images, or other assets, or if the user is on a
slow Internet connection.
One solution is to include in the HTML sent
from the server a progress indicator that
shows that the application is loading. Then,
once the rest of the content is available, the
application can use JavaScript to change the
LI by hiding the progress indicator and
replacing it with the desired HTML (which was
also part of the server response, but hidden
using CSS styles). The code needs only to
change the CSS styles applied to the relevant
elements. This technique means that the user
perceives a reduced waiting time and better
responsiveness, even though there is no
actual increase in performance.

Note:

Many applications require JavaScript. One


approach to communicating this
requirement to the user is to include a
notice in the initial HTML that the site
requires JavaScript. The first action the
application script takes is to hide the
notice, so that it remains visible only when
the client does not support JavaScript. A
more common approach is to require that
the application run on a recent browser
and check that features such as JavaScript
are enabled. This is often easier for users,
who are immediately aware that the
application requires JavaScript or other
features, and it simplifies the work of
technical support teams who do not
encounter errors caused by the use of
older browsers.

Updating Element Attributes


Interactivity in the page can be implemented
using JavaScript code that runs in response to
user actions, or when events such as
completion of page load occur. Typically, the
HTML sent from the server will contain all of
the structure (the HTML element hierarchy)
required to render the page. Unless you

actually need to build all or part of the LI


dynamically on the client, having the initial
structure in place is much faster than creating
the same structure in the script each time.
However, you may need to modify the HTML
elements after the page has loaded in the
browser.
For example, the Mileage Stats main page
contains a header with links to the dashboard
and chart views (The HTML is shown here
with some content removed for clarity).
These hyperlinks must be updated when the
HTML

<I-- Rendered from Layout.c:


<div class="nav"
<span id="welcome"Welcome
[ <a href="/Dashboard"
1( <a href="/Chart/List"
</div
page loads to include in the UK any subfolder
name (if the application is installed on the
server in a subfolder of the default website).
If this is not done, the links will not work

correctly. When the page load is complete, the


following JavaScript runs in the browser to
update the href attributes of these hyperlink
elements to include the correct URL.
JavaScript
/f Contained in mstats.headel
adjustNavigation: function var
state = $.bbici.getSta-url =
this.element.di newUrlBase =
mstats.1
state.layout = idashboan
this.element.find('#dashl
.attrChref', $.parai
state .layout = 'charts'; this
. element . find( 'ttchar .attr(ihref
$.parar

The first part of this code uses the jQuery Back


Button and Query (BBQ) plug-in to create a
state object and get the actual base URL of the
page. This value is discovered on the server and
can be obtained from the
getRelativeEndpointUrl method of the global

mstats object defined in the JavaScript of the


page. Chapter 9, "Navigation," discusses in
more detail the BBB plug-in, the use of a state
object, and how this section of code works.
After the base URL has been established, the
code changes the name/value pair named
layout within the state object instance so
that it specifies the correct layout style
(dashboard or charts) for each hyper -link. It
then uses the find method to select the
appropriate hyperlink element based on the
value of its id attribute, and sets the value of
the href parameter to the correct URL. This
URL is a combination of the base URL of the
application and the relevant layout property
held in the state object instance.
Mileage Stats uses data- attributes both to
locate elements and to store data values in the
DiDIV. As another example, the
_bindNavigation method of the fill ups widget
(part of which is shown below) relies on the
presence of a data-action attribute to locate
navigation buttons. The method also uses the
data-action and data-fillup-id attributes to
determine which action to take and which fill up
to target.

JavaScr ipt
// Contained in mstats.fillul
bindNavigation: function
() var that = this;
this.element.delegate('D
if ($(this).dataCacthat. setOption(
event.preventDefi

Generating and Loading


New HTML in a Page
In the previous section, you saw how you can
select HTML elements and manipulate them.
This obviously requires existing elements to
work with. However, you wilt often need to
create new elements and content within the
existing HTML structure. There are several
ways to generate new HTML and modify the
existing HTML structure on the client. Typical
techniques, which are discussed in this
chapter, are:

Generating the HTML structure


dynamically using JavaScript and
Ouery
Retrieving HTML fragments from the
server and injecting them into the page
Using templates both to retrieve and to
generate the HTML structure to insert
into the page

Generating HTML
Dynamically with
JavaScript and Auery
When developing a hybrid or SPI application,
you often need to modify the existing page by
inserting into it fragments of new HTML. You
can, of course, remove elements from the page
as well, but it is usually easier to change the
CSS styles that control visibility.
Mileage Stats generates and inserts
fragments of HTML into its pages in several
places. For example, it uses JavaScript to add
new elements to the page structure as the
user navigates through the application. The
following code (it is part of the info pane
widget) creates the HTML structure that

displays a vehicle's details.

JavaScript

/1 Contained in rnstats.info-1
setupDetallsPane: function
I var elern = this.element,
options = this.optioi
if (!elem.find("#details.
elem.find("div:first
.append('<div id:
}
this.vehicleDetails = ell
1/ options for the w:
));
},
This code uses the find method to check if the
Details pane is already present in the
structure. If it does not exist, the code locates
the first div element within the current context
and uses the append method to insert a new
div element with id="details-pane" into the
page.
Generally, the amount of HTML generated with
script should be small. Script that creates

large amounts of HTML is difficult to read and


can easily create a structure that is invalid
because of syntax errors in the code. If you
need to generate a large amount of HTML,
you should reevaluate the design or consider
using one of the other methods described in
this section to retrieve or generate the HTML
you require.

Retrieving HTML
Fragments from the
Server
In some situations, it may make sense to
retrieve an HTML fragment from another
source (for example, a URL on the web
server) and inject it directly into the page,
perhaps after manipulating it, rather than
dynamically generating the content on the
client. For example, it may make sense to
reuse an HTML form generated on the server
and dynamically embed it in a web page,
rather than generating the entire form and its
contents with JavaScript. This approach can
simplify the client-side code by moving some
of the complexity to the server.

Typically, you will use Ajax methods, including


the load method of existing elements, to load
the new content asynchronously, directly into
the target element. An alternative is to retrieve
the new content in the background, perhaps in
a hidden element or as a string variable, and
then insert it into the page at the appropriate
location using JavaScript and jQuery. The final
version of Mileage Stats does not retrieve
HTML fragments from the server. However, this
technique was investigated during
development.

Content Retrieval Decisions in


Mileage Stats
Now that we've arrived at the topic of using
HTML fragments and templates, let's take a
moment to talk about the design process our
team followed while looking for the optimal
solution. Since we knew that we wanted to
support both a full-page reload and a hybrid
experience for most of the features in Mileage
Stats, we realized that we needed to generate
HTML on the server as well as manipulate the
HTML on the client. Our goal was to reuse as
much HTML as possible, following the Don't
Repeat Yourself (DRY) principle.

Unfortunately, this was more difficult than


expected. The markup necessary for the fullpage reload scenarios was rendered as large
chunks of HTML combined with data, while
the markup needed for the SPI scenarios was
focused and generally independent of the
data.
Our strategy was to break the server-side
HTML views into small, granular, partial views
(small fragments of the UI). The client-side
code could request the partial views using an
Ajax call, and use the result to replace a small
portion of the rendered UI. When we needed to
reload a full page, the server could assemble
the requested page from the granular partial
views and send the complete page to the client.
In this way, none of the HTML would be
duplicated. We envisioned the final result as a
set of composable blocks that could be used to
build the UI structure for both scenarios.
Once we began implementing this strategy,
we found that the code quickly became very
complicated. Both the controller and the view
code became intertwined and confusing.
Many conditional blocks were required to
share the numerous partial views between the
I'

server-side and client-side code.

Back on the client side, widgets were given


URLs to request the partial views they needed.
This had a number of drawbacks. First, it
increased the surface area of the server by
exposing the additional endpoints the widgets
needed to request the necessary HTML
fragments. Second, the number of Ajax calls
made by the client increased because each
widget needed to retrieve both the required
data and the partial views. The increase in calls
also created additional failure points and made
the error handling code for the widgets more
complex.
As an alternative, we had considered using a
client-side templating engine such as the
jQuery Templates plug-in. That would have
involved using the server-generated HTML for
the full-page reload experience, and creating a
second set of client HTML templates for use
only on the client. We initially decided against
this approach because we thought that we
would be duplicating all of the HTML code that
was generated on the server.
However, after working through the difficulties
of manaaina the small partial views, we
of managing the small partial views, we
decided that it would actually be easier to
maintain the application if we used two

methods to generate the HTIV1Lone on


the server side and one on the client side
so we chose to rewrite the application using
the jaluery Template plug-in. Ensuring that
the HTML that was duplicated in both the
server and client code remained
synchronized was a bit of a challenge.
However, we were able to mitigate this issue
through developer diligence when changing
HTML or HTML templates, through test
automation, and through either paired
programming or code reviews (a practice we
already followed to mitigate other risks).
There were also several cases where we
intentionally generated different HTML on
the client than we generated on the server in
order to accommodate the different Ells for
the JavaScript-enabled experience and the
non-JavaScript experience. These situations
were handled on a case-by-case basis and
communicated to the entire warm

Using Templates to
Retrieve and Generate

HTML
As mentioned in the previous section, another
option for generating HTML is to use HTML

templates. The idea behind templates is fairly


simple: given a set of data and a template
with placeholders for the data, you merge the
HTML in the template with the data to
generate an HTML fragment that can be
inserted into the DOM. Templates provide the
opportunity for generating HTML dynamically
without the need for a lot of JavaScript code.
This approach also allows you to generate
the HTML using standard design tools, and to
insert the placeholders for the data
afterwards.
There are a number of HTML templating
engines that can be used. As you saw,
Mileage Slats uses the jQuery Templates
plug-in because it was a natural fit after the
team decided to use jQuery and jQuery Ul.

Anatomy of a Auery Template


jQuery templates consist of HTML and
placeholders for data. By convention, jQuery
templates usually reside in a script element
that has a unique value for its id attribute, and

a type attribute set to type="textix-jquerytmpl". The template script element can be


located within any HTML element in the
structure: it does not have to be located where
the result will be displayed.
The id attribute allows the Auery template
plug-in to locate the template. The type
attribute is the Internet media type (also
known as the MIME Type or Content Type),
and the value shown above is unknown to
browsers. When the browser parses the
HTML, it will not parse the content of any
section with the unknown type, which is the
desired result.
The following example shows part of the
template used in Mileage Stats to generate the
Statistics panel located on the Dashboard
screen. The
expression is a placeholder
within the template that the jQuery Template
plug-in uses to render a JavaScript value or
expression when the data is applied to the
template. The generated HTML fragment will
contain several values, including the value of the
AverageFuelEfficiency property of the data
applied to the template. Only the section
containing the first of these placeholders is

shown in this listing.


JavaScript
1/ Contained in _TemplateFlei
<script id="fleet-statistics.
ch1>Sumrnary Statistics </h1: <div
class="statistic mile. $Ostats.makeMPGDispli
class="units">mpg</spal
</script>
The template in this example runs other
JavaScript code to create a string
representing the value that is inserted into
the placeholder. It calls the
mstats.makeMPGDisplay method, which
formats the AverageFuelEfficiency value of
the original data to ensure that it displays
correctly.
The example below shows the
_applyTemplate method, which uses the
previous template to generate an HTML
fragment, and places this fragment in the
element with the id of statistics-content.

When the user runs the application, the


Java Script

// Contained in mstats.stati
applyTemplate: function (da'
var options = this.optioi
Stemplate = $(option:
I

this.element.find(141stat:
.html(StemplateAmpli
}
following HTML is generated:
For more information on the jQuery Template
HEAL

// Run-time HTML
<div id="statistics-content":
<h1>Summary Statistics </h1:
<div class="statistic mile.
class="units">mpvispan>.
</div>
plug-in and authoring templates, see "jQuery

Templates" in the "Further Reading" section.

Server-Side Rendering and Auery


Templates
jQuery Templates are a powerful feature of
the jQuery library. Developers can use their
chosen server-side rendering engine to
dynamically create or inject values into jQuery
templates on the server instead of, or in
addition to, having the templates combined
with data on the client. This dynamic serverside rendering of the template provides many
additional options when developing your
application.
In one respect, the approach of populating a
template on the server instead of on the client
resembles the approach described earlier of
retrieving HTML fragments that contain the
final HTML for display. There is no
requirement to merge the data and template
on the client. However, there is no reason why
you cannot combine both approaches. Your
server code could populate some of the
dynamic content in the template, but leave
other placeholders in the content that will be
populated by merging the template with data
on the client.
Mileage Stats uses server-side code to

generate jQuery templates in several places.


For example, templates were used in cases
where the URLs for buttons and links in the
rendered page depended on where the
application was deployed. For example, if the
application is deployed in a subfolder instead
of in the root of the website on the server, the
L.JRL must include the folder name.
Mileage Stats jQuery templates are in the
Views\Shared folder of the application and use
the n_TenriplateNAME.cshtnnIn naming
convention so that they will be processed by
the Razor rendering engine. This allows the
server-side code to inject values into the
template HTML before it is sent to the client.
For example, the @UrI.Action view helper
method can render the correct URL of the add
action of the vehicle controller, whether or not
the application is deployed in a subfolder on the
server, as shown here.

CS HTML
<-- Contained in _TemplateVel
<script id="mstats-add-vehic:
<div class="framed command

<div>
<a data-action="vehicli
href="ftrl.Actionri
<Idly>
</div>
</script>
The _TemplateVehicleList template shown
above is processed by the Razor rendering
engine using the @Html.Partial view helper
method in _Layout.cshtmli as shown below.
CSHTML
<I-- Contained in Layout.cs1
@Html.Partial("_TemplateVehii
The HTML fragment shown below is the
rendered _TemplateVehicleList template
when the web application is deployed to the
root web site on the server.

HTML
<I-- Rendered to the browser
<script id="mstats-add-vehic.
<div class="framed command

<div>
<a data-action="vehicL
href="/vehicle/add":
</div>
</div>
</script>
If, instead, the web application is deployed to
the MileageStats folder in the root website, the
rendered HTML will be the code shown below.
You can see the folder name in the value of the
href attribute.
HTML

<I-- Rendered to the browser


<script id="mstats-add-vehic:
<div class="framed command
<div>
<a data-action="vehicli
href="/MileageStats,
</div>
</div>
</script>
Now the template can be used within the client
application, and will provide the correct URLs

for the current deployment on the web


server.

S u m m a r y
There are three key technologies that work
together in the browser to enable interactive
applications: HTML, CSS, and JavaScript.
HTML specifies the structure of the elements
available within the L11, 055 controls the
styling and positioning of those elements, and
JavaScript allows the element s to respond to
user gestures and other events such as timers
and animations.
Within an application, there is often a
requirement to manipulate the HTML that
generates the page the user sees, and there
are a number of options for selecting the
HTML elements whose appearance or behavior
you wish to change. Of these, the use of
relative position provides the best
performance, while using data- attributes can
significantly help with both the selection of
HTML elements and the transmission of
metadata to the client code. Data- attributes
also help to ensure separation between the
HTML and the metadata the application
requires.

Finally, you saw how you can create new


HTML structure within a page by using
JavaScript and jQuery, by retrieving fragments
of HTML from the server, or by using jQuery
Templates on the client to combine data
retrieved from the server with HTML included
in the templates.

Further Reading
jQuery Home Page: http://jquery.com
jQuery Browser Compatibility
http://docs.jduery.com/Browser_Compatibility
jQuery Selectors:
http://api.jquery.com/categoryiselectors
jQuery Templates:
http://api.jduery.comicategoryipluginsitempl
aces
For more information on how the server can
provide the correct initial HTML to the client,
see "Providing HTML Structure" in Chapter 11,
"Server-Side Implementation."
For more detail on the BBQ plug-in and the use
of a state object, see Chapter 9, 'Navigation."

You might also like