AJAX uden X


193/5-2008


Ajax kan sagtens fungere uden XML. Jeg vil her give et kort eksempel.

På ekstremt mange hjemmesider har man brug for at oprette sig som bruger. Nogle gange indtaster man alle oplysningerne bare for at få at vide, at brugernavnet er taget. Opgaven her går ud på følgende:
-Når brugeren har indtastet sit ønskede brugernavn og går i gang med at indtaste ønsket password, så checker vi, om brugernavnet allerede er taget, om det minimum er seks karakterer langt og kun indeholder bogstaverne a-z.

Først skal vi have en side med en formular:

<html>

<head>
	<title>Opret bruger med Ajax uden x</title>
<head>

<body>
	<form action="opretbruger.php" method="post">
		Brugernavn:<br>
		<input type="text" name="brugernavn" id="brugernavn"><br>
		Password:<br>
		<input type="password" name="pwd1"><br>
		Gentag password:<br>
		<input type="password" name="pwd2"><br>
	</form>
</body>
</html>


Der er ingen grund til at checke noget, førend brugeren er færdig med at udfylde sit brugernavn. Det må vi antage, at han gør, når han forlader brugernavn-feltet, så vi tilføjer lige javascript-funktionen onBlur() til input-feltet, så det nu ser således ud:
<input type="text" name="brugernavn" id="brugernavn" onBlur="checkBrugernavn();">

Dernæst skal vi have oprettet funktionen checkBrugernavn(). Det gør vi i headeren.
Først skal vi ha' fingre i det brugernavn, som brugeren har indtastet. Det gør vi med metoden getElementById() - og funktionen ser nu sådan ud:
<script type="text/javascript">
	function checkBrugernavn() {
		var bNavn = document.getElementByID('brugernavn').value;
	}
</script>
Brugernavnet skal vi have sendt til vores server for at checke, om det allerede er i databasen. For at få det en tur til serveren, har vi brug for javascripts XMLHttpRequest-objektet. Nu er det så, at vi skal til at bøvle med, at der er forskelle i browsernes håndtering af XMLHttpeRequest-objektet.
Funktionen til at oprette objektet ser sådan ud:
function createXmlHttp() { 
	// Hvis XMLHttpRequest-objectet eksisterer, så returnér det.
	if (typeof XMLHttpRequest != "undefined") { 
		return new XMLHttpRequest(); 
	// Ellers skal vi bruge et ActiveX-objekt
	} else if (window.ActiveXObject) { 
		// Lav array med samtlige MS XMLHttp-objekter (nyeste først)
		var aVersions = [ "MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.5.0", "MSXML2.XMLHttp 4.0","MSXMLHttp.3.0","MSXM2.XMLHttp","Microsoft.XMLHttp"]; 
		
		// Gennemløb array med ActiveX-objekter 
		for (var i = 0; i < aVersions.length; i++) { 
			try { 
				// Hvis ActiveX-objektet kan instantieres
				// returneres det
				var oXmlHttp = new ActiveXObject(aVersions[i]); 
				return oXmlHttp; 
			} catch (oError) { 
				// Ellers er det bad luck
			} 
		} 
	} 
	throw new Error("Kan ikke instantiere XMLHttp-object"); 
}
I korte træk gør funktionen følgende:
Hvis XMLHttpRequest-objektet findes, så returnér det (altså der er tale om en Mozilla-, Safari- eller Opera-browser)
Ellers lav et array med de fem kendte MS ActiveX-objektnavne
Gennemløb dette array og forsøg at instantiere et objekt af klassen
Returnér dette, hvis det lykkedes – ellers fortsæt gennemløb af array
Ellers er det bare bad luck

Nu skal vi så kalde vores funktion createXmlHttp() fra funktionen checkBrugernavn(). Det gøres såresimpelt således:
var oXml = createXmlHttp();

Den eneste parameter, vi skal have sendt til vores server, er brugernavnet. Det har vi allerede fat i med variablen bNavn.

oXml.onreadystatechange=function() 
{ 
	// Her kommer mere senere
} 

var url = "checkbruger.php?bruger=" + encodeURI(bNavn); 
xmlHttp.open("GET",url,true);
xmlHttp.send(null);

