Reputation: 659
I'm trying to load images in to page for preview before uploading with javascript.
I have following code:
holder.onclick = function(event) {
function chooseFile(name) {
var chooser = $(name);
chooser.unbind('change');
chooser.change(function(evt) {
function loadFile(file, callback) {
var reader = new FileReader();
(reader.onload = function(file) {
console.log(f);
var output = document.createElement('input');
output.type = 'image';
output.classList.add('image-responsive');
output.classList.add('col-xs-12');
output.name = f;
output.id = f;
output.src = reader.result;
var x = document.getElementById('OrigName');
x.appendChild(output);
return callback(output);
})(f = file.name);
reader.readAsDataURL(file);
}
for (var i = 0; i < evt.target.files.length; i++) {
console.log(i);
var file = evt.target.files[i];
loadFile(file, function(output) {
// console.log(output);
});
}
});
chooser.trigger('click');
}
chooseFile('#fileDialog');
}
Problem is, whenever i load image, code inside reader.onload method execute twice, and in console i 2x result of console.log(f) and 2 errors that 'localhost/null is not found'.
When i remove (f=file.name), script execute as it should be, but then i don't have file.name variable inside reader scope.
EDIT:
Here's JSFiddle of my problem:
https://jsfiddle.net/onedevteam/udmz34z0/6/
Can someone help me fix this?
Upvotes: 1
Views: 3034
Reputation: 556
The way you have your code structured, your onload handler will be executed twice, once when you define it, and then again when the "load" event fires. When you wrap a function definition inside parens:
(reader.onload = function (file) { ... })(f = filename)
you're saying "define this function and execute it immediately."
What you really want is a function that returns a function, like this:
function makeOnLoadHandler (filename) {
return function (file) {
// ... do whatever you need to with file and filename
};
}
reader.onload = makeOnLoadHandler(someFileName);
The outer function, makeOnLoadHandler()
, creates a closure around your filename
variable, and when the inner function handles the reader's load
event, it will see the filename
that you passed in when you called makeOnLoadHandler.
Upvotes: 1
Reputation: 18997
Problem is, whenever i load image, code inside reader.onload method execute twice
This is because in your code you have this.
(reader.onload = function(file) {
//...
//...
})(f = file.name); // <---- self executing function.
reader.readAsDataURL(file);
Here you are using "Self Executing function" for the reader.onload
, So what happens is it will execute once when it hits this line of code, And again when reader.readAsDataURL(file)
has completed reading. So remove the "self executing function " and you logic will run only once
When i remove (f=file.name), script execute as it should be, but then i don't have file.name variable inside reader scope.
to get the file name just add it in a variable and use it like this.
var fileName = file.name;
reader.onload = function() {
//...
//...
output.name = fileName ;
output.id = fileName ;
}; // <-- self executing function REMOVED
Also I feel there is no need to save the file name into a variable because the variable file
passed into function is sufficient to get the job done. So below would be the final code as per my suggestion.
function loadFile(file, callback) {
var reader = new FileReader();
reader.onload = function() {
console.log(file.name); //
var output = document.createElement('input');
output.type = 'image';
output.classList.add('image-responsive');
output.classList.add('col-xs-12');
output.name = file.name; //
output.id = file.name; //
output.src = reader.result;
var x = document.getElementById('OrigName');
x.appendChild(output);
return callback(output);
};
reader.readAsDataURL(file);
}
Upvotes: 2
Reputation: 804
You're calling reader.onload
at least twice. You have this function inside another function loadFile()
, and you call it immediately (which is why you only see this behavior when you have (f=file.name)
there), but then also inside the chooser.change
function you have that for-loop that calls loadFile()
. Perhaps ou could set the file.name
variable somewhere other than (f=file.name)
and then make reader.onload
not execute automatically.
Upvotes: 1