Here I am trying to create html drop down list. I have two things to select on my main list mobile
and laptop
. If I select the mobile option in my first list, the second drop down list has to load the options from mobile brand. and if I select laptop, it has to load laptop brand.Now the third list has to populate depends on the second list selection. suppose if I select samsung as mobile brand, it has to load the android version on next drop down menu.
My code(I have added the second menu list as separate here with same id.)
<select id="main_list">
<option value="default" selected>Select Your List</option>
<option value="mobile">mobile list</option>
<option value="laptop">laptop list</option>
</select>
<select id="brands">
<option value="default" selected>Select Your Mobile Brand</option>
<option value="mobile_1">Samsung</option>
<option value="mobile_2">Nokia</option>
</select>
<select id="brands">
<option value="default" selected>Select Your Laptop Brand</option>
<option value="laptop_1">HP</option>
<option value="laptop_2">Dell</option>
</select>
<select id="samsung_select">
<option value="default" selected>Select Your Andriod Version</option>
<option value="andriod_1">4.1</option>
<option value="andriod_2">4.2</option>
</select>
<select id="nokia_select">
<option value="default" selected>Select Your Windows Version</option>
<option value="windows_1">windows 8</option>
<option value="windows_2">windows 8.1</option>
</select>
what is the best way to populate this list automatically. Not using any db here.
JSFIDDLE
I have seen a previous similar question here, but this is not working here for me
There's no getting around that it's a bit of tedious coding, but this should give you a good start:
jsFiddle Demo
HTML:
<select id="main_list">
<option value="default" selected>Select Your List</option>
<option value="mobile">mobile list</option>
<option value="laptop">laptop list</option>
</select>
<select id="brand" class="secondary"></select>
<select id="version" class="secondary"></select>
css:
.secondary {display:none;}
js/jQuery:
$(function() {
var sel, i,
list = ['mobile', 'laptop'],
phone = ['Samsung', 'Nokia'],
laptop = ['HP', 'Dell'],
android = ['4.1', '4.2'],
windows = ['8', '8.1'],
dev_default = '<option value="default" selected>Select your Device brand</option>',
os_default = '<option value="default" selected>Select your OS version</option>';
sel_brand = $('#brand');
sel_version = $('#version');
$('select').change(function() {
switch (this.id) {
case 'main_list':
$('.secondary').hide();
sel_brand.find('option').remove();
sel_brand.append(dev_default);
sel_brand.show();
if (this.value == 'mobile') {
for (i = 0; i < phone.length; i++) {
$("#brand").append(
'<option value="' + phone[i] + '">' + phone[i] + '</option>'
);
}
}else if (this.value == 'laptop') {
for (i = 0; i < phone.length; i++) {
$("#brand").append(
'<option value="' + laptop[i] + '">' + laptop[i] + '</option>'
);
}
}
break;
case 'brand':
sel_version.find('option').remove();
sel_version.append(os_default);
sel_version.show();
if (this.value == 'Samsung') {
for (i = 0; i < android.length; i++) {
$("#version").append(
'<option value="' + android[i] + '">' + android[i] + '</option>'
);
}
}else if (this.value == 'Nokia' || this.value == 'HP' || this.value == 'Dell') {
for (i = 0; i < windows.length; i++) {
$("#version").append(
'<option value="' + windows[i] + '">' + windows[i] + '</option>'
);
}
}
break;
}
});
}); //END document.ready()
You're right. There have been plenty of similar questions, but there always seem to be little differences between them.
I've written widgets like this before. Here's an approach that's fairly different from gibberish's answer.
It involves a widget that you would use like this:
var widget = new DropdownWidget(options);
widget.onComplete(function(vals) {
console.log(vals);
});
widget.addTo(document.body);
The handlers supplied to onComplete
would receive objects such as
{
"main_list": "mobile list",
"brands": "Samsung",
"samsung_select": "4.2"
}
You would not use any markup at all. Instead it would be configured with an object like this:
var options = [
{
id: 1,
name: "main_list",
defaultVal: "Select Your List",
choices: [
{value: "mobile", text: "mobile list", nextId: 2},
{value: "laptop", text: "laptop list", nextId: 3}
]
},
{
id: 2,
name: "brands",
defaultVal: "Select Your Mobile Brand",
choices: [
{value: "mobile_1", text: "Samsung", nextId: 4},
{value: "mobile_2", text: "Nokia", nextId: 5}
]
},
{
id: 3,
name: "brands",
defaultVal: "Select Your Laptop Brand",
choices: [
{value: "laptop_1", text: "HP"},
{value: "laptop_2", text: "Dell"}
]
},
{
id: 4,
name: "samsung_select",
defaultVal: "Select Your Andriod Version",
choices: [
{value: "android_1", text: "4.1"},
{value: "android_2", text: "4.2"}
]
},
{
id: 5,
name: "nokia_select",
defaultVal: "Select Your Windows Version",
choices: [
{value: "windows_1", text: "windows 8"},
{value: "windows_2", text: "windows 8.1"}
]
}
];
Note that this could be a little different if you weren't using repeated names. The id
s could be removed, and nextId
could become nextName
.
This is a naive implementation of such a widget:
var DropdownWidget = (function() {
var DropdownWidget = function(options) {
// TODO: type-checking on options: should be array of acceptable configurations...
this.options = options;
this.selectedVals = [];
this.showing = false;
this.handlers = [];
};
DropdownWidget.prototype.onComplete = function(handler) {
this.handlers.push(handler);
};
DropdownWidget.prototype.addTo = function(element) {
if (this.showing) {
alert("Oops!"); // TODO: real error handling, or should this be moveable?
return;
}
var dropdown = createDropdown(this.options[0]);
this.elements = [dropdown];
addHandlers(this, dropdown, options, 0);
element.appendChild(dropdown);
};
var createDropdown = function(config) {
var select = document.createElement("SELECT");
select.name = config.name;
select.options[select.options.length] = new Option(config.defaultVal, "default");
config.choices.forEach(function(choice) {
select.options[select.options.length] = new Option(choice.text, choice.value);
});
return select;
};
var addHandlers = function(widget, select, options, index) {
select.onchange = function() {
removeSubsequentSelects(widget, options, index);
if (this.selectedIndex > 0) {
var choice = options[index].choices[this.selectedIndex - 1];
if (widget.selectedVals[widget.selectedVals.length - 1] !== options[index]) {
widget.selectedVals.push(options[index]);
}
if (choice.nextId) {
var nextIndex = findIndex(function(item) {
return item.id === choice.nextId;
}, options);
if (nextIndex > -1) {
var dropdown = createDropdown(options[nextIndex]);
widget.elements.push(dropdown);
addHandlers(widget, dropdown, options, nextIndex);
this.parentNode.appendChild(dropdown);
}
} else {
complete(widget);
}
}
}
};
var removeSubsequentSelects = function(widget, options, index) {
var start = findIndex(function(selected) {
return selected == options[index];
}, widget.selectedVals);
var idx = start;
if (idx > -1) {
while (++idx < widget.elements.length) {
widget.elements[idx].parentNode.removeChild(widget.elements[idx]);
}
widget.elements.length = widget.selectedVals.length = start + 1;
}
}
var findIndex = function(predicate, list) {
var idx = -1;
while (++idx < list.length) {if (predicate(list[idx])) {return idx;}}
return -1;
};
var complete = function(widget) {
var vals = widget.selectedVals.map(function(val, idx) {
return {name: val.name, val: val.choices[widget.elements[idx].selectedIndex - 1].text}
}).reduce(function(memo, obj) {memo[obj.name] = obj.val; return memo;}, {});
widget.handlers.forEach(function(handler) {
handler(vals);
});
};
return DropdownWidget;
}());
You can see it in action on JSFiddle.
There are plenty of things that could be made better. The biggest issue I see is that the DOM location for the constructed SELECTS is extremely simplistic.
In any case, it's a different approach.