1

I've tried to write a simple coffeescript script. It uses easeljs to spawn a small grey circle when the user clicks the mouse. Here's the code

$(window).load ->
    game.init()


game=
    init: ->
        canvas= document.getElementById("Canvas")
        alert(canvas)
        @stage= new createjs.Stage(canvas)
        alert(@stage)

        @testshape= new createjs.Shape()
        @testshape.graphics.beginFill("#555")
        @testshape.graphics.rect(50,50,500,500)

        @stage.addChild(@testshape)
        @stage.update()

        window.onmousedown= (ev)->
            alert "click"
            mx=ev.screenX
            my=ev.screenY
            @spawn({x:mx,y:my})

    spawn: (data)->
        alert("spawn")
        x=data.x
        y=data.y

        shape = new createjs.Shape()
        shape.graphics.beginFill("#555")
        shape.graphics.circle(x,y,5)
        @stage.addChild(shape)
        @stage.update()

The first two alert calls work fine. And the testshape is created correctly. The callback is also registered fine: A mouse click prompts the alert "click". But the method spawn is never called. I didn't understand why and took a look at the generated javascript:

// Generated by CoffeeScript 1.6.1
(function() {
  var game;

  $(window).load(function() {
    return game.init();
  });

  game = {
    gameObjects: [],
    init: function() {
      var canvas;
      canvas = document.getElementById("Canvas");
      alert(canvas);
      this.stage = new createjs.Stage(canvas);
      alert(this.stage);
      this.testshape = new createjs.Shape();
      this.testshape.graphics.beginFill("#555");
      this.testshape.graphics.rect(50, 50, 500, 500);
      this.stage.addChild(this.testshape);
      this.stage.update();
      return window.onmousedown = function(ev) {
        var mx, my;
        alert("click");
        mx = ev.screenX;
        my = ev.screenY;
        return this.spawn({
          x: mx,
          y: my
        });
      };
    },
    spawn: function(data) {
      var shape, x, y;
      alert("rpcspawn");
      x = data.x;
      y = data.y;
      shape = new createjs.Shape();
      shape.graphics.beginFill("#555");
      shape.graphics.circle(x, y, 5);
      this.stage.addChild(shape);
      return this.stage.update();
    }
  };

}).call(this);

The javascript seems functional. Why is spawn not called ?

UPDATE: I've changed the code to

window.onmousedown=(ev)=>

Now the method is called correctly. But inside the method other members are not available. This alert inside spawn

alert(@stage)

Returns "undefined". I've modified spawn, too. It now uses the thick arrow syntax as well. But that didn't solve the problem. Only one method remained: init . Naturally I tried to change init to thick arrow syntax. But with all three methods using thick arrows, the original problem is back: spawn is not called.

  • If only the callback and optionally spawn use thick arrows, spawn is called correctly.
  • If init uses a thick arrow, spawn can't be called.
  • In no case other members are accessible from inside of spawn.

UPDATE: I changed this to OOP programming. Game is now a class and the solution with thick arrows works

lhk
  • 27,458
  • 30
  • 122
  • 201

2 Answers2

3

Change your code to:

window.onmousedown= (ev)=>
        alert "click"
        mx=ev.screenX
        my=ev.screenY
        @spawn({x:mx,y:my})

(Note the =).

The problem is that, when called in the context of an event handler, @ (a.k.a. this in JavaScript) is window, not game.

Using => binds the method to game.

Craig Stuntz
  • 125,891
  • 12
  • 252
  • 273
  • 1
    Minor nitpick: `this` is actually `window` in the `onmousedown` handler, rather than the event. – Linus Thiel Mar 14 '13 at 12:57
  • @LinusGThiel: Correct! I'll change that. – Craig Stuntz Mar 14 '13 at 13:04
  • This doesn't work as expected. spawn is called correctly but inside of the method spawn, other members are not available. I'll update my question accordingly – lhk Mar 15 '13 at 10:02
  • Well, it solved your first problem. But now you have a different problem. Inside `spawn`, inspect `this`. What is it? It should be `game`. Is is 1) not actually `game`, or 2) `game`, but not fully initialized? – Craig Stuntz Mar 15 '13 at 11:49
  • 1
    after implementing game as a class the solution works. I will gladly accept your answer. I already upvoted, so the fact that the answer is only accepted but not upvoted again does not mean that I don't appreciate your efforts – lhk Mar 16 '13 at 14:09
  • hello sir, just dropping by, and maybe you have an idea and can help me on [\[this question\]](http://stackoverflow.com/questions/16083165/ef5-code-first-detect-if-it-creates-a-database-so-i-can-run-alter-statements) thanks.. – John Woo Apr 18 '13 at 13:37
0

The problem here is that this, where you call this.spawn() inside your window.onmousedown callback, is actually the window object, not your game object.

You should do something like

var that = this;
return window.onmousedown = function(ev) {
    var mx, my;
    alert("click");
    mx = ev.screenX;
    my = ev.screenY;
    return that.spawn({
      x: mx,
      y: my
    });
  };
Matteo Tassinari
  • 18,121
  • 8
  • 60
  • 81