See how Scriptaculous makes use of
Prototype to provide a number of higher-level widgets and components,
mostly aimed at creating user interfaces.
Editor's Note: This piece picks up where the article Introducing Prototype and Scriptaculous Part 1 left off.
What is Scriptaculous?
Prototype provides an extremely solid foundation for developing complex,
well-structured code, but on its own does little beyond that. The
onus of developing the functionality that the end user will see still rests
firmly with the developer.
Scriptaculous is a library that makes use of Prototype to deliver a rich
set of high-level functionality that the developer can put to work
directly in creating polished interactive user interfaces. On its own,
Prototype smoothes out many of the wrinkles of Ajax development.
When used with Scriptaculous, it transforms the way in which we
approach the web user interface, by making features such as animation
and dragging and dropping as simple as a few lines of code.
Like Prototype, Scriptaculous covers several distinct areas. Let's look
at each briefly in turn.
It is common when writing any computer application to wish to draw
the user's attention to some part of the interface, in order to provide
visual feedback. A button may wish to announce that it is clickable
when the mouse moves over it. Lists of items may wish to notify the
user when new items arrive or old ones vanish, particularly if it is the
result of a background process. It's easy to overdo this type of functionality
and end up with a user interface that distracts users or gets in
their way, but such effects, if well done, can make an application more
pleasant to use. In the world of web applications, in which a user may
go elsewhere with a few keystrokes, making an application easy to use
Scriptaculous makes it easy to create visual feedback of this type
through its Effects library. This library is remarkable not only for the
quality and range of effects that it enables, but for the high quality of
the underlying design of the code, which makes it easy to compose multiple
effects, run arbitrary code before, during, and after the effect, and
synchronize effects with one another. Needless to say, this good design
is made possible by the language features provided by Prototype.
In addition to being directly available to the coder, the Effects package
is used within Scriptaculous to add visual feedback to the other main
packages. Let's look at them now.
Drag and drop
Before Ajax, clicking on hyperlinks or submitting HTML forms could
only initialize requests to the server. Now that requests can be fired
programmatically, other types of user interaction can be used to trigger
requests too, so a wider range of user interaction techniques are finding
their way into web applications.
Dragging and dropping is a common user interface metaphor in desktop
applications, and in many cases it provides the most convenient and
intuitive way of interacting with a computer. The DOM has no direct
support for drag-and-drop events, and implementing drag and drop in
The good news is that Scriptaculous implements a feature-complete
drag-and-drop system that can be applied to most types of DOM element
with relatively little code. The look and feel of the interaction can
be customized using the Effects library, and custom event handlers
provide callbacks for all stages of the drag-and-drop event.
The features that we've discussed so far are frameworks that can be
used to enhance a coder's application. Scriptaculous also provides a
number of complete widgets, in the Components library. At the time of
writing, the Components library contains two components: the Auto-
Completer can attach a predictive drop-down element to any text field,
which can endow an ordinary HTML Form element with features similar
to Google Suggest; the in-place editor allows any DOM element to
transform itself into a text input field and back again.
In addition to these high-level components, Scriptaculous provides a
few helpers and utilities of its own. We'll conclude our initial review of
the library with a look at these.
Utilities and Testing Frameworks
objects and DOM that are mainly concerned with easier manipulation
of the user interface. These build on top of the extensions defined by
In addition, Scriptaculous provides a complete unit-testing framework
that runs inside the browser. This is designed mainly for internal use
by the Scriptaculous development team, as the entire library is well
covered by tests, but it can be used as a standalone testing library too.
This concludes our initial review of the Prototype and Scriptaculous
libraries. Before we look in more detail at the features of each in subsequent
chapters, we'll quickly demonstrate what Prototype and Scriptaculous
can do to help an ordinary Ajax application.
Applying Prototype and Scriptaculou
Writing Ajax applications by hand requires an intimate knowledge of
server-based web coding, familiar with languages such as Java, PHP,
and C#, many of these features are rather exotic. Worse, we will need
to master the subtleties of cross-browser incompatibilities. Prototype
and Scriptaculous have many language and cross-browser features
built in, and they can help to ease the pain a great deal.
In this section, we'll look at a simple Ajax application that allows a user
to assign a rating to an article (or a tune, picture, or anything else).
We'll show how to code the app by hand, and then refactor it using
and add a few quick wins too. So, without further ado, let's have a
look at the Ratings application.
Introducing the Ratings example
The Ratings example is a simple widget built using Ajax and DHTML
techniques that can be easily inserted into a web page to show an
interactive display of the rating that the user has assigned to an item.
Figure 1.1 shows the widget's visual components.
Figure 1 Ratings widget embedded in a web page. The small arrow icons
are buttons allowing the user to increase or decrease the number of stars
assigned to an item-in this case an article. (Icons are from the "Nuvola" icon
set by David Vignoni, http://www.icon-king.com.)
Operating the widget is simple enough. The user can increase or
decrease the rating by clicking on the blue arrow buttons with the
mouse, and the number of stars is incremented or decremented, within
the range of zero to five. When the user changes the rating, the widget
also makes an asynchronous call to the server to update the central
records. We won't worry for now about what the server does with that
information, or what the response is.
That's our brief, then. As coders, we're more interested in getting under
the hood and seeing how the implementation is done. Let's run through
a few highlights of the code now. The complete code for the app is available
for download from the Manning web page for this book.
Using the component
We have striven to follow best practices in writing the app, and we
tried to make it simple for designers to use without having to write a lot
a result, the Ratings app creates all of its user interface programmatically,
and the designer needs only specify an empty HTML element
within which it will sit. Needless to say, we've separated our various
resources out nicely, providing a .js file containing all the code, a CSS
stylesheet, and a set of images.
To incorporate the widget into a page, then, the designer needs to add a
few lines of code in the header of the page:
at shortly. The constructor for the object takes two arguments: the ID
of the HTML element in which it will render itself, and a caption to be
displayed. We've specified a target element called myRating, so we'll
define this in the HTML like so:
That's everything that our design team needs to do to use the widget.
Let's see what goes on behind the scenes, when the widget is activated.
Initializing the user interface
The constructor function for the Rating object is relatively simple, taking
a note of the main arguments and then delegating to a second function
updateUI(). Listing 1 shows the code for these functions.
There is quite a lot going on here, so let's pick through it piece by piece.
The updateUI() method takes an optional argument delta, which we'll
ignore when we initially call it in the constructor . It then proceeds to
build up a set of HTML markup as a string, defining the UI that we
saw in figure 1 as an HTML table. This string is then assigned to the
target element using the innerHTML property .
We go on to assign event handlers to the buttons. The next line looks
quite strange-we are defining a variable called rating that is a direct
reference to this . The reason for this is rather arcane. We are going
to create a closure when we define the event handler, and the special
variable this cannot be passed in to a closure. We create rating as a
copy in order to pass it in.
In the next few lines we're back on fairly safe ground. We've added
unique IDs to our buttons in the big innerHTML string that we just wrote,
so now we can programmatically reference the button elements .
Adding event handlers
We go on to define an event handler for the entire widget ( in
listing 1). This is an anonymous function, defined inline. Because of
the variable this will no longer refer to the Rating object, but to the
HTML element that fired the event. We refer to the variable rating,
which is bound to the function as part of the closure, in order to see the
Rating object inside the event-handling code.
It's a common mistake to refer to this inside event handlers, and writing
this code took a few goes to straighten all the ratings and thises
out, but we've done it. When the buttons are pressed, we re-render the
entire UI by calling updateUI() again, this time with the delta argument
to indicate that the rating is going up or down.
Finally, we tell the server that the rating for this item has changed .
We'll be using core Ajax techniques to do this, and we'll look at these in
a minute. First, let's review what we've done in order to get our two
buttons up and running. We've visited a number of unusual language
called with arbitrary contexts (i.e., the variable that evaluates to this
within the function), and the ability of Function objects to create closures
implicitly. Both of these require quite a deep understanding of
the language, which is fine if we like collecting unusual programming
languages, but if we're a Java or PHP coder seconded into doing a bit
of Ajax work, it's quite a lot to take on board.
We'll soon see how Prototype and Scriptaculous can help to keep the
language out of our hair. First, let's have a look at the Ajax code.
Making an asynchronous HTTP call
We're going to use the XMLHttpRequest object to contact the server
whenever the user clicks one of the buttons. As we noted earlier,
XMLHttpRequest confers the ability to work with the HTTP protocol
at quite a low level, and it is consequently not very straightforward to
use for extremely simple tasks. There are several wrappers for the
XMLHttpRequest available now, and we'll see the one provided by
Prototype in a minute. To emphasize the difference, though, we're
going to use the raw XMLHttpRequest in this example. Listing 2
shows the code required to do so.
Again, the code required to do the job isn't that small. Let's pick
through the main points. First, we need to get hold of an XMLHttpRequest
object. In some browsers it's a native object, and in others it's an
ActiveX component, and we try to account for all the possibilities .
By luck, we've got it the right way around here, testing for a native
object first. Internet Explorer version 7 has arrived upon the scene, and
it supports a native XMLHttpRequest, as well as ActiveX for backwards
compatibility. If we'd tested for ActiveX first, we would have
ended up using ActiveX unnecessarily under IE 7, and potentially
blocking browsers where ActiveX controls have been locked down, but
our Ajax code would otherwise have worked. We could have supported
older versions of IE by checking for alternative ActiveX types too, but
that's a lot of background knowledge required to implement a simple
rating widget, so users of IE 5.5 are maybe out of luck with our app.
The second point to note is that strange closure trick again. We define
the variable rating and then refer to it inside the event handler .
In this case, the event handler is simply a one-line call to another function,
which might leave us wondering why the onReadyState() function
wasn't assigned directly if we didn't understand the intricacies of
We're calling a server-side process that talks in terms of standard querystring
key-value pairs. Almost every server-side language provides
automatic parsing of querystrings, but with XMLHttpRequest, we need
to build up the string manually , remembering to call encodeURI() for
each value. We then need to set a few crucial HTTP headers before
we're ready to send our request out . It's a little-known fact that the
convenience methods we're used to on the server, such as Java Servlet's
request.getParameter() and PHP's $_GET array, will only be populated
if the request has a content type of application/x-www-form-urlencoded.
HTML forms fill this in for us automatically, but with XMLHttpRequest,
we need to do it ourselves.
Once the request goes out, our callback handler is busy. Rather
than being called once when the request completes, it is notified at various
stages in the lifecycle of the request, which is great for implementing
progress bars, but something of an overhead for us here. A
readystate value of 4 corresponds to a completed request, so we simply
check for that and then call either the success handler or the error handler depending on the HTTP code of our response.
Let's review what we've been through here. Once more, everything is
done, and it works, but we've gone to rather a lot of effort, and we've
needed rather an intimate knowledge of the HTTP protocol, particularly
concerning how querystrings are encoded in requests and are
only decoded on the server if the right set of HTTP headers is applied.
Furthermore, we've had to get our heads around closures once again.
After writing this application, I refactored the code to use Prototype
and Scriptaculous features in a few places, to make it easier to work
with. Let's look at how it simplified things.
Adding Prototype and Scriptaculous
We can see the first advantage of using Prototype and Scriptaculous
before we open the files. The main code file, ratings.js, is roughly 20 percent
smaller as a result of our work, which certainly suggests that these
libraries can help our productivity. However, that in itself doesn't tell us
very much. Let's step through the refactoring and look at the details.
DOM helper methods
Prototype comes equipped with a range of helper methods that make it
easier to work with the DOM. The simplest of all is a function named
In our original code, we've been looking up DOM elements by their
IDs, like this:
Prototype allows us to rewrite this as simply as this:
For now, it's enough to know that we've saved ourselves from some
tedious typing. In fact, $() is a lot more powerful than document.getElementById().
In the original version of the code, we had to get our heads around closures
and function contexts when writing the event handler for the buttons
(see in listing 1). This had two practical consequences. First, we had to define the event-handler code inline as an anonymous function, in order to get the closure to work. Sometimes it's good to use
anonymous inline functions, but here we did it because we had no
choice. Second, we had to refer to the Rating object as rating rather
than this inside the event-handler code, which felt a bit odd.
While writing the event handler, we also had to write some crossbrowser
code to handle the different ways of obtaining the event object
and its target element.
Prototype can relieve us of all these chores with a single call. Function.
bindAsEventListener() wraps an ordinary function up as an
event handler, creating the closure for us, sorting out the function context
issues, and presenting us with a robust, cross-browser event object
whose target element we can readily access. Listing 3 shows the modified
code, with changes shown in bold.
We're using two event-handler features to get around differences in the
cross-browser event models here. Event.observe() allows us to
attach multiple handler functions to an HTML element safely. Function.
bindAsEventListener() turns an ordinary function into an
event handler, supplying it with a cross-browser event object, and passing
in the first argument as the event context. Here, we've passed our
Rating object in, which means that we can define our event-handling
code as an ordinary member function of the Rating prototype .
The clickHandler() function that we define contains the same logic as
its anonymous predecessor but is certainly easier to read. We
can access the HTML element that fired the event in a single line of
code , and we refer to the member variables of the object in a natural
way using this.
There is an even bigger win to be made, though, when sending the
Ajax request to update the server. Let's look at that next.
Ajax requests made easy
language internals, but of the HTTP protocol too. Knowledge
is good, but we were in a hurry, and figuring out the details slowed us
down rather a lot.
Prototype provides a utility object, the Ajax.Request, which encapsulates
a lot of this complexity so that we don't have to in a simple case
like this (but we still can when we're in HTTP power-coding mode!).
Listing 4 shows the revised Ajax code.
When writing our own Ajax call, we had to manually encode and create
a querystring (see in listing 2). Here, we're using Prototype's $H()
function (yes, these guys like short names!) to create a Hash object out
in remembering to call encodeURI() every time you create a querystring.
Now on to the biggest improvement in the coding-making the
request. The Ajax.Request object takes two arguments in its constructor .
object stuffed full of optional arguments. (We'll see this idiom a
lot throughout this book, in the predefined objects and in our own
code.) We specify the HTTP method as POST, and pass in our querystring.
Details such as mime type will be taken care of for us.
We also add in two callback handlers. Ajax.Request allows us to define
suitably high-level callbacks, for success and failure of the request .
Note that we're using Function.bind() here. Like bindAsEventListener(),
this simply ensures that when the callback is invoked, it will
have the context object that we want it to have.
We no longer need to write a callback that will be invoked multiple
times during the request, because in this simple case, we don't need to.
Prototype handles all that and the HTTP response codes for us. Compared
to listing 2, tellServer() has shrunk by at least 50 percent,
and we've got rid of onReadyState() altogether.
We could rest on our laurels right now, but let's make one final change
to the application before we wrap up this chapter, and show off one of
Scriptaculous's useful features.
Adding Polish to the User Interface
Our refactored app is matching the original version feature for feature
with less effort. While coding up the original app, we thought of several
"nice to have" features that there just wasn't time to implement.
Well, we've saved ourselves a little bit of time now, so let's have a look
at one of them.
When the user modifies the rating, there is no visual feedback beyond
the star disappearing. A little animation might make the app more satisfying
to use, and might ultimately increase uptake of the project. This
sort of benefit is hard to gauge, though, so we don't want to spend too
much effort on it, lest it distract us from more serious matters.
Using Scriptaculous's Effects library, we can animate the adding and
removing of stars in only a few lines of code, as shown in listing 5.
(We've reproduced the entire function here-the new code is highlighted
In the previous versions of the application, we always corrected the
rating score before rendering. In this case, when we decrement, we
want to initially draw in one extra star, and then get rid of it, so we
only correct the rating beforehand if the score has gone up . After
everything has rendered, we then set up the effects and decrement the
score if necessary .
The effects themselves are ridiculously easy to use, requiring only the ID
of the element to operate upon. We therefore need to provide ID
attributes for our images , but that's a minor hardship. The constructors can, like Ajax.Request, also accept an object full of options.
By adding these few lines of code, a newly improved rating will flash
on and off briefly to announce its presence, and a reduced rating will
see the leftmost star drop off the bottom of the page. It's hard to
present this as a still picture in a book, unfortunately, but you can
download the code and see it for yourself.
That concludes our first taste of what these libraries can do for us. In
subsequent chapters, we'll dig more methodically into this rich seam.
In these two articles, we looked at the development of Ajax technologies. As
long ago as the late 1990s, preliminary explorations of asynchronous
communication between the browser and server were being undertaken,
mostly in isolation. In early 2005, the coining of the name Ajax
provided a much-needed focal point for these explorations. Since then,
there has been a major drive towards increasing the ease of development
of Ajax, in which frameworks and libraries are playing an important
part. It is no longer sufficient to be able to make an Ajax app work;
we now need it to work smoothly and robustly, and it must be easy to
develop and maintain.
and Ajax libraries, and we looked at their main purposes and constituent
pieces. Prototype is a relatively low-level library, providing
additional language features and facilities. Scriptaculous makes use of
Prototype to provide a number of higher-level widgets and components,
mostly aimed at creating user interfaces.
and even introduce some new advanced features of their own.
However, using these libraries in the most straightforward way does
not require a detailed understanding of these capabilities. We introduced
a simple Ajax example app and refactored it using Prototype
and Scriptaculous. Internally, the libraries are complex, and reading
their source code, one might suppose that a degree in rocket science is
necessary to understand them. However, our refactoring showed this
not to be the case, and we firmly believe that the average coder can
make quick wins by using these libraries. We'll continue to explore the
libraries in more depth throughout this book, and demonstrate how
you can benefit from their raw power.
About the Authors
Dave Crane is an Ajax authority and lead author of the best-selling Ajax in Action. He is currently senior developer for UK-based Historic Futures Ltd., developing the next generation of socially responsible supply-chain systems using Ajax to link rural cooperatives and multinational corporations.
Michael "Bear" Bibeault is a US-based Java programmer with over 20 years' experience in enterprise and Web applications. He's a popular moderator on The Java Ranch and coauthor of the upcoming Ajax in Practice.
Tom Locke is an UK-based independent web developer and trainer specializing in Ruby on Rails. He is the creator of Logix, a multi-language programming system, and the CTO of LiveLogix.
Source of This Material
Prototype and Scriptaculous in Action
By Dave Crane and Bear Bibeault with Tom Locke
Published by Manning Publications Co.
, March 2007
Paperback: 544 pages, Retail price: $49.99
MEAP + Softbound print + ebook
MEAP + ebook only
This material is Chapter 1 of the book.
Reprinted with the publisher's permission.