base.js | |
---|---|
Base ViewA view object to construct a standard view with common properties and utilties The base view extends Backbone.View adding methods for resolving deferreds, rendering, decorating data just in time for rendering, adding child views to form a composite of views under one view object, add a destroy method. | |
Example use for a composite view utilizing addChildView, setOptions & callbacks: | |
Requires | define(['facade', 'facade', 'utils'], function (facade, facade, utils) {
var BaseView,
Backbone = facade.Backbone,
$ = facade.$,
_ = facade._,
_toHTML = facade.toHTML,
Deferred = facade.Deferred,
Callbacks = facade.Callbacks,
lib = utils.lib,
debug = utils.debug; |
Constructor | BaseView = Backbone.View.extend({ |
Method: | initialize: function (options) {
if (options) {
this.setOptions(options);
}
this.deferred = new Deferred();
this.callbacks = Callbacks('unique');
}, |
Method: | setOptions: function (options) {
if (options.destination) {
this.destination = options.destination;
}
if (options.template) {
this.template = options.template;
}
}, |
Method: | render: function (domInsertion, dataDecorator, partials) {
var markup;
if (_.isFunction(this.confirmElement)) {
this.confirmElement();
}
dataDecorator = dataDecorator || this.dataDecorator;
markup = this.toHTML(dataDecorator, partials);
domInsertion = this.domInsertionMethod(domInsertion);
this.$el[domInsertion](markup);
this.resolve();
this.callbacks.fire(this.$el);
return this;
}, |
Method: | resolve: function () {
var view = this;
if (view.deferred.state() !== 'resolved') {
this.callbacks.add(view.deferred.resolve);
} else {
if (this.callbacks.has(view.deferred.resolve)) {
this.callbacks.remove(view.deferred.resolve);
}
}
}, |
Method: | confirmElement: function () {
if (_.isUndefined(this.el)) {
this.$el = $(this.options.el);
}
if (_.isUndefined(this.$el)) {
throw new Error("View has no this.el or this.options.el property defined.");
}
}, |
Method: | toHTML: function (dataDecorator, partials) {
var markup, data, args;
data = (this.model) ? this.model.toJSON() : null;
if (dataDecorator && _.isFunction(dataDecorator)) {
data = dataDecorator.call(this, data);
}
this.template = this.template || this.options.template;
if (!this.template || !data) {
throw new Error("BaseView method toHTML called, but this.template or data is not defined.");
} else {
markup = _toHTML(this.template, data, partials);
}
return markup;
}, |
Method: | domInsertionMethod: function (domInsertionMethod) {
var defaultMethod = 'html',
domInsertionMethods = ['append', 'html', 'prepend', 'text'],
domInsertion;
if (domInsertionMethod !== defaultMethod) {
if (domInsertionMethod && _.isString(domInsertionMethod)) {
if (_.contains(domInsertionMethods, domInsertionMethod)) {
domInsertion = domInsertionMethod;
}
}
}
return domInsertion || defaultMethod;
}, |
Method: | dataDecorator: function (data) { return data; }, |
Property: {Object} | callbacks: null, |
Property: {Object} | deferred: null, |
Primarily a tool for unit tests... Don't rely on calling this.isReady!! | isReady: function () {
return !!(this.deferred.state() === 'resolved');
}, |
Method: | addChildView: function (view, context) {
var callbackFn, msg;
if (!view) {
msg = "baseView addChildView expects view object as first arg.";
throw new Error(msg);
}
if (context && !_.isEmpty(context)) {
callbackFn = function () {
view.render();
view.$el.appendTo(context.$el);
return view;
};
} else {
callbackFn = function () {
return view.render();
};
}
return callbackFn;
}, |
Method: | getOuterHtml: function (obj) {
return (obj[0].outerHTML) ? obj[0].outerHTML : $('<div/>').html( obj.eq(0).clone() ).html();
}, |
Method: | destroy: function () {
var key;
if (this.removeSubscribers) {
this.removeSubscribers();
}
this.$el.remove();
if (this.destination) {
$(this.destination).empty();
}
for (key in this) {
delete this[key];
}
}, |
Method: | addSubscribers: function () {}, |
Method: | removeSubscribers: function () {
this.$el.off();
}
});
return BaseView;
});
|