Skip to main content

Building Ajax-enabled JSP TagLib controls, Part 3: Update panel and popup dialog box controls

Using JSP TagLib, JSON, and Ajax

Brian J Stewart (BrianJStewart@AquaDataTech.com), Principal Consultant, Aqua Data Technologies, Inc.
Photo of Brian Stewart
Brian J. Stewart is currently a principal consultant at Aqua Data Technologies, a company that he founded to focus on content management, XML technologies, and enterprise client/server and Web systems. He architects and develops enterprise solutions based on the J2EE and .NET platforms.

Summary:  Build Asynchronous JavaScript + XML (Ajax) controls that can be used in business-line applications. These configurable JavaServer Pages (JSP) TagLib-based controls leverage JavaScript Object Notation (JSON), JavaScript scripting language, and Cascading Style Sheets (CSS). Because they are standard JSP TagLib controls, find out how you can easily drop them into any application to provide more intuitive and responsive user interfaces.

View more content in this series

Date:  07 Apr 2009
Level:  Intermediate PDF:  A4 and Letter (687KB | 40 pages)Get Adobe® Reader®
Activity:  6610 views
Comments:  

Introduction

Two key technologies enable next-generation Web sites: Asynchronous JavaScript + XML (Ajax) and JavaScript Serialized Object Notation (JSON). Business-line applications can benefit from these technologies to provide more intuitive and responsive user interfaces. This article describes how to add Ajax and JSON to Java™ Platform Enterprise Edition (Java EE) Web applications by building reusable JavaServer Pages (JSP) TagLib controls based on Ajax.

Within this article, learn how to build an update panel control that dynamically retrieves content asynchronously from the server, based on user events. For example, content can be retrieved when a user clicks a field, enters a value in a field, or selects a value in a drop-down selection list. I also describe how to build a pop-up dialog control that asynchronously retrieves the dialog content from the server when the dialog is displayed. For example, the dialog can be displayed when a user hovers over an item, clicks a button, or selects a value in a drop-down selection list.


About this series

This article is part of a multi-part series on developing a suite of Ajax-enabled controls for J2EE applications. The controls are built using JSP TagLib controls and leverage JSON, Servlet, and JavaScript technologies.


About this article

This article describes how to build the following controls:

  • Update panel—Asynchronously retrieves content to provide a dynamic user interface. The control provides configurable parameters for Cascading Style Sheets (CSS) formatting while content is being retrieved as well as post retrieval of content. It also provides standard event handlers (that is, before content is loaded, after the content is loaded) to allow for further customizations.
  • Pop-up dialog—Provides a window that retrieves content asynchronously when the dialog is first shown. This provides a responsive user interface by retrieving content only upon demand. The control provides optional configurable parameters for CSS formatting, a dialog title, a close button located in top right corner of the window (similar to a standard Windows® dialog), and the dialog size and location.

Both of these JSP TagLib controls encapsulate all asynchronous communication, JavaScript code, CSS formatting, and Hypertext Markup Language (HTML) generation.


Technical overview

This article builds upon the design principles and code outlined in the first two articles of this series (see Resources). It introduces techniques for adding event handlers to a custom control, as well as advanced techniques for configuring the control's presentation and behavior.

As in the previous articles in the series, the primary design goals of the JSP Ajax-enabled control suite developed in this article are as follows:

  • Provide easy integration with existing Web applications—the controls should encapsulate all logic and JavaScript code to simplify the deployment process
  • Allow easy configuration
  • Minimize data- and page-size overhead
  • Leverage the CSS and HTML standards
  • Provide cross-browser support (Windows Internet Explorer, Mozilla Firefox)
  • Leverage common design patterns/best practices to improve code maintainability

Similar to the first two articles in this series, the <ajax:page/> control is used to encapsulate common JavaScript functions to minimize data and overhead. Web standards, including CSS and HTML, are used for cross-browser support. The JavaScript code, HTML, and CSS emitted by the controls are tested against Windows Internet Explorer 7.x and Mozilla Firefox 2.x/3.x.

Class model

The example in this article consists of the Data Abstract Layer (DAL), Data Transfer Objects (DTO), the Business Logic Layer (BLL), the Presentation Layer, and supporting helper classes. The article also uses the LocationDataService DAL class from the first article in the series. This class returns collections of LocationDTO DTO instances. No additional DAL or DTO classes are needed in this article. The BLL consists of value providers that provide data to the Ajax-enabled controls, and server-side validators that provide server validation for HTML form data.

This article uses the LocationService class and the JdbcQuery helper class from the first article in the series. No other utility classes are required.

Even though you are only building two controls, you need to create several tags to make those controls robust, flexible, and configurable. Start with the update panel control, which is shown in Figure 1. This is the implementation class for the <ajax:updatepanel/> tag.


Figure 1. Unified Modeling Language (UML) class diagram of UpdatePanelTag
Window showing the UpdatePanelTag class

The update panel control supports optional arguments that are passed along with the asynchronous request for the update panel. The implementation class for the <ajax:panelargument/> tag is shown in Figure 2.


Figure 2. UML class diagram of PanelArgumentTag
Window showing the         PanelArgumentTag class

The pop-up control is more complicated and uses several tags. The key tag is <ajax:popupdialog/>. The implementation class for this tag is shown in Figure 3.


Figure 3. UML class diagram of PopupDialogTag
Window showing the PopupDialogTag class

The <ajax:popupdialog/> can contain a <ajax:popuparguments/> tag for the arguments that are passed along with the asynchronous request for the dialog content. The implementation classes for the <ajax:popuparguments/> and <ajax:popupargument/> tags are shown in Figure 4.


Figure 4. UML class diagram of PopupDialogButtonContainerTag and PopupDialogButtonTag
Window showing the PopupDialogButtonContainerTag and PopupDialogButtonTag classes

The <ajax:popupdialog/> can contain a <ajax:popupbuttoncontainer/> tag for the buttons displayed for the pop-up dialog. The implementation classes for the <ajax:popupbuttoncontainer/> and <ajax:popupbutton/> tags are shown in Figure 5.


Figure 5. UML class diagram of PopupDialogArgumentContainerTag and PopupDialogArgumentTag
Window showing the PopupDialogArgumentContainerTag and PopupDialogArgumentTag classes


