views:

488

answers:

2

I've got a particularly tricky problem using AJAX, which works fine in IE7 and Firefox, but not in IE6.

I have a very simple home-grown AJAX framework, which requires that I extend the XMLHttpRequest object (or in the case of IE, the XMLHttpRequest ActiveXObject) by adding a couple of properties. Relevant section of code is as follows:

//the following is the constructor for our ajax request object - which extends the standard object. It is used in the method below it   
function FD_XMLHttpRequest() {     
  var xmlHttpReq = false;
  if (window.XMLHttpRequest) { // Mozilla/Safari
    xmlHttpReq = new XMLHttpRequest();
  } else if (window.ActiveXObject) { // IE
    xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
  }
  //we now have the request object - extend it with things we might need to store with it
  xmlHttpReq.onReturnFunc = null; //******ERROR IN IE6******
  xmlHttpReq.targetDivId = null;  //******ERROR IN IE6******
  return xmlHttpReq;  
} 
//To use:
myXHReq = new FD_XMLHttpRequest();
myXHReq.onReturnFunc = someFunction; 
myXHReq.targetDivId = "myDiv";

The problem seems to be that FF and IE7 allow extending an object in this way, but IE6 does not (it complains that "Object doesn't support this property or method"). I've tried using the "prototype" property and various methods of "real" inheritance, but I can't quite get my head around what is going on with IE6

+1  A: 

On IE7 you are getting a ‘native JavaScript’ XMLHttpRequest object. As with all JavaScript objects you can add arbitrary properties to them without problem — although it's not always a good idea, because if a future browser added a real ‘onReturnFunc’ member of its own you'd then confuse it.

On IE6, or IE7 when the ‘native XMLHttpRequest’ option is disabled, you fall back to using the original ActiveX XMLHttpRequest. However, ActiveX objects have quite different behaviour to JavaScript objects and one of the differences is you can't add arbitrary properties.

Generally, you should have your own wrapper class that holds any extra data you need, and which holds a reference to the ‘real’ XMLHttpRequest object.

bobince
Ok, but I still don't fully understand var/method scope in JS, particularly the "this" var - it's an odd little beast. Assume I have a wrapper object, and a method of that object creates the request, how would I define the onreadystatechange function, and how would it reference the wrapper (this?)
Graza
Yeah, ‘this’ is a little sod. See http://stackoverflow.com/questions/585840/x/585918#585918 for more info on how it *actually* works. You would want to create a bound method on your wrapper's callback, then set onreadystatechange to that.
bobince
+1  A: 

The problem is that its the browser provided XMLHttpRequest that supports expandos. However IE6 does not have a XMLHttpRequest so your code drops to using the ActiveXObject. MSXML provided object does not support expandos.

A better approach would be to use a closure anyway, something like:-

function getContentForElem(url, elem, completed)
{
    var xhr = getXhr()
    xhr.open("GET", url, true)
    xhr.onreadystatechange = fnstatechange
    xhr.send()
    return xhr;

    function fnstatechange()
    {
       if (xhr.readyState == 4)
       {
           if (xhr.status == 200)
           {
                elem.innerHTML = xhr.responseText;
           }
           if (completed) completed(xhr)
       }
    }
}

function getXhr()
{
    var xhr;
    if (window.XMLHttpRequest)
        xhr = new XMLHttpRequest();
    else
        xhr = new ActiveXObject("MSXML2.XMLHTTP.3.0");
    return xhr;
}
AnthonyWJones