jQuery拖放 - 检查droppable之外的拖放

Posted

技术标签:

【中文标题】jQuery拖放 - 检查droppable之外的拖放【英文标题】:jQuery drag and drop - checking for a drop outside a droppable 【发布时间】:2011-12-26 22:12:20 【问题描述】:

如果在另一个问题中回答了这个问题,我很抱歉,我找不到特定于我的问题的答案!

我正在尝试测试 jQuery 可拖动对象是否被放置在合法可放置对象之外。这通常可以通过恢复可拖动对象在 90% 的时间内解决,但我不想这样做。相反,如果将可拖动对象拖放到可拖放对象上(效果很好!),我想做一件事,如果将其拖放到所有可能的可拖放对象之外(目前正在变得更好!),我想做另一件事。

简而言之:

jQuery('#droppable').droppable(

    accept: '#draggable',
    drop: function(event, ui)
    
        // awesome code that works and handles successful drops...
    
);

jQuery('#draggable').draggable(

    revert: false,
    stop: function()
    
        // need some way to check to see if this draggable has been dropped
        // successfully or not on an appropriate droppable...
        // I wish I could comment out my headache here like this too...
    
);

我觉得我遗漏了一些非常明显的东西......在此先感谢您的帮助!

【问题讨论】:

【参考方案1】:

因为 droppable 的 drop 事件在 draggable 的 stop 事件之前触发,我认为您可以像这样在 drop 事件中为被拖动的元素设置一个标志:

jQuery('#droppable').droppable(

    accept: '#draggable',
    drop: function(event, ui)
    
        ui.helper.data('dropped', true);
        // awesome code that works and handles successful drops...
    
);

jQuery('#draggable').draggable(

    revert: false,
    start: function(event, ui) 
        ui.helper.data('dropped', false);
    ,
    stop: function(event, ui)
    
        alert('stop: dropped=' + ui.helper.data('dropped'));
        // Check value of ui.helper.data('dropped') and handle accordingly...
    
);

【讨论】:

非常酷的解决方案卢克,感谢您的帮助...就像一个魅力! 太棒了,但是:周围有 .data 的文档吗?对我来说,它有点像从天而降:3(阅读:找不到更多信息) 不应该ui.draggable.data('dropped', true);(第6行)实际上是ui.helper.data('dropped', true);吗? 我想是的。否则它总是错误的。 :)【参考方案2】:

我看到你已经得到了答案;无论如何,我今天遇到了同样的问题,我是这样解决的:

var outside = 0;

// this one control if the draggable is outside the droppable area
$('#droppable').droppable(
    accept      : '.draggable',
    out         : function()
        outside = 1;
    ,
    over        : function()
        outside = 0;
    
);

// this one control if the draggable is dropped
$('body').droppable(
    accept      : '.draggable',
    drop        : function(event, ui)
        if(outside == 1)
            alert('Dropped outside!');
        else
            alert('Dropped inside!');
        
    
);

我需要它,因为我无法更改我的 Draggables 的选项,所以我只能使用 droppables(我需要在很棒的 FullCalendar 插件中使用它)。 我想使用 droppables 的“贪婪”选项可能会出现一些问题,但在大多数情况下它应该可以工作。

PS:对不起,我的英语不好。

编辑: 按照建议,我使用 jQuery.data 创建了版本;可以在这里找到:jsfiddle.net/Polmonite/WZma9/

无论如何 jQuery.data 文档说:

请注意,此方法目前不为在 XML 文档上设置数据提供跨平台支持,因为 Internet Explorer 不允许通过扩展属性附加数据。

(意思是在8之前的IE上不起作用)

编辑 2: 正如@Darin Peterson 所指出的,前面的代码不适用于多个放置区域;这应该可以解决这个问题:http://jsfiddle.net/Polmonite/XJCmM/

EDIT 3: EDIT 2 中的示例有一个错误。如果我拖动“拖动我!”到底部的d​​roppable,然后将“Drag me too”放到上面的droppable,然后将“Drag me too”放到外面,它会提示“Dropped inside!”所以,不要使用它。

编辑 4: 正如@Aleksey Gor 所指出的,编辑 2 中的示例是错误的;实际上,它更像是一个示例来解释如何循环遍历所有可拖动/可拖放的,但我实际上忘记删除警报消息,所以它非常混乱。 Here 更新的小提琴。

【讨论】:

