Saturday, October 25, 2008

Ajax snippets

I decided to post a few snippets from my recent Ajax programming. There are quite a few snippets out there on the Web, but the one's I found were imperfect, so I thought I should post some tricks of my own.

Firstly, declare an xmlHttpRequest object and create it:
var xmlHttpRequest = false;
if (window.XMLHttpRequest)
    xmlHttpRequest = new XMLHttpRequest();
else if (window.ActiveXObject)
    xmlHttpRequest = new ActiveXObject('Microsoft.XMLHTTP');

Next, here's a nifty function that allows you to send POST commands:
// url = URL you are posting to
// data = data to be posted, e.g. 'variA=1&varB=2'
// action = pointer to a function that is executed
// when posting is complete; it must accept
// arguments: errorCode & response;
// errorCode will be 0 if no error
function ajaxPost(url, data, action) {
    xmlHttpRequest.open('POST', url, true);
    xmlHttpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xmlHttpRequest.send(data);
    xmlHttpRequest.onreadystatechange = function() {
        if (xmlHttpRequest.readyState == 4) {
            if (xmlHttpRequest.status == 200) {
                action(0, xmlHttpRequest.responseText);
            } else {
                action(xmlHttpRequest.status, '');
            }
        }
    };
}
Now, the hard part - this is a piece of code that searches recursively throughout a <form /> element, so that all the data fields (e.g. <input />) are collected into the POST request:
// node = HTML element, usually <form />
function getFormData(node) {
    var data = '';
    switch (String(node.tagName).toLowerCase()) {
    case 'input':
        switch (String(node.type).toLowerCase()) {
        case 'checkbox':
            data += node.name + '=' + escape(node.checked ? node.value : '') + '&';
            break;
        case 'hidden':
            data += node.name + '=' + escape(node.value) + '&';
            break;
        case 'radio':
            if (node.checked)
                data += node.name + '=' + escape(node.value) + '&';
            break;
        case 'text':
            data += node.name + '=' + escape(node.value) + '&';
        }
        break;
    case 'select':
        data += node.name + '=' + escape(node.options[node.selectedIndex].value) + '&';
        break;
    case 'textarea':
        data += node.name + '=' + escape(node.value) + '&';
        break;
    default:
        for (var i = 0; i < node.childNodes.length; i++)
            if (node.childNodes[i].nodeType == 1)
                data += getFormData(node.childNodes[i]);
    }
    return data;
}
The hardest part was to actually prevent the infinite loop that kept happening as a result of this iteration. Later, I realized that the var in the for loop was essential for it to work - if only JavaScript had complained that i was undefined or something. Sigh.

And now, the sample code that actually uses these abstract functions:
// formId = id of the <form /> element
function submitForm(formId) {
    if (!xmlHttpRequest)
        return true;
    var formTag = document.getElementById(formId);
    ajaxPost(formTag.action, getFormData(formTag), showResponse);
    return false;
}

// display the response in a message box
function showResponse(errorCode, response) {
    alert(errorCode + ':' + response);
}
Simply place this function inside your onclick attribute of the "Submit" button in your form.

Thanks to these sources for teaching me basic Ajax (many of the snippets above are derived from what I found on these sites):
Feel free to comment, if I missed something or made a mistake.

0 comments:

Post a Comment