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.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- New Products
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- A Topic for Discussion - Open Source Feature-Richness?
- Drupal Is a Framework: Why Everyone Needs to Understand This
- One Hand Slapping
- Home, My Backup Data Center
- What's the tweeting protocol?
- RSS Feeds
- Trying to Tame the Tablet
- Readers' Choice Awards 2011
- Reply to comment | Linux Journal
5 hours 2 min ago - Reply to comment | Linux Journal
7 hours 35 min ago - Reply to comment | Linux Journal
8 hours 52 min ago - great post
9 hours 27 min ago - Google Docs
9 hours 49 min ago - Reply to comment | Linux Journal
14 hours 38 min ago - Reply to comment | Linux Journal
15 hours 24 min ago - Web Hosting IQ
16 hours 58 min ago - Thanks for taking the time to
18 hours 35 min ago - Linux is good
20 hours 33 min ago
Enter to Win an Adafruit Prototyping Pi Plate Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Prototyping Pi Plate Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- Next winner announced on 5-21-13!
Free Webinar: Linux Backup and Recovery
Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.
In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.




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