I had a situation in which I wanted to focus either an input tag, if it existed, or it's container if it didn't. So I thought of an intelligent way of doing it:
document.querySelector('.container input, .container').focus();
Funny, though, querySelector
always returns the .container
element.
I started to investigate and came out that, no matter the order in which the different selectors are put, querySelector
always returns the same element.
For example:
var elem1 = document.querySelector('p, div, pre');
var elem2 = document.querySelector('pre, div, p');
elem1 === elem2; // true
elem1.tagName; // "P".
My question is: What are the "reasons" of this behavior and what "rules" (if any) make P elements have priority over DIV and PRE elements.
Note: In the situation mentioned above, I came out with a less-elegant but functional solution:
(document.querySelector('.container input') || document.querySelector('.container') ).focus();
Yes, because querySelectorAll accepts full CSS selectors, and CSS has the concept of selector groups, which lets you specify more than one unrelated selector.
Use the querySelectorAll() method to select elements by multiple ids, e.g. document. querySelectorAll('#box1, #box2, #box3') . The method takes a string containing one or more selectors as a parameter and returns a collection of the matching elements. Here is the HTML for the examples in this article.
The querySelectorAll() method returns all elements that matches a CSS selector(s). The querySelectorAll() method returns a NodeList.
document.querySelector
returns only the first element matched, starting from the first element in the markup. As written on MDN:
Returns the first element within the document (using depth-first pre-order traversal of the document's nodes|by first element in document markup and iterating through sequential nodes by order of amount of child nodes) that matches the specified group of selectors.
If you want all elements to match the query, use document.querySelectorAll
(docs), i.e. document.querySelectorAll('pre, div, p')
. This returns an array of the matched elements.
The official document says that,
Returns the first element within the document (using depth-first pre-order traversal of the document's nodes|by first element in document markup and iterating through sequential nodes by order of amount of child nodes) that matches the specified group of selectors.
So that means, in your first case .container
is the parent element so that it would be matched first and returned. And in your second case, the paragraph should be the first element in the document while comparing with the other pre
and div
. So it was returned.
That's precisely the intended behavior of .querySelector()
— it finds all the elements in the document that match your query, and then returns the first one.
That's not "the first one you listed", it's "the first one in the document".
This works, essentially, like a CSS selector. The selectors p, div, pre
and pre, div, p
are identical; they both match three different types of element. So the reason elem1.tagName == 'P'
is simply that you have a <p>
on the page before any <pre>
or <div>
tags.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With