Reputation: 287
I have some style='display:none'
in the option element, it work well on Chrome and I realise it does not work on IE.
<select>
<option style="display:none;">One</option>
<option>Two</option>
<option style="display:none;">Three</option>
<option>Four</option>
</select>
Using jQuery, how to loop through the option to find display:none
and remove the elements <option>
?
Upvotes: 7
Views: 13256
Reputation: 1
Display: none
will not work for IE11. I had same issue for search in select option. What I did is disabled the unmatched options and then hide them.
After this I have sorted the options to show only enabled options on top.
The code I have written is pasted below - please try to understand the logic I hope it will work.
To disable the options use:
$("#addselect option")attr('disabled', 'disabled').hide
And to again enable it use:
$("#addselect option").removeAttr('disabled').show();
Sort by disabled options:
$("#addselect option").each(function (i, val) {
if ($(this)[i].disabled) {
moveDown("selectId");
}
else {
moveUp("selectId");
}
}
function moveUp(selectId) {
var selectList = document.getElementById(selectId);
var selectOptions = selectList.getElementsByTagName('option');
for (var i = 1; i < selectOptions.length; i++) {
var opt = selectOptions[i];
if (!opt.disabled) {
selectList.removeChild(opt);
selectList.insertBefore(opt, selectOptions[i - 1]);
}
}
}
function moveDown(selectId) {
var selectList = document.getElementById(selectId);
var selectOptions = selectList.getElementsByTagName('option');
for (var i = selectOptions.length - 2; i >= 0; i--) {
var opt = selectOptions[i];
if (opt.disabled) {
var nextOpt = selectOptions[i + 1];
opt = selectList.removeChild(opt);
nextOpt = selectList.replaceChild(opt, nextOpt);
selectList.insertBefore(nextOpt, opt);
}
}
}
Upvotes: 0
Reputation: 1718
Today I had the same problem. Without removing the unwanted options you won't get your expected result. But the problem is that you need to memorize those options if you want to display them later.
My solution is very simple and works in all major browsers:
function filterList(oList, rxSearch)
{
// Create backup of the old option list (only once)
if(typeof(oList.tagOptions) === "undefined")
{
// Save current options
oList.tagOptions = [ ]; // Generate a dynamic property for this DOM object
for(var i = 0; i < oList.options.length; ++i)
oList.tagOptions.push(oList.options[i]);
}
// Clear the current option list
while(oList.options.length)
oList.options.remove(0);
// Add only those options which match the regular expression
for(var i = 0; i < oList.tagOptions.length; ++i)
{
if(rxSearch.test(oList.tagOptions[i].text))
oList.options.add(oList.tagOptions[i]);
}
}
The trick is that the option elements will be copied into the dynamically created tagOptions property on the first run. Since there will be still references (in tagOptions) to these removed option DOM elements they will not be released. Furthermore you need no global variables for that. Later the visible options (oList.options) will be cleared and only those options added, which match the search term.
Using the following HTML code:
<select id="myList" size="10">
<option>apple</option>
<option>advocado</option>
<option>banana</option>
<option>coconut</option>
</select>
You would call it like this:
filterList(document.getElementById("myList"), /^a/i); // Display only those elements, which start with an a
alert("Display all with a");
filterList(document.getElementById("myList"), /^b/i); // Display only those elements, which start with an b
alert("Display all with b");
filterList(document.getElementById("myList"), /^/i); // Display only those elements, which start with an c
alert("Display all");
I've tested this with Firefox, Internet Explorer 11, Chrome and Opera. It works fine for my purposes.
function filterList(oList, rxSearch)
{
// Create backup of the old option list (only once)
if(typeof(oList.tagOptions) === "undefined")
{
// Save current options
oList.tagOptions = [ ]; // Generate a dynamic property for this DOM object
for(var i = 0; i < oList.options.length; ++i)
oList.tagOptions.push(oList.options[i]);
}
// Clear the current option list
while(oList.options.length)
oList.options.remove(0);
// Add only those options which match the regular expression
for(var i = 0; i < oList.tagOptions.length; ++i)
{
if(rxSearch.test(oList.tagOptions[i].text))
oList.options.add(oList.tagOptions[i]);
}
}
filterList(document.getElementById("myList"), /^a/i); // Display only those elements, which start with an a
alert("Display all with a");
filterList(document.getElementById("myList"), /^b/i); // Display only those elements, which start with an b
alert("Display all with b");
filterList(document.getElementById("myList"), /^/i); // Display only those elements, which start with an c
alert("Display all");
<select id="myList" size="10">
<option>apple</option>
<option>advocado</option>
<option>banana</option>
<option>coconut</option>
</select>
Upvotes: 0
Reputation: 19961
John Boker's solution is the right one for this question. But it does have the downside that you won't be able to ever retrieve those options once you've removed them.
One solution is to save the full HTML of the <select>
before you remove any <option>
tags.
var $s = $('select');
$s.data("originalHTML", $s.html());
Now you can easily restore by reversing this: $s.html($s.data("originalHTML"));
Full details are on this solution: https://stackoverflow.com/a/24439289/1766230
Also an example: http://jsfiddle.net/luken/9CYjy/
Upvotes: 1
Reputation: 14470
I had the same issue but bit complex , and yes we need to remove the option to hide in IE/Chrome/Safari.
But in some cases we want to just HIDE group of options based on criteria /filter and remove()
just removes completely. I have following solution to this problem. It removes the options but keeps removed option in a data attribute on same select
element and when desired we just re-populate in given sorting order ( value or label).
Let say:
<select id='sorty' multiple=true>
<option value="1">Group A</option>
<option value="2">Group B</option>
<option value="3">Group c</option>
<option value="4">Group D</option>
<option value="5">Group D</option>
</select>
<button onclick="HideG('A')">Hide Group A</button>
<button onclick='HideG("B")'>Hide Group B</button>
<button onclick='HideG("C")'>Hide Group C</button>
<button onclick='HideG("D")'>Hide Group D</button>
<button onclick='ShowAll()'>Show ALL</button>
(require Jquery):
function selectOptionFilter(src,filter,sortBy)
{
if(!$(src).data('hiddenOpts'))
$(src).data('hiddenOpts',[]);
//re-insert while keeping sort order by value or label
$($(src).data('hiddenOpts')).each(function(){
var hiddenOpt=this;
var positioned=false;
$(src).find('option').each(function(i){
if((sortBy=='value' && $(this).attr('value')*1 > $(hiddenOpt).attr('value'))
||
(sortBy=='label' && $(this).text() > $(hiddenOpt).text())
){
$(this).before(hiddenOpt);
positioned=true;
//break
return false;
}
});
//else append
if(!positioned){
$(src).append(hiddenOpt);
}
});
//clean the hidden list
$(src).data('hiddenOpts',[]);
//apply the filter and remove options
if( typeof filter=='function'){
$(src).find('option').filter(filter).each(function(){
$(src).data('hiddenOpts').push($(this).remove());
});
}
}
function HideG(xname){
selectOptionFilter($('#sorty'),function(){
return ( $(this).text().indexOf(xname) > -1);
},'value');
}
function ShowAll(){
selectOptionFilter($('#sorty'),function(){ return false;},'value');
}
You can pass a more complex filter function to remove the desired options.
Upvotes: 0
Reputation: 83699
this seems to work for me:
$('select option').each(function(){
if(this.style.display == 'none')
{
$(this).remove();
}
});
Upvotes: 6