192

I want to put all attributes in a Html element into an array: like i have a jQuery Object, whichs html looks like this:

<span name="test" message="test2"></span>

now one way is to use the xml parser described here, but then i need to know how to get the html code of my object.

the other way is to make it with jquery, but how? the number of attributes and the names are generic.

Thanks

Btw: I can't access the element with document.getelementbyid or something similar.

Community
  • 1
  • 1
k0ni
  • 2,417
  • 4
  • 22
  • 25

20 Answers20

246

If you just want the DOM attributes, it's probably simpler to use the attributes node list on the element itself:

var el = document.getElementById("someId");
for (var i = 0, atts = el.attributes, n = atts.length, arr = []; i < n; i++){
    arr.push(atts[i].nodeName);
}

Note that this fills the array only with attribute names. If you need the attribute value, you can use the nodeValue property:

var nodes=[], values=[];
for (var att, i = 0, atts = el.attributes, n = atts.length; i < n; i++){
    att = atts[i];
    nodes.push(att.nodeName);
    values.push(att.nodeValue);
}
Roland Bouman
  • 31,125
  • 6
  • 66
  • 67
  • The problem is that i can't use getElementById, it's a jquery object. is there a way that i can make getelementbyclassname inside a context like at jquery? – k0ni Jan 12 '10 at 12:23
  • 4
    You can use `getElementById` - `var el = document.getElementById($(myObj).attr("id"));` – Sampson Jan 12 '10 at 12:36
  • 46
    You can get the DOM object from a jQuery object via the `get` method...e.g.: `var obj = $('#example').get(0);` – Matt Huggins Sep 24 '10 at 22:25
  • 3
    @k0ni - could you use e.g. var atts = $(myObject)[0].attributes; ? – Ralph Cowling Jul 18 '11 at 15:57
  • 13
    Warning: in IE this gets not only specified, but all **possible** attributes – Alexey Lebedev May 22 '13 at 07:28
  • `att.nodeName` and `att.nodeValue` are deprecated properties and may show console warnings. The preferred properties are `att.name` and `att.value` (however, you might want to fall back to the old properties). – kumar303 Jul 06 '20 at 14:57
74

You can use this simple plugin as $('#some_id').getAttributes();

(function($) {
    $.fn.getAttributes = function() {
        var attributes = {}; 

        if( this.length ) {
            $.each( this[0].attributes, function( index, attr ) {
                attributes[ attr.name ] = attr.value;
            } ); 
        }

        return attributes;
    };
})(jQuery);
Community
  • 1
  • 1
manRo
  • 1,455
  • 1
  • 14
  • 19
60

Simple:

var element = $("span[name='test']");
$(element[0].attributes).each(function() {
console.log(this.nodeName+':'+this.nodeValue);});
Aki143S
  • 809
  • 7
  • 5
  • 8
    `Attr.nodeValue` is deprecated in favor of `value`, says Google Chrome. So this could be `this.name + ':' + this.value`. [The Attr Interface](http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-637646024) – Thai Feb 03 '15 at 13:57
21

Because in IE7 elem.attributes lists all possible attributes, not only the present ones, we have to test the attribute value. This plugin works in all major browsers:

(function($) {
    $.fn.getAttributes = function () {
        var elem = this, 
            attr = {};

        if(elem && elem.length) $.each(elem.get(0).attributes, function(v,n) { 
            n = n.nodeName||n.name;
            v = elem.attr(n); // relay on $.fn.attr, it makes some filtering and checks
            if(v != undefined && v !== false) attr[n] = v
        })

        return attr
    }
})(jQuery);

Usage:

var attribs = $('#some_id').getAttributes();
HaNdTriX
  • 28,732
  • 11
  • 78
  • 85
DUzun
  • 1,693
  • 17
  • 15
  • 1
    Typo in this -- el.get(0) at line 6 should be elem.get(0). – Graham Charles Jun 26 '13 at 18:38
  • From my experience just now this is actually a bit more complex than this. At least in some cases. For example, will this include an attribute named 'dataFld' with value 'null' (string value) or would it exclude it? – Shahar 'Dawn' Or Jun 19 '14 at 13:55
  • It doesn't work with dynamically added properties, cause properties and attributes are not always in sync. – DUzun Oct 09 '14 at 15:27
