Skip to content

Commit

Permalink
Support existing 'events' attribute as function
Browse files Browse the repository at this point in the history
Stickit binds to form and contentEditable element changes by adding
bindings to a view's 'events' attribute, which may already exist on the view.

This commit updates stickit() to support an existing 'events' attribute
that is specified as a function, which is already allowed by Backbone.
  • Loading branch information
trabianmatt committed Jan 17, 2013
1 parent 8baa62d commit f1d1cb1
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 5 deletions.
16 changes: 11 additions & 5 deletions backbone.stickit.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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))
Expand All @@ -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) {
Expand Down
112 changes: 112 additions & 0 deletions test/bindData.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'});
Expand Down

0 comments on commit f1d1cb1

Please sign in to comment.