I am having some issues figuring out why this code still lets btn_1 call the function setstate3().

There is a function update() with a code check for (setstate == X) within. When it gets to if (setstate == 5) and if (setstate == 6), I want to remove the listeners.

The story ends that that point and will need a restart or whatever - for testing I want those buttons to be inactive at this point.

If I just turn off both listeners at if (setstate == 1), the button becomes inactive. However, for some reason that doesn't work if I do so at if (setstate == 5) or if (setstate == 6) in the code. I expected it to work if you removed the listener inside the function it calls in the first place. It's not even throwing any error at all.

I did some research and had different attempts at cloning the element (apparently that will kill all listeners on an object), but I can't get that to be recognised as a command.

Any help would be greatly appreciated - have a great day

class Game {
constructor (exportRoot, stage) {
    this.root = exportRoot
    this.stage = stage
    this.str1 = "start"
    this.strOp1 = "1"
    this.strOp2 = "2"
    init () {
    const game = this
    this.main_Txt = this.root.main_Txt
    this.op_1 = this.root.op_1
    this.op_2 = this.root.op_2
    this.root.start_bt.on('click', function () { game.update() })
    this.setstate = 0
 update () {
    if (this.setstate == 0) {
    this.str1 = 'You have had a really big weekend camping.  In fact as you are driving home through the dark forest you can hardly keep you eyes open.  The stereo is playing your favourite song but suddenly it cuts out.  There is a huge bright purple light in the sky and your car sputters to a stop.  The stereo is dead and all the lights are out.'
        this.strOp1 = 'Try to fix your car'
        this.strOp2 = 'Start walking'
        this.root.start_bt.visible = 0
        this.root.mc_2.visible = false
        this.root.btn_1.on('click', function () { game.setstate1()})
         //this.root.btn_2.on("click", function(){ game.setstate2(); })
    } else if (this.setstate == 1) {
       this.str1 = 'You get out and open the hood, its hard to see but there is still some purple glow in the sky.  You wonder what that big light came from and what is going on.  All of a sudden there is some moaning and some noises from the underbrush and a zombie stumbles out onto the road.'
        this.strOp1 = 'Fight the zombie'
        this.strOp2 = 'Ask him to help fix the car'
        this.root.mc_1.visible = false
        this.root.mc_2.visible = true
        this.root.btn_1.on('click', function() { game.setstate3() })
         //this.root.btn_2.on("click", function(){ game.setstate2(); }) 
    } else if (this.setstate == 5) {
        this.str1 = 'You try to fight but the zombie overpowers you and eats your brain.'
        this.strOp1 = "dead"
        this.strOp2 = "dead"
        this.root.mc_1.visible = false
        this.root.mc_2.visible = false
        //this.root.btn_2.on("click", function(){game.setstate2();  })
     } else if (this.setstate == 6) {
        this.str1 = "lost"
        this.strOp1 = "dead"
        this.strOp2 = "dead"
        this.root.mc_1.visible = false
        this.root.mc_2.visible = false
         //this.root.btn_2.on("click", function(){ game.setstate2(); }
    chooseNumber () {
    this.randomNumber = Math.floor(Math.random() * 10) + 1
    setText () {
    this.main_Txt.text = this.str1;
    this.op_1.text = this.strOp1;
    this.op_2.text = this.strOp2;
    setstate1 () {
     this.root.btn_1.off('click', function  (){ game.setstate1() })
    this.setstate = 1
    setstate3 () {
        this.root.btn_1.off('click', function  (){ game.setstate3() })
        if (this.randomNumber >= 5) {
    this.setstate = 5;
    } else {
    this.setstate = 6
  • \$\begingroup\$ Where do these button.on and button.off functions come form? Usually you set button event listeners in Javascript with button.onclick or button.addEventlistener. Looks like you are using some framework you forgot to mention. \$\endgroup\$
    – Philipp
    Commented Jan 2, 2023 at 12:13
  • \$\begingroup\$ Yeh sorry Phillip - it's EaselJS. here is the finished test project if you are interested. github.com/subtlefly/CYOA-animatecc-easelJS-html5. I am a teacher and will be using this idea with a class to let them build something like this - I really like the way animate lets you draw and make animations (as well as code)- for me (more artist than coder) its a nice tool... but dont get too excited we aren't talking about uni students here so its not very high tech :) \$\endgroup\$
    – subtlefly
    Commented Jan 2, 2023 at 12:13
  • \$\begingroup\$ By the way, instead of this.root.btn_1.on('click', function () { game.setstate1()}) you can probably just write this.root.btn_1.on('click', game.setstate1). If you want an event listener to do nothing but call a single function with no arguments, you can just use that function as the event listener. \$\endgroup\$
    – Philipp
    Commented Jan 2, 2023 at 12:37
  • \$\begingroup\$ Nice one thanks Phillip. For kids do you think it might be better just to give the more formal syntax so it will work for them in the future when they do want to use arguments? Or do you think simpler is always better? \$\endgroup\$
    – subtlefly
    Commented Jan 2, 2023 at 12:40
  • \$\begingroup\$ That depends on several factors that are not really on-topic on game dev stack exchange. cseducators.stackexchange.com might be a better place for questions about programming pedagogy. \$\endgroup\$
    – Philipp
    Commented Jan 2, 2023 at 12:59

1 Answer 1


You can not remove a listener is EaselJS via .off by just passing a closure with the same sourcecode as you used in .on. The framework can not tell that it is in fact the same function you set previously. (because technically it's a completely different function which just happens to do the same thing).

As the documentation says:

IMPORTANT: To remove a listener added with on, you must pass in the returned wrapper function as the listener.

The "wrapper function" the documentation talks about is the return value of .on. So if you later want to remove an event listener with .off , you need to capture that return value so you can do so later.

this.btn_1_listener = this.root.btn_1.on('click', function () { 

/* ... */

this.root.btn_1.off('click', this.btn_1_listener)

or alternatively, if you are certain that there are no other listeners on the button you might want to stay active, you can just remove all listeners with:

  • \$\begingroup\$ EaselJS has a removeAllListeners function. createjs.com/docs/easeljs/files/…. this.root.btn_2.removeAllEventListeners('click'); \$\endgroup\$
    – subtlefly
    Commented Jan 2, 2023 at 12:24
  • \$\begingroup\$ @subtlefly Added. \$\endgroup\$
    – Philipp
    Commented Jan 2, 2023 at 12:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .