Sunday, May 1, 2011

How to modify ActiveXObject JS constructor?

I need to wrap an IE ajax request to notify me when it happens. ie i need to know when open is called on this:

var xhr = new ActiveXObject("Microsoft.XMLHTTP");

The only way to do that(i think) is to implement the ActiveXObject constructor to proxy open calls to the real constructor/object. Can you help me do that?

also: i dont need to create the actual xhr object, so please dont tell me to use X framework because its easy.

all i need to know is when open is called (not by my code) on an MS xhr object.

Thank you very much!

From stackoverflow
  • I recommend you to use jQuery for AJAX . It's very small but very flexible and fast framework. Check out docs here.

    mkoryak : i am working on code that will plug into other peoples code (something like a bookmarklet). i dont know what framework they have used, but i need to catch ajax events.
  • Perhaps you can try something like this:

    XMLHttpRequest.prototype.real_open = XMLHttpRequest.prototype.open;
    
    var your_open_method = function(sMethod, sUrl, bAsync, sUser, sPassword) { 
      alert('an XHR request has been made!');
      this.real_open(sMethod, sUrl, bAsync, sUser, sPassword); 
    } 
    
    XMLHttpRequest.prototype.open = your_open_method;
    

    Of course, instead of the alert you can have your own tracking code. I tried it out and it works on 'plain javascript' requests and also requests made with jquery. I think it should work regardless of the framework that was used to make the request.

    EDIT April 21 I don't really know how an ActiveXObject can be extended. My guess is that something like this should work:

    XHR = new ActiveXObject("Microsoft.XMLHTTP");
    var XHR.prototype.old_open = XHR.prototype.open;
    var new_open = function(sMethod, sUrl, bAsync, sUser, sPassword) { 
      alert('an IE XHR request has been made!');
      this.old_open(sMethod, sUrl, bAsync, sUser, sPassword); 
    } 
    
    XHR.prototype.open = new_open;
    

    Unfortunately (or maybe not) I don't have IE, so I can't test it. But give it a spin and let me know if it did the trick.

    mkoryak : ill try that. ill probably need to make one for the firebox XHR implementation, and one for IE's. Thanks
    mkoryak : apr 21: I have tried that, it does not work because "prototype is null or not an object" claims IE. I think its not a real javascript object, but some activeX mutant thing. I think the way to go is to modify the ActiveXObject constructor to make a proxied object
    andi : I think you are right on the activeXObject not returning a real javascript object. I'm afraid I can't help you with how to extend it. Good luck, and keep updating the status, if you can.
    andi : oh, and perhaps you can ask a new question regarding only this issue, of extending an ActiveXObject in javascript. I think you'll get more answers on that.
  • There is nothing "to get at real object" it is the real object!

    Sounds like you are looking for something like this guy is doing....

    http://www.adobepress.com/articles/article.asp?p=439600

    document.write("");

    function Ajax() { this.toString = function() { return "Ajax"; } this.http = new HTTP();

    this.makeRequest = function(_method, _url, _callbackMethod) { this.request = (window.XMLHttpRequest)? new XMLHttpRequest(): new ActiveXObject("MSXML2.XMLHTTP"); this.request.onreadystatechange = _callbackMethod; this.request.open(_method, _url, true); this.request.send(_url); }

    this.checkReadyState = function(_id, _1, _2, _3) { switch(this.request.readyState) { case 1: document.getElementById(_id).innerHTML = _1; break; case 2: document.getElementById(_id).innerHTML = _2; break; case 3: document.getElementById(_id).innerHTML = _3; break; case 4: return this.http.status(this.request.status); } } }

    mkoryak : i am not trying to figure out how to use ajax, i am trying to figure out how to intercept all calls to the HXR object regardless of which framework (or no framework) it was invoked through
    Chad Grant : Yeah ok, well overriding base types is a recipe for disaster but if you still want to do it, you would have to somehow overwrite the entire ActiveXObject and XHR in two class wrappers and intercept the calls that way. Lot of work ;) ActiveXObject.prototype.constructor = function(progId) {} Good Luck
  • This has always worked for me.

    var xmlHttp;
    
    function yourajaxfunction(str)
    { 
       xmlHttp=GetXmlHttpObject();
       if (xmlHttp==null){
          alert ("Browser does not support HTTP Request");
          return;
       }
    
       var url="yourserversidecodefile.php";
       url=url+"?q="+str;
    
       xmlHttp.onreadystatechange=stateChanged;
       xmlHttp.open("GET", url, true);
       xmlHttp.send(null);
    }
    
    function stateChanged() { 
       if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete"){ 
          document.getElementById("txtHint").innerHTML=xmlHttp.responseText;
       } 
    }
    
    function GetXmlHttpObject(){
       var xmlHttp=null;
    
       try {
          // Firefox, Opera 8.0+, Safari
          xmlHttp=new XMLHttpRequest();
       }
       catch (E1) {
          //Internet Explorer
          try {
             xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
          }
          catch (E2) {
             xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
          }
       }
    
       return xmlHttp;
    }
    
    mkoryak : i am not trying to write a wrapper for making ajax calls. see followup comment in my question
  • Since the OP has posted a similar question, and I posted an answer which also happens to fit this question, he asked me to link to my answer, instead of repeating it here.

0 comments:

Post a Comment