From 3306c74c235cb84d58320b7e574bf144d27bf38a Mon Sep 17 00:00:00 2001 From: Isak Bakken Date: Thu, 13 Sep 2012 20:57:36 +0200 Subject: [PATCH 1/5] Remove some space-only lines --- test/nested-model.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test/nested-model.js b/test/nested-model.js index 8ce94c3..b16961b 100644 --- a/test/nested-model.js +++ b/test/nested-model.js @@ -48,7 +48,7 @@ $(document).ready(function() { test("#get() 1-1 returns attributes object", function() { var name = doc.get('name'); - + deepEqual(name, { first: 'Aidan', middle: { @@ -322,7 +322,7 @@ $(document).ready(function() { var changeNameFirst = sinon.spy(); var changeNameLast = sinon.spy(); var changeGender = sinon.spy(); - + doc.bind('change', change); doc.bind('change:name', changeName); doc.bind('change:name.first', changeNameFirst); @@ -504,7 +504,7 @@ $(document).ready(function() { var changeNameMiddleInitial = sinon.spy(); var changeNameMiddleFull = sinon.spy(); var changeNameFirst = sinon.spy(); - + doc.bind('change', change); doc.bind('change:name', changeName); doc.bind('change:name.middle', changeNameMiddle); @@ -536,12 +536,12 @@ $(document).ready(function() { var changeAddresses0City = sinon.spy(); var changeAddresses0State = sinon.spy(); var changeAddresses1 = sinon.spy(); - + doc.bind('change', change); doc.bind('change:addresses', changeAddresses); doc.bind('change:addresses[0]', changeAddresses0); doc.bind('change:addresses[0].city', changeAddresses0City); - + doc.bind('change:addresses[0].state', changeAddresses0State); doc.bind('change:addresses[1]', changeAddresses1); @@ -563,7 +563,7 @@ $(document).ready(function() { var change = sinon.spy(); var changeAddresses = sinon.spy(); var addAddresses = sinon.spy(); - + doc.bind('change', change); doc.bind('change:addresses', changeAddresses); doc.bind('add:addresses', addAddresses); @@ -585,7 +585,7 @@ $(document).ready(function() { var change = sinon.spy(); var changeAddresses = sinon.spy(); var removeAddresses = sinon.spy(); - + doc.bind('change', change); doc.bind('change:addresses', changeAddresses); doc.bind('remove:addresses', removeAddresses); @@ -601,7 +601,7 @@ $(document).ready(function() { var change = sinon.spy(); var changeAddresses = sinon.spy(); var removeAddresses = sinon.spy(); - + doc.bind('change', change); doc.bind('change:addresses', changeAddresses); doc.bind('remove:addresses', removeAddresses); @@ -625,7 +625,7 @@ $(document).ready(function() { full: 'Limburger', fullAlternates: ['Danger', 'Funny', 'Responsible'] }); - + doc.bind('change', change); doc.bind('change:name', changeName); doc.bind('change:name.middle', changeNameMiddle); @@ -662,7 +662,7 @@ $(document).ready(function() { 'name.middle.full': 'Limburger' }); }); - + doc.set({'name.middle.full': 'Limburger'}); }); @@ -684,7 +684,7 @@ $(document).ready(function() { 'name.middle.full': 'Limburger' }); }); - + //Set using conventional JSON - emulates a model fetch doc.set({ gender: 'M', @@ -708,7 +708,7 @@ $(document).ready(function() { ] }); }); - + test("#changedAttributes() should clear the nested attributes between change events", function() { doc.set({'name.first': 'Bob'}); @@ -735,7 +735,7 @@ $(document).ready(function() { return "First name is too long"; } }; - + doc.set({'name.first': 'TooLongFirstName'}); doc.bind('change', function(){ @@ -957,7 +957,7 @@ $(document).ready(function() { doc.bind('remove:addresses', removeAddresses); doc.remove('addresses[0]'); - + sinon.assert.calledOnce(removeAddresses); equal(doc.get('addresses').length, 1); From 6aa237d74b0827b4454fe62e847db7d66cb86dc0 Mon Sep 17 00:00:00 2001 From: Isak Bakken Date: Thu, 13 Sep 2012 21:20:05 +0200 Subject: [PATCH 2/5] Add tests from issue #58 --- test/nested-model.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/nested-model.js b/test/nested-model.js index b16961b..5c7f220 100644 --- a/test/nested-model.js +++ b/test/nested-model.js @@ -356,6 +356,23 @@ $(document).ready(function() { sinon.assert.notCalled(changeNameFirst); }); + test("change() fires the silenced events", function() { + var change = sinon.spy(); + var changeName = sinon.spy(); + var changeNameFirst = sinon.spy(); + + doc.bind('change', change); + doc.bind('change:name', changeName); + doc.bind('change:name.first', changeNameFirst); + + doc.set({'name.first': 'Bob'}, {silent: true}); + doc.change(); + + sinon.assert.calledOnce(change); + sinon.assert.calledOnce(changeName); + sinon.assert.calledOnce(changeNameFirst); + }); + test("change event doesn't fire if new value matches old value", function() { var change = sinon.spy(); var changeName = sinon.spy(); @@ -819,6 +836,23 @@ $(document).ready(function() { sinon.assert.notCalled(changeNameFirst); }); + test("#clear() silent triggers change events when change() is called", function() { + var change = sinon.spy(); + var changeName = sinon.spy(); + var changeNameFirst = sinon.spy(); + + doc.bind('change', change); + doc.bind('change:name', changeName); + doc.bind('change:name.first', changeNameFirst); + + doc.clear({silent: true}); + doc.change(); + + sinon.assert.calledOnce(change); + sinon.assert.calledOnce(changeName); + sinon.assert.calledOnce(changeNameFirst); + }); + // ----- UNSET -------- From 3e4199a445e8008e208a7e1a85d2e84501b316c1 Mon Sep 17 00:00:00 2001 From: Isak Bakken Date: Thu, 13 Sep 2012 21:46:56 +0200 Subject: [PATCH 3/5] Slightly shorter implementation of .get() --- backbone-nested.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/backbone-nested.js b/backbone-nested.js index ef1fbf9..d349905 100644 --- a/backbone-nested.js +++ b/backbone-nested.js @@ -15,18 +15,11 @@ Backbone.NestedModel = Backbone.Model.extend({ get: function(attrStrOrPath){ - var attrPath = Backbone.NestedModel.attrPath(attrStrOrPath), - result; + var attrPath = Backbone.NestedModel.attrPath(attrStrOrPath); - Backbone.NestedModel.walkPath(this.attributes, attrPath, function(val, path){ - var attr = _.last(path); - if (path.length === attrPath.length){ - // attribute found - result = val[attr]; - } - }); - - return result; + return _.reduce(attrPath, function(val, attr) { + return _.isObject(val) ? val[attr] : undefined; + }, this.attributes); }, has: function(attr){ From 83299bc1096f311b10a66aa4f8d8a8bbb42111fe Mon Sep 17 00:00:00 2001 From: Isak Bakken Date: Fri, 14 Sep 2012 00:19:55 +0200 Subject: [PATCH 4/5] Make a few more change() tests pass --- backbone-nested.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/backbone-nested.js b/backbone-nested.js index d349905..9f7e33b 100644 --- a/backbone-nested.js +++ b/backbone-nested.js @@ -108,7 +108,7 @@ if (_.isObject(val)) { // clear child attrs setChanged(val, changedPath); } - if (!options.silent) model._delayedChange(changedPath, null); + model._delayedChange(changedPath, null); changed[changedPath] = null; }); }; @@ -117,11 +117,16 @@ this.attributes = {}; this._escapedAttributes = {}; + this._delayedTrigger('change'); + // Fire the `"change"` events. - if (!options.silent) this._delayedTrigger('change'); + if (!options.silent) this._runDelayedTriggers(); + return this; + }, + change: function() { this._runDelayedTriggers(); - return this; + return Backbone.NestedModel.__super__.change.apply(this, _.toArray(arguments)); }, add: function(attrStr, value, opts){ @@ -168,7 +173,6 @@ return Backbone.NestedModel.deepClone(this.attributes); }, - // private _delayedTrigger: function(/* the trigger args */){ _delayedTriggers.push(arguments); @@ -246,7 +250,7 @@ } } - if (!opts.silent){ + if (!opts.silent) { // let the superclass handle change events for top-level attributes if (path.length > 1 && isNewValue){ model._delayedChange(attrStr, val[attr]); @@ -256,6 +260,7 @@ model._delayedTrigger('add:' + attrStr, model, val[attr]); } } + }); } From 28530dfba4c379cbbaef47a48e60ba484bf97ef4 Mon Sep 17 00:00:00 2001 From: Isak Bakken Date: Fri, 14 Sep 2012 00:38:31 +0200 Subject: [PATCH 5/5] Remove redundant has() - backbone seems to be updated --- backbone-nested.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/backbone-nested.js b/backbone-nested.js index 9f7e33b..d15b140 100644 --- a/backbone-nested.js +++ b/backbone-nested.js @@ -22,12 +22,6 @@ }, this.attributes); }, - has: function(attr){ - // for some reason this is not how Backbone.Model is implemented - it accesses the attributes object directly - var result = this.get(attr); - return !(result === null || _.isUndefined(result)); - }, - set: function(key, value, opts){ var newAttrs = Backbone.NestedModel.deepClone(this.attributes), attrPath;