Section 6.2. Using the Rico Toolkit


6.2. Using the Rico Toolkit

To experiment with Rico, download the latest version from http://openrico.org/rico/downloads.page. The Rico Toolkit depends on the Prototype library, so start by importing the prototype.js and rico.js files into your HTML page:

 <script language="JavaScript" src="/books/4/163/1/html/2/scripts/prototype.js"></script> <script language="JavaScript" src="/books/4/163/1/html/2/scripts/rico.js"></script> 

Then you need to register a request handler:

 ajaxEngine.registerRequest('zipRequestHandle', 'rico'); 

The first parameter, zipRequestHandle, is the handle we'll use to make the Ajax request. The second parameter is the string rico, which is registered with the ajaxEngine. That is the relative URL used when the zipRequestHandle is invoked. Therefore, we need to map the servlet to this URL in web.xml:

 <servlet>     <servlet-name>RicoZipCodesServlet</servlet-name>     <servlet-class>         com.oreilly.ajax.servlet.RicoZipCodesServlet     </servlet-class>     <load-on-startup>5</load-on-startup> </servlet> <servlet-mapping>     <servlet-name>RicoZipCodesServlet</servlet-name>     <url-pattern>/rico</url-pattern> </servlet-mapping> 

Everything is now set up. Back in the HTML page, the zip code text field uses the Ajax engine to send the request to the server, using the zipRequestHandle:

 <td>Zip Code:</td> <td align="left" colspan="2">     <input type="text"  name="zipcode"            onblur="ajaxEngine.sendRequest('zipRequestHandle',            'zip='+escape(this.value));"> </td> 

The onblur JavaScript event is set to call ajaxEngine.sendRequest( ), sending the zipRequestHandle that we initialized earlier and passing in the value of the input field, which should be a zip code.

When the user enters a zip code and presses the Tab key to move the cursor to the next field, the onblur event triggers the Rico ajaxEngine to send a request to the specified URL. The server should then respond with an XML-formatted document that looks like this:

 <ajax-response>     <response type="element" >some content for the city</response>     <response type="element" >some content for the state</response> </ajax-response> 

The root of the XML response must be <ajax-response>. Each element within the response must be wrapped in a <response> tag, with the id and type attributes defined.

When an <ajax-response> document comes back from the server, Rico matches the id attributes in the document with the fields in the HTML form and populates the form accordingly. In this document, we have two IDs: cityDiv and stateDiv. The data from these XML elements is used to populate the HTML tags with the cityDiv and stateDiv IDs in our HTML document:

 <tr>     <td>City:</td>     <td align="left">         <div >             <input type="text"  name="inputcity">         </div>     </td> </tr> <tr>     <td>State:</td>     <td align="left" colspan="2">         <div >             <input type="text"  size="2" name="inputstate">         </div>     </td> </tr> 

So, if an HTML element has an id that matches an id in the response, Rico updates that HTML element with the content from the XML document.

What goes in the <response> elements? It would be simplest if we could just insert the city and state names, but Rico replaces everything inside the tags with the cityDiv and stateDiv IDs with the content from the XML document. In our HTML, the cityDiv and stateDiv IDs are assigned to <div> elements. Therefore, we need to supply new <input> tags to replace the contents of the divs in the HTML document.

Why not use HTML input fields for the state and city rather than wrapping the input fields with a div? The XML is less complex (we can just ship the city and state names back to the browser rather than shipping the entire <input> tags), and Rico can just fill in the fields. If the user-entered zip code does not have a corresponding entry in the database, the user can manually enter the state and city.

That won't work on all browsers, though (particularly Internet Explorer). Rico uses the innerHTML JavaScript method to replace the content of the elements. On Internet Explorer, the <input> element does not work with the innerHTML method.

Instead of directly entering the text into the <input> element, we wrap it with a <div> tag and have the servlet return the complete HTML code to create the <input> element.


