Достаточно распространенная задача — поменять местами элементы в списке. Но как правило эта задача решается жуткими костылями, особенно если это Drag&Drop.
Сейчас я расскажу вам очень простой и гибкий способ сделать это, используя Marionette.js и jQuery UI Sortable.
Подключаем jQuery UI
Из jQuery UI нам потребуется только часть Sortable, поэтому, экономии трафика ради, я смело снял за вас все ненужные галочки отсюда. Вам осталось только загрузить.
Обратите внимание
В коде ниже используется ссылка на Marionette
var Marionette=Backbone.Marionette;
Создаем шаблон поведения
Данную функциональность мы реализуем в виде Behavior, о котором я писал ранее.
Вот код поведения, который будет отвечать за возможность сортировки моделей внутри коллекции
Behaviors.Sortable=Marionette.Behavior.extend({
onRender:function(){
var collection=this.view.collection // Замыкаем коллекцию
,items=this.view.children._views // Получаем список дочерних элементов
,view
;
for(var v in items){
view=items[v]
view.$el.attr('data-backbone-cid',view.model.cid); // Привязываем элемент к модели по cid
}
this.$el.sortable({ // Делаем список сортируемым
axis: this.options.axis||false,
grid: this.options.grid||false,
containment: this.options.containment||false,
cursor: "move",
handle:this.options.handle||false,
revert: this.options.revert||false,
update: function( event, ui ) {
var model=collection.get(ui.item.data('backbone-cid'));
// Получаем привязанную модель
collection.remove(model,{silent:true});
// По-тихому удаляем её из коллекции
collection.add(model,{at:ui.item.index(),silent:true});
//И также втихаря добавляем её по нужному индексу
}
});
}
});
Что это?
Этот шаблон поведения предназначен для CollectionView. Он дожидается события onRender, после чего привязывает каждый элемент ItemView к его модели с помощью cid.
Потом мы разрешаем этому списку сортироваться с помощью Drag&Drop используя jQuery.
Опции Sortable
Для каждого вида можно передавать свой набор опций, подробнее можно прочитать в документации jQuery UI. В представленном выше коде реализованы не все возможные опции, вы можете добавить свои по желанию.
Сортировка
Когда один из элементов перетащили, мы удаляем привязанную к этому элементу по сid модель из коллекции и добавляем заново по нужному индексу. Флаги silent:true нужны, что бы Marionette.js не пыталась переставить все по-своему, у неё это плохо получается.
Соединяем СollectionView и Behavior
Теперь применим это в действии
var IView=Marionette.ItemView.extend({// Создаем стандартный ItemView
template:'#item-template'
})
var CView=Marionette.CollectionView.extend({// Создаем CollectionView
itemView:IView,
behaviors: {// вот тут творится вся магия.
Sortable:{// Применяем поведение Sortable к данному виду.
//В качестве примера я передал параметр containment
containment:'parent' // Теперь перетаскивать элементы мы можем только внутри родительского контейнера.
}
}
})
Теперь вы с помощью одной строчки behaviors: {Sortable:{}} можете добавить возможность Drag&Drop сортировки CollectionView.
Как сохранить это на сервер?
Я не знаю в каком виде на сервере у вас хранится порядок сортировки, но с помощью описанного выше подхода вы сможете передать порядок в любом формате.
Я использую MongoDB, поэтому без особых проблем с помощью сollection.toJSON() отправляю это на сервер Node.JS и сохраняю как есть.
Можно отправить на сервер упорядоченный массив id, получить который можно с помощью
collection.pluck('id');
Вот и всё
enjoy it works!
Надеюсь статья вам помогла.
Пожалуйста, пишите в комментариях о чем вам хотелось бы ещё почитать.
Автор: pharrell