Skip to content
This repository has been archived by the owner on Mar 11, 2024. It is now read-only.

Commit

Permalink
Changing the unbind logic in databind to only remove its own events
Browse files Browse the repository at this point in the history
Removed the destroy-bindings logic on the controller
Added destroy-bindings on the model
Added Update and Options to unbind as well as some corresponding unit
tests
  • Loading branch information
nathanpalmer committed Jul 19, 2012
1 parent ba64fe4 commit 3010bc3
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 101 deletions.
72 changes: 72 additions & 0 deletions spec/SpineDataBindSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,38 @@ describe("Spine.DataBind", function() {
var firstNameInputText = firstNameInput.val();
expect(firstNameInputText).toBe("Eric");
});

it("should unbind without destroying other bindings", function() {
var firstNameDiv = $('#firstNameDiv');
var firstNameDivText = firstNameDiv.text();
if (Watch) {
Person.bind("update[firstName]", function() { console.log("update"); });
expect(Person.constructor._callbacks["update[firstName]"].length).toBe(6);
Person.trigger("destroy-bindings");
expect(Person.constructor._callbacks["update[firstName]"].length).toBe(1);
} else {
Person.bind("change", function() { console.log("update"); });
expect(Person.constructor._callbacks["change"].length).toBe(6);
Person.trigger("destroy-bindings");
expect(Person.constructor._callbacks["change"].length).toBe(1);
}
});

it("should rebind without destroying other bindings", function() {
var firstNameDiv = $('#firstNameDiv');
var firstNameDivText = firstNameDiv.text();
if (Watch) {
Person.bind("update[firstName]", function() { console.log("update"); });
expect(Person.constructor._callbacks["update[firstName]"].length).toBe(6);
Controller.refreshBindings(Person);
expect(Person.constructor._callbacks["update[firstName]"].length).toBe(6);
} else {
Person.bind("change", function() { console.log("update"); });
expect(Person.constructor._callbacks["change"].length).toBe(6);
Controller.refreshBindings(Person);
expect(Person.constructor._callbacks["change"].length).toBe(6);
}
});
};

