2.5. Fallback Option 1: Sending a Request Using an IFrame
Note that the use of IFrames does have a number of further limitations:
One advantage that an IFrame has over XMLHttpRequest is that it can be used to make file uploads. Due to browser security limitations, only user actions, such as clicking a form, can interact with files on the user's machine. This makes targeting a form to an IFrame the only option for file uploads that do not involve a normal form POST and page reload cycle. However, there is no reason you can't fall back to using an IFrame for file uploads and XMLHttpRequest for the rest of your AJAX requests. Unless you are making remote scripting-style AJAX requests (which is covered in Chapter 3, "Consuming the Sent Data"), working around IFrame limitations will add a significant amount of work to any AJAX development project.
2.5.1. Creating a Hidden IFrame
To get maximum compatibility with older browsers, you could just add the IFrame to your HTML and give it a size of 0x0. (You can't just hide it, or some browsers won't load it.) However, this approach isn't flexible, so you will want to create the frame dynamically. Not all older browsers support document.createElement, but browsers without that support will generally lack the other dynamic capabilities needed to use the data you're loading, so it's best to provide support to them with a static HTML version of the page. In the following example, the IFrame is created using innerHTML because it's simpler than creating it using DOM methods. Note, however, that it could also be created with document.createElement, just like the div to which it's being added:
1 var rDiv = document.createElement('div'); 2 rDiv.id = 'remotingDiv'; 3 var style = 'border:0;width:0;height:0;'; 4 rDiv.innerHTML = "<iframe name='"+id+"' id='"+id+"' 5 style='"+style+"'></iframe>"; 6 7 document.body.appendChild(rDiv);
2.5.2. Creating a Form
If you want to make only a GET request, you can change the value of the IFrame's src property, but to do POST, you need to use a targeted form. GET isn't a good solution for AJAX requests for two reasons: it can send only a limited amount of data (an amount that changes depending on the browser), and GET can be cached and/or preloaded by proxy servers, so you never want to use it to perform an action such as updating your database.
Using a form with an IFrame is easy. Just set the form's target attribute, and when you submit the form, the result loads in the IFrame. The following example creates our form and sets its targets to the IFrame we created earlier in the "Creating a Hidden IFrame" section of the chapter:
1 rDiv.form = document.createElement('form'); 2 rDiv.form.setAttribute('id', id+'RemotingForm'); 3 rDiv.form.setAttribute('action', url); 4 rDiv.form.setAttribute('target', id); 5 rDiv.form.target = id; 6 rDiv.form.setAttribute('method', 'post'); 7 rDiv.form.innerHTML = '<input type="hidden" name="data" 8 id="'+id+'Data">';
2.5.3. Send Data from the Loaded Content to the Original Document
2.5.4. Complete IFrame AJAX Example
A full example of an IFrame that AJAX requests includes two pieces. The first piece is the client-side code to create the IFrame and form. The second piece is the server-side code, which prepares some data and sends it back to the parent document in its onload event handler.
Listing 2-5. Making an AJAX Request Using an IFrame
Listing 2-5 is made up of three functions:
The createRemotingDiv function (lines 528) combines the previously described code for creating a hidden IFrame with the code for creating a form to submit to it. When the form is created, it's targeted against the newly created IFrame, making the form submission use it instead of reloading the current page. Showing the IFrame during development is often useful in the debugging process so that you can see any output generated by the page you're calling. You can do this by editing the style on line 8 and changing it to width:200;height:200;.
Listing 2-6. PHP Server Page That Handles an IFrame AJAX Request