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

JavascriptDom

Javascript Problem Overview


<p data-foo="bar">

How can you do the equivalent to

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

where querySelectorAll is not available?

I need a native solution that works at least in IE7. I don’t care about IE6.

Javascript Solutions


Solution 1 - Javascript

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

Solution 2 - Javascript

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

Solution 3 - Javascript

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]');

Solution 4 - Javascript

Try this it works

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

example :

document.querySelector('[role="button"]')

Solution 5 - Javascript

That works too:

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

So:

document.querySelector([data-foo="bar"]);

Solution 6 - Javascript

Try this - I slightly changed the above answers:

var getAttributes = function(attribute) {
    var allElements = document.getElementsByTagName('*'),
        allElementsLen = allElements.length,
        curElement,
        i,
        results = [];

    for(i = 0; i < allElementsLen; i += 1) {
        curElement = allElements[i];

        if(curElement.getAttribute(attribute)) {
            results.push(curElement);
        }
    }

    return results;
};

Then,

getAttributes('data-foo');

Solution 7 - Javascript

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;
}

Solution 8 - Javascript

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionryanveView Question on Stackoverflow
Solution 1 - JavascriptkevinfahyView Answer on Stackoverflow
Solution 2 - JavascriptPylinuxView Answer on Stackoverflow
Solution 3 - JavascriptyckartView Answer on Stackoverflow
Solution 4 - JavascriptBrainabilGHView Answer on Stackoverflow
Solution 5 - JavascriptCallMarlView Answer on Stackoverflow
Solution 6 - JavascriptSurender LohiaView Answer on Stackoverflow
Solution 7 - JavascriptBernardo Dal CornoView Answer on Stackoverflow
Solution 8 - JavascriptgargantuanView Answer on Stackoverflow