From 76758f6dc427c897b4b66f6179b874b209232d8b Mon Sep 17 00:00:00 2001 From: rhubarbselleven Date: Sun, 15 Mar 2015 12:23:19 +1100 Subject: [PATCH 1/5] An indeterminate checkbox will be a null value --- readme.md | 4 +++- spec/javascripts/deserialize.spec.js | 15 +++++++++++++++ spec/javascripts/serialize.spec.js | 14 ++++++++++++++ src/backbone.syphon.inputreaders.js | 2 +- src/backbone.syphon.inputwriters.js | 6 +++++- 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index d607791..31e2a66 100644 --- a/readme.md +++ b/readme.md @@ -123,6 +123,7 @@ By default, a checkbox will return a boolean value signifying whether or not it
+
``` @@ -133,7 +134,8 @@ Backbone.Syphon.serialize(view); { a: false, - b: true + b: true, + c: null } ``` diff --git a/spec/javascripts/deserialize.spec.js b/spec/javascripts/deserialize.spec.js index f73914b..56992f6 100644 --- a/spec/javascripts/deserialize.spec.js +++ b/spec/javascripts/deserialize.spec.js @@ -137,6 +137,21 @@ describe('deserializing an object into a form', function() { expect(this.result).to.be.false; }); }); + + describe('and the corresponding value in the given object is null', function() { + beforeEach(function() { + this.view = new this.View(); + this.view.render(); + this.view.$('#the-checkbox').prop('checked', false); + + Backbone.Syphon.deserialize(this.view, {chk: null}); + this.result = this.view.$('#the-checkbox').prop('indeterminate'); + }); + + it('should add an indeterminate attribute', function() { + expect(this.result).to.be.true; + }); + }); }); describe('when deserializing into a button', function() { diff --git a/spec/javascripts/serialize.spec.js b/spec/javascripts/serialize.spec.js index 4931e9d..3647385 100644 --- a/spec/javascripts/serialize.spec.js +++ b/spec/javascripts/serialize.spec.js @@ -158,6 +158,20 @@ describe('serializing a form', function() { expect(this.result.chk).to.be.false; }); }); + + describe('and the checkbox is indeterminate', function() { + beforeEach(function() { + this.view = new this.View(); + this.view.render(); + this.view.$('#the-checkbox').prop('indeterminate', true); + + this.result = Backbone.Syphon.serialize(this.view); + }); + + it('should return an object with a value of null', function() { + expect(this.result.chk).to.be.null; + }); + }); }); describe('when serializing a button', function() { diff --git a/src/backbone.syphon.inputreaders.js b/src/backbone.syphon.inputreaders.js index ccca818..2636d28 100644 --- a/src/backbone.syphon.inputreaders.js +++ b/src/backbone.syphon.inputreaders.js @@ -17,5 +17,5 @@ InputReaders.registerDefault(function($el) { // Checkbox reader, returning a boolean value for // whether or not the checkbox is checked. InputReaders.register('checkbox', function($el) { - return $el.prop('checked'); + return ($el.prop('indeterminate')) ? null : $el.prop('checked'); }); diff --git a/src/backbone.syphon.inputwriters.js b/src/backbone.syphon.inputwriters.js index 7affde5..a84b828 100644 --- a/src/backbone.syphon.inputwriters.js +++ b/src/backbone.syphon.inputwriters.js @@ -17,7 +17,11 @@ InputWriters.registerDefault(function($el, value) { // Checkbox writer, set whether or not the checkbox is checked // depending on the boolean value. InputWriters.register('checkbox', function($el, value) { - $el.prop('checked', value); + if (value === null) { + $el.prop('indeterminate', true); + } else { + $el.prop('checked', value); + } }); // Radio button writer, set whether or not the radio button is From 7a972d071df363fa5e0fcfd801c73a22bf4a5ff3 Mon Sep 17 00:00:00 2001 From: rhubarbselleven Date: Mon, 16 Mar 2015 17:01:29 +1100 Subject: [PATCH 2/5] Allows travis to use docker images for testing --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 6487ac8..6983520 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +sudo: false language: node_js before_install: npm install -g grunt-cli node_js: From 4f8764c92b0c714e98f9e755a97c526bdfe38303 Mon Sep 17 00:00:00 2001 From: rhubarbselleven Date: Tue, 17 Mar 2015 17:11:43 +1100 Subject: [PATCH 3/5] added note about cicular refs. See #33 --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index d607791..5bfa623 100644 --- a/readme.md +++ b/readme.md @@ -437,6 +437,7 @@ For more information on Key Assignment Validators, see the full There some known limitations in Backbone.Syphon, partially by design and partially implemented as default behaviors. * An input of type `checkbox` will return a boolean value. This can be overriden by replacing the Input Reader for checkboxes. +* Yo avoid circular references, care should be taken when using Backbone.Relational. See (#33)[https://github.com/marionettejs/backbone.syphon/issues/33]. ## Building Backbone.Syphon From e270f39e295fd26c253c903097bb07d9d6572448 Mon Sep 17 00:00:00 2001 From: Patrick Bajao Date: Mon, 23 Mar 2015 20:44:32 +0800 Subject: [PATCH 4/5] Serialize multi-select values as an array --- spec/javascripts/serialize.spec.js | 29 ++++++++++++++++++++++++++++- src/backbone.syphon.js | 14 +++++++++----- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/spec/javascripts/serialize.spec.js b/spec/javascripts/serialize.spec.js index 3647385..47e45b3 100644 --- a/spec/javascripts/serialize.spec.js +++ b/spec/javascripts/serialize.spec.js @@ -114,11 +114,38 @@ describe('serializing a form', function() { this.result = Backbone.Syphon.serialize(this.view); }); - it('should have the textarea\'s value', function() { + it('should return the selected option value', function() { expect(this.result.foo).to.equal('bar'); }); }); + describe('when serializing a multi-select box', function() { + beforeEach(function() { + this.View = Backbone.View.extend({ + render: function() { + this.$el.html( + '
' + + '' + + '
' + ); + } + }); + + this.view = new this.View(); + this.view.render(); + + this.result = Backbone.Syphon.serialize(this.view); + }); + + it('should return the selected options values', function() { + expect(this.result.foo).to.deep.equal(['bar1', 'bar3']); + }); + }); + describe('when serializing a checkbox', function() { beforeEach(function() { this.View = Backbone.View.extend({ diff --git a/src/backbone.syphon.js b/src/backbone.syphon.js index f15d9e3..ab37a8f 100644 --- a/src/backbone.syphon.js +++ b/src/backbone.syphon.js @@ -202,11 +202,15 @@ var assignKeyValue = function(obj, keychain, value) { // if it's the last key in the chain, assign the value directly if (keychain.length === 0) { - if (_.isArray(obj[key])) { - obj[key].push(value); - } else { - obj[key] = value; - } + value = _.isArray(value) ? value : [value]; + + _.each(value, function(v) { + if (_.isArray(obj[key])) { + obj[key].push(v); + } else { + obj[key] = v; + } + }); } // recursive parsing of the array, depth-first From e44f85684ad55f01f397bec0a623f7e7ef447304 Mon Sep 17 00:00:00 2001 From: Patrick Bajao Date: Tue, 24 Mar 2015 13:59:08 +0800 Subject: [PATCH 5/5] Adds a spec to make sure it also works when deserializing --- spec/javascripts/deserialize.spec.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/spec/javascripts/deserialize.spec.js b/spec/javascripts/deserialize.spec.js index 56992f6..e2f9454 100644 --- a/spec/javascripts/deserialize.spec.js +++ b/spec/javascripts/deserialize.spec.js @@ -96,6 +96,34 @@ describe('deserializing an object into a form', function() { }); }); + describe('when deserializing into a multi-select box', function() { + beforeEach(function() { + this.View = Backbone.View.extend({ + render: function() { + this.$el.html( + '
' + + '' + + '
' + ); + } + }); + + this.view = new this.View(); + this.view.render(); + + Backbone.Syphon.deserialize(this.view, {foo: ['bar1', 'bar2']}); + this.result = this.view.$('select').val(); + }); + + it('should select the options corresponding to the values in the given object', function() { + expect(this.result).to.deep.equal(['bar1', 'bar2']); + }); + }); + describe('when deserializing into a checkbox', function() { beforeEach(function() { this.View = Backbone.View.extend({