Skip to content

Instantly share code, notes, and snippets.

@skanev
Created August 11, 2011 13:35
Show Gist options
  • Save skanev/1139663 to your computer and use it in GitHub Desktop.
Save skanev/1139663 to your computer and use it in GitHub Desktop.
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
Copy link

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
Copy link
Author

skanev commented Aug 11, 2011 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment