Reputation: 674
I have a div that I want to be cloned based on user input value. It works fine on page load with default value, but when the value is changed, it gets multiplied. For example, the default input value is 3 and on page load, it clones the existing div twice making the 3 divs, but when I increase the value to 4, it shows 12. Here is the HTML:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="cta-num-select">Show Items: </lebel><input id="cta-num-select" name="cta-num-select" type="text" value="3" size="2">
<div class="cta-block">
<div class="cta-block-item-wrap cta-icon-image">
<label for="item-chooser">FA Icon/Image: </label><select class="item-chooser" name="item-chooser"><option value="fontawesome">FontAwesome Icon</option><option value="image">Image</option></select>
</div>
<div class="cta-block-item-wrap cta-option cta-option-image">
<label for="block-image">Upload Image: </label><input name="block-image" class="block-image" type="text" value=""><input type="button" class="cta-insert-image button button-primary button-large" value="Upload">
</div>
<div class="cta-block-item-wrap cta-option cta-option-fontawesome">
<label for="fa-icon-class">Choose FA Icon: </label><input type="text" name="fa-icon-class" class="fa-icon-class" value="">
</div>
</div>
And, the jQuery:
$('#cta-num-select').on('change', function(){
var noi = $(this).val();
var e = $('.cta-block');
e.not(':first').remove();
//var present = e.length;
for (var i = 0; i < (noi -1); i++) {
e.clone().insertAfter(e);
}
}).trigger('change');
$('.item-chooser').on('change', function() {
var $this=$(this),
$container=$this.closest('.cta-block'),
option = $this.val();
$container.find('.cta-option').slideUp();
$container.find('.cta-option-'+option).stop(true).slideDown();
}).trigger('change');
I made a Fiddle for better demonstrating the issue I am facing. Please help
Upvotes: 0
Views: 1511
Reputation: 388316
It is because even though you are removing all clones except the first one from the dom, e
will still have all the elements.
You should clone only the first element
$('#cta-num-select').on('change', function () {
var noi = $(this).val();
var e = $('.cta-block');
e.not(':first').remove();
//var present = e.length;
for (var i = 0; i < (noi - 1); i++) {
e.first().clone().insertAfter(e);
}
}).trigger('change');
Instead of removing and adding all elements, I might use a slightly different implementation like
$('#cta-num-select').on('change', function() {
var noi = +$(this).val() || 0;
noi = noi < 1 ? 1 : noi;
var e = $('.cta-block'),
$first = e.first();
e.slice(noi).remove();
for (var i = e.length; i < noi; i++) {
$first.clone().insertAfter('.cta-block:last');
}
}).trigger('change');
$('.item-chooser').on('change', function() {
var $this = $(this),
$container = $this.closest('.cta-block'),
option = $this.val();
$container.find('.cta-option').slideUp();
$container.find('.cta-option-' + option).stop(true).slideDown();
}).trigger('change');
.cta-block-item-wrap {
border-bottom: 1px solid #eeeeee;
padding: 10px 0;
}
.cta-image-upload,
.cta-fa-icon {
display: none;
}
.cta-block-item-wrap > label {
font-size: 12px;
font-weight: bold;
margin: 0 50px 0 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<label for="cta-num-select">Show Items:</label>
<input id="cta-num-select" name="cta-num-select" type="text" value="3" size="2">
<div class="cta-block">
<div class="cta-block-item-wrap cta-icon-image">
<label for="item-chooser">FA Icon/Image:</label>
<select class="item-chooser" name="item-chooser">
<option value="fontawesome">FontAwesome Icon</option>
<option value="image">Image</option>
</select>
</div>
<div class="cta-block-item-wrap cta-option cta-option-image">
<label for="block-image">Upload Image:</label>
<input name="block-image" class="block-image" type="text" value="">
<input type="button" class="cta-insert-image button button-primary button-large" value="Upload">
</div>
<div class="cta-block-item-wrap cta-option cta-option-fontawesome">
<label for="fa-icon-class">Choose FA Icon:</label>
<input type="text" name="fa-icon-class" class="fa-icon-class" value="">
</div>
</div>
Upvotes: 3
Reputation: 93
You may change like this hold a copy of first div like var e = $('.cta-block').first(); then remove all element which are after first element: $('.cta-block').not(':first').remove();
Upvotes: 0
Reputation: 476
After first load when you select $('.cta-block')
, it results in an array of divs with class .cta-block
which is 3 in this case and hence the loop runs 3 multiplied by 4(the input value) i.e 12 times. You need to make sure that length of element e
should not be greater than 1.
Here is the fiddle with correction http://jsfiddle.net/hnco3Lfq/
Upvotes: 0
Reputation: 40639
Currently, you are cloning all elements and inserting
var e = $('.cta-block'); // getting all cta-block elements
... and
e.clone().insertAfter(e); //apending all elements in loop
Now, You should get the first element which should be cloned and remove all other elements like,
var e = $('.cta-block:first'); // get the first element only
$('.cta-block:gt(0)').remove(); // remove all except first
Upvotes: 0