jqueryjquery-uijquery-ui-draggablejquery-ui-droppable

jQuery UI (Droppable) : Draggable element not placed at mouse pointer if droppable has css position relative / absolute


I am using jquery ui drag and drop.

If droppable div (#dropContainer) has css position as relative / absolute / fixed, dropped element is not placed at my mouse pointer.

<div id="dropContainer" style="position:relative;"></div>

If I remove the position for droppable div, it is working as expected. But need to use the position for some obvious reasons

enter image description here

draggableInputNo = 0;

var buttonElement = '<div class="button" style="width:200px;">Button</div>'
var textElement = '<div class="text">Text Element</div>'

$(function() {
  $("#dropContainer").droppable({
    drop: function(event, ui) {
      $element = ui.helper.clone();
      $element.resizable();
      $element.draggable();
      $element.selectable();

      if (ui.draggable.hasClass('draggableInput text')) {
        draggableInputNo++;
        $element.attr("id", 'draggableInput' + draggableInputNo);
        $element.appendTo(this);
        $element.append(textElement);
      }
      else if (ui.draggable.hasClass('draggableInput button')) {
        draggableInputNo++;
        $element.attr("id", 'draggableInput' + draggableInputNo);
        $element.appendTo(this);
        $element.append(buttonElement);
      }
    }
  });

  $(".draggableInput").draggable({
    //containment: '#rpWebPushPopupContainer',
    cursor: 'move',
    helper: draggableInputHelper,
  });

});

function draggableInputHelper(event) {
  return '<div id="draggableInput' + draggableInputNo + '" class="draggableInputHelper resizable" ></div>'
}
.draggableInput {
  width: 50px;
  height: 30px;
  padding: 1em;
  float: left;
  margin: 10px 10px 10px 0;
  background-color: #9933ff;
  border-radius: 10px;
  border: 1px solid #9933ff;
}

.draggableInputHelper {
  width: 100px;
  height: 30px;
  padding: 0.5em;
  margin: 10px 10px 10px 0;
  background-color: #006699;
  border-radius: 10px;
  border: 1px solid #006699;
  color:#ffffff;
}

#dropContainer {
  width: 300px;
  height: 200px;
  padding: 0.5em;
  margin: 10px;
  float: left;
  border: 1px solid #867979;
  border-radius: 4px;
  background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.9.1/jquery-ui.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.9.1/themes/base/jquery-ui.min.css" />

<div class="draggableInput text">Text</div>
<div class="draggableInput button">Button</div>

<div id="dropContainer" style="position:relative;"></div>


Solution

  • When you droppable inside a div that is relative, element enclosed within droppable gets the offset position of the parent unnecessarily added to it. So remove the extra offset at the drop call back function.

    Adjust your position like below.

    var parent = $('#dropContainer.ui-droppable');
    var leftAdjust = $element.position().left - parent.offset().left;
    var topAdjust = $element.position().top - parent.offset().top;
    $element.css({
          left: leftAdjust,
          top: topAdjust
          })
    

    draggableInputNo = 0;
    
    var buttonElement = '<div class="button" style="width:200px;">Button</div>'
    var textElement = '<div class="text">Text Element</div>'
    
    $(function() {
      $("#dropContainer").droppable({
        drop: function(event, ui) {
          $element = ui.helper.clone();
          $element.resizable();
          $element.draggable();
          $element.selectable();
    
          if (ui.draggable.hasClass('draggableInput text')) {
            draggableInputNo++;
            $element.attr("id", 'draggableInput' + draggableInputNo);
            $element.appendTo(this);
            $element.append(textElement);
            var parent = $('#dropContainer.ui-droppable');
            var leftAdjust = $element.position().left - parent.offset().left;
            var topAdjust = $element.position().top - parent.offset().top;
            $element.css({
              left: leftAdjust,
              top: topAdjust
            });
          } else if (ui.draggable.hasClass('draggableInput button')) {
            draggableInputNo++;
            $element.attr("id", 'draggableInput' + draggableInputNo);
            $element.appendTo(this);
            $element.append(buttonElement);
            var parent = $('#dropContainer.ui-droppable');
            var leftAdjust = $element.position().left - parent.offset().left;
            var topAdjust = $element.position().top - parent.offset().top;
            $element.css({
              left: leftAdjust,
              top: topAdjust
            });
          }
        }
      });
    
      $(".draggableInput").draggable({
        //containment: '#rpWebPushPopupContainer',
        cursor: 'move',
        helper: draggableInputHelper,
      });
    
    });
    
    function draggableInputHelper(event) {
      return '<div id="draggableInput' + draggableInputNo + '" class="draggableInputHelper resizable" ></div>'
    }
    .draggableInput {
      width: 50px;
      height: 30px;
      padding: 1em;
      float: left;
      margin: 10px 10px 10px 0;
      background-color: #9933ff;
      border-radius: 10px;
      border: 1px solid #9933ff;
    }
    
    .draggableInputHelper {
      width: 100px;
      height: 30px;
      padding: 0.5em;
      margin: 10px 10px 10px 0;
      background-color: #006699;
      border-radius: 10px;
      border: 1px solid #006699;
      color: #ffffff;
    }
    
    #dropContainer {
      width: 300px;
      height: 200px;
      padding: 0.5em;
      margin: 10px;
      float: left;
      border: 1px solid #867979;
      border-radius: 4px;
      background-color: yellow;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="https://code.jquery.com/ui/1.9.1/jquery-ui.min.js"></script>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.9.1/themes/base/jquery-ui.min.css" />
    
    <div class="draggableInput text">Text</div>
    <div class="draggableInput button">Button</div>
    
    <div id="dropContainer" style="position:relative;"></div>