al56
al56

Reputation: 37

Filter options of a <select> with javascript?

I have a select with some values. When the user enters a vehicle in the search box, the drop down gets filtered to the option value that matches in the search box. I am able to get this first part of the code to work but the problem I am having, is how would I be able to save the option value that was filtered in the drop down so that it becomes the first option in the list. Lets say for example the user by mistake, hits the backspace button because if that happens the option value that was selected is no longer selected and the option value is defaulted back to the first option in the drop down. I am guessing to save the value I would have to use a cookie, totally lost on this part, any suggestions would be helpful. Thanks!

Has to be able to work in IE5 and Up :/

<input type="text" id="searchFilter" placeholder="Search" onkeyup="FilterItems(this.value);" />
<select id="ddVehicles">
    <option value="1">BMW</option>
    <option value="2">Mercedes-Benz</option>
    <option value="3">Bentley</option>
    <option value="4">Lamborghini</option>
</select>



var ddlText, ddlValue, ddl;
function CacheItems() {
  ddlText = new Array();
  ddlValue = new Array();
  ddl = document.getElementById("ddVehicles");
  for (var i = 0; i < ddl.options.length; i++) {
     ddlText[ddlText.length] = ddl.options[i].text;
     ddlValue[ddlValue.length] = ddl.options[i].value;
  }
}
window.onload = CacheItems;

function FilterItems(value) {
  ddl.options.length = 0;
  for (var i = 0; i < ddlText.length; i++) {
     if (ddlText[i].toLowerCase().indexOf(value) != -1 || ddlText[i].toUpperCase().indexOf(value) != -1) {
        AddItem(ddlText[i], ddlValue[i]);
    }
  }
}

function AddItem(text, value) {
  var opt = document.createElement("option");
  opt.text = text;
  opt.value = value;
  ddl.options.add(opt);
}

Upvotes: 0

Views: 38908

Answers (3)

Fawad Ali
Fawad Ali

Reputation: 612

A better & fast Version by using "match" enter image description here

    function filter() {
        var keyword = document.getElementById("search").value;
        var select = document.getElementById("select");
        for (var i = 0; i < select.length; i++) {
            var txt = select.options[i].text;
            if (!txt.match(keyword)) {
                $(select.options[i]).attr('disabled', 'disabled').hide();
            } else {
                $(select.options[i]).removeAttr('disabled').show();
            }

        }
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
    <div>
        <input type="text" id="search" name="search" style="margin: 10px;width: 165px;" onkeyup="filter()">
    </div>
    <div>
        <select id="select" size="10" style="margin: 10px; width: 165px;height: 170px;">
            <option>Cupcake</option>
            <option>Cunut</option>
            <option>Eclair</option>
            <option>Froyo</option>
            <option>Gingerbread</option>
            <option>Honeycomb</option>
            <option>Ice Cream Sandwich</option>
            <option>Jelly Bean</option>
            <option>KitKat</option>
            <option>Lollipop</option>
            <option>Marshmallow</option>
            <option>Nougat</option>
        </select>
    </div>
</div>

Upvotes: 3

RobG
RobG

Reputation: 147523

IE 5, wow. That browser is utterly dysfunctional on the web, so I'm assuming this is for homework. It's much better to post your code as a runnable snippet, that way it can be played with right here in SO.

I'd suggest caching the options rather than having to recreate them, and test using all lower case (or upper if you prefer) to increase the chance of a match. If the search field is empty, then restore the select to its original state.

Oh, and the convention is that variable names starting with a capital letter are constructors.

E.g.

var optionsCache = [];

function filterItems(el) {
  var value = el.value.toLowerCase();
  var form = el.form;
  var opt, sel = form.ddVehicles;
  if (value == '') {
    restoreOptions();
  } else {
    // Loop backwards through options as removing them modifies the next
    // to be visited if go forwards
    for (var i=sel.options.length-1; i>=0; i--) {
      opt = sel.options[i];
      if (opt.text.toLowerCase().indexOf(value) == -1){
        sel.removeChild(opt)
      }
    }
  }
}

// Restore select to original state
function restoreOptions(){
  var sel = document.getElementById('ddVehicles');
  sel.options.length = 0;
  for (var i=0, iLen=optionsCache.length; i<iLen; i++) {
    sel.appendChild(optionsCache[i]);
  }
}


window.onload = function() {
  // Load cache
  var sel = document.getElementById('ddVehicles');
  for (var i=0, iLen=sel.options.length; i<iLen; i++) {
    optionsCache.push(sel.options[i]);
  }
}
<form>
  <input type="text" id="searchFilter" name="searchFilter" placeholder="Search" 
   onkeyup="filterItems(this);">
  <select id="ddVehicles" name="ddVehicles" size="4">
    <option value="1">BMW</option>
    <option value="2">Mercedes-Benz</option>
    <option value="3">Bentley</option>
    <option value="4">Lamborghini</option>
  </select>
</form>

I think the above should work in IE 5, I think it has getElementById. If not, you can reference the form controls using document.forms[0].elementName.

Upvotes: 2

varontron
varontron

Reputation: 1157

You can put the option element into a data attribute on the input:

var select = document.getElementById("ddVehicles");
var selOption = select.options[select.selectedIndex]
document.getElementById('searchFilter').dataset.selOption = selOption

Alternatively you could store the option element's index, text, or even outerHTML, whatever you need.

See https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes for more info.

Upvotes: 0

Related Questions