"Ajaxové" formuláre pomocou Iframe
AJAX sem, AJAX tam. Dnes už každá pidi-webová aplikácia asynchrónnu javascriptovú komunikáciu na niečo používa. Pomocou AJAXu je možné odoslať takmer všetko, dokonca i formuláre. Tie však majú pár obmedzení.
Ajaxový formulár
- serializácia formulárových prvkov
- upload
Jedným z problémov je fakt, že v prípade AJAXu si musíme parametre requestu poskladať sami v textovej podobe. To znamená, že si musíme prvky formulára zoserializovat, čo pri množstve rôznych typov prvkov (textový input a textarea, checkbox, radio button, select box, …) nie je jednoduché.
Druhý a väčší problém sú formuláre s uploadom. Javascript nemá prístup k dátam vybraného súboru (HTML5 už prácu so súbormi definuje a napríklad Firefox3.6 dokáže so súbormi už celkom pekne pracovať) a preto si jeho obsah do requestu nemôžeme pridať sami. Tento problém sa často rieši pomocou rôznych Flashových nadstavieb (napr. posielanie príloh v Gmaili).
Iframe to the rescue
Formulár však najspolahlivejšie odošle sám prehliadač, tak prečo ho
z tohto procesu vytláčať? Formuláre (podobne ako odkazy) majú
k dispozícii atribút target, ktorý môže obsahovať meno okna,
do ktorého sa formulár má odoslať. Nemusí to však byť nové okno, či
tab. Môže to byť i iframe, čo s výhodou využijeme.
Na formulár zavesíme vlastný submit handler, v ktorom:
- vytvoríme nový iframe
- previažeme ho s formulárom pomocou atribútov
nameatarget - a na takto vytvorený iframe zavesíme
loadhandler, v ktorom si počkáme na „ajaxovú“ odpoveď servra
function formSubmit( e ) {
var e = evt.fix( e );
var form = e.target;
form.target = form.id + '-iframe';
var iframe = document.createElement( 'iframe' );
iframe.name = form.target;
document.body.appendChild( iframe );
evt.add( iframe, 'load', getXmlResponse );
}
evt.add( document.getElementById( 'form' ), 'submit', formSubmit );
Odpoveď môže prísť v rôznych formách (textová, JSON, XML). Ja som nedávno začal v AJAXovej komunikácii používať práve XML a tu som narazil na pár drobností, ktoré IE rieši trochu inak. Ide o získanie XML dokumentu z načítaného iframu a o získanie obsahu konkrétneho XML tagu.
Iframe, XML a Internet Explorer
XML odpoveď z iframu získame pomerne jednoducho načítaním dokumentu
okna iframu: iframe.contentWindow.document. Internet Explorer
bohužial v tomto kuse kódu vráti HTML dokument, ktorý obsahuje farebne
zvýraznené XML (zobrazte si nejaké XML priamo v IE a uvidíte o čom
hovorím). Našťastie však po XML dokument nemusíme chodiť ďaleko:
var xmlDocument = iframe.contentWindow.document;
var xmlDocumentIE = iframe.contentWindow.document.XMLDocument;
Na podobný drobný rozdiel narazíme i pri pokuse o získanie textového obsahu XML tagu:
var xmlTag = xmlDocument.getElementsByTagName("person")[0];
var value = xmlTag.textContent;
var valueIE = xmlTag.text;
Po vyriešení oboch drobností môže naše spracovanie XML z iframu vyzerať napríklad takto:
function getXmlResponse( e ) {
var e = evt.fix( e ),
iframe = e.target,
xmlDocument = iframe.contentWindow.document.XMLDocument || iframe.contentWindow.document;
setTimeout( function() {
iframe.parentNode.removeChild( iframe );
}, 0 );
// example
var person = xmlDocument.getElementsByTagName( 'person' )[0];
document.getElementById('example-output').innerHTML = person.textContent || person.text;
}
Celý kód si môžete prezrieť v akcii v malej
ukážke. V príklade na prácu s eventami používam narýchlo zbastlený
objektík evt. V praxi však s najväčšou pravdepodobnosťou
šiahneme po obľúbenom JS frameworku.
Niektoré JS frameworky obsahujú i podporu pre odosielanie formulárov pomocou Iframe, napríklad io-upload-iframe modul z YUI3. Práve u tohto som však narazil na problém zo získaním XML dokumentu v IE, pretože aktuálna verzia obsahuje chybu.