-2

I have the following form which basically accepts a file upload and then displays a upload status. The final status goes to the status id. However, I have multiple forms and when you update the second one, for example, the status is displayed on the first form and not the second.

How can i have them all update, respectively, depending on the one that is updated.

Here's my code:

<script>
function _(el) {
  return document.getElementById(el);
}

function uploadFile(element) {
  var file = _("file1").files[0];
  alert(file.name+" | "+file.size+" | "+file.type);
  var formdata = new FormData();
  formdata.append("file1", file);
  var ajax = new XMLHttpRequest();
  var uploadValue = element.getAttribute("data-uploadValue");
  ajax.upload.addEventListener("progress", progressHandler, false);
  ajax.addEventListener("load", completeHandler, false);
  ajax.addEventListener("error", errorHandler, false);
  ajax.addEventListener("abort", abortHandler, false);
  ajax.open("POST", "/upload/" + uploadValue); //
  ajax.send(formdata);
}

function progressHandler(event) {
  _("loaded_n_total").innerHTML = "Uploaded " + event.loaded + " bytes of " + event.total;
  var percent = (event.loaded / event.total) * 100;
  _("progressBar").value = Math.round(percent);
  _("status").innerHTML = Math.round(percent) + "% uploaded... please wait";
}

function completeHandler(event) {
  _("status").innerHTML = event.target.responseText;
  _("progressBar").value = 0; //wil clear progress bar after successful upload
}

function errorHandler(event) {
  _("status").innerHTML = "Upload Failed";
}

function abortHandler(event) {
  _("status").innerHTML = "Upload Aborted";
}
</script>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>

Update 1: changed the JS to something more reliant.

Update 2: Decided to put the JS in the same output loop as the forms (so there was multiple scripts, one for each form) and inserted a unique number in each of the ids - basically making the ids unique. Whilst bad practice, this still didn't solve my issue.

Update 3 I have another form before each upload form which contains a text area - this seems to be causing issues. Alex Kudryashev answer works without these additional forms in place but not with.

Adders
  • 665
  • 8
  • 29
  • 1
    Do all the forms use the same IDs? IDs are supposed to be unique. You should use classes, and then use DOM navigation methods relative to `$(this)`. – Barmar Sep 26 '17 at 07:17
  • Yes they do. This is for the forms to be submitted by Ajax and currently is working as expected so I'd rather not change it due to my lack of skill with js – Adders Sep 26 '17 at 07:24
  • You have to change it. IDs are required to be unique. `$("#status")` will always select the first one on the page. – Barmar Sep 26 '17 at 07:26
  • to update them separately update them using ID #id_selector not the .class selector. Since class selector can be applied to many div's but ID is unique. – Naveen Kumar Sep 26 '17 at 07:26
  • _“and currently is working as expected”_ - I doubt that will still be the case when you actually use more than one of those on the page. Believe us, this is an issue you want to fix first of all, otherwise you are likely to run into all sorts of problems. IDs _have to_ be unique within an HTML document. – CBroe Sep 26 '17 at 07:26
  • Sorry, I was referring to the form id... my bad. yea the status id is the issue, just not sure how to fix it – Adders Sep 26 '17 at 07:34
  • @Adders are you not able to change id for that forms? – Ahmed Ginani Sep 26 '17 at 08:47
  • no not updating them – Adders Sep 26 '17 at 08:52

4 Answers4

1

The problem in OP is in getElementById which returns the first element only. The working solution is to find elements inside each form (when several) inside a closure bound to the form. something like this:
Update

I have another form before each upload form which contains a text area - this seems to be causing issues. Alex Kudryashev answer works without these additional forms in place but not with.

See updates in the code.

