12 Aug

AJAX in IE without ActiveX

What a day! Recently, one of our customers was saying that his site wasn’t working whenever he viewed it in his local net-cafe. This was incredible, to me, as every computer I’ve checked it on has displayed fine.

I finally had an inkling of an idea why this was happening, when I asked him to “click help->about in the browser”, to find out what exact version this was happening in. He said that the browser wasn’t allowing him to access that information.

I understood immediately that it was a security thing. Net-cafes would naturally hate to be infected with the myriad viruses out there, so they tend to belt-up their browsers tighter than the average user.

So, I tried to replicate what might be going on – I set my own Internet Explorer to stun – High security setting. When I tried the site, I was not surprised to find that it was not working. The fact that it relies on JavaScript made that a certainty anyway.

To make it work, I needed to turn on “Active Scripting” (what IE calls ECMAScript), and let it run safe ActiveX modules.

Naturally, I’m slightly ashamed that the site doesn’t work properly in a non-javascript environment, but the site is aimed at the overwhelmingly vast majority of people who are normal. The ActiveX thing, though, was a problem.

I began searching through the source of every AJAX library I could think of – Sarissa, JSPan, Sajax, ie7-xml-extras – every single one of them relied on ActiveX.

Surely there must be some XMLHttpRequest library out there that doesn’t rely on ActiveX?

I sat down, and started work on one. It’s Friday, and I’m exhausted after a very long day’s research, so I won’t go too in-depth into it…

Here’s the file

There are some problems with the above, which I’ll detail.

First off, the file is a drop-in emulation of the XMLHttpRequest object. I wanted to use the exact same API as every other library on the planet is using.

The short explanation of how it works: the library creates an <iframe>, populates it with the requested data, then returns the source of that object.

That’s not quite as simple as it sounds. I got 90% of the code working in 10% of my working time today, and spent the next 90% of the day trying, and failing, to solve the other 10%.

As it is, the file works – it should be bloody simple to add it to any library out there. The major problem, though, is white-space.

The innerHTML returned by IE is not exactly what it was given, but there is no other way of obtaining it.

Trust me – I spent hours crawling through the MSDN library today (in Firefox, because I had IE set on stun, so the navigation (which is ActiveX-based) wouldn’t work) – there is no other way.

I even tried dynamically creating a text/plain <object> to grab the data from it, but got alerts complaining that this was an ActiveX object!

If anyone out there in blogland has an inkling of an idea how to go forward from here, please do pipe up.

