Javascript jQuery 拖放 - 检查可放置对象外的放置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8092771/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 04:42:37  来源:igfitidea点击:

jQuery drag and drop - checking for a drop outside a droppable

javascriptjqueryjquery-uijquery-ui-draggablejquery-ui-droppable

提问by Chris Kempen

My apologies if this was answered in another question, I could not find an answer specific to my problem!

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

I'm trying to test whether a jQuery draggable is being dropped outside of a legal droppable. This would normally be solved 90% of the time by reverting the draggable, but I don't want to do that. Instead, I want to do one thing if the draggable is dropped onto a droppable (working great!), and something else if it is dropped outside of all possible droppables (currently getting the better of me!).

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

In a nutshell:

简而言之:

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

I feel like I'm missing something really obvious...thanks in advance for any help!

我觉得我错过了一些非常明显的东西......提前感谢您的帮助!

回答by Luke Girvin

Because the droppable's drop event fires before the draggable's stop event, I think you can set a flag on the element being dragged in the drop event like so:

因为 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...
    }
});

回答by Polmonite

I see that you already got an answer; anyway I had this same problem today and I solved it this way:

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

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

I needed that because I couldn't change the options of my draggables, so I had to work only with droppables (I needed it inside the awesome FullCalendarplugin). I suppose it could have some issues using the "greedy" option of droppables, but it should work in most cases.

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

PS: sorry for my bad english.

PS:抱歉我的英语不好。

EDIT:As suggested, I created the version using the jQuery.data; it can be found here : jsfiddle.net/Polmonite/WZma9/

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

Anyway jQuery.data documentation say:

无论如何 jQuery.data 文档说:

Note that this method currently does not provide cross-platform support for setting data on XML documents, as Internet Explorer does not allow data to be attached via expando properties.

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

(meaning that it doesn't work on IE prior to 8)

(意味着它在 8 之前的 IE 上不起作用)

EDIT 2:As noted by @Darin Peterson , the previous code doesn't work with more than one drop-area; this should fix that issue: http://jsfiddle.net/Polmonite/XJCmM/

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

EDIT 3:Example from EDIT 2 has a bug. If I drag "Drag me!" to the bottom droppable, then drop "Drag me too" to the upper droppable and then drop "Drag me too" outside, it alerts "Dropped inside!" So, don't use it.

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

EDIT 4:As noted by @Aleksey Gor, the example in Edit 2 was wrong; actually, it was more of an example to explain how to loop through all the draggables/droppables, but I actually forgot to remove the alert messages, so it was pretty confusing. Here the updated fiddle.

编辑 4:正如@Aleksey Gor 所指出的,编辑 2 中的示例是错误的;实际上,这更像是一个解释如何遍历所有可拖动/可放置的示例,但我实际上忘记了删除警报消息,因此非常令人困惑。是更新的小提琴。

回答by ggzone

Try to use the event "out"of a droppableelement.

尝试使用事件“出”一中投掷的元素。

This is the documentation

这是文档

"This event is triggered when an accepted draggable is dragged out (within the tolerance of) this droppable." If I'm right, this is what you need.

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

What is also possible is to create an element overlay over the whole page. If the element is dropped there you fire your event. Not the best, but I think the only way to do it. Because you need some other "droppable" item to fire these events.

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

回答by Bogmag

The advantage of the following example, is that you don't need to change or know about the droppable code:

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

The draggable revert property can have a function(value){}. A value is passed as argument, indicating if helper was dropped onto an element (the drop element), or 'false' if not dropped on an element (drop outside or not accepted).

draggable revert 属性可以有一个 function(value){}。一个值作为参数传递,指示助手是否被放置到一个元素(放置元素)上,或者如果没有放置在元素上(放置在外面或不被接受),则为“假”。

Note: you need to return the correct bool value from that revert-function, in order to tell the helper to revert or not (true/false). True means yes, take the helper back to its original position, by moving it back in a slow motion (out-of-the-box). False means no, just remove the helper abdruptly. Setting the revert property to 'invalid', is a shortcut of saying

  • 'yes, if dropped outside, then revert helper'
  • 'no, if dropped on a droppable element and accepted, then kill the helper right away'.

注意:您需要从该还原函数返回正确的 bool 值,以便告诉助手是否还原(真/假)。True 表示是的,通过以慢动作(开箱即用)将其移回原位,将助手带回其原始位置。False 表示不,只是突然删除助手。将 revert 属性设置为 'invalid',是一种快捷方式

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

My guess is that you can add current ui helper to draggable container with data property during start event. Then pick it up in the revert function from the data property. Then add a property to the helper, indicating if it was dropped or not. Then ultimately in the stop event, check this data property value, and do what you intended.

我的猜测是,您可以在开始事件期间将当前的 ui 助手添加到具有数据属性的可拖动容器中。然后在数据属性的还原函数中选择它。然后向助手添加一个属性,指示它是否被删除。然后最终在停止事件中,检查此数据属性值,然后按照您的意图进行操作。

Order of event/function calls for draggable: start-revert-stop

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

This could be an example:

这可能是一个例子:

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

You can even return true in the revert function, and just remove the helper during the stop event instead, depending on the data('dropped') value with ui.helper.remove(). Or you could even explode it with CSS3 if you still have a bad day ;)

您甚至可以在 revert 函数中返回 true,而只是在停止事件期间移除帮助程序,具体取决于 ui.helper.remove() 的 data('dropped') 值。或者,如果您仍然有糟糕的一天,您甚至可以使用 CSS3 将其炸毁 ;)

回答by coorasse

I add the solution I adopted since you can understand this very easily from the css classes of the object you are moving:

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

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

回答by Chris Ostmo

Old question and old answers mean that this "may" be a new solution. You (maybe) also wanted, as the question states, to know IF a draggable was dropped outside of a droppable. For me, in at least 95% of the cases, I don't really care IF, I just want things to go back to how they were without any changes being made WHEN that happens.

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

Setting revertto the string invalidaccomplishes the desired behavior without any extra code or funky things to do.

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

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

Again, it won't tell you "if it was dropped outside of a droppable," but it will revert to the initial state if that happens.

同样,它不会告诉你“如果它被丢弃在一个 droppable 之外”,但如果发生这种情况,它会恢复到初始状态。