Ajax Hacks: Tips & Tools for Creating Responsive Web Sites

Use a framework to dynamically populate a web page widget from values derived from a Java object.

This hack automatically (you might say automagically) generates an ordered or unordered list using server content, such as a list of high-end bike makers. A typical list on a web page is hardcoded into the web page's HTML code. It looks like a series of bullets or numbers, each accompanied by a label. These list types are fine for content that never (or hardly ever) changes. However, some lists must be dynamically generated from a server object, based on persistent information such as that contained in a database. For example, think of a bike shop that is constantly adding new products to its online store, and/or changing product attributes.

A dynamically generated list is necessary only for persistent information that is updated frequently.

The web page code in this hack derives its content by calling a Java method via Direct Web Remoting, which is designed to bind JavaScript objects to Java objects running on the server. "Integrate DWR into Your Java Web Application" [Hack #43] sets up and configures the Java application on the server end, which is the first step to running this hack.

This hack generates an ordered list on the same web page other hacks in this chapter have used. This is an ol element that contains a numbered list of bike makers. We include the option to generate an unordered list (a ul element) containing bullets to the left of the labels. When the web page loads, its underlying code automatically fetches an array of bike-maker names from a server and generates the list. Figure 5-3 shows what the web page looks like.

Figure 5-3. A list of bike makers

The web page imports all of the necessary JavaScript files with script tags, and includes the list within a div tag with id orlist:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <script type="text/javascript" src="/parkerriver/ajaxhacks/js/hacks5_1.js"></script> <script type="text/javascript" src="/parkerriver/dwr/interface/JsBikeBean.js"></script> <script type="text/javascript" src="/parkerriver/dwr/interface/JsDate.js"></script> <script type="text/javascript" src="/parkerriver/dwr/engine.js"></script> <script type="text/javascript" src="/parkerriver/dwr/util.js"></script> <title>Bike Information</title> </head> <body> <!SNIPPED --> <p><input type="hidden" value="ordered" /></p> <!SNIPPED --> <div ></div> <!-- ... --> </body> </html>

hacks5_1.js includes our custom code, which I'll show in a moment. All the other imported JavaScript files are DWR-related. engine.js is required if your code is using the DWR framework; util.js is an optional library of utility functions, one of which is used in this hack. JsBikeBean is a JavaScript class that is bound to a Java object.

Here is the hacks5_1.js code:

window.onload=function( ){ callSetups( )}; function callSetups( ){ setupSelect( ); setupMap( ); setupList(document.getElementById("hid").value); setupDates( ); } function setupList(typ){ JsBikeBean.getDesignerInfo(function(list) { var div = document.getElementById("orlist"); var el = null; if(div != null){ //remove any existing lists div.innerHTML=""; if(typ.indexOf("un") == -1) { //create an ordered list el=document.createElement("ol"); } else { //create an unordered list el=document.createElement("ul"); } el.setAttribute("id","servlist"); div.appendChild(el); //create li elements from server information DWRUtil.addOptions("servlist", list); } }); } //Rest of code snipped...

One salient aspect is that the code does not require either XMLHttpRequest or our custom library for using the request object, http_request.js (see "Use Your Own Library for XMLHttpRequest" [Hack #3]). The DWR framework takes care of its remote binding between JavaScript and Java.

An event handler linked to window.onload calls a setupList( ) function. setupList( ) has a string specifying "ordered" or "unordered" as a parameter. The code gets this value from a hidden element on the web page, so that a web page designer or author can specify the type of list. Inside setupList( ), the code calls the Java method getdesignerInfo( ), via its client-side proxy JsBikeBean. This method returns an array of bike-maker names.

The way DWR works when remotely calling Java methods is that a parameter representing a function for handling the Java return value is added to the method call, as in:

JsBikeBean.callFoo(function(returnValue){//handle callFoo return value})

This approach, used in the web page code, handles the return value with a function literal. You can, alternatively, use JsBikeBean.callFoo(myFunc) and then define myFunc(returnVal) somewhere. In this case, the framework passes the Java method return value to this handler function as its parameter.

In our code, the function literal that handles the getDesignerInfo( ) return value looks like this:

function(list) { var div = document.getElementById("orlist"); var el = null; if(div != null){ //remove any existing lists div.innerHTML=""; /* The function literal has access to the type parameter of the outer function; typ can be "ordered" or "unordered" */ if(typ.indexOf("un") == -1) { //create an ordered list el=document.createElement("ol"); } else { //create an unordered list el=document.createElement("ul"); } el.setAttribute("id","servlist"); div.appendChild(el); //create li elements from server information DWRUtil.addOptions("servlist", list); } }

list is the array returned from the server, which looks like ["value1","value2"]. First the code determines whether to create an ordered or unordered list. The code then appends the new element with id servlist as a child within an existing div element. Finally, the function uses a DWR utility function to generate the new list:

DWRUtil.addOptions("servlist", list);

Figure 5-4 shows what the browser looks like after generating an unordered list.

Figure 5-4. Creating an unordered list from remote Java

The content at the bottom of Figure 5-4 relates to calling a built-in Java object using DWR. "Call a Built-in Java Object from JavaScript Using DWR" [Hack #49] covers this mechanism.

The addOptions( ) function takes the id of the list as the first argument, and the array of values as the second. If the code has to remove existing options from a list first, one option is to use DWRUtil.removeOptions("servlist").

Категории