I've got a code that is working in my environment. Nevertheless it is pretty ugly.
This is what I am trying to do. I get a selectbox from a side with a lot of city names. I filter some names and push them into an array and hide them. The other ones are also pushed into an array, but shown.
Now I append two options to the end of the selectbox, one is displayed, the other one hidden.
When someone clicks the option all, the options from the array otherCities are shown and defaultCities are hidden. the option all is hidden as well, less is shown.
This behavior works the other way round, too.
How can I simplify my code? Any help is welcome.
var otherCities = new Array();
var defaultCities = new Array();
var selectBoxCity = jQuery("select[name='city']");
if(selectBoxCity.size() != 0) {
selectBoxCity.prepend('<option value="" selected="selected">-- Please Select --</option>');
otherCities = new Array();
defaultCities = new Array();
var cityArray = ['OE', 'MK', 'SI', 'BO', 'DO', 'BM', 'HER', 'GE', 'HH'];
var options = jQuery("select[name='city'] option");
options.each(function() {
var o = jQuery(this);
if (jQuery.inArray(o.attr("value"), cityArray) == -1) {
otherCities.push(o.hide());
} else {
defaultCities.push(o.show());
}
});
selectBoxCity.find("option").end().append("<option value='all'>+</option>");
selectBoxCity.find("option").end().append("<option value='less'>-</option>");
}
var selectBoxCity = jQuery("select[name='city']");
selectBoxCity.find("option:first").attr("selected", true);
$("select[name='city'] option[value='less']").hide();
if(selectBoxCity.val() == "all") {
jQuery.each(otherCities,function() {
$(this).show();
});
jQuery.each(defaultCities,function() {
$(this).hide();
});
$("select[name='city'] option[value='all']").hide();
$("select[name='city'] option[value='less']").show();
}
if(selectBoxCity.val() == "less") {
jQuery.each(otherCities,function() {
$(this).hide();
});
jQuery.each(defaultCities,function() {
$(this).show();
});
$("select[name='city'] option[value='all']").show();
$("select[name='city'] option[value='less']").hide();
}
1 Answer 1
Here's something that seems to work OK (here's a demo)
jQuery(function ($) {
var select = $("select[name=city]"),
defaults = select.children(".default"),
others = select.children(":not(.default)");
others.remove();
select.on("change", function (event) {
var value = select.val();
if(value === "more") {
defaults.remove();
select.append(others);
} else if(value === "less") {
others.remove();
select.append(defaults);
}
});
});
Everything else is stored in the markup, like so:
<select name="city">
<!-- default options -->
<option class="default">A</option>
<option class="default">B</option>
<option class="default">C</option>
<option value="more" class="default">Show more</option>
<!-- expanded options -->
<option>D</option>
<option>E</option>
<option>F</option>
<option>G</option>
<option>H</option>
<option>I</option>
<option value="less">Show less</option>
</select>
As I said in the comments, .hide
and .show
doesn't seem to have any effect on <option>
elements. Neither does visibility: hidden
. In either case, they all show up in the select dropdown. You can disable options, but then they're still there, just greyed out.
Hence, this code forcibly removes/appends the options.
Of course, it might make more sense to simply remove/append only the non-default options. To me it makes more sense that the default options are a subset of all the options, not an entirely different set of options.
Furthermore, it might be good to let the more/less options be added by JS, so clients that don't support JS don't see them.
Putting all that together, you get this .
Without JS, you'll just see a full list. With JS, you get the more/less options and all that jazz.
-
\$\begingroup\$ I know it's tricky, but the options A,B,C shouldn't be shown when selecting more :-) \$\endgroup\$user1735221– user17352212012年10月10日 17:09:11 +00:00Commented Oct 10, 2012 at 17:09
-
\$\begingroup\$ Which is what the code here does. It's only the 2nd jsfiddle demo that keeps the defaults around when selecting "more" \$\endgroup\$Flambino– Flambino2012年10月10日 17:10:51 +00:00Commented Oct 10, 2012 at 17:10
default
). Then you only need to run some selectors to hide/show, and won't have duplication of city values in your JS. Probably, also a good idea to keep the "please select" option in the markup rather than prepending it \$\endgroup\$option
tag doesn't seem to have any effect here in Chrome \$\endgroup\$