1 describe('Binding: Event', {
2 before_each: JSSpec.prepareTestNode,
4 'Should invoke the supplied function when the event occurs, using model as \'this\' param and first arg, and event as second arg': function () {
7 firstHandler: function (passedModel, evt) {
8 value_of(evt.type).should_be("click");
9 value_of(this).should_be(model);
10 value_of(passedModel).should_be(model);
12 value_of(model.firstWasCalled).should_be(false);
13 model.firstWasCalled = true;
16 secondWasCalled: false,
17 secondHandler: function (passedModel, evt) {
18 value_of(evt.type).should_be("mouseover");
19 value_of(this).should_be(model);
20 value_of(passedModel).should_be(model);
22 value_of(model.secondWasCalled).should_be(false);
23 model.secondWasCalled = true;
26 testNode.innerHTML = "<button data-bind='event:{click:firstHandler, mouseover:secondHandler, mouseout:null}'>hey</button>";
27 ko.applyBindings(model, testNode);
28 ko.utils.triggerEvent(testNode.childNodes[0], "click");
29 value_of(model.firstWasCalled).should_be(true);
30 value_of(model.secondWasCalled).should_be(false);
31 ko.utils.triggerEvent(testNode.childNodes[0], "mouseover");
32 value_of(model.secondWasCalled).should_be(true);
33 ko.utils.triggerEvent(testNode.childNodes[0], "mouseout"); // Shouldn't do anything (specifically, shouldn't throw)
36 'Should prevent default action': function () {
37 testNode.innerHTML = "<a href='http://www.example.com/' data-bind='event: { click: function() { } }'>hey</button>";
38 ko.applyBindings(null, testNode);
39 ko.utils.triggerEvent(testNode.childNodes[0], "click");
40 // Assuming we haven't been redirected to http://www.example.com/, this spec has now passed
43 'Should let bubblable events bubble to parent elements by default': function() {
45 innerWasCalled: false, innerDoCall: function () { this.innerWasCalled = true; },
46 outerWasCalled: false, outerDoCall: function () { this.outerWasCalled = true; }
48 testNode.innerHTML = "<div data-bind='event:{click:outerDoCall}'><button data-bind='event:{click:innerDoCall}'>hey</button></div>";
49 ko.applyBindings(model, testNode);
50 ko.utils.triggerEvent(testNode.childNodes[0].childNodes[0], "click");
51 value_of(model.innerWasCalled).should_be(true);
52 value_of(model.outerWasCalled).should_be(true);
55 'Should be able to prevent bubbling of bubblable events using the (eventname)Bubble:false option': function() {
57 innerWasCalled: false, innerDoCall: function () { this.innerWasCalled = true; },
58 outerWasCalled: false, outerDoCall: function () { this.outerWasCalled = true; }
60 testNode.innerHTML = "<div data-bind='event:{click:outerDoCall}'><button data-bind='event:{click:innerDoCall}, clickBubble:false'>hey</button></div>";
61 ko.applyBindings(model, testNode);
62 ko.utils.triggerEvent(testNode.childNodes[0].childNodes[0], "click");
63 value_of(model.innerWasCalled).should_be(true);
64 value_of(model.outerWasCalled).should_be(false);
67 'Should be able to supply handler params using "bind" helper': function() {
68 // Using "bind" like this just eliminates the function literal wrapper - it's purely stylistic
69 var didCallHandler = false, someObj = {};
70 var myHandler = function() {
71 value_of(this).should_be(someObj);
72 value_of(arguments.length).should_be(5);
74 // First x args will be the ones you bound
75 value_of(arguments[0]).should_be(123);
76 value_of(arguments[1]).should_be("another");
77 value_of(arguments[2].something).should_be(true);
79 // Then you get the args we normally pass to handlers, i.e., the model then the event
80 value_of(arguments[3]).should_be(viewModel);
81 value_of(arguments[4].type).should_be("mouseover");
83 didCallHandler = true;
85 testNode.innerHTML = "<button data-bind='event:{ mouseover: myHandler.bind(someObj, 123, \"another\", { something: true }) }'>hey</button>";
86 var viewModel = { myHandler: myHandler, someObj: someObj };
87 ko.applyBindings(viewModel, testNode);
88 ko.utils.triggerEvent(testNode.childNodes[0], "mouseover");
89 value_of(didCallHandler).should_be(true);