•
•
•
•
What is DaniWeb IT Discussion Community?
You're currently browsing the JavaScript / DHTML / AJAX section within the Web Development category of DaniWeb, a massive community of 426,478 software developers, web developers, Internet marketers, and tech gurus who are all enthusiastic about making contacts, networking, and learning from each other. In fact, there are 2,232 IT professionals currently interacting right now! Registration is free, only takes a minute and lets you enjoy all of the interactive features of the site.
Please support our JavaScript / DHTML / AJAX advertiser: Lunarpages Web Hosting
Views: 5686 | Replies: 15
![]() |
| |
•
•
Join Date: Sep 2007
Posts: 25
Reputation:
Rep Power: 2
Solved Threads: 0
Hello,
I am trying to implement two cascading <select> boxes. the second box's options would be fetched from a mysql db via a PHP script.
it works fine on IE.
Problems rise when it comes to Firefox, the form would not submit the value from the second <select> box.
I have the feeling that we need to return the name/value pairs of data and generate the <option>s on client-side, I just dont know how to do it using DOM.
Please advise..
Below is code for both the JS and PHP scripts:
PHP script
Javascript
I am trying to implement two cascading <select> boxes. the second box's options would be fetched from a mysql db via a PHP script.
it works fine on IE.
Problems rise when it comes to Firefox, the form would not submit the value from the second <select> box.
I have the feeling that we need to return the name/value pairs of data and generate the <option>s on client-side, I just dont know how to do it using DOM.
Please advise..
Below is code for both the JS and PHP scripts:
PHP script
<?php
$countrycode=$_GET["countrycode"];
include("key.php");
$connection = mysql_connect($mysql_host_name,$username, $password) or die(mysql_error());
$db = mysql_select_db($mysql_db_name,$connection) or die ("Couldn't select database.");
mysql_select_db("getCities", $connection);
$sql="SELECT city_id, countrycode, name, nr_hotels FROM getCities WHERE countrycode = '".$countrycode."' ORDER BY name";
$result = mysql_query($sql);
echo "
<select name=\"city_id\" style=\"font-family:Verdana, Arial, Helvetica, sans-serif; font-weight: bold; font-size:15px \">
<OPTION VALUE=\"0\">-----------------------------------------
";
$options="";
while($row = mysql_fetch_array($result))
{
$cityname=$row["name"];
$city_id=$row["city_id"];
$nr_hotels=$row["nr_hotels"];
$options.="<OPTION VALUE=\"$city_id\">".$cityname." (".$nr_hotels." hotels)";
}
echo $options;
echo "</select>";
mysql_close($connection);
?>
Javascript
var xmlHttp
function showUser(str)
{
xmlHttp=GetXmlHttpObject()
if (xmlHttp==null)
{
alert ("Browser does not support HTTP Request")
return
}
var url="ajax.php"
url=url+"?q="+str
url=url+"&sid="+Math.random()
xmlHttp.onreadystatechange=stateChanged
xmlHttp.open("GET",url,true)
xmlHttp.send(null)
}
function stateChanged()
{
if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
{
document.getElementById("txtHint").innerHTML=xmlHttp.responseText
}
}
function GetXmlHttpObject()
{
var xmlHttp=null;
try
{
// Firefox, Opera 8.0+, Safari
xmlHttp=new XMLHttpRequest();
}
catch (e)
{
//Internet Explorer
try
{
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
}
return xmlHttp;
}
•
•
Join Date: Sep 2007
Location: Nevada, U.S.A.
Posts: 41
Reputation:
Rep Power: 2
Solved Threads: 1
It looks like you are creating a select element with unclosed options elements.
You have the opening and closing tags for select, but I only see the opening tags for the options, which may or may not be your problem.
I use dynamically created options for my select's using ajax requests to PHP code that gets data from a database as well, but the route I took was to have the select elements present in the HTML code with one dummy <option></option>.
When my ajax request is made, my php does not generate text to get with responseText, but it creates an XML document that has the values+text for each element and retrieved with XMLresult instead of responseText.
For my company contacts menu their names are the text and the value is their email address and the XML doc would contain:
Of course this is not a full XML doc, but my JS iterates over the "row" tags in the XML and puts the info into a global array named company_email.
Then I use the following to remove any/all options from the select object, and create new options, split the company_email at the comma and set the value and text of the option elements accordingly.
I just found it easier to work with elements that were generated in the HTML document than to try to dynamically create new elements on the fly, if you want to try this different route and would like to see how I create and read the XML docs let me know.
You have the opening and closing tags for select, but I only see the opening tags for the options, which may or may not be your problem.
I use dynamically created options for my select's using ajax requests to PHP code that gets data from a database as well, but the route I took was to have the select elements present in the HTML code with one dummy <option></option>.
When my ajax request is made, my php does not generate text to get with responseText, but it creates an XML document that has the values+text for each element and retrieved with XMLresult instead of responseText.
For my company contacts menu their names are the text and the value is their email address and the XML doc would contain:
<row>Bob,bob@abc.com</row> <row>Sally,sally@123.com</row>
Of course this is not a full XML doc, but my JS iterates over the "row" tags in the XML and puts the info into a global array named company_email.
Then I use the following to remove any/all options from the select object, and create new options, split the company_email at the comma and set the value and text of the option elements accordingly.
var cs = document.getElementById("<your select element id here");
//remove all options from the select
while ( cs.options.length )
{
cs.remove(cs.options[0]);
}
for ( var i = 0; i < company_email.length; i++ )
{
var newOpt=document.createElement('option');
var tmp = company_email[i].split(",");
newOpt.text=tmp[0];// the text will be the persons name
try
{
cs.add(newOpt,null); // standards compliant
}
catch(ex)
{
cs.add(newOpt); // IE only
}
cs.options[i].value = tmp[1];//the value will be the persons email
cs.selectedIndex = 0;//select the first option, should be default but make sure
}I just found it easier to work with elements that were generated in the HTML document than to try to dynamically create new elements on the fly, if you want to try this different route and would like to see how I create and read the XML docs let me know.
•
•
Join Date: Sep 2007
Location: Nevada, U.S.A.
Posts: 41
Reputation:
Rep Power: 2
Solved Threads: 1
Try this out...
You need a table in your DB named email with at least one column named email.
The data in each row should be in this format: name,email Example: Bob,bob@bob.com
I did test this and verified that it works as long as:
a) you can connect to your database
b) you have a table named email with a column name email
c) you can run PHP on your host server I assume
The php file outputs an XML document, you can just open the PHP directly in the browser and see it's output, might help you get an idea of what it's doing.
The PHP file
test.ajax.php)
And the HTML with javascript in it:
My disclaimer is that I have never been trained in programming, only self taught, so any pro's out there that see anything they wish to comment on, I would be happy to receive the critique.(with the exception of the HTML portion of the doc above that I just threw together for this example)
For simplicity I have been retrieving all rows I get from my database this way, in a "^" delimited string that I split once I have retrieved it.
Hope this helps you with your menu building.
This method has worked great so far, my goal for the app I am working on is to never have to reload the page and the menus are updated every time the layer is they are on is made visible.
You need a table in your DB named email with at least one column named email.
The data in each row should be in this format: name,email Example: Bob,bob@bob.com
I did test this and verified that it works as long as:
a) you can connect to your database
b) you have a table named email with a column name email
c) you can run PHP on your host server I assume
The php file outputs an XML document, you can just open the PHP directly in the browser and see it's output, might help you get an idea of what it's doing.
The PHP file
test.ajax.php)<?php
header('Content-Type: text/xml');
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\r";
echo "<response>\r\r";
//=============================================================================//
$dbconn = NULL;
function dbconnect($verbose=true) {
global $dbconn;
include('<usernames and pws come in here>');
if (!$dbconn = @mysql_connect("localhost",$name,$pw)){return false;}
if($verbose){echo "\r<!-- opening mysql connection -->\r";}
return true;}
//=============================================================================//
// this function creates a string delimited by "^": "Bob Smith,bob@abc.com^Sally White,sally@xyz.com^John Doe,jdoe@msn.com"
// this function actually serves a bunch of uses, not just the email, I stripped out everything else
// there are some queries where I want unique results only, others I want all results, hence the 'allowDuplicates' toggle
function db_fetch_str($table,$needle,$haystack_1=1,$match_1=1,$allowDuplicates=false,$haystack_2=1,$match_2=1) {
$str = "";
$sql = "SELECT $needle FROM $table WHERE $haystack_1 = '$match_1' AND $haystack_2 = '$match_2'";
$result = @mysql_query($sql);
if ( !$result || !mysql_affected_rows())
{
$str .= "-- NONE --";
}
else
{
$delimiter = "";
$dups = array();
while ( $row = @mysql_fetch_array($result))
{
if ( $allowDuplicates || !in_array($row[$needle],$dups) )
{
if (!$allowDuplicates){array_push($dups,$row[$needle]);}
$str .= $delimiter.$row[$needle];
$delimiter = "^";
}
}
}
return($str);
}
// ------------------------------------------------------------- //
$connection_open = dbconnect(false) or die(" <status>FAILED DBCONN</status>\r</response>");
@mysql_select_db("<name of your database>") or die(" <status>FAILED DBSELECT</status>\r</response>");
echo "<status>SUCCESS</status>\r";
echo "<email>".db_fetch_str('email','email',1,1,true)."</email>\r";
echo "\r</response>";
if ($connection_open){@mysql_close($dbconn);}?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Untitled Document</title>
<script type="text/javascript">
<!--
function HttpClient() { } // HTTPCLIENT CLASS
HttpClient.prototype = {
// type GET,POST passed to open
requestType:'GET',
// when set to true, async calls are made
isAsync:true,
// where an XMLHttpRequest instance is stored
xmlhttp:false,
// what is called when a successful async call is made
callback:false,
// what is called when send is called on XMLHttpRequest
// set your own function to onSend to have a custom loading
// effect
onSend:function()
{
//document.getElementById('HttpClientStatus').style.display = 'block';
},
// what is called when readyState 4 is reached, this is
// called before your callback
onload:function()
{
//document.getElementById('HttpClientStatus').style.display = 'none';
},
// what is called when an http error happens
onError:function(error)
{
alert(error);
},
// method to initialize an xmlhttpclient
init:function()
{
try
{
// Mozilla / Safari
this.xmlhttp = new XMLHttpRequest();
}
catch (e)
{
// IE
var XMLHTTP_IDS = new Array('MSXML2.XMLHTTP.5.0',
'MSXML2.XMLHTTP.4.0',
'MSXML2.XMLHTTP.3.0',
'MSXML2.XMLHTTP',
'Microsoft.XMLHTTP');
var success = false;
for (var i=0;i < XMLHTTP_IDS.length && !success; i++)
{
try
{
this.xmlhttp = new ActiveXObject
(XMLHTTP_IDS[i]);
success = true;
}
catch (e)
{}
}
if (!success)
{
this.onError('Unable to create XMLHttpRequest.');
}
}
},
// method to make a page request
// @param string url The page to make the request to
// @param string payload What you're sending if this is a POST
// request
makeRequest: function(url,payload)
{
if (!this.xmlhttp)
{
this.init();
}
this.xmlhttp.open(this.requestType,url,this.isAsync);
// set onreadystatechange here since it will be reset after a
//completed call in Mozilla
var self = this;
this.xmlhttp.onreadystatechange = function()
{
self._readyStateChangeCallback();
}
if (this.requestType == "POST")
{
this.xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
this.xmlhttp.setRequestHeader("Content-length", payload.length);
this.xmlhttp.setRequestHeader("Connection", "close");
}
this.xmlhttp.send(payload);
if (!this.isAsync)
{
return this.xmlhttp.responseXML;
}
},
// internal method used to handle ready state changes
_readyStateChangeCallback:function()
{
switch(this.xmlhttp.readyState)
{
case 2:
this.onSend();
break;
case 4:
this.onload();
if (this.xmlhttp.status == 200)
{
this.callback(this.xmlhttp.responseXML);
}
else
{
this.onError('HTTP Error Making Request: ' + '[' + this.xmlhttp.status + ']' + ' ' + this.xmlhttp.statusText);
}
break;
}
}
}
var client = new HttpClient();// create an instance of the object
client.isAsync = false;// I personally set this to false to hold execution until the request is finished
var company_email = null;// declare the global
var http_status = null; // global I use to keep track of status
function get_global_email()
{
client.requestType = "GET";
// function to handle completed calls
client.callback = function(XMLresult)
{
if (XMLresult.getElementsByTagName("status"))// did XML page create a 'status' element?
{
http_status = XMLresult.getElementsByTagName("status")[0].childNodes[0].nodeValue;
}else{// if no 'status' element was returned, set global http_status to FAILED NO STATUS
http_status = "FAILED NO STATUS";
return;
}
if (http_status == "SUCCESS") {// if we got a SUCCESS in 'status' element, put row data in global variable
// use of split("^") gives us an array of "name,email" pairs.
company_email = XMLresult.getElementsByTagName("email")[0].childNodes[0].nodeValue.split("^");
}
}
client.makeRequest('test.ajax.php?sid='+Math.random(),null);
return;
}
function build_contact_list()
{
http_status=null; // make sure it's clear beforehand
get_global_email(); // call our ajax function to retrieve contact info from database
// handle incomplete requests
if (http_status != "SUCCESS"){alert("something went wrong:"+http_status);return;}
var cm = document.getElementById("contact_menu"); // get the select element
// remove all options from this select element
while ( cm.options.length )
{
cm.remove(cm.options[0]);
}
for ( var i = 0; i < company_email.length; i++ )
{
var newOpt=document.createElement('option');
// now seperate the name from the email address
var tmp = company_email[i].split(",");
newOpt.text=tmp[0];// set the persons name as the text of the option element
try
{
cm.add(newOpt,null); // standards compliant
}
catch(ex)
{
cm.add(newOpt); // IE only
}
cm.options[i].value = tmp[1];// set the email address as the value of the option element
cm.selectedIndex = 0;
}
}
-->
</script>
</head>
<body>
<div>
<select id="contact_menu">
<option></option><!-- dummy option so you don't throw validation errors -->
</select>
<br>
<button type="button" onClick="build_contact_list()">Build The Menu</button>
</div>
</body>
</html>My disclaimer is that I have never been trained in programming, only self taught, so any pro's out there that see anything they wish to comment on, I would be happy to receive the critique.(with the exception of the HTML portion of the doc above that I just threw together for this example)

