JavaScript, Events, IE
10 May 2007Nota: am ceva probleme cu WordPress & pre-code tags, asa ca formatarea codului nu e nici best-practice nici cum arata ea in realitate, in codul meu ;) .
Aurelian [a scris][2] ieri despre frustrarile pe care i le-a adus Internet Explorer in atribuirea dinamica de evenimente pentru elemente HTML.
Am scris un raspuns destul de consistent pe blog-ul sau, dar s-a pierdut printre request-uri (HTTP)… Dar am avut si eu de-a face cu problema asta si ma gandeam sa prezint solutia gasita.
[2]: http://www.locknet.ro/article/javascript-events-ie “”
Studiu de caz
Intr-o aplicatie la care lucrez, am de luat din baza de date o serie de date, printr-un request Ajax. Script-ul PHP apelat, trimite inapoi array-ul de date in format [JSON][3]. Pentru fiecare element, clonez un nod din DOM (pe post de template) care are, la randul sau, sub-elemente. Atribui frumos diferite proprietati (id, href, src etc.) elementelor din acel nod si il injectez inapoi in document, unde am nevoie de el. Toate bune si frumoase! Pe Firefox. :)
[3]: http://en.wikipedia.org/wiki/JSON “” :)
Prima problema in IE In procesul de parcurgere a
JSON-ului primit de la server, am nevoie sa atribui unor elemente cate-un eveniment onclick, asa ca cel mai la-ndemana mi-a fost: element.setAttribute("onclick", "foo();");
Concret, am facut ceva de genul:
/* response contine obiectul JSON, care arata cam asa:
{ "children": [
{"id": 1, "title": "cool title 1"},
{"id": 2, "title": "cool title 2"},
{"id": 3, "title": "cool title 3"}
] }
*/
for(i = 0; i < response.children.length; i )
{
// multe alte instructiuni...
// "element" este un element de tip anchor (a)
element.setAttribute("onclick", "performAction("
response.children[i].id ")");
}
Atribuirea asta merge fara probleme pe Firefox, dar in IE nu se intampla nimic. Nici o problema, am zis, folosesc o functie generica de
event handling, care sa identifice browser-ul si sa foloseasca metoda corespunzatoare browser-ului curent: function _attachEvent(elem, eventName, handler) { if (elem.attachEvent) { return elem.attachEvent(“on” eventName, handler); } else if (elem.addEventListener) { elem.addEventListener(eventName, handler, false); return true; } return false; }
A doua problema cu IE
Ce am descoperit (dupa multe experimente si cautari pe Google) e ca in Internet Explorer (6) atribuirea de elemente se face dupa ce se executa tot codul JavaScript. E ca si cum s-ar face intr-un thread paralel.
Adica in timp ce in Firefox, fiecare element din acel loop primea un eveniment onclick, in IE doar un singur element primea acel eveniment, dar ca si cum l-as fi atribuit la terminarea acelui for (deci i = response.children.length). Complet aiurea!
Solutia gasita Experimentand variante impreuna cu
Bogdan, seful meu, am hotarat sa facem urmatorul artificiu:
element.setAttribute()) id-ul si am “hardcodat” onclick in acel nod template, pe care l-am clonat. Functioneaza perfect, desigur. :) Ce experiente aveti cu cross-browser JS?