AJAX kommunikáció prototype-pal

ajaxA prototype igazán a kezünk alá dolgozik sok-sok mindenben. Ezek közül most vizslassuk meg, hogy mit tud AJAX ügyben. Egy egyszerű kis példán fogunk végigfutni. Adott egy link és ha rákattintunk akkor a szerver véletlenszerűen kiválaszt egy képet és visszaküldi nekünk.

Alapozunk

Html

A html head részében szükségünk lesz a prototype library-ra, szóval:

<script type="text/javascript" src="./prototype.js"></script>

Kiindulásként a lapon szükségünk lesz egy linkre és egy dobozkára amiben meg fog jelenni a szervertől kapott kép. Ha nem akarjuk, hogy az oldal többi része ide-oda csuszkáljon az adatok fogadása alatt, akkor jó ha a CSS-ben fixáljuk az elemek magasságát. Így akár benne van a válaszul érkezett kép, akár nincs ugyanakkora helyet foglal el.

<div id="ptypeajax">
	<div id="ptakep">ide jön majd a kép</div>
	<a href="#" id="amilinkunk">Kérek a szervertől egy képet!</a>
</div>
ide jön majd a kép

Kérek a szervertől egy képet!

Az üres link # nem éppen a legoptimálisabb megoldás, mivel így a javascriptet nem ismerő böngészők, mint például a keresőrobotok kizáródnak az alkalmazásból, de erről majd máskor beszélünk.

JavaScript

Itt egyenlőre csak arról gondoskodunk, hogy az oldal betöltése után legyen valaki aki figyeli, hogy mikor kattintanak a linkünkre. és ha ez netán bekövetkezne akkor hívja meg az adjUjKepet függvényünket. Az első observer azért kell, mert e nélkül a második observer nagy valószínűséggel még a DOM felépülése előtt lefutna, de a DOM nélkül ugye nem fogja megtalálni a mi linkünket.

Event.observe(window, "load", ptaInit);

function ptaInit(){
	aMiLinkunk = $("amilinkunk");
	Event.observe(aMiLinkunk, "click", adjUjKepet);
	}

AJAX lekérés

A prototype library két eszközt is a kezünkbe ad AJAX kommunikáció lebonyolítására. Ha a szervertől a válasz xml-ben jön akkor az Ajax.Request-et használjuk, ha viszont html-ben akkor az Ajax.Updater-t. Persze ha lehetőségünk van eleve html-t kapni a szervertől akkor miért ne tennénk ezt? 😉

function adjUjKepet(){
	var ptaKepHely = $("ptakep");
	//ajax lekérés
	//az updatert használjuk a request helyett mivel a válasz html-ben jön
	var url = "kepvalaszt.php";
	kepId = this.id ? 1 : 0;
	var params = "id="+kepId;

Az adjUjKepet függvényünk indításként létrehozza a ptaKepHely változót, ebbe a html objektumba fogjuk majd beírni a szerver válaszát. Az url változóban adjuk meg a meghívandó szerver oldali programfile elérési útját. Mivel itt azonos könyvtárban van a jelenlegi oldalt kiszolgáló filelal, így csak a nevét kell megadni elérési út nélkül. Aztán – kizárólag az izgalom kedvéért – paramétereket is létrehozunk, hogy legyen mit átadni a kepvalaszt.phpnak.

Ezután jöhet az AJAX lekérés, amit végtelenül egyszerűvé tesz a prototype.

	var ajax = new Ajax.Updater(
		ptaKepHely,
		url,
		{
			method: "get",
			parameters: params,
			onLoading: ptaLoading,
			onException: ptaKepHelyHiba
		}
		);
	}

Létrehozunk egy új Ajax.Updater objektumot. Az első paraméter ptaKepHely adja meg, hogy a szerver válaszát melyik html objektumban akarjuk megjelenítani, a második az url, hogy melyik szerver oldali alkalmazással kívánunk kommunikálni. A harmadik paraméterben megadjuk, hogy a lekérés get metódussal történjen, legyenek a php-nek átadva a paraméterek, és a következő 3 sorral pedig megmondjuk, hogy az egyes kommunikációs fázisokban mi történjen. Az onLoading esemény addig él amíg a szerver válaszára várunk, az onException pedig hiba esetén kel életre.

Az eseménykezelő függvények

Jó szokás szerint mindig tologatni szoktam, hogy a hibakezelést majd akkor ha…, és így általában el is marad. Szakítva ezzel a szép szokással most akkor kezdjük ezzel.

ptaKepHelyHiba

Hiba esetén egy rövid hibaüzenetet szeretnénk megjeleníteni és egy linket aminek a segítségével a felhasználók egyszerűen küldhetnek nekünk egy részletes bug reportot. Hiba akkor fordulhat elő, ha valami gond van a hálózati kommunikációval, rosszul adunk meg valami adatot, valaki letörli a meghívandó php fileunkat, stb. stb.

function ptaKepHelyHiba(ojjektum,hiba){
	ojjektum.containers.failure.innerHTML = "Valami gubanc van. " + hiba.name + " :: " + hiba.fileName + " :: " + hiba.lineNumber + " :: " + hiba.message;
	}

Ki is próbálhatjuk, úgy hogy mondjuk az url-t direkt hibásan adjuk meg. Ez a kis hibagyártás nem is volt olyan könnyen kikényszeríthető, mivel a wordpress kiszolgálja a nem létező fileokat is. Végül belepiszkáltam a függvénybe, és az url-ként egy html objektumot adtam meg. Na ez már hibát dob.

