I need to check the dimensions of an image by javascript (the image is not attached to the DOM anywhere yet), and do so by a load() event on the image.
The variable IMAGE below contains a valid image url. The variable SELF below contains a reference to THIS of the plugin.
The problem is that from within the load event I don't have access to the variables of my jQuery plugin. And from outside of the load event, I don't have access to the image dimensions checked by that event.
Gives me dimensions but no access to the plugin scope
//Find dimensions of image
var imageTest = new Image(), iWidth, iHeight;
// just in case it is not already loaded
$(imageTest).load(function () {
iWidth = imageTest.width;
iHeight = imageTest.height;
alert(iWidth+' x '+iHeight);
alert(self.data('overlayTypePreview'));
});
imageTest.src = image;
Gives me access to the plugin scope, but not to the image dimensions:
//Find dimensions of image
var imageTest = new Image(), iWidth, iHeight;
// just in case it is not already loaded
$(imageTest).load(function () {
iWidth = imageTest.width;
iHeight = imageTest.height;
});
imageTest.src = image;
alert( self.data('overlayTypePreview') ); // <-- gives me the correct data, string 'mainOverlay'
alert(iWidth+' x '+iHeight); // <-- gives me 'undefined x undefined'
I also tried the ugly hackish solution of going via window, but that didn't work for me either, perhaps because the code supposed to do the alerting triggers before the load event?
//Find dimensions of image
var imageTest = new Image(), iWidth, iHeight;
// just in case it is not already loaded
$(imageTest).load(function () {
window.iWidth = imageTest.width;
window.iHeight = imageTest.height;
});
imageTest.src = image;
alert(window.iWidth+' x '+window.iHeight);
I suppose I could set up a system of 3 functions passing the thread to each other, but from the load event there is no way of calling the instance of my jquery-plugin right? (seeing I don't know what the user will instantiate the plugin as, otherwise I could have hard-coded the instance name, if I wanted an even uglier solution).
I suppose I could set up some sort of timeout-ping:ing of the image from inside the plugin instead of using the load() event but I thought there might be a smarter way that I didn't think of yet...
This is how I ended up solving it. Like I stated in my initial question, a series of 3 functions was necessary to make this clean:
In my plugin, to draw a preview of an image I make this call:
self.data('drawPreview')(self,entityId);
The drawPreview function however is only going to bounce the execution on to the isImageGreaterThanOverlay test
var drawPreview = function(self,entityId){
self.data('isImageGreaterThanOverlay')(self,entityId,'drawPreview2')
}
this.data('drawPreview',drawPreview);
If I had only used the isImageGreaterThanOverlay() function for the drawPreview() function I could have put all of the contents of the isImageGreaterThanOverlay() righ inside the drawPreview above, but since I want to be able to use this tester for other similar functions as well, I keep it separate like this.
As seen below, my tester function declares a new Image, then attaches a load event to that image, then actually loads the image, which triggers the anonymous function inside the load event.
var isImageGreaterThanOverlay = function(self,entityId,destination){
//Find dimensions of image
var imageTest = new Image(), iWidth, iHeight;
$(imageTest).load(function () {
var iWidth = imageTest.width;
var iHeight = imageTest.height;
//find dimensions of overlay
var myOverlay = self.data('overlayTypePreview');
oWidth = parseInt( $(self).find(".VanillaGallery-"+myOverlay).css("width").replace('px', '') );
oHeight = parseInt( $(self).find(".VanillaGallery-"+myOverlay).css("width").replace('px', '') );
if (iWidth > oWidth || iHeight > oHeight) {
var isGreater = true;
}
else {
var isGreater = false;
}
self.data(destination)(self,entityId,isGreater);
});
var entity = self.data('findTheObject')(self,entityId);
var image = entity['path'];
imageTest.src = image;
}
this.data('isImageGreaterThanOverlay',isImageGreaterThanOverlay);
This is important because doing this in any other way would risk the image not being fully loaded in the browser when the code tries to read the dimensions of the image.
Key to making this work in a jQuery plugin is including the reference to the jQuery plugins's THIS like karl-andré-gagnon suggested in his comment. Through that reference, you can access the variables and functions of your plugin scope. It is how I compare the image against the overlay size (stored in my plugin's variable) and also how I pass execution back to a function inside my plugin from the load-event's anonymous function.
Also make sure you don't pass a THIS-reference (in my case SELF) in the load-events anonymous function but do it as I have done, just write it inside the anonymous function.
So when the load-events anonymous function is done checking the sizes, it passes execution on to a function that I call drawPreview2 (since it is the second part of my initial drawPreview function, remember I had to split it up because of the asynchronous load-event)
var drawPreview2 = function(self,entityId,isGreater){
//using the passed in 'isGreater' variable,
//I do the stuff I need to display the image correctly
}
this.data('drawPreview2',drawPreview2);