又好又简单!这是一个很好的解决方案,尤其是当您无法访问可拖动对象时。我想知道,现在考虑可能的范围问题,是否可以使用$("#droppable").data("outside", true); 更优雅地“携带”变量的状态?不错的解决方案!谢谢您的意见! :) 当然。我将使用 jQuery.data 的版本添加到答案中;)无论如何,这意味着没有 IE7(以防有人关心)。 太棒了!感谢您的研究和扩展答案! +1 如果您有多个可放置位置,此解决方案将不起作用。例如,我当前正在处理的页面有许多可放置的单元格,当您的可拖动单元格位于一个可放置的单元格上并转换到一个也可放置的新单元格时,会触发 out。请注意,触发 out 并不一定意味着您位于不可放置的区域。 @Darin Peterson:是的。无论如何,它可以很容易地通过下拉区域循环并寻找每个 .data('outside');像这样:jsfiddle.net/Polmonite/XJCmM .【参考方案3】:

尝试使用 droppable 元素的事件 "out"

这是documentation

“当一个已接受的可拖动对象被拖出(在其容差范围内)此可放置对象时,将触发此事件。” 如果我是对的,这就是你需要的。

还有可能在整个页面上创建一个元素覆盖。如果元素被丢弃在那里,您将触发您的事件。不是最好的,但我认为这是唯一的方法。因为您需要一些其他“可放置”项目来触发这些事件。

【讨论】:

嘿 ggzone,感谢您的快速响应...如果我拖动的可拖动对象来自有效的可放置对象,那将是完美的。如果一个可拖动对象被从其原始位置拖动,然后随机放置在远离合法可放置对象的某个地方,那么据我所知,这个事件永远不会被触发! 太棒了,谢谢ggzone ...就像你说的,可能不是最好的,如果你还没有看到Luke提供的答案,我认为它提供了一个更优雅的解决方案结果!【参考方案4】:

以下示例的优点是您无需更改或了解可放置代码:

可拖动的还原属性可以具有函数(值)。一个值作为参数传递,指示帮助器是否被拖放到元素上(放置元素),如果没有被拖放到元素上(放在外面或不被接受),则为“假”。

注意:您需要从中返回正确的布尔值 revert-function,为了告诉助手是否恢复 (真假)。 True 表示是,将助手带回原来的状态 位置,通过慢动作(开箱即用)将其移回。 False 表示不,只是 突然删除助手。将还原属性设置为“无效”, 是说的捷径

'是的,如果掉到外面,则恢复助手' '不,如果放置在可放置元素上并被接受,则立即杀死助手'。

我的猜测是,您可以在启动事件期间将当前的 ui 助手添加到具有数据属性的可拖动容器中。然后从 data 属性的 revert 函数中选择它。然后向助手添加一个属性,指示它是否被删除。然后最终在停止事件中,检查这个数据属性值,然后做你想做的事情。

可拖动的事件/函数调用顺序: 开始-恢复-停止

这可能是一个例子:

jQuery('#draggable').draggable(

    start: function(event, ui) 
        $(this).data('uihelper', ui.helper);
    ,
    revert: function(value)
        var uiHelper = (this).data('uihelper');
        uiHelper.data('dropped', value !== false);
        if(value === false)
             return true;
        
        return false;
    ,
    stop: function(event, ui)
    
        if(ui.helper.data('dropped') === true)
            // handle accordingly...
        
    
);

您甚至可以在 revert 函数中返回 true,而只是在停止事件期间删​​除助手,这取决于 ui.helper.remove() 中的 data('dropped') 值。或者,如果你的日子还不好过,你甚至可以用 CSS3 来爆炸它;)

【讨论】:

【参考方案5】:

我添加了我采用的解决方案,因为您可以从您正在移动的对象的 css 类中轻松理解这一点:

jQuery('#draggable').draggable(
  stop: function(event, ui) 
    if (ui.helper.hasClass('ui-draggable-dragging')) 
      console.log('dropped out');
     else 
      console.log('dropped successfully');
    
  
);

【讨论】:

【参考方案6】:

旧问题和旧答案意味着这个“可能”是一个新的解决方案。正如问题所述,您(也许)还想知道是否将可拖动对象放置在可放置对象之外。对我来说,在至少 95% 的情况下,我真的不在乎是否,我只想让事情回到原来的样子,而不会在发生这种情况时做出任何改变。

revert 设置为字符串invalid 即可完成所需的行为,而无需任何额外的代码或时髦的事情要做。

$( '#draggable' ).draggable(
    revert: "invalid",
    stop: function( event, ui )
    
       // whatever
    
);

同样,它不会告诉您“它是否被丢弃在可放置对象之外”,但如果发生这种情况,它会恢复到初始状态。

【讨论】:

以上是关于jQuery拖放 - 检查droppable之外的拖放的主要内容,如果未能解决你的问题,请参考以下文章

如何在不实际拖放的情况下使用 jQuery UI Droppable 触发 Drop 事件?

jQuery 可拖放定位

Jquery Droppable 不适用于文件上传拖放,抛出错误:预期的 DOM 元素或视图

jQuery UI - Droppable 只接受一个可拖动的

jQuery 可拖放和可滚动的 div

jQuery Droppable:放在 div 之外?