I am trying to upload multiple images with File API. I want to show picture thumbnails and their names as title tag. The problem is I am not getting correct picture name as title tag. All pictures are showing same name. Here is my Original code...
jQuery, CSS and HTML
var output = document.getElementById("result");
$(document).ready(function ()
{
//Check File API support
if (window.File && window.FileList && window.FileReader)
{
$('#files').on("change", function (event)
{
var files = event.target.files; //FileList object
var iCount = files.length;
for (var i = 0, f; i < iCount; i++)
{
var file = files[i];
//Only pics
if (file.type.match('image.*'))
{
var picReader = new FileReader();
picReader.addEventListener("load", function (event)
{
var picFile = event.target;
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + file['name'] + "'/>";
output.insertBefore(div, null);
});
//Read the image
$('#clear, #result').show();
picReader.readAsDataURL(file);
}
else
{
alert("You can only upload image file.");
$(this).val("");
}
}
});
}
else
{
console.log("Your browser does not support File API");
}
$("#upload").on('submit',(function()
{
var data = new FormData(this);
var iUploaded = 0;
setTimeout(function()
{
var iCount = document.getElementById('files').files.length;
for (var i = 0; i < iCount ; i++)
{
data.append("Index", i);
$.ajax(
{
url: "upload.php",
type: "POST",
data: data,
contentType: false,
cache: false,
processData:false,
async: false,
success: function(response)
{
var sRes = response.split("|-|");
if(sRes['0'] == 'success')
{
iUploaded = iUploaded + 1;
$("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
}
}
});
}
}, 500);
}));
$("#files").change(function()
{
$("#submit").trigger("click");
});
$('#clear').on("click", function ()
{
$('.thumbnail').parent().remove();
$('#result').hide();
$('#files').val("");
$(this).hide();
});
});
body{
font-family: 'Segoe UI';
font-size: 12pt;
}
header h1{
font-size:12pt;
color: #fff;
background-color: #1BA1E2;
padding: 20px;
}
article
{
width: 80%;
margin:auto;
margin-top:10px;
}
.thumbnail{
height: 100px;
margin: 10px;
float: left;
}
#clear{
display:none;
}
#result {
border: 4px dotted #cccccc;
display: none;
float: left;
margin:0 auto;
}
#result > div {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<article>
<form id="upload" onsubmit="return false">
<label for="files">Select multiple files: </label><br /><br />
<input id="files" name="files[]" type="file" multiple/><br /><br />
<input type="Submit" value="submit" id="submit"></input>
<button type="button" id="clear">Clear</button><br /><br />
</form>
<div id="message"></div>
<output id="result" />
</article>
I tried to figure it out and come to know that the value of var i
changes automatically inside the
addEventListener("load", function (event){
// value of “var i” is not the same here as the value coming from outside this function.
});
I have no idea why value is changing inside the “load” function.
I Googled to see how others are doing same and ended up with this working example on SitePoint http://www.sitepoint.com/html5-file-drag-and-drop/ In this example I see these 2 major differences which I do not understand (my little knowledge in programming).
1. Syntax of for loop he is using in example
for (var i = 0, f; f = files[i]; i++) {
See he is assigning value to var f
instead of applying stop condition.
Now my question is how the loop is working without stop condition is specified?
2. Separate function for reading files
He has made a separate function ParseFile();
to read files.
When I tried to read files without a separate function for file reading it is not working (as shown in my original code). But when I put that code in a separate function showThumbnail()
for reading files and call that function inside loop it is working as it should be (as showing in below snippet). Why is this so?
Anyone here explain these two things to me. Thanks in advance.
I followed the example and rearranged my code which is working as it should be. (Code is in below snippet.)
var output = document.getElementById("result");
$(document).ready(function ()
{
//Check File API support
if (window.File && window.FileList && window.FileReader)
{
$('#files').on("change", function (event)
{
var files = event.target.files; //FileList object
var iCount = files.length;
for (var i = 0, f; f = files[i]; i++)
{
showThumbnail(f);
}
});
}
else
{
console.log("Your browser does not support File API");
}
$("#upload").on('submit',(function()
{
var data = new FormData(this);
var iUploaded = 0;
setTimeout(function()
{
var iCount = document.getElementById('files').files.length;
for (var i = 0; i < iCount ; i++)
{
data.append("Index", i);
$.ajax(
{
url: "upload.php",
type: "POST",
data: data,
contentType: false,
cache: false,
processData:false,
async: false,
success: function(response)
{
var sRes = response.split("|-|");
if(sRes['0'] == 'success')
{
iUploaded = iUploaded + 1;
$("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
}
}
});
}
}, 500);
}));
$("#files").change(function()
{
$("#submit").trigger("click");
});
$('#clear').on("click", function ()
{
$('.thumbnail').parent().remove();
$('#result').hide();
$('#files').val("");
$(this).hide();
});
});
function showThumbnail(file)
{
//Only pics
if (file.type.match('image.*'))
{
var picReader = new FileReader();
picReader.addEventListener("load", function (event)
{
var picFile = event.target;
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + file['name'] + "'/>";
output.insertBefore(div, null);
});
//Read the image
$('#clear, #result').show();
picReader.readAsDataURL(file);
}
else
{
alert("You can only upload image file.");
$(this).val("");
}
}
body{
font-family: 'Segoe UI';
font-size: 12pt;
}
header h1{
font-size:12pt;
color: #fff;
background-color: #1BA1E2;
padding: 20px;
}
article
{
width: 80%;
margin:auto;
margin-top:10px;
}
.thumbnail{
height: 100px;
margin: 10px;
float: left;
}
#clear{
display:none;
}
#result {
border: 4px dotted #cccccc;
display: none;
float: left;
margin:0 auto;
}
#result > div {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<article>
<form id="upload" onsubmit="return false">
<label for="files">Select multiple files: </label><br /><br />
<input id="files" name="files[]" type="file" multiple/><br /><br />
<input type="Submit" value="submit" id="submit"></input>
<button type="button" id="clear">Clear</button><br /><br />
</form>
<div id="message"></div>
<output id="result" />
</article>
Haven't seen the edits to question before posting + misread it
So for your questions :
1 This for loop is waiting for file[i] to be undefined. :
for( var i=0, f; f=files[i]; i++)
.
If files[x]
is undefined, then the loop stops (even if files[x+1] is defined)
2 It is because in your first snippet, your file
variable is in the global scope and gets replaced during the iteration. In the second, however, it is linked to the showThumbnail
function scope, and then passed in the EventListener.
To avoid calling an external function, you will need to call a file
binded function :
From mdn : reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
So for you,
picReader.addEventListener("load", (function(aImg) { return function (event)
{
var picFile = event.target;
console.log(picFile);
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + aImg['name'] + "'/>";
output.insertBefore(div, null);
}; })(file));
Example below :
var output = document.getElementById("result");
$(document).ready(function ()
{
//Check File API support
if (window.File && window.FileList && window.FileReader)
{
$('#files').on("change", function (event)
{
var files = event.target.files; //FileList object
var iCount = files.length;
for (var i = 0, f; i < iCount; i++)
{
var file = files[i];
//Only pics
if (file.type.match('image.*'))
{
var picReader = new FileReader();
picReader.addEventListener("load", (function(aImg) { return function (event)
{
var picFile = event.target;
console.log(picFile);
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + aImg['name'] + "'/>";
output.insertBefore(div, null);
}; })(file));
//Read the image
$('#clear, #result').show();
picReader.readAsDataURL(file);
}
else
{
alert("You can only upload image file.");
$(this).val("");
}
}
});
}
else
{
console.log("Your browser does not support File API");
}
$("#upload").on('submit',(function()
{
var data = new FormData(this);
var iUploaded = 0;
setTimeout(function()
{
var iCount = document.getElementById('files').files.length;
for (var i = 0; i < iCount ; i++)
{
data.append("Index", i);
$.ajax(
{
url: "upload.php",
type: "POST",
data: data,
contentType: false,
cache: false,
processData:false,
async: false,
success: function(response)
{
var sRes = response.split("|-|");
if(sRes['0'] == 'success')
{
iUploaded = iUploaded + 1;
$("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
}
}
});
}
}, 500);
}));
$("#files").change(function()
{
$("#submit").trigger("click");
});
$('#clear').on("click", function ()
{
$('.thumbnail').parent().remove();
$('#result').hide();
$('#files').val("");
$(this).hide();
});
});
body{
font-family: 'Segoe UI';
font-size: 12pt;
}
header h1{
font-size:12pt;
color: #fff;
background-color: #1BA1E2;
padding: 20px;
}
article
{
width: 80%;
margin:auto;
margin-top:10px;
}
.thumbnail{
height: 100px;
margin: 10px;
float: left;
}
#clear{
display:none;
}
#result {
border: 4px dotted #cccccc;
display: none;
float: left;
margin:0 auto;
}
#result > div {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<article>
<form id="upload" onsubmit="return false">
<label for="files">Select multiple files: </label><br /><br />
<input id="files" name="files[]" type="file" multiple/><br /><br />
<input type="Submit" value="submit" id="submit"></input>
<button type="button" id="clear">Clear</button><br /><br />
</form>
<div id="message"></div>
<output id="result" />
</article>