|
Datorita restrictiilor de securitate impuse de orice browser web, emiterea mesajelor intr-un mediu de cross domain nu este atat de directa precum intr-un mediu cu domeniu unic. Un browser nu va permite nici unei solicitari AJAX sa patrunda prin doua domenii diferite, dupa cum doua cadre, deschise in doua domenii diferite nu pot comunica unul cu celalalt si nu pot accesa DOM-ul, JavaScript-ul sau Cookie-urile. Atunci, cum poti face ca informatia sa fie transportata intre cele doua domenii diferite?
Exista doua cai populare de a indeplini acest lucru. In primul rand, putem modifica solicitarea AJAX uzuala astfel incat sa ocoleasca restrictiile cross domain-ului. Pentru a vedea cum se face acest lucru vezi tutorialul Pear HTTP Request - A Cross Domain AJAX focused. A doua cale este sa emiti mesajele printre doua cadre iframe, folosind URL Hash. Aceasta tehnica a fost folosita, bucurandu-se de o foarte mare popularitate, in numeroase secvente de instructiuni Java, un exemplu deosebit de celebru fiind toolkit-ul Dojo. Mai este numit si mesaje de identificare a fragmentelor (FIM) cu cadre IFrame.
Prezentarea tehnicii
Un Iframe poate fi deschis in pagina, fie static, fie dinamic. Informeaza-te din articolul: Creating, controlling and manipulating an Iframe through JavaScript. Vom folosi secventa de instructiuni pentru deschiderea dinamica a cadrului Iframe dat in articolul pe care tocmai l-am mentionat.
Acum, sa luam doua domenii, exampleX.com si exampleY.com, intre care trebuie transportate mesaje/date. Sa presupunem ca browser-ul URL indica in mod curent o pagina de pe exampleX.com. Folosind tehnica de emitere a mesajelor vom deschide un Iframe la interiorul acestei pagini. Acest Iframe va incarca apoi, in schimb, o pagina de pe exampleX.com si abia apoi va deschide un nou Iframe care sa indice exampleY.com. Sa numim aceste cadre Iframe1 si Iframe2. Sa presupunem ca Iframe1 incarca o pagina - testX.html, iar Iframe2 va incarca o alta pagina- testY.html. Aceste doua pagini pot reprezenta orice, in afara de pagini goale, cu continut JavaScript. Intreaga structura va fi ceva de genul:
Parent Window - exampleX.com
---- Iframe 1 - exampleX.com/testX.html
-------- Iframe 2 - exampleY.com/testY.html
Tehnica pe care o vom folosi pentru a transporta mesaje intre cele doua Iframe-uri este modificarea hash-urilor lor URL. Un hash URL este sirul care urmeaza dupa simbolul '#' dintr-un URL; de exemplu, in 'www.mabaloo.com#hello', hash-ul URL este '#hello'.
Pentru un browser, hash-ul URL reprezinta doar informatie aditionala pe pagina, iar alterarea acesteia nu afecteaza reincarcarea sau refresh-ul unei pagini. Acest lucru inseamna ca poti modifica hash-ul unui URL fara ca pagina sa fie incarcata din nou. Modificarea hash-ului nu este echivalenta modificarii URL-ului. Javascript poate accesa hash-ul URL apeland 'location.hash'
Iframe 1 - testX.html
Codul pentru testX.html ar fi ceva de genul celui dat mai jos. Aceasta este doar o mostra de codificare, exemplificand metoda de transmitere a mesajelor.
<script>
function generate_iframe(id, url) {
var IFrameObj;
if (!document.createElement) {return true};
var IFrameDoc;
if (!IFrameObj && document.createElement) {
try {
var tempIFrame=document.createElement('iframe');
tempIFrame.setAttribute('id',id);
tempIFrame.setAttribute('name',id);
tempIFrame.style.border='0px';
tempIFrame.style.width='1px';
tempIFrame.style.height='1px';
tempIFrame.style.display='none';
IFrameObj = document.body.appendChild(tempIFrame);
if (document.frames) {
IFrameObj = document.frames[id];
}
} catch(exception) {
iframeHTML='\<iframe id="RSIFrame" style="';
iframeHTML+='border:0px;';
iframeHTML+='width:0px;';
iframeHTML+='height:0px;';
iframeHTML+='"><\/iframe>';
document.body.innerHTML+=iframeHTML;
IFrameObj = new Object();
IFrameObj.document = new Object();
IFrameObj.document.location = new Object();
IFrameObj.document.location.iframe = document.getElementById(id);
IFrameObj.document.location.replace = function(location) {
this.iframe.src = location;
}
}
}
if (navigator.userAgent.indexOf('Gecko') !=-1 &&
!IFrameObj.contentDocument) {
setTimeout('callToServer()',10);
return false;
}
if (IFrameObj.contentDocument) {
IFrameDoc = IFrameObj.contentDocument;
} else if (IFrameObj.contentWindow) {
IFrameDoc = IFrameObj.contentWindow.document;
} else if (IFrameObj.document) {
IFrameDoc = IFrameObj.document;
} else {
return true;
}
IFrameDoc.location.replace(url);
return false;
}
function checkForMessages() {
if(location.hash != orig_hash) {
message = location.hash;
window.clearInterval(intval);
alert("The message recieved is " + message);
}
var orig_hash = location.hash;
intval = setInterval(checkForMessages, 200);
generate_iframe('Iframe2','http://exampleY.com/testY.html');
}
</script>
Acum, sa ne oprim si sa vedem ce se intampla in testX.html. In faza initiala, Iframe-ul testX.html este gol, nu are absolut nici un alt scop in afara receptarii mesajului de la exampleY.com. Asa ar trebui sa se intample mereu, insa, din moment ce nu fac decat sa arat cum functioneaza, nu prea avem nevoie de altceva. Acum, testX.html contine doua functii JavaScript - generate_iframe(), pentru a genera in mod dinamic un Iframe, si checkForMessages() pentru a verifica daca exista mesaje. Cand pagina testX.html este incarcata, ea genereaza un Iframe care deschide locatia lui testY.html, si stabileste de asemenea intervalul de 200ms de executie pentru checkForMessages().
Sa iti explic cum functioneaza functia checkForMessages(). De fapt, este foarte simplu, functia doar compara hash-ul URL curent cu cel original. Daca nu sunt identice (ceea ce inseamna ca a fost emis un mesaj), va extrage hash-ul si va elibera intervalul (presupunand ca se va emite un singur mesaj si ca nu este nevoie ca checkForMessages() sa fie apelata din nou). Apoi, poti folosi mesajul care a fost extras si in continuare. (Nu uita ca location.hash incepe cu caracterul '#'). Tot ce am facut a fost sa alertez mesajul receptat, din moment ce este doar o secventa de instructiuni test.
Iframe 2 - testY.html
Codul pentru testY.html ar fi ceva in genul celui dat mai jos. Aceasta este doar o mostra pentru ilustrarea metodei de emitere a mesajelor.
<script>
var parent_location = 'http://exampleX.com/testX.html';
function send_msg(msg) {
parent.location = parent_location + '#' + msg;
}
send_msg('message');
</script>
Acest lucru este relativ usor prin comparatie cu testX.html. Totusi, nu este decat o demonstratie, si deci am considerat ca mesaj de trimis un mesaj fix. Exista doar o functie- numita send_msg- care ia mesajul ca parametru. Apoi, aceasta stabileste locatia sursa - parent.location – ca si locatie curenta, iar mesajul este insotit de un hash URL.
Cum se aranjeaza totul
Sunt sigur ca pana acum ai ghicit cum functioneaza totul. Iframe-ul 1 deschide un alt cadru - Iframe2 la interiorul sau si continua sa verifice daca exista schimbari in hash-ul sau URL. Iframe2 incarca o pagina care modifica hash-ul URL al sursei sale, in cazul de fata, Iframe1. Restul este aproape mult prea usor pentru a mai fi nevoie de explicatii. De indata ce hash-ul URL este schimbat, functia checkForMessage() din testX.html sesizeaza aceasta schimbare si extrage noul hash (mesaj) URL. Asta este tot. S-a reusit transmiterea unui mesaj dintr-un domeniu in altul
Imaginea de ansamblu
1.) In practica nu se va intampla aproape niciodata sa faci cadrele Iframe1 si Iframe2 sa functioneze atat de simplu dupa cum s-a aratat mai sus. Un scenariu oarecare ar fi acela ca, in momentul in care un utilizator se logheaza pe un site web, putem colora pagina in culoarea sa preferata, pe care o putem lua, sa spunem, de pe un alt site.
Deci, pentru aceasta, se va proceda in acest mod. De indata ce utilizatorul de intoarce la pagina dupa ce s-a logat, noi putem verifica un cookie sau o variabila, care se sesizeaza daca un utilizator este logat. Acum, daca utilizatorul este logat, atunci putem genera in mod dinamic Iframe1 folosind functia function generate_iframe() care va incarca pagina testX.html. Acum, Iframe1 va deschide in schimb un alt cadru - Iframe2, care incarca o pagina de pe un alt website. Aici, Iframe2 face o apelare AJAX pentru a obtine culoarea favorita.
Cand obtine culoarea favorita, transmite mesajul catre Iframe1 modificand hash-ul URL; de indata ce Iframe1 primeste mesajul, va extrage hash-ul URL si apoi va apela o functie din pagina sursa, care va schimba culoarea de fundal (citeste cu atentie articolul : Accesarea functiei sursa din Iframe)
2.) De asemenea, putem trimite URL-ul paginii sursa ca parametru GET catre pagina de pe exampleY.com.
Ceva in genul exampleY.com/testY.html?url=exampleX.com/testX.html. Acesta va inlatura constrangerea care impune cunoasterea URL-ului paginii sursa in avans. Poti lua ca reper articolul despre accesarea parametrilor GET cu JavaScript. (Nu uita de Encodarea URL-ului inainte de a-l trimite ca parametru GET. Ia ca punct de reper articolul despre codificarea si decodificarea URL-rilor)
Problema cu aceasta tehnica
Desi probabil ca functioneaza foarte bine in toate browserele, recenta aparitie IE7 este setata in mod predefinit astfel incat sa considere Iframe-urile imbricate in cross domain ca pop-up-uri. Prin urmare, aceasta tehnica nu va functiona direct in IE7.
Citeste mai multe detalii despre IE7 in acest articol pentru a gasi solutia optima.
|