How to pass event data and id to javascript function - javascript

Im using javascript to be able to display an image pre file upload but Im having this error...
I have a javascript function
function imageIsLoaded(e) {
$('#image_preview_new').css("display", "block");
var previewDiv = $('#previewing_new');
previewDiv.attr('src', e.target.result);
}
and I am calling the function via another script, but I need to be able to pass both the event data as well as an id into that function but it doesn't seem to work...
This is what I am currently using and it works...
var reader = new FileReader();
reader.onload = imageIsLoaded;
reader.readAsDataURL(this.files[0]);
This is what I've been trying and it doesn't work. If try and pass the id and the event data (e, id) it tells me that "e is not defined"...
var reader = new FileReader();
reader.onload = imageIsLoaded(e, id);
reader.readAsDataURL(this.files[0]);
function imageIsLoaded(e, id) {
$('#image_preview_new').css("display", "block");
var previewDiv = $('#previewing_new');
previewDiv.attr('src', e.target.result);
}
How can I get the event data as well as an id into this function.
Thanks.

Use .change() event, Function.prototype.bind()
function imageIsLoaded(id, e) {
// `id` : `"abc"` , `e` : `event`
console.log(id, e);
// do stuff with `id`
var previewDiv = $("#" + id);
previewDiv.attr("src", e.target.result);
}
$(":file").change(function() {
var reader = new FileReader();
// set `this` to `reader` at first parameter to `.bind()`
// pass `id` : `"abc"` at second parameter `.bind()` ,
// called at `imageIsLoaded`
reader.onload = imageIsLoaded.bind(reader, "abc");
reader.readAsDataURL(this.files[0]);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<input type="file">
<br />
<img id="abc" />

Related

Detect if file upload was from drag or regular input click

I'm currently trying create a drag and drop file uploader with the standard option to just use the regular input. I'm not sure what to be targeting to write if the user clicked the upload or dropped a file in.
My first thought was to check if the FileList is empty but both ways produce a FileList. Second thought was just write two functions one for the input and one for the drop but that seems like I would be repeating. Last thought was writing an if statement in the read_file function. However, I'm not sure what to target exactly.
Any ideas would be greatly appreciated!! thanks!!
https://jsfiddle.net/nick1572/b4xzt8oh/3/
var uploader = document.querySelector('.uploader');
var output = document.getElementById('output');
var file = document.getElementById('file');
file.addEventListener('change', function(event) {
read_file(event);
});
function read_file(event) {
file = event.target;
var reader = new FileReader();
reader.onload = function() {
var data_url = reader.result;
output.src = data_url;
};
// This will read when the image is dropped.
//reader.readAsDataURL(event.dataTransfer.files[0]);
reader.readAsDataURL(file.files[0]);
/*
Something like this
if () {
reader.readAsDataURL(file.files[0]);
} else if() {
reader.readAsDataURL(event.dataTransfer.files[0]);
}
*/
};
uploader.addEventListener('dragover', function(e) {
console.log('drag over');
e.preventDefault();
});
uploader.addEventListener('dragenter', function(e) {
console.log('drag enter');
e.preventDefault();
});
uploader.addEventListener('dragleave', function() {
console.log('drag leave');
});
uploader.addEventListener('drop', function(event) {
console.log('drop');
event.preventDefault();
read_file(event);
});
Check the type property of the event object to see which event has been used.
function read_file(event) {
file = event.target;
var reader = new FileReader();
reader.onload = function() {
var data_url = reader.result;
output.src = data_url;
};
if (event.type === 'change') {
reader.readAsDataURL(file.files[0]);
} else if(event.type === 'drop') {
reader.readAsDataURL(event.dataTransfer.files[0]);
}
};

knockout change event function

Trying to upload multiple csv files using a knockout change event. Initially the change function works and the values get written to the viewmodel. The problem is when trying to upload a second csv file the knockout change event doesn't fire. Is there a way to get the change function to re-fire after the first time?
<input id="uploadFile" type="file" multiple="multiple" data-bind="event: { change: PO.fileUploadChange }"/>
export function fileUploadChange(data, evt): void {
ko.utils.arrayForEach(evt.target.files, function (file) {
var reader = new FileReader();
reader.onload = LoadCSVData;
reader.readAsText(evt.target.files.item(0))
model.quickEntryModel.files.push(evt.target.files.item(0));
var input = document.getElementById('uploadFile');
if (input != null)
document.getElementById('uploadFile').outerHTML = input.outerHTML;
})
}
The issue is with the last line. I'm not sure what you're trying to do there, but I'm assuming you're clearing the input. You should move it outside the arrayForEach loop:
export function fileUploadChange(data, evt): void {
ko.utils.arrayForEach(evt.target.files, function (file) {
var reader = new FileReader();
reader.onload = LoadCSVData;
reader.readAsText(evt.target.files.item(0))
model.quickEntryModel.files.push(evt.target.files.item(0));
});
var input = document.getElementById('uploadFile');
if (input != null)
input.value = "";
}
Here's a fiddle

FileReader - Preparing for new file, even the same one

I have several load file html elements, eg:
<input type="file" id="loadFiles0" class="filesclass" name="file" />
<input type="file" id="loadFiles1" class="filesclass" name="file" />
I have added an event listener to them to catch changes:
// Elsewhere
function myFunction(event){
// Stuff
}
var el;
el = document.getElementById("loadFiles0");
el.addEventListener('change', myFunction, false);
As many will know, to get the load working the second time, EVEN WHEN IT IS THE SAME FILE NAME, you must set the html element's 'value' to "". This is the problem. I need to know which one of the load file elements did the call. Was it 'loadFiles0' or 'loadFiles1' etc.
myFunction looks like this - just the important bits:
function myFunction(evt){
...
// We need to remove it so this is not handled again when we set value = ""
this.removeEventListener('change', myFunction, false);
...
var reader = new FileReader();
reader.onload = function (e) {
...
// HERE IS THE PROBLEM
// I need a reference to the dom element that this is working on - call it 'ptr'
// I cannot use 'this' in this function, because that refers to 'reader'
// I need it so I can set its value to "", so even if the person reloads the same file, it will trigger a change
// But I cannot be certain if it was 'loadFiles0' or 'loadFiles1' etc
ptr.value = "";
ptr.addEventListener('change', myFunction, false);
};
}
So the question is, how can I get ptr in the reader's onload function?
I need to know which one of the load file elements did the call. Was it 'loadFiles0' or 'loadFiles1' etc.
It will be this within the event callback to myFunction, which you can then either remember in a variable (ptr, perhaps), or if you want to use ES2015 (with transpiling if necessary) you can use an arrow function.
With ptr:
function myFunction(evt){
// ...
this.removeEventListener('change', myFunction, false);
var ptr = this; // *******
// ...
var reader = new FileReader();
reader.onload = function (e) {
ptr.value = "";
ptr.addEventListener('change', myFunction, false);
};
}
Or with an ES2015+ arrow function:
function myFunction(evt){
// ...
this.removeEventListener('change', myFunction, false);
// ...
var reader = new FileReader();
reader.onload = e => { // ***
this.value = ""; // ***
this.addEventListener('change', myFunction, false); // ***
};
}
Example using setTimeout to emulate the reader.onload callback:
function myFunction(e) {
var ptr = this;
// This emulates the reader.onload callback:
setTimeout(function() {
console.log("reader.onload for " + ptr.id);
}, 10);
}
Array.prototype.forEach.call(
document.querySelectorAll("input[type=file]"),
function(input) {
input.addEventListener("change", myFunction, false);
}
);
<input type="file" id="loadFiles0">
<input type="file" id="loadFiles1">
<input type="file" id="loadFiles2">
Example with an arrow function:
// ES2015 or higher (you can transpile if necessary)
function myFunction(e) {
// This emulates the reader.onload callback:
setTimeout(() => {
console.log("reader.onload for " + this.id);
}, 10);
}
Array.prototype.forEach.call(
document.querySelectorAll("input[type=file]"),
function(input) {
input.addEventListener("change", myFunction, false);
}
);
<input type="file" id="loadFiles0">
<input type="file" id="loadFiles1">
<input type="file" id="loadFiles2">

How Display Image on page After $on("fileSelected") in angular js

How can I display an image after $on("fileSelected") in AngularJS?
I'm selecting a file using the following:
$scope.$on("fileSelected", function (event, args) {
debugger;
$scope.$apply(function () {
$scope.file = args.file;
});
I need to display the image with the img src attribute.
Try something like this:
var reader = new FileReader();
reader.onload = function (e) {
$('#image').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);

Simplifiying/modularizing my code in javascript

I know that I should follow the DRY principle in coding. However, I am not that into javascript so I want to ask how to make the code below more readable and maintanable.
$('#frontfile_v').change(function(){
reader = Main.Mod.image_change(this);
reader.onload = frontvImageIsLoaded;
});
$('#rearfile_v').change(function(){
reader = Main.Mod.image_change(this);
reader.onload = rearvImageIsLoaded;
});
$('#rightfile_v').change(function(){
reader = Main.Mod.image_change(this);
reader.onload = rightvImageIsLoaded;
});
$('#leftfile_v').change(function(){
reader = Main.Mod.image_change(this);
reader.onload = leftvImageIsLoaded;
});
//called after an image file has been chosen
function frontvImageIsLoaded(e) {
$("#frontimagepreview").attr('src', e.target.result);
$("#frontpreview-msg").css('color', 'green');
};
function rearvImageIsLoaded(e) {
$("#rearimagepreview").attr('src', e.target.result);
$("#rearpreview-msg").css('color', 'green');
};
function rightvImageIsLoaded(e) {
$("#rightimagepreview").attr('src', e.target.result);
$("#rightpreview-msg").css('color', 'green');
};
function leftvImageIsLoaded(e) {
$("#leftimagepreview").attr('src', e.target.result);
$("#leftpreview-msg").css('color', 'green');
};
This is the code for Main.Mod.image_change()
var image_change = function handleFileImageChange(obj){
//holds the image preview object
var file = obj.files[0];
var imagefile = file.type;
var match= ["image/jpeg","image/png","image/jpg"];
if(!((imagefile==match[0]) || (imagefile==match[1]) || (imagefile==match[2]))){
alert("Incorrect image file. You still be able to upload this form but the system " +
"will be using the default image.");
$("#preview-msg").css('color', 'red');
return false;
}else{
var reader = new FileReader();
//reader.onload = imageIsLoaded;
reader.readAsDataURL(obj.files[0]);
return reader;
}
};
The code above, will handle file input change event then change img src base on the file input.
I know the code i wrote really sucks since I have to repeat my code several times. How can I implement it in a more efficient way?
Thanks.
use , to combine selectors:
$('#frontfile_v,#rearfile_v').change(function(){
// ...
})
The "change" event will be bound to every object matched by the selector. This way you don't need to duplicate the binding.
Merge the "image loaded" functions into one function by passing parameters:
var idsMap = {
leftfile_v : {preview : '#frontimagepreview', msg : '#frontpreview-msg'},
// etc...
};
$('#leftfile_v,#rearfile_v').change(function(){
var ids = idsMap[$(this).attr('id')];
reader = Main.Mod.image_change(this);
reader.onload = function(e) {
imageIsLoaded(e, ids.preview, ids.msg);
};
});
function imageIsLoaded(e, preview, msg) {
$(preview).attr('src', e.target.result);
$(msg).css('color', 'green');
};
Yet another variant. As say #Malki: use comma in selector
$('#frontfile_v, #rearfile_v,#rightfile_v,#leftfile_v').change(function(){
var id = this.id.replace(/file_v$/,'');
reader = Main.Mod.image_change(this);
if(reader){ //for case when `image_change` return not "false"
// use mode generic function
reader.onload = function(e){
$("#"+id+"imagepreview").attr('src', e.target.result);
$("#"+id+"preview-msg").css('color', 'green');
};
}
});
As for handleFileImageChange you need use Array.indexOf function
var image_change = function handleFileImageChange(obj){
//holds the image preview object
var file = obj.files[0];
var imagefile = file.type;
var match= ["image/jpeg","image/png","image/jpg"];
if(match.indexOf(imagefile) == -1){
alert("Incorrect image file. You still be able to upload this form but the system will be using the default image.");
$("#preview-msg").css('color', 'red');
return false;
}else{
var reader = new FileReader();
//reader.onload = imageIsLoaded;
reader.readAsDataURL(file); //you not need use "obj.files[0]" because you already save it in "var file"
return reader;
}
};

Categories