Skip to content

Instantly share code, notes, and snippets.

@itmammoth
Last active May 17, 2018 03:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save itmammoth/6a6672095ff8f3477aa34cde9f624b88 to your computer and use it in GitHub Desktop.
Save itmammoth/6a6672095ff8f3477aa34cde9f624b88 to your computer and use it in GitHub Desktop.
A jQuery plugin over jQueryUI sortable that arranges Backbone.Collection and item views as the html list are
/**
* $.backboneSortable
*/
(function(){
var methods = {
init: function(options) {
var settings = $.extend({
// defaults
}, options);
return this.each(function() {
var $this = $(this);
var backboneSortable = new BackboneSortable($this, $.extend({}, settings, $this.data()));
backboneSortable.sortable();
$this.data('plugin_backbone_sortable', backboneSortable);
});
},
};
$.fn.backboneSortable = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.backboneSortable');
}
};
/**
* BackboneSortable class
*/
var BackboneSortable = (function() {
var NAMESPACE = '.backboneSortable';
var BackboneSortable = function($el, settings) {
this.$el = $el;
this.settings = settings;
};
// instance methods
$.extend(BackboneSortable.prototype, {
sortable: function() {
var that = this;
var fromIndex;
this.$el.sortable($.extend({}, this.settings, {
start: function(e, ui) {
fromIndex = ui.item.index();
that._delegate('start', e, ui);
},
update: function(e, ui) {
var toIndex = ui.item.index();
// Move a view
var view = that.settings.backboneViews.splice(fromIndex, 1)[0];
that.settings.backboneViews.splice(toIndex, 0, view);
// Move a model
that.settings.backboneCollection.remove(view.model, { silent: true });
that.settings.backboneCollection.add(view.model, { at: toIndex, silent: true });
that.settings.backboneCollection.trigger('sort' + NAMESPACE,
that.settings.backboneCollection,
{ model: view.model, from: fromIndex, to: toIndex });
that._delegate('update', e, ui);
},
}));
},
_delegate: function(funcName, e, ui) {
var f = this.settings[funcName];
if (typeof f === 'function') {
f.call(this.$el, e, ui);
}
},
});
return BackboneSortable;
})();
})();
var CollectionView = Backbone.View.extend({
tagName: 'ul',
initialize: function(options) {
this.listenTo(this.collection, 'sort.backboneSortable', function(collection, options) {
console.log('model moved', options.from, '->', options.to, options.model);
});
},
render: function() {
this.itemViews = [];
var that = this;
this.collection.each(function(model) {
that.add(model);
});
this.$el.backboneSortable({
backboneCollection: this.collection,
backboneViews: this.itemViews,
update: function(e, ui) {
// Both the collection and the views have been updated as they are
console.log(that.collection.pluck('name'), _.pluck(that.itemViews, 'cid'));
console.log(this.sortable('toArray'));
},
});
return this;
},
add: function(model) {
var itemView = new ItemView({ model: model });
this.$el.append(itemView.render().el);
this.itemViews.push(itemView);
},
});
var ItemView = Backbone.View.extend({
tagName: 'li',
render: function() {
this.$el
.text(this.model.get('name') + ' - ' + this.cid)
.attr('id', this.model.id);
return this;
},
});
var collection = new Backbone.Collection([
new Backbone.Model({ id: 'J', name: 'John' }),
new Backbone.Model({ id: 'S', name: 'Sarah' }),
new Backbone.Model({ id: 'A', name: 'Andrew' }),
]);
var collectionView = new CollectionView({ collection: collection });
$('body').append(collectionView.render().el);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment