Alan Coromano
Alan Coromano

Reputation: 26008

"querySelectorAll()" with multiple conditions in JavaScript

Is it possible to make a search by querySelectorAll() using multiple unrelated conditions? If yes, how? And, how to specify whether those are AND or OR criteria?

For example:

How to find all forms, ps and legends with a single querySelectorAll() call? Possible?

Upvotes: 245

Views: 312224

Answers (6)

With querySelectorAll():

  • Logical AND (&&) can be archived by specifying elements and attributes without commas.
  • Logical OR (||) can be archived by specifying elements and attributes with commas.

For example, there is 2 forms as shown below:

<form class="form1" method="post">
  <input type="text" id="input1" name="fruits" value="Apple">
  <p id="p1">Orange</p>
</form>
<form class="form2" method="post">
  <input type="text" id="input2" name="fruits" value="Banana">
  <p id="p2">Kiwi</p>
</form>

<Logical AND (&&)>

Then, you can select Apple's <input> and Banana's <input> with [name="fruits"] as shown below:

document.querySelectorAll('[name="fruits"]');
// Apple's <input> and Banana's <input>

Now by specifying elements and attributes without commas, you can select only Apple's <input> as shown below:

                        // ↓ ↓ ↓ ↓ ↓  ↓ ↓ ↓               ↓ ↓ ↓ ↓ ↓ ↓ ↓     
document.querySelectorAll('form.form1 input[name="fruits"][id="input1"]');
// Apple's <input>

In addition, you can replace .form1 with [class="form1"] and [id="input1"] with #input1 as shown below:

                        //         .form1                       [id="input1"]
                        //     ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓                     ↓ ↓ ↓ ↓
document.querySelectorAll('form[class="form1"] input[name="fruits"]#input1');
// Apple's <input>

<Logical OR (||)>

Next, you can select Apple's <input> with #input1 as shown below:

document.querySelectorAll('#input1');
// Apple's <input>

Now by specifying elements and attributes with commas, you can select Apple's <input>, Orange's <p>, Banana's <input> and Kiwi's <p> as shown below:

                        //          ↓ ↓ ↓ ↓  ↓     
document.querySelectorAll('#input1, #input2, p');
                        //        ↑        ↑
// Apple's <input>, Orange's <p>, Banana's <input> and Kiwi's <p>

<Logical AND (&&)> and <Logical OR (||)>

In addition, of course, you can use both Logical AND and Logical OR together as shown below:

document.querySelectorAll('input#input1, input#input2, p#p1')[
// Apple's <input>, Orange's <p> and Banana's <input> 

Upvotes: 14

first
first

Reputation: 733

Using just document.querySelectorAll('selector1, selector2, selector3') didn't work for me, had to use forEach() method alongside to achieve the desired result.

document.querySelectorAll('selector1, selector2, selector3').forEach(item => {
        item.//code
    })

document.querySelectorAll('#id1, #id2, #id3').style = 'background-color: red';
document.querySelectorAll('#id4, #id5, #id6').forEach(item => {
    item.style = 'background-color: red';
})
<div id="id1">id1</div>
<div id="id2">id2</div>
<div id="id3">id3</div>
<div id="id4">id4</div>
<div id="id5">id5</div>
<div id="id6">id6</div>

Upvotes: 5

Alejandro D.V.
Alejandro D.V.

Reputation: 199

With pure JavaScript you can do this (such as SQL) and anything you need, basically:

<html>

<body>

<input type='button' value='F3' class="c2" id="btn_1">
<input type='button' value='F3' class="c3" id="btn_2">
<input type='button' value='F1' class="c2" id="btn_3">

<input type='submit' value='F2' class="c1" id="btn_4">
<input type='submit' value='F1' class="c3" id="btn_5">
<input type='submit' value='F2' class="c1" id="btn_6">

<br/>
<br/>

<button onclick="myFunction()">Try it</button>

<script>
    function myFunction() 
    {
        var arrFiltered = document.querySelectorAll('input[value=F2][type=submit][class=c1]');

            arrFiltered.forEach(function (el)
            {                
                var node = document.createElement("p");
                
                node.innerHTML = el.getAttribute('id');

                window.document.body.appendChild(node);
            });
        }
    </script>

</body>

</html>

Upvotes: 10

mikus
mikus

Reputation: 3215

According to the documentation, just like with any css selector, you can specify as many conditions as you want, and they are treated as logical 'OR'.

This example returns a list of all div elements within the document with a class of either "note" or "alert":

var matches = document.querySelectorAll("div.note, div.alert");

source: https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll

Meanwhile to get the 'AND' functionality you can for example simply use a multiattribute selector, as jquery says:

https://api.jquery.com/multiple-attribute-selector/

ex. "input[id][name$='man']" specifies both id and name of the element and both conditions must be met. For classes it's as obvious as ".class1.class2" to require object of 2 classes.

All possible combinations of both are valid, so you can easily get equivalent of more sophisticated 'OR' and 'AND' expressions.

Upvotes: 38

T.J. Crowder
T.J. Crowder

Reputation: 1073909

Is it possible to make a search by querySelectorAll using multiple unrelated conditions?

Yes, because querySelectorAll accepts full CSS selectors, and CSS has the concept of selector groups, which lets you specify more than one unrelated selector. For instance:

var list = document.querySelectorAll("form, p, legend");

...will return a list containing any element that is a form or p or legend.

CSS also has the other concept: Restricting based on more criteria. You just combine multiple aspects of a selector. For instance:

var list = document.querySelectorAll("div.foo");

...will return a list of all div elements that also (and) have the class foo, ignoring other div elements.

You can, of course, combine them:

var list = document.querySelectorAll("div.foo, p.bar, div legend");

...which means "Include any div element that also has the foo class, any p element that also has the bar class, and any legend element that's also inside a div."

Upvotes: 365

Bergi
Bergi

Reputation: 664124

Yes, querySelectorAll does take a group of selectors:

form, p, legend

Upvotes: 4

Related Questions