So, the buildRicoXML( ) method needs to generate the content for a div that includes the HTML inputs. Also, we want to add a div to hold a message in case the zip code is not in the database:

 public static String buildRicoXML(HashMap map,String element, String message) {     StringBuffer ricoXML = new StringBuffer("<ajax-response>");     String key = "";     String value = "";     // loop through all the map entries     Iterator it = map.entrySet().iterator( );     while (it.hasNext( )) {         Map.Entry e = (Map.Entry) it.next( );         value = (String) e.getValue( );         key = (String) e.getKey( );         ricoXML.append("\r\n <response type=\"element\" id=\"" + key + "\">" +                 "<input type=\"text\" id=\"inner"+key+"\" name=\"inner"+key+"\"                 value=\""+value+"\" \><\response>");     }     ricoXML.append("\r\n <response type=\"element\" id=\"message\"             name=\"message\">"+message+"<\response>");     ricoXML.append("\r\n</ajax-response>");     return ricoXML.toString( ); } 

Now the zip code lookup application is ready. You'll first see a browser with three empty fields (Figure 6-1).

Figure 6-1. Rico zip code lookup


If a user enters a zip code that is not in the database, the message div instructs that user to manually enter the city and state (Figure 6-2).

Figure 6-2. Unsuccessful zip code lookup with message


Here's the code that creates the Rico response for the unsuccessful zip code lookup and message:

 <ajax-response>     <response type="element" >         <input type="text"  name="innerstate" value=" " />     </response>     <response type="element" >         <input type="text"  name="innercity" value=" " />     </response>     <response type="element"  name="message">         Zip code: 99999 is not in the database. Please enter your City and State     </response> </ajax-response> 

When the user enters the city and state, you can capture that information, verify it, and add it to your zip code database. That goes beyond what we'll demonstrate here, but it would be a useful endeavor.

What if the zip code is in the database? In that case, we don't really need to provide input fields; it may be cleaner to just display the city and state. To accomplish this, we could use a different method that doesn't fill the div with an input field but instead simply returns the city and state wrapped in the Rico response:

 public static String buildRicoXML(HashMap map, String message) {     StringBuffer ricoXML = new StringBuffer("<ajax-response>");     String key = "";     String value = "";     // loop through all the map entries     Iterator it = map.entrySet().iterator( );     while (it.hasNext( )) {         Map.Entry e = (Map.Entry) it.next( );         value = (String) e.getValue( );         key = (String) e.getKey( );         ricoXML.append("\r\n <response type=\"element\" id=\"" +                 key + "\">" + value + "<\response>");     }     ricoXML.append("\r\n <response type=\"element\" id=\"message\"             name=\"message\">"+message+"<\response>");     ricoXML.append("\r\n<\ajax-response>");     return ricoXML.toString( ); } 

Now, the XML we're returning looks like this:

 <ajax-response>     <response type="element" >CA</response>     <response type="element" >FRESNO</response>     <response type="element"  name="message"></response> </ajax-response> 

That results in the div containing only the bare text with no input fields for the user. The resulting page is shown in Figure 6-3.

Figure 6-3. Successful zip code lookup with Rico


Rico requires a bit more setup, but it's worth it because you don't have to write a callback function: Rico automatically populates the fields you need with the data that comes back.

This approach works fine if you want to fill document elements with values coming back from an HTTPRequest, but what if you need to look at the data or modify it? That's where Rico's Object Response Type comes into play.

6.2.1. Using Rico's Object Response Type

The Object Response Type allows the client JavaScript code to pull each element out of the XML response. It can then modify it or put it into the document as is.

To use the Object Response Type, we must register an object with the Rico ajaxEngine:

 ajaxEngine.registerAjaxObject('locationUpdater', cityStateUpdater); 

Now we need to create a cityStateUpdater object that has the method ajaxUpdate( ), as shown in Example 6-2.

Example 6-2. Creating an object for registerAjaxObject( )

 var CityStateUpdater = Class.create( ); CityStateUpdater.prototype = {     initialize: function( ) {     },     ajaxUpdate: function(ajaxResponse) {         this.setFields(ajaxResponse.childNodes[0]);     },     setFields: function(aState) {         document.getElementById('stateDiv').innerHTML=aState.getAttribute('state');         document.getElementById('cityDiv').innerHTML=aState.getAttribute('city');     } }; cityStateUpdater = new CityStateUpdater( ); 

We must then ensure that the XML response coming back from the server has the attribute type="object" and an id that matches the object set by registerAjaxObject( ). In this case, the id must be locationUpdater, and the data must be attributes in XML format. The XML response should look like this:

 <ajax-response>     <response type="object" >         <location state="OH" city="NEWTON FALLS" />     </response> </ajax-response> 

Here is the servlet code that produces the response:

 public static String buildRicoObjectXML(HashMap map, String message) {     StringBuffer ricoXML = new StringBuffer("<ajax-response>/r/n             <response type=\"object\" id=\"locationUpdater\"><location ");     String key = "";     String value = "";     // loop through all the map entries     Iterator it = map.entrySet().iterator( );     while (it.hasNext( )) {         Map.Entry e = (Map.Entry) it.next( );         value = (String) e.getValue( );         key = (String) e.getKey( );         ricoXML.append(key+"=\""+ value +"\" " );     }     ricoXML.append("/></response>\r\n</ajax-response>");     return ricoXML.toString( ); } 

If you missed how the data was inserted in the form, look back at the setFields( ) function in Example 6-2. That function merely gets an element from the DOM and puts the value from the XML response into that element. In this method, you can extract a value from the XML response and modify it or implement some logic based on the value.




Ajax on Java
Ajax on Java
ISBN: 0596101872
EAN: 2147483647
Year: 2007
Pages: 78

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