From 947f8e6fb27e1691dd02ade0ec07f7a545e0d1e3 Mon Sep 17 00:00:00 2001 From: "alexander.beletsky" Date: Sun, 17 Feb 2013 18:59:35 +0200 Subject: [PATCH] fixes #3 fixes #4: minified and amd versions added --- .gitignore | 7 +- README.md | 4 + grunt.js | 71 +++++++++ lib/amd/backbone.computedfields.js | 141 ++++++++++++++++++ lib/amd/backbone.computedfields.min.js | 5 + lib/backbone.computedfields.js | 123 +++++++++++++++ lib/backbone.computedfields.min.js | 5 + package.json | 7 +- {lib => public}/backbone-0.9.10/backbone.js | 0 {lib => public}/backbone-0.9.2/backbone.js | 0 {lib => public}/backbone-0.9.9/backbone.js | 0 .../backbone.marionette.js | 0 {lib => public}/jquery/jquery.js | 0 {lib => public}/underscore/underscore.js | 0 src/amd.js | 20 +++ src/backbone.computedfields.js | 20 +-- test/index-0.9.10.html | 40 ----- test/index-0.9.9.html | 40 ----- test/{index-0.9.2.html => index.html} | 7 +- 19 files changed, 387 insertions(+), 103 deletions(-) create mode 100644 grunt.js create mode 100644 lib/amd/backbone.computedfields.js create mode 100644 lib/amd/backbone.computedfields.min.js create mode 100644 lib/backbone.computedfields.js create mode 100644 lib/backbone.computedfields.min.js rename {lib => public}/backbone-0.9.10/backbone.js (100%) rename {lib => public}/backbone-0.9.2/backbone.js (100%) rename {lib => public}/backbone-0.9.9/backbone.js (100%) rename {lib => public}/backbone.marionette/backbone.marionette.js (100%) rename {lib => public}/jquery/jquery.js (100%) rename {lib => public}/underscore/underscore.js (100%) create mode 100644 src/amd.js delete mode 100644 test/index-0.9.10.html delete mode 100644 test/index-0.9.9.html rename test/{index-0.9.2.html => index.html} (74%) diff --git a/.gitignore b/.gitignore index 1bde3b7..2264456 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ -temp -dist +.DS_Store +*.swp +*.swo +node_modules +_SpecRunner.html diff --git a/README.md b/README.md index b1e6851..d64dc95 100644 --- a/README.md +++ b/README.md @@ -221,6 +221,10 @@ Up-to-date and complete documentation is located at [/test/spec/backbone.compute ## Versions / Changes +### v.0.0.5 17 February, 2013 + +* AMD support added + ### v.0.0.4 26 December, 2012 * Support for Backbone 0.9.9 diff --git a/grunt.js b/grunt.js new file mode 100644 index 0000000..baa5823 --- /dev/null +++ b/grunt.js @@ -0,0 +1,71 @@ +/*global module:false*/ +module.exports = function(grunt) { + + grunt.loadNpmTasks('grunt-rigger'); + + // Project configuration. + grunt.initConfig({ + meta: { + version: '0.0.5', + banner: '// Backbone.ComputedFields, v<%= meta.version %>\n' + + '// Copyright (c)<%= grunt.template.today("yyyy") %> alexander.beletsky@gmail.com\n' + + '// Distributed under MIT license\n' + + '// http://github.com/alexander.beletsky/backbone.clickdebounce' + }, + + lint: { + files: ['src/backbone.computedfields*.js'] + }, + + rig: { + build: { + src: ['', 'src/backbone.computedfields.js'], + dest: 'lib/backbone.computedfields.js' + }, + amd: { + src: ['', 'src/amd.js'], + dest: 'lib/amd/backbone.computedfields.js' + } + }, + + min: { + standard: { + src: ['', ''], + dest: 'lib/backbone.computedfields.min.js' + }, + amd: { + src: ['', ''], + dest: 'lib/amd/backbone.computedfields.min.js' + }, + }, + + jshint: { + options: { + curly: true, + eqeqeq: true, + immed: false, + latedef: true, + newcap: true, + noarg: true, + sub: true, + undef: true, + boss: true, + eqnull: true, + browser: true + }, + globals: { + jQuery: true, + Backbone: true, + _: true, + Marionette: true, + $: true, + slice: true + } + }, + uglify: {} + }); + + // Default task. + grunt.registerTask('default', 'lint rig min'); + +}; diff --git a/lib/amd/backbone.computedfields.js b/lib/amd/backbone.computedfields.js new file mode 100644 index 0000000..fb804a1 --- /dev/null +++ b/lib/amd/backbone.computedfields.js @@ -0,0 +1,141 @@ +// Backbone.ComputedFields, v0.0.5 +// Copyright (c)2013 alexander.beletsky@gmail.com +// Distributed under MIT license +// http://github.com/alexander.beletsky/backbone.clickdebounce +(function (root, factory) { + if (typeof exports === 'object') { + + var underscore = require('underscore'); + var backbone = require('backbone'); + + module.exports = factory(underscore, backbone); + + } else if (typeof define === 'function' && define.amd) { + + define(['underscore', 'backbone'], factory); + + } +}(this, function (_, Backbone) { + + Backbone.ComputedFields = (function(Backbone, _){ + + var ComputedFields = function (model) { + this.model = model; + this._computedFields = []; + + this.initialize(); + }; + + ComputedFields.VERSION = '0.0.5'; + + _.extend(ComputedFields.prototype, { + initialize: function () { + _.bindAll(this); + + this._lookUpComputedFields(); + this._bindModelEvents(); + this._wrapJSON(); + }, + + _lookUpComputedFields: function () { + for (var obj in this.model.computed) { + var field = this.model.computed[obj]; + + if (field && (field.set || field.get)) { + this._computedFields.push({name: obj, field: field}); + } + } + }, + + _bindModelEvents: function () { + _.each(this._computedFields, function (computedField) { + var fieldName = computedField.name; + var field = computedField.field; + + var updateComputed = _.bind(function () { + var value = this._computeFieldValue(field); + this.model.set(fieldName, value, { skipChangeEvent: true }); + }, this); + + var updateDependent = _.bind(function (model, value, options) { + if (options && options.skipChangeEvent) { + return; + } + + if (field.set) { + var fields = this._dependentFields(field.depends); + value = value || this.model.get(fieldName); + + field.set.call(this.model, value, fields); + this.model.set(fields, options); + } + }, this); + + this._thenDependentChanges(field.depends, updateComputed); + this._thenComputedChanges(fieldName, updateDependent); + + if (this._isModelInitialized()) { + updateComputed(); + } + }, this); + }, + + _isModelInitialized: function () { + return !_.isEmpty(this.model.attributes); + }, + + _thenDependentChanges: function (depends, callback) { + _.each(depends, function (name) { + if (typeof (name) === 'string') { + this.model.on('change:' + name, callback); + } + + if (typeof (name) === 'function') { + name.call(this.model, callback); + } + }, this); + }, + + _thenComputedChanges: function (fieldName, callback) { + this.model.on('change:' + fieldName, callback); + }, + + _wrapJSON: function () { + this.model.toJSON = _.wrap(this.model.toJSON, this._toJSON); + }, + + _toJSON: function (toJSON) { + var attributes = toJSON.call(this.model); + + var stripped = _.reduce(this._computedFields, function (memo, computed) { + if (computed.field.toJSON === false) { + memo.push(computed.name); + } + return memo; + },[]); + + return _.omit(attributes, stripped); + }, + + _computeFieldValue: function (computedField) { + if (computedField && computedField.get) { + var fields = this._dependentFields(computedField.depends); + return computedField.get.call(this.model, fields); + } + }, + + _dependentFields: function (depends) { + return _.reduce(depends, function (memo, field) { + memo[field] = this.model.get(field); + return memo; + }, {}, this); + } + + }); + + return ComputedFields; + + })(Backbone, _); + return Backbone.ComputedFields; + +})); diff --git a/lib/amd/backbone.computedfields.min.js b/lib/amd/backbone.computedfields.min.js new file mode 100644 index 0000000..0bf97a2 --- /dev/null +++ b/lib/amd/backbone.computedfields.min.js @@ -0,0 +1,5 @@ +// Backbone.ComputedFields, v0.0.5 +// Copyright (c)2013 alexander.beletsky@gmail.com +// Distributed under MIT license +// http://github.com/alexander.beletsky/backbone.clickdebounce +(function(e,t){if(typeof exports=="object"){var n=require("underscore"),r=require("backbone");module.exports=t(n,r)}else typeof define=="function"&&define.amd&&define(["underscore","backbone"],t)})(this,function(e,t){return t.ComputedFields=function(e,t){var n=function(e){this.model=e,this._computedFields=[],this.initialize()};return n.VERSION="0.0.5",t.extend(n.prototype,{initialize:function(){t.bindAll(this),this._lookUpComputedFields(),this._bindModelEvents(),this._wrapJSON()},_lookUpComputedFields:function(){for(var e in this.model.computed){var t=this.model.computed[e];t&&(t.set||t.get)&&this._computedFields.push({name:e,field:t})}},_bindModelEvents:function(){t.each(this._computedFields,function(e){var n=e.name,r=e.field,i=t.bind(function(){var e=this._computeFieldValue(r);this.model.set(n,e,{skipChangeEvent:!0})},this),s=t.bind(function(e,t,i){if(i&&i.skipChangeEvent)return;if(r.set){var s=this._dependentFields(r.depends);t=t||this.model.get(n),r.set.call(this.model,t,s),this.model.set(s,i)}},this);this._thenDependentChanges(r.depends,i),this._thenComputedChanges(n,s),this._isModelInitialized()&&i()},this)},_isModelInitialized:function(){return!t.isEmpty(this.model.attributes)},_thenDependentChanges:function(e,n){t.each(e,function(e){typeof e=="string"&&this.model.on("change:"+e,n),typeof e=="function"&&e.call(this.model,n)},this)},_thenComputedChanges:function(e,t){this.model.on("change:"+e,t)},_wrapJSON:function(){this.model.toJSON=t.wrap(this.model.toJSON,this._toJSON)},_toJSON:function(e){var n=e.call(this.model),r=t.reduce(this._computedFields,function(e,t){return t.field.toJSON===!1&&e.push(t.name),e},[]);return t.omit(n,r)},_computeFieldValue:function(e){if(e&&e.get){var t=this._dependentFields(e.depends);return e.get.call(this.model,t)}},_dependentFields:function(e){return t.reduce(e,function(e,t){return e[t]=this.model.get(t),e},{},this)}}),n}(t,e),t.ComputedFields}); \ No newline at end of file diff --git a/lib/backbone.computedfields.js b/lib/backbone.computedfields.js new file mode 100644 index 0000000..185bf93 --- /dev/null +++ b/lib/backbone.computedfields.js @@ -0,0 +1,123 @@ +// Backbone.ComputedFields, v0.0.5 +// Copyright (c)2013 alexander.beletsky@gmail.com +// Distributed under MIT license +// http://github.com/alexander.beletsky/backbone.clickdebounce +Backbone.ComputedFields = (function(Backbone, _){ + + var ComputedFields = function (model) { + this.model = model; + this._computedFields = []; + + this.initialize(); + }; + + ComputedFields.VERSION = '0.0.5'; + + _.extend(ComputedFields.prototype, { + initialize: function () { + _.bindAll(this); + + this._lookUpComputedFields(); + this._bindModelEvents(); + this._wrapJSON(); + }, + + _lookUpComputedFields: function () { + for (var obj in this.model.computed) { + var field = this.model.computed[obj]; + + if (field && (field.set || field.get)) { + this._computedFields.push({name: obj, field: field}); + } + } + }, + + _bindModelEvents: function () { + _.each(this._computedFields, function (computedField) { + var fieldName = computedField.name; + var field = computedField.field; + + var updateComputed = _.bind(function () { + var value = this._computeFieldValue(field); + this.model.set(fieldName, value, { skipChangeEvent: true }); + }, this); + + var updateDependent = _.bind(function (model, value, options) { + if (options && options.skipChangeEvent) { + return; + } + + if (field.set) { + var fields = this._dependentFields(field.depends); + value = value || this.model.get(fieldName); + + field.set.call(this.model, value, fields); + this.model.set(fields, options); + } + }, this); + + this._thenDependentChanges(field.depends, updateComputed); + this._thenComputedChanges(fieldName, updateDependent); + + if (this._isModelInitialized()) { + updateComputed(); + } + }, this); + }, + + _isModelInitialized: function () { + return !_.isEmpty(this.model.attributes); + }, + + _thenDependentChanges: function (depends, callback) { + _.each(depends, function (name) { + if (typeof (name) === 'string') { + this.model.on('change:' + name, callback); + } + + if (typeof (name) === 'function') { + name.call(this.model, callback); + } + }, this); + }, + + _thenComputedChanges: function (fieldName, callback) { + this.model.on('change:' + fieldName, callback); + }, + + _wrapJSON: function () { + this.model.toJSON = _.wrap(this.model.toJSON, this._toJSON); + }, + + _toJSON: function (toJSON) { + var attributes = toJSON.call(this.model); + + var stripped = _.reduce(this._computedFields, function (memo, computed) { + if (computed.field.toJSON === false) { + memo.push(computed.name); + } + return memo; + },[]); + + return _.omit(attributes, stripped); + }, + + _computeFieldValue: function (computedField) { + if (computedField && computedField.get) { + var fields = this._dependentFields(computedField.depends); + return computedField.get.call(this.model, fields); + } + }, + + _dependentFields: function (depends) { + return _.reduce(depends, function (memo, field) { + memo[field] = this.model.get(field); + return memo; + }, {}, this); + } + + }); + + return ComputedFields; + +})(Backbone, _); \ No newline at end of file diff --git a/lib/backbone.computedfields.min.js b/lib/backbone.computedfields.min.js new file mode 100644 index 0000000..8b3f52c --- /dev/null +++ b/lib/backbone.computedfields.min.js @@ -0,0 +1,5 @@ +// Backbone.ComputedFields, v0.0.5 +// Copyright (c)2013 alexander.beletsky@gmail.com +// Distributed under MIT license +// http://github.com/alexander.beletsky/backbone.clickdebounce +Backbone.ComputedFields=function(e,t){var n=function(e){this.model=e,this._computedFields=[],this.initialize()};return n.VERSION="0.0.5",t.extend(n.prototype,{initialize:function(){t.bindAll(this),this._lookUpComputedFields(),this._bindModelEvents(),this._wrapJSON()},_lookUpComputedFields:function(){for(var e in this.model.computed){var t=this.model.computed[e];t&&(t.set||t.get)&&this._computedFields.push({name:e,field:t})}},_bindModelEvents:function(){t.each(this._computedFields,function(e){var n=e.name,r=e.field,i=t.bind(function(){var e=this._computeFieldValue(r);this.model.set(n,e,{skipChangeEvent:!0})},this),s=t.bind(function(e,t,i){if(i&&i.skipChangeEvent)return;if(r.set){var s=this._dependentFields(r.depends);t=t||this.model.get(n),r.set.call(this.model,t,s),this.model.set(s,i)}},this);this._thenDependentChanges(r.depends,i),this._thenComputedChanges(n,s),this._isModelInitialized()&&i()},this)},_isModelInitialized:function(){return!t.isEmpty(this.model.attributes)},_thenDependentChanges:function(e,n){t.each(e,function(e){typeof e=="string"&&this.model.on("change:"+e,n),typeof e=="function"&&e.call(this.model,n)},this)},_thenComputedChanges:function(e,t){this.model.on("change:"+e,t)},_wrapJSON:function(){this.model.toJSON=t.wrap(this.model.toJSON,this._toJSON)},_toJSON:function(e){var n=e.call(this.model),r=t.reduce(this._computedFields,function(e,t){return t.field.toJSON===!1&&e.push(t.name),e},[]);return t.omit(n,r)},_computeFieldValue:function(e){if(e&&e.get){var t=this._dependentFields(e.depends);return e.get.call(this.model,t)}},_dependentFields:function(e){return t.reduce(e,function(e,t){return e[t]=this.model.get(t),e},{},this)}}),n}(Backbone,_); \ No newline at end of file diff --git a/package.json b/package.json index 3aa2242..6608873 100644 --- a/package.json +++ b/package.json @@ -11,5 +11,10 @@ }, "lib" : ".", "main" : "src/backbone.computedfields.js", - "version" : "0.0.4" + "version" : "0.0.5", + "devDependencies": { + "grunt": "*", + "grunt-jasmine-runner": "latest", + "grunt-rigger": "*" + } } \ No newline at end of file diff --git a/lib/backbone-0.9.10/backbone.js b/public/backbone-0.9.10/backbone.js similarity index 100% rename from lib/backbone-0.9.10/backbone.js rename to public/backbone-0.9.10/backbone.js diff --git a/lib/backbone-0.9.2/backbone.js b/public/backbone-0.9.2/backbone.js similarity index 100% rename from lib/backbone-0.9.2/backbone.js rename to public/backbone-0.9.2/backbone.js diff --git a/lib/backbone-0.9.9/backbone.js b/public/backbone-0.9.9/backbone.js similarity index 100% rename from lib/backbone-0.9.9/backbone.js rename to public/backbone-0.9.9/backbone.js diff --git a/lib/backbone.marionette/backbone.marionette.js b/public/backbone.marionette/backbone.marionette.js similarity index 100% rename from lib/backbone.marionette/backbone.marionette.js rename to public/backbone.marionette/backbone.marionette.js diff --git a/lib/jquery/jquery.js b/public/jquery/jquery.js similarity index 100% rename from lib/jquery/jquery.js rename to public/jquery/jquery.js diff --git a/lib/underscore/underscore.js b/public/underscore/underscore.js similarity index 100% rename from lib/underscore/underscore.js rename to public/underscore/underscore.js diff --git a/src/amd.js b/src/amd.js new file mode 100644 index 0000000..9cd9061 --- /dev/null +++ b/src/amd.js @@ -0,0 +1,20 @@ +(function (root, factory) { + if (typeof exports === 'object') { + + var underscore = require('underscore'); + var backbone = require('backbone'); + + module.exports = factory(underscore, backbone); + + } else if (typeof define === 'function' && define.amd) { + + define(['underscore', 'backbone'], factory); + + } +}(this, function (_, Backbone) { + + //= backbone.computedfields.js + return Backbone.ComputedFields; + +})); + diff --git a/src/backbone.computedfields.js b/src/backbone.computedfields.js index b0319c9..ed0d8a5 100644 --- a/src/backbone.computedfields.js +++ b/src/backbone.computedfields.js @@ -1,16 +1,4 @@ -/* - Backbone.ComputedFields v.0.0.4 - (c) 2012 alexander.beletsky@gmail.com - Distributed Under MIT License - - https://github.com/alexanderbeletsky/backbone.computedfields -*/ - -(function () { - - if (!Backbone) { - throw 'Please include Backbone.js before Backbone.ComputedFields.js'; - } +Backbone.ComputedFields = (function(Backbone, _){ var ComputedFields = function (model) { this.model = model; @@ -19,7 +7,7 @@ this.initialize(); }; - ComputedFields.VERSION = '0.0.4'; + ComputedFields.VERSION = '0.0.5'; _.extend(ComputedFields.prototype, { initialize: function () { @@ -126,6 +114,6 @@ }); - Backbone.ComputedFields = ComputedFields; + return ComputedFields; -})(); \ No newline at end of file +})(Backbone, _); \ No newline at end of file diff --git a/test/index-0.9.10.html b/test/index-0.9.10.html deleted file mode 100644 index 4042417..0000000 --- a/test/index-0.9.10.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - Mocha Spec Runner - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/index-0.9.9.html b/test/index-0.9.9.html deleted file mode 100644 index 6520c05..0000000 --- a/test/index-0.9.9.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - Mocha Spec Runner - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/index-0.9.2.html b/test/index.html similarity index 74% rename from test/index-0.9.2.html rename to test/index.html index 5e57467..55f3e94 100644 --- a/test/index-0.9.2.html +++ b/test/index.html @@ -24,10 +24,9 @@ - - - - + + +