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:
- Firefox
- Internet Explorer 7.0
- Opera
- Safari
- Safari på iPhone
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:
Kommentarer
18 Aug 2009 23:46
DávurHehe...jeg ser at du har gået i en god skole

- fine små tuts, du laver her.
19 Aug 2009 16:27
V4D5Dávur - hvor herligt. Jeg tænkte på dig i denne uge. Tænkte "gad vide, hvor Dávur blev af". Ja - jeg lærte rigtigt meget på WebCafeen. Er stadig ærgerlig over, at den lukkede.
Hvor har du din online gang? Din offline gang er vel stadig på Færøerne
20 Aug 2009 11:13
DávurJa * snøft * caféen...suk. Bagmandspatruljen er spredt for alle vinde - der går måneder imellem at jeg har kontakt til nogen af dem.
Faktisk har jeg på det seneste ledt efter forskellige af de gamle brugere for at se hvad de har gang i, bare for sjov. Jeg grabbede jo de bedste himmerigsmundfulde blandt materialet på Caféen og skulle launche et statisk arkiv...men du ved: nyt job og nye fokusfelter. Her i ferien har jeg så checket det sørgelige skrog, jeg formåede at skrue sammen dengang, og stødte på bl.a. dit nick - og så ville jeg lige snuse rundt at se om jeg kunne lokalisere dig
Jeg er stadig sysadmin på Færøernes Universitet, roder for det meste med servere (VMware, Debian Linux og Win2003) og med indførelse af Web 2.0 teknologi ifm uni's web, intra -og extranet. Vi kører med Novell OES2 servere og der er der en masse legetøj at rode med.
Online, tjah jeg koder ikke så voldsomt meget mere selv mere men bruger og tweaker mest OpenSource komponenter til forskellige formål, til små begrænsede konsulent-opgaver. Jeg fabrikerede engang et ganske udmærket CMS, som nu driver et par sites men jeg har knap nok en hjemmeside selv, der er værd at vise frem (profocms.com); den er stendød, selvom jeg har prøvet at tage mig sammen til at få fuldført en længe planlagt makeover og køre på mit eget CMS (tsk tsk).
20 Aug 2009 23:16
DávurHeh - jeg besvarede vist ikke dit rigtige spørgsmål: Jeg er p.t. ikke aktiv på nogle fora, der har med IT at gøre overhovedet (udover Launchpad, hvor jeg af og til smider bugrapporter ind til Ubuntu-udviklerne).
25 Aug 2009 10:21
V4D5Nå - så du tog lige et lille online walk down memory lane. Jeg har færdes på flere fora gennem tiden og få er de steder, hvor stemningen var ligeså god som på WebCafe. En skam at den skulle lide off-line døden.
Savner du ikke at kode? Du var da ellers noget af en kode-haj og der er vel god brug for nogle stabile kodere. Du kunne jo lave noget Ubuntu-support? Er selv stor Ubuntu-fan.
25 Aug 2009 12:21
DávurJo, jeg savner i den grad at være lidt kreativ og kode fuldtid og lege Photoshop, lige som jeg gjorde årene 2000 - 2005, mens jeg var hos Sifira. Men der er jo den forskel, at i den periode var det min primære opgave at lave hammersolidt industrikvalitets web og det brugte jeg jo selv Caféen til og kunne give tilbage - gevinst begge veje.
Som sysadmin har jeg nogle manualer, jeg skal kunne på fingerspidserne til den daglige drift. Min kreative drift får så lidt afløb ved at jeg tester alskens systemer på job, som vi kunne implementere i vores netværk og hvor mange af disse er webserver-baserede tjenester, så der kommer mit gode kendskab til LAMP ganske tit meget handy

Jeg har på job lavet et par småting kodestumper til Linux-systemer, bl.a. til overvågning af DHCP-leases, men ikke noget jeg har overvejet at commite ind.
Ubuntu er nok stadig min foretrukne Linux desktop og jeg har efterhånden prøvet stort set alle, der er noget ved musikken og mere til. Til servere foretrækker jeg at bruge Debian.
Når du taler om Ubuntu-support, hvad ville du da efterlyse fra sådan en, som du ikke får svar på hos Google eller Ubuntuforums :) ? Jo, jeg har skam overvejet det men så skal jeg jo til at finde en 'kundeskare'

Hvad med dig - er du stadig regnfrakke-grossist eller hvad giver brød på bordet?
Har du lyst til at kommentere, er du mere end velkommen