Ajax

Introductie

Ajax staat voor “Asynchronous JavaScript and XML” en is een techniek om vanuit Javascript een asynchrone aanroep naar een server functionaliteit (server script page) te doen en met de resultaten daarvan de actieve HTML page aan te passen, zonder dat een page opnieuw geladen wordt. Ajax maakt het zo mogelijk om rich JavaScript client functionaliteit in HTML pagina’s op te nemen en deze asynchroon aan verschillende soorten server backends te koppelen: Java/JEE, .Net, PHP etc. NB: Ajax zelf bevat niet de rich client elementen, maar slechts de verbindingstechniek tussen javaScript en de server logic. Er wordt gewoon gebruik gemaakt form encoded parameters naar de server toe en tekst of xml data terug. Eventueel wordt JSON gebruikt ipv XML. De server logic behandelt dus gewoon http requests en retourneert xml, text of json data.

Ajax omvat de volgende technologie onderdelen:

  • HTML : voor de basis web pagina’s
  • CSS : voor de look en feel van de web pagina’s.
  • JavaScript : voor lokale processing, met het DOM (Document Object Model) om data en html elementen te benaderen en bewerken.
  • Het XMLHttpRequest object : om data asycnhroon uit te wisselen met de server
  • Een scripting language : zoals JSP/XHTML (JSF), ASP, PHP etc. voor verwerking van de XMLHttpRequest verzoeken.

Door het asynchrone karakter kunnen server acties worden uitgevoerd zonder dat het scherm voor de gebruiker wordt bevroren.

XMLHttpRequest heeft 2 methods om data op de server te krijgen:

  • open(mode, url, async): maak een connectie.
      • mode : request type : GET of POST
      • url: url path van het server script bestand
      • asycn : true : asynchroon request, false : synchroon request

    Optioneel kan nog een user en password worden meegegeven

  • send(“string”) : verzendt een request naar de server. De parameter is null i.g.v. een GET.

De server zendt data en status info terug via de volgende XMLHttpRequest object attributen:

  • responseXml : data middels XML
  • responseText : data middels text
  • readyState: De status van het uitstaande request:
    • 0: not initialized.
    • 1: connection established.
    • 2: request received.
    • 3: answer in process.
    • 4: finished.
      Alleen de laatste status is echt zinvol, want dan kunnen we iets doen met het resultaat naar het scherm toe.
  • status:
    200 : OK
    404 : Page not found

De volgende property definieert de aan te roepen function na afloop van het request:

  • onreadystatechange : property met de function die wordt aangeroepen bij readystatechange event

Ajax aanroep proces

Stap 1 : Maak het XMLHttpRequest object

Hiervoor zijn 2 mogelijkheden die afhangen van de browsersoort IE of anders. Controleer daarom eerst welke browser soort we hebben en maak vervolgens de request:

if (window.XMLHttpRequest)     // Standard object
{
    xhr = new XMLHttpRequest();     // Firefox, Safari, ...
}
else if (window.ActiveXObject)   // Internet Explorer
{
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
}

Alternatief is via exception handling probeer eerst IE, en bij exception gebruik de standaard:

try {
   xhr = new ActiveXObject("Microsoft.XMLHTTP");   // Trying IE
}
catch(e)    // Failed, use standard object
{
  xhr = new XMLHttpRequest();
}

Stap 2 : Definieer de afhandeling

Definieer de  function die moet worden aangeroepen na terugkeer van request resultaat

   xhr.onreadystatechange  = function()
      {
         if(xhr.readyState  == 4)
         {
              if(xhr.status  == 200)
                  document.ajax.dyn="Received:"  + xhr.responseText;
              else
                 document.ajax.dyn="Error code " + xhr.status;
         }
      };

In dit voorbeeld is het resultaat een tekst en deze wordt weggeschreven naar een HTML FORM element met name=”ajax” en daarbinnen een HTML INPUT element met name=”dyn”.

Een andere manier van HTML benadering kan zijn :

document.getElementById("dyn").innerHTML= “Received :” + xhr.responseText;

Als er XML wordt teruggegeven dan kan het volgende voorbeeld worden gebruikt:

var   doc = xhr.responseXML;
var  element = doc.getElementsByTagName('root').item(0);
document.ajax.dyn.value= element.firstChild.data;

Stap 3 : Verzendt het request

xhr.open('GET', 'http://localhost/somefile.xhtml', true);
xhr.send(null);

Voorbeeld van gebruik POST:

var data = "par1=" + par1value + "&par2=" + par2value;