<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script>
        document.addEventListener("DOMContentLoaded", function () {
            for (var i = 0, form; form = document.forms[i]; ++i) {//iterate throu forms
                initForm(form);
            }
        });
        function initForm(frm) {
            //find elements of interest inside the form
            var fileUpload = frm.file1;//get by 'name' attribute inside the form
            var statusInfo = frm.querySelector('.status');
            var progressBar = frm.querySelector('.progress');
            var progressInfo = frm.querySelector('.loaded_n_total');

            //update. 'textarea' is in a separate form which doesn't contain 'file1'
            if (fileUpload)
               fileUpload.addEventListener('change', uploadFile);

            function uploadFile(e) {//'e' is 'change' event. It isn't used and may be ommited
                var file = this.files[0];// 'this' is fileUpload element
                //alert(file.name + " | " + file.size + " | " + file.type);
                console.log(file);
                var formdata = new FormData();
                formdata.append("file1", file, file.name);

                //update. A form with fileUpload contains other elements
                for (var i = 0, el; el = this.form.elements[i]; ++i) {
                    if (el !== this)
                        formdata.append(el.name, el.value);
                }

                statusInfo.innerHTML = 'prepare upload';
                var ajax = new XMLHttpRequest();
                var uploadValue = this.getAttribute("data-uploadValue");
                ajax.upload.addEventListener("progress", progressHandler, false);
                ajax.addEventListener("load", completeHandler, false);
                ajax.addEventListener("error", errorHandler, false);
                ajax.addEventListener("abort", abortHandler, false);
                ajax.open("POST", "/upload/" + uploadValue); //
                ajax.send(formdata);
            }
            function progressHandler(event) {
                progressInfo.innerHTML = "Uploaded " + event.loaded + " bytes of " + event.total;
                var percent = (event.loaded / event.total) * 100;
                progressBar.value = Math.round(percent);
                statusInfo.innerHTML = Math.round(percent) + "% uploaded... please wait";
            }

            function completeHandler(event) {
                statusInfo.innerHTML = event.target.responseText;
                progressBar.value = 0; //wil clear progress bar after successful upload
            }

            function errorHandler(event) {
                statusInfo.innerHTML = "Upload Failed";
            }

            function abortHandler(event) {
                statusInfo.innerHTML = "Upload Aborted";
            }
        }//initForm

    </script>
</head>
<body>
    <form enctype="multipart/form-data" method="post">
        <div class="file has-name is-fullwidth is-info">
            <label class="file-label">
                <input class="file-input" type="file" name="file1" data-uploadValue="form/1"><br>
                <span class="file-cta">
                    <span class="file-icon">
                        <i class="fa fa-upload"></i>
                    </span>
                    <span class="file-label">
                        Choose a file…
                    </span>
                </span>
                <div class="file-name">
                    <div style="color:red;" class="status"></div>
                    Supported file types: .png, .jpg, .jpeg and .gif
                </div>
            </label>
            <div style="display:none">
                <p class="loaded_n_total"></p>
                <progress class="progress" value="0" max="100" style="width:300px;"></progress>
            </div>
        </div>
    </form>
    <form enctype="multipart/form-data" method="post">
        <div class="file has-name is-fullwidth is-info">
            <label class="file-label">
                <input class="file-input" type="file" name="file1" data-uploadValue="form/2"
                       ><br>
                <span class="file-cta">
                    <span class="file-icon">
                        <i class="fa fa-upload"></i>
                    </span>
                    <span class="file-label">
                        Choose a file…
                    </span>
                </span>
                <div class="file-name">
                    <div style="color:red;" class="status"></div>
                    Supported file types: .png, .jpg, .jpeg and .gif
                </div>
            </label>
            <div style="display:none">
                <p class="loaded_n_total"></p>
                <progress class="progress" value="0" max="100" style="width:300px;"></progress>
            </div>
        </div>
    </form>
</body>
</html>
Alex Kudryashev
  • 9,120
  • 3
  • 27
  • 36
  • I have a textarea form before each of these forms which seems to be causing an issue... I've updated my question – Adders Oct 01 '17 at 08:43
  • 1
    Works perfect - thanks for your help! As a Python hobbyist, I have a lot to learn, particularly when it comes to JS - awarded the 50 rep – Adders Oct 02 '17 at 10:51
0

