在相对定位的容器之间移动可拖动元素

时间:2016-03-23 09:56:14

标签: html css jquery-ui draggable

我有一个页面,其中包含可以放入各种容器的项目。我必须在任何给定时间将可拖动项目添加到它当前所在的容器中,以便根据css以某种方式对其进行样式设置,这取决于可拖动目标和放置目标的组合'上课。在javascript中应用此样式不是一个选项 - 样式必须来自CSS。

问题来了,因为我在前面添加了draggable的容器具有position: relative属性。当我移动它时,这会让可靠的助手相对于我的鼠标的位置变得混乱。

这是一个非常简化的问题演示:



$('.draggable').draggable({
  drag: _onDrag,
  helper: function () {
    return $(this).clone().prependTo('#div1');
  }
});

function _onDrag(event, ui) {
  ui.helper.hide();

  var elementAtPoint = $(document.elementFromPoint(event.clientX, event.clientY));

  if(elementAtPoint.hasClass('dropTarget')) {
  	ui.helper.prependTo(elementAtPoint);
  }  
  
  ui.helper.show();
}

.draggable {
 display: inline-block;
 background: red;
 height:50px;
 width: 50px;
}

#div1 .item1 {
  background: green;
}

#div1 .item2 {
  background: purple;
}

#div2 .item1 {
  background: blue;
}

#div2 .item2 {
  background: orange;  
}

#div1, #div2 {
  position: relative;
  width: 100px;
  height: 100px;
  border: 1px solid #000;
  display: inline-block;
}

<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>

<div class="draggable item1">
  Drag me!
</div>

<div class="draggable item2">
  Drag me too!
</div>

<div id="div1" class="dropTarget">
  Drag the box here first...
</div>
<div id="div2" class="dropTarget">
  Then drag it here :(
</div>
&#13;
&#13;
&#13;

我可以做些什么来阻止拖拽者失去它的位置,而不改变css或html?

1 个答案:

答案 0 :(得分:2)

这是因为重新排列DOM时,基于新的偏移量重新计算渲染位置。解决它的最简单方法是不重新排列DOM。您是否考虑过使用self.tableView.separatorStyle = UITableViewCellSeparatorStyle.SingleLine self.tableView.separatorInset = UIEdgeInsetsMake(0, 20, 0, 20) 小部件?它们提供了您几乎可以开箱即用的功能:

&#13;
&#13;
droppable
&#13;
$('#draggable').draggable({
  helper: function () {
    return $(this).clone().prependTo('#div1');
  }
});
$('#div1, #div2').droppable({
  over: function(e, ui) {
    ui.helper.addClass($(this).data('target-class'));
  },
  out: function(e, ui) {
    ui.helper.removeClass($(this).data('target-class'));
  }
});
&#13;
#draggable {
 display: inline-block;
 background: red;
 height:50px;
 width: 50px;
}

#draggable.green {
  background: green;
}

#draggable.blue {
  background: blue;
}

#div1, #div2 {
  position: relative;
  width: 100px;
  height: 100px;
  border: 1px solid #000;
  display: inline-block;
}
&#13;
&#13;
&#13;

更新:为了在没有任何CSS更改的情况下执行此操作,您可以获得容器之间的区别&#39;位置,并将其用作位置偏移。

&#13;
&#13;
<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>

<div id="draggable">
  Drag me!
</div>

<div id="div1" class="dropTarget" data-target-class="green">
  Drag the box here first...
</div>
<div id="div2" class="dropTarget" data-target-class="blue">
  Then drag it here :)
</div>
&#13;
$('.draggable').draggable({
  start: _onStart,
  drag: _onDrag,
  helper: function () {
    return $(this).clone().prependTo('#div1');
  }
});

function _onStart(event, ui) {
  this.initialContainer = ui.helper.parent();
  this.currentContainer = ui.helper.parent();
  this.topOffset = 0;
  this.leftOffset = 0;
}

function _onDrag(event, ui) {
  ui.helper.hide();

  var elementAtPoint = $(document.elementFromPoint(event.clientX, event.clientY));

  if(elementAtPoint.hasClass('dropTarget') &&
     !elementAtPoint.is(this.currentContainer)) {

    this.topOffset = elementAtPoint.position().top -
                     this.initialContainer.position().top;
    this.leftOffset = elementAtPoint.position().left -
                      this.initialContainer.position().left;

    this.currentContainer = elementAtPoint;

	ui.helper.prependTo(elementAtPoint);
  }
  
  ui.position.top -= this.topOffset;
  ui.position.left -= this.leftOffset;
  
  ui.helper.show();
}
&#13;
.draggable {
 display: inline-block;
 background: red;
 height:50px;
 width: 50px;
}

#div1 .item1 {
  background: green;
}

#div1 .item2 {
  background: purple;
}

#div2 .item1 {
  background: blue;
}

#div2 .item2 {
  background: orange;  
}

#div1, #div2 {
  position: relative;
  width: 100px;
  height: 100px;
  border: 1px solid #000;
  display: inline-block;
}
&#13;
&#13;
&#13;

我仍然建议尽可能推动重写CSS。第一种方法更具可读性和脆弱性