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.