diff --git a/lib/amd/backbone.picky.js b/lib/amd/backbone.picky.js index 213661d..d575a1d 100644 --- a/lib/amd/backbone.picky.js +++ b/lib/amd/backbone.picky.js @@ -92,20 +92,23 @@ this.selected = model; this.selected.select(); - this.trigger("selected", model); + this.trigger("collection:selected", model); }, // Deselect a model, resulting in no model // being selected deselect: function (model) { + var selected; + if (!this.selected) { return; } model = model || this.selected; if (this.selected !== model) { return; } - this.selected.deselect(); - this.trigger("deselected", this.selected); + selected = this.selected; delete this.selected; + this.trigger("collection:deselected", selected); + selected.deselect(); }, //Finds the first selected model in the collection and selects it, @@ -243,15 +246,16 @@ select: function (options) { if (this.selected) { return; } + if (this.collection && _.isFunction(this.collection.select)) { + this.collection.select(this); + } + this.selected = true; if (options && options.silent) { return; } - this.trigger("selected"); + this.trigger("model:selected"); - if (this.collection) { - this.collection.select(this); - } }, // Deselect this model, and tell our @@ -259,15 +263,16 @@ deselect: function (options) { if (!this.selected) { return; } + if (this.collection && _.isFunction(this.collection.deselect)) { + this.collection.deselect(this); + } + this.selected = false; if (options && options.silent) { return; } - this.trigger("deselected"); + this.trigger("model:deselected"); - if (this.collection) { - this.collection.deselect(this); - } }, // Change selected to the opposite of what @@ -304,17 +309,17 @@ length = collection.length; if (selectedLength === length) { - collection.trigger("selected:all", collection); + collection.trigger("collection:selected:all", collection); return; } if (selectedLength === 0) { - collection.trigger("selected:none", collection); + collection.trigger("collection:selected:none", collection); return; } if (selectedLength > 0 && selectedLength < length) { - collection.trigger("selected:some", collection); + collection.trigger("collection:selected:some", collection); return; } }, @@ -333,7 +338,7 @@ } }); if (collection.selected) { - collection.trigger("selected", collection.selected); + collection.trigger("collection:selected", collection.selected); } }, diff --git a/lib/amd/backbone.picky.min.js b/lib/amd/backbone.picky.min.js index 14ff553..3667968 100644 --- a/lib/amd/backbone.picky.min.js +++ b/lib/amd/backbone.picky.min.js @@ -2,4 +2,4 @@ // Copyright (c)2013 Derick Bailey, Muted Solutions, LLC. // Distributed under MIT license // http://github.com/derickbailey/backbone.picky -(function(e,t){typeof define=="function"&&define.amd&&define(["_","Backbone"],t)})(this,function(e,t){return t.Picky=function(e,t){var n={};n.SingleSelect=function(){},n.SingleSelect.mixInto=function(e,r){var s=new n.SingleSelect;t.extend(e,s),r&&r.selectOnAdd&&e.on("add",function(e,t){t.select(e)}),r&&r.selectOnRemove?e.on("remove",function(e,n,i){var s=i.index,o=Math.max(s-1,0),u=Math.min(s,n.length-1);if(n.selected===e){if(t.isFunction(r.selectOnRemove)){r.selectOnRemove(e,n,i);return}if(n.length===0)return;if(r.selectOnRemove==="prev"){n.at(o).select();return}if(r.selectOnRemove==="next"){n.at(u).select();return}}}):e.on("remove",function(e,t){t.selected===e&&delete t.selected}),e.on("reset",function(e,t){t.refreshSelection()}),i(e)},t.extend(n.SingleSelect.prototype,{select:function(e){if(e&&this.selected===e)return;if(!this.some(function(t){return t===e}))return;this.deselect(),this.selected=e,this.selected.select(),this.trigger("selected",e)},deselect:function(e){if(!this.selected)return;e=e||this.selected;if(this.selected!==e)return;this.selected.deselect(),this.trigger("deselected",this.selected),delete this.selected},refreshSelection:function(){i(this)}}),n.MultiSelect=function(){},n.MultiSelect.mixInto=function(e,i){var o=new n.MultiSelect;o.selected={},t.extend(e,o),i&&i.selectOnAdd&&e.on("add",function(e,t){t.select(e)}),e.on("remove",function(e,t){t.selected&&t.selected.hasOwnProperty(e.cid)&&(delete t.selected[e.cid],r(t))}),e.on("reset",function(e,t){t.refreshSelection()}),s(e)},t.extend(n.MultiSelect.prototype,{select:function(e){if(this.selected[e.cid])return;if(!this.some(function(t){return t===e}))return;this.selected[e.cid]=e,e.select(),r(this)},deselect:function(e){if(!this.selected[e.cid])return;delete this.selected[e.cid],e.deselect(),r(this)},selectAll:function(){this.each(function(e){e.select()}),r(this)},deselectAll:function(){if(this.selectedLength===0)return;this.each(function(e){e.deselect()}),r(this)},toggleSelectAll:function(){this.selectedLength===this.length?this.deselectAll():this.selectAll()},refreshSelection:function(){s(this)},getSelected:function(){var e,t=[];for(e in this.selected)this.selected.hasOwnProperty(e)&&t.push(this.selected[e]);return t}}),n.Selectable=function(){},n.Selectable.mixInto=function(e){var r=new n.Selectable;t.extend(e,r)},t.extend(n.Selectable.prototype,{select:function(e){if(this.selected)return;this.selected=!0;if(e&&e.silent)return;this.trigger("selected"),this.collection&&this.collection.select(this)},deselect:function(e){if(!this.selected)return;this.selected=!1;if(e&&e.silent)return;this.trigger("deselected"),this.collection&&this.collection.deselect(this)},toggleSelected:function(e){this.selected?this.deselect(e):this.select(e)},changeSelected:function(e,t){e?this.select(t):this.deselect(t)}});var r=function(e){e.selectedLength=t.size(e.selected);var n=e.selectedLength,r=e.length;if(n===r){e.trigger("selected:all",e);return}if(n===0){e.trigger("selected:none",e);return}if(n>0&&n0&&n 0 && selectedLength < length) { - collection.trigger("selected:some", collection); + collection.trigger("collection:selected:some", collection); return; } }, @@ -327,7 +332,7 @@ Backbone.Picky = (function (Backbone, _) { } }); if (collection.selected) { - collection.trigger("selected", collection.selected); + collection.trigger("collection:selected", collection.selected); } }, diff --git a/lib/backbone.picky.min.js b/lib/backbone.picky.min.js index b98e411..54efb58 100644 --- a/lib/backbone.picky.min.js +++ b/lib/backbone.picky.min.js @@ -2,4 +2,4 @@ // Copyright (c)2013 Derick Bailey, Muted Solutions, LLC. // Distributed under MIT license // http://github.com/derickbailey/backbone.picky -Backbone.Picky=function(e,t){var n={};n.SingleSelect=function(){},n.SingleSelect.mixInto=function(e,r){var s=new n.SingleSelect;t.extend(e,s),r&&r.selectOnAdd&&e.on("add",function(e,t){t.select(e)}),r&&r.selectOnRemove?e.on("remove",function(e,n,i){var s=i.index,o=Math.max(s-1,0),u=Math.min(s,n.length-1);if(n.selected===e){if(t.isFunction(r.selectOnRemove)){r.selectOnRemove(e,n,i);return}if(n.length===0)return;if(r.selectOnRemove==="prev"){n.at(o).select();return}if(r.selectOnRemove==="next"){n.at(u).select();return}}}):e.on("remove",function(e,t){t.selected===e&&delete t.selected}),e.on("reset",function(e,t){t.refreshSelection()}),i(e)},t.extend(n.SingleSelect.prototype,{select:function(e){if(e&&this.selected===e)return;if(!this.some(function(t){return t===e}))return;this.deselect(),this.selected=e,this.selected.select(),this.trigger("selected",e)},deselect:function(e){if(!this.selected)return;e=e||this.selected;if(this.selected!==e)return;this.selected.deselect(),this.trigger("deselected",this.selected),delete this.selected},refreshSelection:function(){i(this)}}),n.MultiSelect=function(){},n.MultiSelect.mixInto=function(e,i){var o=new n.MultiSelect;o.selected={},t.extend(e,o),i&&i.selectOnAdd&&e.on("add",function(e,t){t.select(e)}),e.on("remove",function(e,t){t.selected&&t.selected.hasOwnProperty(e.cid)&&(delete t.selected[e.cid],r(t))}),e.on("reset",function(e,t){t.refreshSelection()}),s(e)},t.extend(n.MultiSelect.prototype,{select:function(e){if(this.selected[e.cid])return;if(!this.some(function(t){return t===e}))return;this.selected[e.cid]=e,e.select(),r(this)},deselect:function(e){if(!this.selected[e.cid])return;delete this.selected[e.cid],e.deselect(),r(this)},selectAll:function(){this.each(function(e){e.select()}),r(this)},deselectAll:function(){if(this.selectedLength===0)return;this.each(function(e){e.deselect()}),r(this)},toggleSelectAll:function(){this.selectedLength===this.length?this.deselectAll():this.selectAll()},refreshSelection:function(){s(this)},getSelected:function(){var e,t=[];for(e in this.selected)this.selected.hasOwnProperty(e)&&t.push(this.selected[e]);return t}}),n.Selectable=function(){},n.Selectable.mixInto=function(e){var r=new n.Selectable;t.extend(e,r)},t.extend(n.Selectable.prototype,{select:function(e){if(this.selected)return;this.selected=!0;if(e&&e.silent)return;this.trigger("selected"),this.collection&&this.collection.select(this)},deselect:function(e){if(!this.selected)return;this.selected=!1;if(e&&e.silent)return;this.trigger("deselected"),this.collection&&this.collection.deselect(this)},toggleSelected:function(e){this.selected?this.deselect(e):this.select(e)},changeSelected:function(e,t){e?this.select(t):this.deselect(t)}});var r=function(e){e.selectedLength=t.size(e.selected);var n=e.selectedLength,r=e.length;if(n===r){e.trigger("selected:all",e);return}if(n===0){e.trigger("selected:none",e);return}if(n>0&&n0&&n true #### Selectable#deselect Deselect a model, setting the model's `selected` attribute to false and -triggering a "deselected" event. +triggering a "model:deselected" event. ```js var myModel = new SelectableModel(); -myModel.on("deselected", function(){ +myModel.on("model:deselected", function(){ console.log("I'm no longer selected!"); }); @@ -145,11 +145,11 @@ Toggles the selection state between selected and deselected. ```js var myModel = new SelectableModel(); -myModel.on("select", function(){ +myModel.on("model:selected", function(){ console.log("I'm selected!"); }); -myModel.on("deselected", function(){ +myModel.on("model:deselected", function(){ console.log("I'm no longer selected!"); }); @@ -165,11 +165,11 @@ If the given _value_ is truthy selects the model, otherwise deselects it. ```js var myModel = new SelectableModel(); -myModel.on("select", function(){ +myModel.on("model:selected", function(){ console.log("I'm selected!"); }); -myModel.on("deselected", function(){ +myModel.on("model:deselected", function(){ console.log("I'm no longer selected!"); }); @@ -191,11 +191,11 @@ currently selected. The following events are triggered from Selectable models -#### "selected" +#### "model:selected" Triggers when a model is selected. -#### "deselected" +#### "model:deselected" Triggers when a model is deselected. @@ -360,12 +360,12 @@ myCol.selected; //=> model The following events are triggered by the SingleSelect based on changes in selection: -#### "selected" +#### "collection:selected" Triggered when a model has been selected. Provides the selected model as the first parameter. -#### "deselected" +#### "collection:deselected" Triggered when a model has been deselected. Provides the deselected model as the first parameter. @@ -505,7 +505,7 @@ The following rules are used when toggling: Updates the selected attribute based on the currently selected items in the MultiSelect collection. This is useful if you add/remove/reset the items in the collection and want to update the selection state afterwards. -Calling this method will trigger the `selected:XXX` events appropriately. +Calling this method will trigger the `collection:selected:XXX` events appropriately. ```js myCol = new MultiCollection(); @@ -572,15 +572,15 @@ myCol.selectedLength; //=> 1 The following events are triggered by the MultiSelect based on changes in selection: -#### "selected:all" +#### "collection:selected:all" Triggered when all models have been selected -#### "selected:none" +#### "collection:selected:none" Triggered when all models have been deselected -#### "selected:some" +#### "collection:selected:some" Triggered when at least 1 model is selected, but less than all models have been selected diff --git a/spec/javascripts/multiSelect.deselect.spec.js b/spec/javascripts/multiSelect.deselect.spec.js index 258d277..080efaa 100644 --- a/spec/javascripts/multiSelect.deselect.spec.js +++ b/spec/javascripts/multiSelect.deselect.spec.js @@ -28,7 +28,7 @@ describe("multi-select collection deselecting", function(){ }); it("should trigger 'none' selected event", function(){ - expect(collection.trigger).toHaveBeenCalledWith("selected:none", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:none", collection); }); it("should have a selected count of 0", function(){ @@ -56,7 +56,7 @@ describe("multi-select collection deselecting", function(){ }); it("should trigger 'none' selected event", function(){ - expect(collection.trigger).toHaveBeenCalledWith("selected:none", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:none", collection); }); it("should have a selected count of 0", function(){ @@ -85,7 +85,7 @@ describe("multi-select collection deselecting", function(){ }); it("should trigger 'none' selected event", function(){ - expect(collection.trigger).toHaveBeenCalledWith("selected:none", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:none", collection); }); it("should have a selected count of 0", function(){ @@ -113,7 +113,7 @@ describe("multi-select collection deselecting", function(){ }); it("should trigger 'none' selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:none", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:none", collection); }); it("should have a selected count of 0", function () { diff --git a/spec/javascripts/multiSelect.options.spec.js b/spec/javascripts/multiSelect.options.spec.js index 27792b6..93b6432 100644 --- a/spec/javascripts/multiSelect.options.spec.js +++ b/spec/javascripts/multiSelect.options.spec.js @@ -25,7 +25,7 @@ }); it("should trigger 'all' selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:all", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:all", collection); }); it("should selected the added model", function () { diff --git a/spec/javascripts/multiSelect.select.spec.js b/spec/javascripts/multiSelect.select.spec.js index d8866af..fb87898 100644 --- a/spec/javascripts/multiSelect.select.spec.js +++ b/spec/javascripts/multiSelect.select.spec.js @@ -1,109 +1,109 @@ -describe("multi-select collection selecting", function(){ - var Model = Backbone.Model.extend({ - initialize: function(){ - Backbone.Picky.Selectable.mixInto(this); - } - }); - - var Collection = Backbone.Collection.extend({ - model: Model, - - initialize: function(){ - Backbone.Picky.MultiSelect.mixInto(this); - } - }); - - describe("when no models are selected, and selecting all", function(){ - var m1, m2, collection; - - beforeEach(function(){ - m1 = new Model(); - m2 = new Model(); - - collection = new Collection([m1, m2]); - spyOn(collection, "trigger").andCallThrough(); - - collection.selectAll(); - }); - - it("should trigger 'all' selected event", function(){ - expect(collection.trigger).toHaveBeenCalledWith("selected:all", collection); +describe("multi-select collection selecting", function () { + var Model = Backbone.Model.extend({ + initialize: function () { + Backbone.Picky.Selectable.mixInto(this); + } }); - it("should have a selected count of 2", function(){ - expect(collection.selectedLength).toBe(2); - }); + var Collection = Backbone.Collection.extend({ + model: Model, - it("should have the first selected model in the selected list", function(){ - expect(collection.selected[m1.cid]).not.toBeUndefined(); + initialize: function () { + Backbone.Picky.MultiSelect.mixInto(this); + } }); - it("should have the second selected model in the selected list", function(){ - expect(collection.selected[m2.cid]).not.toBeUndefined(); - }); - }); + describe("when no models are selected, and selecting all", function () { + var m1, m2, collection; - describe("when 1 model is selected, and selecting all", function(){ - var m1, m2, collection; + beforeEach(function () { + m1 = new Model(); + m2 = new Model(); - beforeEach(function(){ - m1 = new Model(); - m2 = new Model(); + collection = new Collection([m1, m2]); + spyOn(collection, "trigger").andCallThrough(); - collection = new Collection([m1, m2]); - m1.select(); + collection.selectAll(); + }); - spyOn(collection, "trigger").andCallThrough(); - collection.selectAll(); - }); - - it("should trigger 'all' selected event", function(){ - expect(collection.trigger).toHaveBeenCalledWith("selected:all", collection); - }); + it("should trigger 'all' selected event", function () { + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:all", collection); + }); - it("should have a selected count of 2", function(){ - expect(collection.selectedLength).toBe(2); - }); + it("should have a selected count of 2", function () { + expect(collection.selectedLength).toBe(2); + }); - it("should have the first selected model in the selected list", function(){ - expect(collection.selected[m1.cid]).not.toBeUndefined(); - }); + it("should have the first selected model in the selected list", function () { + expect(collection.selected[m1.cid]).not.toBeUndefined(); + }); - it("should have the second selected model in the selected list", function(){ - expect(collection.selected[m2.cid]).not.toBeUndefined(); + it("should have the second selected model in the selected list", function () { + expect(collection.selected[m2.cid]).not.toBeUndefined(); + }); }); - }); - describe("when all models are selected, and selecting all", function(){ - var m1, m2, collection; + describe("when 1 model is selected, and selecting all", function () { + var m1, m2, collection; - beforeEach(function(){ - m1 = new Model(); - m2 = new Model(); + beforeEach(function () { + m1 = new Model(); + m2 = new Model(); - collection = new Collection([m1, m2]); - m1.select(); - m2.select(); + collection = new Collection([m1, m2]); + m1.select(); - spyOn(collection, "trigger").andCallThrough(); - collection.selectAll(); - }); - - it("should trigger 'all' selected event", function(){ - expect(collection.trigger).toHaveBeenCalledWith("selected:all", collection); - }); + spyOn(collection, "trigger").andCallThrough(); + collection.selectAll(); + }); - it("should have a selected count of 2", function(){ - expect(collection.selectedLength).toBe(2); - }); + it("should trigger 'all' selected event", function () { + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:all", collection); + }); - it("should have the first selected model in the selected list", function(){ - expect(collection.selected[m1.cid]).not.toBeUndefined(); + it("should have a selected count of 2", function () { + expect(collection.selectedLength).toBe(2); + }); + + it("should have the first selected model in the selected list", function () { + expect(collection.selected[m1.cid]).not.toBeUndefined(); + }); + + it("should have the second selected model in the selected list", function () { + expect(collection.selected[m2.cid]).not.toBeUndefined(); + }); }); - it("should have the second selected model in the selected list", function(){ - expect(collection.selected[m2.cid]).not.toBeUndefined(); + describe("when all models are selected, and selecting all", function () { + var m1, m2, collection; + + beforeEach(function () { + m1 = new Model(); + m2 = new Model(); + + collection = new Collection([m1, m2]); + m1.select(); + m2.select(); + + spyOn(collection, "trigger").andCallThrough(); + collection.selectAll(); + }); + + it("should trigger 'all' selected event", function () { + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:all", collection); + }); + + it("should have a selected count of 2", function () { + expect(collection.selectedLength).toBe(2); + }); + + it("should have the first selected model in the selected list", function () { + expect(collection.selected[m1.cid]).not.toBeUndefined(); + }); + + it("should have the second selected model in the selected list", function () { + expect(collection.selected[m2.cid]).not.toBeUndefined(); + }); }); - }); }); diff --git a/spec/javascripts/multiSelect.selectable.interaction.spec.js b/spec/javascripts/multiSelect.selectable.interaction.spec.js index 3de1a70..b074a64 100644 --- a/spec/javascripts/multiSelect.selectable.interaction.spec.js +++ b/spec/javascripts/multiSelect.selectable.interaction.spec.js @@ -29,7 +29,7 @@ describe("multi-select selectable interaction", function () { }); it("should trigger 'some' selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:some", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:some", collection); }); it("should have a selected count of 1", function () { @@ -61,7 +61,7 @@ describe("multi-select selectable interaction", function () { }); it("should trigger 'all' selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:all", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:all", collection); }); it("should have a selected count of 2", function () { @@ -91,7 +91,7 @@ describe("multi-select selectable interaction", function () { }); it("should trigger 'none' selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:none", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:none", collection); }); it("should have a selected count of 0", function () { @@ -119,7 +119,7 @@ describe("multi-select selectable interaction", function () { }); it("should trigger 'all' selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:all", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:all", collection); }); it("should have a selected count of 2", function () { @@ -153,7 +153,7 @@ describe("multi-select selectable interaction", function () { }); it("should trigger 'some' selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:some", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:some", collection); }); it("should have a selected count of 1", function () { @@ -186,7 +186,7 @@ describe("multi-select selectable interaction", function () { }); it("should trigger 'none' selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:none", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:none", collection); }); it("should have a selected count of 0", function () { @@ -280,7 +280,7 @@ describe("multi-select selectable interaction", function () { }); it("should trigger 'all' selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:all", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:all", collection); }); it("should have a selected count of 2", function () { @@ -314,7 +314,7 @@ describe("multi-select selectable interaction", function () { }); it("should trigger 'some' selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:some", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:some", collection); }); it("should have a selected count of 1", function () { @@ -347,7 +347,7 @@ describe("multi-select selectable interaction", function () { }); it("should trigger 'none' selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:none", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:none", collection); }); it("should have a selected count of 0", function () { @@ -379,7 +379,7 @@ describe("multi-select selectable interaction", function () { }); it("should trigger `selected:none` event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:none", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:none", collection); }); }); @@ -401,8 +401,8 @@ describe("multi-select selectable interaction", function () { collection.refreshSelection(); }); - it("should trigger `selected:some` event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:some", collection); + it("should trigger `collection:selected:some` event", function () { + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:some", collection); }); it("should have m1 selected in the collection", function () { @@ -430,8 +430,8 @@ describe("multi-select selectable interaction", function () { collection.refreshSelection(); }); - it("should trigger `selected:all` event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected:all", collection); + it("should trigger `collection:selected:all` event", function () { + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:all", collection); }); it("should have all models selected in the collection", function () { diff --git a/spec/javascripts/multiSelect.toggle.spec.js b/spec/javascripts/multiSelect.toggle.spec.js index 3b475f5..2f4543d 100644 --- a/spec/javascripts/multiSelect.toggle.spec.js +++ b/spec/javascripts/multiSelect.toggle.spec.js @@ -27,7 +27,7 @@ describe("multi-select collection toggle", function(){ }); it("should trigger 'all' selected event", function(){ - expect(collection.trigger).toHaveBeenCalledWith("selected:all", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:all", collection); }); it("should have a selected count of 2", function(){ @@ -56,7 +56,7 @@ describe("multi-select collection toggle", function(){ }); it("should trigger 'all' selected event", function(){ - expect(collection.trigger).toHaveBeenCalledWith("selected:all", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:all", collection); }); it("should have a selected count of 2", function(){ @@ -86,7 +86,7 @@ describe("multi-select collection toggle", function(){ }); it("should trigger 'none' selected event", function(){ - expect(collection.trigger).toHaveBeenCalledWith("selected:none", collection); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected:none", collection); }); it("should have a selected count of 0", function(){ diff --git a/spec/javascripts/selectable.spec.js b/spec/javascripts/selectable.spec.js index b7d9aec..d2d58f4 100644 --- a/spec/javascripts/selectable.spec.js +++ b/spec/javascripts/selectable.spec.js @@ -20,7 +20,7 @@ describe("selectable model", function(){ }); it("should notify of selection", function(){ - expect(model.trigger).toHaveBeenCalledWith("selected"); + expect(model.trigger).toHaveBeenCalledWith("model:selected"); }); }); @@ -39,7 +39,7 @@ describe("selectable model", function(){ }); it("should not notify of selection", function () { - expect(model.trigger).not.toHaveBeenCalledWith("selected"); + expect(model.trigger).not.toHaveBeenCalledWith("model:selected"); }); }); @@ -59,7 +59,7 @@ describe("selectable model", function(){ }); it("should not notify of selection", function(){ - expect(model.trigger).not.toHaveBeenCalledWith("selected"); + expect(model.trigger).not.toHaveBeenCalledWith("model:selected"); }); }); @@ -79,7 +79,7 @@ describe("selectable model", function(){ }); it("should notify of deselection", function(){ - expect(model.trigger).toHaveBeenCalledWith("deselected"); + expect(model.trigger).toHaveBeenCalledWith("model:deselected"); }); }); @@ -99,7 +99,7 @@ describe("selectable model", function(){ }); it("should notify of deselection", function () { - expect(model.trigger).not.toHaveBeenCalledWith("deselected"); + expect(model.trigger).not.toHaveBeenCalledWith("model:deselected"); }); }); @@ -118,7 +118,7 @@ describe("selectable model", function(){ }); it("should not notify of deselection", function(){ - expect(model.trigger).not.toHaveBeenCalledWith("deselected"); + expect(model.trigger).not.toHaveBeenCalledWith("model:deselected"); }); }); @@ -138,7 +138,7 @@ describe("selectable model", function(){ }); it("should notify of deselection", function () { - expect(model.trigger).toHaveBeenCalledWith("deselected"); + expect(model.trigger).toHaveBeenCalledWith("model:deselected"); }); }); @@ -158,7 +158,7 @@ describe("selectable model", function(){ }); it("should notify of selection", function () { - expect(model.trigger).toHaveBeenCalledWith("selected"); + expect(model.trigger).toHaveBeenCalledWith("model:selected"); }); }); @@ -178,7 +178,7 @@ describe("selectable model", function(){ }); it("should notify of deselection", function () { - expect(model.trigger).toHaveBeenCalledWith("selected"); + expect(model.trigger).toHaveBeenCalledWith("model:selected"); }); }); @@ -198,7 +198,7 @@ describe("selectable model", function(){ }); it("should not notify of selection", function () { - expect(model.trigger).not.toHaveBeenCalledWith("selected"); + expect(model.trigger).not.toHaveBeenCalledWith("model:selected"); }); }); @@ -218,7 +218,7 @@ describe("selectable model", function(){ }); it("should notify of deselection", function () { - expect(model.trigger).toHaveBeenCalledWith("deselected"); + expect(model.trigger).toHaveBeenCalledWith("model:deselected"); }); }); @@ -238,7 +238,7 @@ describe("selectable model", function(){ }); it("should not notify of deselection", function () { - expect(model.trigger).not.toHaveBeenCalledWith("deselected"); + expect(model.trigger).not.toHaveBeenCalledWith("model:deselected"); }); }); diff --git a/spec/javascripts/singleSelect.options.spec.js b/spec/javascripts/singleSelect.options.spec.js index fb75c61..c51da7f 100644 --- a/spec/javascripts/singleSelect.options.spec.js +++ b/spec/javascripts/singleSelect.options.spec.js @@ -34,7 +34,7 @@ }); it("should have triggered the selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected"); + expect(collection.trigger).toHaveBeenCalledWith("model:selected"); }); @@ -63,7 +63,7 @@ }); it("should have triggered the selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected"); + expect(collection.trigger).toHaveBeenCalledWith("model:selected"); }); it("should have the last model selected", function () { @@ -97,7 +97,7 @@ }); it("should have triggered the selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected"); + expect(collection.trigger).toHaveBeenCalledWith("model:selected"); }); it("should have the last model selected", function () { @@ -132,7 +132,7 @@ }); it("should have triggered the selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected"); + expect(collection.trigger).toHaveBeenCalledWith("model:selected"); }); }); diff --git a/spec/javascripts/singleSelect.spec.js b/spec/javascripts/singleSelect.spec.js index b03e4a7..d2a84c6 100644 --- a/spec/javascripts/singleSelect.spec.js +++ b/spec/javascripts/singleSelect.spec.js @@ -31,7 +31,7 @@ describe("single select collection", function () { }); it("should trigger a selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected", model); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected", model); }); }); @@ -53,7 +53,7 @@ describe("single select collection", function () { }); it("should trigger a selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected", model); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected", model); }); it("should tell the model to select itself", function () { @@ -91,7 +91,7 @@ describe("single select collection", function () { spyOn(collection, "trigger").andCallThrough(); spyOn(m1, "deselect").andCallThrough(); - + m2.select(); }); @@ -100,7 +100,7 @@ describe("single select collection", function () { }); it("should trigger a selected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("selected", m2); + expect(collection.trigger).toHaveBeenCalledWith("collection:selected", m2); }); it("should deselect the first model", function () { @@ -108,7 +108,7 @@ describe("single select collection", function () { }); it("should fire a deselect event for the first model", function () { - expect(collection.trigger).toHaveBeenCalledWith("deselected", m1); + expect(collection.trigger).toHaveBeenCalledWith("collection:deselected", m1); }); }); @@ -137,7 +137,7 @@ describe("single select collection", function () { model.select(); spyOn(collection, "trigger").andCallThrough(); - + collection.deselect(); }); @@ -146,7 +146,7 @@ describe("single select collection", function () { }); it("should trigger a deselected event", function () { - expect(collection.trigger).toHaveBeenCalledWith("deselected", model); + expect(collection.trigger).toHaveBeenCalledWith("collection:deselected", model); }); }); @@ -178,11 +178,11 @@ describe("single select collection", function () { }); it("should not trigger a deselected event for the selected model", function () { - expect(collection.trigger).not.toHaveBeenCalledWith("deselected", m1); + expect(collection.trigger).not.toHaveBeenCalledWith("model:deselected", m1); }); it("should not trigger a deselected event for the non-selected model", function () { - expect(collection.trigger).not.toHaveBeenCalledWith("deselected", m2); + expect(collection.trigger).not.toHaveBeenCalledWith("model:deselected", m2); }); }); @@ -214,11 +214,11 @@ describe("single select collection", function () { }); it("should not trigger a deselected event for the selected model", function () { - expect(collection.trigger).not.toHaveBeenCalledWith("deselected", m1); + expect(collection.trigger).not.toHaveBeenCalledWith("model:deselected", m1); }); it("should not trigger a deselected event for the non-selected model", function () { - expect(collection.trigger).not.toHaveBeenCalledWith("deselected", m2); + expect(collection.trigger).not.toHaveBeenCalledWith("model:deselected", m2); }); }); @@ -309,7 +309,7 @@ describe("single select collection", function () { }); - describe("when removing a selected item no item is slected", function () { + describe("when removing a selected item no item is selected", function () { var collection, model1, model2, model3; beforeEach(function () { diff --git a/src/backbone.picky.js b/src/backbone.picky.js index 2e2d0f8..e6eda6e 100644 --- a/src/backbone.picky.js +++ b/src/backbone.picky.js @@ -82,20 +82,23 @@ Backbone.Picky = (function (Backbone, _) { this.selected = model; this.selected.select(); - this.trigger("selected", model); + this.trigger("collection:selected", model); }, // Deselect a model, resulting in no model // being selected deselect: function (model) { + var selected; + if (!this.selected) { return; } model = model || this.selected; if (this.selected !== model) { return; } - this.selected.deselect(); - this.trigger("deselected", this.selected); + selected = this.selected; delete this.selected; + this.trigger("collection:deselected", selected); + selected.deselect(); }, //Finds the first selected model in the collection and selects it, @@ -233,15 +236,16 @@ Backbone.Picky = (function (Backbone, _) { select: function (options) { if (this.selected) { return; } + if (this.collection && _.isFunction(this.collection.select)) { + this.collection.select(this); + } + this.selected = true; if (options && options.silent) { return; } - this.trigger("selected"); + this.trigger("model:selected"); - if (this.collection) { - this.collection.select(this); - } }, // Deselect this model, and tell our @@ -249,15 +253,16 @@ Backbone.Picky = (function (Backbone, _) { deselect: function (options) { if (!this.selected) { return; } + if (this.collection && _.isFunction(this.collection.deselect)) { + this.collection.deselect(this); + } + this.selected = false; if (options && options.silent) { return; } - this.trigger("deselected"); + this.trigger("model:deselected"); - if (this.collection) { - this.collection.deselect(this); - } }, // Change selected to the opposite of what @@ -294,17 +299,17 @@ Backbone.Picky = (function (Backbone, _) { length = collection.length; if (selectedLength === length) { - collection.trigger("selected:all", collection); + collection.trigger("collection:selected:all", collection); return; } if (selectedLength === 0) { - collection.trigger("selected:none", collection); + collection.trigger("collection:selected:none", collection); return; } if (selectedLength > 0 && selectedLength < length) { - collection.trigger("selected:some", collection); + collection.trigger("collection:selected:some", collection); return; } }, @@ -323,7 +328,7 @@ Backbone.Picky = (function (Backbone, _) { } }); if (collection.selected) { - collection.trigger("selected", collection.selected); + collection.trigger("collection:selected", collection.selected); } },