Build the update panel JSP TagLib control

Traditionally, Web developers needed to refresh the entire Web page even if only a portion of the page changed as a result of a user action, such as when a user enters a value in a field, selects a value in a drop-down list, checks a check box, or clicks on a control. The content and business requirements differ, but most business-line applications have dynamic content that changes based on user events.

The primary goal of the <ajax:updatepanel/> control is to build a reusable control that addresses this common scenario and lets you easily have only the portions of the page that change be updated dynamically. The control handles all communication and presentation functions, while leaving the content to the Web developers. The control provides the ability to optionally pass arguments, such as form field values, when the asynchronous request is made. To provide maximum flexibility, the update panel should be easily displayed or hidden without any knowledge of the internals of the update panel.

Figure 6 shows how the update panel looks while the panel is being updated.


Figure 6. Update panel while content is being retrieved
Window showing the drop-down list        for the state and a city prefix  while content is being retrieved

When the server responds to the asynchronous request, the update panel content is updated. Figure 7 shows how the update panel looks after the asynchronous content is received and displayed.


Figure 7. Update panel after content has been retrieved
Window showing zip code, state,        city, and county after after content has been retrieved

Technical overview of control

When the page is first rendered, a DIV container is rendered for the dialog box. Initially, the update panel element is empty. When the event is triggered to show the update panel, the content is asynchronously retrieved from the server. The update panel is then updated with the dynamic content.

The <ajax:updatepanel/> provides the configurable options described in Table 1.


Table 1. Configurable options for the update panel
OptionDescription
idControl ID
urlURL to retrieve content for the update panel
updatemessageMessage to display while content is being asynchronously retrieved
loadingcssCSS class name to be applied while the content is being loaded (for example, "Please wait..." message)
cssclassCSS class name to be applied after content is loaded
onclearOptional name of JavaScript function to invoke before the update panel is cleared
onclearedOptional name of JavaScript function to invoke after the update panel is cleared
onloadOptional name of JavaScript function to invoke before the update panel is loaded
onloadedOptional name of JavaScript function to invoke after the update panel is loaded

Use case scenarios for event handlers

The event handlers are a powerful feature of this control. Although the code to render and invoke the hooks is fairly straightforward, they provide a mechanism that makes the control highly flexible and reusable.

You can use the onload event handler to test that specific fields (on which the update panel depends) are populated. A message can be displayed to the user if the required fields aren't populated and false can be returned to cancel the update to the panel. Another use of this function is to populate any hidden INPUT elements based on other form field values. For example, within the event handler, calculation can be performed or strings concatenated for data sent along with the asynchronous request.

You can use the onloaded event handler to process other form fields based on the server response. For example, perhaps certain fields should be disabled, hidden, or populated based on the server response.

You can use the onclear event handler to check certain criteria before clearing the update panel. For example, perhaps the user should be prompted to save the data before clearing the update panel.

You can use the oncleared event handler to clear any other form fields or reset the form. If the update panel is used in a reporting solution, you can place a Clear button on the form. The button can invoke the hide panel function and, upon clearing the panel, clear the report criteria.

Building the functions to display or hide the update panel

The <ajax:page/> renders two key functions for the <ajax:updatepanel/> control:

  • showUpdatePanel—Shows the update panel by invoking the corresponding onShow event handler
  • hideUpdatePanel—Hide the update panel by invoking the corresponding onHide event handler

These functions are nearly identical and are nothing more than wrappers around the show and hide dialog functions for the dialog-specific instances. The name of the dialog is passed into these functions via the controlName argument. The onShow function name is dynamically built by concatenating the name of the dialog and _onShow. The panel-specific function, which is rendered in the <ajax:updatepanel/> tag is then invoked using the JavaScript statement window['functionName'](). Listing 1 shows the showUpdatePanel function.


Listing 1. showUpdatePanel JavaScript function
function showUpdatePanel(controlName) {
	var functionName = controlName + '_onShow';
	window[functionName]();
}

By using this approach, the details about how the dialog is displayed and the content is asynchronously retrieved are abstracted from the Web application developer who is using the <ajax:updatepanel/> control. You simply need to call the showUpdatePanel or hideUpdatePanel JavaScript functions, passing the name of the panel to show or hide.

Showing the update panel

The next step is to build the panel-specific function that is called by the showUpdatePanel JavaScript function. This function is rendered by the <ajax:updatepanel/> tag and is responsible for:

  • Invoking any of the event handlers specified in the onclear, oncleared, onload, and onloaded tag attributes
  • Making the asynchronous request to retrieve the update panel content
  • Displaying the update panel using the options specified in the attributes, such as cssclass, loadingcss, and updatemessage

Start with the dialogName_onShow function, which is shown in Listing 2.


Listing 2. dialogName_onShow JavaScript function
function cityPanel_onShow() { 
	// Invoke the onload event. 
	// If true is not return by the event handler, 
	// cancel the update to the panel
	if (!window['onCityPanelLoad']()) { 
		return; 
	} 
	
	// Get the dialog element
	var controlName = 'cityPanel_Container';	
	var curControl= document.getElementById(controlName);
	
	// Update status message to the value specified in the 
	// updatemessage attribute
	if (curControl != null) {
		curControl.innerHTML = 'Retrieving cities...';
		curControl.className = 'loadingpanel';
	}
	
	// Url for retrieving dialog content (specified in url attribute)
	var targetUrl = '/ajaxcontrols3/fragments/cityList.jsp';
	
	// Build the POST data sent for the asynchronous request to 
	// retrieve the update panel content
	// The arguments specified in the contained panelargument tags
	// are dynamically added to the post data
	var postData = 'panelId=cityPanel' + '&state=' + getFormValue('state') 
		+ '&cityPrefix=' + getFormValue('cityPrefix');		
	
	// Initialize XmlHttpRequest object
	initializeXmlHttpRequest();
	if (req!=null) {
		req.onreadystatechange=cityPanel_onServerResponse;
		// Set window status
		window.status='Retrieving cities...';
		
		// Open server request
		req.open('POST',targetUrl,true);
		req.setRequestHeader("Content-type", 
			"application/x-www-form-urlencoded");
		req.setRequestHeader("Content-length", 
			postData.length);

		// Send data
		req.send(postData);		
	}
}

