2014-12-26 14 views
5

Mam pewne problemy z kierowaniem dynamicznie tworzonych elementów przy pomocy JavaScript.Problemy JavaScript dotyczące zdarzeń dla dynamicznie tworzonego HTML

Issue 1

Skrócony kod 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: Teraz chcę zrobić imprezę na moim <nav>. Jak mogę przekonwertować wydarzenie na adres #lightbox nav a zamiast tylko #lightbox nav?

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

Próbowałem wielu rzeczy, na przykład:

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 
    }); 
} 

I tak:

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

Skrócony kod 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: Jak dodać wydarzenie do dynamicznie tworzonego #lightbox img? img = document.createElement("img") musi być wewnątrz funkcji dołączania wielu obrazów, iz tego powodu nie mogę zrobić tak (jak obecnie na <nav>):

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

Czy ktoś mógłby mi pomóc w tej sprawie? Nie mam dużego doświadczenia z JavaScriptem.

+0

To jest dobre pytanie. +1 –

Odpowiedz

0

W moim przypadku rozwiązanie nie było zbyt trudne. Dzięki temu, że @adeneo zmusił mnie do myślenia o obsłudze zdarzeń zagnieżdżania, okazało się, że działa dobrze - i mogłem używać wszystkich selektorów bez modyfikacji:

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

Dalej ... [Obietnice] (http://blog.millermedeiros.com/callbacks-promises-signals-and-events/) –

+0

@DdieB Nie czytałem o tym, jakie są obietnice, czy można je wdrożyć w mój przypadek? – mnsth

3

wydanie 2

Proste rozwiązanie polega na dodaniu obsługi zdarzeń dla wszystkich elementów wewnątrz pętli

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); 
     } 
    }); 
} 

Nieco trudniejsze rozwiązaniem jest użycie przekazane obsługi zdarzeń

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); 
     } 
    }); 
} 

Wydanie 1

może być rozwiązane jak wyżej, z delegowanym wydarzeniem ndler

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

     // an achor was clicked, do stuff 

    } 
}); 
+0

Dziękuję za odpowiedź. Twoje "delegowane programy obsługi zdarzeń" nie wyglądają zbyt elegancko, nie ma lepszych rozwiązań? A jeśli umieszczę rzeczy takie jak 'e.stopPropagation()' i 'this' wewnątrz tych instrukcji if, na co będą one kierować? Oświadczenie "to", między innymi, polega na selektorze funkcji, prawda? – mnsth

+0

Jeśli chcesz bardziej elegancko, powinieneś przyjrzeć się bliżej, jak to robi jQuery. jQuery wiąże 'event.target' jako' this' w procedurach obsługi zdarzeń, dzięki czemu 'this' faktycznie staje się elementem dynamicznym itd. Zatem możliwe jest tworzenie funkcji convience, które wyglądają lepiej niż sprawdzanie' nodeType'.Zasadniczo jest to dokładnie to, co robią jQuery i inne biblioteki, ale dołączają one procedurę obsługi zdarzeń do elementu nadrzędnego, opierając się na propagacji, a następnie sprawdzają, czy dowolny element w drzewie DOM z pliku event.target pasuje do określonego selektora ciągów itp. – adeneo

+0

Niestety, nie mogę napisać całego mechanizmu selektora i biblioteki obsługi zdarzeń jako odpowiedzi, mogę tylko pokazać, jak działa delegowany program obsługi zdarzeń, a ty musisz spędzić wszystkie godziny robiąc coś, co pasuje do twoich potrzeb. – adeneo

Powiązane problemy