You should not define same id multiple times on a page. Because when you do so, and define jquery code with the id, the DOM will consider very 1st id it will found taking from top in the document. So it will happen that always first occurrence of a particular id will be referred.

So you need to change status to class, so : class="status" and then refer this class inside the ajax function with reference to the form you have sumitted, so it will only append your status to relevant element only. Check the code below:

$('#uploadform').ajaxForm({
    beforeSend: function() {
        $(this).find('.status').empty();
        var percentVal = '0%';
        bar.width(percentVal)
        percent.html(percentVal);
    },
    uploadProgress: function(event, position, total, percentComplete) {
        var percentVal = percentComplete + '%';
        bar.width(percentVal)
        percent.html(percentVal);
        //console.log(percentVal, position, total);
    },
    success: function() {
        var percentVal = '100%';
        bar.width(percentVal)
        percent.html(percentVal);
    },
    complete: function(xhr) {
        $(this).find('.status').html(xhr.responseText);
    }
});
Himanshu Upadhyay
  • 6,558
  • 1
  • 20
  • 33
0

Lets take a look at this part:

    uploadProgress: function(event, position, total, percentComplete) {
        var percentVal = percentComplete + '%';
        bar.width(percentVal)
        percent.html(percentVal);
        //console.log(percentVal, position, total);
    },

as your code refer the bar and percent as follow:

var bar = $('.bar');
var percent = $('.percent');
var status = $('#status');

The thing that i would expect to happened is not only the status will only update the first one, but the bar and percent in form 1, 2 until n will always show the same value when updated, any changes happened will reflected to all of the other as well. This is due to the DOM bound by each variable. So, i will put some changes on your code and lets do this a proper way:

<script>
    (function() {

        var forms = $(".some-upload-forms");

        for (var i = 0; i < forms.length; i++){
            initializeFormEvents(forms[i]);
        }

        function initializeFormEvents(form){
            var bar = form.find('.bar');
            var percent = form.find('.percent');
            var status = form.find('#status');
            var uploadForm = form.find("#uploadform");

            uploadForm.ajaxForm({
                beforeSend: function() {
                    status.empty();
                    var percentVal = '0%';
                    bar.width(percentVal)
                    percent.html(percentVal);
                },
                uploadProgress: function(event, position, total, percentComplete) {
                    var percentVal = percentComplete + '%';
                    bar.width(percentVal)
                    percent.html(percentVal);
                    //console.log(percentVal, position, total);
                },
                success: function() {
                    var percentVal = '100%';
                    bar.width(percentVal)
                    percent.html(percentVal);
                },
                complete: function(xhr) {
                    status.html(xhr.responseText);
                }
            })
        }
    })();


    </script>

And your html:

<div class='some-upload-forms">
    <form id="uploadform" enctype="multipart/form-data" method="post">
        <div class="file has-name is-fullwidth is-info">
          <label class="file-label">
            <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
            <span class="file-cta">
              <span class="file-icon">
                <i class="fa fa-upload"></i>
              </span>
              <span class="file-label">
                Choose a file…
              </span>
            </span>
            <span class="file-name">
              <div style="color:red;" id="status"></div>
              Supported file types: .png, .jpg, .jpeg and .gif
            </span>
          </label>
          <div style="display:none"><p id="loaded_n_total"></p>
          <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
        </div>
    </form>
</div>

Then you can duplicate more and more form in one page, make sure to duplicate start from the ;

Hans Yulian
  • 1,080
  • 8
  • 26
0

What you need to do in order to get your uploader into a valid repeatable form is to go through each of the forms and replace the ids with unique ones that make sense and allow each instance to function separately.

I'll divide the code into two steps. First step is to turn your invalid HTML into valid HTML:

function runner(index) {
  var form = document.getElementById('upload_form');
  if (!form) return false;
  form.id = 'upload_form-' + index;
  var children = document.querySelectorAll('#upload_form-' + index + ' *');
  for (i = 0; i < children.length; i++) {
    if (children[i].id) {
      children[i].id = children[i].id + '-' + index;
    }
  }
  return true;
}

var index = 0;

