Hi,
As you're probably aware, in IE 6, when you assign a function to the XmlHttpRequest onreadystatechange event, you lose the reference to the object. For example, notice how in the function below I have to refer to my xmlhttp object by name, instead of simply saying this.readystate and this.status. :
xmlhttp.onreadystatechange
= function()
{
if (xmlhttp.readyState==4)
{
if ( xmlhttp.status == 200 )
{
//do stuff
}
}
}
Is there a workaround that would allow me to use the this keyword to reference the XmlHttpRequest object. This is especially a problem in IE 6 because it is an ActiveX object.
I found some code for a wrapper class at
http://www.allegro.cc/forums/thread/591774 but I'm not entirely sure how to do it. It looks somewhat complicated. :-)
// inside the RPC.transport constructor
// 'this' is the RPC instance
this.obj = new XMLHttpRequest();
if (this.obj)
{
this.obj.onreadystatechang
e = Delegate.create(this, 'onReadyStateChange');
}(FYI: For IE, I define the XMLHttpRequest function to return the ActiveX control.)
You're right that you lose the "this" pointer in the onReadyStateChange function if you just do an anonymous function. That's why I use a Delegate to keep track of things. I created this method myself; there may be some other defacto standard way of doing this.
Later on:
RPC.transport.prototype.on
ReadyState
Change = function()
{
// this.obj points to the XMLHttpRequest object.
// eventually:
else if (this.responseType == RPC.JSON)
{
eval("var json = " + this.obj.responseText);
this.onLoad(json);
}
}My Delegate class looks like:
/*
Copyright 2006-07 by Matthew Leverton
Delegate: a static class to help keep events tied to an object.
*/
var Delegate = {
objects: new Array(),
/*
(object) ptr: the object the event should be tied to
(string) func: the name of the function that should be called; it must reside in the ptr object.
*/
create: function(ptr, func)
{
if (!ptr._delegates)
{
ptr._delegates = new Array();
Delegate.objects[Delegate.
objects.le
ngth] = ptr;
}
return !ptr._delegates[func] ? (ptr._delegates[func] = function(event) { return ptr[func](event); }) : ptr._delegates[func];
},
/*
Returns a delegate already created. Note that subsequent calls to 'create' are the
same as calling get, so this method really doesn't ever _need_ to be used.
*/
get: function(ptr, func)
{
return (!ptr._delegates || !ptr._delegates[func]) ? false : ptr._delegates[func];
},
/*
Destroys the delegate (but not the actual function). It can be useful in removing
small memory leaks in some browsers, but doesn't have to be called.
*/
destroy: function(ptr, func)
{
if (!ptr._delegates || !ptr._delegates[func]) return false;
ptr._delegates[func] = null;
},
/*
Destroys all the delegates. (See the destroy method.)
*/
destroyAll: function()
{
for (var i in Delegate.objects)
{
for (var j in Delegate.objects[i]._deleg
ates)
{
Delegate.objects[i]._deleg
ates[j] = null;
}
}
}
};
Thanks,
Rob
Start Free Trial