18

Setter and Getter!

(function($) {
    // Attrs
    $.fn.attrs = function(attrs) {
        var t = $(this);
        if (attrs) {
            // Set attributes
            t.each(function(i, e) {
                var j = $(e);
                for (var attr in attrs) {
                    j.attr(attr, attrs[attr]);
                }
            });
            return t;
        } else {
            // Get attributes
            var a = {},
                r = t.get(0);
            if (r) {
                r = r.attributes;
                for (var i in r) {
                    var p = r[i];
                    if (typeof p.nodeValue !== 'undefined') a[p.nodeName] = p.nodeValue;
                }
            }
            return a;
        }
    };
})(jQuery);

Use:

// Setter
$('#element').attrs({
    'name' : 'newName',
    'id' : 'newId',
    'readonly': true
});

// Getter
var attrs = $('#element').attrs();
Eduardo Cuomo
  • 17,828
  • 6
  • 117
  • 94
  • 2
    Nice, I like this answer the best. Fits in perfectly well with `jQuery.attr`. – Scott Rippey Feb 12 '14 at 07:01
  • 1
    Two recommendations: Can you update to use "non-minified" variable names? And I see you're using `jQuery.attr` in the setter, but it would probably be beneficial to use it in the getter too. – Scott Rippey Feb 12 '14 at 07:03
  • Also, small thing - there shouldn't be a semicolon after your first for() statement. – jbyrd Aug 17 '15 at 16:32
13

There is a Better Answer Than This One

I recommend the answer by Tim Kindberg that uses getAttributeNames() and getAttribute(name), which MDN says "is a memory-efficient and performant alternative to accessing Element.attributes."

Below are my original and updated answers, which remain in case they offer some benefit.


Use Array.from() or Spread Operator ...

Update: Array.from() and Spread operator ... were added to ECMA-262 6th Edition in June 2015, which now has universal modern browser support.

See MDN › Array.from() & Spread syntax (...)

var elem  = document.querySelector('[name=test]'),
    attrs = elem.attributes;

console.log('Array.from(attrs)');
Array.from(attrs).forEach(({ name, value }) => {
    console.log(`    ${name}: ${value}`);
})

console.log('[...attrs]');
[...attrs].forEach(({ name, value }) => {
    console.log(`    ${name}: ${value}`);
})
<span name="test" message="test2">See console.</span>

Note: The following is the legacy answer. It will still work, but the newer Array.from() method is now preferred. This could now be considered a polyfill to support pre-ES2015 targets.

Use .slice to convert the attributes property to Array

The attributes property of DOM nodes is a NamedNodeMap, which is an Array-like object.

An Array-like object is an object which has a length property and whose property names are enumerated, but otherwise has its own methods and does not inherit from Array.prototype

The slice method can be used to convert Array-like objects to a new Array.

var elem  = document.querySelector('[name=test]'),
    attrs = elem.attributes;

console.log('Array.prototype.slice.call(attrs)');
Array.prototype.slice.call(attrs).forEach(
    function (cur) {
        console.log(cur.name + ': ' + cur.value);
    }
)
<span name="test" message="test2">See console.</span>
gfullam
  • 11,531
  • 5
  • 50
  • 64
9

Every answer here is missing the simplest solution using the getAttributeNames element method!

It retrieves the names of all the element's current attributes as a regular Array, that you can then reduce to a nice object of keys/values.

const getAllAttributes = el => el
  .getAttributeNames()
  .reduce((obj, name) => ({
    ...obj,
    [name]: el.getAttribute(name)
  }), {})

console.log(getAllAttributes(document.querySelector('div')))
<div title="hello" className="foo" data-foo="bar"></div>
Tim Kindberg
  • 3,605
  • 1
  • 25
  • 26
8

Very simple. You just need to loop over the attributes element and push their nodeValues into an array:

let att = document.getElementById('id');

let arr = Array();

for (let i = 0; i < att.attributes.length; i++) {
    arr.push(att.attributes[i].nodeValue);
}

If you want the name of the attribute you can replace 'nodeValue' for 'nodeName'.

let att = document.getElementById('id');

let arr = Array();

