144

I am trying to go through an element and get all the attributes of that element to output them, for example an tag may have 3 or more attributes, unknown to me and I need to get the names and values of these attributes. I was thinking something along the lines of:

$(this).attr().each(function(index, element) {
    var name = $(this).name;
    var value = $(this).value;
    //Do something with name and value...
});

Could anyone tell me if this is even possible, and if so what the correct syntax would be?

Styphon
  • 10,304
  • 9
  • 52
  • 86

8 Answers8

273

The attributes property contains them all:

$(this).each(function() {
  $.each(this.attributes, function() {
    // this.attributes is not a plain object, but an array
    // of attribute nodes, which contain both the name and value
    if(this.specified) {
      console.log(this.name, this.value);
    }
  });
});

What you can also do is extending .attr so that you can call it like .attr() to get a plain object of all attributes:

(function(old) {
  $.fn.attr = function() {
    if(arguments.length === 0) {
      if(this.length === 0) {
        return null;
      }

      var obj = {};
      $.each(this[0].attributes, function() {
        if(this.specified) {
          obj[this.name] = this.value;
        }
      });
      return obj;
    }

    return old.apply(this, arguments);
  };
})($.fn.attr);

Usage:

var $div = $("<div data-a='1' id='b'>");
$div.attr();  // { "data-a": "1", "id": "b" }
pimvdb
  • 151,816
  • 78
  • 307
  • 352
  • 1
    You may want to fix it when there's no matched elements e.g. `$().attr()` – Alexander Feb 01 '13 at 12:17
  • 12
    The `attributes` collection contains all possible attributes in older IE, not just those that have been specified in the HTML. You can work around this by filtering the attributes list using each attributes `specified` property. – Tim Down Feb 01 '13 at 13:08
  • 7
    This is a very good and expected functionality for jQuery `.attr()` method. It's strange jQuery does not include it. – ivkremer May 21 '14 at 10:06
  • just a bit curious to know that why we are accessing it as an array in `this[0].attributes`? – Vishal Sep 10 '15 at 06:51
  • 1
    `attributes` is not an Array though... in Chrome at least it's a `NamedNodeMap`, which is an Object. – Samuel Edwin Ward Oct 25 '15 at 21:55
  • For the record, while ancient IE versions did list all possible attributes, IE7 was the last version affected by that issue. These days, there is no need to filter the `attributes` list with the `specified` property. – hashchange Jul 27 '16 at 21:00
  • Mar 2020. A bit has changed, on Chrome at least. this.specified is now true for any classes as well as custom attributes... – den232 Mar 30 '20 at 11:26
31

Here is an overview of the many ways that can be done, for my own reference as well as yours :) The functions return a hash of attribute names and their values.

Vanilla JS:

function getAttributes ( node ) {
    var i,
        attributeNodes = node.attributes,
        length = attributeNodes.length,
        attrs = {};

    for ( i = 0; i < length; i++ ) attrs[attributeNodes[i].name] = attributeNodes[i].value;
    return attrs;
}

Vanilla JS with Array.reduce

Works for browsers supporting ES 5.1 (2011). Requires IE9+, does not work in IE8.

function getAttributes ( node ) {
    var attributeNodeArray = Array.prototype.slice.call( node.attributes );

    return attributeNodeArray.reduce( function ( attrs, attribute ) {
        attrs[attribute.name] = attribute.value;
        return attrs;
    }, {} );
}

jQuery

This function expects a jQuery object, not a DOM element.

function getAttributes ( $node ) {
    var attrs = {};
    $.each( $node[0].attributes, function ( index, attribute ) {
        attrs[attribute.name] = attribute.value;
    } );

    return attrs;
}

Underscore

Also works for lodash.

function getAttributes ( node ) {
    return _.reduce( node.attributes, function ( attrs, attribute ) {
        attrs[attribute.name] = attribute.value;
        return attrs;
    }, {} );
}

lodash

Is even more concise than the Underscore version, but only works for lodash, not for Underscore. Requires IE9+, is buggy in IE8. Kudos to @AlJey for that one.

function getAttributes ( node ) {
    return _.transform( node.attributes, function ( attrs, attribute ) {
        attrs[attribute.name] = attribute.value;
    }, {} );
}

Test page

At JS Bin, there is a live test page covering all these functions. The test includes boolean attributes (hidden) and enumerated attributes (contenteditable="").

hashchange
  • 7,029
  • 1
  • 45
  • 41
4

A debugging script (jquery solution based on the answer above by hashchange)

function getAttributes ( $node ) {
      $.each( $node[0].attributes, function ( index, attribute ) {
      console.log(attribute.name+':'+attribute.value);
   } );
}

getAttributes($(this));  // find out what attributes are available
zzapper
  • 4,743
  • 5
  • 48
  • 45
3

with LoDash you could simply do this:

_.transform(this.attributes, function (result, item) {
  item.specified && (result[item.name] = item.value);
}, {});
Eugene Kuzmenko
  • 947
  • 9
  • 11
0

Using javascript function it is easier to get all the attributes of an element in NamedArrayFormat.

$("#myTestDiv").click(function(){
  var attrs = document.getElementById("myTestDiv").attributes;
  $.each(attrs,function(i,elem){
    $("#attrs").html(    $("#attrs").html()+"<br><b>"+elem.name+"</b>:<i>"+elem.value+"</i>");
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="myTestDiv" ekind="div" etype="text" name="stack">
click This
</div>
<div id="attrs">Attributes are <div>
Vishnu Prasanth G
  • 1,133
  • 12
  • 12
0

Simple solution by Underscore.js

For example: Get all links text who's parents have class someClass

_.pluck($('.someClass').find('a'), 'text');

Working fiddle

pymen
  • 5,737
  • 44
  • 35
0

My suggestion:

$.fn.attrs = function (fnc) {
    var obj = {};
    $.each(this[0].attributes, function() {
        if(this.name == 'value') return; // Avoid someone (optional)
        if(this.specified) obj[this.name] = this.value;
    });
    return obj;
}

var a = $(el).attrs();

William
  • 166
  • 1
  • 4
0

Here is a one-liner for you.

JQuery Users:

Replace $jQueryObject with your jQuery object. i.e $('div').

Object.values($jQueryObject.get(0).attributes).map(attr => console.log(`${attr.name + ' : ' + attr.value}`));

Vanilla Javascript Users:

Replace $domElement with your HTML DOM selector. i.e document.getElementById('demo').

Object.values($domElement.attributes).map(attr => console.log(`${attr.name + ' : ' + attr.value}`));

Cheers!!

steven7mwesigwa
  • 5,701
  • 3
  • 20
  • 34