Section 14.2. Working with Prototype


14.2. Working with Prototype

No other library, toolset, or invention has led to the explosive growth of Ajax more than Prototype, the freely available Ajax/JavaScript library created by Sam Stephenson and available at http://prototype.conio.net/. It's become so popular, it's integrated as part of the Ruby on Rails (RoR) development environments. Several other libraries reviewed in this chapter and in previous chapters are based on Prototype.

What Prototype offers is a way to emulate a classlike behavior based on the JavaScript prototype; it provides a set of functions that hide much of the underlying JavaScript behavior. This is good because JS can be cumbersome when you're trying to access several elements in a page and have to get each one using something like getElementById. However, as has been noted frequently, Prototype also hides many of the underlying mechanisms, which can make reading any code that uses the library confusingespecially for newer JavaScript developers or those unfamiliar with Prototype. Luckily, this won't include you after the following brief peek.

14.2.1. Download, Install, Use

One aspect of Prototype I really appreciate is that it's one library, included in one JavaScript file, and easily integrated into a page. Just include a link to the downloaded Prototype library in your application:

<script type="text/javascript" src="/books/4/327/1/html/2/prototype.js"> </script>

That's it (assuming you put the prototype.js file on your server). You're now ready to use Prototype functions in your own applications.

The Ruby on Rails framework provides code support for Prototype, as well as Script.aculo.us. If you're a Ruby developer, find out how to include Prototype in your application at http://api.rubyonrails.com/classes/ActionView/Helpers/JavaScriptHelper.html.


14.2.2. The Helper Functions and the JavaScript Extensions

Prototype is most known for its extensive set of utility or helper functions. I mentioned these in earlier chapters as being responsible for adding a series of cryptic operators into JavaScript, most starting with the dollar sign.

One of the more common functions is $( ), which can be used in place of document.getElementById, but with a kicker: if you specify a list of elements, it returns an array of elements:

var theDivs = $('div1','div2','div3');

