Joseph Webber
Joseph Webber

Reputation: 2173

How do I call a Javascript function outside of another Javascript function?

I have a javascript function that's supposed to toggle an animation when clicked by calling another function outside of it.

function MyFunction(id) {
    var target = document.getElementById(id);
    var on = true;

    this.startMe = function() {
        //animation code
        on = true;
    }
    this.stopMe = function() {
        //animation code
        on = false;
    }
    this.toggleMe = function() {
        if (on) this.stopMe();
        else this.startMe();
    }
    target.addEventListener('click', function() {
        this.toggleMe();
    }, false);
}

The problem lies in the toggleMe and addEventListener functions. "this" refers to the function itself and not the one containing it, which is what I need it to reference. How can I work around this?

Upvotes: 1

Views: 70

Answers (2)

Arun P Johny
Arun P Johny

Reputation: 388316

The easy fix is to use a closure variable as given below

function MyFunction(id) {
    var self = this;
    var target = document.getElementById(id);
    var on = true;

    this.startMe = function () {
        //animation code
        on = true;
    }
    this.stopMe = function () {
        /animation code
        on = false;
    }
    this.toggleMe = function() {
        if (on) this.stopMe();
        else this.startMe();
    }
    target.addEventListener('click', function() {
        //this refers to the element here not the instance of MyFunction
        //use a closure variable
        self.toggleMe();
    }, false);
}

Another solution is to pass a custom execution context to the callback using $.proxy() - you can use Function.bind() also but not supported in IE < 9

function MyFunction(id) {
    var target = document.getElementById(id);
    var on = true;

    this.startMe = function () {
        //animation code
        on = true;
    }
    this.stopMe = function () {
        //animation code
        on = false;
    }
    this.toggleMe = function () {
        if (on) this.stopMe();
        else this.startMe();
    }
    //use Function.bind() to pass a custom execution context to 
    target.addEventListener('click', jQuery.proxy(function () {
        // this refers to the element here not the instance of MyFunction
        //use a closure variable
        this.toggleMe();
    }, this), false);
}

Also use .click()/on('click') to register the click handler instead of addEventListener

    $(target).on('click', jQuery.proxy(function () {
        // this refers to the element here not the instance of MyFunction
        //use a closure variable
        this.toggleMe();
    }, this), false);

Upvotes: 3

Cᴏʀʏ
Cᴏʀʏ

Reputation: 107536

Simply add another variable with a reference to this but with a different name; then you can use that in your functions.

function MyFunction(id) {
    var self = this;

    var target = document.getElementById(id);
    var on = true;

    this.startMe = function() {
        on = true;
    }

    this.stopMe = function() {
        on = false;
    }

    this.toggleMe = function() {
        if (on) self.stopMe();
        else self.startMe();
    }

    target.addEventListener('click', function() {
        self.toggleMe();
    }, false);
}

My personal preference is to take it even one step further and continue to use self everywhere that makes sense:

function MyFunction(id) {
    var self = this;

    var target = document.getElementById(id);
    var on = true;

    self.startMe = function() {
        on = true;
    }

    self.stopMe = function() {
        on = false;
    }

    self.toggleMe = function() {
        if (on) self.stopMe();
        else self.startMe();
    }

    target.addEventListener('click', function() {
        self.toggleMe();
    }, false);
}

Upvotes: 2

Related Questions