Is there a pure JS equivalent of jQuery .is()
on modern browsers?
I know there is the querySelector
method, but I want to check the node itself, rather than finding child nodes.
Is there a pure JS equivalent of jQuery .is()
on modern browsers?
I know there is the querySelector
method, but I want to check the node itself, rather than finding child nodes.
5 Answers
Reset to default 8Looks like matchesSelector
is what I want.
https://developer.mozilla.org/en-US/docs/Web/API/Element.matches
Polyfill is here:
https://gist.github.com/jonathantneal/3062955
this.Element && function(ElementPrototype) {
ElementPrototype.matchesSelector = ElementPrototype.matchesSelector ||
ElementPrototype.mozMatchesSelector ||
ElementPrototype.msMatchesSelector ||
ElementPrototype.oMatchesSelector ||
ElementPrototype.webkitMatchesSelector ||
function (selector) {
var node = this, nodes = (node.parentNode || node.document).querySelectorAll(selector), i = -1;
while (nodes[++i] && nodes[i] != node);
return !!nodes[i];
}
}(Element.prototype);
You've already answered your own question, but as per my comment above I looked through the jQuery.fn.is
function. This isn't a strip from the source, because the function they're using is more generalized so it can be used across multiple other functions, But I've boiled it down to this function:
function is(elem, selector){ //elem is an element, selector is an element, an array or elements, or a string selector for `document.querySelectorAll`
if(selector.nodeType){
return elem === selector;
}
var qa = (typeof(selector) === 'string' ? document.querySelectorAll(selector) : selector),
length = qa.length,
returnArr = [];
while(length--){
if(qa[length] === elem){
return true;
}
}
return false;
}
DEMO
Another approach: Wrap the element you're testing in a parent then run querySelector
from that
function is(el, selector) {
var div = document.createElement('div');
div.innerHTML = el.outerHTML;
return div.querySelector(selector);
}
I ran one test and it worked:
JS
var a = document.querySelector('a');
if(is(a, '.foo[name=foo]')) {
console.log('YES');
} else {
console.log('Nope');
}
HTML
<a href="#" class="foo" name="foo">Meow</a>
I am sure this can be done a lot prettier.
According to youmightnotneedjquery.com depending on your IE compatibility requirement, you can even end up with simpler version:
var is = function(element, selector) {
return (element.matches || element.matchesSelector || element.msMatchesSelector ||
element.mozMatchesSelector || element.webkitMatchesSelector ||
element.oMatchesSelector).call(element, selector);
};
is(element, '.my-class');
With ES6 this would be:
const is = (element, selector) =>
(element.matches || element.matchesSelector || element.msMatchesSelector ||
element.mozMatchesSelector || element.webkitMatchesSelector ||
element.oMatchesSelector).call(element, selector);
};
is(element, '.my-class');
Following the concept from @AdamMerrifield it could be useful building the method is
on any element through the Element.prototype
chain by doing:
Element.prototype.is = function(match) {
...
};
Element
is supported by all major browsers, even by IE 8+.
Here is a DEMO.
node.nodeName
? – StackSlave Commented May 14, 2014 at 2:26