2015-08-10 4 views
3

У меня есть перетаскиваемые li элементов, вложенных в ul, в свою очередь, вложенных в div, как показано ниже:Делегирования Draggable События Родителя Элементы

<div class='group'> 
    <div class='header'> 
    // some stuff here 
    </div> 
    <ul> 
     <li draggable='true'> 
     Stuff I want to drag and drop to another div.group 
     </li> 
    </ul> 
    </div> 

Есть несколько из этих div элементов, и я пытаюсь реализовать drag & функция перетаскивания для перемещения li элементов одной группы div в другую.

Я подключил ondragenter, ondragleave обратные вызовы здесь:

// controller using mithril.js 
    ctrl.onDragLeave = function() { 
     return function (event) { 
      var target; 
      // Using isDropzone to recursively search for the appropriate div.group 
      // parent element, as event.target is always the children inside it 
      if ((target = isDropzone(event.target)) != null) { 
       target.style.background = ""; 
      } 
     } 
    }; 
    ctrl.onDragEnter = function() { 
     return function (event) { 
      var target; 
      if ((target = isDropzone(event.target)) != null) { 
       target.style.background = "purple"; 
      } 
     }; 
    }; 
    function isDropzone(elem){ 
     if(elem == null){ 
      return null; 
     } 
     return elem.className == 'group' ? elem: isDropzone(elem.parentNode) 
    } 

Проблема возникает, когда event.target обратных вызовов всегда являются вложенные дочерние элементы внутри div, такие как li, и, таким образом, обратные вызовы являются постоянно стреляли. В этом случае я меняю цвет div.group с моими обратными вызовами, в результате чего нежелательно моргает div.group.

Есть ли способ делегировать события и разрешить только родителям divli для обработки событий? Или любой другой способ обойти это?

EDIT: Хотелось бы узнать, есть ли способ сделать это, но сейчас я использую обходной путь, который нашел here.

+0

Где вы прикрепляли эти обработчики? –

ответ

0

Таким образом, это будет соответствовать категории ответов «вам нужно подойти под другим углом».

Избегайте - насколько это возможно - манипулируйте DOM с event.target/event.currentTarget в ваших подключенных обработчиках.

Пара вещей по-разному:

  1. Ваш ondragleave и ondragenter обработчики должны просто установить некоторые соответствующие «состояние» атрибуты в контроллере/ViewModel/магазины

  2. Когда обработчик будет решена, это вообще запускает перерисовку в Мифриле. Внутренне m.startComputation() начинается, ваш обработчик называется, затем m.endComputation()

  3. Ваша «функция просмотра» снова запускается. Затем он отражает измененные модели. Ваши действия не меняют представления, ваши взгляды вызывают действия, которые влияют на модели, а затем реагируют на эти изменения. MVC, не MVVM


Модель

В контроллере, создать модель, которая отслеживает все состояния, Вы должны показать свое перетаскивание UI

ctrl.dragging = m.prop(null) 

ctrl.groups = m.prop([ 
    { 
    name: 'Group A', 
    dragOver: false, 
    items: ['Draggable One', 'Draggable Two'] 
    }, 
    ... 
    // same structure for all groups 
]) 

Вид

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


return ctrl.groups.map(function (group, groupIdx) { 
    return m('.group',[ 
    m('.header', group.name), 
    m('ul', 
     { 
     style: { background: (group.dragOver ? 'blue' : '')}, 
     ondragleave: function() {ctrl.handleDragLeave(groupIdx)}, 
     ondragenter: function() {ctrl.handleDragEnter(groupIdx)}, 
     ondrop: function() {ctrl.handleDrop(groupIdx)}, 
     ondragover: function (e) {e.preventDefault()} 
     }, 
     group.items.map(function (item, itemIdx) { 
     return m('li', 
      { 
      draggable: true, 
      ondragstart: function() {ctrl.handleDragStart(itemIdx, groupIdx)} 
      }, 
      item 
     }) 
    ) 
    ]) 
}) 

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

Контроллер

Ваш контроллер поэтому может иметь обработчик, которые имеют всю информацию от действий, необходимых для обновления модели.

Вот что некоторые обработчики на контроллере будет выглядеть следующим образом:

ctrl.handleDragStart = function (itemIdx, groupIdx) { 
    ctrl.dragging({itemIdx: itemIdx, groupIdx: groupIdx}) 
} 

ctrl.handleDragEnter = function (groupIdx) { 
    ctrl.groups()[groupIdx].dragOver = true 
} 

ctrl.handleDragLeave = function (groupIdx) { 
    ctrl.groups()[groupIdx].dragOver = false 
} 

ctrl.handleDrop = function (toGroupIdx) { 
    var groupIdx = ctrl.dragging().groupIdx 
    var itemIdx = ctrl.dragging().itemIdx 
    var dropped = ctrl.groups()[groupIdx].items.splice(itemIdx, 1)[0] 

    ctrl.groups()[toGroupIdx].items.push(dropped) 
    ctrl.groups()[toGroupIdx].dragOver = false 
    ctrl.dragging(null) 
} 

Попробуйте придерживаться обработчиков событий MVC модель MITHRIL призывают действия на контроллере, который манипулирует модели. Затем представление реагирует на изменения этих моделей. Это обходит необходимость запутываться со спецификой событий DOM.

Вот полный пример JSbin показывая, что вы пытаетесь добраться до:

https://jsbin.com/pabehuj/edit?js,console,output

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

Кроме того, обратите внимание, что в JSbin, в ondragenter обработчик:

ondragenter: function() { 
    if (ctrl.dragging().groupIdx !== groupIdx) { 
    ctrl.handleDragEnter(groupIdx) 
    } 
} 

Это так Droppable область не меняет цвет на свой собственный перетаскиваемым, что одна из вещей, которые я думаю, вы в вашем ответе.

 Смежные вопросы

  • Нет связанных вопросов^_^