Reputation: 2583
How can I clone an element and insert it 5 times right after each other? This of course is the base statement:
$('.col').clone().insertAfter('.col');
Here's what I need to get:
<div class="col" id="original"> </div>
<div class="col"> </div>
<div class="col"> </div>
<div class="col"> </div>
<div class="col"> </div>
<div class="col"> </div>
The selector doesn't need to be using an unique id, it can also be a class selector.
I could just repeat the base statement four times but there must be a more elegant way?
Upvotes: 12
Views: 27616
Reputation: 5368
You might want to clone fields when the document is ready against cloning any changes made by client. This is mostly active issue with inputs. Then you should:
Clone the element on document ready: var elementClone = $('#element').clone()
on click clone the cloned element again and add elementClone.clone().insertAfter(element)
Upvotes: 0
Reputation: 27
$(document).ready(function() {
var e = $('.col');
for (var i = 0; i < 5; i++) {
e.clone().insertAfter(e);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col">clone me...</div>
`
Upvotes: 1
Reputation: 1
Javascript Array has a fill function:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill
So you could write something like this
$(
new Array(copies).fill(function () {
return $(this).clone();
}.bind(el))
.map(function (el) {
return el();
})
).map(function() { return this.toArray(); }); //Turn into jQuery
and if you wanted it as a jQuery function that you could re-use you could write something like this
$.fn.multiply = function(amount) {
var cloneFunction = (function() {
return $(this).clone();
}).bind(this);
return $(
new Array(amount).fill(cloneFunction).map(function(el) {
return el();
});
).map(function() { return this.toArray(); }); //Turn into jQuery
}
this gives you the flexibility to separate the function call of clone from being evaluated only when you need it. So if you wanted to you could split up the call and evaluate later.
meaning this is the promise (it returns functions with bound context to this that when called will clone)
new Array(amount).fill(cloneFunction);
and this is the resolution
.map(function(el) { return el(); })
and this little last bit handles the fact that I created an array of jQuery objects but really I want a jQuery collection
.map(function() { return this.toArray(); }); //Turn into jQuery
but at any rate your final solution would look something like this, if you go this route.
$(el).multiply(amount).insertAfter(anotherEl);
cheers
Upvotes: 0
Reputation: 38253
I wrote a jQuery plug-in:
$.fn.multiply = function(numCopies) {
var newElements = this.clone();
for(var i = 1; i < numCopies; i++)
{
newElements = newElements.add(this.clone());
}
return newElements;
};
This code snippet builds the elements as a jQuery set, instead of adding to the DOM multiple times which can be slow.
Usage:
var li = $('<li>Test</li>');
$('ul').append(li.multiply(4));
So, for your example:
$('.col').multiply(5).insertAfter('.col');
Upvotes: 1
Reputation: 700630
Use a loop, like this:
$(document).ready(function() {
var e = $('.col');
for (var i = 0; i < 5; i++) {
e.clone().insertAfter(e);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col">clone me...</div>
Put the element in a variable before the loop, otherwise you will run into problems when you get several elements with the same id were your selector to be based on an id (e.g. $("#col1")
).
If your selector is using a class, it doesn't cause the same conflicts as duplicate id's, but you should still put the element in a variable before the loop, otherwise you will end up with a lot more elements than you want.
Upvotes: 27
Reputation: 3677
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('.col').each(function(){
$(this).clone().insertAfter(this);
});
});
</script>
<div class="col">First div </div>
<div class="col">2nd </div>
<div class="col">3rd </div>
<div class="col">4th </div>
<div class="col">5th </div>
is this you looking for?
Upvotes: 1