Domanda

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.

È stato utile?

Soluzione

Looks 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);

Altri suggerimenti

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top