Abhik
Abhik

Reputation: 674

Clone a div based on input value

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

Answers (4)

Arun P Johny
Arun P Johny

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

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

Araknid
Araknid

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

Rohan Kumar
Rohan Kumar

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

Live Demo

Upvotes: 0

Related Questions