2014-12-26 21 views
5

Ho alcuni problemi con il targeting di elementi creati in modo dinamico con JavaScript.Problemi JavaScript relativi agli eventi per l'HTML creato dinamicamente

Issue 1

codice accorciato JavaScript:

var lightbox = document.createElement('div'), 
    nav = document.createElement("nav"), 
    imga = document.querySelectorAll(".gallery a"); 
for (i = 0; i < imga.length; i++) { 
    imga[i].addEventListener("click", function() { 
     document.body.insertBefore(lightbox, document.body.firstChild); 
     lightbox.appendChild(nav); 
    }); 
} 

1: Ora voglio fare un evento sul mio <nav>. Come faccio a ottenere l'evento come target #lightbox nav a anziché solo #lightbox nav?

nav.addEventListener("click", function() { 
    // works, but I want to target only the <a> links inside 
}); 

Ho provato molte cose, come questo:

var selector = document.querySelectorAll("nav a"); 
for (i = 0; i < selector.length; i++) { 
    selector[i].addEventListener("click", function() { 
     // doesn't work because the <nav> is inserted dynamically 
    }); 
} 

E questo:

var selector = nav.getElementsByTagName("a"); 
for (i = 0; i < selector.length; i++) { 
    selector[i].addEventListener("click", function() { 
     // doesn't work because the <nav> is inserted dynamically 
    }); 
} 

Issue 2

accorciato codice JavaScript:

var img, 
    imga = document.querySelectorAll(".gallery a"); 
for (i = 0; i < imga.length; i++) { 
    imga[i].addEventListener("click", function() { 
      for (i = 0; i < imga.length; i++) { 
       img = document.createElement("img"); 
       lightbox.appendChild(img); 
      } 
    }); 
} 

2: Come si aggiunge un evento allo #lightbox img creato dinamicamente? Il img = document.createElement("img") deve essere all'interno della funzione per aggiungere più immagini, e per questo motivo non posso fare come questo (come attualmente in <nav>):

img.addEventListener("click", function() { 
    // doesn't work because img = document.createElement("img") 
    // has to be inside another function 
}); 

Qualcuno può per favore aiutare su questo? Non ho molta esperienza in JavaScript.

+0

Questa è una buona domanda. +1 –

risposta

0

Nel mio caso, la soluzione non era troppo difficile. Con @adeneo mi sempre pensare a gestori di eventi di nidificazione, si è scoperto funzionare bene - e sono stato in grado di utilizzare tutte le mie selettori senza modifiche:

var lightbox = document.createElement('div'), 
    nav = document.createElement("nav"), 
    imga = document.querySelectorAll(".gallery a"), 
    gallery = document.getElementsByClassName("gallery"), 
    img; 
for (i = 0; i < imga.length; i++) { 
    imga[i].addEventListener("click", function() { 
     lightbox.appendChild(nav); 
     document.body.insertBefore(lightbox, document.body.firstChild); 
     for (i = 0; i < imga.length; i++) { 
      img = document.createElement("img"); 
      lightbox.appendChild(img); 
     } 
     lightbox.addEventListener("click", function() { 
      // works fine 
     }); 
     var nava = document.querySelectorAll("#lightbox nav a"); 
     for (i = 0; i < nava.length; i++) { 
      nava[i].addEventListener("click", function() { 
       // works fine 
      }); 
     } 
     var limg = document.querySelectorAll("#lightbox img"); 
     for (i = 0; i < limg.length; i++) { 
      limg[i].addEventListener("click", function() { 
       // works fine 
      }); 
     } 
    }); 
} 
+0

Next Up ... [Promises] (http://blog.millermedeiros.com/callbacks-promises-signals-and-events/) –

+0

@EddieB Non ho letto su quali promesse sono effettivamente, potrebbero essere implementate in il mio caso? – mnsth

3

Issue 2

La soluzione più semplice è quello di aggiungere il gestore di eventi a tutti gli elementi all'interno del ciclo

var img, 
    imga = document.querySelectorAll(".gallery a"); 

for (i = 0; i < imga.length; i++) { 
    imga[i].addEventListener("click", function() { 
     for (i = 0; i < imga.length; i++) { 
      img = document.createElement("img"); 
      img.setAttribute("src", imga[i].getAttribute("href")); 
      lightbox.appendChild(img); 

      img.addEventListener('click', fn, false); 
     } 
    }); 
} 

la soluzione un po 'più difficile è quella di utilizzare i gestori di eventi delegati

var img, 
    imga = document.querySelectorAll(".gallery a"); 

lightbox.addEventListener('click', function(e) { 
    if (e.target.nodeType.toLowerCase() === 'img') { 
     // do stuff 
    } 
}, false); 

for (i = 0; i < imga.length; i++) { 
    imga[i].addEventListener("click", function() { 
     for (i = 0; i < imga.length; i++) { 
      img = document.createElement("img"); 
      img.setAttribute("src", imga[i].getAttribute("href")); 
      lightbox.appendChild(img); 
     } 
    }); 
} 

Numero 1

può essere risolto come sopra, con un evento delegato ha ndler

nav.addEventListener("click", function(e) { 
    if (e.target.nodeType.toLowerCase() === 'a') { 

     // an achor was clicked, do stuff 

    } 
}); 
+0

Grazie per la risposta. I tuoi "gestori di eventi delegati" non sembrano molto eleganti, non ci sono soluzioni migliori? E se metto cose come 'e.stopPropagation()' e 'this' all'interno di queste if-statement, quali saranno le loro target? L'affermazione di 'this', tra gli altri, si basa sul selettore di funzioni, giusto? – mnsth

+0

Se vuoi più elegante, dovresti guardare più da vicino come fa jQuery. jQuery lega "event.target' come' this' nei gestori di eventi, in modo che 'this' diventi effettivamente l'elemento dinamico, ecc. Quindi è possibile creare funzioni di convience che sembrano migliori del semplice controllo di' nodeType'.Tuttavia, in linea di principio questo è esattamente ciò che fanno jQuery e le altre librerie, collegano il gestore di eventi a un elemento genitore, facendo affidamento su bubbling, e quindi controllano se qualche elemento nella struttura del DOM da event.target corrisponde a un determinato selettore di stringhe ecc. – adeneo

+0

Sfortunatamente, non posso scrivere un intero motore di selezione e una libreria di gestione eventi come risposta, posso solo mostrarti come funziona in linea di principio il gestore di eventi delegato e devi passare tutte le ore a fare qualcosa che soddisfi le tue esigenze. – adeneo