At the Forge - Unobtrusive JavaScript
JavaScript has gone through a number of changes in the past few years. Implementations have become faster, more standardized and more stable. The development and growth of open-source JavaScript libraries, such as Prototype and Dojo, has helped mask many of the remaining differences between JavaScript implementations, such as with AJAX and event handling. The final change has occurred in the minds of developers (including myself), who now approach JavaScript as a serious application development language, rather than as a toy for highlighting images or doing simple effects.
Most JavaScript is executed not when it is initially read into a browser window, but rather when a particular event takes place. The easiest, and most common, way to assign event handlers is inside the HTML itself. For example, we can create a submit button for an HTML form as follows:
<form method="POST" action="/action">
<input type="submit" value="Submit the form" />
</form>
When a user clicks on this button, the browser submits the contents of the form to the URL specified in the form tag's action attribute, using the method specified in the method attribute. But, we can change this by adding an onclick attribute to the submit button:
<form method="POST" action="/action">
<input type="submit" value="Submit the form"
onclick="alert('hello!'); return false;" />
</form>
With the onclick handler in place, the button now opens a JavaScript alert box (saying “hello”). Moreover, because our event-handler definition returns false, the form will not be submitted.
Of course, we don't have to put our JavaScript literally in the event handler. We could define a function somewhere else—in the document's <head> or perhaps in an external JavaScript file altogether:
<form method="POST" action="/action">
<input type="submit" value="Submit the form"
onclick="do_something(); return false;" />
</form>
Now, none of this is new. But, there are problems associated with setting event handlers in “on___” attributes. For one, it becomes difficult to assign more than one handler to the same event on an object.
A second and more significant reason is that our HTML becomes full of JavaScript. Until a few years ago, it wasn't unusual for HTML to be mixed in with code and style information as well, but the growth of strictly separated MVC frameworks have removed most code from the HTML, and style information now is put in external CSS files.
A growing movement during the past few years has pushed for “unobtrusive JavaScript”. Proponents of unobtrusive JavaScript argue that by placing JavaScript in a separate file and by defining event handlers in a separate file, the code becomes easier to read and understand and is cached by the browser. By using JavaScript unobtrusively, we also have the opportunity to make our HTML pages degrade gracefully, continuing to work with browsers that don't support JavaScript.
This month, we look at unobtrusive JavaScript and the unobtrusive approach to defining functions and event handlers. We also examine the Lowpro library that works with the popular Prototype JavaScript library, allowing us to write JavaScript that is unobtrusive, clean and easy to read.
Above, I showed how to assign a piece of JavaScript (called “do_something”) to an event on a particular HTML element. A fuller version of this HTML form, as well as some more content and tags, is shown in Listing 1 (test.html). This file contains a simple hyperlink, as well as our form.
Listing 1. test.html, the Simplest Version
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Unobtrusive JavaScript</title>
</head>
<body>
<h1>Unobtrusive JavaScript</h1>
<p>A paragraph of text.</p>
<p>A <a href="http://www.nytimes.com" id="hyperlink">hyperlink</a>
to The New York Times.</p>
<form method="POST" action="/action">
<input type="text" name="text_field" id="text_field" />
<input type="submit" value="Submit the form" id="submit_button" />
</form>
</body>
</html>
I've already discussed how to handle an onclick event by setting the onclick attribute. However, there are at least two other methods for setting this event handler. One is to set the onclick attribute through JavaScript, treating onclick as a property of the DOM element associated with the hyperlink or button. Using Prototype's $() function, we can write:
$('hyperlink').onclick =
function() { alert('clicked!'); return false; }
Notice how the event handler is an anonymous function, similar to “lambda” in Ruby and Python or an anonymous subroutine in Perl. The event-handling function can take an optional argument, whose value will be an event object. For example:
$('hyperlink').onclick =
function(event) { alert(event); return false; }
With this alternate code in place, the alert (in Firefox, at least) indicates that the event was an “object MouseEvent”. This object, like all objects in JavaScript, then has a number of properties we can query. For example, the pageX and pageY properties indicate the X and Y coordinates of the mouse cursor when the event took place. We can see these by specifying the following:
$('hyperlink').onclick =
function(event) { alert(event.pageX + ", " +
event.pageY); return false; }
Each click on the link will give a slightly different result, depending on the coordinates of the mouse cursor at the time of the click.
Of course, we also can define non-anonymous functions as our event handlers:
function show_x_and_y(event) {
alert(event.pageX + ", " + event.pageY); return false;
}
$('hyperlink').onclick = show_x_and_y;
Notice that our assignment is to show_x_and_y (that is, the name of a function), rather than to show_x_and_y() (that is, the result of executing the function). This is a particularly useful technique if we want to assign the same function to handle multiple events.
We can handle a number of different events. For example, the onmouseover and onmouseout events let us execute a function based on when the mouse starts or stops pointing to a DOM element. Thus, we can do the following:
$('hyperlink').onmouseover =
function() { $('the_form').hide(); }
$('hyperlink').onmouseout =
function() { $('the_form').show(); }
When the mouse points to the hyperlink in test-2.html (Listing 2), the HTML form disappears. When the mouse moves away from the link, the form reappears. This might not be especially useful, but it does demonstrate the sorts of events (and event handlers) we can define.
Trending Topics
| You Need A Budget | Feb 10, 2012 |
| The Linux powered LAN Gaming House | Feb 08, 2012 |
| Creating a vDSO: the Colonel's Other Chicken | Feb 06, 2012 |
| Your CMS Is Not Your Web Site | Feb 01, 2012 |
| Casper, the Friendly (and Persistent) Ghost | Jan 31, 2012 |
| Razor-qt 0.4 - Qt based Desktop Environment | Jan 30, 2012 |
- Fun with ethtool
- Parallel Programming with NVIDIA CUDA
- 100% disappointed with the decision to go all digital.
- Readers' Choice Awards 2011
- Linux-Based X Terminals with XDMCP
- Validate an E-Mail Address with PHP, the Right Way
- You Need A Budget
- The Linux powered LAN Gaming House
- Why Python?
- Python for Android
- Employment Posters
23 min 23 sec ago - Sure the best distro is
1 hour 43 min ago - BeOS was the best
4 hours 27 min ago - I use Wireshark on a daily
8 hours 57 min ago - buena información
14 hours 4 min ago - One important "bucket" that I didn't note (désolé si qqun deja d
15 hours 5 min ago - Gnome3 is such a POS. No one
1 day 32 min ago - Gnome 3 is the biggest POS
1 day 43 min ago - I didn't knew this thing by
1 day 6 hours ago - Author's reply
1 day 10 hours ago






Comments
So interresting...
Thanks for this article. Clear and so usefull...