AJAX generated <select> and FIREFOX

Please support our JavaScript / DHTML / AJAX advertiser: PostgreSQL or MySQL? Compare and contrast the two most popular open source databases
Reply

Join Date: Sep 2007
Posts: 54
Reputation: HazardTW is an unknown quantity at this point 
Solved Threads: 2
HazardTW HazardTW is offline Offline
Junior Poster in Training

Re: AJAX generated <select> and FIREFOX

 
1
  #11
Sep 13th, 2007
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:
JavaScript / DHTML / AJAX Syntax (Toggle Plain Text)
  1. <?php
  2. header('Content-Type: text/xml');
  3. header("Cache-Control: no-cache, must-revalidate");
  4. header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  5. echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\r";
  6. echo "<response>\r\r";
  7. //=============================================================================//
  8. $dbconn = NULL;
  9. function dbconnect($verbose=true) {
  10. global $dbconn;
  11. include('<usernames and pws come in here>');
  12. if (!$dbconn = @mysql_connect("localhost",$name,$pw)){return false;}
  13. if($verbose){echo "\r<!-- opening mysql connection -->\r";}
  14. return true;}
  15. //=============================================================================//
  16. $connection_open = dbconnect(false) or die(" <status>FAILED DBCONN</status>\r</response>");
  17. @mysql_select_db("<name of your database>") or die(" <status>FAILED DBSELECT</status>\r</response>");
  18. // ------------------------------------------------------------- //
  19. echo "<status>SUCCESS</status>\r";
  20.  
  21. $sql = "SELECT * FROM test";
  22. $result = @mysql_query($sql);
  23. if ( !$result || !mysql_affected_rows())// if query failed OR no rows in the table output -- NONE --
  24. {
  25. echo "<countries>-- NONE --</countries>\r";
  26. }
  27. else
  28. {
  29. while ($row = @mysql_fetch_array($result))
  30. {
  31. echo "<countries>" . $row[country] . "|" . $row[cities] . "</countries>\r";
  32. }
  33.  
  34. }
  35. //================================================================================================
  36. echo "\r</response>";
  37. if ($connection_open){@mysql_close($dbconn);}?>
With the data I put in the database table, the resulting XML doc looks like this:
JavaScript / DHTML / AJAX Syntax (Toggle Plain Text)
  1. <response>
  2. <status>SUCCESS</status>
  3. <countries>
  4. America|Los Angeles,New York,Miami,Dallas,Portland,Chicago,Casper
  5. </countries>
  6. <countries>
  7. Canada|Vancouver,Abbotsford,Armstrong,Burnaby,Castlegar,Chilliwack,Colwood,Coquitlam
  8. </countries>
  9. <countries>
  10. Mexico|Cancun,Cabo San Lucas,Los Cabos,San Jose del Cabo,Cozumel,Isla Mujeres,Riviera Maya,Acapulco
  11. </countries>
  12. </response>

