Перетаскивание jQuery - проверка на падение за пределами droppable

Приношу свои извинения, если на этот вопрос был дан ответ в другом вопросе, я не смог найти ответ, специфичный для моей проблемы!

Я пытаюсь проверить, удаляется ли перетаскиваемый 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...
    }
});

Я чувствую, что упускаю что-то действительно очевидное... заранее спасибо за любую помощь!


person Chris Kempen    schedule 11.11.2011    source источник


Ответы (6)


Поскольку событие droppable срабатывает до события остановки draggable, я думаю, вы можете установить флаг для перетаскиваемого элемента в событии 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...
    }
});
person Luke Girvin    schedule 11.11.2011
comment
Очень, очень классное решение, Люк, спасибо за это ... сработало как шарм! - person Chris Kempen; 11.11.2011
comment
Удивительно, но: есть ли документация для .data? Для меня это как бы с небес :3 (читай: больше информации не нашел) - person nuala; 16.07.2012
comment
Разве ui.draggable.data('dropped', true); (строка 6) на самом деле не должно быть ui.helper.data('dropped', true);? - person maryisdead; 26.06.2014
comment
Я так думаю. В противном случае это всегда ложь. :) - person Drachenfels; 27.03.2015

Я вижу, что вы уже получили ответ; во всяком случае, у меня была такая же проблема сегодня, и я решил ее следующим образом:

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

Мне это было нужно, потому что я не мог изменить параметры своих перетаскиваемых элементов, поэтому мне приходилось работать только с выпадающими элементами (мне это было нужно внутри потрясающего Плагин FullCalendar). Я предполагаю, что у него могут быть некоторые проблемы с использованием «жадного» варианта droppables, но в большинстве случаев он должен работать.

PS: извините за мой плохой английский.

EDIT: Как и было предложено, я создал версию, используя jQuery.data; его можно найти здесь: jsfiddle.net/Polmonite/WZma9/

В любом случае документация jQuery.data говорит:

Обратите внимание, что этот метод в настоящее время не обеспечивает межплатформенную поддержку для установки данных в XML-документах, поскольку Internet Explorer не позволяет прикреплять данные через свойства Expando.

(это означает, что он не работает в IE до 8)

EDIT 2: Как отметил @Darin Peterson, предыдущий код не работает с более чем одной областью перетаскивания; это должно решить эту проблему: http://jsfiddle.net/Polmonite/XJCmM/

EDIT 3: Пример из EDIT 2 содержит ошибку. Если я перетащу "Перетащите меня!" в нижний выпадающий элемент, затем перетащите «Перетащите меня тоже» в верхний выпадающий элемент, а затем перетащите «Перетащите меня тоже» наружу, он предупреждает «Выпало внутрь!» Так что не используйте его.

EDIT 4: Как заметил @Aleksey Gor, пример в Edit 2 был неправильным; на самом деле, это был скорее пример, чтобы объяснить, как перебирать все перетаскиваемые/выпадающие элементы, но я на самом деле забыл удалить предупреждающие сообщения, так что это было довольно запутанно. здесь обновленная скрипта.

person Polmonite    schedule 23.10.2012
comment
Красиво и просто! Это хорошее решение, особенно когда у вас нет доступа к перетаскиваемым объектам. Теперь, размышляя о возможных проблемах с областью действия, мне было интересно, не могли бы вы использовать $("#droppable").data("outside", true); для более элегантного «переноса» состояния переменной? Хорошее решение, однако! Спасибо за ваш вклад! :) - person Chris Kempen; 24.10.2012
comment
Конечно. Я добавил версию с использованием jQuery.data в ответ;) В любом случае это означает отсутствие IE7 (если кому-то не все равно). - person Polmonite; 24.10.2012
comment
Великолепно! Спасибо за исследование и развернутый ответ! +1 - person Chris Kempen; 25.10.2012
comment
Это решение не будет работать, если у вас есть несколько удаленных местоположений. Например, страница, над которой я сейчас работаю, имеет много ячеек с возможностью перетаскивания, когда вы перетаскиваете одну ячейку, которую можно удалить, и переходите к новой ячейке, которая также может быть удалена, срабатывает out. Просто имейте в виду, что то, что срабатывает выход, не обязательно означает, что вы находитесь над областью, которую нельзя сбросить. - person Darin Peterson; 23.08.2013
comment
@Дарин Петерсон: это правда. В любом случае это можно легко исправить, перебирая области перетаскивания и ища каждый .data('outside'); например: jsfiddle.net/Polmonite/XJCmM . - person Polmonite; 04.09.2013

Попробуйте использовать событие "out" элемента droppable.

Это документация.

«Это событие запускается, когда принятый перетаскиваемый элемент вытаскивается (в пределах допуска) этого опускаемого элемента». Если я прав, это то, что вам нужно.

Также возможно создать наложение элемента на всю страницу. Если элемент удален, вы запускаете свое событие. Не лучший, но я думаю, единственный способ сделать это. Потому что вам нужен какой-то другой «выпадающий» элемент для запуска этих событий.

person ggzone    schedule 11.11.2011
comment
Эй, ggzone, спасибо за быстрый ответ... было бы идеально, если бы перетаскиваемый объект, который я перетаскивал, выходил из действительного выпадающего объекта. Если перетаскиваемый объект перетаскивается из исходного положения, а затем случайным образом отбрасывается куда-то далеко от легального дроппинга, то, насколько я знаю, это событие никогда не будет запущено! - person Chris Kempen; 11.11.2011
comment
Отлично, спасибо, ggzone ... как вы сказали, вероятно, не лучший, и если вы еще не видели ответ, предоставленный Люком, я думаю, что он предлагает гораздо более элегантное решение с теми же результатами! - person Chris Kempen; 11.11.2011

Преимущество следующего примера заключается в том, что вам не нужно ничего менять или знать о удаляемом коде:

Свойство перетаскиваемого возврата может иметь функцию (значение) {}. В качестве аргумента передается значение, указывающее, был ли вспомогательный элемент переброшен на элемент (элемент перетаскивания), или «false», если не переброшен на элемент (переброшен снаружи или не принят).

Примечание: вам нужно вернуть правильное логическое значение из этой функции возврата, чтобы указать помощнику возвращаться или нет (true/false). True означает да, верните помощника в исходное положение, двигая его назад в замедленном темпе (из коробки). False означает нет, просто резко удалите помощника. Установка свойства 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...
        }
    }
});

Вы даже можете вернуть true в функции возврата и вместо этого просто удалить помощника во время события остановки, в зависимости от значения данных («отброшено») с помощью ui.helper.remove(). Или вы могли бы даже взорвать его с помощью CSS3, если у вас все еще был плохой день;)

person Bogmag    schedule 07.07.2016

Я добавляю решение, которое я принял, так как вы можете легко понять это из классов CSS объекта, который вы перемещаете:

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

Старый вопрос и старые ответы означают, что это «может» быть новым решением. Вы (возможно) также хотели, как говорится в вопросе, знать, ЕСЛИ перетаскиваемый объект был удален за пределы отбрасываемого. Для меня, по крайней мере, в 95% случаев мне все равно, ЕСЛИ, я просто хочу, чтобы все вернулось к тому, что было, без каких-либо изменений, КОГДА это произойдет.

Установка revert в строку invalid обеспечивает желаемое поведение без какого-либо дополнительного кода или причудливых действий.

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

Опять же, он не скажет вам, «если он был выброшен за пределы выпадающего», но вернется в исходное состояние, если это произойдет.

person Chris Ostmo    schedule 25.07.2019