Famous / Famous/engine

node.emit() does not emit to children that have onRecieve set as a component

Open
#428 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
1.7k
Forks
249
PR merge metrics
No merged PRs in 30d

Description

Hello,

The function `node.emit()` doesn't send an event to children that have an `onReceive` function added as a component:

For example:

``` javascript
FamousEngine.init();

// Initialize with a scene; then, add a 'node' to the scene root
var scene = FamousEngine.createScene();
var rootNode = scene.addChild();

rootNode.onReceive = function(event, payload) {
if(event==='click'){
rootNode.emit('custom_event',payload);
}
};

var myNode = rootNode.addChild();
myNode.setSizeMode('absolute', 'absolute')
.setAbsoluteSize(160, 160)
.setPosition(0,0,0);
myNode.addUIEvent('click');

var boxElement = new DOMElement(myNode);
boxElement.setProperty('background', '#bbb');
boxElement.setContent('Click Me');

var myComponent = {
id: null,
node: null,
onMount: function (node) {
this.id = node.addComponent(this);
this.node = node;
},
onReceive: function (event, payload) {
console.log('received: ',event,payload);
}
};

myNode.addComponent(myComponent);
```

Expected console output:

``` javascript
received: click MouseEvent {type: "click", defaultPrevented: false, timeStamp: 1437079352167, detail: 1, screenX: 30…}
received: custom_event MouseEvent {type: "click", defaultPrevented: false, timeStamp: 1437079352167, detail: 1, screenX: 30…}
```

Actual console output:

``` javascript
received: click MouseEvent {type: "click", defaultPrevented: false, timeStamp: 1437079352167, detail: 1, screenX: 30…}
```

This is due to an issue in `Dispatch.prototype.dispatch` which only emits an event to a child of the emitter if that child has onReceive set as a direct or prototype function. I've modified the `Dispatch.prototype.dispatch` function to also emit to any components of the child that have an onRecieve direct or prototype function.

``` javascript
/**
* dispatch takes an event name and a payload and dispatches it to the
* entire scene graph below the node that the dispatcher is on. The nodes
* receive the events in a breadth first traversal, meaning that parents
* have the opportunity to react to the event before children.
*
* @param {String} path path of the node to send the event to
* @param {String} event name of the event
* @param {Any} payload data associated with the event
*
* @return {undefined} undefined
*/
Dispatch.prototype.dispatch = function dispatch (path, event, payload) {
if (!path) throw new Error('dispatch requires a path as it\'s first argument');
if (!event) throw new Error('dispatch requires an event name as it\'s second argument');

var node = this._nodes[path];
if (!node)
throw new Error('No node registered at path: ' + path);

this.addChildrenToQueue(node);
var child;

while ((child = this.breadthFirstNext())){
if (child && child.onReceive){
child.onReceive(event, payload);
// added this to cover the case when onReceive is added as a component
} else if (child){
for(var i = 0; i < child.getComponents().length; i++){
if (child._components[i].onReceive) {
child._components[i].onReceive(event, payload);
}
}
}
}
};
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.