3

I'm uploading files via an input type="file" and an XHR request. Uploads proceed very well. The problem is, I can't update my progress bars with onprogress. It works well if I upload only one file, but since there's more than one, there is only one progress bar being updated, the others simply just don"t work. It might come from the for loop, but I don't see how I may fix this If anyone has an idea, that'd be great !

Here's the code:

$('input').change(function() {

var allowedTypes = ['png', 'jpg', 'jpeg', 'gif'];   
var filesLen = this.files.length;
var fileInput = document.querySelector('#file');

for (i = 0; i < filesLen; i++)
{
    var vidType = this.files[i].name.split('.');

    if (allowedTypes.indexOf(vidType[vidType.length -1].toLowerCase()) != -1)
    {
        var progress = 'progress' + i;

        $('input').before('<p>' + this.files[i].name + ' <progress id="' + progress + '"></progress></p>');

        var xhr = new XMLHttpRequest();

        xhr.open('POST', '/upload/');

        xhr.upload.onprogress = function(e) 
        {
            $('#' + progress).attr('value', e.loaded);
        $('#' + progress).attr('max', e.total);
        };

        xhr.onload = function()
        {
            console.log('upload complete');
        };

        var form = new FormData();
        form.append('title', this.files[i].name);
        form.append('pict', fileInput.files[i]);

        xhr.send(form);

    }

    else
    {
        alert('Your file "' + this.files[i].name + '" \'s format isn\'t supported');    
    }
}
Andrew Domaszek
  • 651
  • 6
  • 18
Buzut
  • 4,875
  • 4
  • 47
  • 54
  • possible duplicate of [Javascript infamous Loop problem?](http://stackoverflow.com/questions/1451009/javascript-infamous-loop-problem) – Dagg Nabbit Oct 03 '12 at 16:51

1 Answers1

8

This is the "infamous loop problem."

The problem is here:

xhr.upload.onprogress = function(e) 
{
    $('#' + progress).attr('value', e.loaded);
    $('#' + progress).attr('max', e.total);
};

When this function runs, progress will be whatever it was when the loop exited, not what it was at the point in the loop where the function was defined. Try replacing that code with something like this:

(function(progress) { 
    xhr.upload.onprogress = function(e) 
    {
        $('#' + progress).attr('value', e.loaded);
        $('#' + progress).attr('max', e.total);
    };
}(progress));

More: Javascript infamous Loop issue?

Community
  • 1
  • 1
Dagg Nabbit
  • 75,346
  • 19
  • 113
  • 141
  • It works, thank you so much ! I'm quite new to JS and i had never heard of this "infamous loop problem". Now after a quick research, i have weel understood the issue : "JavaScript's scopes are function-level, not block-level, and creating a closure just means that the enclosing scope gets added to the lexical environment of the enclosed function." That's why an anonymous function gets rid of this infamous loop problem. Thank you again, you've just released me from a big headache ! – Buzut Oct 03 '12 at 17:20