0

Consider the following code:

    var table = function () {

        return {
            _init: function (tableId) {
                this.tableId = tableId;
                this.table = $("#" + tableId);
            },

            removeStripes: function() {
                this.table.find(".alt").removeClass("alt");
            },

            addStripes: function () {
                this.table.find("tbody tr:even").addClass("alt");
            },

            resetStripes: function() {
                this.removeStripes();
                this.addStripes();
            },

            sort: function (options) {
                this.table.tablesorter(options);
                this.table.bind("sortEnd", this.resetStripes);
            },

        }

    }

var newTable = new table();
newTable._init("tableId");
var options = {};
newTable.sort(options);

The browser says this.removeStripes called by this.resetStripes, on one of the last lines) is not a function. I guess there is some error with this, but I can't figure out where it is. Any idea, anyone?

Helge
  • 823
  • 5
  • 13
  • 28
  • You might find an answer if you study [this question](http://stackoverflow.com/questions/4886632/what-does-var-that-this-mean-in-javascript)... – DaveRandom Aug 18 '11 at 12:31
  • A general suggestion: Add console.log statements (or alert statements, if you prefer) inside each function saying the name of the function and what it thinks "this" is. – Miriam Aug 18 '11 at 12:31
  • Also, you may want to use prototype. (I'm working on a fiddle, I'll update in a few minutes with details.) – Miriam Aug 18 '11 at 12:32
  • http://jsfiddle.net/miriam/ePWBP/3/ tablesorter is not defined in the code snippet you've provided. – Miriam Aug 18 '11 at 12:37
  • I think you are using "new" in a way that is not necessary. In your case you could create a table object like this : var newTable = table(); – fusion Aug 18 '11 at 12:42
  • tablesorter is included in the code somewhere else. :) – Helge Aug 18 '11 at 12:44

5 Answers5

0

As you are declaring methods with anonymous functions, this is not anymore in the table function scope.

You should use:

 removeStripes: function() {
   // ...
 }.bind(this)

on all of your methods.

ldiqual
  • 15,015
  • 6
  • 52
  • 90
  • Yes, I am sure there are some variable scope issues. However, bind(this) didn't help too much... – Helge Aug 18 '11 at 12:45
0

Try removing coma (,) after declaration of sort function. This will probably not solve your problem, but it will 'compile' under ie<7.

Michał Szkudlarek
  • 1,443
  • 1
  • 21
  • 35
0

What your looking for is a constructor method/pattern. Now when you call one of the instantiated objects methods (eg. newTable.removeStripes() ) the context (this) is set to newTable. I believe you can always change the context however with newTable.removeStripes.call(someOtherTableOrObject) which comes in handy in a lot of cases.

function Table(tableId) {

    this.tableId = tableId;
    this.table = $("#" + tableId);

    this.removeStripes = function() {
        this.table.find(".alt").removeClass("alt");
    };

    this.addStripes = function () {
        this.table.find("tbody tr:even").addClass("alt");
    };

    this.resetStripes = function() {
        this.removeStripes();
        this.addStripes();
    };

    this.sort = function (options) {
        this.table.tablesorter(options);
        this.table.bind("sortEnd", this.resetStripes);
    };

}

var newTable = new Table("tableId");
var options = {};
newTable.sort(options);
Alex Pineda
  • 2,909
  • 2
  • 14
  • 17
0
var table = function (tableId) {

        this.tableId = tableId;
        this.table = $("#" + tableId);

        this.removeStripes= function() {
            this.table.find(".alt").removeClass("alt");
        };

        this.addStripes= function () {
            this.table.find("tbody tr:even").addClass("alt");
        };

        this.resetStripes= function() {
            this.removeStripes();
            this.addStripes();
        };

        this.sort= function (options) {
            this.table.tablesorter(options);
            this.table.bind("sortEnd", this.resetStripes);
        };
}

The "this" keyword usage in Javascript is rather different than in other languages. The version above should work (I tested it with jsc, rather than properly in a browser with jQuery). Now the function is a proper constructor, making the interpreter to set "this" to the object to be created.

tty56
  • 151
  • 1
  • 3
0

Try this:

var table = function () {
        var that = this;
        return {
            _init: function (tableId) {
                that.tableId = tableId;
                that.table = $("#" + tableId);
            },

            removeStripes: function() {
                that.table.find(".alt").removeClass("alt");
            },

            addStripes: function () {
                that.table.find("tbody tr:even").addClass("alt");
            },

            resetStripes: function() {
                that.removeStripes();
                that.addStripes();
            },

            sort: function (options) {
                that.table.tablesorter(options);
                that.table.bind("sortEnd", that.resetStripes);
            },

        }

    }

var newTable = new table();
newTable._init("tableId");
var options = {};
newTable.sort(options);

Its a common pattern in JavaScript to save the this into another variable so you can reference it in deeper nested functions. As javascript this always refers to either the global object or the this object that was passed to the function through .call or .apply it's rather unreliable to use at times..

Tigraine
  • 23,358
  • 11
  • 65
  • 110