JavaScript set value to variable defined in parent function - javascript

i want to return imageSize but it is returning undefined. i am confused i have tried many things. in the alert i am getting size.
getImageSize : function(file) {
var reader = new FileReader();
var image = new Image();
var imageSize;
reader.readAsDataURL(file);
reader.onload = function(_file) {
image.src = _file.target.result;
image.onload = function() {
imageSize = ~~(file.size/1024) +'KB';
alert(imageSize);
};
};
return imageSize;
}

Since you are loading the image asynchronously, you cannot return the size directly. The best you can do is pass in a call-back function to be called when the size is available:
getImageSize : function(file, callback) {
var reader = new FileReader();
var image = new Image();
var imageSize;
reader.readAsDataURL(file);
reader.onload = function(_file) {
image.src = _file.target.result;
image.onload = function() {
imageSize = ~~(file.size/1024) +'KB';
callback(imageSize);
};
};
}

Related

How do I wait for FileReader onload to complete first

I am working with FileReader and I have come across an issue with the onLoad method of FileReader not being executed synchronously with the rest of the code. Basically I have 2 functions like these:
imageExists(url, callback) {
var img = new Image();
img.onload = function () { callback(true); };
img.onerror = function () { callback(false); };
img.src = url;
}
isImageCorrupt(file): boolean {
var reader = new FileReader();
var isCorrupt = false;
reader.readAsDataURL(file);
reader.onload = (e) => {
this.imageExists(e.target.result, (exists) => {
if (exists) {
isCorrupt = false;
// Image is not corrupt
} else {
isCorrupt = true;
//Image is corrupt
}
});
};
return isCorrupt;
}
The isImageCorrupt() function calls the reader.onLoad which calls the imageExists callback function, which also contains a image onload method.
The problem is that during the execution of the isImageCorrupt() function, the reader.onLoad has not changed the value of isCorrupt yet but the function has returned the value in the last line which is always false.
I want my function to wait for the reader.onLoad to finish its execution before the function returns the value.
maybe something like this?
isImageCorrupt(file): Promise<Boolean> {
return new Promise((resolve) => {
var reader = new FileReader();
reader.onload = (e) => {
var img = new Image();
img.onload = function () {
resolve(false);
};
img.onerror = function () {
resolve(true);
};
img.src = <string>e.target.result;
}
reader.readAsDataURL(file);
});
}
*disclaimer: I did not test it
You could use Promises. The code could be still refactorized using async/await
isImageCorrupt(file): Promise<boolean> {
return new Promise<boolean>((resolve,reject)=>{
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = ()=>{
var img = new Image();
img.src = reader.result;
img.onload = function () {
resolve(false);
};
img.onerror = function () {
resolve(true);
};
}
reader.onerror=()=>{reject(true)}
});
};
isImageCorrupt(yourFile).then((result)=>{/*HERE USE RESULT*/},(error)=>{HERE USE ERROR RESULT})
However you shouldn't return true o false, but resolve if it's ok and reject otherwise, whithout a boolean value in this way
isImageCorrupt(file): Promise<void> {
return new Promise<void>((resolve,reject)=>{
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = ()=>{
var img = new Image();
img.src = reader.result;
img.onload = function () {
resolve();
};
img.onerror = function () {
reject();
};
}
reader.onerror=()=>{reject()}
});
};
isImageCorrupt(yourFile).then(()=>{/*HERE OK*/},()=> {HERE
THERE WAS SOME ERROR/PROBLEM})

Use p5js script for an NFT?

