Backbone.Mutators
Advanced tools
Comparing version 0.4.1 to 0.4.2
@@ -0,9 +1,34 @@ | ||
/*! Backbone.Mutators - v0.4.1 | ||
------------------------------ | ||
Build @ 2014-03-27 | ||
Documentation and Full License Available at: | ||
http://asciidisco.github.com/Backbone.Mutators/index.html | ||
git://github.com/asciidisco/Backbone.Mutators.git | ||
Copyright (c) 2014 Sebastian Golasch <public@asciidisco.com> | ||
Permission is hereby granted, free of charge, to any person obtaining a | ||
copy of this software and associated documentation files (the "Software"), | ||
to deal in the Software without restriction, including without limitation | ||
the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
and/or sell copies of the Software, and to permit persons to whom the | ||
Software is furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
IN THE SOFTWARE.*/ | ||
(function (root, factory, undef) { | ||
'use strict'; | ||
if (typeof exports === 'object' && typeof require === 'function') { | ||
if (typeof exports === 'object') { | ||
// Node. Does not work with strict CommonJS, but | ||
// only CommonJS-like enviroments that support module.exports, | ||
// like Node. | ||
module.exports = factory(require('underscore'), require('Backbone')); | ||
module.exports = factory(require('underscore'), require('backbone')); | ||
} else if (typeof define === 'function' && define.amd) { | ||
@@ -148,5 +173,7 @@ // AMD. Register as an anonymous module. | ||
// override toJSON functionality to serialize mutator properties | ||
Mutator.prototype.toJSON = function () { | ||
Mutator.prototype.toJSON = function (options) { | ||
// fetch ye olde values | ||
var attr = oldToJson.call(this); | ||
var attr = oldToJson.call(this), | ||
isSaving, | ||
isTransient; | ||
// iterate over all mutators (if there are some) | ||
@@ -156,4 +183,8 @@ _.each(this.mutators, _.bind(function (mutator, name) { | ||
if (_.isObject(this.mutators[name]) === true && _.isFunction(this.mutators[name].get)) { | ||
attr[name] = _.bind(this.mutators[name].get, this)(); | ||
} else { | ||
isSaving = _.has(options || {}, 'emulateHTTP'); | ||
isTransient = this.mutators[name].transient; | ||
if (!isSaving || !isTransient) { | ||
attr[name] = _.bind(this.mutators[name].get, this)(); | ||
} | ||
} else if (_.isFunction(this.mutators[name])) { | ||
attr[name] = _.bind(this.mutators[name], this)(); | ||
@@ -160,0 +191,0 @@ } |
@@ -1,8 +0,8 @@ | ||
/*! Backbone.Mutators - v0.4.0 | ||
/*! Backbone.Mutators - v0.4.1 | ||
------------------------------ | ||
Build @ 2013-05-01 | ||
Build @ 2014-03-27 | ||
Documentation and Full License Available at: | ||
http://asciidisco.github.com/Backbone.Mutators/index.html | ||
git://github.com/asciidisco/Backbone.Mutators.git | ||
Copyright (c) 2013 Sebastian Golasch <public@asciidisco.com> | ||
Copyright (c) 2014 Sebastian Golasch <public@asciidisco.com> | ||
@@ -26,2 +26,2 @@ Permission is hereby granted, free of charge, to any person obtaining a | ||
IN THE SOFTWARE.*/ | ||
(function(t,s,i){"use strict";"object"==typeof exports?module.exports=s(require("underscore"),require("Backbone")):"function"==typeof define&&define.amd?define(["underscore","backbone"],function(o,e){return o=o===i?t._:o,e=e===i?t.Backbone:e,t.returnExportsGlobal=s(o,e,t)}):t.returnExportsGlobal=s(t._,t.Backbone)})(this,function(t,s,i,o){"use strict";s=s===o?i.Backbone:s,t=t===o?i._:t;var e=function(){},r=s.Model.prototype.get,n=s.Model.prototype.set,u=s.Model.prototype.toJSON;return e.prototype.mutators={},e.prototype.get=function(s){var i=this.mutators!==o;return i===!0&&t.isFunction(this.mutators[s])===!0?this.mutators[s].call(this):i===!0&&t.isObject(this.mutators[s])===!0&&t.isFunction(this.mutators[s].get)===!0?this.mutators[s].get.call(this):r.call(this,s)},e.prototype.set=function(s,i,e){var r=this.mutators!==o,u=null,a=null;return t.isObject(s)||null===s?(a=s,e=i):(a={},a[s]=i),r===!0&&t.isObject(this.mutators[s])===!0&&(t.isFunction(this.mutators[s].set)===!0?u=this.mutators[s].set.call(this,s,a[s],e,t.bind(n,this)):t.isFunction(this.mutators[s])&&(u=this.mutators[s].call(this,s,a[s],e,t.bind(n,this)))),t.isObject(a)&&t.each(a,t.bind(function(s,i){var a=null;if(r===!0&&t.isObject(this.mutators[i])===!0){var c=this.mutators[i];t.isFunction(c.set)&&(c=c.set),t.isFunction(c)&&((e===o||t.isObject(e)===!0&&e.silent!==!0&&e.mutators!==o&&e.mutators.silent!==!0)&&this.trigger("mutators:set:"+i),a=c.call(this,i,s,e,t.bind(n,this)))}null===a&&(a=t.bind(n,this)(i,s,e)),u!==!1&&(u=a)},this)),null!==u?u:n.call(this,s,i,e)},e.prototype.toJSON=function(){var s=u.call(this);return t.each(this.mutators,t.bind(function(i,o){s[o]=t.isObject(this.mutators[o])===!0&&t.isFunction(this.mutators[o].get)?t.bind(this.mutators[o].get,this)():t.bind(this.mutators[o],this)()},this)),s},e.prototype.escape=function(s){var i=this.get(s);return t.escape(null==i?"":""+i)},t.extend(s.Model.prototype,e.prototype),s.Mutators=e,e}); | ||
!function(a,b,c){"use strict";"object"==typeof exports?module.exports=b(require("underscore"),require("backbone")):"function"==typeof define&&define.amd?define(["underscore","backbone"],function(d,e){return d=d===c?a._:d,e=e===c?a.Backbone:e,a.returnExportsGlobal=b(d,e,a)}):a.returnExportsGlobal=b(a._,a.Backbone)}(this,function(a,b,c,d){"use strict";b=b===d?c.Backbone:b,a=a===d?c._:a;var e=function(){},f=b.Model.prototype.get,g=b.Model.prototype.set,h=b.Model.prototype.toJSON;return e.prototype.mutators={},e.prototype.get=function(b){var c=this.mutators!==d;return c===!0&&a.isFunction(this.mutators[b])===!0?this.mutators[b].call(this):c===!0&&a.isObject(this.mutators[b])===!0&&a.isFunction(this.mutators[b].get)===!0?this.mutators[b].get.call(this):f.call(this,b)},e.prototype.set=function(b,c,e){var f=this.mutators!==d,h=null,i=null;return h=g.call(this,b,c,e),a.isObject(b)||null===b?(i=b,e=c):(i={},i[b]=c),f===!0&&a.isObject(this.mutators[b])===!0&&(a.isFunction(this.mutators[b].set)===!0?h=this.mutators[b].set.call(this,b,i[b],e,a.bind(g,this)):a.isFunction(this.mutators[b])&&(h=this.mutators[b].call(this,b,i[b],e,a.bind(g,this)))),f===!0&&a.isObject(i)&&a.each(i,a.bind(function(b,c){if(a.isObject(this.mutators[c])===!0){var f=this.mutators[c];a.isFunction(f.set)&&(f=f.set),a.isFunction(f)&&((e===d||a.isObject(e)===!0&&e.silent!==!0&&e.mutators!==d&&e.mutators.silent!==!0)&&this.trigger("mutators:set:"+c),f.call(this,c,b,e,a.bind(g,this)))}},this)),h},e.prototype.toJSON=function(b){var c,d,e=h.call(this);return a.each(this.mutators,a.bind(function(f,g){a.isObject(this.mutators[g])===!0&&a.isFunction(this.mutators[g].get)?(c=a.has(b||{},"emulateHTTP"),d=this.mutators[g].transient,c&&d||(e[g]=a.bind(this.mutators[g].get,this)())):a.isFunction(this.mutators[g])&&(e[g]=a.bind(this.mutators[g],this)())},this)),e},e.prototype.escape=function(b){var c=this.get(b);return a.escape(null==c?"":""+c)},a.extend(b.Model.prototype,e.prototype),b.Mutators=e,e}); |
@@ -178,5 +178,5 @@ /*global module:false*/ | ||
grunt.registerTask('default', ['jshint', 'complexity', 'qunit', 'nodeunit', 'concat', 'uglify']); | ||
grunt.registerTask('travis', ['jshint', 'complexity', 'qunit', 'saucelabs-qunit']); | ||
grunt.registerTask('travis', ['jshint', 'complexity', 'qunit']); | ||
}; |
{ | ||
"name": "Backbone.Mutators", | ||
"version": "0.4.1", | ||
"version": "0.4.2", | ||
"description": "Backbone plugin to override getters and setters with logic", | ||
@@ -5,0 +5,0 @@ "homepage": "http://asciidisco.github.com/Backbone.Mutators/index.html", |
@@ -24,3 +24,3 @@ ## Backbone.Mutators | ||
### Dowload | ||
### Download | ||
You can directly download the | ||
@@ -318,2 +318,33 @@ [Development Version](https://raw.github.com/asciidisco/Backbone.Mutators/master/backbone.mutators.js) | ||
### Define a getter as transient | ||
Defining a getter as transient means that it will be omitted when Backbone saves the model. This is | ||
useful if the backend system (whatever Backbone is syncing to) fails if you send it a property that does | ||
not actually exist on the model. Note that this only works for mutators defined with a `get()` | ||
function. | ||
In the example below, the `fullName` property will be available when toJSON is called under | ||
non-syncing circumstances--for example, when providing this model to a template--but will be omitted | ||
from the JSON when sync is called (because you called the `sync()` or `save()` method), and will not | ||
be sent to the server. | ||
```javascript | ||
var Model = Backbone.Model.extend({ | ||
defaults:{ | ||
firstName:"Iain", | ||
middleInit:"M", | ||
lastName:"Banks" | ||
}, | ||
mutators:{ | ||
fullName:{ | ||
get: function() { | ||
var fullName = this.get("firstName"); | ||
fullName += " " + this.get("middleInit"); | ||
fullName += ". " + this.get("lastName"); | ||
return fullName; | ||
}, | ||
transient: true | ||
} | ||
} | ||
}); | ||
``` | ||
## Further reading | ||
@@ -325,2 +356,5 @@ James Brown ([@ibjhb](https://github.com/ibjhb/Exploring-Backbone.Mutators)) | ||
### 0.4.2 | ||
+ Fixes [#20](https://github.com/asciidisco/Backbone.Mutators/issues/20) | ||
### 0.4.1 | ||
@@ -327,0 +361,0 @@ + Fixes [#22](https://github.com/asciidisco/Backbone.Mutators/pull/22) |
@@ -8,3 +8,3 @@ (function (root, factory, undef) { | ||
// like Node. | ||
module.exports = factory(require('underscore'), require('Backbone')); | ||
module.exports = factory(require('underscore'), require('backbone')); | ||
} else if (typeof define === 'function' && define.amd) { | ||
@@ -149,5 +149,7 @@ // AMD. Register as an anonymous module. | ||
// override toJSON functionality to serialize mutator properties | ||
Mutator.prototype.toJSON = function () { | ||
Mutator.prototype.toJSON = function (options) { | ||
// fetch ye olde values | ||
var attr = oldToJson.call(this); | ||
var attr = oldToJson.call(this), | ||
isSaving, | ||
isTransient; | ||
// iterate over all mutators (if there are some) | ||
@@ -157,4 +159,8 @@ _.each(this.mutators, _.bind(function (mutator, name) { | ||
if (_.isObject(this.mutators[name]) === true && _.isFunction(this.mutators[name].get)) { | ||
attr[name] = _.bind(this.mutators[name].get, this)(); | ||
} else { | ||
isSaving = _.has(options || {}, 'emulateHTTP'); | ||
isTransient = this.mutators[name].transient; | ||
if (!isSaving || !isTransient) { | ||
attr[name] = _.bind(this.mutators[name].get, this)(); | ||
} | ||
} else if (_.isFunction(this.mutators[name])) { | ||
attr[name] = _.bind(this.mutators[name], this)(); | ||
@@ -161,0 +167,0 @@ } |
var _ = require('underscore'); | ||
var Backbone = require('Backbone'); | ||
var Backbone = require('backbone'); | ||
require('../src/backbone.mutators'); | ||
@@ -331,3 +331,3 @@ | ||
"can set 'mutated' value and fire event": function (test) { | ||
test.expect(3); | ||
test.expect(4); | ||
var Model = Backbone.Model.extend({ | ||
@@ -396,2 +396,25 @@ mutators: { | ||
"can serialize mutated model with only a setter": function (test) { | ||
test.expect(2); | ||
var Model = Backbone.Model.extend({ | ||
mutators: { | ||
status: { | ||
set: function (key, value, options, set) { | ||
set(key, value.toLowerCase(), options); | ||
} | ||
} | ||
}, | ||
defaults: { | ||
status: 'awkward' | ||
} | ||
}); | ||
var model = new Model(); | ||
test.equal(model.toJSON().status, 'awkward', 'can serialize mutated model with only a setter'); | ||
model.set('status', 'SUPERCOOL', {mutators: {silent: true}}); | ||
test.equal(model.toJSON().status, 'supercool', 'can serialize mutated model with only a setter'); | ||
test.done(); | ||
}, | ||
"can escape mutated properties": function (test) { | ||
@@ -450,4 +473,44 @@ test.expect(2); | ||
test.done(); | ||
}, | ||
"can omit transient variables from JSON when saving": function(test) { | ||
test.expect(4); | ||
var Model = Backbone.Model.extend({ | ||
defaults:{ | ||
firstName:"Iain", | ||
middleInit:"M", | ||
lastName:"Banks" | ||
}, | ||
mutators:{ | ||
fullName:{ | ||
get: function() { | ||
var fullName = this.get("firstName"); | ||
fullName += " " + this.get("middleInit"); | ||
fullName += ". " + this.get("lastName"); | ||
return fullName; | ||
}, | ||
transient: true | ||
} | ||
} | ||
}); | ||
var model = new Model(); | ||
// First make sure we didn't break the accessor (or the normal model property | ||
// access) | ||
test.equal(model.get("fullName"), "Iain M. Banks"); | ||
test.equal(model.get("firstName"), "Iain"); | ||
// Ensure that a normal toJSON call (like you'd use with a template) includes | ||
// the computed value | ||
var modelToJSON = model.toJSON(); | ||
test.equal(modelToJSON.fullName, "Iain M. Banks"); | ||
// Backbone always sets 'emulateHTTP' to true or (usually) false when syncing, | ||
// so we use the existence of that property as a proxy for "yes I'm syncing" | ||
var modelToJSONSync = model.toJSON({emulateHTTP:false}); | ||
test.equal(typeof modelToJSONSync.fullName, "undefined"); | ||
test.done(); | ||
} | ||
}; |
@@ -316,3 +316,3 @@ module('Backbone.Mutators'); | ||
test("can set 'mutated' value and fire event", function () { | ||
expect(3); | ||
expect(4); | ||
var Model = Backbone.Model.extend({ | ||
@@ -379,2 +379,24 @@ mutators: { | ||
test("can serialize mutated model with only a setter", function () { | ||
expect(2); | ||
var Model = Backbone.Model.extend({ | ||
mutators: { | ||
status: { | ||
set: function (key, value, options, set) { | ||
set(key, value.toLowerCase(), options); | ||
} | ||
} | ||
}, | ||
defaults: { | ||
status: 'awkward' | ||
} | ||
}); | ||
var model = new Model(); | ||
equal(model.toJSON().status, 'awkward', 'can serialize mutated model'); | ||
model.set('status', 'SUPERCOOL', {mutators: {silent: true}}); | ||
equal(model.toJSON().status, 'supercool', 'can serialize mutated model'); | ||
}); | ||
test("can escape mutated properties", function () { | ||
@@ -438,1 +460,38 @@ expect(2); | ||
}); | ||
test("can omit transient variables from JSON when saving", 4, function() { | ||
var Model = Backbone.Model.extend({ | ||
defaults:{ | ||
firstName:"Iain", | ||
middleInit:"M", | ||
lastName:"Banks" | ||
}, | ||
mutators:{ | ||
fullName:{ | ||
get: function() { | ||
var fullName = this.get("firstName"); | ||
fullName += " " + this.get("middleInit"); | ||
fullName += ". " + this.get("lastName"); | ||
return fullName; | ||
}, | ||
transient: true | ||
} | ||
} | ||
}); | ||
var model = new Model(); | ||
// First make sure we didn't break the accessor (or the normal model property | ||
// access) | ||
equal(model.get("fullName"), "Iain M. Banks"); | ||
equal(model.get("firstName"), "Iain"); | ||
// Ensure that a normal toJSON call (like you'd use with a template) includes | ||
// the computed value | ||
var modelToJSON = model.toJSON(); | ||
equal(modelToJSON.fullName, "Iain M. Banks"); | ||
// Backbone always sets 'emulateHTTP' to true or (usually) false when syncing, | ||
// so we use the existence of that property as a proxy for "yes I'm syncing" | ||
var modelToJSONSync = model.toJSON({emulateHTTP:false}); | ||
equal(typeof modelToJSONSync.fullName, "undefined"); | ||
}); |
71820
1391
387