Last active
October 13, 2015 15:38
-
-
Save craigmaslowski/4218205 to your computer and use it in GitHub Desktop.
Backbone Mixins
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (Mixins) { | |
Mixins.BootStrapModal = { | |
show: function () { | |
var self = this; | |
if (self.preShow) | |
self.preShow(); | |
// TODO - Review CSS to make it more generic | |
self.$el.modal().css({ | |
width: 'auto', | |
'margin-left': function () { | |
return -(self.$el.width() / 2); | |
} | |
}); | |
if (self.postShow) | |
self.postShow(); | |
}, | |
hide: function () { | |
if (this.preHide) | |
this.preHide(); | |
this.$el.modal('hide'); | |
if (this.postHide) | |
this.postHide(); | |
} | |
}; | |
})(module('Mixins')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
BackboneMixins.DestroyableView = { | |
destroy: function () { | |
if (Backbone.Validation) Backbone.Validation.unbind(this); | |
this.undelegateEvents(); | |
this.$el.removeData().unbind(); | |
this.remove(); | |
Backbone.View.prototype.remove.call(this); | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (Mixins) { | |
Mixins.FocusForm = { | |
postInitialize: function () { | |
if (this.options.firstInput) this.firstInput = this.options.firstInput; | |
if (this.firstInput && !this.firstInput.skipFocusOnInit) { | |
this.focus(); | |
} | |
}, | |
focus: function () { | |
if (this.firstInput) { | |
if (typeof this.firstInput === 'string') { | |
this.firstInput = { selector: this.firstInput }; | |
} | |
var input = this.$(this.firstInput.selector); | |
if (input.is(':visible')) { | |
var select2Data = input.data('select2'); | |
if (select2Data) { | |
$(select2Data.containerSelector).find('input.select2-focusser').focus(); | |
// select2 likes to apply the active class to too many containers. | |
// sanity check to remove it and make sure only the one we want has it. | |
//$('.select2-container').removeClass('.select2-container-active'); | |
//$('s2id_' + input.attr('id')).addClass('.select2-container-active'); | |
} else { | |
if (input.val()) { | |
input.select(); | |
} | |
input.focus(); | |
} | |
} | |
} | |
} | |
}; | |
if (Backbone.View.prototype.stickit) { | |
var originalStickit = Backbone.View.prototype.stickit; | |
Backbone.View.prototype.stickit = function () { | |
originalStickit.apply(this, arguments); | |
if (this.firstInput && !this.firstInput.skipFocusOnStickit && this.focus) { | |
this.focus(); | |
} | |
}; | |
} | |
})(module('Mixins')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (Mixins) { | |
Mixins.Formatters = { | |
formatDate: function (val, options) { | |
return moment(new Date(val)).format('MM/DD/YYYY'); | |
} | |
}; | |
})(module('Mixins')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (Mixins) { | |
Mixins.ListItemFormView = { | |
events: { | |
'click .save': 'completeEdit', | |
'click .cancel': 'cancel', | |
}, | |
initialize: function () { | |
if (this.options.template) { | |
this.template = _.isFunction(this.options.template) | |
? this.options.template | |
: _.template($(this.options.template).html()); | |
} else if (this.template) { | |
this.template = _.isFunction(this.template) | |
? this.template | |
: _.template($(this.template).html()); | |
} | |
this.originalAttributes = this.model.toJSON(); | |
this.render(); | |
}, | |
render: function () { | |
this.$el.empty().html(this.template(this.model.attributes)); | |
this.$('.dropdown-select2').select2(); | |
this.$('.date-picker').datepicker(); | |
this.stickit(); | |
}, | |
completeEdit: function (e) { | |
e.preventDefault(); | |
this.trigger('edit.complete'); | |
}, | |
cancel: function (e) { | |
this.model.set(this.originalAttributes); | |
this.completeEdit(e); | |
} | |
}; | |
})(module('Mixins')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (Mixins) { | |
Mixins.ListItemView = { | |
tagName: 'tr', | |
highlightClass: 'warning', | |
inEditMode: false, | |
events: { | |
'click .edit': 'edit', | |
'click .remove': 'removeItem', | |
}, | |
initialize: function () { | |
_.bindAll(this); | |
if (this.options.template) { | |
this.template = _.isFunction(this.options.template) | |
? this.options.template | |
: _.template($(this.options.template).html()); | |
} else if (this.template) { | |
this.template = _.isFunction(this.template) | |
? this.template | |
: _.template($(this.template).html()); | |
} | |
if (this.options.formView) { | |
this.formView = this.options.formView; | |
} | |
if (this.options.highlightClass) { | |
this.highlightClass = this.option.highlightClass; | |
} | |
this.listenTo(this.model, 'destroy', this.destroy); | |
this.listenTo(this.model.collection, 'reset', this.destroy); | |
this.bindSubscriptions(); | |
}, | |
render: function () { | |
if (!this.inEditMode) { | |
if (!this.template) | |
throw new Backbone.Error('The template must be specified.', this); | |
this.$el.empty().append(this.template(this.model.attributes)); | |
this.delegateEvents(); | |
if (this.bindings) { | |
this.stickit(); | |
} | |
return this; | |
} | |
}, | |
edit: function (e) { | |
e.preventDefault(); | |
if (!this.formView) | |
throw new Backbone.Error('The formView must be specified.', this); | |
this.$el.addClass(this.highlightClass); | |
this.form = new this.formView({ | |
el: this.$el, | |
model: this.model | |
}); | |
this.inEditMode = true; | |
this.listenTo(this.form, 'edit.complete', this.completeEdit); | |
}, | |
completeEdit: function () { | |
this.stopListening(this.form); | |
this.form.destroy('soft'); | |
this.form = undefined; | |
this.inEditMode = false; | |
this.render(); | |
this.$el.removeClass(this.highlightClass); | |
}, | |
removeItem: function (e) { | |
e.preventDefault(); | |
this.$el.addClass(this.highlightClass); | |
if (confirm('Remove this item?')) { | |
this.model.destroy(); | |
} else { | |
this.$el.removeClass(this.highlightClass); | |
} | |
} | |
}; | |
})(module('Mixins')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (Mixins) { | |
// usage: | |
// var MyListView = Backbone.View.extend({ | |
// listItemView: MyListItemView, | |
// | |
// // optional: Causes the list to be hidden if there are no records in the collection. | |
// autoHide: true, | |
// | |
// // optional: Causes list item views to be appended to this.$(this.containerSelector) instead of this.$el | |
// // This is useful for setting $el to a table and appending to the tbody | |
// containerSelector: 'tbody', | |
// }); | |
// | |
// Backbone.mixin(MyView, ListView); | |
Mixins.ListView = { | |
_itemViews: [], | |
initialize: function () { | |
if (!this.collection) { | |
throw new Backbone.Error('ListView: A collection must be specified', this); | |
} | |
this.listenTo(this.collection, 'remove', this.setVisibility); | |
this.listenTo(this.collection, 'reset', this.setVisibility); | |
this.listenTo(this.collection, 'reset', this.render); | |
this.listenTo(this.collection, 'add', this.renderItem); | |
this.setVisibility(); | |
}, | |
render: function () { | |
var self = this; | |
if (this.containerSelector) { | |
this.$(this.containerSelector).empty(); | |
} else { | |
this.$el.empty(); | |
} | |
self.collection.each(function (model) { | |
self.renderItem(model); | |
}); | |
}, | |
renderItem: function (model) { | |
if (!this.listItemView) throw new Backbone.Error('listItemView property must be set.', this); | |
var view = new this.listItemView({ | |
model: model | |
}); | |
this._itemViews.push(view); | |
if (this.containerSelector) { | |
this.$(this.containerSelector).append(view.render().el); | |
} else { | |
this.$el.append(view.render().el); | |
} | |
this.setVisibility(); | |
}, | |
setVisibility: function () { | |
if (this.autoHide) { | |
if (this.collection.length === 0) { | |
this.$el.hide(); | |
} else { | |
this.$el.show(); | |
} | |
} | |
}, | |
remove: function () { | |
_.each(this._itemViews, function (view) { | |
view.remove(); | |
}); | |
Backbone.View.prototype.remove.call(this); | |
} | |
}; | |
})(module('Mixins')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
BackboneMixins.Subscriber = { | |
bindSubscriptions: function () { | |
var self = this; | |
self._subscriptions = []; | |
if (self.subscriptions) { | |
_.each(self.subscriptions, function (subscription) { | |
var handler = _.isFunction(subscription.handler) | |
? subscription.handler | |
: self[subscription.handler]; | |
self._subscriptions.push( | |
app.broker.channel( | |
subscription.channel, | |
subscription.topic) | |
.subscribe(handler) | |
); | |
}); | |
} | |
}, | |
unbindSubscriptions: function () { | |
var self = this; | |
_.each(self._subscriptions, function (subscription) { | |
subscription.unsubscribe(); | |
}); | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
BackboneMixins.SlickgridCollection = { | |
setGrid: function (grid) { | |
var self = this; | |
this.grid = grid; | |
this.setGridData(); | |
this.grid.onCellChange.subscribe(function (event, args) { | |
var modelToUpdate; | |
modelToUpdate = args.item.id != null ? self.get(args.item.id) : self.getByCid(args.item.cid); | |
modelToUpdate.set(args.item); | |
}); | |
this.grid.onAddNewRow.subscribe(function (event, args) { | |
self.add(args.item); | |
}); | |
this.grid.onSort.subscribe(function (event, args) { | |
var sortType; | |
sortType = args.sortCol.sortType || 'string'; | |
self.comparator = self.comparatorDefinitions[sortType](self, args.sortCol.field, args.sortAsc); | |
self.sort(); | |
self.comparator = null; | |
}); | |
this.bind('add', function (model) { | |
self.grid.updateRowCount(); | |
self.grid.invalidateRow(self.length - 1); | |
self.grid.render(); | |
}); | |
this.bind('change', function (model) { | |
self.grid.invalidateRow(self.indexOf(model)); | |
self.grid.render(); | |
}); | |
this.bind('remove', function (model) { | |
self.grid.updateRowCount(); | |
self.grid.render(); | |
}); | |
this.bind('reset', function (model) { | |
self.setGridData(); | |
}); | |
}, | |
setGridData: function () { | |
this.grid.setData(this); | |
this.grid.invalidate(); | |
}, | |
getItem: function (index) { | |
var attrs, model; | |
model = this.at(index); | |
if (model != null) { | |
attrs = model.toJSON(); | |
attrs.cid = model.cid; | |
} | |
return attrs; | |
}, | |
comparatorDefinitions: { | |
number: function (collection, field, sortAsc) { | |
return function (model) { | |
var val; | |
val = Number(model.get(field)); | |
if (sortAsc) { | |
return val; | |
} else { | |
return -val; | |
} | |
}; | |
}, | |
string: function (collection, field, sortAsc) { | |
return function (model) { | |
var fieldValue; | |
fieldValue = model.get(field); | |
if (sortAsc) { | |
return fieldValue; | |
} else { | |
return -(collection.sortedIndex(model, function (m) { | |
return m.get(field); | |
})); | |
} | |
}; | |
} | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (Mixins) { | |
// TODO - Document and make this a bit more generic | |
Mixins.TabManager = { | |
// list of backbone views. one for each tab. key corresponds to value in the data-tab attr on the trigger. (eg data-tab="priceList" corresponds to tabs.priceList) | |
tabs: {}, | |
events: { | |
'click .tab': 'changePane' | |
}, | |
changePane: function (e) { | |
e.preventDefault(); | |
var $target = $(e.target), | |
tabToShow = $target.data('tab'); | |
// set active tab | |
this.$('.tab').parent().removeClass('active'); | |
$target.parent().addClass('active'); | |
if (_.isFunction(this.preTabChange)) { | |
this.preTabChange(tabToShow); | |
} | |
// show the pane | |
_.each(this.tabs, function (tab) { | |
tab.$el.hide(); | |
}); | |
this.tabs[tabToShow].$el.show(); | |
if (_.isFunction(this.postTabChange)) { | |
this.postTabChange(tabToShow); | |
} | |
} | |
}; | |
})(module('Mixins')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// For use with https://github.com/thedersen/backbone.validation | |
BackboneMixins.ValidatingView = { | |
bindValidation: function () { | |
Backbone.Validation.unbind(this); | |
Backbone.Validation.bind(this, { | |
forceUpdate: true, | |
selector: 'class', | |
valid: this.valid, | |
invalid: this.invalid | |
}); | |
}, | |
valid: function (view, attr) { | |
var $field = this.$("[data-field='" + attr + "']"), | |
$error = this.$("[data-error-for='" + attr + "']"); | |
if ($field.length) $field.removeClass('validation-error'); | |
if ($error.length) $error.html('').hide(); | |
}, | |
invalid: function (view, attr, error) { | |
var $field = this.$("[data-field='" + attr + "']"), | |
$error = this.$("[data-error-for='" + attr + "']"); | |
if ($field.length) $field.addClass('validation-error'); | |
if ($error.length) $error.html(error).show(); | |
}, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment