Team LiB
Previous Section Next Section

Hack 48. Submit Background Form Data

Submit form data without using a Submit button and without replacing the current page.

Web pages have a variety of security restrictions designed to protect the end user. When it comes to fill-in forms, HTML pages can't ordinarily submit form data without direct action from the user.

There is one exception. In the days of Java Applets, an applet could "phone home" to the server it came from, without user intervention. Web pages can now do that too. The XMLHttpRequest object makes it possible. The XML prefix is meaningless; any kind of data can be sent over HTTP using this object.

5.6.1. Getting Oriented

The syntax for Firefox's XMLHttpRequest object is slightly different than for Internet Explorer's version (a browser incompatibility). A jumping-off point for this technology is http://www.mozilla.org/xmlextras/. You can hear about issues with cross-browser syntax from the front line here:

http://www.scss.com.au/family/andrew/webdesign/xmlhttprequest/

The XMLHttpRequest object can make a synchronous or asynchronous request. In the synchronous case, the page will freeze until the web server sends back the response. In the asynchronous case, other activity can happen while the request is in progress, but the programmer has to remember to set up a script to listen for the results.

In all the examples shown here, assume that the current page is HTML and that it includes this fragment of content:

<form name="form1">
  <input type="text" name="field1" value="test1">
  <textarea name="field2">test2</textarea>
</form>

The XMLHttpRequest object can equally be used in XUL pages, provided that the different tags used for user-input elements are taken into account.

In the following examples, the server-supplied Content-Type header sets the type of any content returned. The overrideMimeType(string) method can be used to force that returned content to be treated as another type, but if so, that method must be called before the request is started with send(). Overriding types flies in the face of Internet standards and is usually the mark of a poor programmer. The only good reason for doing so is if you're sure that the server-supplied content is delivered wrongly in the first place.

5.6.2. Sending a Synchronous GET Request

This script queries the web server for data based on the current form. It examines results sent back in the HTTP headers and in the HTTP response body content and puts those results into the form:

var form     = document.form1;
var request  = new XMLHttpRequest(  );
var params = encodeURI("field1="+form.field1.value+";field2="+form.field2.value);

request.open("GET", "query.cgi" + "?" + params);
request.send("");                      // no POST data in a GET request.

if ( request.status == 200 )
{
   form.field1.value = request.getResponseHeader("Content-Length");
   form.field2.value = request.responseText;
}

5.6.3. Sending a Synchronous POST Request

This script packs up the form data and submits to the server. It checks the results to make sure everything went OK. POSTed data doesn't usually return a document, only repsonse headers, so this is a natural use of the XMLHttpRequest object:

var form     = document.form1;
var request  = new XMLHttpRequest(  );
var params = encodeURI("field1="+form.field1.value+";field2="+form.field2.value);

request.open("POST", "submit.cgi");
request.send(params);

if ( request.status == 200 )
{
   form.field1.value = request.getResponseHeader("Content-Length");
   form.field2.value = "Form data has been successfully sent";
}

5.6.4. Sending an Asynchronous GET Request

In this GET variant, an event handler is lodged on the request. The handler fires when the response is received. The script continues immediately after send() is called:

function response_handler(  )
{
  if ( request.status == 200 ) {
    form.field1.value = request.getResponseHeader("Content-Length");
    form.field2.value = request.responseText;
  }
  else {
    form.field1.value = "Query Failed";
  }
}

var form     = document.form1;
var request  = new XMLHttpRequest( );
var params = encodeURI("field1="+form.field1.value+";field2="+form.field2.value);

request.onload = response_handler;
request.open("GET", "query.cgi" + "?" + params, true);  // true = async
request.send("");
form.field1.value = "Waiting for Response";            // runs straight away

To see this at work, put a sleep statement (or other delay) in the server .cgi, .jsp, or .php form handler code. You can still interact with the web page while the server's asleep.

5.6.5. Sending an Asynchronous POST Request

In this POST variant, an event handler is also lodged on the request. The handler again fires when the response is received. The script continues immediately after send() is called:

function response_handler(  )
{
  if ( request.status == 200 ) {
    form.field1.value = request.getResponseHeader("Content-Length");
    form.field2.value = "Form data has been successfully sent";
  }
  else {
    form.field1.value = "Submission Failed";
  }
}

var form     = document.form1;
var request  = new XMLHttpRequest( );
var params = encodeURI("field1="+form.field1.value+";field2="+form.field2.value);

request.onload = response_handler;
request.open("POST", "submit.cgi", true);               // true = async
request.send(params);
form.field1.value = "Waiting for Confirmation";        // runs straight away

Again, to see this at work, put a sleep statement (or other delay) in the server .cgi form processing code to see that the browser isn't suspended waiting.

    Team LiB
    Previous Section Next Section