在Dropable事件发生时,将jQuery可拖动对象还原回其原始容器
我有一个可拖放的项目,如果不在一个可拖放将恢复。在用户将一个项目放入可拖放列表之前,这项功能一直运行良好。如果他们决定在任何时候拉出可拖动设备时犯了错误,它将恢复为可拖放设备。我更喜欢打开并停用Dragable,使其返回到原始容器 我的代码如下,但我已提供 HTML在Dropable事件发生时,将jQuery可拖动对象还原回其原始容器,jquery,jquery-ui,Jquery,Jquery Ui,我有一个可拖放的项目,如果不在一个可拖放将恢复。在用户将一个项目放入可拖放列表之前,这项功能一直运行良好。如果他们决定在任何时候拉出可拖动设备时犯了错误,它将恢复为可拖放设备。我更喜欢打开并停用Dragable,使其返回到原始容器 我的代码如下,但我已提供 HTML 我不确定这是否适用于您的实际使用,但它适用于您的测试用例-更新于 我只是这样做的,只有在项目之前没有被删除的情况下才使用内置的恢复。如果已删除,则手动执行还原。您可以通过检查实际的CSS属性来调整它,使其动画化到某个计算出的偏移量,
我不确定这是否适用于您的实际使用,但它适用于您的测试用例-更新于 我只是这样做的,只有在项目之前没有被删除的情况下才使用内置的恢复。如果已删除,则手动执行还原。您可以通过检查实际的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);
}
});
});
如果要将未放入
#droppable
元素中的元素还原到源位置,则只需在脚本开头保存可拖动的原始父元素(而不是位置),如果确认未将其放入#droppable
,然后将#draggable
的父元素还原到此原始元素
因此,替换这个:
}).each(function() {
var top = $(this).position().top;
var left = $(this).position().left;
$(this).data('orgTop', top);
$(this).data('orgLeft', left);
});
为此:
}).each(function() {
$(this).data('originalParent', $(this).parent())
});
在这里,您将拥有可拖动的原始父元素。现在,您必须在精确的时刻恢复它的父级
drop
在每次从可拖放项中拖出元素时调用,而不是在停止时调用。因此,您添加了很多事件回调。这是错误的,因为您从未清除mouseup
事件。您可以挂接回调并检查元素是否在#droppable
元素的内部或外部放置的一个好位置是revert
,您现在正在执行此操作,因此,只需删除drop
回调即可
当元素被拖放,并且需要知道它是否应该被还原时,您可以肯定地知道,在新的拖放开始之前,用户不会进行任何其他交互。因此,使用您用来知道它是否应该恢复或知道的相同条件,让我们将此警报
替换为一段代码:将父元素恢复到原始div,并从可拖动的内部重置原始位置
。原始位置
属性是在\u 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;
}
就这样!您可以在此处检查此工作:
考虑到,如果在任何jQuery的UI更新中,revert
或originalPosition
的行为发生了变化,则需要更新代码以使其正常工作。记住这一点
如果您需要一个不使用对ui.draggable内部调用的解决方案,您可以使用定义为false
的greedy
选项,使您的body
成为可拖放元素。你必须确保你的主体
元素占据全屏
祝你好运
- 使用jquery 1.11.3和jquery ui 1.11.4进行测试
- 演示:
它与还原原点相关:要在拖动对象时设置原点:只需使用$(this).data(“draggable”).originalPosition={top:0,left:0}代码>
例如:我这样使用
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);
}
如果有人感兴趣,这是我对这个问题的解决方案。它完全独立于可拖动对象工作,而是使用可拖放对象上的事件。它工作得相当好:
$(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'});
}
我找到了另一种解决此问题的简单方法,您只需使用属性“connectToSortable:”即可拖动,如下代码所示:
$("#a1,#a2").draggable({
connectToSortable: "#b,#a",
revert: 'invalid',
});
PS:更多细节和示例
不幸的是,出于我的目的,out启动得太早了(拖拉机离开的那一刻)。
这不是out的目的吗?你只想知道他们是不是mouseup
而out
?@drachenstern好主意。我将在out事件中进行实验,但无论哪种方法都无法解决可拖动设备恢复为可拖放设备的问题。很高兴我能提供帮助,但仍然不确定我在您的脑海中触发了什么。我认为,一旦你移动它,拖拽装置就失去了它的“家”可放下性。您可能需要将该信息存储在某个辅助方法中。@drachenstern我正打算存储原始位置。我只是不能让它用它来代替它在下拉列表中的新位置(顺便说一句:代码已更新以反映您的建议。您需要两个可拖放区域。当您未超过其中任何一个区域时,返回!drop
,此时您需要处理拖放到何处。不要在out或mouseup上执行此操作。一旦您将还原的内容拖放到可拖放区域,它就没有任何地方可以放置。(或者,当你没有检测到你在可拖放区域时,只需删除“position:relative”(位置:相对)Gonzalo,我认为这里不需要“originalParent”逻辑。当你拖放一个可拖放对象时,底层DOM结构实际上不会改变。是的!你是对的。不需要:-)我习惯于使用ULs和LIs来处理可拖动/可拖放。谢谢!这里的内容确实有效,但是如果与无序列表一起使用,readd会有点不稳定。通过将其添加到底部。这意味着这是更可读的解决方案。据我所知,drop
仅在元素实际被删除时才被调用。我遗漏了什么吗?@ahsteele也许你可以提供你正在尝试使用的实际DOM。它可能是h
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);
}
$(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'});
}
$("#a1,#a2").draggable({
connectToSortable: "#b,#a",
revert: 'invalid',
});