197

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.

0

20 Answers 20

257

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

6 Comments

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?
You can use getElementById - var el = document.getElementById($(myObj).attr("id"));
You can get the DOM object from a jQuery object via the get method...e.g.: var obj = $('#example').get(0);
@k0ni - could you use e.g. var atts = $(myObject)[0].attributes; ?
Warning: in IE this gets not only specified, but all possible attributes
|
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);

3 Comments

FYI: This only exposes the first element of the selector.
I tested and it works with dynamically added attributes (chrome)
@BrettVeenstra I created a plugin that handles multiple inputs.
61

Simple:

var element = $("span[name='test']");
$(element[0].attributes).each(function() {
console.log(this.nodeName+':'+this.nodeValue);});

1 Comment

Attr.nodeValue is deprecated in favor of value, says Google Chrome. So this could be this.name + ':' + this.value. The Attr Interface
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();

3 Comments

Typo in this -- el.get(0) at line 6 should be elem.get(0).
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?
It doesn't work with dynamically added properties, cause properties and attributes are not always in sync.
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();

3 Comments

Nice, I like this answer the best. Fits in perfectly well with jQuery.attr.
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.
Also, small thing - there shouldn't be a semicolon after your first for() statement.
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>

5 Comments

It will return array of objects and not of attribute names as strings, though
The OP didn't specify an array of names as strings: "I want to put all attributes in a Html element into an array." This does that.
OK, makes sense
While iterating over the items in attrs, you can access the name of the attribute with the name property on the item.
[...elem.attributes]
12

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>

1 Comment

Note: it's not supported on <= IE 11
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);
}

Comments

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="…"/>

Comments

4

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"

1 Comment

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()
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"]

Comments

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>

Comments

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"

Comments

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>

Comments

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))

Comments

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

Comments

1
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;
    }
}

1 Comment

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.
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'}

Comments

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
}

Comments

-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

1 Comment

Going thru all span elements would be too slow

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.