arguments.callee web design & development blog  


AJAX Phrasebook
  1. Creating an AJAX object (XMLHttpRequest)
  2. Setting up a callback function
  3. Making GET requests
  4. Setting HTTP request headers
  5. POSTing form data
  6. Aborting an AJAX request in progress
  7. Server-side AJAX processing with PHP
  8. Serving XML, JSON, (X)HTML, or plain text
  9. Putting it all together: A reusable AJAX Singleton

Creating an AJAX object (XMLHttpRequest)

    // reusable XMLHttpRequest object
    var http = function() {
        return ('XMLHttpRequest' in window)
            ? new XMLHttpRequest()
            : (('ActiveXObject' in window)
                ? new ActiveXObject("Msxml2.XMLHTTP")
                : null);
    }();
top

Setting up a callback function

    // IE requires that you use http.open BEFORE assigning this
    http.onreadystatechange = function() {
        if (http.readyState === 4) {   // XMLHttpRequest code for "Done"
            if (http.status === 200) { // HTTP status code for "OK"
                // use http.responseText or http.responseXML here
            }
        }
    };
top

Making GET requests

    // simple GET request
    http.open("GET", "myPage.php", true); // false for synchronous (blocking)
    http.send(null);                      // null is required here
    
    // passing variables to PHP by modifying the URL
    var name = escape("Your Name");
    var age = 27;
    var queryString = "?name=" + name + "&age=" + age;
    http.open("GET", "myPage.php" + queryString, true);
    http.send(null);
top

Setting HTTP request headers

    http.open("GET", "myPage.php", true);
    
    /**
     * Set headers after open() and before send().
     * For a complete list of request headers, see:
     * http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html
     */
    http.setRequestHeader("User-Agent", "arguments.callee Custom UA");
    http.setRequestHeader("Accept", "text/plain, text/html, text/xml");
        
    http.send(null);
top

POSTing form data

    // gather form data
    var name = escape(document.getElementById("form-name").value);
    var address = escape(document.getElementById("form-address").value);
    
    // build query string
    var query = "?name=" + name + "&address=" + address;
    
    // make AJAX request
    http.open("POST", "myPage.php", true);
    http.onreadystatechange = function() {};
    http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    http.setRequestHeader("Content-length", query.length);
    http.setRequestHeader("Connection", "close");
    http.send(query); // not "null" as with GET requests
top

Aborting an AJAX request in progress

    http.abort(); // it's that easy!
top

Server-side AJAX processing with PHP

<?php
    // gather POST (or GET) variables
    foreach($_POST as $key => $value) {
        $$key = $value; // note the double $$
        /**
         * Using the last POST example, this loop will
         * create the variables $name and $address.
         */
    }
    
    /**
     * ALWAYS sanitize user input immediately before using it.
     * htmlspecialchars() for displaying on a webpage
     * mysql_real_escape_string() when using a MySQL database
     * filter_var() for more customizable sanitization
     */
    echo htmlspecialchars("$name lives at $address!");
    exit;
?>
top

Serving XML, JSON, (X)HTML, or plain text

<?php
    header("Content-Type: text/xml; charset=utf-8");
    echo '<?xml version="1.0" encoding="utf-8"?>
        <root>
            <name>HB</name>
            <address>123 Any St.</address>
        <root>
    ';
    exit;
?>
<?php
    // some older browsers don't recognize JSON, so serve plain text to them
    $mime = preg_match("/application\/json/i", $_SERVER["HTTP_ACCEPT"]) ? "application/json" : "text/plain";
    header("Content-Type: $mime; charset=utf-8");
    echo '[{"name":"HB","address":"123 Any St."}]';
    exit;
?>
<?php
    header("Content-Type: text/html; charset=utf-8");
    
    /**
     * JavaScript may do something like this with the following response:
     * document.getElementById("targetDiv").innerHTML = http.responseText;
     */
    echo '<p>This paragraph was retrieved via AJAX!</p>';
    exit;
