I'm using a library that takes, amongst other parameters, an array of names and create a <select> combobox containing the <option> elements named after what was in that array. It also assigns to the value attribute of the <option> nodes the value of the index at which the name was taken. So, for example, if the index 0 of an array contained "foo", then it would create a tag like follows: <option value="0">foo</option>. For reference, here is the code for that library:
function generateSelect(objDimensionAssoc, obj, select_name, label_name, function_name, state, DivAlignement)
{
//Valid object before
sChaine = "";
if( (obj != null) && (obj != undefined) && (obj != "") && (parseInt(countObject(obj)) > 0) ){
if( state == 'show' ){
sChaine +="<label for='"+select_name+"' ><span>"+label_name+"</span></label>\n";
sChaine +="<div class='"+DivAlignement+"'>\n";
if(function_name != "")
sChaine +="<select name='"+select_name+"' id='"+select_name+"' onchange='"+function_name+"' >\n";
else
sChaine +="<select name='"+select_name+"' id='"+select_name+"'>\n";
//lang = variable reconnu dans tout les pages
for (var x=0; x < obj.length; x++){
//One or two domentionnal array
if(obj[x] != null){
if(objDimensionAssoc == "1"){
if(chaineUrl){
sChaine += compare_and_create( x, obj[x], chaineUrl[select_name], select_name);
} else {
sChaine += compare_and_create( x, obj[x], "", select_name);
}
} else {
if(chaineUrl){
sChaine += compare_and_create( x, obj[x][lang], chaineUrl[select_name], select_name);
} else {
sChaine += compare_and_create( x, obj[x][lang], "", select_name);
}
}
}
}
sChaine +="</select>\n";
sChaine +="</div>\n";
}
return(sChaine);
} else {
//empty array
if( state == 'show' ){
sChaine +="<label for='"+select_name+"' ><span>"+label_name+"</span></label>\n";
sChaine +="<div class='"+DivAlignement+"'>\n";
sChaine +="<select name='"+select_name+"' id='"+select_name+"' disabled='true' >\n";
sChaine +="<option value='0'> </option>\n";
sChaine +="</select>\n";
sChaine +="</div>\n";
}
return(sChaine);
}
}
function compare_and_create( key, innerText, string_compare,select_name)
{
if(key == string_compare){
return ("<option value='"+key+"' selected='selected'>"+innerText+"</option>\n");
} else {
return ("<option value='"+key+"'>"+innerText+"</option>\n");
}
}
Here is where I call it:
myDiv = document.getElementById('tmp_stationDiv');
var stationsList = new Array();
stationsList = JSON.parse(<?php getStationList($regions); ?>);
myDiv.innerHTML = generateSelect("1",stationsList,
"slt_idStations",message["txt_choose_station"][lang],
'','show','blockDiv');
And this is the code of the function getStationList():
function getStationList($regions)
{
$slt_nomStations = (isset($_GET["slt_nomStations"]) ? $_GET["slt_nomStations"] : 0);;
$db = ConnectionFactory::getFactory()->getConnection();
$stmt = $db->prepare("SELECT DISTINCT S.station_id, S.name, SA.sub_area_name FROM dev.Station AS S INNER JOIN dbo.SubArea AS SA ON S.sub_area_id = SA.sub_area_id INNER JOIN data.MonthlyNormalData as MND ON MND.station_id = S.station_id WHERE sub_area_name = '$regions[$slt_nomStations]' AND value IS NOT NULL ORDER BY S.name ASC");
$stmt->execute();
$stations = array();
$lastStationName = "";
while ($row = $stmt->fetch())
{
if ($lastStationName != $row['name'])
{
array_push($stations, $row['name']);
$lastStationName = $row['name'];
}
}
$newJSArray = json_encode($stations);
echo json_encode($newJSArray);
}
Now this works perfectly fine. The output of getStationList() is, for example, "[\"LA GRANDE RIVIERE A\"]" and I then use JSON.parse() to transform that into a javascript array.
Unfortunately, the value associated with the <option> node will be 0, 1, 2, ..., n, where n is the number of stations - 1. I would like to associate the name of the stations with their station ID (which I recover from the database) so the value associated with the <option> node would be those IDs. To do that, I suppose I would need to push the name of the stations at the index of the corresponding ID. I have tried doing that with the following modifications to getStationList():
function getStationList($regions)
{
$slt_nomStations = (isset($_GET["slt_nomStations"]) ? $_GET["slt_nomStations"] : 0);;
$db = ConnectionFactory::getFactory()->getConnection();
$stmt = $db->prepare("SELECT DISTINCT S.station_id, S.name, SA.sub_area_name FROM dev.Station AS S INNER JOIN dbo.SubArea AS SA ON S.sub_area_id = SA.sub_area_id INNER JOIN data.MonthlyNormalData as MND ON MND.station_id = S.station_id WHERE sub_area_name = '$regions[$slt_nomStations]' AND value IS NOT NULL ORDER BY S.name ASC");
$stmt->execute();
$IDs = array();
$names = array();
$stations = array();
$lastStationName = "";
while ($row = $stmt->fetch())
{
if ($lastStationName != $row['name'])
{
array_push($names, $row['name']);
array_push($IDs, $row['station_id']);
$lastStationName = $row['name'];
}
}
$stations = array_fill_keys($IDs, $names);
$newJSArray = json_encode($stations);
echo json_encode($newJSArray);
}
Unfortunately, this does not work since the output of the getStationList() function is now something like this: "{\"6047\":[\"LA GRANDE RIVIERE A\"]}". So how would I have to modify my code for it to generate my <select> node with its children <option> nodes having their value attribute set to the ID of each of their corresponding station names?
json_encode()on the result of callingjson_encode.SyntaxError: JSON.parse: unexpected character, which is at the following line:stationsList = JSON.parse({"6047":"LA GRANDE RIVIERE A"});. Not callingjson_encode()a second on the result of calledjson_encode()' makes the output of the functiongetStationList()`{"6047":"LA GRANDE RIVIERE A"}instead of"{\"6047\":[\"LA GRANDE RIVIERE A\"]}"JSON.parse()unnecessarily in the Javascript. Inserting the result ofgetStationList()parses it automatically, and then you parse it again. Get rid of both these extra encodes and parses.