for (let i = 0; i < att.attributes.length; i++) {
    arr.push(att.attributes[i].nodeName);
}
Berg_Durden
  • 1,531
  • 4
  • 24
  • 46
5

Much more concise ways to do it:

Old way (IE9+):

var element = document.querySelector(/* … */);
[].slice.call(element.attributes).map(function (attr) { return attr.nodeName; });

ES6 way (Edge 12+):

[...document.querySelector(/* … */).attributes].map(attr => attr.nodeName);

Demo:

console.log(
  [...document.querySelector('img').attributes].map(attr => attr.nodeName)
);
/* Output console formatting */
.as-console-wrapper { position: absolute; top: 0; }
<img src="…" alt="…" height="…" width="…"/>
Przemek
  • 3,855
  • 2
  • 25
  • 33
3

This approach works well if you need to get all the attributes with name and value in objects returned in an array.

Example output:

[
    {
        name: 'message',
        value: 'test2'
    }
    ...
]

function getElementAttrs(el) {
  return [].slice.call(el.attributes).map((attr) => {
    return {
      name: attr.name,
      value: attr.value
    }
  });
}

var allAttrs = getElementAttrs(document.querySelector('span'));
console.log(allAttrs);
<span name="test" message="test2"></span>

If you want only an array of attribute names for that element, you can just map the results:

var onlyAttrNames = allAttrs.map(attr => attr.name);
console.log(onlyAttrNames); // ["name", "message"]
KevBot
  • 17,900
  • 5
  • 50
  • 68
3

Element.attributes returns a NamedNodeMap of attributes of that HTMLElement which is mildly a JavaScript Map. Hence supposing

<span id="mySpan" name="test" message="test2"></span>

you can create an object from the NamedNodeMap like below:

const el = document.querySelector('#mySpan')
const attrs = Object.fromEntries(Array.from(el.attributes).map(item => [item.name, item.value]))

and then access an individual attribute by the dot notation for object properties:

console.log(attrs.name) // "test"
console.log(attrs.messsage) // "test2"
shvahabi
  • 1,218
  • 10
  • 7
  • 1
    This feels like it would be slightly more performant than a similarly-functional approach of `Object.fromEntries(el.getAttributeNames().map(k => [k, el.getAttribute(k)]))`. Good usage of `Object.fromEntries()` – Phrogz Feb 20 '23 at 04:44
2

Roland Bouman's answer is the best, simple Vanilla way. I noticed some attempts at jQ plugs, but they just didn't seem "full" enough to me, so I made my own. The only setback so far has been inability to access dynamically added attrs without directly calling elm.attr('dynamicAttr'). However, this will return all natural attributes of a jQuery element object.

Plugin uses simple jQuery style calling:

$(elm).getAttrs();
// OR
$.getAttrs(elm);

You can also add a second string param for getting just one specific attr. This isn't really needed for one element selection, as jQuery already provides $(elm).attr('name'), however, my version of a plugin allows for multiple returns. So, for instance, a call like

$.getAttrs('*', 'class');

Will result in an array [] return of objects {}. Each object will look like:

{ class: 'classes names', elm: $(elm), index: i } // index is $(elm).index()

Plugin

;;(function($) {
    $.getAttrs || ($.extend({
        getAttrs: function() {
            var a = arguments,
                d, b;
            if (a.length)
                for (x in a) switch (typeof a[x]) {
                    case "object":
                        a[x] instanceof jQuery && (b = a[x]);
                        break;
                    case "string":
                        b ? d || (d = a[x]) : b = $(a[x])
                }
            if (b instanceof jQuery) {
                var e = [];
                if (1 == b.length) {
                    for (var f = 0, g = b[0].attributes, h = g.length; f < h; f++) a = g[f], e[a.name] = a.value;
                    b.data("attrList", e);
                    d && "all" != d && (e = b.attr(d))
                } else d && "all" != d ? b.each(function(a) {
                    a = {
                        elm: $(this),
                        index: $(this).index()
                    };
                    a[d] = $(this).attr(d);
                    e.push(a)
                }) : b.each(function(a) {
                    $elmRet = [];
                    for (var b = 0, d = this.attributes, f = d.length; b < f; b++) a = d[b], $elmRet[a.name] = a.value;
                    e.push({
                        elm: $(this),
                        index: $(this).index(),
                        attrs: $elmRet
                    });
                    $(this).data("attrList", e)
                });
                return e
            }
            return "Error: Cannot find Selector"
        }
    }), $.fn.extend({
        getAttrs: function() {
            var a = [$(this)];
            if (arguments.length)
                for (x in arguments) a.push(arguments[x]);
            return $.getAttrs.apply($, a)
        }
    }))
})(jQuery);

