Meine lightweight Ajax-Klasse
27. September 2009 | 00:00:18
Motivation
Heute möchte ich euch meine lightweight Ajax-Klasse vorstellen. Diese habe ich in den letzten zwei Tagen entwickelt. Den Anstoß dazu gab mir ein Kommentar, der zu meinem Beitrag Freelancer abgegeben wurde und dort vermerkt war, dass mein Code wohl nicht "original" war. Nun, in der Tat (und das hatte ich beinahe übersehen) gab es die Ajax-Implementierung, bei der ich zu - ich würde sagen - 90% von meinem früheren Arbeitgeber (carcopy.com) beeinflusst wurde. Ich war bei Carcopy von Mitte 2007 bis (fast) Mitte 2008 angestellt und kam dort zum ersten Mal mit Ajax in Kontakt. Ich hatte dort sehr viel gelernt. Danke dafür an dieser Stelle!In der Zwischenzeit kam aber noch mehr dazu (obwohl ich nun in der Hardwarebranche arbeite) und so musste ich feststellen, dass der alte Ajax-Ansatz zu schwerfällig war. Es gab zwei Javascript-Dateien und drei Php-Dateien (plus der Php-Datei für den Widget-Pool) und alles zusammen machte ungefähr 600 Zeilen Programm-Code aus (ohne den Widget-Pool). Es war aber nicht nur unnötig aufgebläht, es war auch umständlich zu handhaben. Darum habe ich mir die ganze Sache nochmal zu Herzen genommen und das Ding auf meine Bedürfnisse zurecht gestutzt (auf ca. 160 Zeilen Code [JS + PHP]).
Download
Was dabei herausgekommen ist könnt ihr euch hier runterladen. Achso, das Ding steht unter der GPL.Die benötigte json.js Datei könnt ihr hier runterladen.
Anwendungsbeispiele
Hier ein Beispiel für die Anwendung eines Intervall-gesteuerten Requests. Der Paramter interval besimmt, in welchem Abstand (gemessen in Millisekunden) der Request ausgeführt werden soll.function test_interval( interval )
{
var ajaxTimer = new msAjax();
ajaxTimer.set( ajaxTimer.config, "interval", interval );
ajaxTimer.intervalSend(
ajaxTimer,
'timer_test',
function( retval ){
$('#test-interval').html( retval );
}
);
}
Hier ein Beispiel für die Anwendung eines Timeout-gesteuerten Requests. Der Paramter timeout besimmt, in nach wieviel Millisekunden der Request ausgeführt werden soll.
function test_timer( timeout )
{
var ajaxTimer = new msAjax();
ajaxTimer.set( ajaxTimer.config, "timer", timeout );
ajaxTimer.timerSend(
ajaxTimer,
'timer_test',
function( retval ){
$('#test-timer').html( retval );
}
);
}
Ajax-Klasse
Und nun zu guter Letzt noch die Klasse selbst./*
* Distributed under the terms of the GPL:
* Copyright (c) 2009, Matthias Sonnenkalb
* (www.matthias-sonnenkalb.net, msonnenkalb@gmx.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
function msAjax(){
var xhr = false;
this.config = {
'URL' : 'http://',
'widgetBase' : 'widgets.inc.php',
'asynchronous' : true,
'method' : 'POST',
'charset' : 'UTF-8',
'cache' : false,
'timer' : 0,
'interval' : 0,
'headers' : {
'X-Requested-With' : 'XMLHttpRequest',
'X-MsAjax-Version' : '1.2',
'Accept' : 'text/javascript, text/html, application/xml, text/xml, */*',
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
}
};
/**
* send.
*
* send request (try to get the widget).
*/
this.send = function( widgetName, callbackFunc, argsObj ) {
if( xhr ) {
xhr.open( this.config.method, this.config.URL +
this.config.widgetBase, this.config.asynchronous );
if( this.config.asynchronous == true ) {
xhr.onreadystatechange = function() {
if( xhr.readyState == 4 ) {
try {
retval = JSON.parse( unescape( xhr.responseText ));
if( !!callbackFunc ) {
callbackFunc( retval );
}
}catch( e ){
alert("invalid server response");
}
}
};
}
for( var header in this.config.headers ) {
xhr.setRequestHeader( header, this.config.headers[header] );
}
xhr.send( data( widgetName, argsObj ));
if( this.config.asynchronous == false ) {
try {
retval = JSON.parse( unescape( xhr.responseText ));
if( !!callbackFunc ) {
callbackFunc( retval );
}
}catch( e ){
alert("invalid server response");
}
}
}
}
/**
* timerSend.
*
* will be called once if timerout (config.timer) is reached.
*/
this.timerSend = function( objInstance, widgetName, callbackFunc, argsObj ) {
setTimeout( function(){
objInstance.send( widgetName, callbackFunc, argsObj );
}, objInstance.config.timer );
}
/**
* intervalSend.
*
* will be called every n-milliseconds (n is defined by value of config.interval).
*/
this.intervalSend = function( objInstance, widgetName, callbackFunc, argsObj ) {
setInterval( function(){
objInstance.send( widgetName, callbackFunc, argsObj );
}, objInstance.config.interval );
this.send( widgetName, callbackFunc, argsObj );
}
/**
* set.
*
* configuration setter.
*/
this.set = function( obj, prop, value ){
obj[prop] = value;
}
/**
* set.
*
* configuration getter.
* returns 'undefined' if propterty not available
*/
this.get = function( obj, prop ){
return obj[prop];
}
/**
* toString.
*
* provides the configuration object as a string.
*/
this.toString = function( obj ){
var str = "{\n";
for( var prop in obj ){
if( typeof obj[prop] == "object" ) {
str += prop + " : " + this.toString( obj[prop] );
}else{
str += prop + " = " + obj[prop] + "\n";
}
}
return str + "}\n";
}
/**
* build up a request object
*
* widgetName (string) - name of widget we want to request
* argsObj (json-object) - parameter given to widget (optional)
*
* return boolean true or false
*/
var data = function( widgetName, argsObj ){
if( !widgetName ){
alert('no widget-name given');
return false;
}
var data = new Object();
data.widgetName = widgetName;
if( argsObj ){
data.argsObj = new Object();
for( var property in argsObj ){
if( argsObj[property] != null && typeof argsObj[property] != 'object' ){
data.argsObj[property] = encodeURIComponent( argsObj[property] );
}else{
data.argsObj[property] = argsObj[property];
}
}
} else {
data.argsObj = null;
}
return 'args=' + escape( JSON.stringify( data ));
}
// -------------------------------------------------------
// try to get an request instance
// -------------------------------------------------------
// Mozilla, Opera, Safari and IE (>= v7)
if( window.XMLHttpRequest ){
xhr = new XMLHttpRequest();
// IE 6 or prior
}else{
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}catch( e ){
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}catch( e ){
alert("cannot get an instance of XMLHttpRequest object");
xhr = false;
}
}
}
}

