簡體   English   中英

在 droppable 的 out 事件中將 jQuery 可拖動對象恢復到其原始容器

[英]Revert a jQuery draggable object back to its original container on out event of droppable

我有一個可拖動的項目,如果不放在 droppable 中,它將恢復。 這很有效,直到用戶在 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 };
            });
        }
    });
});
$(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();
});

我不確定這是否適用於您的實際使用,但它適用於您的測試用例 - 在http://jsfiddle.net/sTD8y/27/更新。

我只是做了這樣的內置還原,只有在項目之前沒有被丟棄的情況下才使用。 如果它已被刪除,則還原是手動完成的。 您可以通過檢查實際的 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())
});

在這里,您將擁有可拖動元素的原始父元素。 現在,您必須在精確的時刻恢復它的父級。

每次將元素從 droppable 中拖出時都會調用drop ,而不是在停止處。 所以,你添加了很多事件回調。 這是錯誤的,因為您從不清除mouseup事件。 一個可以掛鈎回調並檢查元素是否被放置在#droppable元素內部或外部的好地方是revert ,並且您現在正在執行此操作,因此,只需刪除drop回調即可。

當元素被放下,並且需要知道它是否應該被還原時,你肯定知道在新的拖動開始之前你不會有來自用戶的任何其他交互。 因此,使用您用來知道它是否應該恢復或知道的相同條件,讓我們用以下代碼片段替換此alert :將父元素恢復到原始 div,並從draggable內部重置originalPosition originalPosition廣告載體在時間設置好的_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;
}

就是這樣! 你可以在這里檢查這個工作: http : //jsfiddle.net/eUs3e/1/

考慮到,如果在任何 jQuery 的 UI 更新中, revertoriginalPosition的行為發生變化,您將需要更新代碼以使其工作。 請記住這一點。

如果您需要一個不使用對 ui.draggable 內部調用的解決方案,您可以使您的body成為一個可放置的元素,其greedy選項定義為false 你必須確保你的body元素全屏顯示。

祝你好運!

如果有人感興趣,這是我對問題的解決方案。 它完全獨立於 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'});
}

它與還原原點有關:在拖動對象時設置原點:只需使用$(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);
                }

我找到了另一種簡單的方法來處理這個問題,你只需要屬性“connectToSortable:”來拖動,如下面的代碼:

$("#a1,#a2").draggable({
        connectToSortable: "#b,#a",
        revert: 'invalid',
    });

PS:更多細節和例子
如何使用 jQuery 在源區域和目標區域之間移動可拖動對象

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM