Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery Filter Select Menu with rel value

I use this code to filter my <select> menu:

jQuery.fn.filterByText = function(textbox) {
    return this.each(function() {
        var select = this;
        var options = [];
        $(select).find('option').not('option:first-child').each(function() {
            options.push({value: $(this).val(), text: $(this).text(), rel: $(this).attr('rel')});
        });
        $(select).data('options', options);

        $(textbox).bind('change keyup', function() {
            var options = $(select).empty().data('options');
            var search = $.trim($(this).val());
            var regex = new RegExp(search,"gi");

            $.each(options, function(i) {
                var option = options[i];
                if(option.text.match(regex) !== null) {
                    $(select).append(
                        $('<option>').text(option.text).val(option.value)
                    );
                }
            });
        });
    });
};

As you can see, I use .not('option:first-child') to exclude the first <option> tag.

I have 2 problems with this code, it works fine, but I need to include the rel attribute in my filtering and I want to re-add the option:first-child when I clear my textbox.

I've added the rel: $(this).attr('rel') to my options array, but I'm not sure how to add it back to the filtered results?

Can I create var original = []; and push all of the original values into it?

like image 931
tcd Avatar asked Nov 16 '25 17:11

tcd


2 Answers

To include the rel attribute in your filtering, you almost did the job. Just add .attr('rel', option.rel):

$('<option>').text(option.text).val(option.value).attr('rel', option.rel)

Instead of re-add the first option, you can just keep it, and remove the others:

$(select).children("option").not(":first").remove();

Edit (how to retrieve the "data" attribute):

You can do like this (improvable using variables caching):

var options = $(select).data('options');
$(select).children("option").not(":first").remove();

or like this, to maintain chainability:

var options = $(select).children("option:not(:first)").remove().end().data('options');

Edited answer

$(select).children("option").not(":first")
$(select).find('option').not('option:first-child')

children VS find:

The .children() method differs from .find() in that .children() only travels a single level down the DOM tree while .find() can traverse down multiple levels to select descendant elements (grandchildren, etc.) as well.

Since options are direct children of the select element, it's better to use children().

:first VS :first-child

The :first pseudo-class is equivalent to :eq(0). It could also be written as :lt(1). While this matches only a single element, :first-child can match more than one: One for each parent.

We only have one parent (our select). So both work here. However, note that:

Because :first is a jQuery extension and not part of the CSS specification, queries using :first cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. To achieve the best performance when using :first to select elements, first select the elements using a pure CSS selector, then use .filter(":first") (or here, .not(":first")).

As often, it's all depending on the situation / context.

like image 189
CronosS Avatar answered Nov 19 '25 10:11

CronosS


Try something like this for attributes:

attr('rel', option.rel)

No need in $('select').data('option'), because you store them in array. Use object caching, no need for wrapping 3 times option to get 3 values.

Demo how it could look like: http://jsfiddle.net/BSDdZ/

like image 32
webdeveloper Avatar answered Nov 19 '25 08:11

webdeveloper



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!