Skip to content

Instantly share code, notes, and snippets.

@dgs700
Created May 11, 2012 05:58
Show Gist options
  • Save dgs700/2657819 to your computer and use it in GitHub Desktop.
Save dgs700/2657819 to your computer and use it in GitHub Desktop.
Remove all hardcoded dependancies from your Backbone classes for clean MVC separation!
/* Copywrite 2012, David Shapiro - portions added to existing Backbone code*/
/* Subject to FFRUYL licensing - Feel free to rip and use as you like. */
/*globals Backbone:true, _:true, $:true*/
// @name: Configurator
//
// @tagline: Configurator for Backbone Apps- models, views and routers
//
// @description:
// Experimental code
// -Maintain Backbone MVC classes free of hardcoded dependancies including strings, css, text, and html fragments.
// -Create and modify application configuration object and inject into app bootstrap.
// -Modify configurations and trigger config:changed events during runtime to dynamically decorate your app.
// -Configurator classes and config objects can be subclassed or mixed into to
// Class and inheritance structure follows the same conventions used in core Backbone modules
Backbone.Configurator = (function (Backbone, _, $) {
"use strict";
var Configurator = {}, config;
Configurator.version = "0.01";
//The general idea is to remove any and all hardcoded dependancies from your
//Backbone classes and list them here or add by subclassing, mixing in, or dynamically at runtime
//changes to this object can trigger config change events that your application can react to
//sample, skeletal configuration for basic Backbone modules
//you can extend this object or set your own via
// Backbone.Configurator.config = {your base config} prior to extending your own
//Configurator classes
config = {
//
app: {
//name of the data collection to look for on page load
//bootStrapData: My.JSON.dataObject,
//any jQuery selector strings needed to reference layout containters
selectors: {
domAttachClass: '.some_content_div',
rootPageElem: 'body'
},
//switches to indicate if the app contains any optional views
//to include in initialization
pager:false,
filter:false,
//optional classnames to for views (controllers) to reference
classes: {
//model: My.Application.ItemClassName,
//collection: My.Application.CollectionClassName
}
},
router: {
routes:{
'': 'home'
},
//reverse hash of routes for use with router.navigate()
paths:{
home: ''
}
},
history: {
root: '/',
pushState: true
},
item: {
urlRoot: '/my_collection/'
},
collection: {
url: '/my_collection/'
//item: My.Collections.ItemClassName
},
test: {
foo:'bar'
}
};
Configurator = function(props, options) {
this.config = $.extend(true,{}, this.constructor.config);
this.add(props || {});
this._configure(options || {});
this.initialize.apply(this, arguments);
};
Configurator.config = config;
// List of config instance options to be merged as properties. Empty by default.
// Add any special instance options you want set directly on the config instance.
var configOptions = [];
// Set up all inheritable **Backbone.Configurator** properties and methods.
_.extend(Configurator.prototype, Backbone.Events, {
// recursively add properties to the config object
// triggers a change:config event unless {silent:true}
add: function(props){
if(typeof props == 'object'){
$.extend(true, this.config, props);
if(!arguments[1]){
this.trigger('change:config', props);
}
}
},
// Same functionality as Bacbone.View. To use, add values to the
// configOptions array.
_configure: function(options) {
if (this.options)
options = _.extend({}, this.options, options);
for (var i = 0, l = configOptions.length; i < l; i++) {
var attr = configOptions[i];
if (options[attr])
this[attr] = options[attr];
}
this.options = options;
},
// Initialize is an empty function by default. Override it with your own
// initialization logic.
initialize: function(){},
//warning... this will replace the current config obj.
//triggers a reset event unless silent:true
resetConfig: function(conf){
conf = conf || {};
this.config = conf;
if(!arguments[1]){
this.trigger('reset:config', conf);
}
},
getConfig: function(){
return this.config;
}
});
// The self-propagating extend function that Backbone classes use.
// Added configProps to for deep copying
Configurator.extend = function(configProps, protoProps, classProps) {
var child = inherits(this, configProps, protoProps, classProps);
child.extend = this.extend;
return child;
};
// Shared empty constructor function to aid in prototype-chain creation.
var ctor = function(){};
// Helper function to correctly set up the prototype chain, for subclasses.
// Similar to `goog.inherits`, but uses a hash of prototype properties and
// class properties to be extended.
var inherits = function(parent, configProps, protoProps, staticProps) {
var child;
// The constructor function for the new subclass is either defined by you
// (the "constructor" property in your `extend` definition), or defaulted
// by us to simply call the parent's constructor.
if (protoProps && protoProps.hasOwnProperty('constructor')) {
child = protoProps.constructor;
} else {
child = function(){
parent.apply(this, arguments);
};
}
// Inherit class (static) properties from parent.
_.extend(child, parent);
// reset child.config to a deep copy since we want to remove any references
// to parent.config before adding or changing config props
child.config = $.extend(true, {}, parent.config);
// Set the prototype chain to inherit from `parent`, without calling
// `parent`'s constructor function.
ctor.prototype = parent.prototype;
child.prototype = new ctor();
// Add deep copy of config properties (instance properties) to the subclass,
// if supplied since we don't want to copy any nested references.
if (configProps) $.extend(true, child.config, configProps);
// Add prototype properties (instance properties) to the subclass,
// if supplied.
if (protoProps) _.extend(child.prototype, protoProps);
// Add static properties to the constructor function, if supplied.
if (staticProps) _.extend(child, staticProps);
// Correctly set child's `prototype.constructor`.
child.prototype.constructor = child;
// Set a convenience property in case the parent's prototype is needed later.
child.__super__ = parent.prototype;
return child;
};
return Configurator;
}(Backbone, _, $));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment