0

I am creating div elements dynamically, on clicking on duplicate button. the divs are draggable and resizable horizontally. Everytime I create a new div, by clicking on duplicate, the new divs are draggable. But with resizable an unusual behavior is observed. The behavior is all the divs uptil second last div gets the resizable feature, but the most recent(last) doesn't get resizable. I referred the solution given here,

Apply jQueryUI Resizable widget to dynamically created elements. They are using :last and after() methods.

I am not getting how I use it in my case.

Following is my code,

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css">
    <script src="https://code.jquery.com/jquery-3.3.1.js"
  integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
  crossorigin="anonymous"></script>
    <script
    src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"
    integrity="sha256-0YPKAwZP7Mp3ALMRVB2i8GXeEndvCq3eSl/WsAl1Ryk="
    crossorigin="anonymous"></script>
    <script type="text/javascript">
        var bar_id = 1;
        $(document).ready(function(){
            $(".action").draggable({cursor:"move",containment:"#limits"});
            $(".action").resizable({handles:"e,w",maxWidth:1300,maxHeight:46,minWidth:100,minHeight:46});

            $(document).on('click',".duplicate_btn",function(){
                bar_id += 1;                
                var duplicate_bar = $(this).parent().clone();
                duplicate_bar.attr("id","action_"+bar_id);
                duplicate_bar.find(".duplicate_btn").attr("id","duplicate_btn_"+bar_id);                         
                $("#limits").append(duplicate_bar);
                $(".action").draggable({cursor:"move",containment:"#limits"});                    
                $(".action").resizable({handles:"e,w",maxWidth:1300,maxHeight:46,minWidth:100,minHeight:46});
            });

        });
    </script>
    <style type="text/css">
        .action{
            background-color: #aaa;
            height: 46px;
            width: 200px;
            float:left;
            border:2px solid black;
            position:absolute;
            /*for items inside div*/
            display: flex;
            align-items: center;
            justify-content: center;
        }
        #limits{
            background-color: lavender;
            height: 50px;
            width: 1300px;
        }           
    </style>
</head>
<body>
<div id="limits">
    <div id="action_1" class="action">
        <button id="duplicate_btn_1" class="duplicate_btn">Duplicate</button>
    </div>
</div>
</body>
</html>

Please help to get the way out. Thank You in advance!.

Vrajesh Doshi
  • 744
  • 2
  • 8
  • 27
  • @ Rory McCrossan On applying same on draggable and resizable, what you said. draggable is working normal as previous, but resizable is now working only for 1st div. – Vrajesh Doshi Feb 06 '19 at 11:14

1 Answers1

1

If you check the DOM inspector after you clone() the element you'll see that it has also copied the .ui-resizable-handle elements which were added to the original element when draggable() and resizable() were called on it.

This is the cause of the issue. You need to remove those elements before you define draggable and resizable on the new element. Also note that you can call those methods on the new instance directly instead of redefining the plugin on all instances of .action. Try this:

var bar_id = 1;
$(document).ready(function() {
  defineDragResize($('.action'));

  $(document).on('click', ".duplicate_btn", function() {
    bar_id += 1;
    var $duplicate_bar = $(this).parent().clone().appendTo('#limits')
    $duplicate_bar.find('div').remove();
    defineDragResize($duplicate_bar);
  });

  function defineDragResize($el) {
    $el.draggable({
      cursor: "move",
      containment: "#limits"
    }).resizable({
      handles: "e,w",
      maxWidth: 1300,
      maxHeight: 46,
      minWidth: 100,
      minHeight: 46
    });
  }
});
.action {
  background-color: #aaa;
  height: 46px;
  width: 200px;
  float: left;
  border: 2px solid black;
  position: absolute;
  /*for items inside div*/
  display: flex;
  align-items: center;
  justify-content: center;
}

#limits {
  background-color: lavender;
  height: 50px;
  width: 1300px;
}

#limits {
  background-color: lavender;
  height: 50px;
  width: 1300px;
}
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js" integrity="sha256-0YPKAwZP7Mp3ALMRVB2i8GXeEndvCq3eSl/WsAl1Ryk=" crossorigin="anonymous"></script>

<div id="limits">
  <div class="action">
    <button class="duplicate_btn">Duplicate</button>
  </div>
</div>

One thing to note is that I removed the dynamic id logic. This is an anti-pattern and should not be used. Use common classes and DOM traversal instead.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • When I am running your code snippet in the stackoverflow itself, it is showing me a good behaviour of displaying clone next to the last div, but when I copied the code in machine it is showing me cloned div overlaped on the current div, which I manually drag. Can you tell what could be the reason. – Vrajesh Doshi Feb 06 '19 at 11:40
  • Without seeing the issue it's hard to diagnose. I would assume there's a difference in the CSS you're using. – Rory McCrossan Feb 06 '19 at 11:40
  • – Vrajesh Doshi Feb 06 '19 at 11:42
  • its the same CSS I copied from your code, which I pasted above – Vrajesh Doshi Feb 06 '19 at 11:43
  • I updated the answer with that CSS and it works fine. If you can't solve this issue I'd suggest starting a new question but be sure to include all the code which recreates it. – Rory McCrossan Feb 06 '19 at 11:44
  • I have appended the code at the bottom of this same question, can you tell the reason going through it. A big thanks in advance. – Vrajesh Doshi Feb 06 '19 at 11:51
  • Sorry I don't have time right now. This is why I suggested starting a new question - as I'm sure other people who can help you will then see it. – Rory McCrossan Feb 06 '19 at 11:52