How can you do the equivalent to
document.querySelectorAll(\'[data-foo]\')
where query
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);
}
That works too:
document.querySelector([attribute="value"]);
So:
document.querySelector([data-foo="bar"]);
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
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]');
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;
}
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');