6

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.

3

4 Answers 4

2

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');
});
Sign up to request clarification or add additional context in comments.

Comments

2

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>

3 Comments

How well does this scale? Say you have 5,000-10,000 entry tags - what does the performance look like in a situation like that? Is there a better solution in that case?
@That1Guy I'm not certain. Jsperf is giving trouble.
FYI rather than wrapping the element in a jQuery object to get the attribute's value (eg $(this).attr('id'), you can simply do this.getAttribute('id')
1

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>

Comments

0

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>

1 Comment

@That1Guy This is probably faster, more flexible and scales better than a solution using jQuery in all intermediate steps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.