0

Here is my crazy code:

t.config.searchSpanInput.keyup(function () {
    var searchCriteria = t.config.searchSpanInput.val();

    $.each (t.config.promoInput, function (i, v) {
        $.each ($(v + " option"), function (j, v) {
            if (optObj[i][j].text().toLowerCase().indexOf(searchCriteria.toLowerCase(), 0) === -1) {
                $(v).remove();
            }

            if (optObj[i][j].text().toLowerCase().indexOf(searchCriteria.toLowerCase(), 0) > -1) {
                if (optObj[i][j].length === 1) {
                    $(v).append(optObj[i][j][0]);
                }
            }

            if (! optObj[0][0]) {
                $(v).prepend(optObj[0][0]);
            }
        });
    });
});

So... All of that is trying to do a somewhat simple task.

  • On page load get all of the select boxes and all of their options and store them in an array. (this part of the code isn't shown in my example)
  • On keyup of the search box iterate through all of the select dropdowns and their options. - If the text entered in the search box matches any of the text stored in the options in the array then leave those matching options in the select dropdown.
  • If the text entered does not match any options, remove those options from the select dropdown.
  • If the text entered in the search box matches any of the text stored in the options in the array, but it does not exist in the DOM, add it back in.
  • Lastly, keep the top option in all the select boxes always on top. This option says "(All)".

Any help would be appreciated. I'm currently getting a Node cannot be inserted at the specified point in the hierarchy on line 3 of jquery.min.js. :(

Jesse Atkinson
  • 10,586
  • 13
  • 42
  • 45

2 Answers2

2

If you don't want to show an option, just hide it!

First, from How do I make jQuery Contains case insensitive, including jQuery 1.8+?:

jQuery.expr[':'].Contains = function(a, i, m) { 
  return jQuery(a).text().toUpperCase().indexOf(m[3].toUpperCase()) >= 0; 
};


t.config.searchSpanInput.keyup(function () {
    var searchCriteria = t.config.searchSpanInput.val();
    $.each (t.config.promoInput, function (i, v) {
        $(v).find('option').show() // show all options in v.
          .not(':first-child') // drop first option (All)
          .not(':Contains("'+searchCriteria +'")') // drop options that match search
          .hide(); // hide the rest
    });
)}
Community
  • 1
  • 1
ori
  • 7,817
  • 1
  • 27
  • 31
  • You don't really need the `.each`, just replace `$(v)` with a query that matches your select boxes, such as: `$('#some_container select')` – ori Jan 31 '12 at 21:35
  • I am an idiot. I don't know why I'm going about it the way I was. I'm taking over for some vendor code written in India that is, well, terrible. I'm trying to convert their approach to a better more-readable approach. Unfortunately I didn't see the forest for the trees. – Jesse Atkinson Jan 31 '12 at 21:59
  • I seriously cannot thank you enough for this. I didn't think I'd even get an answer. Instead, you came up with a much better way to do things. Thank you. Saved me hours. – Jesse Atkinson Feb 01 '12 at 14:33
  • You're very welcome. BTW. you should look into escaping `searchCriteria` (at least `"` => `\"`) – ori Feb 01 '12 at 14:54
0

I'm actually working on a project that does just this. Check out my attempt:

 $("#filterBox").keyup(function(e) {        
    if($(this).val() === "") {
        $("option.myOptions").show();
    } else {
        var filter = $(this).val();

        $("option.myOptions:contains('" + filter + "')").show();
        $("option.myOptions:not(:contains('" + filter + "'))").hide();
    }

});

I know this changes your process a little bit, but I think it might be a better implementation than what you are doing. Rather than removing elements and adding them back in (and having to do all that sorting), it's easier just to hide them from the user.

jwegner
  • 7,043
  • 8
  • 34
  • 56