Reddy
Reddy

Reputation: 1497

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>

Upvotes: 2

Views: 759

Answers (2)

Twisty
Twisty

Reputation: 30893

Here is another example, based on the answer you already have above.

$(function() {
  function draggableInputHelper(event) {
    return $("<div>", {
      id: "draggableInput" + draggableInputNo,
      class: "draggableInputHelper resizable"
    });
  }

  function correctDrop(ui, par) {
    return {
      top: (ui.position.top - $(par).offset().top) + "px",
      left: (ui.position.left - $(par).offset().left) + "px"
    }
  }

  var draggableInputNo = 0;

  var buttonElement = $("<div>", {
      class: "button"
    })
    .css("width", "200px")
    .html("Button");
  var textElement = $("<div>", {
    class: "text"
  }).html("Text Element");

  $("#dropContainer").droppable({
    drop: function(event, ui) {
      $element = ui.helper.clone();
      $element.attr("id", 'draggableInput' + ++draggableInputNo);
      $element.css(correctDrop(ui, $("#dropContainer"))).appendTo(this);
      if (ui.draggable.hasClass('draggableInput text')) {
        $element.append(textElement);
      } else if (ui.draggable.hasClass('draggableInput button')) {
        $element.append(buttonElement);
      }
      $element.resizable();
      $element.draggable();
      $element.selectable();
    }
  });

  $(".draggableInput").draggable({
    cursor: 'move',
    helper: draggableInputHelper,
  });
});
.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>

This just condenses some of the code. Making small functions can make it easier to apply some of the changes needed.

Upvotes: 1

4b0
4b0

Reputation: 22323

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>

Upvotes: 1

Related Questions