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 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.
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. 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.
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:<a href="#" id="element_28"
onclick="performAction(this.id.split('_')[1]);">
Am atribuit dinamic (cu 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?