Complied

;;(function(c){c.getAttrs||(c.extend({getAttrs:function(){var a=arguments,d,b;if(a.length)for(x in a)switch(typeof a[x]){case "object":a[x]instanceof jQuery&&(b=a[x]);break;case "string":b?d||(d=a[x]):b=c(a[x])}if(b instanceof jQuery){if(1==b.length){for(var e=[],f=0,g=b[0].attributes,h=g.length;f<h;f++)a=g[f],e[a.name]=a.value;b.data("attrList",e);d&&"all"!=d&&(e=b.attr(d));for(x in e)e.length++}else e=[],d&&"all"!=d?b.each(function(a){a={elm:c(this),index:c(this).index()};a[d]=c(this).attr(d);e.push(a)}):b.each(function(a){$elmRet=[];for(var b=0,d=this.attributes,f=d.length;b<f;b++)a=d[b],$elmRet[a.name]=a.value;e.push({elm:c(this),index:c(this).index(),attrs:$elmRet});c(this).data("attrList",e);for(x in $elmRet)$elmRet.length++});return e}return"Error: Cannot find Selector"}}),c.fn.extend({getAttrs:function(){var a=[c(this)];if(arguments.length)for(x in arguments)a.push(arguments[x]);return c.getAttrs.apply(c,a)}}))})(jQuery);

jsFiddle

