将jQuery可拖动对象还原为其原始容器时,可以将其拖放

我有一个可拖动的物品,如果不落在droppable将恢复。 这个效果很好,直到用户放下一个物品。 如果他们认为他们在拖出可拖拽的时候犯了错误,那么它就会回到可丢弃的状态。 我更喜欢在外面和停用可拖动回到其原来的容器。

我的代码在下面,但我提供了一个jsFiddle的示例 。

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的

 $(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 }; }); } }); }); 
  • jQuery 1.11.3jquery-ui 1.11.4进行了testing

  • DEMO: http : //so.devilmaycode.it/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(); }); 

我不确定这是否适用于您的实际使用,但它在您的testing案例中工作 – 更新在http://jsfiddle.net/sTD8y/27/

我只是这样做,只有在物品还没有被丢弃之前,才使用内置的还原。 如果已经被删除,恢复是手动完成的。 你可以通过检查实际的CSS属性来调整这个animation来达到一些计算出的偏移量,但是我会让你玩这个,因为它很多取决于可拖动的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()) }); 

在这里,您将拥有可拖动的原始父元素。 现在,你必须在一个精确的时刻恢复它的父母。

每当元素从droppable中拖出时,都会调用drop ,而不是在stop处。 所以,你添加了很多事件callback。 这是错误的,因为你永远不会清理mouseup事件。 一个好的地方,你可以挂钩一个callback,并检查元素是否被抛弃在#droppable元素内部或外部,是revert ,你现在正在做,所以,只要删除callback。

当元素被删除,并且需要知道是否应该被还原时,您确定不会有任何其他用户的交互,直到新的拖动开始。 因此,使用与使用相同的条件来知道它是否应该还原或知道,让我们用一段代码replace此alert :将父元素恢复到原始div,并重置originalPositiondraggable内部。 originalPosition proeprty是在_mouseStart的时候设置的,所以如果你改变元素的所有者,你应该重置它,以便使回复的animation到适当的位置。 所以,我们将其设置为{top: 0, left: 0} ,使animation进入元素的原点:

 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; } 

而就是这样! 你可以在这里检查这个工作: http : //jsfiddle.net/eUs3e/1/

考虑到,如果在任何jQuery的UI更新中, revertoriginalPosition的行为发生了变化,您需要更新代码才能使其工作。 请记住这一点。

如果你需要一个不使用ui.draggable的内部调用的解决scheme,你可以让你的body是一个可选的元素, greedy选项被定义为false 。 你必须确保你的body元素全屏。

祝你好运!

如果有人感兴趣,这是我的问题的解决scheme。 它通过使用Droppable对象上的事件来完全独立于Draggable对象。 它工作得很好:

 $(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'}); } 

这是关于恢复原点:当对象是拖动时设置原点:只需使用$(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); }