Drag-and-Drop в пользовательском интерфейсе Webix

Еще совсем недавно функциональность drag-and-drop довольно редко использовалась в веб-приложениях. С появлением HTML5 нативный drag-and-drop стал популярным и легко доступным. Функциональность, которая ранее требовала много усилий при написании кода, теперь может быть добавлена с использованием всего нескольких строк HTML-кода. Разрабатывая библиотеку Webix, мы старались сохранить все функции и преимущества нативного drag-and-drop. В то же время,были добавлены новые возможности, которые будут полезными в разработке веб-приложений.

Drag-and-Drop компонентного уровня

В то время, как drag-and-drop в HTML5 фокусируется на HTML-элементе, drag-and-drop в Webix сконцентрирован на UI-компонентах. Например, попробуйте перетянуть элементы между Tree и DataTable в демо ниже:

Все UI-компоненты Webix поддерживают функциональность drag-and-drop. С помощью всего одной строки кода вы можете использовать функцию перетаскивания для таких компонентов, как List, DataTable, Tree, TreeTable и DataView.

webix.ui({
    view:"list",
    drag:true
});

Если у вас на странице есть 2 компонента, для которых разрешена операция “перетаскивания”, (свойство drag установлено как “true”), вы можете перетягивать элементы между этими компонентами. При этом, неважно, какие это компоненты, вы можете перетягивать строки из Grid вTree или из TreeTable в List и так далее.
Такой неограниченный drag-and-drop едва ли полезен. Поэтому Webix позволяет задавать роли компонентов, используя то же свойство “drag”.

webix.ui({
    view:"tree",
    drag:"source"
});

webix.ui({
    view:"datatable",
    drag:"target"
});

Такая инициализация делает возможным операцию “перетаскивания” только из Tree в DataTable (из компонента, указанного как drag:”source”, в компонент, заданный как drag:”target”).

Еще один вариант использования drag-and-drop – это изменение порядка элементов (строк, узлов дерева, элементов списка и т.д.) внутри одного компонента. У Webix есть готовая модель для этой операции:

webix.ui({
  view:"list",
  drag:"order"
});

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

Drag-and-Drop HTML-уровня

Несмотря на то, что Webix — компонентно-ориентированная библиотека, она также поддерживает drag-and-drop для кастомных HTML-элементов. Это обеспечивает дополнительную гибкость, поскольку вы можете использовать Webix Drag-and-Drop со своим собственным HTML-контентом или с какой-либо сторонней библиотекой.

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

Для того чтобы в любой HTML элемент можно было перетащить элемент Webix компонента, достаточно написать что-то вроде:

<input type="text" id="mytext">
    <script>
        webix.DragControl.addDrop("mytext");
    </script>

В реальном приложении нам нужно определить, какие данные перетаскиваемого объекта отобразятся в поле ввода, поэтому понадобится немного больше кода:

webix.DragControl.addDrop("mytext", {
    $drop:function(source, target, event){
        var dnd = webix.DragControl.getContext();
        target.value = dnd.from.getItem(dnd.source[0]).title;
    }
})

Как видите, это тот же код, но мы добавили функцию для обработки дропа ($drop), которая который задает логику отображения данных.

Перетаскивание HTML-элемента в компонент Webix реализуется похожим образом:

<div id="divA" style='float:left; padding:20px; background-color:#dff;'> A </div>
<script>
    webix.DragControl.addDrag("divA");
</script>

Чтобы правильно провести drag-and-drop операцию, нам нужно задать обработчик события onBeforeDrop для компонента Webix:

webix.ui({
    view:"datatable",
    on:{
        onBeforeDrop:function(context, e){
            this.getItem(context.target).title = context.source.innerHTML;
            this.refresh(context.target);
            return false;
        }
    }
});

Теперь, попробуйте перетянуть любой из цветных блоков в DataTable на демо ниже. Содержимое блока появится в строке грида.

A
B
C

Нативный HTML5 Drag-and-Drop

Все представленные выше примеры используют свою логику для реализации drag-and-drop. В то же время можно использовать библиотеку Webix вместе с нативным HTML5 drag-and-drop.

Для создания HTML5 элемента, который можно перетаскивать, понадобится следующий код:

<div draggable="true" ondragstart="drag(event)" > A </div>
<script type="text/javascript" charset="utf-8">
function drag(ev){
    ev.dataTransfer.setData("title",ev.target.innerHTML);
}
</script>

Чтобы перетащить такой HTML элемент в Webix компонент, можно использовать следующий код для этого компонента:

var mygrid = webix.ui{
  view:"datatable",
};

webix.event(mygrid.$view, "dragover", function(e){ e.preventDefault(); });
webix.event(mygrid.$view, "drop", function(e){
   var grid = $$(e);
   var id = grid.locate(e);
  grid.getItem(id).title = e.dataTransfer.getData("title");
  grid.refresh(id);
});

С помощью этого кода мы:

  • создаем DataTable компонент Webix;
  • задаём обработчик событию dragover, чтобы разрешить перетаскивание в область грида;
  • задаём обработчик событию drop, в котором определяем то, как данные перетаскиваемого элемента будут использованы в гриде

В результате, любой HTML элемент может быть перетянут в WebixDataTable. Подобным образом мы можем комбинировать любые существующие drag-and-drop решения, основанные на HTML5 и Drag-and-Drop функциональности Webix.

Заключение

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

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