Reputation: 8572
Suppose we have the following HTML:
<entries>
<entry id="1" />
<entry id="2" />
<entry id="3" />
<entry id="4" />
</entries>
Does jQuery have a built-in mechanism for retrieving all values of a specific attribute? And if not, then what is the most efficient way to retrieve them?
Eg, something similar to: $('entry').attrs('id')
, returning a list of values across all elements which returns something similar to ["1", "2", "3", "4"]
?
jQuery documentation under General Attributes (which is where attr
is found,) doesn't give any hint to such a thing existing, and I've found nothing on StackOverflow or any other support forum asking this question.
Upvotes: 6
Views: 446
Reputation: 19762
There is not a direct function to do that. However, it can be easily accomplished using .map(). E.g.,
let ids = $('entry').map(function() {
return this.getAttribute('id');
}).get();
let ids = $('entry').map(function() {
return this.getAttribute('id');
}).get();
console.log(ids);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<entries>
<entry id="1" />
<entry id="2" />
<entry id="3" />
<entry id="4" />
</entries>
Upvotes: 2
Reputation: 21161
You can extend jQuery using jQuery.fn.extend()
and add a custom method that iterates over all matching elements, extracting a single or multiple attributes from all of them and pushes/merges them into the returned array/object, respectively.
As the implementation is vanilla JS, this will be faster than working with jQuery objects and functions in all intermediate steps, but might need some tuning depending on which browsers you need to support:
jQuery.fn.extend({
attrs: function(attributeName) {
if (attributeName) {
return this.toArray().map((el) => el.getAttribute(attributeName));
}
return this.toArray().reduce((merged, el) => {
const { attributes } = el;
const totalAttributes = attributes.length;
for (let i = 0; i < totalAttributes; ++i) {
const attribute = attributes[i].nodeName;
if (merged[attribute]) {
merged[attribute].push(el.getAttribute(attribute));
} else {
merged[attribute] = [el.getAttribute(attribute)];
}
}
return merged;
}, {});
},
});
console.log($('entry').attrs());
console.log($('entry').attrs('id'));
console.log($('entry').attrs('class'));
.as-console-wrapper {
max-height: 100% !important;
}
<entries>
<entry id="1" class="foo" />
<entry id="2" class="bar" />
<entry id="3" class="baz" />
<entry id="4" class="qux" />
</entries>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Upvotes: 0
Reputation: 7086
Here's one way that uses the JavaScript Array .map() function:
let ids = jQuery.makeArray($('entry')).map(entry => entry.id);
console.log('ids:', ids);
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
<entries>
<entry id="1" />
<entry id="2" />
<entry id="3" />
<entry id="4" />
</entries>
Upvotes: 1
Reputation: 820
You can use something like that: https://jsfiddle.net/g903dyp6/
<entries>
<entry id="1" />
<entry id="2" />
<entry id="3" />
<entry id="4" />
</entries>
let arr = $.map($('entry'), function(el) {
return $(el).attr('id');
});
Upvotes: 2