Search code examples
jqueryscopecloneprepend

Can't Remove a Cloned Element in jQuery


I've cloned an element in jQuery and now want to remove this when I click on the 'x' of the cloned element.

There is a codepen here: http://codepen.io/emilychews/pen/YZGxWZ

I can't work out if the reason it isn't working is because I need to return the variable $myClone outside the function (which i've tried), or if I need everything to happen inside the main function with a nested function?

For some reason jQuery isn't recognising either the cloned element when I click on the prepended 'x' to remove it, or the prepended 'x' itself.

$(document).ready(function() {

  $('.holder').click(function() {
    var $myClone = $(this).clone()
      .appendTo(this)
      .addClass('cloned')
      .css({
        position: 'absolute',
        background: 'blue',
        top: 0,
        'z-index': 10,
        left: 0
      });

    $($myClone).prepend('<div class="closeX">X</div>');

    $('.closeX').click(function() {
      $($myClone).remove();
    });

  });

});
.wrapper {
  width: 100%;
  height: 100%;
}

.holder {
  width: 20vw;
  height: 100px;
  background: red;
  position: relative;
  margin-bottom: 5px;
  display: inline-block;
  transition: all .25s ease-out;
  z-index: 0;
  transform-origin: top left;
}


/*CSS for the prepended 'x' that shows on cloned element*/

.closeX {
  position: absolute;
  background: yellow;
  top: 5px;
  right: 5px;
  width: 25px;
  height: 25px;
  line-height: 25px;
  text-align: center;
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="wrapper">
  <div class="holder image1">Image 1</div>
  <div class="holder image2">Image 2</div>
  <div class="holder image3">Image 3</div>
  <div class="holder image4">Image 4</div>
  <div class="holder image5">Image 5</div>
</div>


Solution

  • You have several issues.

    1. you clone for every click on div AND X
    2. you need to only remove the parent of the clicked div
    3. you need to delegate the click and have it outside the click handler

    $(function() {
    
      $('.holder').on("click",function() {
        if ($(this).find(".cloned").length == 0) { // no cloned already
          var $myClone = $(this).clone()
            .appendTo(this)
            .addClass('cloned')
            .css({
              position: 'absolute',
              background: 'blue',
              top: 0,
              'z-index': 10,
              left: 0
            });
    
          $myClone.prepend('<div class="closeX">X</div>');
        }
    
      });
      $(".wrapper").on("click", ".closeX", function(e) {
        e.stopPropagation(); // this stops the click on the holder
        $(this).closest("div.cloned").remove();
      });
    });
    .wrapper {
      width: 100%;
      height: 100%;
    }
    
    .holder {
      width: 20vw;
      height: 100px;
      background: red;
      position: relative;
      margin-bottom: 5px;
      display: inline-block;
      transition: all .25s ease-out;
      z-index: 0;
      transform-origin: top left;
    }
    
    
    /*CSS for the prepended 'x' that shows on cloned element*/
    
    .closeX {
      position: absolute;
      background: yellow;
      top: 5px;
      right: 5px;
      width: 25px;
      height: 25px;
      line-height: 25px;
      text-align: center;
      cursor: pointer;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <div class="wrapper">
      <div class="holder image1">Image 1</div>
      <div class="holder image2">Image 2</div>
      <div class="holder image3">Image 3</div>
      <div class="holder image4">Image 4</div>
      <div class="holder image5">Image 5</div>
    </div>