Here is the HTML, tested it, it works:
JavaScript / DHTML / AJAX Syntax (Toggle Plain Text)
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml">
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  5. <title>Untitled Document</title>
  6. <script type="text/javascript">
  7. <!--
  8. function HttpClient() { } // HTTPCLIENT CLASS
  9. HttpClient.prototype = {
  10. // type GET,POST passed to open
  11. requestType:'GET',
  12. // when set to true, async calls are made
  13. isAsync:true,
  14. // where an XMLHttpRequest instance is stored
  15. xmlhttp:false,
  16. // what is called when a successful async call is made
  17. callback:false,
  18. // what is called when send is called on XMLHttpRequest
  19. // set your own function to onSend to have a custom loading
  20. // effect
  21. onSend:function()
  22. {
  23. //document.getElementById('HttpClientStatus').style.display = 'block';
  24. },
  25.  
  26. // what is called when readyState 4 is reached, this is
  27. // called before your callback
  28. onload:function()
  29. {
  30. //document.getElementById('HttpClientStatus').style.display = 'none';
  31. },
  32.  
  33. // what is called when an http error happens
  34. onError:function(error)
  35. {
  36. alert(error);
  37. },
  38.  
  39. // method to initialize an xmlhttpclient
  40. init:function()
  41. {
  42. try
  43. {
  44. // Mozilla / Safari
  45. this.xmlhttp = new XMLHttpRequest();
  46. }
  47. catch (e)
  48. {
  49. // IE
  50. var XMLHTTP_IDS = new Array('MSXML2.XMLHTTP.5.0',
  51. 'MSXML2.XMLHTTP.4.0',
  52. 'MSXML2.XMLHTTP.3.0',
  53. 'MSXML2.XMLHTTP',
  54. 'Microsoft.XMLHTTP');
  55. var success = false;
  56. for (var i=0;i < XMLHTTP_IDS.length && !success; i++)
  57. {
  58. try
  59. {
  60. this.xmlhttp = new ActiveXObject
  61. (XMLHTTP_IDS[i]);
  62. success = true;
  63. }
  64. catch (e)
  65. {}
  66. }
  67. if (!success)
  68. {
  69. this.onError('Unable to create XMLHttpRequest.');
  70. }
  71. }
  72. },
  73. // method to make a page request
  74. // @param string url The page to make the request to
  75. // @param string payload What you're sending if this is a POST
  76. // request
  77. makeRequest: function(url,payload)
  78. {
  79. if (!this.xmlhttp)
  80. {
  81. this.init();
  82. }
  83. this.xmlhttp.open(this.requestType,url,this.isAsync);
  84.  
  85. // set onreadystatechange here since it will be reset after a
  86. //completed call in Mozilla
  87. var self = this;
  88. this.xmlhttp.onreadystatechange = function()
  89. {
  90. self._readyStateChangeCallback();
  91. }
  92. if (this.requestType == "POST")
  93. {
  94. this.xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  95. this.xmlhttp.setRequestHeader("Content-length", payload.length);
  96. this.xmlhttp.setRequestHeader("Connection", "close");
  97. }
  98.  
  99. this.xmlhttp.send(payload);
  100.  
  101. if (!this.isAsync)
  102. {
  103. return this.xmlhttp.responseXML;
  104. }
  105. },
  106.  
  107. // internal method used to handle ready state changes
  108. _readyStateChangeCallback:function()
  109. {
  110. switch(this.xmlhttp.readyState)
  111. {
  112. case 2:
  113. this.onSend();
  114. break;
  115. case 4:
  116. this.onload();
  117. if (this.xmlhttp.status == 200)
  118. {
  119. this.callback(this.xmlhttp.responseXML);
  120. }
  121. else
  122. {
  123. this.onError('HTTP Error Making Request: ' + '[' + this.xmlhttp.status + ']' + ' ' + this.xmlhttp.statusText);
  124. }
  125. break;
  126. }
  127. }
  128. }
  129. //----------------------------------------------------------------------------------------------------//
  130.  
  131. var client = new HttpClient();
  132. client.isAsync = false;
  133. var countries = "";
  134. var cities = new Array();
  135. http_status = null;
  136.  
  137. function get_country_city_list()
  138. {
  139. client.requestType = "GET";
  140. // function to handle completed calls
  141. client.callback = function(XMLresult)
  142. {
  143. if (XMLresult.getElementsByTagName("status"))// did XML page create a 'status' element?
  144. {
  145. http_status = XMLresult.getElementsByTagName("status")[0].childNodes[0].nodeValue;
  146. }else{// if no 'status' element was returned, set global http_status to FAILED
  147. http_status = "FAILED NO RESPONSE";
  148. return;
  149. }
  150. if (http_status == "SUCCESS") {// if we got a SUCCESS in 'status' element, put row data in global variable
  151.  
  152. // var results will be an array of all the <countries></countries> rows in the XML document
  153. var results = XMLresult.getElementsByTagName("countries");
  154.  
  155. var comma = "";
  156.  
  157. // I am going to make countries a comma delimited string of the country names
  158. countries = ""; // make sure we clear this global first
  159.  
  160. for (var i=0; i<results.length; i++){// itterate through results
  161.  
  162. // each row in results is formatted "countryname | city,city,city,city"
  163. // by spliting the result at the pipe we get a 2 element array
  164. //tmp[0]=country name tmp[1]=string of cities
  165. var tmp = results[i].childNodes[0].nodeValue.split("|");
  166.  
  167. countries += comma + tmp[0];// build the list of countries
  168.  
  169. comma = ",";
  170.  
  171. cities[tmp[0]] = tmp[1]; // use country name as key for cities array and assign the cityname string
  172.  
  173. }
  174. }
  175. }
  176. client.makeRequest('country_test.php?sid='+Math.random(),null);
  177. return;
  178. }
  179.  
  180. function build_country_menu()
  181. {
  182. http_status = null; // make sure this is cleared
  183.  
  184. get_country_city_list() // make the ajax call
  185.  
  186. if (http_status != "SUCCESS"){alert("something went wrong");return;}
  187.  
  188. var cc = document.getElementById("country_menu");
  189. // remove all options from it
  190. while ( cc.options.length )
  191. {
  192. cc.remove(cc.options[0]);
  193. }
  194.  
  195. var ctry = countries.split(",");
  196.  
  197. for ( var i = 0; i < ctry.length; i++ )
  198. {
  199. // create new option element
  200. var newOpt=document.createElement('option');
  201.  
  202. newOpt.text=ctry[i];
  203. // try adding the option to the select object
  204. try
  205. {
  206. cc.add(newOpt,null); // standards compliant
  207. }
  208. catch(ex)
  209. {
  210. cc.add(newOpt); // IE only
  211. }
  212. // set the value to same as the text
  213. cc.options[i].value = ctry[i];
  214. }
  215. // set selected index
  216. cc.selectedIndex = 0;
  217. build_city_menu(ctry[0]); // will need to rebuild the city list
  218. }
  219.  
  220.  
  221. function build_city_menu(country)
  222. {
  223. var cs = document.getElementById("city_menu");
  224. // remove all options from it
  225. while ( cs.options.length )
  226. {
  227. cs.remove(cs.options[0]);
  228. }
  229.  
  230. var cty = cities[country].split(",");
  231.  
  232. for ( var i = 0; i < cty.length; i++ )
  233. {
  234. // create new option element
  235. var newOpt=document.createElement('option');
  236.  
  237. newOpt.text=cty[i];
  238. // try adding the option to the select object
  239. try
  240. {
  241. cs.add(newOpt,null); // standards compliant
  242. }
  243. catch(ex)
  244. {
  245. cs.add(newOpt); // IE only
  246. }
  247. // set the value to same as the text
  248. cs.options[i].value = cty[i];
  249. }
  250. // set selected index
  251. cs.selectedIndex = 0;
  252. }
  253. -->
  254. </script>
  255. </head>
  256.  
  257. <body onload="build_country_menu()">
  258.  
  259. <select id="country_menu" onchange="build_city_menu(this.value)">
  260. <option></option>
  261. </select>
  262.  
  263. <select id="city_menu">
  264. <option></option>
  265. </select>
  266.  
  267. </body>
  268. </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
