Get all Attributes from a HTML element with Javascript/jQuery
JavascriptJqueryAttributesParsingJavascript Problem Overview
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.
Javascript Solutions
Solution 1 - Javascript
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);
}
Solution 2 - Javascript
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);
Solution 3 - Javascript
Simple:
var element = $("span[name='test']");
$(element[0].attributes).each(function() {
console.log(this.nodeName+':'+this.nodeValue);});
Solution 4 - Javascript
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();
Solution 5 - Javascript
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();
Solution 6 - Javascript
A Better Answer
I now 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
."
Array.from()
or Spread Operator ...
Use 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.
.slice
to convert the attributes
property to Array
Use 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>
Solution 7 - Javascript
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>
Solution 8 - Javascript
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);
}
Solution 9 - Javascript
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);
document.querySelector()
returns the first Element within the document that matches the specified selector.Element.attributes
returns a NamedNodeMap object containing the assigned attributes of the corresponding HTML element.[].map()
creates a new array with the results of calling a provided function on every element in the calling array.
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="…"/>
Solution 10 - Javascript
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"]
Solution 11 - Javascript
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>
Solution 12 - Javascript
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"
Solution 13 - Javascript
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>
Solution 14 - Javascript
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))
Solution 15 - Javascript
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
Solution 16 - Javascript
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'}
Solution 17 - Javascript
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;
}
}
Solution 18 - Javascript
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"
Solution 19 - Javascript
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