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.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
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
| Designing Electronics with Linux | May 22, 2013 |
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| 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 |
- Designing Electronics with Linux
- New Products
- Linux Systems Administrator
- Senior Perl Developer
- Technical Support Rep
- UX Designer
- Web & UI Developer (JavaScript & j Query)
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Dynamic DNS—an Object Lesson in Problem Solving
- Using Salt Stack and Vagrant for Drupal Development
- Reply to comment | Linux Journal
6 hours 56 min ago - Dynamic DNS
7 hours 30 min ago - Reply to comment | Linux Journal
8 hours 29 min ago - Reply to comment | Linux Journal
9 hours 19 min ago - Not free anymore
13 hours 21 min ago - Great
17 hours 8 min ago - Reply to comment | Linux Journal
17 hours 16 min ago - Understanding the Linux Kernel
19 hours 31 min ago - General
22 hours 1 min ago - Kernel Problem
1 day 8 hours ago
Enter to Win an Adafruit Pi Cobbler Breakout 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 Pi Cobbler Breakout 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
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Featured Jobs
| Linux Systems Administrator | Houston and Austin, Texas | Host Gator |
| Senior Perl Developer | Austin, Texas | Host Gator |
| Technical Support Rep | Houston and Austin, Texas | Host Gator |
| UX Designer | Austin, Texas | Host Gator |
| Web & UI Developer (JavaScript & j Query) | Austin, Texas | Host Gator |
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




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