The $F function returns whatever value there is for a specific form field, while the $H function converts an object into an enumerable Hash (one of Prototype's many new object types). In the following code, an object is converted to a Prototype Hash, and the values are then accessed and stored in a JavaScript array using one of the Hash functions, values:

var obj = {                   partA : one,                  partB : two,                  partC : three,                   }; var hshObj = $H(obj); var arr = hshObj.values(  ); 

The $R function creates one of the new Prototype objects, ObjectRange. An ObjectRange is a range of values, with given lower and upper boundaries that exclude any specific values. The parameter objects are JavaScript Number objects, which themselves have been extended to include a new method, succ. This method, when called, increments whatever primitive value the Number object wraps. ObjectRange inherits behavior from the Prototype Enumerable objects that provide several enumeration functions. These functions include each, find, findAll, entries; they convert the object into an array, and so on. We'll look more closely at Prototype's enumeration capabilities in a moment, but first, let's take these shortcut functions for a test drive.

In Example 14-1, two input fields accept numbers, which are then used to create an ObjectRange. Once created, Prototype enumeration iterates through the collection of values, creating a string. This string is then printed out using innerHTML to a DIV element, which is accessed by the generic $ function.

Example 14-1. Trying out the Prototype helper functions

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>$</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="/books/4/327/1/html/2/prototype.js"> </script> <script type="text/javascript"> //<![CDATA[ function iterate(  ) {   var lower = new Number($F('input1'));   var higher = new Number($F('input2'));   var rng = $R(lower,higher,false);   var div = $('div1');   var strng = "";   rng.each(function(value,index) {              strng+=value + " ";              });   div.innerHTML = "<p>" + strng + "</p>"; } //]]> </script> </head> <body> <form > lower: <input type="text"  /><br /> upper: <input type="text"  /><br /> <a href="javascript:iterate(  )">Iterate</a> </form> <div > </div> </body> </html>

Notice how the numbers accessed via the form are wrapped in a Number constructor? Without this, you'll receive an error about succ missing on the values. The reason you do so is because the values aren't returned from $F as Number objects, and it is the Number object that's extended with a succ method to aid in enumeration. You can also use parseInt or some other conversion function to ensure the values are the correct type when passed to the ObjectRange.

This example gave us a taste of some of the objects in Prototype. Let's look more closely at a few others.

14.2.3. Some Specialized Prototype Objects

Among some of the objects Prototype provides is a Class one-off object, which is used to manage the creation and initialization of the other objects. There's also an Element, which extends the functionality of DOM nodes; it basically merges many of the DHTML effects into method calls. The Form object extends the functionality of Form, providing methods such as getValue to get the value of a form field.

The Prototype Ajax object encapsulates much of the Ajax behavior demonstrated in the last chapter. To see how this object works, we'll replace the core JavaScript from examples in Chapter 13.

Example 14-2 is a recreation of Example 13-1, except this time we're using the Ajax object, as compared to doing the Ajax processing ourselves. Notice two things. First, we're using a lot less code. Second, we're providing an element that serves as a target for the Ajax results.

Example 14-2. Using Prototype Ajax object to make an Ajax request

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Hello Prototype Ajax World</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="/books/4/327/1/html/2/prototype.js"> </script> <style type="text/css"> div.elem { margin: 20px; } </style> <script type="text/javascript"> //<![CDATA[ function populateList(  ) {    var url = 'ajaxprototype.php';    var params = "state=" + escape($F('state'));    var ajx = new Ajax.Updater('cities',url,{method: 'get', parameters: params, onFailure : handleError}); } function handleError(request,hdr) {    alert(hdr); } //]]> </script> </head> <body> <h3>Select State:</h3> <form action="ajax.php" method="get"> <div > <select onchange="populateList(  )" > <option value="CA">California</option> <option value="MO">Missouri</option> <option value="WA">Washington</option> <option value="ID">Idaho</option> </select> </div> <h3>Cities:</h3> <div  > <select> </select> </div> </form> </body> </html>

Since we're specifying a target, and Prototype will insert the response in this object, I've also adjusted the PHP script to append the select element before and after the options list so that the whole object is replaced. In Chapter 13, we did this directly in the client JavaScript:

echo "<select>$result</select>";

I could have created an option in the Updater constructor, onSuccess, that passes in a function to be invoked on success, rather than sending it through a target. The function has one parameter, XMLHttpRequest, which I could have used to process the result exactly as processed in Chapter 13. In addition, how the data is inserted can be modified based on the insertion property. This represents an Insertion class object that determines how data is inserted: before, after, top, or bottom. There is also the Ajax.Request object, which gives even finer control in how the Ajax request/response is managed.

14.2.4. A Compliment and a Caveat

I've barely scratched the surface on what Prototype can do, but hopefully I've given you a taste, at least, of some of the functionality. There are many more objects, including objects that provide enumeration to many of our base objects. It is this fact that also forces me to issue a caveat when you're using Prototype or any of the libraries derived from Prototype (a few of which I'll be describing later in the chapter).

In Version 1.4 of Prototype, Stephenson made alterations to the Object.prototype that ended up breaking associative arrays. This was fixed in Version 1.5, but the Array object still breaks on associative arrays. According to an article at the web site Ajaxian, using the Array object conflicts with Prototype's array-management extensions. (See "JavaScript Associative Arrays Considered Harmful," at http://ajaxian.com/archives/javascript-associative-arrays-considered-harmful). The philosophy behind the decision to alter the Array prototype was that arrays should be numeric, and associative arrays should occur only directly through Object.

Regardless of whether you agree with this or not (and I'll go on record as saying I unequivocally do not agree with this), it's an important reminder that, because of the immensely flexible nature of JavaScript and the increasingly complex, functionally overriding nature of some of the JavaScript libraries, you may end up actually breaking any existing code just by importing another library. Definitely explore the use of such libraries, but always do so with caution.

Like too many other Ajax libraries, Prototype is virtually free of any form of formal documentation. It's relatively easy to read, but this doesn't help when you're trying to get a quick overview of what it can and cannot do. Luckily, Sergio Pereira created a nice overview of the Prototype framework, in different languages, at http://www.sergiopereira.com/articles/prototype.js.html.





Learning JavaScript
Learning JavaScript, 2nd Edition
ISBN: 0596521871
EAN: 2147483647
Year: 2006
Pages: 151

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net