Advanced

Продвинутый Drag-and-Drop

В этой статье мы поговорим о расширенных возможностях drag-and-drop, о том, как сделать любой элемент перетаскиваемым, а также о контроле каждой стадии перетаскивания.

Если вашему проекту достаточно базового функционала drag-n-drop (напр. перетаскивание элементов в пределах одного или нескольких компонентов), читайте эту статью.

Синтаксис Drag-n-Drop

С помощью метода addDrag вы можете сделать элемент перетаскиваемым.

webix.DragControl.addDrag(node);

Related sample:  Drag-and-Drop from HTML

где node - ID или объект узла HTML (или сам объект).

Если вам необходимо указать какую-либо область, как доступную для сброса элемента, воспользуйтесь методом addDrop:

webix.DragControl.addDrop(node);

где node - ID или объект узла HTML (или сам объект).

Контролируемый drag-n-drop

Если вам необходимо контролировать стадии процесса перетаскивания, то к вызовам вышеперечисленных методов добавляется дополнительный параметр ($drag или $drop), который принимает функцию в качестве значения:

// для перетаскивания
webix.DragControl.addDrag(node, $drag:function(source, target, event){/*...*/});
 
// для сброса 
webix.DragControl.addDrop(node, $drop:function(source, target, event){/*...*/});

Функция-контроллер принимает 3 параметра:

  • source - исходный HTML объект
  • target - целевой HTML объект
  • event - нативное событие.

В примере ниже показано, как можно установить значение инпута путём перетаскивания записи из таблицы:

webix.DragControl.addDrop("mytext", {
    $drop:function(source, target, event){
        var dnd = webix.DragControl.getContext();
 
        // передаём название элемента в инпут
        target.value = dnd.from.getItem(dnd.source[0]).title; 
    }
});

Related sample:   Drag-and-Drop to HTML

Контекст drag-n-drop

Чтобы получить объект контекста, вызовите метод getContext() у модуля DragControl:

var state = webix.DragControl.getContext();

Контекст также доступен как параметр во всех событиях drag-n-drop:

state = {
    source:[1,2,3], // массив ID элементов, которые можно перетаскивать
    target:id, // ID перетаскиваемого элемента
    from:some_obj, // ссылка на исходный объект
    to:some_obj, // ссылка на целевой объект 
    x_offset:some_number, // позиция элемента относительно левого края
    y_offset:some_number, // позиция элемента относительно верхнего края
    start:id // необязательно; ID первого элемента, который перетащили 
}

Методы для контроля перетаскивания

У Webix есть несколько событий для контроля drag-n-drop. Эти события можно использовать при описании кастомного поведения элементов, участвующих в процессе перетаскивания.

События для перетаскивания элемента (drag):

  • $drag - вызывается, когда пользователь перетаскивает элемент
  • $dragCreate - вызывается после того, как пользователь начал перетаскивать элемент
  • $dragDestroy - вызывается после того, как пользователь перетащил элемент.

События для сброса элемента (drop):

  • $dragIn - вызывается, когда перетаскиваемый элемент находится над областью, доступной для сброса
  • $dragOut - вызывается, когда перетаскиваемый элемент покинул область, доступную для сброса
  • $drop - вызывается, когда пользователь сбрасывает перетаскиваемый элемент.
{
  $dragIn: function(source, target, event){ /*...*/ }, // элемент перетаскивают к потенциальной области для сброса 
  $dragOut: function(source, target, event){ /*...*/ },  // элемент перетаскивают из области
  $drop: function(source, target, event){ /*...*/ }, // пользователь бросил элемент
  $drag: function(source, target, event){ /*...*/ }, // пользователь начал перетаскивать элемент
  $dragCreate: function(from, event){ /*...*/ }  // операция начата
  $dragDestroy: function(from, html){ /*...*/ } // операции завершена
}

Где:

  • source - исходный HTML объект
  • target - целевой HTML объект
  • event - нативное событие
  • from - объект-контроллер (относится к исходному объекту)
  • html - содержимое маркера для перетаскивания.

Если вы переопределите любой из обработчиков onDrag, процесс больше не будет обрабатываться логикой по умолчанию. Код ожидает, что ваша кастомная логика возьмёт всю работу на себя.

Компонент-мастер для drag-n-drop

Мастер - это объект компонента с методами для контроля процесса drag-n-drop. Он определяет, как элемент будет вести в целевой области.

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

Для методов, где мастера для исходного и целевого объектов не указаны, вы можете получить их с помощью метода getMaster:

var source_master = webix.DragControl.getMaster(source);
var target_master = webix.DragControl.getMaster(target);

Интерфейсный drag-n-drop

С помощью нижеперечисленных интерфейсов вы можете сделать элемент перетаскиваемым:

Низкоуровневый интерфейс. Компонент, который наследует этот интерфейс становится перетаскиваемым (о том, как наследовать от интерфейса читайте в этой статье).

Высокоуровневый интерфейс. Добавляет возможность перетаскивания компоненту, у которого есть DataStore (о том, как наследовать от интерфейса читайте в этой статье)

Примеры использования

Перетаскивание из кастомного HTML

<div package="DragPackage" version="1.0" maintainer="Webix Team" 
    id="drag_1" 
    style='width:150px; height:50px; color:white; background-color:navy;'>
    Перетащи меня в dataview
</div>
webix.DragControl.addDrag("drag_1");
data1.attachEvent("onBeforeDrop",function(context){
    if (context.from == webix.DragControl){
        this.add({
            Package:context.source.getAttribute("package"),
            Version:context.source.getAttribute("version"),
            Maintainer:context.source.getAttribute("maintainer")
        }), this.getIndexById(context.target || this.getFirstId());
        return false;
    }
    return true;
});

Перетаскивание в кастомного HTML

<div id="data_container2" style="width:400px;height:396px;border:1px solid red;">
    Сбрось меня здесь
</div>
webix.DragControl.addDrop("data_container2",{
    $drop:function(source, target, e){
        var context = webix.DragControl.getContext();
        var item = context.from.getItem(context.source[0]);
 
        var d = document.createElement("DIV");
        d.innerHTML = item.Package+" - "+item.Version;
        target.appendChild(d);
    }
});
Наверх