while (runner(index)) {
  index++;
}

This goes through all the forms having an id of upload_form in your page and appends a nice little index after their ids and the ids of their children, making sure they become unique.

Here's a small test:

function runner(index) {
  var form = document.getElementById('upload_form');
  if (!form) return false;
  form.id = 'upload_form-' + index;
  var children = document.querySelectorAll('#upload_form-' + index + ' *');
  for (i = 0; i < children.length; i++) {
    if (children[i].id) {
      children[i].id = children[i].id + '-' + index;
    }
  }
  return true;
}

var index = 0;

while (runner(index)) {
  index++;
}
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <div class="file has-name is-fullwidth is-info">
    <label class="file-label">
        <input class="file-input" type="file" name="file1" id="file1" data-uploadValue="{{ item[0] }}"  onchange="uploadFile(this)"><br>
        <span class="file-cta">
          <span class="file-icon">
            <i class="fa fa-upload"></i>
          </span>
          <span class="file-label">
            Choose a file…
          </span>
        </span>
        <span class="file-name">
          <div style="color:red;" id="status"></div>
          Supported file types: .png, .jpg, .jpeg and .gif
        </span>
      </label>
    <div style="display:none">
      <p id="loaded_n_total"></p>
      <progress id="progressBar" class="progress" value="0" max="100" style="width:300px;"></progress></div>
  </div>
</form>

Run it and inspect the forms, you'll notice they get indexes and so do their children having id attributes.


The second step is to make sure your current code looks for, gets and uses the id of the parent form, so that it correctly selects the ids of the elements inside it. To do this, I first get the parent form index for the input being used, and I pass this index to each subsequent function call, using a closure, so _() is always selecting the proper elements.

function _(el, index) {
  return document.getElementById(el + '-' + index);
}

function uploadFile(element) {
  var formId = element.closest('form').id,
    index = formId.split('-')[formId.split('-').length - 1],
    file = _("file1", index).files[0];
  alert(file.name + " | " + file.size + " | " + file.type);
  var formdata = new FormData();
  formdata.append("file1", file);
  var ajax = new XMLHttpRequest();
  var uploadValue = element.getAttribute("data-uploadValue");
  ajax.upload.addEventListener("progress", 
    (function(n) { progressHandler(event, n) })(index), 
    false);
  ajax.addEventListener("load", 
    (function(n) { completeHandler(event, n) })(index), 
    false);
  ajax.addEventListener("error", 
    (function(n) { errorHandler(event, n) })(index), 
    false);
  ajax.addEventListener("abort", 
    (function(n) { abortHandler(event, n) })(index), 
    false);
  ajax.open("POST", "/upload/" + uploadValue); //
  ajax.send(formdata);
}

function progressHandler(event, index) {
  _("loaded_n_total", index).innerHTML = "Uploaded " + event.loaded + " bytes of " + event.total;
  var percent = event.total ? event.loaded * 100 / event.total : 0;
  _("progressBar", index).value = Math.round(percent);
  _("status", index).innerHTML = Math.round(percent) + "% uploaded... please wait";
}

function completeHandler(event, index) {
  _("status", index).innerHTML = event.target.responseText;
  _("progressBar", index).value = 0; //wil clear progress bar after successful upload
}

function errorHandler(event, index) {
  _("status", index).innerHTML = "Upload Failed";
}

function abortHandler(event, index) {
  _("status", index).innerHTML = "Upload Aborted";
}

Side note: I took the liberty of changing

var percent = (event.loaded / event.total) * 100;

... into:

var percent = event.total ? event.loaded * 100 / event.total : 0;

..., as (maybe due to POST not being allowed on SO), event.total was 0 making percent NaN, generating an error on the very next line. If you don't have this problem in your live example, make sure you change this line back to whatever works for you.

As far as I could test it, it seems to work, the only error is about SO not allowing POST request, once the file has been selected and appended to the form.

If you run into any trouble, let me know and I'll try to figure out what's going on.

tao
  • 82,996
  • 16
  • 114
  • 150