For simplicity I have been retrieving all rows I get from my database this way, in a "^" delimited string that I split once I have retrieved it.
Hope this helps you with your menu building.
This method has worked great so far, my goal for the app I am working on is to never have to reload the page and the menus are updated every time the layer is they are on is made visible.
•
•
Join Date: Sep 2007
Posts: 25
Reputation:
Rep Power: 2
Solved Threads: 0
Interesting approach you've got here.. appreciate your time.
I am no programmer myself, just trying to work things out :/
I tried your example and it worked fine.
My requirements are a bit different though,
I have two <select> boxes.
first contains a list of countries
second would a list of the cities in the selected country (i.e will be changed each time the first select is changed)
any ideas?
P.S: i found out that closing the <option> is optional in most of the browsers. did close it anyways though.
I am no programmer myself, just trying to work things out :/
I tried your example and it worked fine.
My requirements are a bit different though,
I have two <select> boxes.
first contains a list of countries
second would a list of the cities in the selected country (i.e will be changed each time the first select is changed)
any ideas?
P.S: i found out that closing the <option> is optional in most of the browsers. did close it anyways though.
•
•
Join Date: Sep 2007
Location: Nevada, U.S.A.
Posts: 41
Reputation:
Rep Power: 2
Solved Threads: 1
Browsers will go into quirks mode when encountering markup errors, they try to correct your errors which can from my understanding result in slower pages and pages that do not render quite right.
Again from my understanding it is best to use a strict doc type and validate your code, the strict doc type tells the browser your doc contains no errors and to render it exactly as you have written.
On your cascading selects, that is actually more simple than you might think, I have them implemented 3-deep in my current app.
Here is an example of 2-deep cascading selects for country and city.
When you change the value of country, the "onChange" calls the function to rebuild the city menu, sending it's value for the function to use.
You will of course need to have all the arrays filled, you should be able to use the previous examples to fill in global variables for countries and cities.
Example:
You might use one global variable for the cities menu, and add an ajax call from the build_city_menu
function requesting the cities from your database for the country name passed to the function, have the returned result a comma delimited string place right into a global city_list and replace cities[] with that.
That would save you having to fill city lists for every country.
Again from my understanding it is best to use a strict doc type and validate your code, the strict doc type tells the browser your doc contains no errors and to render it exactly as you have written.
On your cascading selects, that is actually more simple than you might think, I have them implemented 3-deep in my current app.
Here is an example of 2-deep cascading selects for country and city.
When you change the value of country, the "onChange" calls the function to rebuild the city menu, sending it's value for the function to use.
You will of course need to have all the arrays filled, you should be able to use the previous examples to fill in global variables for countries and cities.
Example:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Untitled Document</title>
<script type="text/javascript">
<!--
var cities = new Array();
cities["country1"]="c1city1,c1city2,c1city3";
cities["country2"]="c2city1,c2city2,c2city3";
cities["country3"]="c3city1,c3city2,c3city3";
function build_city_menu(country)
{
var cs = document.getElementById("city_menu");
// remove all options from it
while ( cs.options.length )
{
cs.remove(cs.options[0]);
}
var cty = cities[country].split(",");
for ( var i = 0; i < cty.length; i++ )
{
// create new option element
var newOpt=document.createElement('option');
newOpt.text=cty[i];
// try adding the option to the select object
try
{
cs.add(newOpt,null); // standards compliant
}
catch(ex)
{
cs.add(newOpt); // IE only
}
// set the value to same as the text
cs.options[i].value = cty[i];
}
// set selected index
cs.selectedIndex = 0;
}
-->
</script>
</head>
<body onLoad="build_city_menu('country1')">
<select id="country_menu" onchange="build_city_menu(this.value)">
<option value="country1" selected="selected">country 1</option>
<option value="country2">country 2</option>
<option value="country3">country 3</option>
</select>
<select id="city_menu">
<option></option>
</select>
</body>
</html>You might use one global variable for the cities menu, and add an ajax call from the build_city_menu
function requesting the cities from your database for the country name passed to the function, have the returned result a comma delimited string place right into a global city_list and replace cities[] with that.
That would save you having to fill city lists for every country.
Last edited by HazardTW : Sep 13th, 2007 at 1:19 pm. Reason: Added a comment
•
•
Join Date: Sep 2007
Posts: 25
Reputation:
Rep Power: 2
Solved Threads: 0
point taken regarding strict doc type. spot on.
In my first post I managed to populate the second select box just fine. the whole problem was in the Ajax call.
I couldnt manage to write a proper ajax method that would work on all browsers (firefox didnt like my method) (refer to my first post)
it would be nice to see your way of doing it.
cheers mate.
•
•
•
•
You might use one global variable for the cities menu, and add an ajax call from the build_city_menu
function requesting the cities from your database for the country name passed to the function, have the returned result a comma delimited string place right into a global city_list and replace cities[] with that.
That would save you having to fill city lists for every country.
In my first post I managed to populate the second select box just fine. the whole problem was in the Ajax call.
I couldnt manage to write a proper ajax method that would work on all browsers (firefox didnt like my method) (refer to my first post)
it would be nice to see your way of doing it.
cheers mate.
•
•
Join Date: Sep 2007
Location: Nevada, U.S.A.
Posts: 41
Reputation:
Rep Power: 2
Solved Threads: 1
I will post more when I get home, but wanted to say thanks for that comment MidiMagic, I had not thought about that, so far I have had no problems, keeping fingers crossed.
Regarding Firefox not liking your HTTP requests, I have not figured why that is, but installing Firebug has worked on 3 PC's with Firefox 2.0.0.6 installed.
Each would not run my app until I installed Firebug, just google it, easy to find and install.
What's funny is I initially installed Firebug so I could view the response headers to see what was going on, but it magically started working then
EDIT: btw MidiMagic, are you referring to html created via document.write(), .innerHTML, or .createElement() + .appendChild()??
Regarding Firefox not liking your HTTP requests, I have not figured why that is, but installing Firebug has worked on 3 PC's with Firefox 2.0.0.6 installed.
Each would not run my app until I installed Firebug, just google it, easy to find and install.
What's funny is I initially installed Firebug so I could view the response headers to see what was going on, but it magically started working then

