diff --git a/backbone.stickit.js b/backbone.stickit.js index 192e602..bfcd9e7 100644 --- a/backbone.stickit.js +++ b/backbone.stickit.js @@ -33,7 +33,13 @@ this.unstickModel(model); - this.events || (this.events = {}); + // this.events may be a function, but we want to add new event bindings + // to it. Creating our own stickitEvents property allows us to add + // bindings while allowing this.events to remain a function. This also + // supports multiple calls to stickit() in a single Backbone View. + this.stickitEvents = _(_.result(this, 'events') || {}).extend( + this.stickitEvents + ); // Iterate through the selectors in the bindings configuration and configure // the various options for each field. @@ -116,7 +122,7 @@ if (isFormEl($el) || isContenteditable($el)) { // Bind events to the element which will update the model with changes. _.each(config.eventsOverride || getModelEvents($el), function(type) { - self.events[type+'.stickit '+selector] = function() { + self.stickitEvents[type+'.stickit '+selector] = function() { var val = getElVal($el, isContenteditable($el)); // Don't update the model if false is returned from the `updateModel` configuration. if (evaluateBoolean(self, config.updateModel, val, modelAttr)) @@ -137,9 +143,9 @@ updateViewBindEl(self, $el, config, getVal(model, modelAttr, config, self), model, true); } }); - - // We added to `this.events` so we need to re-delegate. - this.delegateEvents(); + + // We added to `this.stickitEvents` so we need to re-delegate. + this.delegateEvents(this.stickitEvents); // Wrap remove so that we can remove model events when this view is removed. this.remove = _.wrap(this.remove, function(oldRemove) { diff --git a/test/bindData.js b/test/bindData.js index 3a9cd43..791e06e 100644 --- a/test/bindData.js +++ b/test/bindData.js @@ -220,6 +220,118 @@ $(document).ready(function() { equal(model2.get('candy'), 'butterfinger'); }); + test('stickit (existing events property as hash with multiple models and bindings)', function() { + + var model1, testView; + + model1 = new (Backbone.Model)({id:1, candy:'twix' }); + model2 = new (Backbone.Model)({id:2, candy:'snickers'}); + + testView = new (Backbone.View.extend({ + + initialize: function() { + this.model = model1; + this.otherModel = model2; + }, + + events: { + click: 'handleClick' + }, + + bindings: { + '#test0-textarea': 'candy' + }, + + otherBindings: { + '#test0-input': 'candy' + }, + + render: function() { + var html = document.getElementById('jst0').innerHTML; + this.$el.html(_.template(html)()); + this.stickit(); + this.stickit(this.otherModel, this.otherBindings); + return this; + }, + + handleClick: function() { + this.clickHandled = true; + } + + }))(); + + $('#qunit-fixture').html(testView.render().el); + + testView.$('#test0-textarea').val('kit kat').keyup(); + testView.$('#test0-input').val('butterfinger').keyup(); + + equal(model1.get('candy'), 'kit kat'); + equal(model2.get('candy'), 'butterfinger'); + + testView.$el.click(); + + equal(testView.clickHandled, true); + + }); + + test('stickit (existing events property as function with multiple models and bindings)', function() { + + var model1, testView; + + model1 = new (Backbone.Model)({id:1, candy:'twix' }); + model2 = new (Backbone.Model)({id:2, candy:'snickers'}); + + testView = new (Backbone.View.extend({ + + initialize: function() { + this.model = model1; + this.otherModel = model2; + }, + + events: function() { + + var self = this; + + return { + click: function() { + self.clickHandled = true; + } + }; + + }, + + bindings: { + '#test0-textarea': 'candy' + }, + + otherBindings: { + '#test0-input': 'candy' + }, + + render: function() { + var html = document.getElementById('jst0').innerHTML; + this.$el.html(_.template(html)()); + this.stickit(); + this.stickit(this.otherModel, this.otherBindings); + return this; + } + + }))(); + + $('#qunit-fixture').html(testView.render().el); + + testView.$('#test0-textarea').val('kit kat').keyup(); + testView.$('#test0-input').val('butterfinger').keyup(); + + equal(model1.get('candy'), 'kit kat'); + equal(model2.get('candy'), 'butterfinger'); + + testView.$el.click(); + + equal(testView.clickHandled, true); + + }); + test('bindings:setOptions', function() { model.set({'water':'fountain'});