Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Convert a <select> with <optgroups> to two <select>s that are interconnected

If you have a select with option groups:

<select data-nested-select="Select country">
  <option>Select city</option>
  <optgroup label="Bulgaria">
    <option value="sofia">Sofia</option>
    <option value="plovdiv">Plovdiv</option>
  </optgroup>
  <optgroup label="Sweden">
    <option value="stockholm">Stockholm</option>
    <option value="uppsala">Uppsala</option>
  </optgroup>
</select>

This jQuery snippet will convert it to two separate 's -- one for country and one for city. Whenever the user changes the country, the other will display only the cities that are in that country.

$(function() {
$('select[data-nested-select]').each(function() {
var select = $(this),
groupName = select.data('nested-select'),
optgroups = select.find('optgroup'),
options = select.find('optgroup option'),
groupSelect = $('<select>'),
promptOption = makeOption(groupName, null, false);
groupSelect.
append(promptOption).
insertBefore(select);
optgroups.each(function(index) {
var optgroup = $(this),
name = this.label,
children = optgroup.children(),
selected = children.is(':selected'),
groupOption = makeOption(name, index, selected);
groupOption.data('options', children);
groupSelect.append(groupOption);
optgroup.detach();
});
groupSelect.change(function() {
var optionsInGroup = groupSelect.find('option:selected').data('options') || [],
hiddenOptions = options.not(optionsInGroup);
hiddenOptions.
attr('selected', false).
detach();
select.append(optionsInGroup);
});
groupSelect.change();
function makeOption(text, value, selected) {
return $('<option>').
attr('value', value).
attr('selected', selected).
text(text);
}
});
});
@edzhelyov

This comment has been minimized.

Copy link

edzhelyov commented Aug 11, 2011

Hm, forking this gist doesn't work :/

You can at least do the DOM manipulations at once. I couldn't find a way to replicate the hiddenOptions behavior, but you can easily insert the groupSelect after all modifications have been made, this way you will trigger only one DOM repaint.

see https://gist.github.com/1140062

@skanev

This comment has been minimized.

Copy link
Owner Author

skanev commented Aug 11, 2011

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.