Proper way to call function in JS layer from external listener

When I detect a click on my sprite, I want to call a function in my Layer to generate another sprite.
But I’m not entirely sure how to do that since my listener is defined outside of my layer object.

Should I pass in a reference to my already created HelloWorldLayer2 object into my listener?

var touchListener = cc.EventListener.create({
	event: cc.EventListener.MOUSE,
	onMouseMove: function(event) {
		
	},
	onMouseUp: function(event) {
		var target = event.getCurrentTarget();
		target.handleClick(event);
            //Call the function addCircle in the HelloWorldLayer2 class
            //If I create a new object, I'd have a different layer than the already generated layer
            //HelloWorldLayer2.addCircle() ?
	},
	onMouseDown: function(event) {
	},
	onMouseScroll: function(event) {
	}
});
var HelloWorldLayer2 = cc.Layer.extend({
size: null,
ctor:function () {
    //////////////////////////////
    // 1. super init first
    this._super();
   ...make var spriteOne
   ....other code

  cc.eventManager.addListener(touchListener.clone(), spriteOne);
 }, 
addCircle:function() {
		var circleSprite = new cc.Sprite.create(res.circle);
		circleSprite.setPosition(cc.p(this.size.width/2, this.size.height/2));
		this.addChild(circleSprite);
	}

You could attach spriteOne to the layer, i.e. this.spriteOne = ... rather than var spriteOne = ..., and then use the layer as the node when adding the listener, i.e. cc.eventManager.addListener(touchListener.clone(), this);.

In onMouseUp, access spriteOne by using event.getCurrentTarget().spriteOne and then you can access addCircle by event.getCurrentTarget().addCircle();.

So if I do it that way, would I then have to loop through all the node’s current sprites to determine if the click clicked that specific sprite?

Because right now, I just do

handleClick: function(event) {
	var target = event.getCurrentTarget();
	var locationInNode = target.convertToNodeSpace(event.getLocation());
	var s = target.getContentSize();
	var rect = cc.rect(0, 0, s.width, s.height);
        if(cc.rectContainsPoint(rect, locationInNode)) {
		cc.log("clicked at " + locationInNode.x + ", " + locationInNode.y);
		return true;
	} else {
		return false;
	}

So would I have to change the var target = ... to
a for each sprite in event.getCurrentTarget() check if cc.rectContainsPoint(rect, locationInNode)
and then call the click event for the specific sprite that was clicked?

If you have one sprite you want to check if clicked, if you create the sprite using this.spriteOne rather than var spriteOne, then the name gets attached to the layer. When you get the layer using event.getCurrentTarget(), the sprite can be referred to by name. For example,

// in HelloWorldLayer2 ctor
this.spriteOne = new cc.Sprite("SpriteOne.png");
// in handle click
var layer = event.getCurrentTarget();
var target = layer.spriteOne;

If you have multiple sprites to click, you may wish to add them to a list belonging to the layer and loop through the list.

1 Like