首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >事件输出时,将jQuery可拖动对象恢复到其原始容器

事件输出时,将jQuery可拖动对象恢复到其原始容器
EN

Stack Overflow用户
提问于 2011-04-21 03:00:30
回答 5查看 111.6K关注 0票数 66

我有一个可拖动的项目,如果不是放在一个可丢弃的项目中,它将恢复。这很好用,直到用户在droppable中拖出一个项目。如果他们认为他们犯了一个错误,那么每当他们拉出可拖放对象时,它就会恢复为可放放对象。我更喜欢on out并停用draggable返回到它的原始容器。

我的代码如下,但我提供了a sample on 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 };
            });
        }
    });
});
EN

回答 5

Stack Overflow用户

发布于 2011-04-26 01:44:09

我不确定这是否适用于您的实际使用,但它适用于您的测试用例-在http://jsfiddle.net/sTD8y/27/更新。

我只是这样做的,只有当项目没有被删除时,才会使用内置的还原。如果已将其删除,则手动执行还原。您可以通过检查实际的CSS属性将其调整为某个计算出的偏移量,但我将允许您使用它,因为它在很大程度上依赖于draggable的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);
        }
    });
});
票数 9
EN

Stack Overflow用户

发布于 2011-04-26 03:15:09

如果您想要将元素还原到源位置(如果它没有被放到#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,而不是在停止时。因此,您添加了大量的事件回调。这是错误的,因为您从未清理过mouseup事件。revert是一个很好的地方,您可以挂接回调并检查元素是放在#droppable元素的内部还是外部,而您现在正在做这件事,所以,只需删除drop回调即可。

当元素被拖放,并且需要知道它是否应该恢复时,您可以肯定地知道,在新的拖动开始之前,您将不会与用户进行任何其他交互。因此,使用您用来知道它是否应该恢复或知道的相同条件,让我们用一段代码替换这个alert:将父元素恢复到原始originalPosition,并从draggable内部重置div。revert属性是在_mouseStart时设置的,因此,如果您更改了元素的所有者,则应该重新设置它,以便使revert的动画转到适当的位置。因此,让我们将其设置为{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;
}

就是这样!你可以在这里检查它的工作情况:http://jsfiddle.net/eUs3e/1/

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

如果你需要一个不使用对ui.draggable内部调用的解决方案,你可以让你的body成为一个可丢弃的元素,并将greedy选项定义为false。您必须确保您的body元素占据整个屏幕。

祝好运!

票数 5
EN

Stack Overflow用户

发布于 2013-05-09 04:07:28

如果有人感兴趣,这里是我对这个问题的解决方案。它完全独立于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'});
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5735270

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档