EDIT: btw MidiMagic, are you referring to html created via document.write(), .innerHTML, or .createElement() + .appendChild()??
Last edited by HazardTW : Sep 13th, 2007 at 7:49 pm. Reason: Additional comment
•
•
Join Date: Sep 2007
Location: Nevada, U.S.A.
Posts: 41
Reputation:
Rep Power: 2
Solved Threads: 1
OK, here is an example, this one does not make an ajax request every time the country is changed, it only makes the request after page load, gets the countries and cities from the database and puts them in global variables.
The table name is test, the fields are "country" and "cities" where "country" is the country name, and "cities" is a comma delimited string of city names for that country.
Here is the PHP file that creates the XML response doc:
With the data I put in the database table, the resulting XML doc looks like this:
Here is the HTML, tested it, it works:
From this you should be able to extend it's capabilities to suit your needs, hopefully it's commented enough, I am bad about not commenting my work enough
The table name is test, the fields are "country" and "cities" where "country" is the country name, and "cities" is a comma delimited string of city names for that country.
Here is the PHP file that creates the XML response doc:
<?php
header('Content-Type: text/xml');
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\r";
echo "<response>\r\r";
//=============================================================================//
$dbconn = NULL;
function dbconnect($verbose=true) {
global $dbconn;
include('<usernames and pws come in here>');
if (!$dbconn = @mysql_connect("localhost",$name,$pw)){return false;}
if($verbose){echo "\r<!-- opening mysql connection -->\r";}
return true;}
//=============================================================================//
$connection_open = dbconnect(false) or die(" <status>FAILED DBCONN</status>\r</response>");
@mysql_select_db("<name of your database>") or die(" <status>FAILED DBSELECT</status>\r</response>");
// ------------------------------------------------------------- //
echo "<status>SUCCESS</status>\r";
$sql = "SELECT * FROM test";
$result = @mysql_query($sql);
if ( !$result || !mysql_affected_rows())// if query failed OR no rows in the table output -- NONE --
{
echo "<countries>-- NONE --</countries>\r";
}
else
{
while ($row = @mysql_fetch_array($result))
{
echo "<countries>" . $row[country] . "|" . $row[cities] . "</countries>\r";
}
}
//================================================================================================
echo "\r</response>";
if ($connection_open){@mysql_close($dbconn);}?><response> <status>SUCCESS</status> − <countries> America|Los Angeles,New York,Miami,Dallas,Portland,Chicago,Casper </countries> − <countries> Canada|Vancouver,Abbotsford,Armstrong,Burnaby,Castlegar,Chilliwack,Colwood,Coquitlam </countries> − <countries> Mexico|Cancun,Cabo San Lucas,Los Cabos,San Jose del Cabo,Cozumel,Isla Mujeres,Riviera Maya,Acapulco </countries> </response>
Here is the HTML, tested it, it works:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
<script type="text/javascript">
<!--
function HttpClient() { } // HTTPCLIENT CLASS
HttpClient.prototype = {
// type GET,POST passed to open
requestType:'GET',
// when set to true, async calls are made
isAsync:true,
// where an XMLHttpRequest instance is stored
xmlhttp:false,
// what is called when a successful async call is made
callback:false,
// what is called when send is called on XMLHttpRequest
// set your own function to onSend to have a custom loading
// effect
onSend:function()
{
//document.getElementById('HttpClientStatus').style.display = 'block';
},
// what is called when readyState 4 is reached, this is
// called before your callback
onload:function()
{
//document.getElementById('HttpClientStatus').style.display = 'none';
},
// what is called when an http error happens
onError:function(error)
{
alert(error);
},
// method to initialize an xmlhttpclient
init:function()
{
try
{
// Mozilla / Safari
this.xmlhttp = new XMLHttpRequest();
}
catch (e)
{
// IE
var XMLHTTP_IDS = new Array('MSXML2.XMLHTTP.5.0',
'MSXML2.XMLHTTP.4.0',
'MSXML2.XMLHTTP.3.0',
'MSXML2.XMLHTTP',
'Microsoft.XMLHTTP');
var success = false;
for (var i=0;i < XMLHTTP_IDS.length && !success; i++)
{
try
{
this.xmlhttp = new ActiveXObject
(XMLHTTP_IDS[i]);
success = true;
}
catch (e)
{}
}
if (!success)
{
this.onError('Unable to create XMLHttpRequest.');
}
}
},
// method to make a page request
// @param string url The page to make the request to
// @param string payload What you're sending if this is a POST
// request
makeRequest: function(url,payload)
{
if (!this.xmlhttp)
{
this.init();
}
this.xmlhttp.open(this.requestType,url,this.isAsync);
// set onreadystatechange here since it will be reset after a
//completed call in Mozilla
var self = this;
this.xmlhttp.onreadystatechange = function()
{
self._readyStateChangeCallback();
}
if (this.requestType == "POST")
{
this.xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
this.xmlhttp.setRequestHeader("Content-length", payload.length);
this.xmlhttp.setRequestHeader("Connection", "close");
}
this.xmlhttp.send(payload);
if (!this.isAsync)
{
return this.xmlhttp.responseXML;
}
},
// internal method used to handle ready state changes
_readyStateChangeCallback:function()
{
switch(this.xmlhttp.readyState)
{
case 2:
this.onSend();
break;
case 4:
this.onload();
if (this.xmlhttp.status == 200)
{
this.callback(this.xmlhttp.responseXML);
}
else
{
this.onError('HTTP Error Making Request: ' + '[' + this.xmlhttp.status + ']' + ' ' + this.xmlhttp.statusText);
}
break;
}
}
}
//----------------------------------------------------------------------------------------------------//
var client = new HttpClient();
client.isAsync = false;
var countries = "";
var cities = new Array();
http_status = null;
function get_country_city_list()
{
client.requestType = "GET";
// function to handle completed calls
client.callback = function(XMLresult)
{
if (XMLresult.getElementsByTagName("status"))// did XML page create a 'status' element?
{
http_status = XMLresult.getElementsByTagName("status")[0].childNodes[0].nodeValue;
}else{// if no 'status' element was returned, set global http_status to FAILED
http_status = "FAILED NO RESPONSE";
return;
}
if (http_status == "SUCCESS") {// if we got a SUCCESS in 'status' element, put row data in global variable
// var results will be an array of all the <countries></countries> rows in the XML document
var results = XMLresult.getElementsByTagName("countries");
var comma = "";
// I am going to make countries a comma delimited string of the country names
countries = ""; // make sure we clear this global first
for (var i=0; i<results.length; i++){// itterate through results
// each row in results is formatted "countryname | city,city,city,city"
// by spliting the result at the pipe we get a 2 element array
//tmp[0]=country name tmp[1]=string of cities
var tmp = results[i].childNodes[0].nodeValue.split("|");
countries += comma + tmp[0];// build the list of countries
comma = ",";
cities[tmp[0]] = tmp[1]; // use country name as key for cities array and assign the cityname string
}
}
}
client.makeRequest('country_test.php?sid='+Math.random(),null);
return;
}
function build_country_menu()
{
http_status = null; // make sure this is cleared
get_country_city_list() // make the ajax call
if (http_status != "SUCCESS"){alert("something went wrong");return;}
var cc = document.getElementById("country_menu");
// remove all options from it
while ( cc.options.length )
{
cc.remove(cc.options[0]);
}
var ctry = countries.split(",");
for ( var i = 0; i < ctry.length; i++ )
{
// create new option element
var newOpt=document.createElement('option');
newOpt.text=ctry[i];
// try adding the option to the select object
try
{
cc.add(newOpt,null); // standards compliant
}
catch(ex)
{
cc.add(newOpt); // IE only
}
// set the value to same as the text
cc.options[i].value = ctry[i];
}
// set selected index
cc.selectedIndex = 0;
build_city_menu(ctry[0]); // will need to rebuild the city list
}
function build_city_menu(country)
{
var cs = document.getElementById("city_menu");
// remove all options from it
while ( cs.options.length )
{
cs.remove(cs.options[0]);
}
var cty = cities[country].split(",");
for ( var i = 0; i < cty.length; i++ )
{
// create new option element
var newOpt=document.createElement('option');
newOpt.text=cty[i];
// try adding the option to the select object
try
{
cs.add(newOpt,null); // standards compliant
}
catch(ex)
{
cs.add(newOpt); // IE only
}
// set the value to same as the text
cs.options[i].value = cty[i];
}
// set selected index
cs.selectedIndex = 0;
}
-->
</script>
</head>
<body onload="build_country_menu()">
<select id="country_menu" onchange="build_city_menu(this.value)">
<option></option>
</select>
<select id="city_menu">
<option></option>
</select>
</body>
</html>From this you should be able to extend it's capabilities to suit your needs, hopefully it's commented enough, I am bad about not commenting my work enough
![]() |
•
•
•
•
•
•
•
•
DaniWeb JavaScript / DHTML / AJAX Marketplace
•
•
•
•
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
•
•
•
•
ajax asp beta bon browser browsers browsing developer development echo email encryption europe firefox gecko home html internet internet explorer internet explorer 7 javascript leak linux memory microsoft mozilla msdn networking news office open source open-source patch phishing scams security site social software sql super testing users vista web webmail
- No ajax responseText received in firefox. (JavaScript / DHTML / AJAX)
- Levyo Ajax Gallery supports Firefox 2.0.1 only?? (Software Developers' Lounge)
- AJAX : Am i right with the concept? (JavaScript / DHTML / AJAX)
- Firefox default (Don't want Epiphany) (*nix Software)
- Problems with Windows Explorer (Windows NT / 2000 / XP / 2003)
- javascript to add select button (JavaScript / DHTML / AJAX)
- Internet Explorer vs Firefox (Web Browsers)
Other Threads in the JavaScript / DHTML / AJAX Forum
- Previous Thread: Simple JS question(DWR)
- Next Thread: Getting Permission denied in IE 7 when trying to print from child window


Hybrid Mode