views:

109

answers:

4

I know that jQuery isn't designed for working with a class-like model but I really could do with being able to extend a base class as that fits my needs perfectly.

I started by just doing the following:

jQuery.myBase = {
    foo: 'bar',
    bar: function() { ... }
}

jQuery.fn.myPlugin = function() {
   $.extend( this, jQuery.myBase, {
       oof: 'rab',
       rab: function() { ... }
  }
}

That all works fine, I can access the base methods & properties via this. That is until I try adding something like a jQuery event handler (etc.) which applies the event target to the this.

So with the following:

jQuery.myBase = {
    bar: function() { ... }
}

jQuery.fn.myPlugin = function() {
   jQuery.extend( this, jQuery.myBase, {
       init: function() {
           jQuery('#someEl').click( this.onClick );
       },

       onClick: function(e) {
           // this now references the element I bound the event to (<div id="someEl" />)
           // so the following doesn't work
           this.bar();
       }
  }
}

I've found a couple of things for class creation and inheritance that work with jQuery (such as John Resig's one and DUI) but those will/do experience the same issue.

So after all of that, how do I get to the original this in these situations?

Update: The event handler (etc.) could be in either the jQuery.myBase or the plugin itself.

A: 

The only way that I've thought of doing this, which I don't really like and thus asking the question, is with the following:

jQuery.myBase = {
    bar: function() { ... }
}

jQuery.fn.myPlugin = function() {
   jQuery.extend( this, jQuery.myBase, {
       init: function() {
           var self = this;
           jQuery('#someEl').click( function(e) {
                this.onClick.apply( self, arguments );
           };
       },

       onClick: function(e) {
           // this works
           this.bar();
       }
  }
}
DEfusion
+2  A: 

You need a reference to it in the appropriate scope.

jQuery.fn.myPlugin = function() {
   var $this = this;  // Scope it up!
   jQuery.extend( this, jQuery.myBase, {
       init: function() {
           jQuery('#someEl').click( this.onClick );
       },

       onClick: function(e) {
           $this.bar();
       }
  }
}
Josh Stodola
I should have mentioned that I already tried that and it kind of works, but what if the event were in the jQuery.myBase definition? That still has no access to $this.
DEfusion
A: 

Another alternative would be to follow prototypes method of having a bind() function (which actually does the same as my other answer but in a cleaner fashion), as pointed out in this question, e.g.:

if (!Object.bind) {
    Function.prototype.bind= function(owner) {
        var that= this;
        var args= Array.prototype.slice.call(arguments, 1);
        return function() {
            return that.apply(owner,
                args.length===0? arguments : arguments.length===0? args :
                args.concat(Array.prototype.slice.call(arguments, 0))
            );
        };
    };
}


jQuery.fn.myPlugin = function() {
   jQuery.extend( this, jQuery.myBase, {
       init: function() {
           jQuery('#someEl').click( this.onClick.bind( this ) );
       },

       onClick: function(e) {
           this.bar(); // this works
       }
  }
}
DEfusion
A: 

It looks like they are addressing this in jQuery which should be part of 1.3.3 according to the comments

DEfusion