Предотвратить событие перетаскивания для распространения на родительский объект, если внутренний объект сброса не принимает перетаскиваемое - PullRequest
1 голос
/ 08 августа 2011

У меня есть буква div#space и коллекция перетаскиваемых li.element. Когда я перетаскиваю li.element в div#space, создается новый ul.group, li.element добавляется к ul.group и, наконец, ul.group становится сбрасываемым.

Дано

Я бы хотел, чтобы эти элементы вели себя следующим образом:

  1. когда li.element опущен в ul.group, который не содержит , li.element будет добавлен к ul.group
  2. когда li.element сбрасывается в ul.group, который содержит , li.element возвращается в исходное положение
  3. когда li.element отбрасывается в div#space (за пределами ul.group), создается новая группа, как упоминалось выше.

Проблема в том, что когда элемент сбрасывается на ul.group, который не принимает его, родительский элемент div#space перехватит событие и создаст новую группу.

У ul.grpup есть функция accept , которая проверяет, является ли сбрасываемый элемент элементом и не был ли он отброшен.

newULGroup.droppable({
    drop: ...
    accept: function(ui)
    {
        var isElement = ui.hasClass('element')
        var elementId = '.' + ui.data().id
        var isAlreadyPresent = $(this).find(elementId).length > 0
        return isElement && (!isAlreadyPresent)
    },
    greedy: true
});

Как бы вы реализовали это поведение, если бы не принимали все и игнорировали вещи в обработчике отбрасывания? (Я не пробовал, но думаю, что это сработало бы)


Редактировать

Попытка это исправить

Я исправил jquery-ui-1.8.4.js, чтобы передать событие в функцию accept. Теперь я могу остановить распространение с помощью $(event).stopPropagation(), но мне нужно анимировать вручную перетаскиваемого помощника обратно в исходное положение, чтобы смоделировать возврат, а затем удалить его из домена.

accept: function(ui, event)
{
    var isCriteria = ui.hasClass('criteria')
    var criteriaId = '.' + ui.data().id
    var isAlreadyPresent = $(this).find(criteriaId).length > 0
    var accepted = isCriteria && (!isAlreadyPresent)
    if (event && !accepted)
    {
        $(event.target).animate(ui.offset(), {complete: function() {$(this).remove()}})
        $(event).stopPropagation()
    }
    return accepted
}

К сожалению, это, похоже, разрушает поведение draggable из исходного элемента. Почему, о, почему?

1 Ответ

1 голос
/ 14 ноября 2011

Мне удалось добиться подобного поведения, хотя я использовал недокументированную функцию jQuery.ui.

Если вы посмотрите на реализацию jquery.ui.draggable (по крайней мере для v1.8.16), опция revert также может быть функцией. Он имеет this как перетаскиваемый элемент, единственный параметр - это буксируемое лицо, принявшее перетаскивание, а возвращаемое значение - boolean, чтобы указать, следует ли вернуть перетаскиваемый элемент или нет.

Так что в вашем случае вам нужно

  1. пусть ваши div#space и ul.group всегда принимают капли и будут жадными
  2. выполните проверку в обработчике ul.group drop и обрабатывает элемент, только если он еще не находится в группе
  3. выполните аналогичную проверку в перетаскиваемой функции revert и вернитесь, если она уже находится в группе.
...