Использование javascript и jquery для заполнения связанных полей выбора структурой массива
Используя ответы на этот вопрос, я смог заполнить поле выбора на основе выбора другого поля выбора. ( Я разместил свой ответ здесь). Извлечение данных из структуры массива, созданной на стороне сервера, сохраненной в файле.js и указанной на html-странице.
Теперь я хотел бы добавить третье поле выбора. Если бы у меня было 3 набора данных (модель, марка, опции) примерно так (псевдокод):
cars : [Honda[Accord[Lx, Dx]], [Civic[2dr, Hatchback]],
[Toyota[Camry[Blk, Red]], [Prius[2dr,4dr]]
Пример: Если выбрана Honda, в следующем поле выбора будет [Accord Civic], а если выбрано Accord, в следующем поле выбора будет [Lx Dx]
Как я могу
1) создать структуру массива для хранения данных? такой, что
2) Я могу использовать значение из одного поля выбора, чтобы ссылаться на необходимые значения для следующего поля выбора
Спасибо
РЕДАКТИРОВАТЬ
Я могу создать следующее, но не могу понять ссылки таким образом, чтобы это помогло заполнить поле выбора
var cars = [
{"makes" : "Honda",
"models" : [
{'Accord' : ["2dr","4dr"]} ,
{'CRV' : ["2dr","Hatchback"]} ,
{'Pilot': ["base","superDuper"] } ]
},
{"makes" :"Toyota",
"models" : [
{'Prius' : ["green","reallyGreen"]} ,
{'Camry' : ["sporty","square"]} ,
{'Corolla' : ["cheap","superFly"] } ]
} ] ;
alert(cars[0].models[0].Accord[0]); ---> 2dr
4 ответа
Я предпочитаю структуру данных следующим образом:
var carMakers = [
{ name: 'Honda', models: [
{ name: 'Accord', features: ['2dr', '4dr'] },
{ name: 'CRV', features: ['2dr', 'Hatchback'] },
{ name: 'Pilot', features: ['base', 'superDuper'] }
]},
{ name: 'Toyota', models: [
{ name: 'Prius', features: ['green', 'superGreen'] },
{ name: 'Camry', features: ['sporty', 'square'] },
{ name: 'Corolla', features: ['cheap', 'superFly'] }
]}
];
Имея три списка выбора с идентификаторами: "производитель", "модель" и "функции", вы можете манипулировать ими с помощью этого (я думаю, это довольно очевидно):
// returns array of elements whose 'prop' property is 'value'
function filterByProperty(arr, prop, value) {
return $.grep(arr, function (item) { return item[prop] == value });
}
// populates select list from array of items given as objects: { name: 'text', value: 'value' }
function populateSelect(el, items) {
el.options.length = 0;
if (items.length > 0)
el.options[0] = new Option('please select', '');
$.each(items, function () {
el.options[el.options.length] = new Option(this.name, this.value);
});
}
// initialization
$(document).ready(function () {
// populating 1st select list
populateSelect($('#maker').get(0), $.map(carMakers, function(maker) { return { name: maker.name, value: maker.name} }));
// populating 2nd select list
$('#maker').bind('change', function() {
var makerName = this.value,
carMaker = filterByProperty(carMakers, 'name', makerName),
models = [];
if (carMaker.length > 0)
models = $.map(carMaker[0].models, function(model) { return { name: model.name, value: makerName + '.' + model.name} });
populateSelect($('#model').get(0), models);
$('#model').trigger('change');
});
// populating 3rd select list
$('#model').bind('change', function () {
var nameAndModel = this.value.split('.'),
features = [];
if (2 == nameAndModel.length) {
var makerName = nameAndModel[0],
carModel = nameAndModel[1],
carMaker = filterByProperty(carMakers, 'name', makerName);
if (carMaker.length > 0) {
var model = filterByProperty(carMaker[0].models, 'name', carModel)
if (model.length > 0)
features = $.map(model[0].features, function(feature) { return { name: feature, value: makerName + '.' + carModel + '.' + feature} })
}
}
populateSelect($('#feature').get(0), features);
})
// alerting value on 3rd select list change
$('#feature').bind('change', function () {
if (this.value.length > 0)
alert(this.value);
})
});
Благодаря ответу @Marko Dunic я смог построить структуру массива (данных), на которую можно ссылаться, чтобы заполнить 3 поля выбора. Я не использовал код реализации только потому, что не до конца его понял... он работает так, как написано. Я вернусь к этому коду позже, когда буду изучать jQuery. Мой код размещен ниже (очевидно, ваша ссылка на jQuery может отличаться)
<html><head>
<script language="Javascript" src="javascript/jquery-1.2.6.min.js"></script>
<script type="text/JavaScript">
var cars = [
{ name: 'Honda', models: [
{ name: 'Accord', features: ['2dr', '4dr'] },
{ name: 'CRV', features: ['2dr', 'Hatchback'] },
{ name: 'Pilot', features: ['base', 'superDuper'] }
]},
{ name: 'Toyota', models: [
{ name: 'Prius', features: ['green', 'superGreen'] },
{ name: 'Camry', features: ['sporty', 'square'] },
{ name: 'Corolla', features: ['cheap', 'superFly'] }
]
}
];
$(function() {
var options = '' ;
for (var i = 0; i < cars.length; i++) {
var opt = cars[i].name ;
if (i == 0){ options += '<option selected value="' + opt + '">' + opt + '</option>'; }
else {options += '<option value="' + opt + '">' + opt + '</option>'; }
}
$("#maker").html(options); // populate select box with array
var options = '' ;
for (var i=0; i < cars[0].models.length; i++) {
var opt = cars[0].models[0].name ;
if (i==0){options += '<option selected value="' + opt + '">' + opt + '</option>';}
else {options += '<option value="' + opt + '">' + opt + '</option>';}
}
$("#model").html(options); // populate select box with array
var options = '' ;
for (var i=0; i < cars[0].models[0].features.length; i++) {
var opt = cars[0].models[0].features[i] ;
if (i==0){options += '<option selected value="' + opt + '">' + opt + '</option>';}
else {options += '<option value="' + opt + '">' + opt + '</option>';}
}
$("#feature").html(options); // populate select box with array
$("#maker").bind("click",
function() {
$("#model").children().remove() ; // clear select box
for(var i=0; i<cars.length; i++) {
if (cars[i].name == this.value) {
var options = '' ;
for (var j=0; j < cars[i].models.length; j++) {
var opt= cars[i].models[j].name ;
if (j==0) {options += '<option selected value="' + opt + '">' + opt + '</option>';}
else {options += '<option value="' + opt + '">' + opt + '</option>';}
}
break;
}
}
$("#model").html(options); // populate select box with array
$("#feature").children().remove() ; // clear select box
for(var i=0; i<cars.length; i++) {
for(var j=0; j<cars[i].models.length; j++) {
if(cars[i].models[j].name == $("#model").val()) {
var options = '' ;
for (var k=0; k < cars[i].models[j].features.length; k++) {
var opt = cars[i].models[j].features[k] ;
if (k==0){options += '<option selected value="' + opt + '">' + opt + '</option>';}
else {options += '<option value="' + opt + '">' + opt + '</option>';}
}
break;
}
}
}
$("#feature").html(options); // populate select box with array
});
$("#model").bind("click",
function() {
$("#feature").children().remove() ; // clear select box
for(var i=0; i<cars.length; i++) {
for(var j=0; j<cars[i].models.length; j++) {
if(cars[i].models[j].name == this.value) {
var options = '' ;
for (var k=0; k < cars[i].models[j].features.length; k++) {
var opt = cars[i].models[j].features[k] ;
if (k==0){options += '<option selected value="' + opt + '">' + opt + '</option>';}
else {options += '<option value="' + opt + '">' + opt + '</option>';}
}
break ;
}
}
}
$("#feature").html(options); // populate select box with array
});
});
</script>
</head> <body>
<div id="selection">
<select id="maker"size="10" style="{width=75px}"></select>
<select id="model" size="10" style="{width=75px}"></select>
<select id="feature" size="10"style="{width=75px}"></select>
</div></body></html>
Мне действительно понравилось решение @Marko Dunic, но оно не соответствовало моим потребностям в прикреплении идентификаторов к опциям. Как только я прикрепил идентификаторы, я понял, что могу сделать код JS еще меньше и проще. Мое решение предназначено для случаев, когда данные поступают из реляционной базы данных, а входные данные JSON сохраняют реляционную структуру с первичными / внешними ключами. Вот данные JSON:
<html lang="en">
<head>
<title>Populate a select dropdown list with jQuery - WebDev Ingredients</title>
<script type="text/javascript" src="js/jquery-1.4.2.js"></script>
<script type="text/javascript">
var types = [
{ typeID: 1, name: 'Domestic'},
{ typeID: 2, name: 'Import'},
{ typeID: 3, name: 'Boat'}
]
var makes = [
{ typeID: 1, makeID: 1, name: 'Chevy'},
{ typeID: 1, makeID: 2, name: 'Ford'},
{ typeID: 1, makeID: 3, name: 'Delorean'},
{ typeID: 2, makeID: 4, name: 'Honda'},
{ typeID: 2, makeID: 5, name: 'Toyota'},
{ typeID: 2, makeID: 6, name: 'Saab'}
]
var model = [
{ makeID: 1, modelID: 1, name: 'Camaro'},
{ makeID: 1, modelID: 2, name: 'Chevelle'},
{ makeID: 1, modelID: 3, name: 'Nova'},
{ makeID: 2, modelID: 4, name: 'Focus'},
{ makeID: 2, modelID: 5, name: 'Galaxie'},
{ makeID: 2, modelID: 6, name: 'Mustang'},
{ makeID: 4, modelID: 7, name: 'Accord'},
{ makeID: 4, modelID: 8, name: 'Civic'},
{ makeID: 4, modelID: 9, name: 'Odyssey'},
{ makeID: 5, modelID: 10, name: 'Camry'},
{ makeID: 5, modelID: 11, name: 'Corolla'}
]
//
// Put this in a stand alone .js file
//
// returns array of elements whose 'prop' property is 'value'
function filterByProperty(arr, prop, value) {
return $.grep(arr, function (item) { return item[prop] == value });
}
// populates select list from array of items given as objects: { name: 'text', value: 'value' }
function populateSelect(el, items) {
el.options.length = 0;
if (items.length > 0)
el.options[0] = new Option('please select', '');
$.each(items, function () {
el.options[el.options.length] = new Option(this.name, this.value);
});
}
// initialization
$(document).ready(function () {
// populating 1st select list
populateSelect($('#sType').get(0), $.map(types, function(type) { return { name: type.name, value: type.typeID} }));
// populating 2nd select list
$('#sType').bind('change', function() {
var theModels = filterByProperty(makes, 'typeID', this.value);
populateSelect($('#sMake').get(0), $.map(theModels, function(make) { return { name: make.name, value: make.makeID} }));
$('#sMake').trigger('change');
});
// populating 3nd select list
$('#sMake').bind('change', function() {
var theSeries = filterByProperty(model, 'makeID', this.value);
populateSelect($('#sModel').get(0), $.map(theSeries, function(model) { return { name: model.name, value: model.modelID} }));
});
});
</script>
</head>
<body>
Enter values, click submit, and look at the post parameters
<form method="get" action="index.php">
<div id="selection">
<select id="sType" name="type_id" style="{width=75px}"></select>
<select id="sMake" name="make_id" style="{width=75px}"></select>
<select id="sModel" name="model_id" style="{width=75px}"></select>
</div>
<input type="submit">
</form>
</body>
</html>
Обратите внимание, что мое решение меняет функциональность так, что Make-Model - это 2-е и 3-е текстовые поля, а Type (внутренний, импорт, лодка и т. Д.) - 1-й уровень. Я сократил шаблон JS до 23 строк (меньше комментариев), сохранив хорошее форматирование.
Данные JSON очень легко визуализировать из запросов SQL, которые кэшируются в списках java по init, поскольку Type-Make-Model редко изменяется. Я не использую динамический AJAX, потому что это усложняет архитектуру, и у меня есть сравнительно небольшой список доступных значений, поэтому я просто отправляю его по запросу страницы.
"Решения должны быть максимально простыми, но не более простыми" - А. Эйнштейн
Вы должны посмотреть здесь для выбора окна манипуляции. Для того, что вы хотите, я думаю, что JSON сделает правильную работу для вас. В любом случае, если бы вы были на вашем месте, я бы поступил следующим образом: когда я изменяю первый выбор, я делаю ajax-запрос. С ответом ajax я заполню второе поле. То же самое для второго блока, и там у вас есть третий блок, заполненный правильными данными.