How to Create an Ajax Autocomplete Text Field - Part 7 [con't]
Converting from Table Layouts to CSS
There are several tools available to help you convert from a table-based layout
to one that uses CSS formatting. One such example is Dreamweaver UltraDev, which includes a command called
"Convert Tables to Layers" that does just that. There are also several
standalone products that generate the <div>
tags and CSS rules from table
layouts.
Comparing the Table and CSS Version of the Autocomplete Control
By adding a border to the control we can easily compare the two implementations of the Autocomplete control.
The table version is taller because it contains an extra placeholder row for the list. This could be minimized by setting the second row height to a number like "1." Other than that, I would say that the resemblance is striking!
- Table Version (See Figure 6)
- CSS Version (See Figure 7)
JSP File Includes
There are two mechanisms for including another Web resource in a JSP page:
the include
directive and the jsp:include
element.
The include
directive is processed when the JSP page is translated into
a servlet class. The effect of the directive is to insert the text contained
in another file in the including JSP page. The include
directive is ideal
for including banner content, copyright information or any chunk of content
that you might want to reuse in another page. The syntax for the include
directive is as follows:
The jsp:include
element, on the other hand, is processed when a JSP
page is executed. It allows you to include either a static or dynamic resource
in a JSP file, which are both handled differently. If the resource is static,
its content is simply inserted into the calling JSP file, much like the include
directive. If the resource is dynamic, the request is sent to the included resource,
the included page is executed, and the result is included in the response
from the calling JSP page. Here's the syntax for the jsp:include
element:
Remove the <form>
from the AutocompleteSearch page and add the include
directive for the Autocomplete control:
The AutocompleteControl JavaScript File
Here, we rename the AutocompleteList.js
file to AutocompleteControl.js
, indicating that it now contains code for the entire control, not just the Autocomplete list. To rename the file, follow the same process as you did with the CSS file: right-click on the AutocompleteList.js
file in the "Project Explorer" pane to open the popup menu and select the Rename
item. The file will then turn into a textbox for editing. Alternatively, you can press the F2
function key.
The onload
Event Handler
One final remnant from our old control is the onload="init()"
event handler in the <body>
tag. We can remove this as well by adding code to the top of the Autocomplete.js
file:
Our addEventHandler (string, function)
function accepts two parameters: the name of the event and the event handler function. This is a simplified version of the same function that appeared in my URPMs - AJAX Edition article. The reason for needing a function to attach the event is because there are two different implementations. Here's an explanation of each from that article:
"In Internet Explorer, the
attachEvent()
function is used, while in DOM 2 compliant browsers, you add a listener to an event by callingaddEventListener()
. The World Wide Web Consortium had their hands full when deciding on an event model because the two main standards were diametrically opposed, with Netscape using something called the capturing model, and Internet Explorer endorsing bubbling. Basically, the two camps emerged as a result of answering the questing of what should happen if an element within another element both have handlers for the same event: Should the parent (outer) element fire first, or should the child (inner element)? Netscape concluded that the parent should fire first. That's Event Capturing. Internet Explorer took the opposite stance and decided that the child should be the one to fire first! That's event bubbling. The W3C took the middle road in creating their own W3C Event Model whereby the event is first captured until it reaches the innermost element and then bubbles up again. This allows the developer to select either style of event firing by supplying theaddEventListener()
function with a Boolean argument. I used "constants" to show that true means capture and false means bubble. In practice, unless you have a specific reason to use capturing, stick with bubbling, as I did here."
Aside from the onload event handler, all changes in the JavaScript file take place in the init()
method. As I mentioned earlier, we'll now use a different way to create the table and position it. Since there's no completeTable
in the document, we have to create it using the DOM createElement(string elementName)
method. We also set its ID so that the completeTable
CSS rule will apply to it.
The code to set the left
position of the completeTable
has changed because the completeField
's containing element is the AutocompleteControl. Hence, its left
property is calculated from the left
of the AutocompleteControl and not the left side of the page. For this reason, we have to subtract the autocompleteControl
's left
value from the completeField
's.
Without our placeholder auto-row, we have to be a bit more creative when setting the top
property. One easy way to do it is to set it to the bottom of the AutocompleteContol
, because it's just tall enough to contain its elements. We can easily retrieve this value via the autocompleteControl
's clientHeight
property. It retrieves the height of the object including padding, but not including the margin, border or scrollbar:
Go ahead and try it in a browser. Right-click on the AutocompleteSearchCSS.jsp
file in the "Project Explorer" pane and select "Run As => 1 Run on Server" from the popup menu (See Figure 8).
After a few seconds, the AutocompleteSearch
page should appear in the browser or main Eclipse window, depending on how you've configured the "Web Browser" preferences. If all went according to plan, the Autocomplete control should look more or less the same as it did earlier (See Figure 9).
Our final task of the day will be to add some optional parameters to our control that will augment its versatility.