Get elements by attribute when querySelectorAll is not available without using libraries?

后端 未结 8 744
半阙折子戏
半阙折子戏 2020-11-22 11:27

How can you do the equivalent to

document.querySelectorAll(\'[data-foo]\')

where query

相关标签:
8条回答
  • 2020-11-22 11:44

    Don't use in Browser

    In the browser, use document.querySelect('[attribute-name]').

    But if you're unit testing and your mocked dom has a flakey querySelector implementation, this will do the trick.

    This is @kevinfahy's answer, just trimmed down to be a bit with ES6 fat arrow functions and by converting the HtmlCollection into an array at the cost of readability perhaps.

    So it'll only work with an ES6 transpiler. Also, I'm not sure how performant it'll be with a lot of elements.

    function getElementsWithAttribute(attribute) {
      return [].slice.call(document.getElementsByTagName('*'))
        .filter(elem => elem.getAttribute(attribute) !== null);
    }
    

    And here's a variant that will get an attribute with a specific value

    function getElementsWithAttributeValue(attribute, value) {
      return [].slice.call(document.getElementsByTagName('*'))
        .filter(elem => elem.getAttribute(attribute) === value);
    }
    
    0 讨论(0)
  • 2020-11-22 11:47

    That works too:

    document.querySelector([attribute="value"]);
    

    So:

    document.querySelector([data-foo="bar"]);
    
    0 讨论(0)
  • 2020-11-22 11:48

    Use

    //find first element with "someAttr" attribute
    document.querySelector('[someAttr]')
    

    or

    //find all elements with "someAttr" attribute
    document.querySelectorAll('[someAttr]') 
    

    to find elements by attribute. It's now supported in all relevant browsers (even IE8): http://caniuse.com/#search=queryselector

    0 讨论(0)
  • 2020-11-22 11:55

    I played a bit around and ended up with this crude solution:

    function getElementsByAttribute(attribute, context) {
      var nodeList = (context || document).getElementsByTagName('*');
      var nodeArray = [];
      var iterator = 0;
      var node = null;
    
      while (node = nodeList[iterator++]) {
        if (node.hasAttribute(attribute)) nodeArray.push(node);
      }
    
      return nodeArray;
    }
    

    The usage is quite simple, and works even in IE8:

    getElementsByAttribute('data-foo');
    // or with parentNode
    getElementsByAttribute('data-foo', document);
    

    http://fiddle.jshell.net/9xaxf6jr/

    But I recommend to use querySelector / All for this (and to support older browsers use a polyfill):

    document.querySelectorAll('[data-foo]');
    
    0 讨论(0)
  • 2020-11-22 12:06

    A little modification on @kevinfahy 's answer, to allow getting the attribute by value if needed:

    function getElementsByAttributeValue(attribute, value){
      var matchingElements = [];
      var allElements = document.getElementsByTagName('*');
      for (var i = 0, n = allElements.length; i < n; i++) {
        if (allElements[i].getAttribute(attribute) !== null) {
          if (!value || allElements[i].getAttribute(attribute) == value)
            matchingElements.push(allElements[i]);
        }
      }
      return matchingElements;
    }
    
    0 讨论(0)
  • 2020-11-22 12:08

    You could write a function that runs getElementsByTagName('*'), and returns only those elements with a "data-foo" attribute:

    function getAllElementsWithAttribute(attribute)
    {
      var matchingElements = [];
      var allElements = document.getElementsByTagName('*');
      for (var i = 0, n = allElements.length; i < n; i++)
      {
        if (allElements[i].getAttribute(attribute) !== null)
        {
          // Element exists with attribute. Add to array.
          matchingElements.push(allElements[i]);
        }
      }
      return matchingElements;
    }
    

    Then,

    getAllElementsWithAttribute('data-foo');
    
    0 讨论(0)
提交回复
热议问题