?>
<?php
    header("Content-Type: text/plain"); // useful for delimited data (CSV, etc.)
    echo "1, HB Stone, 123 Any St.\n";
    echo "2, Sample Name, 345 Another St.\n";
    exit;
?>
top

Putting it all together: A reusable AJAX Singleton

    var Http = function() {
        var ReadyStates = {
            UNINITIALIZED : 0,
            OPEN          : 1,
            SENT          : 2,
            RECEIVING     : 3,
            DONE          : 4
        };
        var Status = {
            OK           : 200,
            MULTIPLE     : 300,
            FORBIDDEN    : 403,
            NOT_FOUND    : 404,
            SERVER_ERROR : 500
        };
        var http = function() {
            return ('XMLHttpRequest' in window)
                ? new XMLHttpRequest()
                : (('ActiveXObject' in window)
                    ? new ActiveXObject("Msxml2.XMLHTTP")
                    : null);
        }();
        return {
            isBusy: function() {
                return ((http.readyState !== ReadyStates.UNINITIALIZED) && (http.readyState !== ReadyStates.DONE));
            },
            request: function(obj) {
                if (typeof obj.url !== "string") {
                    return;
                }
                var orsc function() { // onreadystatechange
                    if (http.readyState === ReadyStates.DONE) {
                        switch(http.status) {
                            case Status.OK:
                                if (typeof obj.success == "function") {
                                    obj.success.call(http, http, obj);
                                }
                                break;
                            // handle other cases here as desired
                            default:
                                if (typeof obj.failure == "function") {
                                    obj.failure.call(http, http, obj);
                                }
                        }
                    }
                };
                var query = function() {
                    if (typeof obj.data !== "object") {
                        return "";
                    }
                    var q = "";
                    for (var i in obj.data) {
                        if (obj.data.hasOwnProperty(i)) {
                            q += (q.length) ? "&" : "";
                            q += encodeURIComponent(i) + "=" + encodeURIComponent(obj.data[i]);
                        }
                    }
                    return q;
                }();
                switch(obj.method) {
                    // implement other methods as desired (HEAD, PUT, DELETE, etc.)
                    case "GET":
                        http.open(obj.method, obj.url + "?" + query, true);
                        http.onreadystatechange = orsc;
                        http.send(null);
                        break;
                    case "POST":
                        http.open(obj.method, obj.url, true);
                        http.onreadystatechange = orsc;
                        http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                        http.setRequestHeader("Content-length", query.length);
                        http.setRequestHeader("Connection", "close");
                        http.send(query);
                        break;
                    default:
                        return; // invalid or unsupported method
                }
            }
        };
    }();

Any time you want to perform a request, you can do something like this:

    Http.request({
        url: "weather.php",
        method: "GET",
        data: {
            zipCode = "92261"
        },
        success: function(http) {
            alert("Weather report: " + http.responseText);
        },
        failure: function(http) {
            alert("AJAX call failed! Status code: " + http.status);
        }
    });
Tags




blog comments powered by Disqus
search blog
  • Professional-Ajax-2nd-Programmer
  • Rocket-Surgery-Made-Easy-Yourself
categories & tags
random posts
about hb stone

I'm a Front-End Engineer at Yahoo! working on the Mail and Messenger teams. I blog about web design and development topics including accessibility, usability, performance, and developing HTML / CSS / JavaScript applications on Appcelerator Titanium and Adobe AIR.

If you're a web developer, you might enjoy Jelo, my JavaScript library.

  • Adobe-AIR-1-5-Cookbook-Application
  • Introducing-HTML5-Voices-That-Matter
copyright

All original work on this site is covered by a Creative Commons Attribution 3.0 license unless otherwise specified.

You may share or use any code or images from this site in any manner, for free, so long as reasonable effort has been made to give credit where due.

The views expressed in the posts and comments on this blog do not necessarily reflect the views of Yahoo!