describe("with bindings", function() {
Expand Down Expand Up @@ -308,6 +340,46 @@ describe("Spine.DataBind", function() {
companySelect.trigger("change");
expect(Person.company).toBe("0");
});

it("should unbind without destroying other bindings", function() {
var phoneNumberSelect = $('#phoneNumbers');
var phoneNumberHtml = [
'<option value="555-555-1010">555-555-1010</option>',
'<option value="555-101-9999">555-101-9999</option>'
].join("");

if (Watch) {
Person.bind("update[phoneNumbers]", function() { console.log("update"); });
expect(Person.constructor._callbacks["update[phoneNumbers]"].length).toBe(2);
Person.trigger("destroy-bindings");
expect(Person.constructor._callbacks["update[phoneNumbers]"].length).toBe(1);
} else {
Person.bind("update", function() { console.log("update"); });
expect(Person.constructor._callbacks["update"].length).toBe(3);
Person.trigger("destroy-bindings");
expect(Person.constructor._callbacks["update"].length).toBe(1);
}
});

it("should rebind without destroying other bindings", function() {
var phoneNumberSelect = $('#phoneNumbers');
var phoneNumberHtml = [
'<option value="555-555-1010">555-555-1010</option>',
'<option value="555-101-9999">555-101-9999</option>'
].join("");

if (Watch) {
Person.bind("update[phoneNumbers]", function() { console.log("update"); });
expect(Person.constructor._callbacks["update[phoneNumbers]"].length).toBe(2);
Controller.refreshBindings(Person);
expect(Person.constructor._callbacks["update[phoneNumbers]"].length).toBe(2);
} else {
Person.bind("update", function() { console.log("update"); });
expect(Person.constructor._callbacks["update"].length).toBe(3);
Controller.refreshBindings(Person);
expect(Person.constructor._callbacks["update"].length).toBe(3);
}
});
};

describe("with bindings", function() {
Expand Down
84 changes: 52 additions & 32 deletions src/spine.databind.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,18 @@ class Update extends Template

bind: (operators,model,el,options) ->
el.bind("change", => @change(operators,model,el,options))
if options.watch
model.bind("update["+operator.property+"]", => @update([operator],model,el,options)) for operator in operators
else
model.bind("change", => @update(operators,model,el,options))

for operator in operators
event = if options.watch then "update["+operator.property+"]" else "change"
model.constructor.bind(event, binder = () => @update([operator],model,el,options))
model.constructor.bind("destroy-bindings", unbinder = (record) =>
if record && model.eql(record)
model.constructor.unbind(event,binder)
model.constructor.unbind("destroy-bindings", unbinder)
)

@update(operators,model,el,options)

unbind: (operators,model,el,options) ->
el.unbind("change")
if options.watch
model.unbind("update["+operator.property+"]") for operator in operators
else
model.unbind("update")

change: (operators,model,el,options) ->
binder = @
el.each () ->
Expand Down Expand Up @@ -79,25 +78,38 @@ class Options extends Template
if options.watch
ops = operators.filter((e) -> e.name is "options")[0]
opsSelected = operators.filter((e) -> e.name is "selectedOptions")[0]
model.bind("update["+ops.property+"]", => @update([ops,opsSelected],model,el,options))
model.bind("update["+opsSelected.property+"]", => @update([ops,opsSelected],model,el,options))

# ops
opsEvent = "update["+ops.property+"]"
model.constructor.bind(opsEvent, opsUpdateBinder = () => @update([ops,opsSelected],model,el,options))
model.constructor.bind("destroy-bindings", opsUpdateUnbinder = (record) =>
if record && model.eql(record)
console.log("unbind " + opsEvent)
model.constructor.unbind(opsEvent,opsUpdateBinder)
model.constructor.unbind("destroy-bindings", opsUpdateUnbinder)
)

# opsSelected
opsSelectedEvent = "update["+opsSelected.property+"]"
model.constructor.bind(opsSelectedEvent, opsSelectedBinder = () => @update([ops,opsSelected],model,el,options))
model.constructor.bind("destroy-bindings", opsSelectedUnbinder = (record) =>
if record && model.eql(record)
model.constructor.unbind(opsSelectedEvent,opsSelectedBinder)
model.constructor.unbind("destroy-bindings", opsSelectedUnbinder)
)
else
model.bind("update", => @update(operators,model,el,options))
model.constructor.bind("update", binder = () => @update(operators,model,el,options))
model.constructor.bind("destroy-bindings", unbinder = (record) =>
if record && model.eql(record)
model.constructor.unbind("update",binder)
model.constructor.unbind("destroy-bindings", unbinder)
)

@update(operators,model,el,options)

if operators.some((e) -> e.name is "selectedOptions")
el.bind("change", => @change(operators,model,el,options))

unbind: (operators,model,el,options) ->
el.unbind("change") if operators.some((e) -> e.name is "selectedOptions")
if options.watch
ops = operators.filter((e) -> e.name is "options")[0]
opsSelected = operators.filter((e) -> e.name is "selectedOptions")[0]
model.unbind("update["+ops.property+"]")
model.unbind("update["+opsSelected.property+"]")
else
model.unbind("update")

update: (operators,model,el,options) ->
ops = operators.filter((e) -> e.name is "options")[0]
opsSelected = operators.filter((e) -> e.name is "selectedOptions")
Expand Down Expand Up @@ -247,18 +259,22 @@ class Checked extends Template
el.bind("change", => @change(operators,model,el,options))

if options.watch
model.bind("update["+operator.property+"]", => @update([operator],model,el,options)) for operator in operators
model.bind("update["+operator.property+"]", binder = => @update([operator],model,el,options)) for operator in operators
model.bind("destroy-bindings", (record) =>
if record && model.eql(record)
model.constructor.unbind("update["+operator.property+"]",binder)
)
else
model.bind("change", => @update(operators,model,el,options))

@update(operators,model,el,options)

unbind: (operators,model,el,options) ->
el.unbind("change")
if options.watch
model.unbind("update["+operator.property+"]") for operator in operators
else
model.unbind("change")
#el.unbind("change")
#if options.watch
# model.unbind("update["+operator.property+"]", => @update([operator],model,el,options)) for operator in operators
#else
# model.unbind("change")

change: (operators,model,el,options) ->
operator = operators.filter((e) -> e.name is "checked")[0]
Expand Down Expand Up @@ -299,6 +315,9 @@ DataBind =
@trigger "destroy-bindings"

model = this.model if not model
return if not model

model.trigger "destroy-bindings"

controller = this
splitter = /(\w+)(\\[.*])? (.*)/
Expand Down Expand Up @@ -365,8 +384,9 @@ DataBind =
element.binder.bind(operators,model,el,options)
controller.bind "destroy", ->
element.binder.unbind(operators,model,el,options)
controller.bind "destroy-bindings", ->
element.binder.unbind(operators,model,el,options)
#controller.bind "destroy-bindings", ->
# element.binder.unbind(operators,model,el,options)


trim = (s) ->
s.replace(/^\s+|\s+$/g,"")
Expand Down
Loading

0 comments on commit 3010bc3

Please sign in to comment.