diff --git a/src/Node.js b/src/Node.js index 0d5b333a..d679a1a2 100644 --- a/src/Node.js +++ b/src/Node.js @@ -572,24 +572,22 @@ } }, /** - * simulate event with event bubbling - * @name simulate - * @methodOf Kinetic.Node.prototype - * @param {String} eventType - * @param {EventObject} evt event object - */ - simulate: function(eventType, evt) { - this._handleEvent(eventType, evt || {}); - }, - /** - * synthetically fire an event. The event object will not bubble up the Node tree. You can also pass in custom properties + * fire event * @name fire * @methodOf Kinetic.Node.prototype - * @param {String} eventType - * @param {Object} obj optional object which can be used to pass parameters + * @param {String} eventType event type. can be a regular event, like click, mouseover, or mouseout, or it can be a custom event, like myCustomEvent + * @param {EventObject} evt event object + * @param {Boolean} preventBubble setting the value to false, or leaving it undefined, will result in the event bubbling. Setting the value to true will result in the event not bubbling. */ - fire: function(eventType, obj) { - this._executeHandlers(eventType, obj || {}); + fire: function(eventType, evt, preventBubble) { + // no bubble + if (preventBubble) { + this._executeHandlers(eventType, evt || {}); + } + // bubble + else { + this._handleEvent(eventType, evt || {}); + } }, /** * get absolute transform of the node which takes into @@ -889,9 +887,7 @@ } if(okayToRun) { - if(el[eventType]) { - this.fire(eventType, evt); - } + this._executeHandlers(eventType, evt); // simulate event bubbling if(evt && !evt.cancelBubble && this.parent) { @@ -905,10 +901,14 @@ } }, _executeHandlers: function(eventType, evt) { - var events = this.eventListeners[eventType]; - var len = events.length; - for(var i = 0; i < len; i++) { - events[i].handler.apply(this, [evt]); + var events = this.eventListeners[eventType], + len, i; + + if (events) { + len = events.length; + for(i = 0; i < len; i++) { + events[i].handler.apply(this, [evt]); + } } } }; diff --git a/tests/js/unit/containerTests.js b/tests/js/unit/containerTests.js index 6ea424b2..9f66a115 100644 --- a/tests/js/unit/containerTests.js +++ b/tests/js/unit/containerTests.js @@ -247,9 +247,9 @@ Test.Modules.CONTAINER = { shapes.on('mouseover', function() { a++; }); - circle.simulate('mouseover'); + circle.fire('mouseover'); test(a === 1, 'listener should have fired for circle'); - rect.simulate('mouseover'); + rect.fire('mouseover'); test(a === 2, 'listener should have fired for rect'); }, 'test ids and names hashes': function(containerId) { diff --git a/tests/js/unit/nodeTests.js b/tests/js/unit/nodeTests.js index 12145132..9e48d9eb 100644 --- a/tests/js/unit/nodeTests.js +++ b/tests/js/unit/nodeTests.js @@ -253,9 +253,9 @@ Test.Modules.NODE = { // test user event binding cloning test(clicks.length === 0, 'no clicks should have been triggered yet'); - rect.simulate('click'); + rect.fire('click'); test(clicks.toString() === 'myRect', 'only myRect should have been clicked on'); - clone.simulate('click'); + clone.fire('click'); test(clicks.toString() === 'myRect,rectClone', 'click order should be myRect followed by rectClone'); }, 'clone a group': function(containerId) { @@ -351,16 +351,16 @@ Test.Modules.NODE = { // test user event binding cloning test(clicks.length === 0, 'no clicks should have been triggered yet'); - group.simulate('click'); + group.fire('click'); test(clicks.toString() === 'myGroup', 'only myGroup should have been clicked on'); - clone.simulate('click'); + clone.fire('click'); test(clicks.toString() === 'myGroup,groupClone', 'click order should be myGroup followed by groupClone'); // test user event binding cloning on children test(taps.length === 0, 'no taps should have been triggered yet'); - group.get('.myRect')[0].simulate('tap'); + group.get('.myRect')[0].fire('tap'); test(taps.toString() === 'group rect', 'only group rect should have been tapped on'); - clone.get('.myRect')[0].simulate('tap'); + clone.get('.myRect')[0].fire('tap'); test(taps.toString() === 'group rect,clone rect', 'tap order should be group rect followed by clone rect'); stage.draw(); @@ -1547,7 +1547,7 @@ Test.Modules.NODE = { stage.setListening(false); test(!rect.isListening(), 'rect should not be listening because stage is not listening'); }, - 'test simulate and fire event': function(containerId) { + 'test fire event': function(containerId) { var stage = new Kinetic.Stage({ container: containerId, width: 578, @@ -1587,15 +1587,17 @@ Test.Modules.NODE = { layer.on('click', function() { clicks.push('layer'); }); - // simulated event - circle.simulate('click'); + // fire event with bubbling + circle.fire('click'); + + //console.log(clicks); - test(clicks.toString() == 'circle,layer', 'problem with simulate'); + test(clicks.toString() == 'circle,layer', 'problem with fire 1'); // synthetic event - circle.fire('click'); + circle.fire('click', null, true); - test(clicks.toString() == 'circle,layer,circle', 'problem with fire'); + test(clicks.toString() == 'circle,layer,circle', 'problem with fire 2'); // test custom event circle.fire('customEvent', { @@ -1603,6 +1605,9 @@ Test.Modules.NODE = { }); test(foo === 'bar', 'problem with customEvent param passing'); + + // test fireing custom event that doesn't exist. script should not fail + circle.fire('kaboom'); }, 'add remove event': function(containerId) { @@ -1716,7 +1721,7 @@ Test.Modules.NODE = { clicks.push('layer'); }); - circle.simulate('click'); + circle.fire('click'); test(clicks[0] === 'circle', 'circle event should be fired first'); test(clicks[1] === 'layer', 'layer event should be fired second');