Test if a selector matches a given element

后端 未结 7 1661
庸人自扰
庸人自扰 2020-11-27 05:58

Is there any way to test if a selector would match a given DOM Element? Preferably, without the use of an external library like Sizzle. This is for a library and I would li

7条回答
  •  忘掉有多难
    2020-11-27 06:52

    I'm dealing with this issue now. I have to support IE8 with native Javascript, which presents a curious challenge: IE8 supports both querySelector and querySelectorAll, but not matchesSelector. If your situation is similar, here's an option for you to consider:

    When you're handed the DOM node and a selector, make a shallow copy of the node as well as its parent. This will preserve all of their attributes but won't make copies of their respective children.

    Attach the cloned node to the cloned parent. Use querySelector on the cloned parent -- the only thing it needs to search is the only child node it has so this process is constant time. It will either return the child node or it won't.

    That'd look something like this:

    function matchesSelector(node, selector)
    {
       var dummyNode = node.cloneNode(false);
       var dummyParent = node.parent.cloneNode(false);
       dummyParent.appendChild(dummyNode);
       return dummyNode === dummyParent.querySelector(selector);
    }
    

    It may be worth creating a complete chain of shallow-copied parents all the way up to the root node and querying the (mostly empty) dummy root if you'd like to be able to test your node's relationship to its ancestors.

    Off the top of my head I'm not sure what portion of selectors this would work for, but I think it'd do nicely for any that didn't worry about the tested node's children. YMMV.

    -- EDIT --

    I decided to write the function to shallow copy everything from the node being tested to root. Using this, a lot more selectors are employable. (Nothing related to siblings, though.)

    function clonedToRoot(node)
    {
        dummyNode = node.cloneNode(false);
        if(node.parentNode === document)
        {
            return {'root' : dummyNode, 'leaf' : dummyNode};
        }
        parent = clonedToRoot(node.parentNode).root;
        parent.appendChild(dummyNode);
        return {'root' : parent, 'leaf' : dummyNode};
    }
    
    function matchesSelector(node, selector)
    {
        testTree = clonedToRoot(node)
        return testTree.leaf === testTree.root.querySelector(selector)
    }
    

    I'd welcome an expert to explain what kinds of selectors there are that this wouldn't cover!

提交回复
热议问题