Javascript-Code arbeitet mit Firebug Debugging korrekt, ohne nicht

WebWuschel

Grünschnabel
Hallo zusammen,

ich habe ein mysteriöses Problem. Habe ein Formular mit Dateiupload für Bilder. Das FileInput-Feld ist multiple, so dass man 4 Bilder auswählen kann. Wenn die Bilder ausgewählt wurden, sollen diese als Preview angezeigt werden, bevor diese hochgeladen werden. das habe ich mit folgendem Code realisiert:
Javascript:
function readURL(input) {
   var tr = $("#preview");
   tr.html("");
   for(var i=0; i < input.files.length; i++){
     if (input.files && input.files[i]) {
       var reader = new FileReader();
       reader.onload = function (e) {
         tr.append('<td id="img'+i+'" class="center">');
         var img = $('<img class="center" id="Bild'+i+'" alt="Bild '+i+'" width="100px" />');
         img.attr("src", e.target.result);
         var td = $("#img"+i);
         td.html("");
         td.append(img);
         tr.append('</td>');
       };
       reader.readAsDataURL(input.files[i]);
     }
   }
}
$('input[type="file"]').change(function(){
  readURL(this);
});

Das ganze soll die einzelnen Bilder laden und dann in eine Tabelle in die Tabellenzeile <tr id="preview"> einfügen:
HTML:
<table class="table table-striped">
 <thead>
  <tr>
    <th class="center">Bild 1</th>
    <th class="center">Bild 2</th>
    <th class="center">Bild 3</th>
    <th class="center">Bild 4</th>
   </tr>
  </thead>
  <tbody>
   <tr>
    <td class="center">'+file0+'</td>
    <td class="center">'+file1+'</td>
    <td class="center">'+file2+'</td>
    <td class="center">'+file3+'</td>
   </tr>
   <tr id="preview"></tr>
  </tbody>
 </table>

Problem:
Sobald die Bilder ausgewählt wurden, werden alle Bilder nacheinander (überschreiben sich) in die erste eingefügte <td>-Zelle eingefügt, weil alle <td id="img3"...> bekommen (bei 3 ausgewählten Bildern).
So sieht es aus wenn es ohne Firebug läuft:
HTML:
<tr>
<tr id="preview">
<td id="img3" class="center"><img class="center" src="base64......" id="Bild3" alt="Bild 3" width="100px" /></td>
<td id="img3" class="center"></td>
<td id="img3" class="center"></td>
</tr>

Wenn ich den Code in Firebug debugge und jede Zeile einzeln auführe, geht alles wie es soll (jedes Bild in eigener Tabellenzelle mit richtiger id).

So sieht es aus wenn es MIT Firebug läuft:
HTML:
<tr>
<tr id="preview">
<td id="img0" class="center"><img class="center" src="base64......" id="Bild0" alt="Bild 0" width="100px" /></td>
<td id="img1" class="center"><img class="center" src="base64......" id="Bild1" alt="Bild 1" width="100px" /></td>
<td id="img2" class="center"><img class="center" src="base64......" id="Bild2" alt="Bild 2" width="100px" /></td>
</tr>

Beende ich Firebug und wähle erneut 3 Bilder aus, werden wieder alle 3 Bilder in die Erste Tabellenzelle mit id="img3" geschrieben.

Ich kapiere es einfach nicht warum das so ist. Überspringt der Code da irgendwie die Zeilen oder was passiert da? Bin über jede Hilfe dankbar.

Gruß
Jochen
 

Sempervivum

Erfahrenes Mitglied
Dies ist ein gängiges Problem, wenn man in einer Schleife einen Eventlistener registriert und darin den Schleifenindex verwendet: Wenn das Event feuert, ist die Schleife durchgelaufen und der Index hat den Wert input.files.length.
Probiere dieses:
Javascript:
            function readURL(input) {
               var tr = $("#preview");
               tr.html("");
               for(var i=0; i < input.files.length; i++){
                 if (input.files && input.files[i]) {
                   var reader = new FileReader();
                   reader.onload = function (idx) {
                     return function(e) {
                       tr.append('<td id="img'+idx+'" class="center"></td>');
                       var img = $('<img class="center" id="Bild'+idx+'" alt="Bild '+idx+'" width="100px" />');
                       img.attr("src", e.target.result);
                       var td = $("#img"+idx);
                       td.html("");
                       td.append(img);
                      };
                   }(i);
                   reader.readAsDataURL(input.files[i]);
                 }
              }
            }
Allerdings ist die Reihenfolge zufällig, je nachdem welches Event zuerst feuert. Das könntest Du noch verbessern, indem Du die Tabellenzellen außerhalb des Listeners anlegst und das Bild dann in die richtige Zelle einfügst; der Index liegt ja vor.