A number of people have
contacted me recently about Ajax [
1] -- a catchy name -- coined to
provide an umbrella term for a particular group of technologies
used to build web applications. The use of the word comes from
Jesse James Garrett in a recent blog [
2], and describes a class of internet
applications written using JavaScript in a browser. By using
JavaScript these apps have full access to the DOM, and as a
consequence are able to make all sorts of changes to the page that
the user is interacting with, without having to go back to the
server.
When the application
does need to go back to the server --
to deliver some data and get a response -- the idea is to keep the
DOM intact so that the user has a smooth experience. This means
that all communication with the server needs to take place outside
of the normal HTML form mechanism, since this would obviously
replace the current page.
Ajax addressed this, with what it calls 'asynchronous-JavaScript'
-- retrieve only the data you need, and then directly manipulate
the DOM to get the effect you want. 'Asynchronous-JavaScript'
accounts for the first few letters of the name, with the remainder
being the obligatory 'X' for XML (although XML is not really key to
this technology, and many of the applications that are often cited
as Ajax-apps don't use XML as the data medium).
Buzzing
The response to Ajax has been pretty positive. In fact the only
negatives have been either to suggest a change of name or to moan a
little that "I've been doing this for years, why hasn't anyone
noticed me?" (I won't put any links to those sort of articles,
since they are a little embarassing -- after all,
everyone
has been doing this for years!)
Anyway, despite a couple of sour-pusses, the software community is
almost universally excited, and the blog wires have glowed over the
last few months with descriptions of Google Maps, GMail, and so
on.
Just about everyone who has asked me about Ajax has expected me to
be disappointed. Surely, they say, this makes the case for XForms
weaker? But my answer is the exact opposite -- XForms and
standards-based web applications are in every way superior to the
techniques described as Ajax, since the whole
raison
d'être of XForms and XHTML 2 is to address the very problems
that Ajax-like techniques suffer from.
That may come across as a little bold...so perhaps I should
explain.
From Workaround to Feature
We've all been using HTML mark-up for years now, and the language
hasn't changed much in that time. As a consequence, the increasing
demand for more complex web-pages has meant that the balance in our
documents has shifted increasingly from vanilla mark-up to 'the
workaround'.
Whether it's providing tooltips, dynamic/repeating data sections,
or small portions of our page that change without having to request
a new document, we've generally had to dive into script. But the
shift from mark-up to script has meant that the mark-up language
itself has been relegated to a mere carrier for programs.
Unfortunately this means that no-one gains -- it's annoying for the
programmer to have to produce ever more convoluted spaghetti
JavaScript to meet the demands of their audience, but it's also
annoying for the non-programmer, who probably only wants a tooltip.
And its particularly annoying for those who want to use documents
on the web for more ambitious applications to find that most of the
important stuff in a document is hidden away in script.
All is not lost, however, since this collection of 'workarounds'
provides a rich source of real-life patterns that appear for
authors and programmers, time and again. They may be workarounds,
but they are much-needed ones.
The aim of the new generation of languages like XForms and XHTML 2
is to take these 'common patterns' and turn them into mark-up. Just
like the HTML elements
<a>
and
<form>
pack an enormous amount of functionality
into deceptively simple tags, so too can new declarative mark-up
capture patterns that have emerged 'in the wild'.
(Note that this is the opposite of so-called folksonomies, where
popular practice that occurs in the wild is left it the wild, and
codification is regarded as a dirty word.)
The XML HTTP Request Object
Let's take the much talked about XML HTTP Request Object
(XMLHttpRequest). If you are not familiar with it, it was
originally part of Microsoft's XML parser, and allows you to send
and receive data outside of the normal HTML form processing. Since
it's a handy feature to have in a client, other browsers have
followed suit and it's now becoming the 'standard' way to
communicate with servers without messing up your page. It's a
corner-stone of Ajax. (A good summary with examples is on Jim Ley's
jibbering.com site [
3].)
But...we need to be clear that we're using XMLHttpRequest to get
round a weakness in HTML forms. The problem we have is that even if
you know that a server is about to give you some data, and the
server knows it's about to give you some data, there's no
way to tell your
form that -- instead your page will be
wiped out and replaced with whatever the server sends back.
Of course, constant round-tripping doesn't make it completely
impossible to produce applications, and a lot of books and airline
tickets are bought every day without the facility to get 'just the
data'. But we all know it would reduce network traffic and create a
smoother user experience if we could just send a list of books or
seats, rather than a whole new page.
Over the years applications such as Microsoft's
Outlook Web
Access (OWA), have had to step around the HTML form to get
just the data they need. But, whilst OWA considerably predates
GMail, until the advent of XMLHttpRequest, the techniques used were
quite difficult to manage. (Google Suggest is often cited as a good
example of an Ajax-app, but interestingly merges old and new
techniques; XMLHttpRequest is used to obtain a piece of JavaScript
from a server, and this script contains a call to a client-side
function, but using server-provided parameters. It's one of the
techniques you might have used in the past with a hidden
frame.)
So as many have said on their blogs, XMLHttpRequest is not a newly
devised technique, but rather a generally accepted replacement for
a very old technique. But ultimately that technique is a workaround
since the
real problem is that HTML forms will always
replace the current page.
Beyond HTML Forms
Whilst XMLHttpRequest gives us a way to get data to and from the
server without losing our document, we've unfortunately thrown the
baby out with the bath-water; whatever the weaknesses of HTML
forms, you have to acknowledge that they are pretty simple to use.
Here's an abbreviated version of Google's search form (note that
the mark-up is HTML, not XML):
<form action=/search name=f>
<input type=hidden name=hl value=en>
<input maxLength=256 size=55 name=q value="">
<input type=submit value="Google Search" name=btnG>
</form>
As you can see, the simple problem with HTML forms is that we don't
say anything about where the data should go when we've received it
from the server. The assumption in HTML of old is that we are just
doing a kind of 'super-navigation', and no matter what we send to
the server, it will only ever give us back a new web-page. (To put
it a different way, you could say that
<a>
and
<form>
are pretty much the same thing.)
To see how this problem is resolved, let's code the same Google
search in XForms:
<xf:submission id="sub-search"
action="http://www.google.com/complete/search?hl=en"
method="get" separator="&"
replace="all"
/>
<xf:input ref="q">
<xf:label>Query:</xf:label>
</xf:input>
<xf:submit submission="sub-search">
<xf:label>Google Search</xf:label>
</xf:submit>
Although it will do exactly the same -- right down to replacing the
current page -- it's a little different to the HTML mark-up. But
the changes in structure have given us some major benefits, from
accessible labels on our form controls, to the possibility of many
different submissions for the same data.
But what it has also given us is the possibility of solving our
data update problem. The
replace
attribute is actually
optional in XForms, but I showed it in the previous mark-up so that
you can compare it to this:
<xf:submission id="sub-search"
action="http://www.google.com/complete/search?hl=en"
method="get" separator="&"
replace="instance"
/>
In this example the data returned from the server will just replace
the instance that was sent, and our page will remain completely
intact. (The
replace
attribute can take the values
all
,
instance
, or
none
.)
I won't show the full equivalent using XMLHttpRequest since it's
pretty large, but I'll give a flavour of it. (Jim Ley's page --
referenced earlier -- shows how to search Google with
XMLHttpRequest.)
The Script Version
First we need to create an XMLHttpRequest object, but we need to do
it in such a way that it will work on both Mozilla and IE:
var req;
function loadXMLDoc(url) {
// native XMLHttpRequest object
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.onreadystatechange = readyStateChange;
req.open("GET", url, true);
req.send(null);
// IE/Windows ActiveX version
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.onreadystatechange = readyStateChange;
req.open("GET", url, true);
req.send();
}
}
}
When a document is loaded via this function, the
readyStateChange()
method is invoked:
function readyStateChange() {
// '4' means document "loaded"
if (req.readyState == 4) {
// 200 means "OK"
if (req.status == 200) {
// do something here
} else {
// error processing here
}
}
}
From a
programming point of view, I guess you could say
that there isn't a lot wrong with this, but then from a programming
point of view there wasn't a lot wrong with Z80 or 6502 assembly
languages -- I just wouldn't want to go back to them!
But the most important issue is that we have lost the very thing
that was responsible for HTML's success -- the use of simple,
clear, declarative mark-up, in which we simply state our intent,
without having to write a program to do it for us. After all, the
web took off because authors only had to master
<a>
in order to enter the exciting new world of
'hypertext' -- but XMLHttpRequest raises the bar again, and takes
us right back into the heart of geek-world.
Beyond XMLHttpRequest
But in keeping with the principle that I outlined above -- that
XForms and XHTML 2 try to provide mark-up for commonly existing
design patterns -- let's see if there are any other patterns that
XMLHttpRequest has thrown up.
You will have noticed in the earlier script that we had tests for
success and failure:
if (req.status == 200) {
// do something here
} else {
// error processing here
}
XForms provides the same functionality through the use of events --
on success do this, on failure do that. This is far more powerful,
since it hides the protocol-specific aspects of this code ("200"
may be 'success' for HTTP, but it isn't 'success' when saving data
to the hard-drive or sending an email).
XForms uses declarative mark-up to express those events, which
again dramatically reduces coding:
<xf:action ev:observer="sub-search" ev:event="xforms-submit-error">
<xf:message level="modal">
Submission failed
</xf:message>
</xf:action>
But there's lots, lots more in the
submission
part of
XForms:
-
- it can provide full XML Schema validation before submitting the
data;
-
- there is built in support for numerous types of serialisation,
such as
multipart/related
;
-
- abstract methods are used so the code is independent of
protocol. For example, since
put
means the same thing
whether the target URL begins http:
or
file:
, a form with relative paths will run unchanged
on a local machine or a web server;
-
- it's extensible -- in formsPlayer 2.0 we have used the
submission
element to read and write from an ADO
database, allowing programmers to convert forms from using the web
to using a local database by doing nothing more than changing a
single target URL. (Try doing that with XMLHttpRequest!)
-
The
submission
part of XForms is in fact so powerful
that it will eventually form a separate specification, for use in
other languages.
From Patterns to Mark-up
And there are plenty more patterns out there that were crying out
to be turned into mark-up, and which are now incorporated into
XForms and XHTML 2. Do you remember the days when if we wanted a
tooltip that contained mark-up -- perhaps an image, or bold text --
we had to use a carefully placed
<div>
, a CSS
display: none;
, a
mouseover
event handler
and a timer? Nowadays the programmer with better things to do than
work with spaghetti-JavaScript just uses the XForms
<hint>
element, and for free they get platform
independence (and therefore accessibility), as well as the ability
to insert any mark-up.
And what about the days when we had to write code to open up a
text-to-speech engine, and then invoke the various methods on the
object to get it to speak its mind? Nowadays who wouldn't just use
a CSS property on their XForms'
message
s?
Bad Slacks
And do you remember...I'm sorry, this one always makes me
laugh...do you remember how we used to write lots of JavaScript to
recalculate the shopping-cart when a new item was added? I know
it's hard to believe -- it's like looking at old photos of us all
wearing flares. Anyway, thank God for straight trousers and the
XForms dependency-engine.
But enough of the good old days, the days of assembly language, C
and JavaScript...let's stick with the new.
Do Try This at Home
To round all of this off, we'll take a look at Google Suggest, and
we'll use XForms to implement it. I'll walk through the demo in a
separate blog [
4] so that this
one doesn't get too cluttered -- and hopefully by disecting this
simple but useful application, we can show how declarative mark-up
scores over scripting.
[1] Will AJAX help Google clean up?,
c|net,
http://news.com.com/Will+AJAX+help+Google+clean+up/2100-1032_3-5621010.html
[2] Ajax: A New Approach to Web Applications,
Jesse James Garrett, Adaptive Path blog,
http://www.adaptivepath.com/publications/essays/archives/000385.php
[3] Using the XML HTTP Request object,
http://jibbering.com/2002/4/httprequest.html
[4] "Google Suggest" Using XForms,
http://internet-apps.blogspot.com/2005/04/google-suggest-using-xforms.html
Tags:
xforms |
xbl |
webapps |
ajax |
javascript