Compound JQuery Selectors

2020-02-12 12:16发布

问题:

I have a page with several multiselect drop-down menus. Each menu has a general category, for example:

Box1: Fruits         Box2: Veggies
 - Peach              - Celery
 - Orange             - Broccoli
 - Apple              - Spinach

On the page are objects which contain up to one class from each dropdown.

When a class is selected from a dropdown, these objects are filtered based on the selected class and only those which contain the class are displayed. For example, if you select "Peach" from the first drop down, all the Apples and Oranges would be hidden. (.peach)

Since you are able to select multiple items from a dropdown, you can then also select "Apple" causing both the "Apple" and "Peach" objects to display, but not the Oranges. (.peach, .apple)

Alternatively, you could select one of the veggies, and it will only display objects which contain both. (.peach.spinach)

The problem I'm having is that I can't figure out how to extend this so that I can have something as complex as "Objects which are ((Apples OR Peaches) AND (Spinach OR Broccoli))" I recognize that I could do (.apple.spinach, .apple.broccoli, .peach.spinach, .peach.broccoli) however this seems like it would end up needlessly complex, especially as the size of the menus, number of menus, and number of options selected grows (I simplified to two for the example).

I've tried several ways of solving this, such as:

//:has() does not appear to be useable in this fashion
(:has(.peach, .apple):has(.spinach, .broccoli)) 

//multiple selectors within brackets[] doesn't appear to be supported
([class~='apple', class~='peach'][class~='spinach', class~='broccoli'])

//grouping OR sets doesn't appear to help:
((.peach, .apple)(.spinach, .broccoli))

Is there some simple way of doing this that I'm missing or screwing up? Or am I forced to create some heavy loops to generate all the possible AND combinations?

回答1:

A multiple selector can indeed be used to implement the OR operator. To implement the AND operator between two expressions, you can use filter():

// ((Apples OR Peaches) AND (Spinach OR Broccoli))
var matches = $(".peach, .apple").filter(".spinach, .broccoli");

You can chain calls to filter() if you have multiple expressions:

// ((Apples OR Peaches) AND (Spinach OR Broccoli) AND (Dragon OR Unicorn))
var matches = $(".peach, .apple")
              .filter(".spinach, .broccoli")
              .filter(".dragon, .unicorn");


回答2:

You may be able to do this:

$(".apple, .peach").filter(".spinach, .broccoli");

It will select the fruits, then select the vegetable classes from those fruits.

In the generic case:

var fruits = [".apple", ".peach", /* Rest of your fruits */],
    vegetables = [".broccoli", ".spinach", /* Rest of your vegetables */];

$(fruits.join(",")).filter(vegetables.join(","));