For at overføre variablen bNavn, smider vi den i den enden af URL'en til serveren. Det gør jeg i linjen
var url = "checkbruger.php?bruger=" + bNavn; 

Dernæst åbner jeg forbindelsen til serveren og sender forespørgslen asynkront.

Nu er det tid til at kigge på serversiden. Det håndterer jeg med et PHP-script, men det kan også sagtens håndteres med JSP, ASP eller et andet serverside-sprog.

Jeg har kommenteret scriptet, så det skulle være til at forstå:
<? 
// Hent variablen bruger 
$bruger = $_GET["bruger"]; 

// Hardcodet bruger - her bør man i stedet lave et databaseopslag 
$oprettet = "birger"; 

// Hvis brugernavnet er taget 
if ($bruger == $oprettet) { 
	echo "Brugernavn taget"; 
	exit; 
} 

// Hvis brugernavnet indeholder andet end a-z
if (!eregi("^[a-zA-Z]+$",$bruger)) {
	echo "Ugyldige tegn";
	exit;
}

// Hvis brugernavnet er under seks karakterer 
if (strlen($bruger) < 6) { 
	echo "Brugernavn for kort"; 
	exit; 
} 

// Ellers returner OK 
echo "OK"; 

?>
For overskuelighedens skyld har jeg hard-codet en bruger. Det bør naturligvis være et databaseopslag (husk at sikre dig mod SQL-injektion - det er ligeså vigtigt i AJAX-applikationer).

Nu skal vi have kommunikeret serverens svar videre til brugeren. Til det formål, har jeg lavet en <span> med id'et "brugernavnStatus" efter brugernavnet i formularen, så jeg kan skrive serverens svar deri. Den ser nu således ud:
<input type="text" name="brugernavn" id="brugernavn" onBlur="checkBrugernavn();"> 
<span id="brugernavnStatus"></span>

Nu skal vi kigge lidt nærmere på, hvad der skal ske, når vi får et svar fra serveren.

Det første vi gør, er at checke, om vores oXml-objekt er "ready". Når det er tilfældet, checker vi, om vi har fået en 200 OK-besked fra serveren (det eneste, vi er interesseret i lige nu). Dette svar kommer vi i variablen svar.

Dernæst skal jeg have fat i den span, som svaret skal puttes i. Det gør jeg med getElementById()-metoden. Hvis der allerede er kommet ét svar, skal jeg blot ændre dette. Hvis ikke skal der oprettes en ny tekst-node, som svaret skal hældes i. Derfor checker jeg først, om span har nogen børn. Er dette ikke tilfældet, oprettes en tekstnode med svaret. Dette tilføjes så med appendChild()-metoden.

Jeg benytter med vilje ikke innerhtml, som mange gør. Det kræver et par ekstra linjer at undgå innerHTML, men innerHTML er ikke valid, så det er besværet værd, at tilføje en tekst-node i stedet.

oXml.onreadystatechange=function()
{
	if(oXml.readyState==4) {
		if (oXml.status == 200) {
			var svar = oXml.responseText;
			var svarspan = document.getElementById('brugernavnStatus');
			if (svarspan.childNodes.length == 0) {
				var txt = document.createTextNode(svar);
				svarspan.appendChild(txt);
			} else {
				svarspan.firstChild.nodeValue = svar;
			}
		}
	}
}
Så er vores brugernavns-check med AJA(X) færdigt. Da jeg bare får svaret i klar tekst, er der ikke noget XML indover det. Derfor artiklen hedder AJAX uden X.
Dette er testet og virker i:
OBS: - da jeg kun laver en case-sensitiv sammenligning på brugernavnet, vil du kunne bruge navnet "Birger", men ikke "birger" (som i øvrigt er den eneste hard-codede bruger i det her tilfælde).

Du kan selv prøve det her:
Brugernavn:

Password:

Gentag password:



Kommentarer


Ingen har endnu kommenteret dette indlæg. Du kan blive den første.
Har du lyst til at kommentere, er du mere end velkommen

Navn: *
Email: * (bliver ikke vist)
Hjemmeside:
Kommentar:

Anti-spam-check (beklager, men det er åbenbart nødvendigt):
Hvad er fire + fire? (skriv tal - ikke bogstaver)