Frage

I have a simple live search filter that runs as follow:

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

var $section = $('section');
var $noresults = $('#noresults');

$noresults.hide();

$('#search').bind('keyup focus', function() {
    var input = $(this).val();

    if(input) {
        $section.hide();
        var result = $("section:Contains('"+input+"')");

        if(result.length) {
            $noresults.hide();
            result.show();
        }
        else {
            $noresults.show();
        }
    }
    else {
        $noresults.hide();
        $section.show();
    }
});

It works fine but I was asked to make it accept multiple values. With this current filter, if I type "ABC" only the sections containing the string "ABC" will be displayed. Yet if I type "ABC DEF", nothing will be displayed even though these two strings are contained in one or several sections of the document.

What I would like to obtain is a filter that only displays the sections containing the strings "ABC" and "DEF" when I type "ABC DEF" in the input field.

I tried a couple of solutions, that involve splitting the input, and came up with the following version but it does not work. Could you please help me make this filter accept multiple values?

$('#search').bind('keyup focus', function() {
    var input = $(this).val();

    var arr = input.split(/[ ,]+/);

    var len = arr.length;

    console.log(arr);
    console.log(len);

    for(var i=0; i<len; ++i) {  
        if(input) {
            $section.hide();

            var result = $("section:Contains('"+arr[i]+"')");

            if(result.length) {
                $noresults.hide();
                result.show();
            }
            else {
                $noresults.show();
            }
        }
        else {
            $noresults.hide();
            $section.show();
        }
    }
});

Thanks a lot for your help.

War es hilfreich?

Lösung 2

  • Cache jQuery(a).text().toUpperCase()
  • Split query by whitespace
  • Loop over the split query, testing each one
  • If you find a query member that is not contained, return false
  • At loop end, return true

Also note that if you don't want to change your custom selector code, you can also write section:Contains('ABC'):Contains('DEF').

EDIT: Translation:

jQuery.expr[':'].Contains = function(a,i,m) { 
  var text = jQuery(a).text().toUpperCase();          // Cache `jQuery(a).text().toUpperCase()`
  var words = m[3].split(/\s+/);                      // Split query by whitespace
  for (var i = 0; i < words.length; i++) {            // Loop over the split query, testing each one
    if (-1 == text.indexOf(words[i].toUpperCase())) { // If you find a query member that is not contained,
      return false;                                   // return false
    }
  }
  return true;                                        // At loop end, return true
};

Andere Tipps

It looks like it's not possible to select multiple criteria from the one ":contains" method ( http://forum.jquery.com/topic/how-to-get-contains-to-work-with-multiple-criteria).

Chaining the :contains method will do what you want to achieve:

$('section:contains("ABC"):contains("DEF")');

You could create your selector dynamically so that it would work for an array of variable lengths.

Here's a jsfiddle which should do what you are after: http://jsfiddle.net/sKgpj/

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top