Get all Attributes from a HTML element with Javascript/jQuery
Asked Answered
C

20

193

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.

Chimp answered 12/1, 2010 at 12:5 Comment(0)
S
250

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);
}
Spireme answered 12/1, 2010 at 12:17 Comment(6)
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?Chimp
You can use getElementById - var el = document.getElementById($(myObj).attr("id"));Parceling
You can get the DOM object from a jQuery object via the get method...e.g.: var obj = $('#example').get(0);Nanceenancey
@Chimp - could you use e.g. var atts = $(myObject)[0].attributes; ?Doralin
Warning: in IE this gets not only specified, but all possible attributesAridatha
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).Cosentino
H
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);
Hummer answered 12/3, 2011 at 13:34 Comment(2)
FYI: This only exposes the first element of the selector.Echoism
I tested and it works with dynamically added attributes (chrome)Altheta
A
60

Simple:

var element = $("span[name='test']");
$(element[0].attributes).each(function() {
console.log(this.nodeName+':'+this.nodeValue);});
Aleksandrovsk answered 20/7, 2012 at 10:4 Comment(1)
Attr.nodeValue is deprecated in favor of value, says Google Chrome. So this could be this.name + ':' + this.value. The Attr InterfaceArgol
W
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();
Willin answered 5/6, 2013 at 9:6 Comment(3)
Typo in this -- el.get(0) at line 6 should be elem.get(0).Debutant
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?Debenture
It doesn't work with dynamically added properties, cause properties and attributes are not always in sync.Willin
C
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();
Capetian answered 26/7, 2013 at 19:26 Comment(3)
Nice, I like this answer the best. Fits in perfectly well with jQuery.attr.Mettle
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.Mettle
Also, small thing - there shouldn't be a semicolon after your first for() statement.Gorky
P
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>
Pesach answered 27/5, 2015 at 14:4 Comment(5)
It will return array of objects and not of attribute names as strings, thoughRobinett
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.Pesach
OK, makes senseRobinett
While iterating over the items in attrs, you can access the name of the attribute with the name property on the item.Botnick
[...elem.attributes]Feinberg
N
10

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>
Nitrite answered 7/2, 2019 at 18:0 Comment(1)
Note: it's not supported on <= IE 11Nitrite
M
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);
}
Mamie answered 23/10, 2019 at 13:34 Comment(0)
R
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="…"/>
Robinett answered 10/6, 2017 at 11:7 Comment(0)
A
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"
Anele answered 15/3, 2022 at 12:43 Comment(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()Graben
N
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"]
Neomaneomah answered 26/5, 2016 at 22:6 Comment(0)
A
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>
Alverta answered 9/1, 2015 at 16:47 Comment(0)
C
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"
Combustible answered 9/8, 2019 at 13:59 Comment(0)
N
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>
Newland answered 22/11, 2015 at 19:55 Comment(0)
A
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))
Anastase answered 15/2, 2019 at 10:29 Comment(0)
D
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

Dayak answered 16/4, 2020 at 7:57 Comment(0)
H
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'}
Hera answered 23/4, 2019 at 14:28 Comment(0)
C
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;
    }
}
Cleave answered 13/3, 2022 at 12:7 Comment(1)
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.Towboat
C
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
}
Columbia answered 9/12, 2022 at 19:48 Comment(0)
T
-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
Thoughtful answered 12/1, 2010 at 12:23 Comment(1)
Going thru all span elements would be too slowRubbico

© 2022 - 2024 — McMap. All rights reserved.