Ja, så er Ajax klart løsningen. Det er ikke helt simpelt, men prøv at følge princippet i denne kode - og spørg, hvis der er noget, du er i tvivl om eller undrer dig over:
<script type="text/javascript">
function getTheRest(elmSrc, elmDestID) {
var oXHR = new XMLHttpRequest(),
sVal = elmSrc.value,
sQuery = "context=getSomething&dest="+elmDestID+"&value="+encodeURIComponent(sVal);
oXHR.open("post", "response.php", true);
oXHR.setRequestHeader("Content-Type: application/x-www-form-urlencoded; charset=utf-8");
oXHR.onreadystatechange = function() {
if (this.readyState<4) return;
fillSelect(this.responseText);
}
oXHR.send(sQuery);
}
function fillSelect(sResp) {
var oResp = null;
try {
oResp = JSON.parse(sResp);
}
catch(e) {
return alert("Fejl: Responsen fra serveren kunne ikke parses.");
}
if (oResp.error) return alert("Fejl: "+oResp.error);
var oTempl, elmTemp, elmDest = document.getElementById(oResp.dest);
while (elmDest.firstChild!==elmDest.lastChild) {
elmDest.removeChild(elmDest.lastChild);
}
oTempl = elmDest.removeChild(elmDest.firstChild);
for (var i=0,j=oResp.rows.length; i<j; i++) {
elmTemp = oTempl.cloneNode(true);
elmTemp.setAttribute("value", oResp.rows.val);
elmTemp.firstChild.nodeValue = oResp.rows[i].txt;
elmDest.appendChild(elmTemp);
}
elmDest.attributes.removeNamedItem("disabled");
oResp = oTempl = null;
}
</script>
<div>
<select id="sel_1" onchange="getTheRest(this, 'sel_2')">
<option value="-1">Vælg ...</option>
<option value="foo">Foo</option>
<option value="bar">Bar</option>
<option value="foobar">FooBar</option>
</select>
<select id="sel_2" disabled="disabled">
<option> </option>
</select>
</div>
response.php kunne så se nogenlunde sådan ud:
<?php
/* Functions for different tasks */
function getSomething($json) {
/* Pseudo code: $res = Query DB using $_POST['value'] */
$res = [MYSQL_QUERY];
$rows = array();
while ($row=mysql_fetch_object($res)) {
$rows = $row;
}
$json->rows = $rows;
return $json;
}
/* ------- Functions End ------- */
if (!empty($_POST)) {
header('Content-Type: application/json; charset=utf-8');
$json = new stdClass();
if (isset($_POST['context'])) {
switch ($_POST['context']) {
case 'getSomething':
$json = getSomething($json);
break;
default:
$json->error = 'Unknown contextID: "'.$_POST['context'].'"';
}
}
else $json->error = 'No contextID found.';
echo json_encode($json);
}
?>
I HTML-filen skal du lægge mærke til, at den enlige option (og standarden kræver, der er mindst én option) [i]skal indeholde tekst - mindst et
. Ellers virker scriptet ikke (
elmTemp.firstChild.nodeValue vil fejle uden).
Læg også mærke til de to værdier 'val' og 'txt', som skal svare til feltnavnene i databasen:
elmTemp.setAttribute("value", oResp.rows[i].val);
elmTemp.firstChild.nodeValue = oResp.rows[i].txt;
Læg også mærke til at jeg referer til oXHR-objektet med nøgleordet
this indenfor event handleren. Det gør jeg for at undgå en cirkulær reference over en closure (= memory leak i IE før version 9).
Skulle der opstå en fejl i funktionen
getTheRest i PHP-filen, kan du jo sætte den som
$json->error og straks returnere
$json til kaldet i switchen. Så kan den aflæses i alert'en i HTML-filen.
Koden er skrevet fra hoften uden test. Jeg har efterhånden øvelsen (nu må jeg zq snart få skrevet den guide færdig!), men ronols må meget gerne kikke med og klappe mig én i nakken, hvis der skulle være fejl =)