Reply With Quote Quick reply to this message  
Join Date: Sep 2007
Posts: 25
Reputation: roy-- is an unknown quantity at this point 
Solved Threads: 0
roy-- roy-- is offline Offline
Light Poster

Re: AJAX generated <select> and FIREFOX

 
0
  #12
Sep 14th, 2007
Spot on mate!

I really appreciate your time.

Although, in your example you assumed that I have the countries and cities in one table..

where as a matter of fact i have them in two seperate tables,

countries table: [countrycode] [name]

cities table: [countrycode] [city_id] [name] [nr_hotels]

What I need is to construct the options in a way that would show the city and number of hotels between brackets (i.e. London (45 hotels) )

I am sure there is a way of constructing this into the <countries> tag in your php script. Just not sure how! :s
Reply With Quote Quick reply to this message  
Join Date: Sep 2007
Posts: 54
Reputation: HazardTW is an unknown quantity at this point 
Solved Threads: 2
HazardTW HazardTW is offline Offline
Junior Poster in Training

Re: AJAX generated <select> and FIREFOX

 
0
  #13
Sep 15th, 2007
Your PHP file should be able to query more than one table to build your information and you can build a more complicated doc from it, I just try to keep it as simple as I can, I am complete rookie with XML and ajax.

If you first query your country table, get the list in an array $countries[] for example.
Then iterate through it, each pass using the country code to query your cities table.

Kind of like:

JavaScript / DHTML / AJAX Syntax (Toggle Plain Text)
  1. echo "<response>\r";
  2. $countries = mysql_query("select * from countries");
  3. while ($row = mysql_fetch_array($countries)){
  4. echo "<country>\r";
  5. echo " <code>".$row[countryCode]."</code>\r";
  6. echo " <name>".$row[countryName]."</name>\r";
  7. $sql = "select * from cities where countryCode = '$row[countryCode]'";
  8. $cities = mysql_query($sql);
  9. while ($cty = mysql_fetch_array($cities)){
  10. echo "<city>\r";
  11. echo " <code>".$cty[cityCode]."</code>\r";
  12. echo " <name>".$cty[cityName]."</name>\r";
  13. echo " <hotels>".$cty[cityHotels]."</hotels>\r";
  14. echo "</city>\r";
  15. }
  16. echo "</country>\r";
  17. }
  18. echo "</response>";