The optional event handlers onclear, oncleared, onload, and onloaded are invoked by using the same window['functionName']() JavaScript statement.

The data sent to the asynchronous request is dynamically added to the request. You use POST instead of GET because you want to avoid any issues with the query string length being exceeded or escaping of strings. The name/value pair is added to the POST data for each contained panelargument tag. The value can either be static using the value attribute or dynamic using the sourcefield attribute.

The final step in showing the update panel is to handle the server response, which is done by the dialogName_onServerResponse function. The code is uncomplicated. It's a matter of checking the response and, if successful, replacing the content contained in the update panel with the server response. Listing 3 shows this function.


Listing 3. dialogName_onServerResponse JavaScript function
function cityPanel_onServerResponse() {
	// If loaded
	if(req.readyState!=4) return;
	
	// If an error occurred
	if(req.status != 200) {
		alert('An error occurred retrieving data.');
		return;
	}

	// Get panel
	var curControl= document.getElementById('cityPanel_Container');
	
	// If panel not found simply return (this shouldn't happen)
	if (curControl == null) 
		return;
	
	// Update CSS class to the value specified in the cssclass attribute
	curControl.className = 'normalpanel';
	
	// Set content of element to the server response
	curControl.innerHTML = req.responseText;
	
	// Clear window status
	window.status='';
	
	// Invoke the onloaded event handler (this is not rendered
	// if there is no event handler specified in the oncleared
	// attribute)
	window['onCityPanelLoaded']();
}

Hiding the update panel

Next you build the dialogName_onHide function. This is the function that is called by the hideUpdatePanel function. The key purpose, besides the obvious clearing of the panel, is to optionally enforce business rules with the custom event handlers. This function is shown in Listing 4.


Listing 4. dialogName_onHide JavaScript function
function onHide_cityPanel() { 
	// Invoke the onclear event. 
	// If true is not returned by the event handler, 
	// the action is cancelled and the panel remains 
	// visible
	if(!window['onCityPanelClear']()) { 
		return; 
	}
	
	// Retrieve the update panel container
	var controlName = 'cityPanel_Container';
	var curControl= document.getElementById(controlName);
	
	// If control wasn't found, return
	if (curControl == null) {
		alert(controlName + ' control not found!');
		return;
	}
	
	// Clear tag
	curControl.innerHTML = '';
	
	// Invoke the oncleared event handler (this is not rendered
	// if there is no event handler specified in the oncleared
	// attribute)
	window['onCityPanelCleared']();
}

Update panel TagLib library definition entry

The next step is to define the <ajax:updatepanel/> JSP control in the TagLib library definition file. Listing 5 shows the update panel control's TagLib library definition entry (with embedded comments for a description of each attribute).


Listing 5. Update panel TagLib library definition entry
<tag>
	<name>updatepanel</name>
	<tagclass>com.testwebsite.controls.updatepanel.UpdatePanelTag</tagclass>
	<bodycontent>JSP</bodycontent>
	<info>Update Panel tag.</info>
	<!-- Panel ID-->
	<attribute>
		<name>id</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Url to fragment-->
	<attribute>
		<name>url</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Message displayed while retrieving panel content-->
	<attribute>
		<name>updatemessage</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Loading CSS class name -->
	<attribute>
		<name>loadingcss</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>		
	<!-- CSS class name (Post loading) -->
	<attribute>
		<name>cssclass</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Event: on clear -->
	<attribute>
		<name>onclear</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Event: on cleared -->
	<attribute>
		<name>oncleared</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Event: on loading-->
	<attribute>
		<name>onload</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Event: post loaded-->
	<attribute>
		<name>onloaded</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
</tag>

Panel argument TagLib library definition entry

Listing 6 shows the <ajax:panelargument/> JSP control in the TagLib library definition file (with embedded comments for a description of each attribute).


