Возврат перетаскиваемого объекта jQuery обратно в исходный контейнер при событии сброса - PullRequest
60 голосов
/ 20 апреля 2011

У меня есть перетаскиваемый предмет, который, если его не уронить в сбрасываемый предмет, вернется.Это работает хорошо до тех пор, пока пользователь не уронит предмет в предмет сброса.Если они решают, что совершили ошибку в любое время, они вытаскивают перетаскиваемый предмет, и он превращается в сбрасываемый предмет.Я бы предпочел, чтобы при отключении и отключении перетаскиваемый элемент возвращался в исходный контейнер.

Мой код приведен ниже, но я предоставил образец для 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 };
            });
        }
    });
});

Ответы [ 6 ]

127 голосов
/ 01 мая 2011
$(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();
});
7 голосов
/ 25 апреля 2011

Я не уверен, будет ли это работать для вашего реального использования, но оно работает в вашем тестовом примере - обновлено на http://jsfiddle.net/sTD8y/27/.

Я просто сделал так, чтобы встроенныйВозврат используется только в том случае, если предмет не был сброшен ранее.Если он был отброшен, возврат производится вручную.Вы можете настроить его для анимации с некоторым вычисленным смещением, проверив фактические свойства CSS, но я позволю вам поиграть с этим, потому что многое зависит от CSS перетаскиваемого объекта и окружающей его структуры DOM.

4 голосов
/ 25 апреля 2011

Если вы хотите вернуть элемент в исходную позицию, если он не помещен в элемент #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())
});

Здесь у вас будет исходный родительский элемент перетаскиваемого объекта. Теперь вы должны восстановить его родителя в точный момент.

drop вызывается каждый раз, когда элемент вытаскивается из предмета, а не на остановке. Итак, вы добавляете много обратных вызовов событий. Это неправильно, потому что вы никогда не очищаете событие mouseup. Хорошее место, где вы можете подключить обратный вызов и проверить, был ли элемент пропущен внутри или снаружи элемента #droppable, это revert, и вы делаете это прямо сейчас, поэтому просто удалите обратный вызов drop.

Когда элемент отброшен и ему нужно знать, следует ли его вернуть или нет, вы точно знаете, что у вас не будет никакого другого взаимодействия с пользователем до начала нового перетаскивания. Итак, используя то же условие, которое вы используете, чтобы узнать, должно ли оно вернуться или узнать, давайте заменим этот alert фрагментом кода, который: восстанавливает исходный элемент в исходном div и сбрасывает originalPosition из draggable внутренности. Свойство 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 поведение revert или originalPosition изменится, вам потребуется обновить код, чтобы он работал. Имейте в виду, что.

Если вам нужно решение, в котором не используются вызовы внутренних компонентов ui.draggable, вы можете сделать свой body опускаемым элементом с опцией greedy, определенной как false. Вам нужно убедиться, что ваши body элементы занимают весь экран.

Удачи!

3 голосов
/ 09 мая 2013

В случае, если кому-то интересно, вот мое решение проблемы.Он работает полностью независимо от объектов 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'});
}
1 голос
/ 11 ноября 2012

Это связано с возвратом источника: чтобы установить источник, когда объект перетаскивается: просто используйте $(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);
                }
0 голосов
/ 04 августа 2018

Я нашел другой простой способ справиться с этой проблемой, вам просто нужен атрибут "connectToSortable:" для перетаскивания, как показано ниже:

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

PS: подробнее и пример
Как перемещать перетаскиваемые объекты между исходной областью и целевой областью с помощью jQuery

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...