I have seen people use this method for SVG-based NFTs:
function p5jsToImageURI(){
string memory baseURL = "data:image/svg+xml;base64,PUT-BASE64-HERE"
}
But, since I don't want to generate a fixed image how can I use my p5js script (that looks slightly different each time the js code runs)? Is there a way to just somehow pass the seed to my script and the script with the seed passed to it is stored on-chain?
var img,inpt,div
function convertImgToDataURLviaCanvas(url, callback, outputFormat){
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function(){
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
var dataURL;
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this, 0, 0);
dataURL = canvas.toDataURL(outputFormat);
callback(dataURL);
canvas = null;
};
img.src = url;
}
function convertFileToDataURLviaFileReader(url, callback){
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function() {
var reader = new FileReader();
reader.onloadend = function () {
callback(reader.result);
}
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', url);
xhr.send();
}
function img2b64(imagefile){
var imageUrl = imagefile;
var convertType = 'Canvas';
var convertFunction = convertType === 'FileReader' ? convertFileToDataURLviaFileReader : convertImgToDataURLviaCanvas;
convertFunction(imageUrl, function(base64Img){
code='foto = "'+base64Img+'";'
inpt.value(code)
div.html('<img src="'+base64Img+'">');
});
}
function setup() {
but = createButton("CONVERT");
but.mousePressed(function () {
img2b64('nature100b.jpg');
});
inpt = createP('');
inpt = createElement("textarea",'');
inpt.elt.rows = 5;
inpt.elt.cols = 50;
div = createDiv('');
}
Try this
https://editor.p5js.org/josepssv/full/wsCZnJqkA

Need help to generate three blocks using loop

Following 3 block of code, want to generate using loop/array to make short code.I know use of loop is not a big thing, but for me its difficult to change counter with variable "openFile", I want counter increment with variable "openFile" like openFile1, openFile2 and openFile3 with each iteration of loop.
$(function() {
var openFile1 = function(event) {
var input = event.target;
var reader = new FileReader();
reader.onload = function(){
var dataURL = reader.result;
var output = document.getElementById('img1');
output.src = dataURL;
};
reader.readAsDataURL(input.files[0]);
};
var openFile2 = function(event) {
var input = event.target;
var reader = new FileReader();
reader.onload = function(){
var dataURL = reader.result;
var output = document.getElementById('img2');
output.src = dataURL;
};
reader.readAsDataURL(input.files[0]);
};
var openFile3 = function(event) {
var input = event.target;
var reader = new FileReader();
reader.onload = function(){
var dataURL = reader.result;
var output = document.getElementById('img3');
output.src = dataURL;
};
reader.readAsDataURL(input.files[0]);
};
});
Just create a function that takes count as arg and return a function that takes just event as arg. due to closure, the value of 'count' given when calling openFile with a given value of count will be used for the inner function.
var openFileFunc = function(count) {
return
function(event) {
var input = event.target;
var reader = new FileReader();
reader.onload = function(){
var dataURL = reader.result;
var output = document.getElementById('img'+(count+1));
output.src = dataURL;
};
reader.readAsDataURL(input.files[count]);
};
}
Now you can get the three functions equivalent to what you did by calling a map like this:
var functions = [1,2,3].map(openFileFunc)
Each function in this array is the same as what you had.
var openFile = function(arrOfCount){
var reader;
for(i=0;i<arrOfCount;i++){
reader= new FileReader();
return function(event){
var input = event.target;
reader.onload = function(){
var dataURL = reader.result;
var output = document.getElementById('img'+(i+1));
output.src = dataURL;
};
reader.readAsDataURL(input.files[i]);
}
}
}
May be this will work for you.
function callFunctionNtimes(totalCount){
for(start=1;i<=totalCount;i++)
{
var filevar = 'openFile'+start;
filevar = function(event)
{
var input = event.target;
var reader = new FileReader();
reader.onload = function()
{
var dataURL = reader.result;
var output = document.getElementById('img'+start);
output.src = dataURL;
};
reader.readAsDataURL(input.files[0]);
};
}
}
//to call n time below function
var totalCount = 3;
callFunctionNtimes(totalCount);
I have tried to generalize code
var allImages = document.getElementsByClassName("my-images");
for (var i = 0; i < allImages.length; i++) {
var openFile = function(event) {
var input = event.target;
var reader = new FileReader();
reader.onload = function(){
var dataURL = reader.result;
var output = allImages[i];
output.src = dataURL;
};
reader.readAsDataURL(input.files[0]);
}
But still it seems you have 3 file upload controls and you want to display preview for each, is it so?

How to convert BinaryString to jpg

function upload(file){
var reader = new FileReader();
reader.onload = function (evt) {
uploadComplet(file.name, evt.target.result);
}
reader.readAsBinaryString(file.fileBlob);
}
function downloadComplet(binaryString){
var newFile = new File( [binaryString] , "newName.jpg");
var downloadUrl = URL.createObjectURL(newFile);
var downloadButton = document.createElement('a');
downloadButton.setAttribute('href', downloadUrl);
downloadButton.setAttribute('download', newFile.name);
downloadButton.setAttribute('class', 'button');
downloadButton.innerText = 'Download: ' + newFile.name;
downloadButton.click();
}
I uploaded the BinaryString of the image file and downloaded it as it was. But I could not bring in the correct image. What should I do?
Take this as an example:
var img = document.createElement('img');
img.src = 'data:image/jpeg;base64,' + btoa('your-binary-data');
document.body.appendChild(img);

Javascript variables declared and initialized but give undefined when checked

The following are the variables i have declared in javascript script tag.
The Variables are declared globally and initialized in the inner function which is inside another function (outer).
The problem is; when i try to check the variables using console.log i get "undefined". I don't know why.
I have read the variable hoisting, scope etc of Javascript variables. But i am unable to solve it. Please help.
var width;
var height;
var ratio;
var nwidth;
var nheight;
var wbool;
var imgsrc;
var canvas;
$("#myimage").change(function(){
readURL(this);
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
var image = new Image();
image.src = e.target.result;
image.onload = function(){
if(this.width > this.height){
ratio = this.width/this.height;
nheight = parseInt(Math.ceil(1024/ratio));
wbool = true;
}
else{
ratio = this.height/this.width;
window.nwidth = parseInt(Math.ceil(768*ratio));
wbool = false;
}
}
console.log(window.nwidth + "" + wbool);
You're console.log()'ing nwidth before it has been assigned.
image.onload is an asynchronous operation (think like a callback). the console.log() is firing before the variable data has been assigned.
Try moving the log into the onload function.
var width;
var height;
var ratio;
var nwidth;
var nheight;
var wbool;
var imgsrc;
var canvas;
$("#myimage").change(function(){
readURL(this);
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
var image = new Image();
image.src = e.target.result;
image.onload = function(){
if(this.width > this.height){
ratio = this.width/this.height;
nheight = parseInt(Math.ceil(1024/ratio));
wbool = true;
}
else{
ratio = this.height/this.width;
window.nwidth = parseInt(Math.ceil(768*ratio));
wbool = false;
// it will be defined here, because you are doing
// it inside the async operation.
console.log(window.nwidth);
}
}
// this will be undefined, because the var has not been set
// by the time this line executes.
console.log(window.nwidth + "" + wbool);
why does this happen?
async operations, like ajax calls ( or file loading in your code), take time to complete. Since javascript runs on a single thread, if the app were to stop and wait for the operation to complete, then the browser would lock up. Not good!
So, async operations are skipped over, and the callback portion is executed once the operation completes. This means your code is executing like this:
start loading the file
console.log() // undefined
loading complete, and the variable has been defined.
To trigger a custom event, you could do something like this:
$("#myimage").change(function(){
readURL(this);
});
// SET UP LISTENER FOR YOUR CUSTOM EVENT
$(document).on('fileWasLoaded', function () {
console.log(window.nwidth + "" + wbool);
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
var image = new Image();
image.src = e.target.result;
image.onload = function(){
if(this.width > this.height){
ratio = this.width/this.height;
nheight = parseInt(Math.ceil(1024/ratio));
wbool = true;
}
else{
ratio = this.height/this.width;
window.nwidth = parseInt(Math.ceil(768*ratio));
wbool = false;
// TRIGGER YOUR CUSTOM EVENT WHEN THE IMAGE IS LOADED
$(document).trigger('fileWasLoaded');
}
}

Categories

Resources