Listing 6. Panel argument TagLib library definition entry
<tag>
	<name>panelargument</name>
	<tagclass>com.testwebsite.controls.updatepanel.PanelArgumentTag</tagclass>
	<bodycontent>empty</bodycontent>
	<info>Contains the argument tag.</info>
	<!-- Argument name -->
	<attribute>
		<name>name</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Source field for argument value -->
	<attribute>
		<name>sourcefield</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Value for argument (overrides source field value if specified -->
	<attribute>
		<name>value</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
</tag>	


Build the pop-up dialog JSP TagLib control

Traditionally, Web developers use window.open or window.showModalDialog to display pop-up windows in Web applications. Although they work fairly well, they aren't without their quirks and complexities. First, referring to other form fields can be cumbersome. Second, the presentation isn't as crisp and intuitive as Document Object Model (DOM) Scripting and CSS-based dialog boxes. Third, they don't lend themselves to a smooth way to display more information when, for example, a user hovers over an item on the page.

Through DOM scripting and the use of the CSS z-index property, you can simulate dialogs for a Web page. With Ajax and asynchronous techniques, you can build quite powerful and flexible dialog boxes because data can be asynchronously retrieved from the server on demand.

The primary goal of the <ajax:popupdialog/> is to create a JSP-based pop-up dialog control that combines DOM scripting, CSS, and Ajax to create a reusable control that can be easily added to any business-line application. The pop-up dialog control consists of several tags, which are described in Table 2.


Table 2. Popup dialog control tags
TagDescription
popupdialogPopup dialog
popupargumentsOptional tag that contains one or more arguments (popupargument tags) passed to popup dialog
popupargumentPopup dialog argument for the popup dialog
popupbuttoncontainerOptional tag that contains one more buttons (popupbutton tags). It can also contain HTML for formatting the button layout.
popupbuttonButton for popup dialog

Figure 8 shows the components of the pop-up dialog.


Figure 8. Sample popup dialog container
Window showing checkboxes for        states

Technical overview of control

When the page is first rendered, a DIV container is rendered for the dialog box. The style display: none is applied to hide the pop-up dialog. The container will optionally contain a title panel (depending on the showtitle and title attributes) and a button panel (depending on whether the <ajax:popupdialog/> contains a <ajax:popupbuttoncontainer/> tag). It also renders DIV within the dialog container for the dialog content. This element is initially empty, and the dialog content is added when the showDialog function is called for the corresponding pop-up dialog. When the pop-up dialog is displayed, the following occurs:

  1. The style is changed to display: block to make the pop-up dialog visible.
  2. The updatemessage is displayed in the pop-up dialog while the dialog content is being retrieved.
  3. An asynchronous request is made to the server to retrieve the dialog content.
  4. Upon receiving the server response, the dialog content is displayed.

Two key CSS properties are also applied to the pop-up dialog container to make it work. The first is z-index: 100;, which ensures the dialog container is displayed on top of other Web page elements. The second is position: absolute;, which allows for the pop-up dialog to be positioned.

The pop-up dialog control provides several configurable features that define the pop-up dialog's behavior and presentation. The configurable features described in Table 3 are supported.


Table 3. Configurable features of the pop-up dialog control
FeatureDescription
idControl ID
titleDialog title
showtitleOption to control whether the dialog title is displayed (default: true)
showcloseOption to control whether the close button is displayed (default: true)
widthOverall width of dialog
heightOverall height of dialog
contentheightHeight of dialog content pane that is scrollable
leftLeft position of dialog
topTop position of dialog
urlURL to retrieve dialog content when the dialog is shown
updatemessageMessage displayed while content is being retrieved

Building the functions to display or hide the pop-up dialog

The <ajax:page/> renders two key functions for the <ajax:popupdialog/> control:

  • showDialog—Shows the pop-up dialog by invoking the corresponding onShow event handler.
  • closeDialog—Hide the pop-up dialog by invoking the corresponding onHide event handler.

Similar to the update panel, these functions are nearly identical and do nothing more than provide wrappers around the show and hide dialog functions for the dialog-specific instances. As mentioned with the update panel, this approach abstracts the details about how the dialog is displayed and content is asynchronously retrieved from anyone who is using the <ajax:popupdialog/> control. You simply need to call the showDialog or closeDialog JavaScript functions, passing the name of the dialog to show or hide the update panel.

Showing the pop-up dialog

The next step is to build the dialog-specific functions to display the pop-up dialog. This function, rendered mostly by the <ajax:popupdialog/> tag, contains JavaScript code based on the options specified in the tag's attributes. For example, set the title of the dialog, build the POST data and URL, and make the asynchronous request. This function is shown in Listing 7.


Listing 7. dialogName_onShow JavaScript function
function stateDialog_onShow() {
	// Get dialog control
	var dialogControl = document.getElementById('stateDialog');
	dialogControl.style.display = 'block';
	
	// Set title (if showtitle attribute is not false)
	var titleControl = document.getElementById('stateDialog_dialogTitleText');
	titleControl.innerHTML = 'Select States';
	
	// Get dialog content control
	var dialogContentName = 'stateDialog_dialogContent';
	var contentControl = document.stateDialog_dialogForm[dialogContentName];
	
	// If dialog content control is not null
	if (contentControl != null) {
		contentControl.innerHTML = 'null';
	}
	
	// Initialize XmlHttpRequest object
	initializeXmlHttpRequest();	
	if (req == null) {
		alert('XmlHttpRequest object not initialized.');
	}
	
	// Url for retrieving dialog content (specified in url attribute)
	var targetUrl = '/ajaxcontrols3/fragments/selectState.jsp';
		
	// Build the POST data sent for the asynchronous request to
	// retrieve the dialog content
	// The arguments specified in the optional argument tag(s)
	// contained in the popuparguments tag
	var postData = '';		
	// The dialogName_getPostData function is rendered by the 
	// popuparguments tag (if specified). 
	// Check if the function is defined and if so, invoke the 
	// function
	if (window['stateDialog_getPostData'] != undefined) {
		postData = window['stateDialog_getPostData']();
	}
	
	// Set server response function
	var responseFunction = 'stateDialog_onServerResponse';
	req.onreadystatechange = eval(responseFunction);
	
	// Open server request
	req.open('POST',targetUrl,true);	
	req.setRequestHeader("Content-type", 
		"application/x-www-form-urlencoded");
	req.setRequestHeader("Content-length", 
		postData.length);
	
	// Send data
	req.send(postData);
}		

The next step is to handle the server response, which is handled by the dialogName_onServerResponse function. The code is not difficult. The dialog content is replaced with the HTML returned by the asynchronous server request. The server response function is shown in Listing 8.


Listing 8. dialogName_onServerResponse JavaScript function
function stateDialog_onServerResponse() {
	// If loaded
	if(req.readyState!=4) 
		return;
		
	// If an error occurred
	if(req.status != 200) {
		alert('An error occurred retrieving panel content.');
		return;
	}
	
	// Get response
	var responseData = req.responseText;
	
	// Get dialog content pane
	var dialogContentName = 'stateDialog_dialogContent';
	var contentControl = document.getElementById(dialogContentName);
	
	// If dialog content pane found, set the content
	if (contentControl != null) {
		contentControl.innerHTML = responseData;
	}
}

Pop-up dialog TagLib library definition entry

The next step is to define the <ajax:popupdialog/> JSP control in the TagLib library definition file. Listing 9 shows the pop-up dialog control's TagLib library definition entry (with embedded comments for a description of each attribute).


Listing 9. Popup dialog TagLib library definition entry
<tag>
	<name>popupdialog</name>
	<tagclass>com.testwebsite.controls.popupdialog.PopupDialogTag</tagclass>
	<bodycontent>JSP</bodycontent>
	<info>Popup Dialog tag.</info>
	<!-- Popup ID-->
	<attribute>
		<name>id</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Popup Title-->
	<attribute>
		<name>title</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Show Title -->
	<attribute>
		<name>showtitle</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Show Close Button -->
	<attribute>
		<name>showclose</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute> 
	<!-- Size Width -->
	<attribute>
		<name>width</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Size Height -->
	<attribute>
		<name>height</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Size Content Height -->
	<attribute>
		<name>contentheight</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>		
	<!-- Position Left -->
	<attribute>
		<name>left</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Position Top-->
	<attribute>
		<name>top</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Url to fragment-->
	<attribute>
		<name>url</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Message displayed while retrieving panel content-->
	<attribute>
		<name>updatemessage</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
</tag>

Pop-up argument container and pop-up argument controls

The <ajax:popupdialog/> can optionally contain the <ajax:popuparguments/> tag to send POST data for the asynchronous request to retrieve the dialog content. This tag is responsible for rendering the dialogName_getPostData function. Listing 10 shows an example dialogName_getPostData function that simply returns a string containing all name/value pairs for the POST data.


Listing 10. dialogName_getPostData JavaScript function
		
function cityDetailsDialog_getPostData() {	
	var data = 'dialogName=cityDetailsDialog'
			+ '&zipCode=' + getFormValue('selectedZipCode');
	return data;
}

A name/value is rendered for each popupargument tag. The following code fragment is rendered for each argument: + '&zipCode=' + getFormValue('selectedZipCode');. The popupargument tag is explained in more detail later.

The doStartTag renders the start of the dialogName_getPostData function. The method for the <ajax:popuparguments/> is shown in Listing 11.


Listing 11. Pop-up argument container doStartTag method
		
public int doStartTag() throws JspException {
	StringBuffer html = new StringBuffer();
	
	String dialogName = this.getDialogName();
	
	html.append("<script type='text/javascript' language='javascript'>");
	html.append("function ");
	html.append(dialogName);
	html.append("_getPostData() {");
	html.append("var data = 'dialogName=");
	html.append(dialogName);
	html.append("'");
	
	JspWriter out = pageContext.getOut();
	try {
		out.append(html.toString());
	} catch (IOException e) {
		e.printStackTrace();
	}
	
	return PopupDialogArgumentContainerTag.EVAL_BODY_INCLUDE;
}

The doEndTag method closes the dialogName_getPostData function, and is shown in Listing 12.


Listing 12. Pop-up argument container doEndTag method
		
public int doEndTag() throws JspException {
	StringBuffer html = new StringBuffer();
	
	html.append(";");
	html.append("return data;");
	html.append("}");
	html.append("</script>");
	
	// Write output
	JspWriter out = pageContext.getOut();
	try {			
		out.append(html.toString());
	} catch (IOException e) {
		e.printStackTrace();
	}
	
	return PopupDialogArgumentContainerTag.EVAL_PAGE;
}

The next step is to define the <ajax:popuparguments/> JSP control in the TagLib library definition file. Listing 13 shows the pop-up dialog argument container's TagLib library definition entry (with embedded comments for a description of each attribute).


Listing 13. Pop-up arguments TagLib library definition entry
<tag>
	<name>popuparguments</name>
	<tagclass>com.testwebsite.controls.popupdialog.PopupDialogArgumentContainerTag
	</tagclass>
	<bodycontent>JSP</bodycontent>
	<info>Popup Dialog Argument Container</info>
	<!-- Popup Argument Container ID-->
	<attribute>
		<name>id</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
</tag>

The next step is to define the <ajax:popupargument/> JSP control in the TagLib library definition file. The pop-up argument's TagLib library definition entry (with embedded comments for a description of each attribute) is shown in Listing 14.


Listing 14. Pop-up argument TagLib library definition entry
<tag>
	<name>popupargument</name>
	<tagclass>com.testwebsite.controls.popupdialog.PopupArgumentTag</tagclass>
	<bodycontent>empty</bodycontent>
	<info>Contains the argument tag.</info>
	<!-- Argument name -->
	<attribute>
		<name>name</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Source field for argument value -->
	<attribute>
		<name>sourcefield</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- Value for argument (overrides source field value if specified) -->
	<attribute>
		<name>value</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
</tag>

Pop-up button container and button controls

The <ajax:popupdialog/> can optionally contain a button panel <ajax:popupbuttoncontainer/> tag. The container tag renders a DIV element named dialogName_dialogButtonContainer.

The <ajax:popupbuttoncontainer/> tag can contain one or more <ajax:popupbutton/> tags. There are two types of buttons supported by the pop-up dialog control—cancel and normal. If the button type is cancel, the closeDialog is invoked when the button is clicked. If the button type is normal, the JavaScript function specified in the onclick attribute is invoked.

The button is rendered in the doStartTag method of the pop-up button. The logic for the type of button and the event handler to be invoked is contained in this method, shown in Listing 15.


Listing 15. Pop-up button doStartTag method
public int doStartTag() throws JspException {
	StringBuffer html = new StringBuffer();
	
	// Get button container
	PopupDialogButtonContainerTag buttonPane = 
		(PopupDialogButtonContainerTag) this.getParent();
	String dialogName = buttonPane.getDialogName();
	
	// Render button
	html.append("<input type='button' id='");
	html.append(this.getId());
	html.append("' class='");
	html.append(this.getCssclass());
	
	String buttonLabel = this.getLabel();
	if (buttonLabel != null && buttonLabel.length() > 0) {
		html.append("' value='");
		html.append(buttonLabel);
	}
	
	html.append("' onclick='");
					
	// Check button type and render event handler accordingly
	String buttonType = this.getType();
	if (buttonType == null || 
			buttonType.length() < 1 || 
			buttonType.equalsIgnoreCase("cancel")) {
		html.append("closeDialog(\"");
		html.append(dialogName);
		html.append("\")");
	}
	else {
		html.append(this.getOnclick());
		html.append("(\"");
		html.append(dialogName);
		html.append("\", document.");
		html.append(dialogName);
		html.append("_dialogForm)");
	}
	html.append("'/>");
	
	
	// Write output
	JspWriter out = pageContext.getOut();
	try {
		out.append(html.toString());
	} catch (IOException e) {
		e.printStackTrace();
	}

	return PopupButtonTag.EVAL_BODY_BUFFERED;
}		

The next step is to define the <ajax:popupbuttoncontainer/> JSP control in the TagLib library definition file. The button panel container's TagLib library definition entry (with embedded comments for a description of each attribute) is shown in Listing 16.


Listing 16. Pop-up dialog button container TagLib library definition entry
<tag>
	<name>popupbuttoncontainer</name>
	<tagclass>com.testwebsite.controls.popupdialog.PopupDialogButtonContainerTag
	</tagclass>
	<bodycontent>JSP</bodycontent>
	<info>Popup Dialog Button Container</info>
	<!-- Popup Button Container ID-->
	<attribute>
		<name>id</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
</tag>

Next, you'll want to define the <ajax:popupbutton/> JSP control in the TagLib library definition file. The button's TagLib library definition entry (with embedded comments for a description of each attribute) is shown in Listing 17.


Listing 17. Pop-up button TagLib library definition entry
<tag>
	<name>popupbutton</name>
	<tagclass>com.testwebsite.controls.popupdialog.PopupButtonTag</tagclass>
	<bodycontent>empty</bodycontent>
	<info>Contains the argument tag.</info>
	<!-- Button id -->
	<attribute>
		<name>id</name>
		<required>true</required>
		<rtexprvalue>true</rtexprvalue>
	</attribute>
	<!-- Button label -->
	<attribute>
		<name>label</name>
		<required>false</required>
		<rtexprvalue>true</rtexprvalue>
	</attribute>
	<!-- Type of button -->
	<attribute>
		<name>type</name>
		<required>true</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- onclick Event handler -->
	<attribute>
		<name>onclick</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
	<!-- CSS class name -->
	<attribute>
		<name>cssclass</name>
		<required>false</required>
		<rtexprvalue>false</rtexprvalue>
	</attribute>
</tag>


Testing the controls

There are three test pages you use to demonstrate the new Ajax enabled controls. Those pages are described in Table 4.


Table 4. Test pages
PageDescription
SearchLocations.jspUses the <ajax:updatepanel/> to provide real-time filtering of a data grid containing cities. The city lists can be filtered by state (drop-down selection list) and city name (text field). The two fields call the showUpdatePanel when their respective values change.
LocationReport.jspUses the <ajax:popupdialog/> to provide a mock reporting page. The reporting criteria include a state text field that, when clicked, displays a pop-up dialog containing a list of all states with check boxes. When the user clicks the Save button, a comma-separated list of states is built and the value of the state text field is set to the comma-separated list.
NewYorkCityList.jspDisplays a list of all cities in New York. It uses the <ajax:popupdialog/> to display additional information for a city when a user hovers over a zip code in the city list. The pop-up dialog is hidden when the zip code loses focus.

Search Locations page (SearchLocations.jsp)

The Search Locations page demonstrates how to use the update panel control. Figure 9 shows a sample update panel.


Figure 9. Update panel demonstration: Search Locations page
Window showing Florida in the        state drop-down box on the Search Locations page

The Search Locations page demonstrates how to use the event handlers, as well as how to hook the update panel to two controls (a SELECT and an INPUT text box). Listing 18 shows the code for this sample page.


Listing 18. SearchLocations.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="ajax" uri="/WEB-INF/tlds/ajax_controls.tld"%>
<html>
<head>
<title>Locations</title>

<link href="core.css" rel="stylesheet" type="text/css" />
<ajax:page/>

<script type='text/javascript' language='javascript'>
function onCityPanelCleared() {
var msgControl = document.getElementById('statusMessage');			
if (msgControl != null) {
msgControl.innerHTML = 'oncleared'; 
}
}

function onCityPanelClear() {
var msgControl= document.getElementById('statusMessage');
if (msgControl != null) {
msgControl.innerHTML = 'onclear'; 
}
return true;
}

function onCityPanelLoad() {
var msgControl = document.getElementById('statusMessage');
if (msgControl != null) {
msgControl.innerHTML = 'onload'; 
}
return true;
} 		 		

function onCityPanelLoaded() {			
var msgControl= document.getElementById('statusMessage');			
if (msgControl != null) {
msgControl.innerHTML = 'onloaded';				
}
}

function displayCityPanel(curControl) {
if (!curControl.checked) {	
hideUpdatePanel('cityPanel');
} 
}

function retrieveCityData() {			
showUpdatePanel('cityPanel');
document.all.showCityPanel.checked = 'checked';
}
</script>
</head>

<body>
<b>State: </b>
<select id="state" onchange="retrieveCityData()">
<option value=''> </option>
<option value='AK'> Alaska</option>
<option value='AL'> Alabama</option>
<option value='AR'> Arkansas</option>
...
...
<option value='WI'> Wisconsin</option>
<option value='WV'> West Virginia</option>
<option value='WY'> Wyoming</option>
</select><br/>

<b>City Prefix: </b>
<input type="text" id="cityPrefix" onkeyup="retrieveCityData()"/>
<br/>

<input type="checkbox" 
id="showCityPanel" 
name="showCityPanel"
checked="checked" 
onclick="displayCityPanel(this)" />Show City Panel<br/>

<div><b>Result: </b><span id="statusMessage"></span></div>

<div>		
<ajax:updatepanel id="cityPanel" 
url="/fragments/cityList.jsp" 
updatemessage="Retrieving cities..."
cssclass="normalpanel"
loadingcss="loadingpanel"
onclear="onCityPanelClear"
oncleared="onCityPanelCleared"
onloaded="onCityPanelLoaded"
onload="onCityPanelLoad">

<ajax:panelargument name="state" sourcefield="state"/>
<ajax:panelargument name="cityPrefix" sourcefield="cityPrefix"/>
</ajax:updatepanel>
</div>

</body>
</html>

Location report (LocationReport.jsp)

The Location report demonstrates how to use the pop-up dialog let users select multiple states (check boxes). When the user selects the Save button on the pop-up dialog, a text box is set to a comma-separated list containing the selected states. Figure 10 shows the pop-up dialog.


Figure 10. Pop-up dialog demonstration: Location report
Window showing a list of states        beside check boxes

When the user double clicks the selectedStates control, the pop-up dialog is displayed using the showDialog function. When the user clicks the Save button on the popupdialog, the onSaveStates JavaScript function is invoked, which builds a comma-separated list of the selected values. The selectedStates text box is then populated with the list. The code for the Location report is shown in Listing 19.


Listing 19. LocationReport.jsp
<%@ page language="java" contentType="text/html; 
	charset=ISO-8859-1"  pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="ajax" 
uri="/WEB-INF/tlds/ajax_controls.tld"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; 
charset=ISO-8859-1">
<title>Search Locations</title>
<link href="core.css" rel="stylesheet" 
type="text/css" />
<script type="text/javascript">
function onSaveStates(dialogName, dialogForm) {
var values = '';		
var stateList = dialogForm.states;
for (var i = 0; i < stateList.length; i++) {
if (stateList[i].checked) {
if (values.length != 0) {		   
values += ", ";
}
values += stateList[i].value;
}
}

var targetControl = document.getElementById('selectedStates');
targetControl.value = values;

closeDialog(dialogName);
}
</script>
<ajax:page id="page"/>
</head>
<body>
<h1>Report Criteria</h1>
<table width="80%" >
<colgroup>
<col width="40%"/> 
<col width="60%"/>
</colgroup>
<tbody>
<tr>
<td align="right" style="border:none;">
<span style="font-weight:bold">Zip Code:&nbsp;
</span>
</td>
<td align="left" style="border:none;">
<input type="text"
size="50" 
id="zipCode" />
</td> </tr>
<tr>
<td align="right" style="border:none;">
<span style="font-weight:bold">States:&nbsp;
</span>
</td>
<td align="left" style="border:none;">
<input type="text"
size="50" 
readonly="readonly" 
id="selectedStates" 
onclick="showDialog('stateDialog')"/>
</td> </tr>
</tbody>
<thead>
<th colspan="2" class="subHeading">
Search Locations</th>
</thead>
<tfoot>
<tr>
<td colspan="2">
<input type="button" class="dialogButton" 
value="Run Report" id="runReport"/>
</td> </tr>
</tfoot>
</table>		

<ajax:popupdialog url="/ajaxcontrols3/fragments/selectState.jsp" 
id="stateDialog" 
width="400px" height="28em"
left="0" top="0" 
title="Select States" 
contentheight="23em">
<ajax:popuparguments id="stateDialogArgs">
<ajax:popupargument name="arg1" value="test1"/>
<ajax:popupargument name="arg2" value="test2"/>
</ajax:popuparguments>
<ajax:popupbuttoncontainer id="stateDialogButtons">
<ajax:popupbutton id="cancelButton" 
label="Cancel" type="cancel"/>&nbsp;
<ajax:popupbutton id="saveButton" label="Save" 
type="normal" onclick="onSaveStates"/>
</ajax:popupbuttoncontainer>	
</ajax:popupdialog>

<h1>Report Results</h1>
<div>Show report results here...</div>
</body>
</html>

Listing 20 shows the page displayed within the pop-up dialog box. The code is relatively simple. A list of locations is retrieved from the Location Data Service, and this list is then iterated through, and a check box is rendered for each state.


Listing 20. selectState.jsp
<%@ page language="java" contentType="text/html; 
charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page import="com.testwebsite.dal.LocationDataService" %>
<%@ page import="com.testwebsite.dto.LocationDTO" %>
<%@ page import="com.testwebsite.dto.StateDTO" %>
<%@ page import="java.util.Iterator" %>
<%@ page import="java.util.TreeMap" %>
<%@ page import="java.util.Set" %>


<ul style="list-style: none;"
		<%
		TreeMap<String, StateDTO> stateData = 
			LocationDataService.getStateData();
		
		// Iterate through all data looking for matching 
		// cities and add to temporary TreeMap
		Set<String> keySet = stateData.keySet();
		Iterator<String> stateIter = keySet.iterator();		
		while (stateIter.hasNext()) {
			// Get current state
			String curKey = stateIter.next();
			StateDTO curState = stateData.get(curKey);
			
			out.println("<li><input type='checkbox' 
				name='states' value='");
			out.println(curState.getAbbreviation());
			out.println("'/>&nbsp;");
			out.println(curState.getName());
			out.println("</li>");
		}
		%>
</ul>

New York City Listing page (NewYorkCityList.jsp)

The New York City Listing page demonstrates another way the pop-up dialog box can be leveraged. A common scenario in many Web applications is to display additional information when a user hovers over an item in a list. The pop-up dialog box allows the detailed information to be retrieved only when requested through Ajax. This example is shown in Figure 11.


Figure 11. Sample pop-up dialog container
Window of sample pop-up dialog        container showing information for the Bronx in New York

The code for the New York City Listing page is shown in Listing 21. The key function in this sample is showCityDialog, which takes a single parameter, the zip code, for the item the user is currently hovering over. The dialog box position is set using standard CSS properties and JavaScript code. The showDialog function is then shown. When the user hovers away from the zip code, the hideDialog function is called to hide the pop-up dialog.


Listing 21. NewYorkCityList.jsp
<html><head>
<title>New York City Listing</title>
	<ajax:page/>
<link href="core.css" rel="stylesheet" 
		type="text/css" />
</head>
<script type="text/javascript">	
	
	function showCityDialog(zipCode) {
		var xPosition = 0;
		var yPosition = 0;
		if (!e) var e = window.event;
		if (e.pageX || e.pageY) 	{
			posx = e.pageX;
			yPosition = e.pageY;
		}
		else if (e.clientX || e.clientY) 	{
			xPosition = e.clientX + document.body.scrollLeft
				+ document.documentElement.scrollLeft;
			yPosition = e.clientY + document.body.scrollTop
				+ document.documentElement.scrollTop;
		}
		
		var dialogControl = document.getElementById("cityDetailsDialog");
		if (dialogControl != null) {
			dialogControl.style.top = yPosition;
			dialogControl.style.left = xPosition;
		}		
		// Get selected zip code
		var zipCodeControl = document.getElementById("selectedZipCode");
		if (zipCodeControl != null) {
			zipCodeControl.value = zipCode;
			showDialog('cityDetailsDialog');
		}
	}	
</script>
<body>
<table cellpadding="0" cellspacing="0" width="60%">	
		<tbody> <%
		TreeMap<Integer, LocationDTO> locData = 
			LocationDataService.getLocationData();
		// Temp map to ensure only unique cities are added. 
		HashMap tempMap = new HashMap(); 
		// Iterate through all data looking for matching cities and add to 
		// temporary TreeMap
		Set<Integer> keySet = locData.keySet();
		Iterator<Integer> locIter = keySet.iterator();		
		while (locIter.hasNext()) {
			// Get current state
			Integer curKey = locIter.next();
			LocationDTO curLocation = locData.get(curKey);			
			String curState = curLocation.getState();			
			String curCity = curLocation.getCity();
			String lowerCurCity = curCity.toLowerCase();			
			if (!tempMap.containsKey(curCity) && 
				curState.equalsIgnoreCase("NY")) {
				tempMap.put(curCity, curCity);
				out.println("<tr>");
				out.println("<td><a href='#' 
					style='text-decoration:none;color' 
					onMouseOver=\"showCityDialog('" + 
					curLocation.getZipCode() + 
					"')\" >");
				out.println(curLocation.getZipCode());
				out.println("</td>");
				out.println("<td>");
				out.println(curLocation.getCity());
				out.println("</td>");			
				out.println("<td>");
				out.println(curLocation.getCounty());
				out.println("</td>");
				out.println("</tr>");
			}
		} %>
		</tbody>
		<thead> <tr>
<th colspan="3"><b>Cities</b></th></tr>
<tr>
<th class="subHeading">	<b>Zip Code</b></th>
<th class="subHeading">
	<b>City</b></th>
	<th class="subHeading">
	<b>County</b></th>
	</tr> </thead>
	</table>
	<input type="hidden" id="selectedZipCode" 
		value=""/>
	<ajax:popupdialog url="/ajaxcontrols3/fragments/cityDetails.jsp" 
		id="cityDetailsDialog" width="400px" 
		left="0" top="0" title="City Information" 
		height="10.5em" contentheight="8.5em">
		<ajax:popuparguments id="stateDialogArgs">
			<ajax:popupargument name="zipCode" 
				sourcefield="selectedZipCode"/>
		</ajax:popuparguments>
	</ajax:popupdialog>
</body></html>

Listing 22 shows the JSP code for the pop-up dialog content. It is reasonably clear-cut. The detailed information for the city is retrieved from the Location Data Service, and the corresponding record is displayed.


Listing 22. cityDetails.jsp
<%@ page language="java" contentType="text/html; 
	charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page import="com.testwebsite.dal.LocationDataService" %>
<%@ page import="com.testwebsite.dto.LocationDTO" %>
<%@ page import="com.testwebsite.dto.StateDTO" %>
<%@ page import="java.util.Iterator" %>
<%@ page import="java.util.TreeMap" %>
<%@ page import="java.util.Set" %>

<%
TreeMap<Integer, LocationDTO> locData = LocationDataService.getLocationData();
String zipCodeStr = request.getParameter("zipCode"); 
Integer zipCode = new Integer(zipCodeStr);
LocationDTO curLocation = locData.get(zipCode);
if (curLocation != null) {
	out.println("<div id='cityDetails'>");
	
	// Render zip code
	out.println("<div>");		
	out.println("<span style='font-weight:bold;color: 
		#00628B'>Zip Code:&nbsp;</span>");
	out.println("<span style='color: #00628B'>");
	out.println(curLocation.getZipCode());
	out.println("</span>");
	out.println("</div>");
	
	// Render city name
	out.println("<div>");		
	out.println("<span style='font-weight:bold;color: 
		#00628B'>City:&nbsp;</span>");
	out.println("<span style='color: #00628B'>");
	out.println(curLocation.getCity());
	out.println("</span>");
	out.println("</div>");
	
	// Render county name
	out.println("<div>");		
	out.println("<span style='font-weight:bold;color: 
		#00628B'>County:&nbsp;</span>");
	out.println("<span style='color: #00628B'>");
	out.println(curLocation.getCounty());
	out.println("</span>");
	out.println("</div>");
	
	// Render state
	out.println("<div>");		
	out.println("<span style='font-weight:bold;color: 
		#00628B'>State:&nbsp;</span>");
	out.println("<span style='color: #00628B'>");
	out.println(curLocation.getState());
	out.println("</span>");
	out.println("</div>");
	
	// Render longitude
	out.println("<div>");		
	out.println("<span style='font-weight:bold;color: 
		#00628B'>Longitude:&nbsp;</span>");
	out.println("<span style='color: #00628B'>");
	out.println(curLocation.getLongitude());
	out.println("</span>");
	out.println("</div>");
	
	// Render latitude
	out.println("<div>");		
	out.println("<span style='font-weight:bold;color: 
		#00628B'>Latitude:&nbsp;</span>");
	out.println("<span style='color: #00628B'>");
	out.println(curLocation.getLatitude());
	out.println("</span>");
	out.println("</div>");
	
	out.println("</div>");
}
%>


Conclusion

In this article, you learned a few asynchronous communication and JSP TagLib control techniques, including how to build composite controls, how to add client-side event hooks for custom controls, and how to leverage Ajax to make Web pages more dynamic. The article built on the Ajax communication techniques described in the first two articles in this series. Ajax enables you to build Web applications that are highly dynamic, scalable, and user-friendly. By developing JSP TagLib controls, you can reduce the time to build business-line applications.

You can extend these controls further to:

  • Add additional presentation options to the pop-up dialog control, such as positioning the pop-up dialog box (for example, centering it or positioning it relative to another control.
  • Add animation to the pop-up dialog and update panel controls, such as fading, slide in, and so on.
  • Add a loading animation (while waiting for content to be retrieved) to the pop-up dialog and update panel controls, such as an hourglass.


Download

DescriptionNameSizeDownload method
Source code for this articleArticleCodeSample.zip2560KB HTTP

Information about download methods


Resources

Learn

  • See the first article in this series, "Building Ajax-enabled auto-complete and cascading drop-down controls" (developerWorks, September 2008) for information about how to build a cascading drop-down control that dynamically populates values in an HTML SELECT control, based on other form field values.

  • Read the second article in this series, "Building auto-populate and field validator controls" (developerWorks, November 2008) for information about how to build an Ajax-enabled auto-populate control that dynamically populates form fields based on a selected value and an Ajax-enabled field validator control that adds server side validation.

  • Learn more about JSON in Java, an open source library for using JSON in Java.

  • The World Wide Web Consortium (W3C) Working Draft 15 April 2008 contains valuable information about the proposed standard for the XMLHttpRequest Object.

  • Read Introducing JSON to find out what JSON is all about.

  • Refer to Mozilla's official documentation for the JavaScript language.

Get products and technologies

About the author

Photo of Brian Stewart

Brian J. Stewart is currently a principal consultant at Aqua Data Technologies, a company that he founded to focus on content management, XML technologies, and enterprise client/server and Web systems. He architects and develops enterprise solutions based on the J2EE and .NET platforms.

Comments



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=380233
ArticleTitle=Building Ajax-enabled JSP TagLib controls, Part 3: Update panel and popup dialog box controls
publish-date=04072009
author1-email=BrianJStewart@AquaDataTech.com
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers