19 July 2005

Some AJAX thoughts

Every webdeveloper has heard of AJAX last time. If you have not, you are not a webdeveloper, or you have invented it yourself and use another name for it. AJAX means: Asynchronous JavaScript and XML. But not all AJAX implementations use XML (see this article about JSON). But DHTML is not a buzz-word nowadays... Wikipedia has more info about AJAX than about DHTML.

Because I am a PHP developer, I am interested in the available PHP libraries for AJAX. After some searching I found the sajax and xajax libraries. I will not use sajax because it is not object oriƫnted.
But the JPSpan project is an AJAX project too. However, they do not use the AJAX buzz-word. And the JPSpan libraries make it possible to use PHP functions through JavaScript with the same name and parameters.

While reading around I found an interesting article titled: "Listen kids, AJAX is not cool". The author states JavaScript is not meant to implement basic functionality of a web page. I agree; too much web pages does not work without JavaScript. Use JavaScript (and all based on it) only to add some helper functions or do some layout enhancements.

However, I like the AJAX technology. You can use it to add hints (if typing the recipient in GMail) or create a dropdown list under an edit box. But always use it asynchronous (first A of AJAX). Requests have latency and it is very annoying if you can not type because the web page is waiting for an AJAX request.

For sending forms I have developed another asynchronous technology. I have implemented it in one site for the poll yet. But unfortunately that site is not updated frequently and the vote period has past. The maintainers should publish a new poll.
If JavaScript is enabled, the form will be sent using JavaScript and some info on the page will be dynamically updated. Without JavaScript a normal GET request will be sent and the whole page will be updated.
With JavaScript the request is sent by adding a <script> node to the HTML DOM tree with the url of the GET request in the src attribute. An extra parameter in the GET request indicates it is sent using JavaScript. If the script is sent using HTML this parameter is unavailable. The server responds depending on the presence of this parameter with JavaScript or with HTML.

An example of the JavaScript function to send a form:

/**
* Send contents of a form using a special JavaScript GET
*
* @access public
* @param object theForm
* @return bool return false on error (remember to set a return false in the onclick handler to prevent a double submit)
*/
function FormSendJs(theForm)
{
myRadioGroups = new Array();
myQuery = 'request_method=javascript';
for (i = 0; i < theForm.elements.length; i++) {
if ((theForm.elements.item(i).nodeName == 'INPUT') && (theForm.elements.item(i).type == 'radio')) {
/* handle radio buttons */
if (theForm.elements.item(i).checked) {
myRadioGroups[theForm.elements.item(i).name] = new Array();
myRadioGroups[theForm.elements.item(i).name]['Name'] = theForm.elements.item(i).name;
myRadioGroups[theForm.elements.item(i).name]['Value'] = theForm.elements.item(i).value;
} else if (!myRadioGroups[theForm.elements.item(i).name]) {
myRadioGroups[theForm.elements.item(i).name] = null;
}
} else {
/* other fields */
if (theForm.elements.item(i).name && (theForm.elements.item(i).name.length > 0)) {
myQuery += '&' + theForm.elements.item(i).name + '=' + theForm.elements.item(i).value;
}
}
}
/* detect if all radiogroups are filled */
myResult = true;
for (myRadioGroup in myRadioGroups) {
if (myRadioGroup == null) {
myResult = false;
break;
}
myQuery += '&' + myRadioGroups[myRadioGroup]['Name'] + '=' + myRadioGroups[myRadioGroup]['Value'];
}
if (!myResult) {
lastError = 'U heeft geen optie gekozen!';
return false;
}
/* construct URL */
myQuery = myQuery.replace(/&$/, '');
myUrl = new String('');
myUrl += theForm.getAttribute('action');
if (!myUrl.match(/\?/)) {
myUrl += '?';
} else if (!myUrl.match(/&$/)) {
myUrl += '&';
}
myUrl += myQuery;
/* construct results id */
myResultsId = theForm.id.replace(/_form_id$/, '_results_div_id');
/* remove form */
theForm.parentNode.removeChild(theForm);
/* display results */
myResults = document.getElementById(myResultsId);
myResults.style.display = 'block';
/* include JavaScript with constructed Url which will update the results */
myScript = document.createElement('SCRIPT');
myScript.type = 'text/javascript';
myScript.src = myUrl;
myResults.parentNode.insertBefore(myScript, myResults);
return true;
}

No comments: