I needed to write a function today in JavaScript that would return all elements based on a given attribute.
e.g retrieve all elements that have an id attribute in them.
The function I wrote for this is as follows:
function getElements(attrib) {
// get all dom elements
var elements = document.getElementsByTagName("*");
// initialize array to put matching elements into
var foundelements = [];
// loop through all elements in document
for (var i = 0; i < elements.length; i++) {
// check to see if element has any attributes
if (elements[i].attributes.length > 0) {
// loop through element's attributes and add it to array if it matches attribute from argument
for (var x = 0; x < elements[i].attributes.length; x++) {
if (elements[i].attributes[x].name === attrib) {
foundelements.push(elements[i]);
}
}
}
}
return foundelements;
}
Looking at this, I am sure it could be written a great deal better. Any feedback would be much appreciated!
2 Answers 2
querySelectorAll
First off, if you're only dealing with relatively modern browsers (basically anything above IE7), you can use querySelectorAll
, which is the fastest and easiest method to go about this:
document.querySelectorAll('[' + attrib + ']');
Here's the fiddle: http://jsfiddle.net/rc6Pq/
Sizzle
If you're stuck having to support IE7 and below, then you might as well just include the Sizzle selector engine, since you're bound to be using some additional selectors in the future. Once you include the Sizzle script in your page, you could then just use it in a similar fashion to the native querySelectorAll
:
Sizzle('[' + attrib + ']');
Here's the fiddle: http://jsfiddle.net/rc6Pq/1/
jQuery
If you're already using jQuery on the page, you don't have to use Sizzle separately, since jQuery has Sizzle incorporated within it. If that's the case, just use this:
$('[' + attrib + ']').get();
Here's the fiddle: http://jsfiddle.net/rc6Pq/2/
I'm not too familiar with JS, so just three generic notes:
It seems to me that the
elements[i].attributes.length > 0
check is unnecessary because the statements inside the followingfor
loop won't ifelements[i].attributes.length
is zero.Consider creating local variables for
elements[i]
andelements[i].attributes
. It would remove some duplication.for (var i = 0; i < elements.length; i++) { var currentElement = elements[i]; var currentAttributes = currentElement.attributes; for (var x = 0; x < currentAttributes.length; x++) { if (currentAttributes[x].name === attrib) { foundelements.push(currentElement); } } }
It might be easier with jQuery: find element by attribute.
-
\$\begingroup\$ I didn't realize that the check in your first note was unnecessary, I thought the interpreter might throw an error if it tried to loop something that wasn't an array. Your second note helped make my code more readable. Thank palacint! \$\endgroup\$John H– John H2012年07月27日 16:40:35 +00:00Commented Jul 27, 2012 at 16:40
-
\$\begingroup\$ @JohnH
element.attributes
is never an array; it's an array-like object. But even when there are 0 attributes, it is set to an object with a length of 0. So, the first comparison of the loop would returnfalse
without error. \$\endgroup\$delete me– delete me2012年07月30日 18:07:31 +00:00Commented Jul 30, 2012 at 18:07