/*  BEGIN PLUGIN  */
;;(function($) {
 $.getAttrs || ($.extend({
  getAttrs: function() {
   var a = arguments,
    c, b;
   if (a.length)
    for (x in a) switch (typeof a[x]) {
     case "object":
      a[x] instanceof f && (b = a[x]);
      break;
     case "string":
      b ? c || (c = a[x]) : b = $(a[x])
    }
   if (b instanceof f) {
    if (1 == b.length) {
     for (var d = [], e = 0, g = b[0].attributes, h = g.length; e < h; e++) a = g[e], d[a.name] = a.value;
     b.data("attrList", d);
     c && "all" != c && (d = b.attr(c));
     for (x in d) d.length++
    } else d = [], c && "all" != c ? b.each(function(a) {
     a = {
      elm: $(this),
      index: $(this).index()
     };
     a[c] = $(this).attr(c);
     d.push(a)
    }) : b.each(function(a) {
     $elmRet = [];
     for (var b = 0, c = this.attributes, e = c.length; b < e; b++) a = c[b], $elmRet[a.name] = a.value;
     d.push({
      elm: $(this),
      index: $(this).index(),
      attrs: $elmRet
     });
     $(this).data("attrList", d);
     for (x in $elmRet) $elmRet.length++
    });
    return d
   }
   return "Error: Cannot find Selector"
  }
 }), $.fn.extend({
  getAttrs: function() {
   var a = [$(this)];
   if (arguments.length)
    for (x in arguments) a.push(arguments[x]);
   return $.getAttrs.apply($, a)
  }
 }))
})(jQuery);
/*  END PLUGIN  */
/*--------------------*/
$('#bob').attr('bob', 'bill');
console.log($('#bob'))
console.log(new Array(50).join(' -'));
console.log($('#bob').getAttrs('id'));
console.log(new Array(50).join(' -'));
console.log($.getAttrs('#bob'));
console.log(new Array(50).join(' -'));
console.log($.getAttrs('#bob', 'name'));
console.log(new Array(50).join(' -'));
console.log($.getAttrs('*', 'class'));
console.log(new Array(50).join(' -'));
console.log($.getAttrs('p'));
console.log(new Array(50).join(' -'));
console.log($('#bob').getAttrs('all'));
console.log($('*').getAttrs('all'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
All of below is just for stuff for plugin to test on. See developer console for more details.
<hr />
<div id="bob" class="wmd-button-bar"><ul id="wmd-button-row-27865269" class="wmd-button-row" style="display:none;">
<div class="post-text" itemprop="text">
<p>Roland Bouman's answer is the best, simple Vanilla way. I noticed some attempts at jQ plugs, but they just didn't seem "full" enough to me, so I made my own. The only setback so far has been inability to access dynamically added attrs without directly calling <code>elm.attr('dynamicAttr')</code>. However, this will return all natural attributes of a jQuery element object.</p>

<p>Plugin uses simple jQuery style calling:</p>

<pre class="default prettyprint prettyprinted"><code><span class="pln">$</span><span class="pun">(</span><span class="pln">elm</span><span class="pun">).</span><span class="pln">getAttrs</span><span class="pun">();</span><span class="pln">
</span><span class="com">// OR</span><span class="pln">
$</span><span class="pun">.</span><span class="pln">getAttrs</span><span class="pun">(</span><span class="pln">elm</span><span class="pun">);</span></code></pre>

<p>You can also add a second string param for getting just one specific attr. This isn't really needed for one element selection, as jQuery already provides <code>$(elm).attr('name')</code>, however, my version of a plugin allows for multiple returns. So, for instance, a call like</p>

<pre class="default prettyprint prettyprinted"><code><span class="pln">$</span><span class="pun">.</span><span class="pln">getAttrs</span><span class="pun">(</span><span class="str">'*'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'class'</span><span class="pun">);</span></code></pre>

<p>Will result in an array <code>[]</code> return of objects <code>{}</code>. Each object will look like:</p>

<pre class="default prettyprint prettyprinted"><code><span class="pun">{</span><span class="pln"> </span><span class="kwd">class</span><span class="pun">:</span><span class="pln"> </span><span class="str">'classes names'</span><span class="pun">,</span><span class="pln"> elm</span><span class="pun">:</span><span class="pln"> $</span><span class="pun">(</span><span class="pln">elm</span><span class="pun">),</span><span class="pln"> index</span><span class="pun">:</span><span class="pln"> i </span><span class="pun">}</span><span class="pln"> </span><span class="com">// index is $(elm).index()</span></code></pre>
    </div>
  </div>
Community
  • 1
  • 1
SpYk3HH
  • 22,272
  • 11
  • 70
  • 81
2

Imagine you've got an HTML element like below:

<a class="toc-item"
   href="/books/n/ukhta2333/s5/"
   id="book-link-29"
>
   Chapter 5. Conclusions and recommendations
</a>

One way you can get all attributes of it is to convert them into an array:

const el = document.getElementById("book-link-29")
const attrArray = Array.from(el.attributes)

// Now you can iterate all the attributes and do whatever you need.
const attributes = attrArray.reduce((attrs, attr) => {
    attrs !== '' && (attrs += ' ')
    attrs += `${attr.nodeName}="${attr.nodeValue}"`
    return attrs
}, '')
console.log(attributes)

And below is the string that what you'll get (from the example), which includes all attributes:

class="toc-item" href="/books/n/ukhta2333/s5/" id="book-link-29"
Yuci
  • 27,235
  • 10
  • 114
  • 113
1

Does this help?

This property returns all the attributes of an element into an array for you. Here is an example.

window.addEventListener('load', function() {
  var result = document.getElementById('result');
  var spanAttributes = document.getElementsByTagName('span')[0].attributes;
  for (var i = 0; i != spanAttributes.length; i++) {
    result.innerHTML += spanAttributes[i].value + ',';
  }
});
<span name="test" message="test2"></span>
<div id="result"></div>

To get the attributes of many elements and organize them, I suggest making an array of all the elements that you want to loop through and then create a sub array for all the attributes of each element looped through.

This is an example of a script that will loop through the collected elements and print out two attributes. This script assumes that there will always be two attributes but you can easily fix this with further mapping.

window.addEventListener('load',function(){
  /*
  collect all the elements you want the attributes
  for into the variable "elementsToTrack"
  */ 
  var elementsToTrack = $('body span, body div');
  //variable to store all attributes for each element
  var attributes = [];
  //gather all attributes of selected elements
  for(var i = 0; i != elementsToTrack.length; i++){
    var currentAttr = elementsToTrack[i].attributes;
    attributes.push(currentAttr);
  }
  
  //print out all the attrbute names and values
  var result = document.getElementById('result');
  for(var i = 0; i != attributes.length; i++){
    result.innerHTML += attributes[i][0].name + ', ' + attributes[i][0].value + ' | ' + attributes[i][1].name + ', ' + attributes[i][1].value +'<br>';  
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span name="test" message="test2"></span>
<span name="test" message="test2"></span>
<span name="test" message="test2"></span>
<span name="test" message="test2"></span>
<span name="test" message="test2"></span>
<span name="test" message="test2"></span>
<span name="test" message="test2"></span>
<div name="test" message="test2"></div>
<div name="test" message="test2"></div>
<div name="test" message="test2"></div>
<div name="test" message="test2"></div>
<div id="result"></div>
www139
  • 4,960
  • 3
  • 31
  • 56
1

Try something like this

    <div id=foo [href]="url" class (click)="alert('hello')" data-hello=world></div>

and then get all attributes

    const foo = document.getElementById('foo');
    // or if you have a jQuery object
    // const foo = $('#foo')[0];

    function getAttributes(el) {
        const attrObj = {};
        if(!el.hasAttributes()) return attrObj;
        for (const attr of el.attributes)
            attrObj[attr.name] = attr.value;
        return attrObj
    }

    // {"id":"foo","[href]":"url","class":"","(click)":"alert('hello')","data-hello":"world"}
    console.log(getAttributes(foo));

for array of attributes use

    // ["id","[href]","class","(click)","data-hello"]
    Object.keys(getAttributes(foo))
weroro
  • 1,690
  • 1
  • 11
  • 9
1

Attributes to Object conversion

*Requires: lodash

function getAttributes(element, parseJson=false){
    let results = {}
    for (let i = 0, n = element.attributes.length; i < n; i++){
        let key = element.attributes[i].nodeName.replace('-', '.')
        let value = element.attributes[i].nodeValue
        if(parseJson){
            try{
                if(_.isString(value))
                value = JSON.parse(value)
            } catch(e) {}
        }
        _.set(results, key, value)
    }
    return results
}

This will convert all html attributes to a nested object

Example HTML: <div custom-nested-path1="value1" custom-nested-path2="value2"></div>

Result: {custom:{nested:{path1:"value1",path2:"value2"}}}

If parseJson is set to true json values will be converted to objects

Dieter Gribnitz
  • 5,062
  • 2
  • 41
  • 38
0
Element.prototype.getA = function (a) {
        if (a) {
            return this.getAttribute(a);
        } else {
            var o = {};
            for(let a of this.attributes){
                o[a.name]=a.value;
            }
            return o;
        }
    }

having <div id="mydiv" a='1' b='2'>...</div> can use

mydiv.getA() // {id:"mydiv",a:'1',b:'2'}
bortunac
  • 4,642
  • 1
  • 32
  • 21
0
function getElementHTMLAttributes(elementId) {
    var element = document.getElementById(elementId);
    if (element != undefined) {
      var elementHTMLAttributes = {};
      for (var attr, i = 0, attrs = element.attributes, n = attrs.length; i < n; i++){
        attr = attrs[i];
        elementHTMLAttributes[attr.nodeName] = attr.nodeValue;
      }
    return elementHTMLAttributes;
    }
}
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 13 '22 at 12:16
0

Simply access element.attributes

// get-attr-names.js v1
function getAttrNames(element) {
    return [...element.attributes]
}

// get-attr-obj.js v1
function getAttrObj(element) {
    const attrsObj = {}
    const attrs = [...element.attributes]
    for (attr of attrs) {
        attrsObj[attr.name] = attr.value
    }
    return attrsObj
}
Luis Lobo
  • 489
  • 4
  • 7
-8

In javascript:

var attributes;
var spans = document.getElementsByTagName("span");
for(var s in spans){
  if (spans[s].getAttribute('name') === 'test') {
     attributes = spans[s].attributes;
     break;
  }
}

To access the attributes names and values:

attributes[0].nodeName
attributes[0].nodeValue