2013-07-15 16 views
13

Mam funkcję javascript "doAll", która ma napisać cały tekst, który został umieszczony między tagami <p>, </p>. W moim kodzie jest on używany na dwa sposoby.Funkcja JavaScript działa w nieoczekiwany sposób

Działa poprawnie, gdy po prostu nazywam to na końcu strony. Jednak należy go również uruchomić, gdy nastąpi zdarzenie typu "kliknij przycisk". Z jakiegoś powodu nie robi to, co ma robić tym razem. Po jednym kliknięciu przycisku po prostu drukuje wewnętrzny html pierwszego elementu html o nazwie <p>...</p>.

Moje pytanie brzmi: dlaczego w tych dwóch sytuacjach działa inaczej i co należy zrobić, aby rozwiązać ten problem.

<!DOCTYPE html> 
<html> 
    <head> 
     <script> 
      function returnList(x) 
      { 
       return document.getElementsByTagName(x); 
      } 

      function writeList(x) 
      { 
       var i = 0; 

       while (x[i]) 
       { 
        document.write(x[i++].innerHTML + '<br/>'); 
       } 
      } 

      function doAll(x) 
      { 
       writeList(returnList(x)); 
      } 
     </script> 
    </head> 

    <body> 
     <p>XXX</p> 
     <p>YYY</p> 
     <div style = 'background-color: gray;'> 
      <p>YYY</p> 
      <p>XXX</p> 
     </div> 

     <button type = 'button' onclick = "doAll('p')"> 
      Click me! 
     </button> 

     <script> 
      document.write('<br/>'); 
      doAll('p'); 
     </script> 
    </body> 
</html> 

Oto 'wyjście':
XXX
YYY
YYY
XXX

XXX
YYY
YYY
XXX

A oto co można zobacz po kliknięciu przycisku:
XXX

+0

Dlaczego pierwsze wyjście składa się z 8 linii, chociaż istnieją tylko 4 p-tagi? wygląda na to, że kliknięcie jest uruchamiane wcześniej. –

+0

Pamiętaj: 'debugger' + narzędzia do tworzenia przeglądarki są zawsze Twoimi przyjaciółmi. – DontVoteMeDown

+0

@LarsEbert: nie, nie jest to spowodowane kliknięciem przycisku. Cztery dodatkowe linie wyjścia są konsekwencją sześciu ostatnich linii mojego kodu: D. Jak widać funkcja "doAll" jest automatycznie wyzwalana przez sekcję na dole kodu. –

Odpowiedz

14

Problem polega na tym, że strona jest już renderowane, po kliknięciu przycisku. W tym momencie wyzwalanie document.write() spowoduje przesłonięcie całego dokumentu. Pisze pierwszy element, ponieważ jest to jedyny element, który wciąż istnieje, kiedy uruchomiłeś swoją funkcję. Jakikolwiek inny element po prostu nie będzie po raz pierwszy wykonany po wykonaniu polecenia document.write().

Nawet twoja funkcja nie będzie już częścią dokumentu. Jeśli MUST praca z document.write() lub po prostu chcesz go używać w celach testowych, trzeba jakoś „cache” dane i wyjście to od razu:

function writeList(x) { 
    var i = 0, data = ""; 

    while (x[i]) { 
     data += x[i++].innerHTML + '<br/>'; 
    } 

    document.write(data); 
} 
3

document.write jest w stanie pisać treść tylko do aktualnie załadowanego dokumentu. Po załadowaniu zachowuje się trochę inaczej - patrz https://developer.mozilla.org/en-US/docs/Web/API/document.write. Użyj specjalnego elementu kontenera i innerHTML, aby napisać pożądany wynik.

function writeList(list) { 
    var i, result = ""; 
    for (i = 0; i < list.length; i++) { 
     result += list[i].innerHTML + "<br />"; 
    } 
    document.getElementById("myContainer").innerHTML = result; 
} 

http://jsfiddle.net/3yPAW/1/

+0

Nie ma właściwie potrzeby 'if' w pętli' for'. Po prostu 'result + = list [i] .innerHTML +"
";'. – Amberlamps

+1

Usunięto ... dziękuję za wskazanie tego. –

2

Pozostałe dwie odpowiedzi wyjaśniono dlaczego, I” ll proponujemy jak tego uniknąć:

dołączania kodu HTML do innerHTML ciała (lub inny element);

zamiast

document.write(x[i++].innerHTML + '<br/>'); 

użytku

document.getElementsByTagName("body")[0].innerHTML += x[i++].innerHTML + '<br/>'; 

Demo: http://jsfiddle.net/MNCbx/

Powiązane problemy