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 id
s and the id
s 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 id
s 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.