Filip Cherecheș-Toșa
Follower of Jesus, husband, father of three, builder

JavaScript, Events, IE

Nota: 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?