search the site  

Enter search terms:


subscribe to newsletters   WebReference.com logo   WebReference.com
dev the Web
tip archive  •   about  •   contact  •   jobs  •   sitemap

 
Search
 



[next]

Universally Related Popup Menus AJAX Edition:
Part 2

By Rob Gravelle.

Digg This Add to del.icio.us

ASP 3.0/.NET Developer
Jupitermedia
US-NY-New York

Justtechjobs.com Post A Job | Post A Resume

Last week we looked at a brief overview of Ajax, relevant JavaScript 1.3 enhancements, how to run the example and using the script within your own Web page. This week we look at additional functionality that you'd like to add to scripts and an in-depth explanation of the JavaScript code.

Customizing the Script

For those of you who like to tinker with things or have additional functionality that you'd like to add to the scripts, here's a line by line explanation of the JS and ASP scripts to help get you better acquainted with the code.

At the very top of the URPM_AJAX.js file there is a couple of global "constants". I could have used real constants by going with JavaScript 1.5, but I felt that 1.3 had more browser support at this time. Hence, these are actually just regular variables. Constants can be distinguished from regular variables by their uppercase names. The DEFAULT_URL stores the name of the default server-side script. If you wish to substitute your own script, remember to use a hidden field in your page, as outlined in part 2. You should never have to change this value. We need to detect Safari browsers because there is a bug in version 3 (at least on Windows 2000).

The initialize() function is the first to be called.  It is called from the BODY tag's onLoad() event with the IDs of each URPM, starting with the base list:

The first call within the initialize() function (see line 5 in box below) is to setOptionalProperties() (line 7). It sets some global constants from hidden fields in the HTML document. However, it is within the initLists() function that most of the work takes place (line 15). Some of its duties include binding the onchange event to our script and setting up the AJAX XmlHttpRequest object. The initLists() function returns true if it's safe to proceed and populate the lists and false if any errors are encountered. Although initLists() runs every time the page loads, the lists are only populated on the first page load because the list options and selections should be retained between page refreshes. If we repopulate the lists every time the page loads, we would wipe out the previous selections! The test to decide whether or not to populate the lists is the presence of options (line 15). In other words, once they're there, we don't load them again. The call to callServer() (line 15) loads the base list and causes a cascade effect to all the child lists. Here is the code for the initialize() function:

Lets take a closer look at the setOptionalProperties() function (line 18) . The optional properties, like all variables, have to be initialized every time as the values are lost between page reloads. Global variables have been prefaced with the window namespace to explicitly show that all global variables are appended as a property to the window Object when created. It's also a useful way to keep track of them. Here's the code for the setOptionalProperties() function:

The getHiddenFieldValue() (line 20) function above is used to retrieve the optional properties from the hidden form fields. There are a few scenarios that it has to deal with, including:

  1. No field present.
  2. No value assigned.
  3. Data type conversion required.

Dealing with all these possibilities is a lot easier than might first appear. Since all form control values are read in as strings, simply testing for the field is enough. There's no need to check for a blank value since that could be valid. A value of false is returned if the field isn't there because it's the most unambiguous value to test for in an if statement. The function is stored in a local variable to show that it's private:

In the case of the BLANK_ENTRY variable (line 46), a bit of conversion is necessary to get the proper value in order to convert "true" and "false" strings to their respective boolean equivalents. It seems straightforward, but it's not as trivial a matter as it first appears. The challenge is the Boolean() function (lines 36 ,40) converts any non-empty string to true! One way to get around this inconvenience is to use the eval() function (line 34). It will attempt to interpret any string as JavaScript code. In doing so, it will also throw errors for any bad syntax that it encounters. Once the string has been evaluated, the Boolean() function must still be used because numbers such as 0 or 1 will be stored as integers. If eval() doesn't recognize the string as JavaScript code, we call the Boolean() function directly so that any non-empty string besides "false" will evaluate to true.

The Boolean function is used to convert a non-Boolean value to a Boolean value. Creating a new Boolean object will also work, but instanciating a new object for a one time use is somewhat wasteful.

x = Boolean(expression) //preferred
x = new Boolean(expression).valueOf() //don't use

