Question

I'm using classic OOP code from Mozilla

var myExtension = {
    init: function() {
        // The event can be DOMContentLoaded, pageshow, pagehide, <b style="color:black;background-color:#99ff99">load</b> or unload.
        if(gBrowser) gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad, false);
    },
    onPageLoad: function(aEvent) {
        var doc = aEvent.originalTarget; // doc is document that triggered the event
        var win = doc.defaultView; // win is the window for the doc
          alert("<b style="color:black;background-color:#a0ffff">page</b> is loaded \n" +doc.location.href);
        //OOPs, error here, username is undefined
        Firefox.Console.log(this.userName);
    },
    anotherMethod: function (){
       this.userName = 'UserName'; 
    }
}
window.addEventListener("<b style="color:black;background-color:#99ff99">load</b>", function() { myExtension.init(); }, false);

The general question is how can initialize and user public variables in my class? You know, this in this class is some browser's object (tab), but not a current class and I can't assign this.win = doc.defaultView and use later like this.win.userName = 'UserName'

Was it helpful?

Solution

A couple of options:

Using Function#bind:

I believe in a Firefox extension you should have most if not all ES5 features available to you, which means you can use Function#bind to make sure your event handler gets called with this set to your instance. E.g.:

if (gBrowser) {
    gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad.bind(this), false);
}

Within the call to onPageLoad, this will refer to your instance. You won't have access to the normal this Firefox gives the event handler (the tab or whatever).

Fuller example of the bind option:

var myExtension = {
    init: function() {
        // The event can be DOMContentLoaded, pageshow, pagehide, <b style="color:black;background-color:#99ff99">load</b> or unload.
        if(gBrowser) {
            gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad.bind(this), false);
        }
    },
    onPageLoad: function(aEvent) {
        var doc = aEvent.originalTarget; // doc is document that triggered the event
        var win = doc.defaultView; // win is the window for the doc
          alert("<b style="color:black;background-color:#a0ffff">page</b> is loaded \n" +doc.location.href);
        // This now works
        Firefox.Console.log(this.userName);
        // ...but you don't have access to the `this` that the browser gave
        // the event handler (the tab or whatever)
    },
    anotherMethod: function (){
       this.userName = 'UserName'; 
    }
}
window.addEventListener("<b style="color:black;background-color:#99ff99">load</b>", function() { myExtension.init(); }, false);

Using a closure:

If I'm mistaken about ES5 in Firefox extensions, or if you want to have access to the this that the event handler would normally receive, you can readily use a closure to do the same thing:

var self = this;
if (gBrowser) {
    gBrowser.addEventListener("DOMContentLoaded", function(event) {
        // Here, `self` refers to your instance, and `this` to the
        // element, so for instance you can call your `onPageLoad`
        // and pass it the element as a second argument:
        return self.onPageLoad(event, this);
        // Within the call to `onPageLoad`, `this` will be your instance
    }, false);
}

(If "closure" is a new term to you, don't worry, closures are not complicated.)

Fuller example of the closure option:

var myExtension = {
    init: function() {
        var self = this;

        // The event can be DOMContentLoaded, pageshow, pagehide, <b style="color:black;background-color:#99ff99">load</b> or unload.
        if(gBrowser) {
            gBrowser.addEventListener("DOMContentLoaded", function(event) {
                return self.onPageLoad(event, this);
            }, false);
        }
    },
    onPageLoad: function(aEvent, aElement) {
        var doc = aEvent.originalTarget; // doc is document that triggered the event
        var win = doc.defaultView; // win is the window for the doc
          alert("<b style="color:black;background-color:#a0ffff">page</b> is loaded \n" +doc.location.href);
        // This now works
        Firefox.Console.log(this.userName);

        // If you needed the `this` that Firefox gives the event handler
        // (the tab or whatever), it's accessible via `aElement`
    },
    anotherMethod: function (){
       this.userName = 'UserName'; 
    }
}
window.addEventListener("<b style="color:black;background-color:#99ff99">load</b>", function() { myExtension.init(); }, false);

OTHER TIPS

You might be hung up a little too much on using "this." Make your global variables properties of MyExtension and refer to variables by their full names rather than using "this," which can be ambiguous. For example:

var myExtension = {
    username : '',
    email : '',

    init : function() {
        if ((app = document.getElementById("appcontent"))) {
            app.addEventListener("DOMContentLoaded", myExtension.run, true);
        }
   },

   run : function(event) {
       ...
    },

   anotherMethod : function() {
       // same as your example: this.username = 'Username';
       myExtension.username = 'Username';
   }

};

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top