Script popolamento form selezione comuni – province in Ajax e PHP

Classico problema del form in cui vogliamo popolare una SELECT con i nomi dei Comuni italiani in base alla selezione della Provincia tramite un’altra SELECT. Questo per evitare di dover caricare una SELECT con oltre 8000 campi (tanti sono i Comuni italiani).
Procurarsi un Database contenente le tabelle di province e comuni.
In questo esempio utilizziamo 3 files:

richiesta.php (pagina PHP con lo script)
form.html (pagina web con il form)
select.js (file Javascript)

FORM.HTML

<html>
 <head>
 <title>Ajax-PHP</title>
 <script type="text/javascript" src="lists.js"></script>
 </head>
 <body>
 <form action="form.html" method="post">
 <fieldset>
 <label for="province">Province</label><br />
 <select name="province" id="province" onchange="loadList('citta', getSelected(this))" >
 </select><br />
 <label for="citta">Citta</label><br />
 <select name="citta" id="citta">
 </select><br />
 </fieldset>
 </form>
 <!-- script per precaricare le province  -->
 <script type="text/javascript">
 //<![CDATA[
 loadList('province', 0);
 //]]>
 </script>
 </body>
 </html>


SELECT.JS

var xmlHttp = getXmlHttpObject();
function loadList(tb, id){
 xmlHttp.open('GET', 'richiesta.php?table='+tb+'&id='+id, true);
 xmlHttp.onreadystatechange = stateChanged;
 xmlHttp.send(null);
 }

 function addOption(select, value, text) {
 //Aggiunge un elemento ad una select
 var option = document.createElement("option");
 option.value = value,
 option.text = text;
 try {
 select.add(option, null);
 } catch(e) {
 //Per Internet Explorer
 select.add(option);
 }
 }

 function getSelected(select) {
 //ritorna il valore dell'elemento selezionato
 return select.options[select.selectedIndex].value;
 }

 function stateChanged() {
 if(xmlHttp.readyState == 4) {
 //Stato OK
 if (xmlHttp.status == 200) {
 var resp = xmlHttp.responseText;
if(resp) {
 var values = resp.split(';');
 var listId = values.shift();
 var select = document.getElementById(listId);
 //svuota elementi precedenti
 while (select.options.length) {
 select.remove(0);
 }
if(listId == 'province') {
 addOption (select, 0, '-- Selezionare la provincia --');
 }
 var limit = values.length;
for(i=0; i < limit; i++) {
 var pair = values[i].split('|');
 addOption(select, pair[0], pair[1]);
 }
 }
 } else {
 alert(xmlHttp.responseText);
 }
 }
 }
//funzione per abilitare Ajax, la chiamata è diversa a seconda del browser
 function getXmlHttpObject()
 {
 var xmlHttp=null;
 try
 {
 //Firefox e Opera
 xmlHttp=new XMLHttpRequest();
 }
 catch(e)
 {
 //Internet Explorer
 try
 {
 xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
 }
 catch(e)
 {
 xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
 }
 }
 return xmlHttp;
 } 

REQUEST.PHP

<?php
 define('DB_HOST','localhost');
 define('DB_NAME','nome_del_database');
 define('DB_USER','user_del_database');
 define('DB_PASSWORD','password_del_database');
 $connection= mysql_connect(DB_HOST, DB_USER, DB_PASSWORD) or die;
 mysql_select_db(DB_NAME) or die;
$pid = $_REQUEST['id'];
 $tb = mysql_real_escape_string($_REQUEST['table'], $connection);
switch($tb) {
 case 'province':
 $sql="SELECT id, nome FROM `$tb` ORDER BY nome";
 break;
 case 'citta':
 $sql="SELECT id, nome FROM `$tb` WHERE id_provincia=$pid ORDER BY nome";
 break;
 }
 $out="$tb;";
 if($result = mysql_query($sql, $conn)) {
 while ($row = mysql_fetch_row($result)) {
 $out .= $row[0] . '|' . $row[1] . ';';
 }
 }
 echo rtrim($out, ';');
 ?>