Saving Changes in jQuery Sortable to Backbone localStorage

The goal is to using jQuery Sortable to show models stored in localStorage and saving the sequence after changing.

Getting started


First is to define Model, Collection, View.

Define Model
1
2
3
4
5
6
7
8
9
10
11
12
var Content = Backbone.Model.extend({  
defaults: function () {
return {
text: "",
order: collection.nextOrder()
};
},
initialize: function () {
if (!this.get("text")) {
this.set({"text": "empty", "title": "empty"});
}
});
Define Collection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var ContentCollection = Backbone.Collection.extend({  
model: Content,
localStorage: new Backbone.LocalStorage("contentList"),
nextOrder: function(){
if (!this.length) return 0;
return this.last().get('order') + 1;
},

comparator: function(model) {
return model.get('order');
},

reOrder: function(){
this.each(function(model, index) {
if (model.get('order') !== index) {
model.save({ "order": index });
}
});
}
});

Note: the comparator is to sort models in collection

Define View
1
2
3
4
5
6
7
8
9
var ContentView = Backbone.View.extend({  
tagName: 'li',
template: _.template($('#searchTemplate').html()),
render: function() {
this.$el.html( this.template( this.model.toJSON() ) );
return this;
}

});

This is the view shows each single model

Define AppView
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var AppView = Backbone.View.extend({  
el: $("#contents"),
initialize: function(){
_.bindAll(this, 'add', 'addAll');
this.collection.bind('add', this.add);
this.collection.bind('reset', this.addAll);
this.listenTo(collection, 'sort', this.render);
this.collection.fetch();
},

render: function(){
$("#sortable").children().remove();
this.addAll();
return this;
},

add: function(model){
var view = new ContentView({model: model});
$("#sortable").append(view.render().el);
},

addAll: function(){
this.collection.each(this.add, this);
}
});
HTML part
1
2
3
4
5
<script type="text/template" id="searchTemplate">  
<div class="show-content">
<label><%- text %></label>
</div>
</script>

Setting up Sortable


Now initialise AppView and set up sortable.

1
2
var collection = new ContentCollection();  
var app = new AppView({collection: collection});

After this the whole page should be able to display models in content. Add models as you like.

Initialise sortable and trigger

1
2
3
4
5
6
7
$(document).ready(function() {  
$('#sortable').sortable({
stop: function (event, ui) {
ui.item.trigger('drop', ui.item.index());
}
});
});

This event is triggered when sorting has stopped, you can see official document here event-stop, it will trigger the item’s event ‘drop’. In this case, it’s ContentView, add the event in ContentView

1
2
3
4
5
6
7
events: {  
'drop': 'drop'
},

drop: function(event, index){
this.$el.trigger('update-sort', [this.model, index]);
}

Drop function also triggers an envent and passed 2 parameters, one is current dragged item, and the other is the position it dropped. In AppView we define

1
2
3
4
5
6
7
8
9
10
11
12
13
14
events: {  
'update-sort': 'updateSort'
},

updateSort: function(event, model, position){
this.collection.remove(model);
var previousIndex = model.get("order");
for(previousIndex ; previousIndex <= position ; previousIndex++){
this.collection.models[previousIndex].save({"order": previousIndex});
}
this.collection.add(model,{at: position});
this.collection.models[position].save({"order": position});
this.render();
}
Author

X,qUe

Posted on

2014-05-02

Licensed under

Comments