85

How do I copy the attributes of one element to another element?

HTML

<select id="foo" class="bar baz" style="display:block" width="100" data-foo="bar">...</select> <div>No attributes yet</div> 

JavaScript

var $div = $('div'); var $select = $('select'); //now copy the attributes from $select to $div 
5
  • 3
    Are you sure you want to copy id? Commented Jul 19, 2011 at 20:04
  • If it is going to copy the id attribute you will have a duplicated id. Commented Jul 19, 2011 at 20:04
  • Perhaps you could explain why you need to this? There's likely a better solution. Commented Jul 19, 2011 at 20:08
  • Don't worry, I will either not copy the ID attrbute or remove the duplicate ID attribute. Commented Jul 19, 2011 at 20:09
  • Because I don't want to forget an attribute if I copy each one by hand. Also, I didn't know how to do this, so I wanted to ask so I could learn how to do it in the future. Commented Jul 19, 2011 at 20:10

12 Answers 12

91

You can use the native Node#attributes property: http://jsfiddle.net/SDWHN/16/.

var $select = $("select"); var $div = $("div"); var attributes = $select.prop("attributes"); // loop through <select> attributes and apply them on <div> $.each(attributes, function() { $div.attr(this.name, this.value); }); alert($div.data("foo")); 
Sign up to request clarification or add additional context in comments.

4 Comments

As a note: attributes array is far from compatible. Yes, it is core, but IE in earlier version treats 'core' properties as it pleases. I use "hackish", but as paradox more compliant way taken from forum.jquery.com/topic/… - make node a string representation, change it's tag with regexp and convert back to node. Then I can re-attach data and events. IE version threw errors on copying some of the attributes (ex 'implementation' attribute - did you know it's attached to all tags?)
Kudos for prepending your variables with '$' when they contain references to jQuery objects. I started this trend in my current company... it makes it MUCH easier to read the code quickly!
Would like to ask a side question related to this. I tried $something.prop('attributes') and it give an array with attributes. One of them is crossorigin for an image. I tried $item.prop('crossorigin') which is undefined but if I try $item.prop('src'), it give result. And then I tried $item.attr('crossorigin') which give the value. What is the difference of .attr() and .prop()? Why is the above situation somewhat different? Thanks in advance.
@simongcc .prop gets a property from the underlying native Node object representing the DOM of the element. .attr gets the value of a HTML attribute as defined programmatically or via markup.
38

ES6 syntax one liner:

function cloneAttributes(target, source) { [...source.attributes].forEach( attr => { target.setAttribute(attr.nodeName ,attr.nodeValue) }) } 

And as noted in the first comment - you would probably don't want to copy the source id attribute... so this one will save it as a 'data-id' attribute in case you need a reference.

function cloneAttributes(target, source) { [...source.attributes].forEach( attr => { target.setAttribute(attr.nodeName === "id" ? 'data-id' : attr.nodeName ,attr.nodeValue) }) } 

4 Comments

best answer so far. It's 2020.
This is a better solution than the accepted answer. It's clean and can easily be used interchangeably between vanilla JS and jQuery.
nodeName, nodeValue are deprecated now developer.mozilla.org/ru/docs/Web/API/Attr
What I did was use attr.name and attr.value instead of attr.nodeName and attr.nodeValue respectively. It still works as expected.
14

Pretty Simple

function cloneAttributes(element, sourceNode) { let attr; let attributes = Array.prototype.slice.call(sourceNode.attributes); while(attr = attributes.pop()) { element.setAttribute(attr.nodeName, attr.nodeValue); } } 

3 Comments

Also note that this method does not copy any unnecessary primitive types. It only clones each attribute.
Is there a reason why you use Array#slice and while instead of just Array#forEach?
Probably for dead browsers compatibility.
11

A working solution on jsfiddle

EDIT

Updated jsfiddler

Javascript

$(function(){ var destination = $('#adiv').eq(0); var source = $('#bdiv')[0]; for (i = 0; i < source.attributes.length; i++) { var a = source.attributes[i]; destination.attr(a.name, a.value); } }); 

HTML

<div id="adiv" class="aclass">A class</div> <div id="bdiv" class="bclass">B class</div> 

That's copying #bdiv attributes to #adiv.

3 Comments

You should post at least the important part of your code here, if for no other reason than if jsfiddle ever disappears your answer remains.
@kingjiv, Thank's for advising.
This seems to have a problem in IE (8) where it finds far too many properties (100+) and jQuery throws a member not found exception when trying to set the attribute.
3

We could also try extending the jQuery prototype ($.fn) object to provide a new method that can be chained to the jQuery() function.

Here's an extension of @pimvdb's solution to provide a function that copies all attributes

The usage would be like so:

 $(destinationElement).copyAllAttributes(sourceElement); 

The extension function can be defined like so:

(function ($) { // Define the function here $.fn.copyAllAttributes = function(sourceElement) { // 'that' contains a pointer to the destination element var that = this; // Place holder for all attributes var allAttributes = ($(sourceElement) && $(sourceElement).length > 0) ? $(sourceElement).prop("attributes") : null; // Iterate through attributes and add if (allAttributes && $(that) && $(that).length == 1) { $.each(allAttributes, function() { // Ensure that class names are not copied but rather added if (this.name == "class") { $(that).addClass(this.value); } else { that.attr(this.name, this.value); } }); } return that; }; })(jQuery); 

An Example is available at http://jsfiddle.net/roeburg/Z8x8x/

Hope this helps.

1 Comment

Your code has unnecessary duplicate jQuery wrappers/initializations. See my changes: jsfiddle.net/5eLdcya6
3

You can try this:

function copyAttributes(from, to) { $($(from)[0].attributes). each(function(){$(to).attr(this.nodeName, this.nodeValue);}); return $(to); }; 

The return statement lets you write things like:

copyAttributes(some_element, $('<div></div>')).append(...) ... 

Hope this helps.

Comments

2

A non-jquery solution:

function copy(element){ var clone = document.createElement(element.nodeName); for(key in element){ clone.setAttribute(key,element[key]); } return clone; } 

It copies methods and other stuff you probably don't need, but hopefully you don't mind. This code is small and simple.

Comments

2

I'm facing same problem and after invested lots of time and effort i am creating thisclone textarea into editable div with same attribute

select.getAttributeNames().forEach(attrName => { $(div).attr(attrName, inputData.getAttribute(attrName)); }); 

Comments

1

A very straight to the point solution would be make something like this:

const _$ = domQuery => document.querySelector(domQuery) let div1 = _$('#div-1') let div2 = _$('#div-2') for(attr of div1.attributes) { div2.setAttribute(attr.name, attr.value); }
.my-div { height: 100px; width: 100px; }
<h1>div-1</h1> <div atribute-test="test" class="my-div" style="background: red" id="div-1"></div> <h1>div-2</h1> <div id="div-2"></div>

Comments

0

Since Firefox 22, Node.attributes is no longer supported (not implemented by other browsers and removed from the spec). It is only supported on Element (Element.attributes).

1 Comment

This doesn't matter at all for OP, he doesn't talk about text or other nodes.
-1

Javascript solution

Copy the attributes of old element to the new element

const $oldElem = document.querySelector('.old') const $newElem = document.createElement('div') Array.from($oldElem.attributes).map(a => { $newElem.setAttribute(a.name, a.value) }) 

Replace the old element with the new element, if required

$oldElem.parentNode.replaceChild($newElem, $oldElem) 

Comments

-2
$("div").addClass($('#foo').attr('class')); 

2 Comments

my mistake, i thought you wanted to copy the css.
Although it was a mistake, it's exactly what I was googling for. So, thanks! ;)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.