For the last month or two I’ve been sweating away developing a new, all-singing all-dancing version of the CMS for the project we’re working on. I’ve been making extensive use of XMLHTTPRequest (Ajax, if you must) techniques to streamline workflow. And it’s all been working pretty well so far.
However, because (as far as I’m aware) XMLHTTPRequest can’t handle file uploads, I’ve had to be a bit more creative in coming up with a seamless way to allow files to be uploaded (ie. without a page refresh). After some fiddling about I resorted to a method that uses a dynamically-created, hidden iframe as the target for the upload form. It goes something like this:
- User chooses file and clicks submit
- Iframe is dynamically created and added to the page (using appendChild())
- Form is submitted through iframe
- Iframe executes callback function in parent document
- Iframe is removed (using removeChild())
And it works pretty well. But I found an odd quirk with Firefox (I’m using version 1.0.4, which is the current stable version at the time of writing). If an XMLHTTPRequest is executed, by a function that’s initiated by the iframe, after removing the iframe, then Firefox throws the following exception:
Error: uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIXMLHttpRequest.open]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: [File name] :: [Function name] :: line [ line number ]" data: no]
Please ignore the fact that I should really be catching all exceptions
At first I thought it must be security thing (allowing an iframe to call XMLHTTPRequests in its parent could, I suppose, be considered a potential security hole), but if you try the same thing without destroying the iframe then it works just fine. Which leads me to think it must be a *gasp* bug.
I checked bugzilla and found what sounds like the same problem in different circumstances so added my own findings and this reduced test case (source). I hate submitting to Bugzilla because I always seem to get shouted at for some reason, but maybe my submission will be enough to help it get fixed — although it’s been there for nearly a year now so I’m not holding my breath.
Solutions? Well I tried various approaches but ended up with a rather ugly fix: the callback function itself (in the parent document) just stores the data that’s supplied by the iframe. In the meantime, a function is repeatedly checking (using setTimeout()) whether any data has been returned and acts accordingly if it has. That way, it’s the parent document that initiates any subsequent XMLHTTPRequest calls, rather than a function that’s been called by the iframe. Not ideal, but it does the job.