Note: If the Boolean object has no initial value or if it is 0, -0, null, "", false, undefined, or NaN, the variable is set to false. Otherwise it is true (even with the string "false")!

Here's the code for the convertToBoolean() function:

A Doubly Linked List
A Doubly Linked List

The next function, initiLists() (line 58), is where all of the URPMs' setup is done. It loops through each ID passed to the arguments array, and attempts to get a reference to each element using the Document Object Model's (DOM) getElementById() function. This is the preferred way to reference form elements nowadays. Previously, you had to use document.formname.elementname notation. This was inconvenient because you had to keep track of the form object as well as the element! The getElementById() (line 22) function deals with this issue by ignoring the form altogether.

The last variable (line 324) stores a reference to the list form element that we initialized on the previous run through the loop. Hence, the base list won't have anything in the last variable. The next property (line 332) is added to the last variable and set to the current list so that each list points to the next one, similar to linked list:

The first time through the loop, we call the initBaseList() function (line 335) using the JavaScript 1.3 call() method (line 335), passing the list as the object, with no arguments. It returns the browser-dependent function code to fire the onchange event programmatically, which is then stored in the fireOnChangeEvent (lines 324, 335) variable.

The bindOnChangeHandlerToList() function (line 337) is called for all except the last list. As the name suggests, it binds our changeHandler function to the list's onchange event by adding it as a listener. Once the function is bound, the fireOnChangeEvent() function will indirectly cause the setSublist() function (line 337) to be called within the scope of the list via the onchange event. We don't bind the setSublist() function (line 337) to the last child list, because it has no sublist to set.


[next]

Recent Articles

WebReference.com site name
Perl Pragma Primer
Implement Drag and Drop in Your Web Apps: Part 2
How to Create an Ajax Autocomplete Text Field: Part 5
internet.com site name
SQL Server 2005 Express Edition - Part 22 - Upgrading from Microsoft SQL Server Desktop Engine (MSDE)
Vyatta: Downgrades that Pay Off
NetMotion Brings Cross-Network Support to Wireless VoIP




JupiterOnlineMedia

internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info


Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers

Solutions
Whitepapers and eBooks
Microsoft Article: HyperV-The Killer Feature in WinServer ‘08
Avaya Article: How to Feed Data into the Avaya Event Processor
Microsoft Article: Install What You Need with Win Server ‘08
HP eBook: Putting the Green into IT
Whitepaper: HP Integrated Citrix XenServer for HP ProLiant Servers
Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 1
Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 2--The Future of Concurrency
Avaya Article: Setting Up a SIP A/S Development Environment
IBM Article: How Cool Is Your Data Center?
Microsoft Article: Managing Virtual Machines with Microsoft System Center
HP eBook: Storage Networking , Part 1
Microsoft Article: Solving Data Center Complexity with Microsoft System Center Configuration Manager 2007
MORE WHITEPAPERS, EBOOKS, AND ARTICLES
Webcasts
Intel Video: Are Multi-core Processors Here to Stay?
On-Demand Webcast: Five Virtualization Trends to Watch
HP Video: Page Cost Calculator
Intel Video: APIs for Parallel Programming
HP Webcast: Storage Is Changing Fast - Be Ready or Be Left Behind
Microsoft Silverlight Video: Creating Fading Controls with Expression Design and Expression Blend 2
MORE WEBCASTS, PODCASTS, AND VIDEOS
Downloads and eKits
Sun Download: Solaris 8 Migration Assistant
Sybase Download: SQL Anywhere Developer Edition
Red Gate Download: SQL Backup Pro and free DBA Best Practices eBook
Red Gate Download: SQL Compare Pro 6
Iron Speed Designer Application Generator
MORE DOWNLOADS, EKITS, AND FREE TRIALS
Tutorials and Demos
How-to-Article: Preparing for Hyper-Threading Technology and Dual Core Technology
eTouch PDF: Conquering the Tyranny of E-Mail and Word Processors
IBM Article: Collaborating in the High-Performance Workplace
HP Demo: StorageWorks EVA4400
Microsoft How-to Article: Get Going with Silverlight and Windows Live
MORE TUTORIALS, DEMOS AND STEP-BY-STEP GUIDES