xhr.open("POST", "http://localhost/somefile.xhtml", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(data);

Voorbeeld code

ajax.js

function  createXHR()
{
    var request = false;
    try {  request = new ActiveXObject('Msxml2.XMLHTTP');   }
    catch (e)
    {
        try {   request = new ActiveXObject('Microsoft.XMLHTTP');    }
        catch (e2)
        {
          try {  request = new XMLHttpRequest();     }
          catch (e3) {  request = false;   }
        }
     }
     return request
}

index.html

<html>
<head>
</head>
<script src="ajax.js" type="text/javascript"></script>
<script>
    var xhr = createXHR();
    xhr.onreadystatechange  = function()
    {
         if(xhr.readyState  == 4)
         {
              if(xhr.status  == 200)
                  document.ajax.dyn="Received:"  + xhr.responseText;
              else
                 document.ajax.dyn="Error code " + xhr.status;
         }
    };

   xhr.open(GET, "data.txt",  true);
   xhr.send(null);

</script>

<body>
    <FORM method="POST" name="ajax" action="">
         <INPUT type="BUTTON" value="Submit"  ONCLICK="submitForm()">
         <INPUT type="text" name="dyn"  value="">
    </FORM>
</body>
</html>

Ajax en JSF

Uiteraard kan Ajax gewoon worden gebruikt met een servlet die de parameters leest en data retourneert in de vorm van text, xml of json. In JEE6 wordt echter Ajax expliciet ondersteund met een ingebouwde Ajax resource library.
Deze library kan met name worden toegepast binnen de JSF facelets technologie.
Daarbij kan met een tag elke JSF ui component Ajax enabled worden gemaakt. De benodigde Ajax resource library wordt in dat geval automatisch geladen. Bijv:

<h:inputText value="#{bean.message}">
    <f:ajax />
</h:inputText>

Met attributen van de <ajax:> tag kan het gedrag worden bepaald:

event :
Definieert het type event wat het gedrag triggert, bijv. click, mouseover, bluer, keyup etc.
Het zijn feitelijk dezelfde als JavaScript events, maar dan zonder de on prefix.
Als het event attribuut niet wordt gedefinieerd dan zal het default event worden gekozen.
Voor een commandButton element is dat bijv. click en voor een input element is dat valueChange.

<f:ajax event="click" />

execute :
Definieert de component of componenten die uitgevoerd moeten worden als het event optreedt. Default is dat de component waarin de ligt. Maar het kunnen ook andere componenten zijn waarbij de id’s van deze componenten worden gedefinieerd.
De volgende keywords kunnen ook worden gebruikt : @all, @none, @this, of @form.
Default is @this: het element waarin de tag zich bevindt.

<h:inputText id="userNo"
             title="Type a number from 0 to 10:"
             value="#{userNumberBean.userNumber}">
    ...
</h:inputText>

<h:commandButton id="submit" value="Submit">
    <f:ajax event="click" execute="userNo" />
</h:commandButton>

In dit voorbeeld wordt bij klik op de commandButton de inputText uitgevoerd. Dit moet worden gedaan omdat normaal gesproken dit element wordt uitgevoerd bij de submit van een form en de processing vervolgens op de server. Bij Ajax gebeurt dat natuurlijk niet en wordt precies aangegeven wat wel moet worden uitgevoerd.

render :
Definieert net als execute welke componenten ververst moeten worden na de request.

<h:commandButton id="submit" value="Submit">
    <f:ajax event="click" execute="userNo" render="result"/>
</h:commandButton>
<h:outputText id="result" value="#{userNumberBean.response}"/>

In dit voorbeeld wordt de outputText ververst. Dit wordt normaal gesproken uitgevoerd bij de submit van een form en de processing vervolgens op de server. Bij Ajax gebeurt dat natuurlijk niet en wordt precies aangegeven wat wel moet worden ververst na ontvangst van het Ajax request resultaat.

listener :
Definieert de method die in een backing bean wordt uitgevoerd.

<f:ajax listener="#{mybean.someaction}" render="somecomponent" />

Deze listener definieert bijv. de volgende method in de backing bean “mybean”:

public void someaction(AjaxBehaviorEvent event) {
    dosomething;
}

onevent :
Definieert de JavaScript function die uitgevoerd moet worden om de Ajax request te monitoren:

<f:ajax event="click" render="errormessage" onevent="monitormyajaxevent"/>

In dit voorbeeld wordt de JavaScript function “monitormyajaxevent” aangeroepen.
Dit gebeurt bij elke status change van de Ajax Request.
De JavaScript function krijgt een dataobject mee met de volgende attributen:

  • responseXML: De response in XML formaat
  • responseText: De response in text formaat
  • responseCode: De response in numeriek formaat
  • source: De bron van de event: het DOM element
  • status: De status van de Ajax call: begin, success, of complete
  • type: Het type van de Ajax call: event

onerror:
Definieert de JavaScript function die uitgevoerd moet worden om de Ajax fout resultaten af te handelen:

<f:ajax event="click" render="test" onerror="handlemyajaxerror"/>

De JavaScript function krijgt hetzelfde dataobject mee als bij onevent. De mogelijke waarden van de status attribuut zijn dan :

  • emptyResponse : Geen Ajax response van de server.
  • httpError : Een standaard HTTP error code : request.status==null of request.status==undefined of request.status < 200 of request.status >= 300
  • malformedXML : De Ajax response is niet goed gevormd.
  • serverError : De Ajax response bevat een error element.

Ajax en Rich Client Frameworks / Libraries

Ajax levert de asynchrone verbinding tussen javaScript en de logic op de server. Daarmee maakt het mogelijk om rich client interfaces te bouwen die gebruik maken van server logic door uitgebreid gebruik te maken van de JavaScripting. Behalve Ajax is er dus meer nodig om rich clients te maken, want je wilt vooral gebruik maken van beschikbare JavaScript componenten.

Er zijn verschillende benaderingen op dit gebied, Java/JEE/JSF specifiek, .Net specifiek, Generiek JavaScript only. Deze laatste heeft geen enkele binding met de gebruikte server technologie. De eerste twee richten zich op de specifieke Java en .Net platforms en richten zich op het eenvoudig maken van rich client componenten, zonder dat Ajax en JavaScript expliciet zichtbaar zijn.

JSF Specifiek: PrimeFaces, RichFaces

Voor JSF omgevingen zijn er libraries als PrimeFaces, RichFaces (JBoss), etc. die de JSF componenten set verrijken en uitbreiden met Ajax enabled rich client componenten waarbij de Ajax en JavaScript technologie volkomen onder water worden toegepast. Er worden feitelijk binnen het JSF concept nieuwe type componenten gebruikt die out-of-the-box zijn voorzien van diverse rich ui mogelijkheden. Bijv. een DataTable met alle faciliteiten voor paging, search etc.
Ook zijn er allerlei menu componenten beschikbaar.
Belangrijk is ook de mobile versie van PrimeFaces die widgets biedt om web applicaties een mobile app gezzicht te geven.

Java Specifiek: DWR (Direct Web Remoting)

Dit betreft een technologie die het mogelijk maakt om Java te voorzien van  JavaScript proxy interfaces. O.b.v. een Java omgeving worden de JavaScript proxies gegenereerd. Deze kunnen dan weer eenvoudig worden gebruikt in de JavaScript omgeving. Dit product kan ook goed worden gecombineerd met bijv. jQuery en frameworks die daar weer op zijn gebaseerd zoals jQuery EasyUI. Deze laatste biedt direct met een plugin ondersteuning voor DWR.

ASP.Net Specifiek

Microsoft biedt voor ASP.Net de Ajax Control Toolkit. Een verzameling kant en klare Ajax enabled controls. Verder verwijst het op haar asp.net/ajax site naar jQuery en Juice UI.
Juice UI is een library t.b.v. ASP.NET gebaseerd op jQuery en jQuery UI.
Dit is allemaal te vinden op http://www.asp.net/ajax.

Google Web Toolkit

Betreft een Google specifiek product waarbij de applicatie geheel in Java wordt ontwikkeld en middels een GWT-compiler wordt vertaald naar JavaScript + Java.
GWT bevat een Web UI Class Library met de nodige widgets voor het maken van schermen.
GWT bevat de GWT Designer, en GWT SDK. Dit zijn plugins voor Eclipse.
Met de Designer kunnen WYSIWYG schermen worden ontwikkeld en getest.
GWT kan gebruik maken van SmartGWT (http://code.google.com/p/smartgwt/) (voorheen GWT-Ext), een library met rich client widgets incl. server logic. Bijv. databound table controls incl. paging, sorting etc. SmartGWT kent ook een uitgebreidere commerciele editie: SmartClient pro en enterprise editions: http://www.smartclient.com/product/. Deze biedt ondermeer rapid prototyping features om userinterface+server+database te genereren.

jQuery (JavaScript only)

Zeer veel gebruikte library (jquery.com). Biedt niet zozeer zelf de rich JavaScript componenten. Er zijn wel veel van deze componenten verkrijgbaar die jQuery als basis gebruiken. Zo zijn er jQuery UI (jqueryui.com) en jQuery EasyUI (jeasyui.com). Deze bevatten diverse widgets om i.s.m. jQuery te gebruiken. jQuery zelf bevat vooral de functionaliteit om DOM en CSS elementen te banderen en bewerken en om Ajax calls naar de server uit te voeren en af te handelen.
De kracht van jQuery zit in de transparantie van de DOM bewerkingen over de verschillende browser producten en versies heen.

Dojo toolkit (JavaScript only)

Vergelijkbaar met jQuery, maar aangevuld met rich componenten.

Mootools (JavaScript only)

Vergelijkbaar met jQuery, maar aangevuld met rich componenten.

ExtJS (JavaScript only)

Sencha is leverancier van een Rapid development platform voor HTML5 en mobile rich client ontwikkeling. Onderdeel van het aanbod is Sencha ExtJS. Niet goedkoop!!!

This entry was posted in JavaScript and tagged , . Bookmark the permalink.

Geef een reactie

Je e-mailadres wordt niet gepubliceerd.

De volgende HTML tags en attributen zijn toegestaan: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>