将可拖动元素交换到另一个可拖动的拖放上的鼠标光标

时间:2014-03-07 17:24:53

标签: javascript jquery javascript-events jquery-ui-draggable jquery-ui-droppable

好的,我已经看到几个关于只是在下降时交换两个可拖动元素的问题,但我的情况有点不同。

基本上,我在(非线性)网格中放置了一堆可拖动元素。在许多情况下,网格将完全填充数据。我们希望允许用户轻松地重新排列网格元素,但由于网格是非线性的,因此使用“可排序”不是一种选择。并且由于网格是完全填充的,当一个网格被拖到另一个网格位置时,直接交换两个网格位置并不是理想的解决方案(因为我们不会尝试将三个位置重新排列到某种脑筋急转弯中)。 / p>

我们想要做的是在拖动网格元素(称为A)时进行正常的“拖动”操作,但是当元素被拖放到所需的目标(其中已经有另一个网格项)时,称之为B),然后A应该取B的位置,然后B应该“捕捉”鼠标光标,就像用户点击并拖动它一样。这显然会稍微扰乱鼠标的交互,因为现在用户没有按下鼠标按钮但是正在拖动元素,所以要释放元素,他要么点击A来自的空单元格,要么单击另一个网格元素C ,此时B将占据C的位置,C现在将“附加”到鼠标光标。

我仔细阅读了“Draggable”文档和源代码,并且似乎没有办法完全按照我想要的方式配置它,但我很确定我可以扩展可拖动的小部件并覆盖其几个方法来实现我想要的,而不是必须从头开始编写我自己的解决方案。如果它变得更容易,对我来说,如果用于首先触发拖动的鼠标事件是与拖动事件相比的点击,那对我来说无关紧要。

要清楚,这是我正在寻找的一种交互图:

Original Setup - ^ is mouse cursor
[A]  ^  [C]
[B]     [D]

Now click and drag on A. Result is:
[ ]^A   [C]
[B]     [D] 

Now drag over B and release. Result is:
[ ]     [C]
[A]^B   [D]

B is now acting as if it's being dragged, but mouse button is not held down. Move
cursor over C and click mouse button. Result is:
[ ]     [B] ^C
[A]     [D]

B has taken C's place, and C is now following the mouse cursor. Again, mouse 
button is not being held down. Move cursor over empty cell and click mouse 
button. Result is:
[C] ^   [B]
[A]     [D]

Now there is nothing attached to the mouse cursor.

2 个答案:

答案 0 :(得分:2)

好吧,既然没有人试过回答我的问题,我设法找到一个相当简单的方法来实现这一点。在这种情况下,我的救世主是jquery.simulatejquery.simulate.extjquery.simulate.drag-n-drop插件。使用这些来模拟一组元素上的特定本机浏览器事件(或者在drag-n-drop插件的情况下,单个元素)是微不足道的。这意味着我可以简单地使用jQueryUI droppable中的“drop”回调来完成我需要的东西:

drop: function (e, ui) {
    var $targ = $(e.target);
    ui.draggable.detach().appendTo($targ).css({top: 0, left: 0});
    $targ.find('.ui-draggable .handle').simulate('drag', {});
}

就是这样!这就是全部。这是演示解决方案的小提琴:http://jsfiddle.net/isochronous/mD8uM/

更新:原来处理draggable中的“恢复”行为实际上是最困难的部分。我最终创建了自己的小部件,扩展了$.ui.draggable来处理这个问题。我已经更新了小提琴并添加了注释来解释它是如何工作的,以防万一有兴趣。

答案 1 :(得分:0)

将此作为单独的答案添加,因为这是解决问题的完全不同的方法。

在我开始工作之后,我尝试添加了一些其他新功能,例如将is-swap类应用于悬停在非空的droppable上的draggable,并应用is-drop类当它悬停在一个空的时候。但是因为我们的droppables如此接近,overout回调会在成为over新的dropable之前变得困惑,然后成为前一个out

我已经意识到我需要做的,如果我希望继续使用jQuery UI,不是要子类可拖动或可放置,而是只是使用它们完全是新的小部件。可拖动和可放置都是在许多不同元素上实例化的小部件(例如,每个可拖动的是它自己的实例,每个可放置的是它自己的实例),但我需要的是一个小部件包含许多draggables和droppables。这将使他们在相互交互时更容易控制状态。

现在我的计划是创建一个可以在某种容器元素上实例化的窗口小部件,并提供允许窗口小部件的使用者将所需元素作为可拖动和可放置的目标进行实例化的选项,并简单地使用可拖动和可放置的他们的“自然”状态。这将允许我执行诸如从另一个回调中检查一个dropable的状态,并修复我之前提到的outover时序问题等问题。

我将在接下来的几天内尝试实施这一点,并且一旦我有要展示的话,我会更新这个答案。

更新:这是使用这种方法的更简化,更准确的实现。 http://jsfiddle.net/isochronous/BQyx2/