Tuesday, April 22, 2008

Universally Related Popup Menus AJAX Edition: Part1

Getting Acquainted with the New Script and Sample Files

Welcome to the fourth installment of my Universally Related Popup Menus (URPM) series. I think you'll agree that AJAX has ushered in a whole new paradigm of browser and server interaction and end user satisfaction. If you haven't yet heard of it, prepare to be amazed!

If you aren't familiar with the URPMs, here's a working example of the original JavaScript implementation.

This article is divided into three parts. This section covers:

* a brief overview of AJAX
* some relevant JavaScript 1.3 enhancements
* how to run the example
* using the script within your own Web page

The second section will offer a more in-depth explanation of the JavaScript code.

Finally, the third section will conclude the line-by-line walkthrough of the JavaScript code and describe the server-side classic ASP script code.
AJAX in a Nutshell
AJAX stands for Asynchronous JavaScript And XML. Unlike Perl or Java, AJAX isn't a distinct language, but rather an extension of JavaScript used in conjunction with XML and DHTML. AJAX was created to solve a nagging problem that developers of dynamic Web content were faced with: how to refresh Web data without reloading the entire page. Before the advent of AJAX, developers had to resort to browser dependent hacks such as IFrames or more esoteric solutions such as Java applets. In JavaScript, the XMLHttpRequest object is what allows the browser to make asynchronous server calls behind the scenes. Since execution of AJAX processes can proceed independently, other processes may be started before the asynchronous process has finished. In other words, the user can continue to interact with the page. Otherwise, the browser would "freeze up" while it waits for the response from the server. We'll be looking at the XMLHttpRequest object in a lot more detail a little later on.
AJAX vs. XML

In the URPMs Version III article, I used XML to logically represent the contents of several related dropdown lists. To make it easier on the developer, an ASP script generated the XML code from a database. Here is an example of the resulting XML code:
1
2
3
4
5 2.2 PREMIUM
6 2.3
7 3.0
8

9
10 PREMIUM
11 SE
12 SPORT
13

14
15 GS
16 GS-R
17 LS
18 RS
19 SE
20 TYPE-R
21

22

23
24
25 LEVEL N/A
26

27
28 LEVEL N/A
29 VELOCE
30

31

32 ...
33
view plain | print | ?
2.2 PREMIUM 2.3 3.0 PREMIUM SE SPORT GS GS-R LS RS SE TYPE-R LEVEL N/A LEVEL N/A VELOCE ...

This structure makes it easy to see how each child list relates to its parent node. After reading several responses from people and playing with the sample page, there's no question that it was a versatile and useful implementation of the URPM concept. However, there was still one issue that it didn't resolve, the initial page size. The problem is that all possible selections must be download along with the page. Depending on the size of your lists, that can amount to a lot of unnecessary text! ( On the plus side, changes in the list contents are lightning fast. :-) ) AJAX circumvents this issue by loading the child lists when a selection is made instead of when the page first loads. A server-side script retrieves items from a database or flat file and then returns them to the page. Small amounts of data like this usually load fairly quickly so that any delay in loading is minimal and hardly noticeable. As a side benefit, retrieving only the relevant list items resulted in simpler server-side code than generating complex nested XML nodes.
JavaScript Gets a Makeover

The JavaScript has been updated from version 1.2 to 1.3 in order to take advantage of the new call() and apply() Function object methods. Although JavaScript 1.5 is the most current, I chose to go with 1.3 because it is the latest version supported by Internet Explorer 6. According to the w3schools.com browser statistics for December of 2007, 33.2% of web surfers were still using IE 6, compared to an even 21% for IE 7. Who wants to alienate a third of Internet users?!

Both the call() and apply() methods allows you to share the same object between any number of functions. This allows us to pass it to a function so that it runs within the scope of the object. In other words, the supplied object will be accessible to the function via the this pointer. The call() function accepts any number of parameters, while apply() takes only two, as the second parameter is an array. Later on, we'll see how to recycle a function's arguments by passing the Function.arguments property to the apply() function. Here is some sample code for the call() and apply() functions:
1 function car(make, model, year)
2 {this.make = make, this.model = model, this.year = year}
3
4 function hireCar(carNo, make, model, year)
5 {this.carNo = carNo, car.call(this, make, model, year)}
view plain | print | ?
function car(make, model, year) {this.make = make, this.model = model, this.year = year} function hireCar(carNo, make, model, year) {this.carNo = carNo, car.call(this, make, model, year)}

OR
1 function RentalCar(carNo, make, model, year)
2 {this.carNo = carNo, car.apply(this, new Array(make, model, year))}

Universally Related Popup Menus AJAX Edition: Part 3

The XmlHttpObjectManager Object

