views:

73

answers:

3

I have a JavaScript object called ShippingUI:

function ShippingUI(){
   ...
}

It has several methods:

ShippingUI.prototype.UpdateItemQTYs = function(ItemJQOBJ, NewQTY)
{
   ...
}

ShippingUI.prototype.EH_SortableRecieve = function(event, ui)
{
    ...
}

The "EH_SortableRecieve()" function is a drop event handler. When it runs, it needs to call "UpdateItemQTYs()", a sister function in the same object. I'm trying to use:

ShippingUI.prototype.EH_SortableRecieve = function(event, ui)
{
    this.UpdateItemQTYs('ABCD',123);
}

But keep getting the error:

 "this.UpdateItemQTYs is not a function"

I'm guessing that "this" is pointing to something else... so how do I get the 'real' "this"?

Event Binding method:

// Takes a Jquery Object and makes it sortable with our custom options
   this.MakeSortable = function(JQOBJ)
   {
     JQOBJ.sortable({
       connectWith: '.connectedSortable',
       items: '.ItemLineWrapper',
       dropOnEmpty: true,
       axis: 'y',
       receive: this.EH_SortableRecieve       
       });
   }
+1  A: 

The problem is that when you register the function as an event handler, its relationship to your object is lost.

How are you registering the event handler? If it's with jQuery, you can use the new "proxy" API:

$('#someButton').click($.proxy(myShippingUI, 'EH_SortableReceive'));

That'll make sure the object (I used "myShippingUI" as a sample instance of your class) is acting as the "this" pointer. There are other ways to do this to, but that's a simple one.

The "$.proxy" thing is new with 1.4.

Pointy
ES5 also specifies a Function .bind method, that's seen other various implementations in JS.
Tracker1
+2  A: 

There is something missing in your examples which is how EH_SortableRecieve is called. But based on what you say it should be used as I'm thinking it is used something like this:

htmlelement.onmouseup = shippingObject.EH_SortableRecieve;

In which case you should be aware of Javascript's binding of this in methods. Specifacally, in event handlers this is bound to the window object instead of the object the method belongs to. This is a general feature of javascript: methods can be re-bound at runtime. In other words, objects can steal other object's methods. For example, I can have my object slebetmans_object steal your method and re-bind its this with the following:

shippingObject.EH_SortableRecieve.apply(slebetmans_object,parameters);

There are several strategies to get around this. You can use a closure to capture your object:

htmlelement.onmouseup = function(){ shippingObject.EH_SortableRecieve() };

You can use a closure in the object's constructor to capture the correct reference to your object:

function ShippingUI () {
    var self = this; // since self is resolved at the time the object is created
                     // it always reference to the "correct" object

    this.EH_SortableRecieve = function(event, ui)
    {
        self.UpdateItemQTYs('ABCD',123);
    }
}

There are probably other ways to do this but these are the two most common that I personally use.

slebetman
Since @Nick is using jQuery, he really should be doing his event binding that way, and not with the deprecated "onfoo" attributes.
Pointy
Excellent, thank you! I placed all of my methods inside the constructor, and stopped using prototype to add them. Then I could "save" 'this' to a variable so it was always available and correct. "self" was highlighted in my editor as a keyword, so I used "TrueThis" instead. Thanks again!
Nick
@Pointy I've updated the original question to include the event binding function. I'm using JQuery UI's ".sortable()" method.
Nick
A: 
function ShippingUI(){
   ...
}

ShippingUI.prototype = {
UpdateItemQTYs : function(ItemJQOBJ, NewQTY)
{
   ...
},
that = this,
EH_SortableRecieve = function(event, ui)
{

that.UpdateItemQTYs('ABCD',123);
    ...
}
};

The above should work too... All you need is the reference to ShippingUI object you are currently using in this.

moha297
This won't work, I don't think. What is the value of "this" when the object constant is being evaluated? I would expect it to be the "window" object.
Pointy
by object constant here u mean? maybe u can point. I wrote this code on the fly...didnt really test it out
moha297