Monday April 18, 2005
OTMT Ajax Experienced
Ajax - also known as asynchronous JavaScript + XML, or even xmlHttpRequest is the newest flavor of the month with web developers. I have to admit that I was interested in using this to dynamically communicate with the server and craft the output of a page without doing a full page load.
I've documented several examples where people have explored the technology and written about it. Now I've finally done my own.
The trick for me is to make the code work in as many situations as possible, so it can be deployed with a minimum of thought. For my first implementation, I needed to build a drop down box with a list of profiles that are associated with a application selected in another drop down box. For example, the application "brand" has four profiles that are valid. When the user picks "brand" from the list of applicaitons, the profile list is updated to only show those four profiles.
Sounds simple enough.
What I ended up with is that a each deployment of the technology is deployed with 2 lines in a single function called by the "onChange" event of the application drop down list. Here is the select tag for the application list:
select name="selected_appl_name" size="1" onchange="updateProfileList(this[selectedIndex].text,document.appselect.profile_name_ms);"
Here is the profile select list (nothing really to see):
select name="profile_name_ms" size="1"
So when the user changes the application name, the "updateProfileList" function fires passing the value of the user's selection, and the drop down box that will be re-populated.
function updateProfileList(appl_name,lbToChange) {
targetlb = lbToChange;
loadXMLDoc("pkg.get_appl_profiles?p_appl_name=" + appl_name);
}
The first line assigns the targeted select box to be changed to a variable that is global and available to all procedures. The second line is where the interaction begins. The loadXMLDoc procedure accepts a URL that returns a result set of option names and values. Here is a sample of the output:
<?xml version="1.0" encoding="UTF-8" >
<response>
<option>
<optionvalue>admin</optionvalue>
<optiontext>admin</optiontext>
</option>
<option>
<optionvalue>americas</optionvalue>
<optiontext>americas</optiontext>
</option>
<option>
<optionvalue>international</optionvalue>
<optiontext>international</optiontext>
</option>
</response>
As a developer, all I have to do is write the two html tags, the function called on the onChange event, and the server side procedure to generate the proper XML.
Piece of cake.
The real work is being done by three functions. The first one, initiates the xmlHTTPRequest object. Basically, it checks to see which type of XmlHTTP object it can create (the browser makers implement it differently, so the code needs to figure out which is correct).
function getXMLHTTP(){
var A=null;
try{
A=new ActiveXObject("Msxml2.XMLHTTP")
}catch(e){
try{
A=new ActiveXObject("Microsoft.XMLHTTP")
} catch(oc){
A=null
}
}
if(!A && typeof XMLHttpRequest != "undefined") {
A=new XMLHttpRequest()
}
return A
}
The second function is the one that actually sends the request to the server. The tricky part about this functionality is that the object is Asynchronus, meaning that the code does not wait for the function to finish before continuing on. So the "onreadystatechange" property is an event handler which is triggered whenever the state of the request object changes - notice how it is assigned a function. This function is run each time the state of the request changes, which means it's not in your control.
function loadXMLDoc(url) {
req=getXMLHTTP();
if(req){
req.onreadystatechange = processReqChange;
req.open("GET", url, true);
req.send(null);
}
}
The last function is the "processReqChange" function that is being run. This is where all the real work is being done to build the new list box. The first if statement that checks the readyState and the status is really testing if the HTTP request is complete, and there is data to process. If the server does not respond, then nothing will happen. Otherwise, it parses the XML document, truncates the targeted list box of any previous entries, and then rebuilds it with the values in the XML package. If there are no entries, then a single entry in the drop down list is built "No Value", and a null value will be passed as the selected value.
var req;
var targetlb;
function processReqChange () {
if ((req.readyState == 4) && (req.status == 200)) {
response = req.responseXML.documentElement;
options = response.getElementsByTagName("optiontext");
targetlb.length=0;
if (options.length > 0) {
for (i=0; i < options.length; i++) {
opttext = response.getElementsByTagName("optiontext")[i].firstChild.data;
optvalue = response.getElementsByTagName("optionvalue")[i].firstChild.data;
targetlb.options[i] = new Option(opttext,optvalue );
}
} else {
targetlb.options[0] = new Option("No Value","");
}
}
}
A couple things to note.
- There are two variables that are defined that must be available to all four of the functions - put them after the "script" tag.
- This code will only work when populating a select box.
- The XML packaged must be formatted with the two elements - optiontext and optionvalue..
A couple of opportunities for improvement.
- How about adding support for other types of form elements - e.g enter value in a text box and it populates another box, or boxes.
- Support some type of indicator that would tell the script if a null value should be even available. If not, then should the application drop down be set back to what it was? Is there an error message?
- The value provided for the null - "No Value" should be customizable.
I relied on these two articles heavily when building my implementation - the very good primer at XML.com "Very Dynamic Web Interfaces" and the great job Chris Justus did dissecting the Google Suggest page.I put together my first working implementation in about 3-4 hours, and the finishing touches to generalize it in about another 3-4 (including BDM -Big Dumb Mark-time chasing dumb Javascript errors where I should have known better).
UPDATE: - I've posted a few examples of this technique.
Check the samples page where there are some working examples. I suspect that if the mime/type provided by the webserver on your response is not text/xml, then the responseXML function may not work.
If you are still having problems send me an email at the address in the "About the Author" section and I'll try to help.
Make sure your Encoding type is valid. I am quite familiar with the Content-Type text/xml issue with IE and have solved it in the past. But I was just stumped for about an hour with a very similar issue. This time instead of the Content-Type, I had a typo in my Encoding type! Instead of ISO-8859-1 I had ISO-8895-1 .. trixy, but just another warning to pay the utmost attention to your Response Headers - especially in IE.
Sorry, comments cannot be added to this entry.
Search This Site
About the Author
is a Web Application Designer working in the suburbs of Portland Oregon.
He specializes in bringing user-centered, standards based, easy to use applications developed using Oracle web technologies.
This blog will focus on the crossover of standards based design and web application development with Oracle technology, and an occasional sprinkling of articles about his newly discovered "Entrepreneurial Spirit."
Recent Articles
- Fun with Ajax and Native Dynamic SQL
06-JAN-06 - Battle With the Comment Spammers
04-JAN-06 - More Web Goodness
02-DEC-05 - One of the Best Words in the Language - Free
01-DEC-05 - The Way of the Code Samurai
22-NOV-05
The Archives
- January, 2006 (2)
- December, 2005 (2)
- November, 2005 (1)
- July, 2005 (1)
- April, 2005 (1)
- March, 2005 (1)
- February, 2005 (5)
- January, 2005 (6)
- December, 2004 (2)
- November, 2004 (4)
- October, 2004 (2)
Categories
- PL/SQL (11)
- CSS (1)
- Oracle (5)
- Development (8)
- Technology (7)
- XHTML (3)
- Entrepreneurial Spirit (1)
- About this Website (1)
Quick Hits
- Here are some good notes from the Business for Geeks tutorial at OSCON. I'm not an open-source person, but it does give some good info on starting a software business.
- Drag and Drop functionality on a web page? Docking boxes shows you how.
- Amazing visual effects using Javascript is shown at script.aculo.us - and available for download!
- Ten good practices for writing JavaScript in 2005 discusses the separation of structure, content and behavior for good web practices.
- Styling form controls is riddled with problems, the visual quality of the "select" or drop-down box is one. Here is a solution
- I'm beginning to be a collector of these Ajax examples. Soon I hope to actually do one, then I'll do my own tutorial.
- I've been thinking about a business plan. Here are Top 10 Business Plan Myths of Solo Entrepreneurs
- Ajax - Asynchronous JavaScript + XML - Making Dynamic web applications possible without the disaster of Java Applets.
- ZDNet Reports on the uncertain future of web forms.
- XML.com does an excellent primer on XmlHttpRequest for dynamic web pages.

This doesn't work. I have tried this cut and pasted exactly as he says. I return the exact data he shows to the JavaScript and the "req.responseXML.documentElement;" returns a null every time.
Doesn't anyone have a WORKING example they can post?