Подтвердить что ты не робот

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

Мои извинения, если на этот вопрос был дан ответ в другом вопросе, я не смог найти ответ, свойственный моей проблеме!

Я пытаюсь проверить, не перетаскивается ли jQuery перетаскиваемый за пределы юридического droppable. Обычно это можно решить в 90% случаев, возвращая перетаскиваемый, но я не хочу этого делать. Вместо этого я хочу сделать одно, если draggable будет сброшен на droppable (отлично работает!) И что-то еще, если оно будет сброшено за пределы всех возможных droppables (в настоящее время становится лучше меня!).

В двух словах:

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

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

4b9b3361

Ответ 1

Поскольку событие droppable drop срабатывает перед перетаскиваемым событием 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...
    }
});

Ответ 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!');
        }
    }
});

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

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

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

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

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

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

РЕДАКТИРОВАТЬ 2: Как отметил @Darin Peterson, предыдущий код не работает с более чем одной областью drop; это должно исправить эту проблему: http://jsfiddle.net/Polmonite/XJCmM/

РЕДАКТИРОВАТЬ 3: Пример из EDIT 2 имеет ошибку. Если я перетащил "Перетащи меня!" в нижней части, затем отбросьте "Перетащите меня слишком" в верхнюю отбрасываемую, а затем отбросьте "Перетащить меня тоже" на улицу, он оповещает "Бросил внутрь!". Поэтому не используйте его.

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

Ответ 3

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

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

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

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

Ответ 4

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

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

Примечание: вам нужно вернуть правильное значение bool из этого revert-function, чтобы сообщить помощнику о возврате или нет (Истина/ложь). Истинный означает "да", вернуть помощника в исходное положение, перемещая его назад в замедленном режиме (из коробки). False означает нет, просто удалите помощника ненормально. Установка свойства revert на "invalid", является ярлыком сказать

  • 'да, если вы сбросили на улицу, а затем верните помощник
  • 'нет, если он выпадет на элемент сбрасываемым и принят, а затем немедленно удалите помощника.

Я предполагаю, что вы можете добавить текущий помощник 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...
        }
    }
});

Вы можете даже вернуть значение true в функции возврата и просто удалить помощника во время события остановки, в зависимости от значения данных ( "отброшен" ) с помощью ui.helper.remove(). Или вы даже можете взорвать его с помощью 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
    }
});

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