ide jön majd a kép (most meg a hibaüzenet.)

Kérek a szervertől egy képet!

ptaLoading

Ha a szervertől a válasz lassan jön, mert hosszú a szerver oldal feldolgozási ideje, vagy lassú a hálózat, akkor gondoskodnunk kell róla, hogy a user valahogy lássa, hogy a program fut, a kommunikáció folyamatban van, de még nem érkezett meg a szerver válasza. Erre szolgál a ptaLoading függvény. Itt a töltés ideje alatt egy kis animált cuccot jelenítünk meg amiből a user rájöhet, hogy mi történik. Ilyen kis kütyüket innen lehet szerezni.

function ptaLoading(){
	var ptaKepHely = $("ptakep");
	ptaKepHely.innerHTML = "<img src=\"ajax-loader.gif\" alt=\"töltögetek\" />";
	}

Ennek a függvénynek a segítségével így fog kinézni a boxunk a töltés alatt.

A szerver oldali script

Ennek magyarázatába nem akarok túlságosan belebonyolódni, mert nem sok kapcsolata van a témánkkal. A sleep azért kell, hogy láthassuk a loading állapotot. Mivel az updatert használtuk a szerver oldali scriptünknek html-t kell visszaadnia.

<?php
sleep(2);	//ezt éles alkalmazásokban nem javaslom ;)
$konyvtar = './images/';
$kiterjesztes = 'jpg';

$i = 0;
$fajlok = array();
if ($dir = @opendir($konyvtar)) {
	while ($file = readdir($dir)) {
		if(preg_match("/[a-zA-Z0-9]*\.$kiterjesztes/",$file)) $fajlok[$i] .= $file;
		$i++;
		}  
	closedir($dir);
	}
else print 'Nem találok a szerveren megfelelő fileokat ;( ';
	
print '<img src="'.$konyvtar.$fajlok[array_rand($fajlok)].'" width="100" />';
?>

És akkor lássuk az alkotást:

ide jön majd a kép

Kérek a szervertől egy képet!

Megjegyzések

  • A <a href=”#” onclick=”return(false);” id=”amilinkunk”> típusú megoldások nem éppen a legelegánsabbak. De erről inkább máskor írok. Addig is : diszkrét javascript.
  • Általában a felhasználók nem szeretik a technikai jellegű hibaüzeneteket, így nem is célszerű rájuk zúdítani. Barátságosabbá tehetjük az egész történetet, ha mondjuk csak annyit írunk ki, hogy sajnálom de elpusztultam és van melette egy link amire ha rákattint akkor egy részletes bug reportot kapunk emailben.
  • Tesztelve: Firefox, Opera, Safari és IE. Mindenhol fut, az IE a képet összenyomja, de ezt itt én most nem fogom megoldani 😉
  • Forráskódok letölthetők innen (4 KB).

9 thoughts on “AJAX kommunikáció prototype-pal

  1. Hi

    Túl sok mindent nem tudok hozzátenni 🙂
    Talán annyit, hogy “elegánsabb”, ha a loading gif-et egyszerűen beteszed a html-be id=”loading” és style=”display:none”-nal (fontos!!!). Ezután onLoadingnál egyszerűen Element.show(‘loading’), majd betöltés után Element.hide(‘loading’).

    Prototype 1.4 leírás (magyar): http://prototype.rajmi.hu/prototype.js.hu.html

    Prototype 1.5 leírás (angol): http://www.sergiopereira.com/articles/prototype.js.html

  2. IE6.0 alatt ha rákattintok a linkre akkor müxik, ha megint rákattintok akkor felvillantja ugyanazt a képet és elkezd a végtelenségig forogni a letöltésjelző..

    Ezért hanyagolom egyre inkább a prototype.js -t, csak a szívás van vele, hogy nem kezeli rendesen, hogy IE alatt status kód 200 jelenti a tranzakció végét FF alatt pedig 205.

    u.i.
    a muszájt sima j-vel írjuk 🙂

  3. Érdekes, hogy mennyire másképp álltam volna hozzá egy ilyen feladathoz, mind szerver oldalon, mind kliens oldalon. 🙂

    Szerveroldalon tuti, csak egy glob-ot használtam volna, és nem egy egész html-t adtam volna vissza, hanem csak mondjuk a filenevét.

    Kliens oldalon pedig dom-mal raktam volna be a képet a megfelelő helyre.

    Persze értem én, hogy ez csak egy példa… 🙂 Mégis érdekes, hogy egy egyszerű feladatot is számtalan módon meg lehet oldani. 🙂

    ui: a muszáj tényleg pontos j… 😉

  4. kicsiZ felvetésével kapcsolatban mi a megoldás? Próbáltam 1.6-os Prototype-pal is és így sem működik IE alatt. Ez kicsit eltántorított a prototype-pal való ismerkedéstől. Sok ilyen hülyesége van a prototype-nak? Mennyire fogom szivatni magam, ha rállok a prototype alapú fejlesztésre?

  5. Johnson: kicsiZ által megtalált hiba nem a prototype-é hanem az enyém 🙂

    Itt a leírásban próbáltam a lehető legegyszerűbbre venni a példát, hogy lehessen érteni. A prototype feltételezi, hogy a megoldandó feladat be van csomagolva egy objektumba, ami itt a példában nem történik. Ez okozza IE alatt a hibát.

    Az ember utánna gyorsan megszokja, hogy a prototype mit vár el tőle és akkor sokat lehet nyerni a használatával.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöljük.