在 droppable 的 out 事件中将 jQuery 可拖动对象恢复到其原始容器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5735270/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Revert a jQuery draggable object back to its original container on out event of droppable
提问by ahsteele
I have a draggable item which if not dropped in a droppable will revert. This works well until a user drops an item in the droppable. If they decide they've made a mistake anytime they pull the draggable out it reverts to the droppable. I would prefer that on out and deactivate the draggable goes back to its original container.
我有一个可拖动的项目,如果不放在 droppable 中,它将恢复。这很有效,直到用户在 droppable 中放置一个项目。如果他们认为他们在任何时候都犯了错误,那么他们将可拖动对象拉出,它会恢复为可放置对象。我更喜欢关闭并停用可拖动对象回到其原始容器。
My code is below but I have provided a sample on jsFiddle.
我的代码在下面,但我在 jsFiddle 上提供了一个示例。
HTML
HTML
<div id="origin">
<div id="draggable" class="ui-widget-content">
<p>I revert when I'm not dropped</p>
</div>
</div>
<div id="droppable" class="ui-widget-header">
<p>Drop me here</p>
</div>
JavaScript
JavaScript
$(function() {
$("#draggable").draggable({
revert: function(dropped) {
var dropped = dropped && dropped[0].id == "droppable";
if(!dropped) alert("I'm reverting!");
return !dropped;
}
}).each(function() {
var top = $(this).position().top;
var left = $(this).position().left;
$(this).data('orgTop', top);
$(this).data('orgLeft', left);
});
$("#droppable").droppable({
activeClass: 'ui-state-hover',
hoverClass: 'ui-state-active',
drop: function(event, ui) {
$(this).addClass('ui-state-highlight').find('p').html('Dropped!');
},
out: function(event, ui) {
// doesn't work but something like this
ui.draggable.mouseup(function () {
var top = ui.draggable.data('orgTop');
var left = ui.draggable.data('orgLeft');
ui.position = { top: top, left: left };
});
}
});
});
回答by Luca Filosofi
TESTEDwith jquery 1.11.3& jquery-ui 1.11.4
检测过用jQuery的1.11.3和jQuery的UI 1.11.4
演示:http : //so.lucafilosofi.com/revert-a-jquery-draggable-object-back-to-its-original-container-on-out-event-of-d/
$(function() {
$("#draggable").draggable({
revert : function(event, ui) {
// on older version of jQuery use "draggable"
// $(this).data("draggable")
// on 2.x versions of jQuery use "ui-draggable"
// $(this).data("ui-draggable")
$(this).data("uiDraggable").originalPosition = {
top : 0,
left : 0
};
// return boolean
return !event;
// that evaluate like this:
// return event !== false ? false : true;
}
});
$("#droppable").droppable();
});
回答by BBonifield
I'm not sure if this will work for your actual use, but it works in your test case - updated at http://jsfiddle.net/sTD8y/27/.
我不确定这是否适用于您的实际使用,但它适用于您的测试用例 - 在http://jsfiddle.net/sTD8y/27/更新。
I just made it so that the built-in revert is only used if the item has not been dropped before. If it has been dropped, the revert is done manually. You could adjust this to animate to some calculated offset by checking the actual CSS properties, but I'll let you play with that because a lot of it depends on the CSS of the draggable and it's surrounding DOM structure.
我只是做了这样的内置还原,只有在项目之前没有被丢弃的情况下才使用。如果它已被删除,则还原是手动完成的。您可以通过检查实际的 CSS 属性来调整它以根据计算出的偏移量设置动画,但我会让您尝试一下,因为它很大程度上取决于可拖动对象的 CSS 及其周围的 DOM 结构。
$(function() {
$("#draggable").draggable({
revert: function(dropped) {
var $draggable = $(this),
hasBeenDroppedBefore = $draggable.data('hasBeenDropped'),
wasJustDropped = dropped && dropped[0].id == "droppable";
if(wasJustDropped) {
// don't revert, it's in the droppable
return false;
} else {
if (hasBeenDroppedBefore) {
// don't rely on the built in revert, do it yourself
$draggable.animate({ top: 0, left: 0 }, 'slow');
return false;
} else {
// just let the built in revert work, although really, you could animate to 0,0 here as well
return true;
}
}
}
});
$("#droppable").droppable({
activeClass: 'ui-state-hover',
hoverClass: 'ui-state-active',
drop: function(event, ui) {
$(this).addClass('ui-state-highlight').find('p').html('Dropped!');
$(ui.draggable).data('hasBeenDropped', true);
}
});
});
回答by Gonzalo Larralde
If you want to revert the element to the source position if it's not dropped inside a #droppable
element, just save the original parent element of the draggable at the start of the script (instead of the position), and if you verify that it's not dropped into #droppable
, then just restore the parent of #draggable
to this original element.
如果您想将元素恢复到源位置(如果它没有放在#droppable
元素内),只需在脚本开头(而不是位置)保存可拖动元素的原始父元素,如果您验证它没有放入#droppable
,然后只需将 的父级恢复#draggable
到该原始元素。
So, replace this:
所以,替换这个:
}).each(function() {
var top = $(this).position().top;
var left = $(this).position().left;
$(this).data('orgTop', top);
$(this).data('orgLeft', left);
});
with this:
有了这个:
}).each(function() {
$(this).data('originalParent', $(this).parent())
});
Here, you'll have the original parent element of the draggable. Now, you have to restore it's parent in a precise moment.
在这里,您将拥有可拖动元素的原始父元素。现在,您必须在精确的时刻恢复它的父级。
drop
is called every time the element is dragged out from the droppable, not at the stop. So, you're adding a lot of event callbacks. This is wrong, because you never clean the mouseup
event. A good place where you can hook a callback and check if the element was dropped inside or outside the #droppable
element, is revert
, and you're doing it right now, so, just delete the drop
callback.
drop
每次元素从 droppable 中拖出时都会调用,而不是在停止处。所以,你添加了很多事件回调。这是错误的,因为您从不清理mouseup
事件。一个可以挂钩回调并检查元素是放在元素内部还是外部的好地方#droppable
is revert
,并且您现在正在执行此操作,因此,只需删除drop
回调即可。
When the element is dropped, and needs to know if it should be reverted or not, you know for sure that you'll not have any other interaction from the user until the new drag start. So, using the same condition you're using to know if it should revert or know, let's replace this alert
with a fragment of code that: restores the parent element to the original div, and resets the originalPosition
from the draggable
internals. The originalPosition
proeprty is setted at the time of _mouseStart
, so, if you change the owner of the element, you should reset it, in order to make the animation of revert go to the proper place. So, let's set this to {top: 0, left: 0}
, making the animation go to the origin point of the element:
当元素被放下,并且需要知道它是否应该被还原时,你肯定知道在新的拖动开始之前你不会有来自用户的任何其他交互。因此,使用您用来知道它是否应该恢复或知道的相同条件,让我们用以下alert
代码片段替换它:将父元素恢复到原始 div,并originalPosition
从draggable
内部重置 div 。该originalPosition
广告载体在时间设置好的_mouseStart
,所以,如果你改变元素的主人,你应该重新设置,以使复归走的动画到适当的位置。因此,让我们将其设置为{top: 0, left: 0}
,使动画转到元素的原点:
revert: function(dropped) {
var dropped = dropped && dropped[0].id == "droppable";
if(!dropped) {
$(this).data("draggable").originalPosition = {top:0, left:0}
$(this).appendTo($(this).data('originalParent'))
}
return !dropped;
}
And that's it! You can check this working here: http://jsfiddle.net/eUs3e/1/
就是这样!你可以在这里检查这个工作:http: //jsfiddle.net/eUs3e/1/
Take into consideration that, if in any jQuery's UI update, the behavior of revert
or originalPosition
changes, you'll need to update your code in order to make it work. Keep in mind that.
考虑到,如果在任何 jQuery 的 UI 更新、行为revert
或originalPosition
更改中,您将需要更新您的代码以使其工作。请记住这一点。
If you need a solution which doesn't make use of calls to the internals of ui.draggable, you can make your body
an droppable element with greedy
option defined as false
. You'll have to make sure that your body
elements take the full screen.
如果您需要一个不使用对 ui.draggable 内部调用的解决方案,您可以body
使用greedy
定义为 的选项制作一个可放置的元素false
。您必须确保您的body
元素全屏显示。
Good luck!
祝你好运!
回答by bnrup
In case anyone's interested, here's my solution to the problem. It works completely independently of the Draggable objects, by using events on the Droppable object instead. It works quite well:
如果有人感兴趣,这是我对问题的解决方案。它完全独立于 Draggable 对象工作,而是使用 Droppable 对象上的事件。它工作得很好:
$(function() {
$(".draggable").draggable({
opacity: .4,
create: function(){$(this).data('position',$(this).position())},
cursor:'move',
start:function(){$(this).stop(true,true)}
});
$('.active').droppable({
over: function(event, ui) {
$(ui.helper).unbind("mouseup");
},
drop:function(event, ui){
snapToMiddle(ui.draggable,$(this));
},
out:function(event, ui){
$(ui.helper).mouseup(function() {
snapToStart(ui.draggable,$(this));
});
}
});
});
function snapToMiddle(dragger, target){
var topMove = target.position().top - dragger.data('position').top + (target.outerHeight(true) - dragger.outerHeight(true)) / 2;
var leftMove= target.position().left - dragger.data('position').left + (target.outerWidth(true) - dragger.outerWidth(true)) / 2;
dragger.animate({top:topMove,left:leftMove},{duration:600,easing:'easeOutBack'});
}
function snapToStart(dragger, target){
dragger.animate({top:0,left:0},{duration:600,easing:'easeOutBack'});
}
回答by Hugo Gresse
It's related about revert origin : to set origin when the object is drag : just use $(this).data("draggable").originalPosition = {top:0, left:0};
它与还原原点有关:拖动对象时设置原点:只需使用 $(this).data("draggable").originalPosition = {top:0, left:0};
For example : i use like this
例如:我这样使用
drag: function() {
var t = $(this);
left = parseInt(t.css("left")) * -1;
if(left > 0 ){
left = 0;
t.draggable( "option", "revert", true );
$(this).data("draggable").originalPosition = {top:0, left:0};
}
else t.draggable( "option", "revert", false );
$(".slider-work").css("left", left);
}
回答by Willie Cheng
I've found another easy way to deal with this problem, you just need the attribute " connectToSortable:" to draggable like as below code:
我找到了另一种简单的方法来处理这个问题,你只需要属性“connectToSortable:”来拖动,如下面的代码:
$("#a1,#a2").draggable({
connectToSortable: "#b,#a",
revert: 'invalid',
});
PS: More detail and example
How to move Draggable objects between source area and target area with jQuery
PS:更多细节和示例
How to move Draggable objects between source area and target area with jQuery