I just wrote this here so I have not tried this code, but it should give you the idea.
If your country table had only one country and there were 4 cities in the cities table for that country code, the code above should result in a doc structure like this:

JavaScript / DHTML / AJAX Syntax (Toggle Plain Text)
  1. <response>
  2. <country>
  3. <code>country code</code>
  4. <name>country name</name>
  5. <city>
  6. <code>city code</code>
  7. <name>city name</name>
  8. <hotels>number of hotels</hotels>
  9. </city>
  10. <city>
  11. <code>city code</code>
  12. <name>city name</name>
  13. <hotels>number of hotels</hotels>
  14. </city>
  15. <city>
  16. <code>city code</code>
  17. <name>city name</name>
  18. <hotels>number of hotels</hotels>
  19. </city>
  20. <city>
  21. <code>city code</code>
  22. <name>city name</name>
  23. <hotels>number of hotels</hotels>
  24. </city>
  25. </country>
  26. </response>
and a short bit of javascript to get at the values, I put no assignments in front of the references to each bit of data, how you assign them is up to you, whether you put them in arrays, or straight into form element values, etc...
JavaScript / DHTML / AJAX Syntax (Toggle Plain Text)
  1. // get array of all country tags
  2. var records = XMLresult.getElementsByTagName("country");
  3. // loop through them
  4. for (var i=0; i<records.length; i++){
  5. // since records[i] points to an individual <country>, we can get it's children by tag name
  6. // first the country code
  7. records[i].getElementsByTagName("code")[0].childNodes[0].nodeValue;
  8. // then the country name
  9. records[i].getElementsByTagName("name")[0].childNodes[0].nodeValue;
  10. // now city will be an array of all the <city> tags
  11. var city = records[i].getElementsByTagName("city");
  12. // lets loop through them
  13. for (var z=0; z<city.length; z++){
  14. // get the city code
  15. city[z].getElementsByTagName("code")[0].childNodes[0].nodeValue;
  16. // the city name
  17. city[z].getElementsByTagName("name")[0].childNodes[0].nodeValue;
  18. // and the hotels for this city
  19. city[z].getElementsByTagName("hotels")[0].childNodes[0].nodeValue;
  20. }
  21. }

There may be more proper and better ways of dealing with XML but like I said, I am a noob, and the above is about the extent of my knowledge about it and the easiest way for me to get the information I needed.
The examples I gave before where I put together long comma and ^ delimited strings is because a) I control the data so there are no characters in the data that would break the results and b) creating the multi level document structure makes for a pretty big file real quick and I want my responses as quick as they can be, don't know how much load time it saves but a 1k doc must load a lot quicker than a 40k doc eh?
I hope it helps
Last edited by HazardTW; Sep 15th, 2007 at 5:25 am. Reason: added comment
Reply With Quote Quick reply to this message  
Join Date: Sep 2007
Posts: 25
Reputation: roy-- is an unknown quantity at this point 
Solved Threads: 0
roy-- roy-- is offline Offline
Light Poster

Re: AJAX generated <select> and FIREFOX

 
0
  #14
Sep 15th, 2007
Thanks alot man, will try and make this work now..
Reply With Quote Quick reply to this message  
Join Date: Jan 2007
Posts: 3,210
Reputation: MidiMagic has a spectacular aura about MidiMagic has a spectacular aura about 
Solved Threads: 164
MidiMagic's Avatar
MidiMagic MidiMagic is offline Offline
Nearly a Senior Poster

Re: AJAX generated <select> and FIREFOX

 
0
  #15
Sep 18th, 2007
Anything that changes the HTML file from the original way it loads can cause the interpreter to fail, if the code is not valid. How the extra code is created does not matter.
Daylight-saving time uses more gasoline
Reply With Quote Quick reply to this message  
Join Date: Sep 2007
Posts: 54
Reputation: HazardTW is an unknown quantity at this point 
Solved Threads: 2
HazardTW HazardTW is offline Offline
Junior Poster in Training

Re: AJAX generated <select> and FIREFOX

 
0
  #16
Sep 20th, 2007
haven't tried experimenting but the idea that came to mind was is you inadvertently appended a block level element as a child of an inline element where a validator would flag it as an error, would that type of invalid code cause problems when the doc type is strict.
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:



Similar Threads
Other Threads in the JavaScript / DHTML / AJAX Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC