Во-первых, вы можете переписать кусок кода, который создает параметры контракта. Циклический просмотр результатов запроса и выполнение другого запроса для каждой записи неэффективно. Основываясь на ваших запросах, вы можете использовать этот код, который выполняет один запрос, а затем генерирует параметры на основе этого. (Я должен был использовать имена составных столбцов в предложении ORDER. В общем, вы всегда должны сортировать набор записей так, чтобы результаты были в определенном порядке - даже если вам все равно, каков этот порядок.
<select name="idcontract" id="idcontract">
<!--fetch/display contracts/clients-->
<?php
include 'sqldb.php';
$clients = mysqli_query($dbc, '
SELECT ct.idcontract, ct.idclient, cl.name
FROM contract ct LEFT OUTER JOIN client cl ON ct.idclient = cl.idclient
ORDER BY ct.contractname, cl.clientname
');
while ($client = mysqli_fetch_array($clients)) {
echo "<option value=\"{$client[idcontract]}\">{$client[idcontract} {$client[name]}</option>";
}
?>
</select>
<select name="idjob" id="idjob">
<option value="NULL">Please select a contract</option>
</select>
На ваш вопрос, код, который вы ищете, на самом деле не идет туда, где находится этот комментарий. Вам нужен обработчик событий, который отвечает на выбор пользователем опции в первом SELECT; Затем он должен получить значение этой опции и запросить у сервера набор пар ключ-значение для вставки во второй SELECT.
Примерно так:
document.getElementById('idcontract').onchange = function(event) {
// grab currently selected value
var sValue = null;
for(var i = 0, imax = this.childNodes.length; i < imax; i++) {
var eOption = this.childNodes[i]; // shorthand
if(eOption.selected) {
sValue = eOption.value;
break;
}
}
if(!sValue) return;
// get the sub-options for this value
getSubOptions(sValue, function(XHR) {
// this code runs once the response comes back from the server
var aPairs = [];
var nlJobs = XHR.getElementsByTagName('jobs'); // assumptions #1 & #2: response is XML, includes <job> tag for each job
// extract key-value pairs from XML
for(var i = 0, imax = nlJobs.length; i < imax; i++) {
var xJob = nlJobs[i]; // shorthand
/*
assumption #3: <job> tag has "id" property
assumption #4: job name appears inside <job> tag
assumption #4.5: you've got an abstraction layer that normalizes XML node interfaces so that "text" and "textContent" are folded into "textContent"
*/
aPairs.push({ 'key': xJob.getAttribute('id'), 'value': xJob.textContent });
}
// given array of key-value pairs, rebuild select box
var eJobs = document.getElementById('idjob');
setOptions(eJobs, aPairs);
});
}
function setOptions(eNode, aPairs) {
if(!eNode || !eNode.nodeName || eNode.nodeName.toUpperCase() !== 'SELECT') return false;
// empty SELECT of all options
while(eNode.firstChild) {
eNode.removeChild(eNode.firstChild);
}
// build up new nodes
var eOpt = null;
for(var i = 0, imax = aPairs.length; i < imax; i++) {
eOpt = document.createElement('OPTION');
eOpt.value = aPairs[i].key;
eOpt.appendChild(document.createTextNode(aPairs[i].value));
eNode.appendChild(eOpt);
}
return true;
}
Конечно, здесь не хватает важной части: вам нужен какой-то слой абстракции AJAX. Вам не нужно получать это из фреймворка, и хорошая библиотека для этого может содержать менее 50 строк кода (например, см. Ajax-скрипт PPK на quirksmode.org), но вам что-то абсолютно необходимо. Этот уровень обеспечит два преимущества: (1) кросс-браузерная совместимость; (2) синтаксический сахар.
Например, приведенный выше код не включает определение getSubOptions
. Это связано с тем, что логика будет зависеть от интерфейса, предоставляемого вашей абстракцией AJAX. Идея, однако, заключается в том, что вы будете выполнять запрос GET к написанному вами сценарию, который принимает аргументы и возвращает данные, удовлетворяющие этому запросу. В приведенном выше коде я сделал вид, что сценарий, который вы пишете, будет возвращать правильно сформированные данные XML с типом MIME, идентифицирующим их как таковой. В качестве альтернативы вы можете использовать JSON (или JSONP), прямой текст (например, данные в стиле CSV) или даже необработанный HTML, который вы просто вставите на страницу.
Преимущество использования полной структуры состоит в том, что все они предоставляют удобные способы выполнения DOM-манипуляций (т.е. снова синтаксический сахар).
Суть: вы можете сделать это с помощью доморощенного подхода (и я с гордостью могу сказать, что сделал это сам). Но это займет больше времени - не только потому, что это менее удобно, но и потому, что вам придется заново изобретать колесо === для поиска и исправления ошибок в вашем коде вместо того, чтобы использовать проверенные основные компоненты из некоторой библиотеки.
РЕДАКТИРОВАТЬ: Если вы хотите использовать JSON в качестве формата обмена данными вместо XML, вы бы изменили обработчик ответа, передаваемый в getSubOptions
, примерно так:
getSubOptions(sValue, function(XHR) {
// this code runs once the response comes back from the server
var aPairs = eval(XHR.responseText); // assumes JSON defines an array of key-value pairs
// given array of key-value pairs, rebuild select box
var eJobs = document.getElementById('idjob');
setOptions(eJobs, aPairs);
});
А вот пример того, как может выглядеть этот JSON:
[ { key: '1234', value: 'Job #1' },
{ key: '2345', value: 'Job #2' },
...
];
В этом примере структура JSON удобно отражает имена свойств, ожидаемые setOptions
; тем не менее, key
и value
кажутся довольно безобидными.
Если вы настроили использовать JSON для данных, вы можете рассмотреть JSONP как более безопасную альтернативу. Это действительно похоже, но шаблон дизайна немного отличается от описанной выше техники анонимного обратного вызова.
РЕДАКТИРОВАТЬ 2: Модифицированный пример кода для респондента:
<?php
include 'sqldb.php';
$cnt = mysqli_real_escape_string($dbc, $_GET['cnt']);
$sql = "SELECT * FROM job WHERE idcontract='$cnt' ORDER BY job.idjob";
$jqres = mysqli_query($dbc, $sql);
$i = 1;
// prepare the response
header('Content-Type: text/html');
while (($jrow = mysqli_fetch_array($jqres)) && ($i < count($jrow))) {
echo "<option value=\"$jrow[idjob]\" id=\"$jrow[idjob]\">Job-$i ${htmlentities(jrow[part_desc])}</option>";
$i++;
}
?>