69 thoughts on “AJAX in IE without ActiveX

  1. I used to do this – the IFRAME “converse with server without refreshing client” thing – a year or two ago before the whole AJAX thing (which I haven’t really looked into at all for precisely the reason that it relies on ActiveX in IE). Could you describe your problem in more detail? Surely a whitespace problem can be dealt with via a javascript regex? What other problems are you having?

  2. The problem is that innerHTML completely strips out all \n symbols – it is impossible to know the difference between a space and a carriage return.

    I’m thinking I may need to escape every carriage return, and possible every space. I hate to have to do anything special on the server-side, but I really have spent all day racking my brain, and can’t think of a way to get around this other than to insert “carriage-return-goes-here” type symbols in on the server-side – which really is blasphemy…

  3. If your data is only text use innerText instead but if its HTML (and I’m presuming it is) … I dunno. I used to use write out javascript objects instead of HTML to the IFRAME, which didn’t have such problems. But thats going to add a load of extra overhead in your particular case – it does remove some processing from the client-side though (why output HTML and then have to parse it with javascript aswell, when you can skip the HTML part?)

    You could try using the DOM instead of innerHTML, although you could well come across the same problem, IIRC. I’m having net connection problems ATM, so I can’t do much right now.

    PS. Not to be an ass, but should you not ideally be using normal client-server interaction as a fallback for when AJAX fails?

  4. Pingback: Holy Shmoly! :: AJAX in IE without ActiveX

  5. innerText is basically innerHTML.replace(/<[^>]*>/g,''). Believe me – I was playing around with this all day yesterday, and innerHTML is actually closer to what I needed.

    You’re right about the basic non-JavaScript client-server being the most important fallback, but in the case I’m describing, JavaScript is available, but with very drastic and ridiculous restrictions (it makes sense to ban the user from downloading unknown ActiveX objects – but to ban them from using their already-installed ones??).

  6. Pingback: » Sajax, without ActiveX « klog

  7. I experienced this problem with a customer. This shows that Microsoft should implement DOM3 load/save and XMLHttprequest in the same way Mozilla has, instead of relying on ActiveX. However, for this to become a problem a user must explicitly set the security settings to disallow safe ActiveX. This is not an average scenario – but for public websites this script is very useful as some users will have problems with ActiveX like this.

  8. Pingback: Pete Freitag

  9. Pingback: » Blog Archive » Ajax en IE sin ActiveX

  10. Yeah, the only thing I can think of immediately is to inside two or three spaces (whatever works with the content) on the server side everytime there is a newline. In the client, then, whenever you see those spaces, you can replace with a newline.

  11. Kae,

    I’ve been trying to make this work myself but was trying to encode my data within a CDATA section in an XML document, so I woudn’t have the whitespace issues I had. (Or the issues I get in Firefox: angle brackets converted to HTML entities.) I wrote a very simple PHP script to stuff the contents of a desired URL into a CDATA section, and things worked fine in Firefox. But not in IE. I’ve concluded that IE’s iframes convert XML documents into HTML documents on the fly.

    In any case, I came up a different encoding and escaping scheme using a tag that works in Firefox and IE, and avoids the awkward problem of having to poll the readyState property. See http://www.davidflanagan.com/blog/2005_08.html#000081

  12. David – I noticed your article yesterday. Isn’t it weird how people sometimes solve the same problem at almost exactly the same time?? Anyway – I incorporated the solution I came up with into the popular Sajax library. That way, even if I don’t notice a bug in it myself, other people will have the time, knowledge and incentive to work on the code. The power of open source!

    There is a problem with IFrames that I noticed while working on a solution for a problem noticed by Dean Edwards – if you try to load up plain-text files such as CSS, then the browser will try to download them, instead of simply handing them back to the script. I recommend using the Sajax library, or your own home-grown library.

  13. Pingback: Software Development Blog » AJAX Module

  14. Pingback: A Venture Forth » Blog Archive » What’s Wrong With Ajax?

  15. Dwight, that would only work if the server was specifically tailored to match the document that was requesting it, and built up custom JavaScript to incorporate the returned data into the running script. In most cases, AJAX involves retrieving pure data from the server. Using a script tag implies that a script is returned – not pure data.

  16. The good news is that IE 7.0 will remove the need for the ActiveX component that drives their XMLHTTP implementation. Of course, that does not help you now…

  17. I wanted to preserve white space characters in innerHTML and I used element “pre”.

    I tried:
    pre.innerHTML = textWithWhiteSpaceChars;
    but it only worked for Mozilla and not for IE.

    However, I found workaround that worked well in IE:
    dummyElm.innerHTML = “(pre)” + textWithWhiteSpaceChars + “(/pre)”;
    After retrieving innerHTML, all white space characters are preserved (do not forget to trim “pre” tags or access dummyElm.firstChild.innerHTML directly).

    Now I tried the most straight-forward solution and it worked too:
    dummyElm.appendChild (document.createTextNode (textWithWhiteSpaceChars));
    To retrieve text with preserved white space characters:
    dummyElm.firstChild.data

    I hope this helps.

  18. kae, Yes that is exactly what I meant dynamic JS. It there an issue with building dynamic js instead of building dynamic xml?

    Is there a problem with createing a “script” tag with a src attribute that has &parms= in it?

    Of course, you could not call it AJAX anymore if you dont use the XML object, but, I dont personally see that big of an issue with it.

  19. Dwight – I’ve never seen XML used in any AJAX clients before – it’s just a name, as far as I can tell.

    There is no problem with writing a server-side script for doing what you want. In fact, I hacked the SAJAX library to use these iframe functions – I don’t know if you’ve followed the link in comment number 7, but it solves all of these problems.

  20. Sorry – I misunderstood what you were saying there, Dwight.

    Actually, the reason I chose not to use a script tag, is that the data returned by an XMLHTTPRequest is not always JavaScript – I wanted to come up with a solution that didn’t force the user to write server-side code as well as client-side.

    Anyway… the SAJAX library solves all my own problems anyway 😉

    I haven’t tried Los’s solution, but if I need to do something similar again, then I will try it – it may be the answer to this article’s problems.

  21. Pingback: Get Off Microsoft » Blog Archive » Ajax to Scrub Desktop Applications

  22. Hi,I was wondering if you could post an example of implementing the code. I’m interested in seeing how you define the onreadystatechange function.When I try to use it in this form: var ajaxengine = new XMLHttpRequest();     ajaxengine.i = 1;     ajaxengine.url = “http://domain.com/testxml.xml”;     ajaxengine.open(“GET”, “http://domain.com/testxml.xml”);it seems to freeze after calling the open method. Could you please tell me what I am doing wrong? Thanks,Daniel 

  23. Daniel, call it exactly as you would call any other XMLHttpRequest function.

    var ajaxengine = new XMLHttpRequest();
    ajaxengine.onreadystatechange=function(req){alert(req.responseText);}
    ajaxengine.open(”GET”, “http://domain.com/testxml.xml”);
    ajaxengine.send(null);

    the above is not tested. just written from memory based on what you were trying to do.

  24. I successfully made my own IFRAME ‘ajax’ object for when activex and xmlhttprequest were not available. I did this a little while back, being inspired by allwrightythen.com. Sofar I have had no problems with it, and when used alone I find it works quite well. Here is a link to the zip: http://www.k4bb.org/AJAX.zip
    There are some other files in there because it uses functions from all of the different files. Hope this helps you out!

  25. To use the above (with all files) you can do:
    k4Ajx.loadPage(‘url to page’,’GET or POST’,’container_div_id’);

    this method will do everything for you.

    Otherwise, you can do things in a more manual fashion:
    var k4_http = k4XMLHttpRequestFactory.createInstance();
    k4_http.Request(‘[request type]’, ‘[url here]’, [loading function], [error function], [success function] );

  26. Howdy from Limerick!!! 😉 I have played with ajax and as an fyi – if you use Microsoft.XMLHTTP object from javascript and use the object to do a post – BEWARE!! I wasted a couple of hours trying to get a POST to work, it worked fine from Konquereor/Mozilla/Opera…I have seen sites using this example
    if (window.ActiveX){
    http_req = new ActiveX(Microsoft.XMLHTTP);
    }
    http_req.open(‘PUT’, some_url, true);
    http_req.setRequestHeader(‘Content Type’, ‘application/x-www-form-urlencoded’);
    IE 6 w SP1 under W2k w SP4, barfs on this, I found the best way to deal with it is to do this,
    http_req.setContentType(‘application/x-www-form-urlencoded’); and it works.
    I have put in a branching check to see if it’s IE then to use the SetContentType, for non-ie use setRequestHeader….hope this helps out to someone and save them trouble! 🙂

    Meanwhile, excellent article and interesting! Will try this when I get home!
    Slan,
    Tom Brennan.

  27. Arrgh.. Kae, i’ve been going through a day exactly how you were a while back.
    I need those newline characters and it seems really stupid and pointless to put other tags in when its all just raw data.

    Maybe not to the scale of what you were doing i was simply working on my portfolio site and i thought hey, some of this data which i’ll change regularly i can seperate from the html without having to have server side includes. I’ve used a similar methodology to you however without the state checking as the data i am loading is so small even a setTimeout value of 500ms is probably too long but still.

    It’s driving me crazy, did you find a attribute that didnt require hacking around the data? see it all works fine for me in IE cause it doesnt strip the \n for innerHTML however there are a few white space issues that i dont get if i use innerText. But for firefox i’ve not found anything that will preserve the newlines without having to hack around.

    I used to do this sort of thing in IE for years with only a small amount of javascript, sure its not strict to the DOM but i’ve been using firefox’s DOM inspector and i must say im not that impressed 🙂
    Hey im not trying to start up a debate over browsers, i’m simply frustrated and at the moment firefox is my enemy because its stripping my newlines 😉

  28. Jay, this is specifically an IE problem. For Firefox, use the inbuilt XMLHttpRequest object.

    I never found a clean solution for this, but as I am always developing for environments that support server-side code, I resorted to hacking Sajax (as can be seen in the follow-up to this post).

    That’s my recommendation – use the hacked version of Sajax.

  29. Hi Kae,

    it wasnt really a production thing, more of my own implementation of some reasonably complex javascript just to prove on my portfolio that i’m not a noob 🙂
    I have successfully made something that works in both IE and FF now, what brought me here initially was the fact firefox was stripping my newlines on innerHTML; I didnt come here looking for help with ajax without activex. So i’m sorry if you have misunderstood my comment 🙂
    Weird thing is is the fact that firefox 1.0.7 doesnt touch my newlines yet 1.5 strips them.
    But as you said its not really related so thanks for your time 🙂

  30. I have seen a way to use Microsoft’s XMLDOM object even if the browser (ie 6 at least) has high security settings that would normally prompt/disable when the object is created. To do it just call:
    document.createElement(“xml”)
    Cool huh?

  31. Hi guys
    i’m new in Ajax stuff and programing at all
    and i just want to mention that my ajax page working fine in Firefox
    but refuse to work in IE even with all ActiveX control enabled
    give’s me an error – ‘ajax is null or not an object…’
    Anyway url of my page is
    http://www.infinity2002.net/surferguide/
    and if someone can help please contact me at novmejl@yahoo.com
    Just builded my online PC shop, and was disapointed when found out it does not working in IE

  32. Has someone tried this script with XAJAX and PHP? I heard about success with this, but it doesn’t work for me. In IE I just get the XAJAX message -Your browser does not appear to support asynchronous requests using POST.

  33. Greg, the IFrame method I wrote is specifically Get only. I believe it /can/ be adapted to use POST, but I have not done this, as I have not had this need yet.

    The only times when POST is needed are when you are uploading a file, or when the parameters are just too damned long.

    In the case of the file uploading, I use an actual form element pointing to an invisible iframe, and in the case of very long parameters, it’s probably best to use traditional HTTP requests.

  34. Thanks for the fast answer, Kae! I think I should have a better look at your code next time before posting here. 🙂 I switched XAJAX to GET-mode, but it’s still not working. Now I’m getting a javascript error (r.responseText is null or not an object). Think I will have to have a closer look on the XAJAX package…

  35. I’ve never used the XAJAX library, although I think I remember noticing a referral from the XAJAX forum. It’s possible that whoever integrated it made a few minor mistakes or something. Personally, I use the Sajax library – more out of comfort, than any idea that it is “superior”. My own copy of it (here) is a bit more developed than the current “official” release, if you want to try it.

  36. Hey, I’m one of the developers of xajax (mentioned a few comments ago)
    and have been playing around with a couple of attempts of using iframes as fallback for no ActiveX.

    xajax (at the moment) uses the XMLHttpRequest.responseXML() rather than the responseText() function that’s been provided, so I’ve tried to use the document.createElement(‘xml’) to make an xml data island, but not getting very far. The best part is that IE likes to format the xml in the iframe (which i get rid of with .replace(/\r\n- /g,”);)

    Anyone have any non-ActiveX code to get a text string of XML into a proper xml object?

    I’ve got things working with both post’s and get’s ok. That was the easy bit 🙂

  37. Hi everybody,

    I am having a problem with XAJAX.. I have implemented it.. and it worked FINE in IE but it was giving problem in Mozilla Firefox… I used

    The Flow is …. The user selects the width from the drop down box and after that i called the PHP function i.e. xajax_getAllPrices() this will return me the price depending on the width selected.. and that price is displayed in the DIV tag with table , tr , td tags etc….

    This is working fine in IE but not in mozilla Firefox.. To Test please visit
    http://www.topblinds.com/view.html?cid=7 check this in IE and Firefox..

    Please reply ASAP… waiting for positive replies…

    Thanking You All.

    Regards
    D Nagesh

  38. Hi,

    In “AJAX”, is it possible to contact a server other than the one that the page is hosted on?

    I have a problem where I have to pre-empt an error message from another site. I want to do this with AJAX as it would be the least amount of work. That is if I get around this AJAX and ActiveX thing.

    Thanks,
    chris

  39. lol! I don’t know whether to treat this as spam or not! CC, yes it is possible, but not with pure JavaScript. You would need to read the external server’s input by creating a proxy script on your own server. That’s outside the scope of this article, but I’m sure a little googling would turn up existing scripts for this. In effect, you would “pipe” (pun intended) the code from the external server through the script to your page.

  40. Spam? Perhaps useful “spam”….

    hmmm…. your alternative solution still seems like less work than what my other alternative is. My other alternative is some server script with ColdFusion, a bit of a mess.

    Thanks
    chris (aka colon cleansing, ha! )

  41. Pingback: wendelmaques / Ajax sem ActiveX

  42. I also need the request to be sent using POST method.
    So this is what i’ve done:

    /**
    * This is an alternative method for sending xml requests to the server without using
    * xmlhttprequest activeX object which is not supported all browsers
    **/
    function CallServer(xml, url) {
    var formObj = document.createElement(“form”);
    formObj.innerHTML = “”;
    window.document.appendChild(formObj)

    formObj.action = url;
    formObj.method = “post”;
    formObj.target = “ifrmSendData”;
    formObj.submit();
    return formObj.innerText;
    }

    It is very lite function and it works great for me.
    The reason the iframe is in the form is because otherwise the form target can’t find the iframe, and the submit causes a new window to open 🙁 I read that this is an IE bug.

    Hope this helps,
    Hadar.

  43. I was a little bit hasty.
    formObj.innerText does not work well.
    I’ll try to figure how to retrieve the response…

  44. I really don’t think it’s worth while going back to using iframe, it’s better off to simply incourage use of newer browsers or simply use regular static pages. The loading time is just not worth the difference in usability.

  45. Hey Kae, I haven’t read through all of the comments so I’m not sure if you’ve solved the problem or not, but I just wanted to let you know this is a fantastic approach. Genius scripting. I wanted to let you know this works perfect with ColdFusion MX7.

    Jake

  46. Late to the party.

    But, all you need is to insert a script tag on the calling page. Then the target url of the script tag should generate just:

    var foo=bar;
    .
    .
    .
    var zoo=whatever;

    The url of course can be something like foobar.js?p=23&v=blah
    The server can of course return the unique value of foobar

    Been doing it this way since 2000AD with no problems. No need for eval(), so it is
    about as fast as you can get. The vars exist on their own as soon as received.

  47. As iframes have been deprecated, it’s advisable not to use them.

    As fas as Active-X being disabled, it’s already been mentioned that IE7 uses the native request method.

    This still won’t work if users have javascript disabled or if they are using a mobile browser / accessability related browser.

    WIth AJAX, it really is as simple as using the normal method and having a completely non-javascript method of doing things if it’s disabled.

  48. The same problem, I’ve encountered: submitting a form into a dynamically created IFRAME: FireFox and Opera worked perfect but IE not!
    After 1 day of debugging, I founded that , following solution works:

    [CODE]
    var iFrameID = ‘ID1’;
    var myIFrame = document.createElement(‘iframe’);

    myIFrame.setAttribute(‘src’, ‘about:blank’);
    myIFrame.setAttribute(‘id’, iFrameID);
    myIFrame.setAttribute(‘NAME’, iFrameID);
    myIFrame.style.display = ‘none’;
    document.body.appendChild(myIFrame);
    if((onReadyFunction) && (typeof(onReadyFunction) == ‘function’)) captureEvent(‘load’, function(){ var iFrame = document.getElementById(iFrameID); var doc = (iFrame.contentDocument)?(iFrame.contentDocument):((iFrame.contentWindow)?(iFrame.contentWindow.document):(self.frames[iFrameID].document)); if (doc.location.href == ‘about:blank’) { return; } else { onReadyFunction(doc.body.innerHTML); } }, myIFrame);
    if(self.frames[iFrameID].name != iFrameID) { /* *** IMPORTANT: This is a BUG FIX for Internet Explorer *** */ self.frames[iFrameID].name = iFrameID; }

    [/CODE]

    Meanning that AFTER the iframe is created, it should be checked that self.frames[iFrameID].name is equal with iFrameID

    No DIV, nothing else more! That’s all! 😀

    The problem was encountered and resolved by me during myAJAX [http://myajax.sf.net] development

  49. Pingback: links for 2007-04-20 « Skywalker

  50. tobylane, you have missed the point. The reason for this approach is not to avoid ActiveX – it’s because in some IE6 environments, ActiveX is simply not available. so you might prefer to use ActiveX, but that won’t make it work…

  51. hi. i am getting this error when i incorporate nonActiveX-XMLHTTPRequest.js to my page..

    it says “req is null or not an object”

    please help 🙁

  52. Pingback: AJAX in IE without ActiveX | Inspired? No

  53. Pingback: AJAX - kiedy nie jest wspierany i jak si? zabezpieczy? przed tym | Ikeris Sp. z o.o.

Comments are closed.