I nearly have the theory down but am getting stuck wit the fine details. An image sizing function, given a var $data
(which is the event object
of a file input after changing) will return a var dataurl
back (which is a dataurl
jpeg
).
My issue was getting dataurl
to recognise it was updated inside a nested function. The code, as I show it below, was logging data:image/jpg;base64
to the console, showing dataurl
was not updated.
Research led me to find that this is due to the asynchronous calls and this makes sense. The var wasn't changed in time before moving on and printing to the console. I've also learned that this is a standard situation to issue a callback
to update the var.
Having made a few attempts at doing so, I can't find a clean (or working) method to update the var using a callback
. I'll expand on this after I show my current code:
function clProcessImages($data) {
var filesToUpload = $data.target.files;
var file = filesToUpload[0];
var canvas = document.createElement('canvas');
var dataurl = 'data:image/jpg;base64';
var img = document.createElement("img");
var reader = new FileReader();
reader.onload = function(e, callback) {
img.onload = function () {
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var MAX_WIDTH = 800;
var MAX_HEIGHT = 600;
var width = img.width;
var height = img.height;
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
dataurl = canvas.toDataURL("image/jpeg",0.8);
callback(dataurl);
}
img.src = e.target.result
}
reader.readAsDataURL(file);
console.log(dataurl); // console log mentioned in question
return dataurl;
};
This is the code as it stands, somewhere in the middle of figuring out how to pull off the callback
. I'm aware that in its shown state the callback isn't called.
My first hurdle was that I (seemingly) couldn't later call the reader.onload
function again, as it appears to be an event specifically to be fired when the object is loaded, not something to call on manually at any time. My best guess was to create a new function that reader.onload
would trigger, would contain all of the the current reader.onload
function and I could specify directly later, to issue the callback
, skipping referring to the onload
event.
Seemed like a sound theory, but then I got stuck with the event object
that the onload
function passes through. Suppose I apply the above theory and the onload
event calls the new function readerOnLoad(e)
. It would pass through the event object
fine. However, when wanting to perform a callback later, how could I manually call readerOnLoad(e)
as I don't see a way to pass on the event object
from the same FileReader
in an elegant way. It feels a little like I'm straying into very messy code* to solve whereas it feels like there should be something a little bit more elegant for a situation that doesn't feel too niche.
*The original $data
event object
variable was obtained by storing a global variable when a file input detected a change. In theory, I could create a global variable to store the event object
for the FileReader
onload. It just feels quite convoluted, in that the difference between my original code and a code that functions this way is quite severe and inelegant when the only difference is updating a var that wasn't ready in time.