1. Why jQuery?
jQuery is ideal because it can create impressive
animations and interactions. jQuery is simple to understand and easy to use, which
means the learning curve is small, while the possibilities are (almost) infinite.
Javascript and Best Practices
Javascript has long been the subject of many heated debates about whether it is
possible to use it while still adhering to best practices regarding accessibility
and standards compliance.
The answer to this question is still unresolved, however, the emergence of Javascript
frameworks like jQuery has provided the necessary tools to create beautiful websites
without having to worry (as much) about accessibility issues.
Obviously there are cases where a Javascript solution is not the best option. The
rule of thumb here is: use DOM scripting to enhance functionality,
not create it.
Unobtrusive DOM Scripting
While the term “DOM scripting” really just refers to the use of scripts (in this
case, Javascripts) to access the Document Object Model, it has widely become accepted
as a way of describing what should really be called “unobtrusive DOM scripting”—basically,
the art of adding Javascript to your page in such a way that if there were NO Javascript,
the page would still work (or at least degrade gracefully). In the website world,
our DOM scripting is done using Javascript.
The Bottom Line: Accessible, Degradable Content
The aim of any web producer, designer or developer is to create content that is
accessible to the widest range of audience. However, this has to be carefully balanced
with design, interactivity and beauty. Using the theories set out in this article,
designers, developers and web producers will have the knowledge and understanding
to use jQuery for DOM scripting in an accessible and degradable way; maintaining
content that is beautiful, functional AND accessible.
2. Unobtrusive DOM Scripting?
In an ideal world, websites would have dynamic functionality AND effects that degrade
well. What does this mean? It would mean finding a way to include, say, a snazzy
Javascript Web 2.0 animated sliding news ticker widget in a web page, while still
ensuring that it fails gracefully if a visitor’s browser can’t (or won’t) run Javascripts.
The theory behind this technique is quite simple: the ultimate aim is to use Javascript
for non-invasive, “behavioural” elements of the page. Javascript is used to add
or enhance interactivity and effects. The primary rules for DOM scripting follow.
Rule #1: Separate Javascript Functionality
Separate Javascript functionality into a “behavioural layer,” so that it is separate
from and independent of (X)HTML and CSS. (X)HTML is the markup, CSS the presentation
and Javascript the behavioural layer. This means storing ALL Javascript code in
external script files and building pages that do not rely on Javascript to be
usable.
For a demonstration, check out the following code snippets:
Bad
markup:
Never include Javascript events as inline attributes. This practice should be completely
wiped from your mind.
1 |
<a onclick="doSomething()"
href="#">Click!</a> |
Good
markup:
All Javascript behaviours should be included in external script files and linked
to the document with a <script> tag in the head of the page. So, the anchor
tag would appear like this:
1 |
<a href="backuplink.html"
class="doSomething">Click!</a> |
And the Javascript inside the myscript.js file would contain something like this:
3 |
$('a.doSomething').click(function(){ |
5 |
alert('You did something, woo hoo!'); |
The .click() method in jQuery
allows us to easily attach a click event to the result(s) of our selector. So the
code will select all of the <a> tags of class “doSomething” and attach a click
event that will call the function. In practice, this
In Rule #2 there is a further demonstration of how a similar end can be achieved
without inline Javascript code.
Rule #2: NEVER Depend on Javascript
To be truly unobtrusive, a developer should never rely on Javascript support to
deliver content or information. It’s fine to use Javascript to enhance the information,
make it prettier, or more interactive—but never assume the user’s browser will have
Javascript enabled. This rule of thumb can in fact be applied to any third-party
technology, such as Flash or Java. If it’s not built into every web browser (and
always enabled), then be sure that the page is still completely accessible and usable
without it.
Bad
markup:
The following snippet shows Javascript that might be used to display a “Good morning”
(or “afternoon”) message on a site, depending on the time of day. (Obviously this
is a rudimentary example and would in fact probably be achieved in some server-side
scripting language).
1 |
<script
language="javascript"> |
3 |
if(now.getHours() < 12) |
4 |
document.write('Good
Morning!'); |
6 |
document.write('Good
Afternoon!'); |
This inline script is bad because if the target browser has Javascript disabled,
NOTHING will be rendered, leaving a gap in the page. This is NOT graceful degradation.
The non-Javascript user is missing out on our welcome message.
Good
markup:
A semantically correct and accessible way to implement this would require much simpler
and more readable (X)HTML, like:
1 |
<p title="Good Day Message">Good Morning!</p> |
By including the “title” attribute, this paragraph can be selected in jQuery using
a selector (selectors
are explained later in this article) like the one in the following Javascript
snippet:
2 |
if(now.getHours() >= 12) |
4 |
var
goodDay = $('p[title="Good
Day Message"]'); |
5 |
goodDay.text('Good Afternoon!'); |
The beauty here is that all the Javascript lives in an external script file and
the page is rendered as standard (X)HTML, which means that if the Javascript isn’t
run, the page is still 100% semantically pure (X)HTML—no Javascript cruft. The only
problem would be that in the afternoon, the page would still say “Good morning.”
However, this can be seen as an acceptable degradation.
Rule #3: Semantic and Accessible Markup Comes First
It is very important that the (X)HTML markup is semantically structured. (While
it is outside the scope of this article to explain why, see the links below for
further reading on semantic markup.) The general rule here is that if the page’s
markup is semantically structured, it should follow that it is also accessible to
a wide range of devices. This is not always true, though, but it is a good rule
of thumb to get one started.
Semantic markup is important to unobtrusive DOM scripting because it shapes the
path the developer will take to create the DOM scripted effect. The FIRST step in
building any jQuery-enhanced widget into a page is to write the markup and make
sure that the markup is semantic. Once this is achieved, the developer can then
use jQuery to interact with the semantically correct markup (leaving an (X)HTML
document that is clean and readable, and separating the behavioural layer).
Terrible
markup:
The following snippet shows a typical list of items and descriptions in a typical
(and terribly UNsemantic) way.
03 |
<td onclick="doSomething();">First Option</td> |
04 |
<td>First
option description</td> |
07 |
<td onclick="doSomething();">Second Option</td> |
08 |
<td>Second
option description</td> |
Bad markup:
The following snippet shows a typical list of items and descriptions in a more semantic
way. However, the inline Javascript is far from perfect.
2 |
<dt onclick="doSomething();">First Option</dt> |
3 |
<dd>First option description</dd> |
4 |
<dt onclick="doSomething();">Second Option</dt> |
5 |
<dd>Second option description</dd> |
Good markup:
This snippet shows how the above list should be marked up. Any
interaction with Javascript would be attached at DOM load using jQuery, effectively
removing all behavioural markup from the rendered (X)HTML.
3 |
<dd>First option description</dd> |
5 |
<dd>Second option description</dd> |
The <id> of “OptionList” will enable us to target this particular definition
list in jQuery using a selector—more
on this later.
3. Understanding jQuery for Unobtrusive DOM Scripting
This section will explore three priceless tips and tricks for using jQuery to implement
best practices and accessible effects.
Understanding Selectors: the Backbone of jQuery
The first step to unobtrusive DOM scripting (at least in jQuery and Prototype) is
using selectors. Selectors can (amazingly) select an element out of the DOM tree
so that it can be manipulated in some way.
If you’re familiar with CSS then you’ll understand selectors in jQuery; they’re
almost the same thing and use almost the same syntax. jQuery provides a special
utility function to select elements. It is called $.
A set of very simple examples of jQuery selectors:
So, as the Javascript comments suggest:
- $(document);The first option will apply the jQuery library methods to a DOM object (in this
case, the document object).
- $(‘#mydiv’)The second option will select every <div> that has the <id> attribute
set to “mydiv”.
- $(‘p.first’)The third option will select all of the <p> tags with the class of “first”.
- $(‘p[title="Hello"]‘)This option will select from the page all <p> tags that have a title of “Hello”.
Techniques like this enable the use of much more semantically correct (X)HTML markup,
while still facilitating the DOM scripting required to create complex interactions.
- $(‘p[title^="H"]‘)This enables the selection of all of the <p> tags on the page that have a
title that starts with the letter H.
These examples barely scratch the surface.
Almost anything you can do in CSS3 will work in jQuery, plus many more complicated
selectors. The complete list of selectors is well documented on the
jQuery Selectors documentation page. If you’re feeling super-geeky, you
could also read the CSS3 selector specification
from the W3C.
Get ready.
$(document).ready()
Traditionally Javascript events were attached to a document using an “onload” attribute
in the <body> tag of the page. Forget this practice. Wipe it from your mind.
jQuery provides us with a special utility on the document object, called “ready”,
allowing us to execute code ONLY after the DOM has completely finished loading.
This is the key to unobtrusive DOM scripting, as it allows us to completely separate
our Javascript code from our markup. Using $(document).ready(), we
can queue up a series of events and have them execute after the DOM is initialized.
This means that we can create entire effects for our pages without changing the
markup for the elements in question.
Hello World! Why $(document).ready() is SO cool
To demonstrate the beauty of this functionality, let’s recreate the standard introduction
to Javascript: a “Hello World” alert box.
The following markup shows how we might have run a “Hello World” alert without jQuery:
Bad markup:
1 |
<script
language="javascript"> |
Good markup:
Using this functionality in jQuery is simple. The following code snippet demonstrates
how we might call the age-old “Hello World” alert box after our document has loaded.
The true beauty of this markup is that it lives in an external Javascript file.
There is NO impact on the (X)HTML page.
1 |
$(document).ready(function() |
How it works
The $(document).ready() function takes a function as its argument. (In this case,
an anonymous function is created inline—a technique that is used throughout the
jQuery documentation.) The function passed to $(document).ready() is called after
the DOM has finished loading and executes the code inside the function, in this
case, calling the alert.
Dynamic CSS Rule Creation
One problem with many DOM scripting effects is that they often require us to hide
elements of the document from view. This hiding is usually achieved through CSS.
However, this is less than desirable. If a user’s browser does not support Javascript
(or has Javascript disabled), yet does support CSS, then the elements that
we hide in CSS will never be visible, since our Javascript interactions will not
have run.
The solution to this comes in the form of a plugin for jQuery called
cssRule, which allows us to use Javascript to easily add CSS rules to the
style sheet of the document. This means we can hide elements of the page using CSS—however
the CSS is ONLY executed IF Javascript is running.
Bad markup:
02 |
<h2>This
is a heading</h2> |
03 |
<p class="hide-me-first"> |
04 |
This is some information about the heading. |
Assuming that a paragraph with the class of “hide-me-first” is going to first be
hidden by CSS and then be displayed by a Javascript after some future user interaction,
if the Javascript never runs the content will never be visible.
Good markup:
02 |
<h2>This
is a heading</h2> |
03 |
<p class="hide-me-first"> |
04 |
This is some information about the heading. |
08 |
$(document).ready(function{ |
09 |
jQuery.cssRule("p.hide-me-first",
"display", "none"); |
Using a $(document).ready() Javascript here to hide the paragraph element means
that if Javascript is disabled, the paragraphs won’t ever be hidden—so the content
is still accessible. This is the key reason for runtime, Javascript-based, dynamic
CSS rule creation.
4. Conclusion
jQuery is an extremely powerful library that provides all the tools necessary to
create beautiful interactions and animations in web pages, while empowering the
developer to do so in an accessible and degradable manner.
This article has covered:
- Why unobtrusive DOM scripting is so important for accessibility,
- Why jQuery is the natural choice to implement unobtrusive DOM scripting effects,
- How jQuery selectors work,
- How to implement unobtrusive CSS rules in jQuery.
5. Further Reading
Further Reading: jQuery and JavaScript Practices
- jQuery Web Site: How
jQuery Works and Tutorials
John Resig + Other Contributors
One of jQuery’s true strengths is the documentation provided by John Resig and his
team.
51 Best jQuery Tutorials and Examples
Easy As Pie: Unobtrusive JavaScript
- Seven
Rules of Unobtrusive JavaScript
- Learning jQuery
- Visual jQuery
jQuery Tutorials For Designers
- jQuery For DesignersjQuery for Designers: learn how easy it is to apply web interaction using jQuery.
- 15 Days Of jQueryjQuery tutorials and example code that takes you from zero to hero in no time flat.
15 Resources To Get You Started With jQuery From Scratch
The Seven Rules Of Pragmatic Progressive Enhancement
- The Behaviour Layer SlidesJeremy Keith
Great slide notes giving a quick rundown on unobtrusive Javascripting.
- A List Apart:
Behavioral Separation
Jeremy Keith
A more in-depth explanation of the idea of separating Javascript into an unobtrusive
“behavioural” layer.
- Unobtrusive JavaScript with
jQuery
Simon Willison
A great set of slides about using jQuery unobtrusively. Also, finishes with a wonderful
summary of jQuery methods and usage.
Further Reading: Semantic Markup
- Wikipedia: Definition of SemanticsIt’s worth understanding the idea of semantics in general prior to trying to wrap
one’s head around the concept of semantic markup.
- Who cares about
semantic markup?
Dave Shea
Dave Shea explores the benefits of semantic markup and
- Standards don’t
necessarily have anything to do with being semantically correct
Jason Kottke
Kottke discusses the differences between standards compliance and semantic markup.
- CSS3 selector specificationW3C
The complete specification for CSS3 selectors (most of which work perfectly in jQuery
selectors also). This is great reading for anyone who likes to keep up to date with
best practices and standards compliance.