SitePoint Sponsor
Article
Painless JavaScript Using Prototype
Handling Forms
The Form and Field objects provide a
number of simple but convenient functions for working with forms and
input fields, as well as code that supports Prototype's AJAX implementation.
The Form Object
Generally, methods of the Form object take either an ID or an object reference to an element:
// disables the form making all elements read only
Form.disable(form)
// enables a form again
Form.enable(form)
// clears values from all form elements
Form.reset(form)
// returns an array of all form fields in the form
Form.getElements(form)
// focuses on the first form field
Form.focusFirstElement(form)
The Field Object
The Field object deals with individual form elements,
and its methods typically take an ID or an object reference to the
element in a similar way to the Form object:
// clears the field, will accept any number of arguments
Field.clear(field)
// returns true if all given fields have a value
Field.clear(field, anotherField)
// gives focus to the field
Field.focus(field)
// selects any text in the field
Field.select(field)
Form Serialisation
In Prototype terms, serializing a form means reading all the form's elements and turning them into a URL-encoded string (nearly) identical to the one that would be sent if you submitted the form. For example, consider this form:
<form id="search" action="search.php" method="post">
<input type="text" name="query" value="thing" />
<select name="field">
<option value="artistname">Artist Name</option>
<option value="title" selected="selected">Title</option>
</select>
<input type="submit" name="submit" value="Search" />
</form>
// query=thing&field=title&submit=Search
Form.serialize($("search"))
Notice that Form.serialize cleverly smoothes over the
differences between the ways in which different form elements are
accessed, so that inputs, selects, checkboxes and radio buttons are
handled properly. Form.serialize is useful for several tasks, but comes into its own when we're working with AJAX, as we'll see shortly.
Form.serialize exhibits some strange behaviour that's worth mentioning here. You'll remember that I said the URL-encoded string that Form.serialize
produces is nearly identical to the one that would be sent if you
submitted the form. Well, it's "nearly identical" because
Form.serialize doesn't deal with submit button or image inputs
properly. It includes all submit buttons in the string, regardless of
whether or not they've been pressed, and completely ignores image and
button inputs. As long as you're aware of this, you can code around it.
Form Observers
Form.Observer and Form.Element.Observer
allow you to watch a form (or, in the latter case, a single form
element) and trigger callbacks when the data changes. There are
actually two flavours of each observer that check for value changes.
The first is a periodic observer, which works like this:
new Form.Observer($("myform"), 1, myCallBackFunction);
new Form.Element.Observer($("myfield"), 1, myCallBackFunction);
These observers check every second whether or not the data has changed and, if it has, will call myCallBackFunction.
The second type of observer is event-based and will only perform the check when change or click events are produced for the elements. You can use it like this:
new Form.EventObserver($("myform"), myCallBackFunction);
new Form.Element.EventObserver($("myfield", myCallbackFunction);
If all the fields in the form you're observing support an event handler, this is a much more efficient way to observe the form. However, if you want to watch for changes in elements that don't support these events, use the periodic observers.
Working the DOM
Prototype has 4 objects (Element, Insertion, Observer, and Position)
that allow various forms of DOM manipulation and smooth over many of
the browser differences that make dealing with the DOM so
screen-smashingly infuriating. Instead of throwing your computer out
the window, have a look through this section.
The Element Object
The Element object works in the way you've probably come to expect by this point: most of Element's methods simply take an ID or an object reference to the element you want to manipulate. Here's a peek at some of the most useful methods:
// Hides an element
Element.hide(element)
// Shows an element
Element.show(element)
// Adds a CSS class to the element
Element.addClassName(element, "cssClassName")
// Removes a CSS class from the element
Element.removeClassName(element, "cssClassName")
// Returns true if element has the CSS class
Element.hasClassName(element, "cssClassName")
// {width: 394, height: 20}
Element.getDimensions(element)
// replaces the innerHTML of element with newHtml
Element.update(element, newHtml)
See the full list at Sergio Pereira's site.
The Insertion Object
I know what you're thinking: this sounds a bit weird, right? Well, the Insertion object adds chunks of HTML in and around an element. There are 4 types of insertion: Before, After, Top and Bottom. Here's how you'd add some HTML before an element with the ID "myelement":
new Insertion.Before("myelement", "<p>I'm before!</p>");
This diagram shows where each type of Insertion will drop your HTML content in relation to the given element.

The Position Object
The Position object offers a load of methods that can
tell you about a given location on the screen, and provide information
about that location relative to other elements, in a cross-browser
compatible way. This should take much of the fiddliness out of writing
animations, effects and drag-and-drop code. Have a look at the Position reference for more details.
Get your Web 2.0 On
"Finally!" you're thinking, "He's got on to what we really want to know about." Yes, I've left it to the end to get into Prototype's AJAX helpers, because they're built on top of all the other stuff we've been going through, and it helps to understand Prototype's form serialization, observers and insertions when we talk about AJAX.
AJAX, in case you've been buried in a very deep hole for the past couple of years, refers to using the browser's XMLHttpRequest
object (or equivalent) to communicate with the server without reloading
the page. Prototype smoothes over most of the detail, but it's still
good to get a bit of background on XMLHttpRequest, which you'll find in this article by Cameron Adams.
So, now you're all pumped to get some Web 2.0 action, let's look in to a really simple AJAX request:
new Ajax.Request("hello.php", {
onSuccess : function(resp) {
alert("The response from the server is: " + resp.responseText);
},
onFailure : function(resp) {
alert("Oops, there's been an error.");
},
parameters : "name=Fred"
});
The Ajax.Request constructor takes a URL and an options object. In this case, we're sending a parameter (name) to hello.php,
and alerting its response (or alerting an error if it doesn't work).
It's worth taking the time to get familiar with what options are
available; here's an overview of the options, along with their defaults:

Prototype adds a custom HTTP header to all its AJAX requests so that your server application can detect that it's an AJAX call, rather than a normal call. The header is:
X-Requested-With: XMLHttpRequest
Here's an example PHP function used to detect an AJAX call:
function isAjax() {
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
$_SERVER ['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
}
Using this approach, you can write AJAX applications that work even if the user is using an old browser or has JavaScript disabled, but that's a whole other article...
Using Form.serialize to Pass Data to Ajax.Request
As we've seen above, the parameters option is used to pass a URL-encoded string of variables. If the data you need to send is set by a form, as it is with most AJAX applications, you can simply use Form.serialize to generate a URL-encoded string from all of your form fields and pass that into the parameters option like so:
function addComment(e) {
// submit the form using Ajax
new Ajax.Request("comment.php", {
parameters : Form.serialize(this),
onSuccess : updateComment
});
Event.stop(e);
}
Event.observe($("commentform"), "submit", addComment, false);
Writing AJAX Event Handlers
In the example above, onSuccess and onFailure are two examples of AJAX event handlers. Event handler functions given in the options object of an Ajax.Request call are given one argument, which is the XMLHttpRequest object for that AJAX call. I normally call this argument response or resp. You can use this argument to get the response from the server like so:
function successHandler(resp, jsonObj) {
// returns the response from the server as raw text
resp.responseText
// returns the response as an XML document that you can navigate with the DOM
resp.responseXML
// alert some property of the returned JSON
alert(jsonObj.name);
}
Remember, though, that resp is just the XMLHttpRequest object, so all of those properties are available.
You can send data as JSON from your server by adding the JSON data to the X-JSON response header. This will then automatically be evaluated by Prototype, and sent as the second argument.
The Ajax.Updater and Ajax.PeriodicalUpdater
Many AJAX operations simply involve updating some HTML on your page with HTML returned from the server. The Ajax.Updater object wraps Ajax.Request and simplifies this common use case for us. Here's a simple example:
new Ajax.Updater("mydiv", "hello.php", {
parameters : "name=Fred",
onFailure : function(resp) {
alert("Oops, there's been an error.");
}
});
The above snippet would simply replace the contents of the element
whose ID was "mydiv" with whatever content was returned from the
server. Ajax.PeriodicalUpdater is similar, but makes the Ajax call repeatedly at an interval that you set:
new Ajax.PeriodicalUpdater("mydiv", "hello.php", {
// initial number of seconds interval between calls
frequency : 1,
decay : 2
});
The decay option allows you to give your server a bit of a break if it's returning a lot of identical responses. Essentially, every time PeriodicalUpdater
makes a request, it compares the results with what the server returned
last time. If the values are the same, it multiplies the interval by
the decay value. So, for the above example, it would make the next
request two seconds later, then four seconds later, and so on, until it
received a different result from the server. At that point, the
interval would be reset to one second.
AJAX with Responders
AJAX responders allow you to register global event handlers that are triggered for each and every AJAX request that happens on the page. They're very useful for managing applications with large amounts of AJAX activity. For instance, you can use them to show a standard loading animation whenever an AJAX request is happening:
Ajax.Responders.register({
onCreate : showLoader,
onComplete : hideLoader
});
If you are looking for some working examples of AJAX with Prototype, try this article.
Where to Next?
As we've seen through this article, Prototype not only is useful on its own, but provides an excellent starting point for writing other, more specialized libraries. That's exactly what a growing number of people have been doing.
Script.aculo.us and Moo.fx
Thomas Fuchs' script.aculo.us is getting a lot of attention at the moment for its whiz-bang effects and clever UI widgets. It was originally part of the core Prototype library, but soon grew out of control and broke free of its parent.
Using Prototype as a basis, script.aculo.us specialises in providing a rich user experience through animated effects, simple to use drag and drop functionality, and powerful UI components. There's a nice Wiki on the site, with a rapidly growing store of quality documentation to help you get started, and examples pages to get your creative juices flowing. As script.aculo.us is getting rather large in file size, it's been split into several files, so your users won't have to download the whole library just so you can use a few slide effects. However, even the individual files are pretty bulky.
If you're after some simple effects, I'd really recommend Moo.fx. It's only 3k in size, and gives you some toggling slide and fade effects that, often, are all that's required in a simple AJAX application. It's also a great starting point if you want to write your own effects. Have a look at the code to see a great example of programming using Prototype's Object.extend to provide simple inheritance. Valerio is obviously very focused on keeping his script file sizes down, so he even has a 'lite' version of Prototype (chopped to around 10k), and a lean version of Ajax.Request, which I find myself using more often than the full Prototype library. It's definitely worth a look.
Behaviour
Behaviour is a great addition to your DOM scripting toolkit that allows you to use CSS selectors to add behaviour to your documents. Here's a sample of what it allows you to do:
Behaviour.register({
"#comment_form form" : function(el) {
// catch form submission and complete with XHR if possible
el.onsubmit = function() {
Form.disable(this);
new Ajax.Request(this.action, {
method: this.method,
postBody: Form.serialize(this),
onComplete: updateComments});
return false;
};
}
});
Read more about this over at the Behaviour site. It's now possible to achieve a similar type of thing using the brand new $$ function discussed earlier, so this may eventually become redundant.
jQuery
jQuery is a compact little library that plays well with Prototype and creates a superhero version of the $
function that can take XPath and CSS 3 selectors. It couples that
capability with some extremely clever method chaining approach that
makes for very concise code. Watch out for this one.
Wrap up
Prototype is a powerful piece of kit when it comes to adding some DOM scripted spice to your web applications. Unfortunately, its capabilities and tools have grown at a much faster rate than its documentation! We've managed to cover every corner of Prototype in this article, but not every method. I hope, though, that you now know where to go to get the extra information you need.
If you want to know more try Ronnie Roller's prototypedoc.com, a resource that keeps up with the growing body of Prototype documentation. Have fun!
» Page 1 2Rate This Article
- 1
Poor - 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Great
Recent Comments
Comment
Almost all of these libraries that try to "change the way javascript works" (or make it "suck less") seem to be approaching the situation all wrong. Prototype provides some useful helper functions, but it really fails to exploit javascript's unique strengths.
Javascript is a functional language.
Javascript gains encapsulation in the form of closures.
Javascript uses prototypal inheritance.
These things (among others...) make javascript completely different from traditional programming models, and I'm baffled as to why everyone tries to make it something that it's not. Turning javascript into a half-assed Java or a half-assed Ruby is pure idiocy. Javascript works extremely well for the tasks it's used for (mostly web apps) when used properly, and a solid understanding of the things mentioned previously are going to do you a hell of a lot more good than some silly framework.
Posted by: Etnu Feb 23rd, 2006 @ 5:34 AM EST
Comment
I do agree with you to a certain extend. I'm not a fan of people trying to make JavaScript be like another language. In nearly all cases JavaScript is the programmers secondary language and they just want it to work the same as whatever there main language is. This is obviously not a good idea but is an understandable reaction.
Prototype is not too bad on this which is why I find it more agreeable than most other libraries. After all, it's only really Enumerable that's very Rubyish and to be honest that's really useful. I wrote my own suite of functions similar to this years ago and while I think theres maybe a bit too many methods in Enumerable, on the whole it's great to have around.
Prototype doesn't override any of the aspects of the language that you've highlighted though. Take a look at the source.
Posted by: Dan Webb Feb 23rd, 2006 @ 9:55 AM EST
Comment
It doesn't override (that's not really possible), it discourages the use thereof. Helper functions (adding methods to String, Array, etc.) == good. Treating javascript as if it were another language == bad.
Posted by: Etnu Feb 23rd, 2006 @ 1:59 PM EST
SitePoint Marketplace
SitePoint Marketplace
Buy and sell Websites, templates, domain names, hosting, graphics and more.
SitePoint Software

Now even the CEO can edit the company Website!
Never mind showing people how to use HTML or XML to markup their
Website content. Download Editize, drop it into your CMS and forget
about it...
SitePoint Kits
NEW! - December 2005
Run Your Own Web Server Using Linux & Apache
Setup, optimize and secure your own Web Server!
Download the FREE sample chapters
NEW! - September 2005
Build Your Own Standards Compliant Website Using Dreamweaver 8
Create accessible, standards compliant Websites today!
Download the FREE sample chapters
SitePoint Books
Download sample chapters of any of our popular books.

