Ajax - IFrame
Keď už vieme prenášať požiadavky prostredníctvom objektu XMLHttpRequest, nezaškodí poznať aj iné alternatívy komunikácie medzi klientom a serverom. V dnešnom článku sa podrobne pozrieme na prenos údajov cez dynamicky vytvorený skrytý rámec.
Minule sme sa oboznámili s použitím objektu
XMLHttpRequest
, ktorý je určený na komunikáciu klienta so serverom. Dnešný článok bude o alternatívnom spôsobe komunikácie, ktorého použitie je v niektorých aspektoch oveľa výhodnejšie. Ak potrebujeme odosielať iba požiadavky typu GET a POST (čo je drvivá väčšina prípadov), je v súčasnosti komunikácia prostredníctvom skrytého rámca väčšinou tou lepšou možnosťou, ako samotný objekt
XMLHttpRequest
.
Prostredníctvom elementu
iframe
dokážeme prenášať údaje v HTML alebo v textovom formáte. Navyše od objektu
XMLHttpRequest
môžeme prenášať aj súbory z klientského počítača. Cestu k súboru však musí najskôr návštevník stránky vybrať, až potom môžeme prepísaním atribútu
target
formulára presmerovať požiadavku do skrytého rámca a súbor pomocou JavaScriptu odoslať na server.
V súčasnosti najväčšou výhodou prenosu dát prostredníctvom skrytého rámca je to, že v prehliadači Internet Explorer 6 a jeho predchádzajúcich verziách nepotrebujme používať ActiveX objekt. Pri vyššom stupni zabezpečenia tak nebude vyskakovať na používateľa otravná hláška. Okrem toho je element
iframe
podporovaný vo viacerých prehliadačoch, než objekt
XMLHttpRequest
. Vývoj však nezastavíme a v budúcnosti zrejme nebudú tieto dve výhody skrytého rámca až také podstatné.
Podobne ako to bolo pri použití objektu
XMLHttpRequest
, ani prostredníctvom rámca nemôžeme plne komunikovať so serverom z inej domény. Odosielanie požiadaviek je síce možné, avšak prečítanie odpovede už také jednoduché nie je. V JavaScripte sa totiž nedostaneme k dokumentu v elemente
iframe
, ktorý obsahuje stránku servera z inej domény. Napriek tomu môžeme v obmedzenej forme dostať odpoveď aj z takéhoto servera. Odpoveď môže byť obsiahnutá v adrese stránky, na ktorú server požiadavku skriptu presmeruje. Prečítaním adresy rámca z atribútu
src
sa túto odpoveď dozvieme.
Vytvorenie skrytého rámca
Najjednoduchším spôsobom, ako vytvoriť na stránke skrytý element
iframe
, je vložiť ho priamo do HTML kódu stránky. To však vôbec nie je elegantné. Keďže chceme oddeliť správanie od obsahu stránky, budeme skrytý rámec vytvárať prostredníctvom JavaScriptu. Rámec vytvoríme pomocou štandardnej metódy
createElement
pre vytváranie elementov. Aby bol neviditeľný, nastavíme mu nulovú šírku, výšku a nulové okraje. Posledným krokom je nastavenie obslužnej funkcie, ktorá sa zavolá vždy po dokončení nahrávania obsahu rámca.
function createIFrame ()
{
var iframe = null;
if (document.createElement)
{
var iframe = document.createElement ("iframe");
iframe.style.position = "absolute";
iframe.style.border = "0";
iframe.style.width = "0";
iframe.style.height = "0";
iframe.load = function () {receiveResponse (iframe)};
document.body.appendChild (iframe);
if (iframe.addEventListener) // Gecko / W3C
iframe.addEventListener ("load", iframe.load, false);
else if (iframe.attachEvent) // IE
iframe.attachEvent ("onload", iframe.load);
else
iframe.onload = iframe.load;
}
return iframe;
}
Pre nastavenie obslužnej funkcie použijeme štandardnú metódu
addEventListener
. V prehliadačoch, ktoré túto metódu nepodporujú, skúsime použiť neštandardnú metódu
attachEvent
, prípadne priradiť obslužnú funkciu priamo. Podobne ako v predchádzajúcom článku musíme aj tu myslieť na uvoľňovanie pamäte. Keďže sme elementu
iframe
nastavili obslužnú funkciu, ktorá používa odkaz na
iframe
, vytvorili sme kruhovú referenciu medzi elementom dokumentu a objektom JavaScriptu. Aby sme dokázali neskôr tento začarovaný kruh rozťať, odložíme si dočasne odkaz na obslužnú funkciu do vlastnosti
load
elementu
iframe
.
Odoslanie požiadavky
Požiadavku na server odošle prehliadač automaticky po nastavení adresy skrytého rámca alebo po zavolaní metódy
submit
formulára, ktorého odpoveď smeruje do skrytého rámca. Po spracovaní požiadavky sa odpoveď servera v tomto rámci objaví.
Odoslanie požiadavky metódou POST
Odoslanie údajov z formulára, ktorý je už na stránke, je jednoduché. Rámcu, ktorý sme vytvorili, priradíme nejaké meno v atribúte
name
a to isté meno nastavíme formuláru do atribútu
target
. Väčšinou však takýto formulár na stránke nemáme a odoslanie bude zložitejšie.
Pri odosielaní údajov metódou POST vytvoríme v skrytom rámci formulár, ktorý naplníme požadovanými údajmi. Nakoniec ho odošleme metódou
submit
. Odoslanú požiadavku zakóduje samotný prehliadač, takže nemáme priamu kontrolu nad odoslanými údajmi.
function sendRequest (data, url)
{
var iframe = createIFrame ();
if (iframe)
{
var iframeDoc = (iframe.contentWindow?
iframe.contentWindow.document:
iframe.contentDocument);
if (iframeDoc)
{
var pairs = data.split ("&");
var inputs = [];
var encode = function (text)
{
return decodeURIComponent (text).
replace (/&/g, "&").
replace (/</g, "<").
replace (/>/g, ">").
replace (/"/g, """);
};
for (var i = 0; i < pairs.length; ++i)
{
var pair = pairs [i].split ("=");
inputs [i] =
'<input type="text" name="' + encode (pair [0]) + '"' +
' value="' + encode (pair [1]) + '" />';
}
iframeDoc.open ();
iframeDoc.write (
'<form action="' + url + '" method="POST">' +
inputs.join ("") +
"</form>");
iframeDoc.getElementsByTagName ("form") [0].submit ();
}
return iframeDoc;
}
return false;
}
Uvedená funkcia dynamicky vytvorí skrytý rámec. Aby bolo možné zapísať do dokumentu rámca formulár, musí sa najprv dostať k dokumentu rámca, ktorý si uloží do premennej
iframeDoc
. V nasledujúcom kroku vygeneruje formulár na základe údajov, ktoré chceme odoslať. Tieto údaje sú uložené v reťazci
data
. Namiesto reťazca by sme mohli použiť napríklad asociatívne pole. Reťazec používame preto, aby bolo rozhranie funkcie pre odoslanie požiadavky rovnaké, ako v minulom článku.
Premenná
data
teda obsahuje zakódovaný formulár. Formulár je zakódovaný rovako, ako by to spravil pri odosielaní prehliadač. Reťazec pozostáva z dvojíc
meno=hodnota
, ktoré sú zreťazené znakom
&
. Meno aj hodnota sú URL-zakódované. Funkcia pre odoslanie požiadavky metódou POST tento reťazec dekóduje a vytvorí z neho formulár. Každá dvojica
meno=hodnota
zodpovedá jednému elementu
input type=text
, ktorého atribút
name
obsahuje meno a atribút
value
obsahuje hodnotu. Vygenerovaný formulár odošle údaje na zadanú adresu, čo dosiahneme nastavením atribútu
action
. Nakoniec volaním metódy
submit
formulár odošleme.
Odoslanie požiadavky metódou GET
Odoslanie požiadavky metódou GET je oveľa jednoduchšie. Stačí nastaviť zdroj rámca prostredníctvom atribútu
src
na požadovanú URL.
function sendRequest (data, url)
{
var iframe = createIFrame ();
if (iframe)
iframe.location.replace (url);
}
Táto funkcia ani nepotrebuje komentár. Nasledujúcim krokom bude prijatie a spracovanie odpovede nastavenou funkciou
receiveResponse
.
Prijatie odpovede
Pri vytváraní rámca sme mu nastavili obslužnú funkciu, ktorá sa zavolá po nahraní jeho obsahu. Táto funkcia spracuje odpoveď nastavenú v jeho dokumente:
function receiveResponse (iframe)
{
var iframeDoc = (iframe.contentWindow?
iframe.contentWindow.document:
iframe.contentDocument);
var text = iframeDoc.body.innerHTML.
replace (/&/g, "&").
replace (/</g, "<").
replace (/>/g, ">").
replace (/"/g, '"');
alert (text);
if (iframe.removeEventListener)
iframe.removeEventListener ("load", iframe.load, false);
else if (iframe.detachEvent)
iframe.detachEvent ("onload", iframe.load);
else
iframe.onload = null;
iframe.load = null;
setTimeout (function () {document.body.removeChild (iframe)}, 0);
}
Pri prijatí odpovede sa najprv dostaneme k dokumentu rámca. Potom dekódujeme jeho obsah. Ten je zakódovaný do HTML, takže musíme nahradiť špeciálne entity za znaky, ktoré reprezentujú.
Po spracovaní odpovede nesmieme zabudnúť na odregistrovanie obslužnej funkcie a odstránenie skrytého rámca zo stránky. Odstránením obslužnej funkcie, na ktorú sme si odložili referenciu do vlastnosti
load
, prerušíme kruhovú referenciu, čím umožníme prehliadaču Internet Explorer uvoľniť pamäť. Odstránenie skrytého rámca zo stránky o niečo oneskoríme, pretože odstraňujeme element, ktorého udalosť práve obsluhujeme. V opačnom prípade by prehliadač Firefox neukončil korektne načítavanie obsahu rámca.
Záver
V tejto časti seriálu sme si ukázali spôsob odosielania údajov metódou GET aj POST prostredníctvom skrytého rámca. Uvedené funkcie by mali stačiť na vytvorenie jednoduchej aplikácie, kde komunikuje klient so serverom.
Podobne ako v predchádzajúcom článku sme sa aj tu zaoberali uvoľňovaním pamäte. Pri písaní funkcií v JavaScripte, ktoré plánujeme využívať mnohokrát za sebou, by sme sa mali vždy zamyslieť aj nad problémom neuvoľňovania pamäte v niektorých prehliadačoch.
Vynikajúci serál, len tak ďalej. Niečo také na slovensko - českom internete dlho chýbalo. škoda že v čase keď som ja začínal s ajaxom toho bolo na nete oveľa menej. Inak Rich Internet Applications sa dajú kódiť aj vo Flashi.
Už se těším až budu mít čas a vyzkouším si to.