The XmlHttpObjectManager is a private member variable of the callServer() function (line 141). It's a static class, so we never create an instance of it. Rather, it just houses some variables and methods that relate to the XmlHttpRequest object. Its main purpose is to act as a wrapper to the XmlHttpRequest object because we only create one that we reuse every time we want to call the server. The real object is stored in the private XmlHttpObject variable (line 143). To get a reference to it, we call getXmlHttpInstance(), which is one of two public functions exposed via the interface object (line 144). The interface object uses JavaScript Object Notation (JSON) which is a standardized way of denoting an object literal, much the same way that XML is used to describe data. Hence, its syntax is quite a bit different from regular JavaScript The entire object is located between two curly braces {}. Each public property is notated by its name, followed by a colon (:) and the value. The properties are then separated by commas.

Now let's take a look at our interface's methods and properties.

The getXmlHttpInstance() method (line 146) is what I like to call a "mutating function". Here's why. The first time it's called, it returns a new XmlHttpObject (line 150) but it also sets itself to a new function that returns the private xmlHttpObject variable (line 148). Oddly, this has no effect on the execution of the function because it's already on the stack, so the changes don't take effect until after the current one finishes executing. Every successive call afterwards receives the same xmlHttpObject variable.

The state_change() method is the second one that is accessible via the XmlHttpObjectManager's public interface (line 153). Its job is to check the xmlhttp.readyState property every time the xmlhttp.onreadystate property changes. We have to check the readyState property to make sure the object has finished bringing back all the data from the server (line 155). There are a total of five possible states but we're testing against a value of 4. Here's the list of ready state values and their meaning:

  1. The request is uninitialized (before you've called open()).
  2. The request is set up, but not sent (before you've called send()).
  3. The request was sent and is in process (you can usually get content headers from the response at this point).
  4. The request is in process; often some partial data is available from the response, but the server isn't finished with its response.
  5. The response is complete; you can get the server's response and use it.

Once we hit the last loading state, we can run the call back function (line 159). Any errors that occur in the callback function will be trapped by the try/catch block so that a message can be displayed (line 163). The list is again passed along in the this pointer.

The following properties are also accessible via the interface object: RUN (line 171), READY_STATE (line 173), and STATUS (line 175). They are JSON objects containing named constants. Here's the first part of the XmlHttpObjectManager object, including its private interface variable (we'll see how it's made public in a moment)

141var XmlHttpObjectManager = (function()
142{
143 var xmlHttpObject = null;
144 var interface =
145 {
146 getXmlHttpInstance:function()
147 {
148 interface.getXmlHttpInstance = function() { return xmlHttpObject; };
149
150 return new XmlHttpObject();
151 }
152 ,
153 state_change:function(xmlhttp, callBackFunction, READY_STATE, STATUS)
154 {
155 if (xmlhttp.readyState == READY_STATE._DONE_LOADING)
156 {
157 try
158 {
159 callBackFunction.call(this, xmlhttp, STATUS);
160 }
161 catch (e)
162 {
163 alert( "An error occurred in the AJAX call back method:"
164 + "\nNumber:\t" + e.number
165 + "\nName:\t" + e.name
166 + "\nMessage:\t" + e.message );
167 }
168 }
169 } //public constants
170 ,
171 RUN: { _ASYNCHRONOUSLY:true }
172 ,
173 READY_STATE: { _DONE_LOADING:4 }
174 ,
175 STATUS: { _OK:200 }
176 };

Our next stop is the XmlHttpObject() constructor class (line 179). The XmlHttpObject is a little different than your typical JavaScript class in that it sets the XmlHttpObjectManager's private xmlHttpObject variable (notice the lowercase x) and it also returns it. In other words, the constructor returns a different object than the class (line 208). The constructor is used to create the XmlHttpRequest in a browser-independent way. The first couple of try/catch blocks are for Internet Explorer (lines 181,187). The new XMLHttpRequest() constructor is used for all other DOM Level 2 compliant browsers (line 199). If it can't create the object, it displays an error message and returns false so that the script can abort (line 201).


178//constructor
179var XmlHttpObject = function()
180{
181 try
182 {
183 xmlHttpObject = new ActiveXObject('Msxml2.XMLHTTP');
184 }
185 catch (e)
186 {
187 try
188 {
189 xmlHttpObject = new ActiveXObject('Microsoft.XMLHTTP');
190 }
191 catch (E)
192 {
193 xmlHttpObject = false;
194 }
195 }
196
197 if (! xmlHttpObject && typeof(XMLHttpRequest) != 'undefined')
198 {
199 xmlHttpObject = new XMLHttpRequest();
200
201 if ( ! xmlHttpObject )
202 {
203 alert("Your browser does not support the XMLHttpRequest object.");
204 return false;
205 }
206 }
207
208 return (xmlHttpObject);
209}


The bind() function (line 211) is a private member function to the XmlHttpObjectManager. It's used to provide the state_change() function with the objects and variables it needs when the XMLHttpRequest fires the onreadystatechange event. It does so by creating local variables within the function on which it's applied. The function that bind() is being applied to - state_change() in this case - is saved in the method variable (line 213). The first argument is the object which will define the scope of the callback function (line 211). We supply the list object for this purpose. All other arguments will be passed along to the calling function, but in order to do that, we have to separate them from the first argument. The Array object has the perfect method called slice(). It splits the array from the element number that we provide and returns the remaining elements as a new Array. Unfortunately, it turns out that the arguments property is not a true Array. While it shares some of the same properties such as length, it doesn't implement all the methods of a true Array object. There are two ways around this: to write our own slice() function, or, to steal the existing one from the Array object! Once we've copied the slice() function over to the arguments property (line 215), we can call it as if it always existed (line 217). The return type is a function because the onreadystatechange property expects one (line 219).


211Function.prototype.bind = function(object)
212{
213 var method = this;
214
215 arguments.slice = Array.prototype.slice;
216
217 var oldArguments = arguments.slice(1);
218
219 return function() { return method.apply(object, oldArguments); };
220 }


The last line in the XmlHttpObjectManager returns our interface object containing all the public methods and properties (line 222). Those parentheses immediately proceeding the function curly brace (line 223) (along with the opening parenthesis before the function) are used to create an inline function (line 141). This causes the XmlHttpObjectManager to be instantiated on the same line as it's declared. Thus, the only object that we can interact with is the interface which is what's actually stored in the XmlHttpObjectManager variable. The result is a static object that we can call with various methods.

141 var XmlHttpObjectManager = (function()
. //code
. //code
. /more code
.

222 return interface;
223 })();

When the XmlHttpRequest object's readyState contains a value of 4 ( done loading ), the state_change() function calls fillListCallBack() (lines 159, 250). This is where the string from the server gets converted into list options. To act as a reminder that the function is executing within the list's scope, a variable by that name stores the this pointer (line 252). The HTTP status code is returned in the XmlHttpRequest's status property. If its value is 200 (for OK) (line 254), we proceed to check the responseText property (line 257). This is necessary because it's possible there are no linked items for that entry. The XmlHttpRequest object also has a responseXml property, but we don't use it because we treat the response as a straight string, not an XML formatted document. We could have formatted the response as an Xml document on the server-side, but that would require parsing to be done at the JavaScript end. By formatting the response as JavaScript code, we can use the mighty eval() function to set all the options in one fell swoop (line 270)! Here is one of the shorter responses of Model options:

options[options.length] = new Option("METRO", "133");
options[options.length] = new Option("STORM", "134");

Again a with statement is used (line 263). It serves a specific purpose here as the server script does not include the list identifier. This was done in order to save bandwidth. Remember that each and every call to the server creates network traffic, so those two little words can amount to over 10% reduction! There is some code in the fillListCallBack() function for a Safari bug in Windows, which we'll get to after the following code snippet:


250var fillListCallBack = function( xmlhttp, STATUS )
251{
252 var list = this;
253
254 if ( xmlhttp.status == STATUS._OK )
255 {
256 //confirm that there are linked items
257 if ( !xmlhttp.responseText || xmlhttp.responseText == "N/A" )
258 {
259 list.options[0] = new Option("N/A", "");
260 }
261 else
262 {
263 with ( list )
264 {
265 //Safari 3 bug workaround code
266
267
268 if ( window.BLANK_ENTRY ) options[0] = new Option(window.PROMPT_TEXT, "");
269
270 eval(xmlhttp.responseText);
271
272 //more Safari 3 bug workaround code
273
274 }


Now it's time to take closer look at the code for handling a pesky Safari bug that I came across on Windows 2000. Once you've opened a listbox, any additional options than weren't there originally show up as solid black! They are present, but you can't see them. To get around this, I had to set the style before and after populating the list (lines 266,273). I got the idea because I noticed that it didn't occur with multi-selects. Besides this problem, there were also issues with the onchange event being fired instead of onblur!

Here is the code inside the with statement for the Safari bug fix:


265//Safari 3 bug workaround
266if (window.IS_SAFARI) list.style.display='none';
267
268if ( window.BLANK_ENTRY ) options[0] = new Option(window.PROMPT_TEXT, "");
269
270eval(xmlhttp.responseText);
271
272//Safari 3 bug workaround
273if (window.IS_SAFARI) style.display='block';

view plain | print | ?

After populating the list, there's a call to the setDefaultIndex() in the base list (line 277). This is the only global constant that can't be set with the others because setDefaultIndex() (lines 277,112) checks that value against the number of options in the list. Hence we have to wait until the base list has been populated. The fireOnChangeEvent() function is called so that the next list's options will be set accordingly (line 279). If you recall, we called the bindOnChangeFunctionsToListElement() function in initLists(). That binded the setSublist() function to the onchange event, which saves us from having to call setSubList() directly.


275//this initialization code has to run here
276//because ajax is running asynchronously.
277window.BASE_LIST.setDefaultIndex( list.options.length );
278
279fireOnChangeEvent.call(list);
280}

view plain | print | ?

Any status other that 200 is an indication that the items couldn't be retrieved due to an error. To keep things simple, the list is populated with one entry of Ajax Error (line 284) and an error message is displayed (line 284). The list variable is set to null at the end of the function to avoid memory leaks (line 289).


281 }
282 else
283 {
284 list.options[0] = new Option("Ajax Error", "");
285
286 alert( "The XMLHttpRequest object returned a status of '" + xmlhttp.status
287 + ": " + xmlhttp.statusText + "'." );
288 }
289 list = null;
290}

Universally Related Popup Menus AJAX Edition: Part 3

The XmlHttpObjectManager Object

The XmlHttpObjectManager is a private member variable of the callServer() function (line 141). It's a static class, so we never create an instance of it. Rather, it just houses some variables and methods that relate to the XmlHttpRequest object. Its main purpose is to act as a wrapper to the XmlHttpRequest object because we only create one that we reuse every time we want to call the server. The real object is stored in the private XmlHttpObject variable (line 143). To get a reference to it, we call getXmlHttpInstance(), which is one of two public functions exposed via the interface object (line 144). The interface object uses JavaScript Object Notation (JSON) which is a standardized way of denoting an object literal, much the same way that XML is used to describe data. Hence, its syntax is quite a bit different from regular JavaScript The entire object is located between two curly braces {}. Each public property is notated by its name, followed by a colon (:) and the value. The properties are then separated by commas.

Now let's take a look at our interface's methods and properties.

The getXmlHttpInstance() method (line 146) is what I like to call a "mutating function". Here's why. The first time it's called, it returns a new XmlHttpObject (line 150) but it also sets itself to a new function that returns the private xmlHttpObject variable (line 148). Oddly, this has no effect on the execution of the function because it's already on the stack, so the changes don't take effect until after the current one finishes executing. Every successive call afterwards receives the same xmlHttpObject variable.

The state_change() method is the second one that is accessible via the XmlHttpObjectManager's public interface (line 153). Its job is to check the xmlhttp.readyState property every time the xmlhttp.onreadystate property changes. We have to check the readyState property to make sure the object has finished bringing back all the data from the server (line 155). There are a total of five possible states but we're testing against a value of 4. Here's the list of ready state values and their meaning:

  1. The request is uninitialized (before you've called open()).
  2. The request is set up, but not sent (before you've called send()).
  3. The request was sent and is in process (you can usually get content headers from the response at this point).
  4. The request is in process; often some partial data is available from the response, but the server isn't finished with its response.
  5. The response is complete; you can get the server's response and use it.

Once we hit the last loading state, we can run the call back function (line 159). Any errors that occur in the callback function will be trapped by the try/catch block so that a message can be displayed (line 163). The list is again passed along in the this pointer.

The following properties are also accessible via the interface object: RUN (line 171), READY_STATE (line 173), and STATUS (line 175). They are JSON objects containing named constants. Here's the first part of the XmlHttpObjectManager object, including its private interface variable (we'll see how it's made public in a moment)

141var XmlHttpObjectManager = (function()
142{
143 var xmlHttpObject = null;
144 var interface =
145 {
146 getXmlHttpInstance:function()
147 {
148 interface.getXmlHttpInstance = function() { return xmlHttpObject; };
149
150 return new XmlHttpObject();
151 }
152 ,
153 state_change:function(xmlhttp, callBackFunction, READY_STATE, STATUS)
154 {
155 if (xmlhttp.readyState == READY_STATE._DONE_LOADING)
156 {
157 try
158 {
159 callBackFunction.call(this, xmlhttp, STATUS);
160 }
161 catch (e)
162 {
163 alert( "An error occurred in the AJAX call back method:"
164 + "\nNumber:\t" + e.number
165 + "\nName:\t" + e.name
166 + "\nMessage:\t" + e.message );
167 }
168 }
169 } //public constants
170 ,
171 RUN: { _ASYNCHRONOUSLY:true }
172 ,
173 READY_STATE: { _DONE_LOADING:4 }
174 ,
175 STATUS: { _OK:200 }
176 };

Creating an AJAX-Enabled Calendar Control

ntroduction
Go to any travel or event booking website and you'll find the same user interface for collecting date information: the Calendar. Providing such an interface in an ASP.NET application is a breeze, thanks to the built-in Calendar Web control. There are two downsides to ASP.NET's Calendar control: first, it is not very useful when selecting dates far into the future or past, as you can only navigate to the next or previous month; and, second, the Calendar does not use AJAX techniques, so each click, be it selecting a date or moving to the next or previous month, requires a full postback.

Mehmet Genc addressed this first shortcoming in Extending the Calendar Control's Date Navigation by showing how to add month and year drop-down lists. But Mehmet's article was written in 2004 and since then AJAX-enabled websites have become all the rage. I decided it was high time to update Mehmet's custom Calendar control to support AJAX. Specifically, I implemented the AJAX-enabled Calendar control as a User Control. The User Control renders a TextBox control that, when clicked, displays a Calendar control from which the user can select the date. Like with Mehmet's Calendar, users can quickly jump to a particular month or year by using two drop-down lists. And best of all, the user experience is very responsive.

The AJAX-enabled Calendar control in action.

Read on to learn more!

- continued -

Get the SOA Development Survival Guide
Get started understanding the benefits and tools needed for service-oriented architecture development. Includes whitepapers, Webcasts, and articles. » IBM Rational Systems Development Solution eKit
As systems increase in complexity, communication between systems and teams becomes more and more difficult. Read the "Model Driven Systems Development" whitepaper to see how to improve product quality. Also included are more whitepapers, customer examples, tutorials, informative Webcasts, and best practices for designing, building, and managing systems. » Webcast: Succeed with Asset-Based Development: Introducing Rational Asset Manager
Learn how IBM Rational Asset Manager enables organizations to identify, manage and govern the design, development and consumption of software assets, including services, as part of an SOA initiative. Learn about the key challenges of asset-based development and how IBM Rational Asset Manager can help provide the solutions. » Download: IBM Rational Rose Technical Developer
IBM Rational Rose Technical Developer is a robust Model-Driven Development (MDD) solution, expressly created to meet the challenges of complex systems development. Based on UML, Rational Rose Technical Developer provides a highly-automated and reliable solution to the unique problems of concurrency and distribution. »

First Things First: Ensuring Your Environment Supports ASP.NET AJAX
To use this AJAX-enabled Calendar control, make sure your development environment supports the ASP.NET AJAX framework. If you are using Visual Studio 2008, then this framework is already present. If, however, you are using Visual Studio 2005, then you need to download and install the ASP.NET AJAX framework from Microsoft's site, http://www.asp.net/ajax/. For more information on this process, refer to Scott Mitchell's article, AJAX Basics and Getting Started with Microsoft's ASP.NET AJAX Framework.

My AJAX-enabled Calendar control uses the UpdatePanel and PopupControlExtender controls. While the UpdatePanel is part of the framework's "Essential Components," the PopupControlExtender is part of the ASP.NET AJAX Control Toolkit, which is a separate download (even for Visual Studio 2008). If you check out the Control Toolkit samples you'll notice that there's an AJAX Calendar control in the Toolkit. I built my own AJAX-enabled Calendar control instead of using the one in the Control Toolkit because I wanted to add the month/year drop-down lists. Also, there have been a variety of display bugs with the Calendar control (see the AJAX Control Toolkit work item list). I invite you to try out mine and the AJAX Control Toolkit's Calendar and use the one that's best suited for your needs.

Getting Started with My AJAX-Enabled Calendar Control
The complete code for this User Control, along with a sample web page, is available at the end of this article. You should be able to open the folder as a website in either Visual Studio 2005 or Visual Studio 2008.

The Calendar is implemented in the CoolCalendar.ascx file as a User Control. Take a moment to examine the markup in this page. You'll find the following key controls:

  1. The DateTextFrom TextBox
  2. A RequiredFieldValidator named DateTextFromRequired
  3. A Panel control
  4. An UpdatePanel control
  5. The month and year DropDownList controls
  6. The Calendar control
  7. An AJAX PopupControlExtender control

Note the onfocus="javascript:this.blur();". This bit of client-side script ensures that whenever the user clicks on the DateTextFrom TextBox, focus is immediately taken away from the control. The idea here - as we'll see shortly - is that whenever the user focuses on the TextBox it is immediately taken away and the Calendar control is displayed. This forces the user to select a date from the calendar. If you remove the onfocus script, the user could enter the date into the TextBox via the keyboard. I find this option undesirable due to the possibility of user entry errors.

The RequiredFieldValidator (item 2) is used to optionally ensure that a date value has been supplied. The User Control contains a Boolean public property named DateTextRequired. Setting this value to True enables the RequiredFieldValidator; setting it to False disables it. By default, the RequiredFieldValidator is enabled.

The AJAX PopupControlExtender control pops up a particular Panel on the page in response to a certain client-side action. The Panel control (item 3) defines the region that is popped up, and includes the UpdatePanel (item 4), the month/year DropDownLists (item 5), and the Calendar control (item 6).

The final piece in the markup page is the PopupControlExtender control (item 7) and is configured to display the Panel (item 3) whenever the DateTextFrom TextBox receives focus. This behavior is dictated entirely through the PopupControlExtender control's properties, there's no need to write any JavaScript or code!

An Introduction to JavaScript Object Notation (JSON)

JavaScript Object Notation, or JSON for short, is a lightweight data-interchange format which may prove to be a viable alternative to XML for IT developers. The purpose of a data-interchange format is to transfer information between potentially incompatible technologies. For example, the sender may be a Java application running on Unix and the receiver could be a Visual Basic program running on Windows. In this instance one would require a standardized format to send the data because the applications could not communicate directly with each other. Even if they could, using a protocol such as TCP/IP or FTP, the data structures would have be to be defined somewhere. That's where the data-interchange format comes in. When XML came onto the scene in the late nineties, it was hailed as a godsend by many business managers because it was intuitive to look at and based on the well-known HTML language. Developers, on the other hand, were less impressed. It turns out that parsing XML was not nearly as simple as one might think! Today, despite the proliferation of programming libraries to perform many common tasks, from extracting node attributes to searching for specific data in the hierarchy, programmers are still faced with a learning curve when having to deal with the tags. Web developers faced a similar situation in the early days of dynamic HTML content. Eventually, frameworks such as Struts and Spring provided a way to handle "boiler plate" tag generation. Now, JSON offers developers a more familiar means of structuring data.

Change is in the Air

While XML was meant to transfer data between applications, its format was derived from Standard Generalized Markup Language (SGML), which bears a closer resemblance to HTML than to any programming language. One could say it's equally cumbersome in any language! JSON doesn't share this detriment since it's based on programming conventions found in the C family of languages, including C, C++, C#, Java, JavaScript, Perl, Python and others. It's also more succinct than tags-based XML. As we will soon see, the fact that it's a subset of JavaScript is advantageous with Web apps, where a lot of data exchange takes place. Moreover, JSON is especially well suited for AJAX calls.

Language Overview

JSON's raison d'ĂȘtre is to encapsulate an object in a meaningful and standardized way that can be easily understood by humans, as well as being rapidly parsed by machines. This is accomplished by structuring an object as literal representation using common programming syntax characters. Programmers have little difficulty in wrapping their heads around literals because they've been around for a long time. For instance, we almost instinctively know that the following code refers to an integer: "var intType = 3;" whereas this is a String: "var stringType = '3';" (technically a String within a String here!). Most languages can also represent more complex data types like arrays using literals such as: "var arrayLiteral = [1, '2', 3.34, 'dog'];" Notice that the array may contain several data types as well, depending on the language.

Let's get into some specifics regarding the JSON standard.

JSON objects are delimited by curly braces {}. Your initial thought might be that this would confuse the JavaScript interpreter because the curly braces are also used to enclose function bodies. In actuality, operator overloading is a long-standing practice and goes at least as far back to C++. Context is everything, and in each case, there are clues to help identify one from the other. JSON's signature is the key-value pairs used to represent the data, which are each separated by a colon (:):

Syntax String Example or Numeric Example
"key": value "name": "Fred" "price": 55.99

In the example above, the word "Fred" is enclosed by quotes to denote that it's a String data type, whereas a numeric value does not, as in any programming language. Keys and String values should always be enclosed by double quotes. In my last article, URPM's:AJAX Edition, I made the mistake of not enclosing the keys in quotes. It would seem I'm not alone. Jesse Skinner wrote about this very subject in his article entitled "JSON is not just Object Notation" (see references at the end of the article for a link to the site). It would seem that JSON is a lot pickier about format than JavaScript, as the latter will happily allow you to use single quotes or omit quotes around the keys, as I did. The moral of the story is this: while the JavaScript language provides some flexibility in the construction of Object literals, you may run into issues should you opt to use ready-made JSON parsers. I say may because I didn't encounter any problems when I tested some parsers on my class. Nonetheless, it costs nothing to use the stricter JSON standard.

JSON supports several data types including:

  • number (integer, real, or floating point)
  • String (double-quoted Unicode with backslash escapement)
  • boolean (true and false)
  • Array (an ordered sequence of values, comma-separated and enclosed in square brackets)
  • Object (collection of key/value pairs, comma-separated and enclosed in curly brackets)
  • null

Taking JSON for a Test Drive

So what can you do with it? Earlier, I mentioned that JSON is especially well suited for AJAX calls. The reason is that JavaScript understands the JSON syntax without requiring any parsing whatsoever! That's the advantage of using a programming-based format.

A common use for JSON is to pass objects between the Web page and a server-side application. In the following JSP example, a simple JSON object is constructed using the JSON Object utility class from the JSON.org home page.

An Introduction to JavaScript Object Notation (JSON)

JavaScript Object Notation, or JSON for short, is a lightweight data-interchange format which may prove to be a viable alternative to XML for IT developers. The purpose of a data-interchange format is to transfer information between potentially incompatible technologies. For example, the sender may be a Java application running on Unix and the receiver could be a Visual Basic program running on Windows. In this instance one would require a standardized format to send the data because the applications could not communicate directly with each other. Even if they could, using a protocol such as TCP/IP or FTP, the data structures would have be to be defined somewhere. That's where the data-interchange format comes in. When XML came onto the scene in the late nineties, it was hailed as a godsend by many business managers because it was intuitive to look at and based on the well-known HTML language. Developers, on the other hand, were less impressed. It turns out that parsing XML was not nearly as simple as one might think! Today, despite the proliferation of programming libraries to perform many common tasks, from extracting node attributes to searching for specific data in the hierarchy, programmers are still faced with a learning curve when having to deal with the tags. Web developers faced a similar situation in the early days of dynamic HTML content. Eventually, frameworks such as Struts and Spring provided a way to handle "boiler plate" tag generation. Now, JSON offers developers a more familiar means of structuring data.

Change is in the Air

While XML was meant to transfer data between applications, its format was derived from Standard Generalized Markup Language (SGML), which bears a closer resemblance to HTML than to any programming language. One could say it's equally cumbersome in any language! JSON doesn't share this detriment since it's based on programming conventions found in the C family of languages, including C, C++, C#, Java, JavaScript, Perl, Python and others. It's also more succinct than tags-based XML. As we will soon see, the fact that it's a subset of JavaScript is advantageous with Web apps, where a lot of data exchange takes place. Moreover, JSON is especially well suited for AJAX calls.

Language Overview

JSON's raison d'ĂȘtre is to encapsulate an object in a meaningful and standardized way that can be easily understood by humans, as well as being rapidly parsed by machines. This is accomplished by structuring an object as literal representation using common programming syntax characters. Programmers have little difficulty in wrapping their heads around literals because they've been around for a long time. For instance, we almost instinctively know that the following code refers to an integer: "var intType = 3;" whereas this is a String: "var stringType = '3';" (technically a String within a String here!). Most languages can also represent more complex data types like arrays using literals such as: "var arrayLiteral = [1, '2', 3.34, 'dog'];" Notice that the array may contain several data types as well, depending on the language.

Let's get into some specifics regarding the JSON standard.

JSON objects are delimited by curly braces {}. Your initial thought might be that this would confuse the JavaScript interpreter because the curly braces are also used to enclose function bodies. In actuality, operator overloading is a long-standing practice and goes at least as far back to C++. Context is everything, and in each case, there are clues to help identify one from the other. JSON's signature is the key-value pairs used to represent the data, which are each separated by a colon (:):

Syntax String Example or Numeric Example
"key": value "name": "Fred" "price": 55.99

In the example above, the word "Fred" is enclosed by quotes to denote that it's a String data type, whereas a numeric value does not, as in any programming language. Keys and String values should always be enclosed by double quotes. In my last article, URPM's:AJAX Edition, I made the mistake of not enclosing the keys in quotes. It would seem I'm not alone. Jesse Skinner wrote about this very subject in his article entitled "JSON is not just Object Notation" (see references at the end of the article for a link to the site). It would seem that JSON is a lot pickier about format than JavaScript, as the latter will happily allow you to use single quotes or omit quotes around the keys, as I did. The moral of the story is this: while the JavaScript language provides some flexibility in the construction of Object literals, you may run into issues should you opt to use ready-made JSON parsers. I say may because I didn't encounter any problems when I tested some parsers on my class. Nonetheless, it costs nothing to use the stricter JSON standard.

JSON supports several data types including:

  • number (integer, real, or floating point)
  • String (double-quoted Unicode with backslash escapement)
  • boolean (true and false)
  • Array (an ordered sequence of values, comma-separated and enclosed in square brackets)
  • Object (collection of key/value pairs, comma-separated and enclosed in curly brackets)
  • null

Taking JSON for a Test Drive

So what can you do with it? Earlier, I mentioned that JSON is especially well suited for AJAX calls. The reason is that JavaScript understands the JSON syntax without requiring any parsing whatsoever! That's the advantage of using a programming-based format.

A common use for JSON is to pass objects between the Web page and a server-side application. In the following JSP example, a simple JSON object is constructed using the JSON Object utility class from the JSON.org home page.

Transparency in Ajax Applications

Myth: Ajax applications are black box systems, just like regular Web applications.

If you are like most people, when you use a microwave oven, you have no idea how it actually works. You only know that if you put food in and turn the oven on, the food will get hot in a few minutes. By contrast, a toaster is fairly easy to understand. When you're using a toaster, you can just look inside the slots to see the elements getting hot and toasting the bread.

A traditional Web application is like a microwave oven. Most users don't know how Web applications work—and don't even care to know how they work. Furthermore, most users have no way to find out how a given application works even if they did care. Beyond the fundamentals, such as use of HTTP as a request protocol, there is no guaranteed way to determine the inner workings of a Web site. By contrast, an Ajax Web application is more like a toaster. While the average user may not be aware that the logic of the Ajax application is more exposed than that of the standard Web page, it is a simple matter for an advanced user (or an attacker) to "look inside the toaster slots" and gain knowledge about the internal workings of the application.

Black Boxes Versus White Boxes

Web applications (and microwave ovens) are examples of black box systems. From the user's perspective, input goes into the system, and then output comes out of the system, as illustrated in Figure 6-1. The application logic that processes the input and returns the output is abstracted from the user and is invisible to him.

Figure 6-1 The inner workings of a black box system are unknown to the user.
Figure 6-1 The inner workings of a black box system are unknown to the user.

For example, consider a weather forecast Web site. A user enters his ZIP code into the application, and the application then tells him if the forecast calls for rain or sun. But how did the application gather that data? It may be that the application performs real-time analysis of current weather radar readings, or it may be that every morning a programmer watches the local television forecast and copies that into the system. Because the end user does not have access to the source code of the application, there is really no way for him to know.

Security Note

There are, in fact, some situations in which an end user may be able to obtain the application's source code. These situations mostly arise from improper configuration of the Web server or insecure source code control techniques, such as storing backup files on production systems. Please review Chapter 3, "Web Attacks," for more information on these types of vulnerabilities.

White box systems behave in the opposite manner. Input goes into the system and output comes out of the system as before, but in this case the internal mechanisms (in the form of source code) are visible to the user (see Figure 6-2).

Any interpreted script-based application, such as a batch file, macro, or (more to the point) a JavaScript application, can be considered a white box system. As we discussed in the previous chapter, JavaScript must be sent from the server to the client in its original, unencrypted source code form. It is a simple matter for a user to open this source code and see exactly what the application is doing.

Figure 6-2 The user can see the inner workings of a white box system.
Figure 6-2 The user can see the inner workings of a white box system.

It is true that Ajax applications are not completely white box systems; there is still a large portion of the application that executes on the server. However, they are much more transparent than traditional Web applications, and this transparency provides opportunities for hackers, as we will demonstrate over the course of the chapter.

It is possible to obfuscate JavaScript, but this is different than encryption. Encrypted code is impossible to read until the correct key is used to decrypt it, at which point it is readable by anyone. Encrypted code cannot be executed until it is decrypted. On the other hand, obfuscated code is still executable as-is. All the obfuscation process accomplishes is to make the code more difficult to read by a human. The key phrases here are that obfuscation makes code "more difficult" for a human to read, while encryption makes it "impossible," or at least virtually impossible. Someone with enough time and patience could still reverse-engineer the obfuscated code. As we saw in Chapter 2, "The Heist," Eve created a program to de-obfuscate JavaScript. In actuality, the authors created this tool, and it only took a few days. For this reason, obfuscation should be considered more of a speed bump than a roadblock for a hacker: It may slow a determined attacker down but it will not stop her.

Figure 6-3 A standard, non-Ajax weather forecasting Web site
Figure 6-3 A standard, non-Ajax weather forecasting Web site

In general, white box systems are easier to attack than black box systems because their source code is more transparent. Remember that attackers thrive on information. A large percentage of the time a hacker spends attacking a Web site is not actually spent sending malicious requests, but rather analyzing it to determine how it works. If the application freely provides details of its implementation, this task is greatly simplified. Let's continue the weather forecasting Web site example and evaluate it from an application logic transparency point of view.

Example: MyLocalWeatherForecast.Com

First, let's look at a standard, non-Ajax version of MyLocalWeatherForecast.com (see Figure 6-3).

Implementing AJAX Components in the JWL Framework

Introduction

In 2005, IBM© introduced JWL (JavaScript-based Widget Library); it enhances JSP and HTML pages with rich set of inputs, output, and navigation components. If you are not familiar with JWL and would like to learn more about it, you can reference the following articles under the IBM Developer Works web site to give you an idea of what JWL can offer:

  1. Developing an application with the JWL DataGrid using Rational Application Developer: http://www.ibm.com/developerworks/rational/library/06/0117_gallagher/
  2. The JWL Tree component: http://www.ibm.com/developerworks/rational/library/05/1220_coffey/

With the release of RAD 6.0 (Rational Application Developer), IBM has introduced a much improved support systemfor JWL AJAX components. In this article, you will find out about these components and go through three how-to exercises. You will also find sample source code that you can import into your workspace.

Definitions

An AJAX tag must be defined as a child tag of any of the JWL panel tags. The AJAX tag defines an alternate content for the panel. An AJAX tag makes a server request when the panel containing the AJAX tag is invoked. The server processes the request and returns control to the panel.

9 Javascript(s) you better not miss

This tutorial is aimed at those who have a working knowledge of Javascript. So the examples are not explained in great detail. Only the important parts are highlighted.

Presented are 9 Javascript examples that have been found very useful while designing professional websites. There are many ways to implement these examples here. The code presented here is neither the shortest nor the most efficient. But it does work satisfactorily.

JavaScript Tutorial

JavaScript is the scripting language of the Web!

In this JavaScript tutorial you will learn how to write JavaScripts and insert them into your HTML documents, and how to make your pages more dynamic and interactive.

Javascript - Age Finder

Not only will this script tell you how many days, hours, minutes, and seconds old you are, it tells you how long until your next birthday!

Javascript History

JavaScript is Netscape's cross-platform, object-based scripting language.

Each version of Navigator supports a different version of JavaScript. The link shows the table which lists the JavaScript version supported by different Navigator versions. Versions of Navigator prior to 2.0 do not support JavaScript.

Netscape's JavaScript ?

In the complex world of web development, arriving at good, open standards - even for a language as solid as JavaScript - can be a process as mysterious and complex as atomic particles whizzing and mutating during brief moments in time.

Hiding/Encrypting your HTML and JavaScript Source Code

These scripts are intended to explain how to "hide" HTML and/or javascript from other people who view your page's source code.

It is not foolproof, but it does make it more difficult to read and understand the source code. Due to the nature of how these scripts work, the explanation may seem complicated and drawn out, but be patient and it should make sense once you gain a little experience with them.

You don't really have to know the ins-and-outs of these scripts, but it does help you understand how and why they work.

Hiding/Encrypting your HTML and JavaScript Source Code

These scripts are intended to explain how to "hide" HTML and/or javascript from other people who view your page's source code.

It is not foolproof, but it does make it more difficult to read and understand the source code. Due to the nature of how these scripts work, the explanation may seem complicated and drawn out, but be patient and it should make sense once you gain a little experience with them.

You don't really have to know the ins-and-outs of these scripts, but it does help you understand how and why they work.