0

I need to verify the image dimension before accepting upload, see code below.

For some reason, the "check" parameter didn't get set as I wish and the checkImage function always return false.

The form element...

<input type="file" name="bg_image" id="bg_image" accept=".jpg, .png, .gif" />

The jQuery validation method, rules and message...

jQuery.validator.addMethod("check_size",checkImage);

function runFormValidation() {
    var $myForm= $('#reg-form').validate({
        rules: {
            bg_image: {
                check_size: 720
            },
        },
        messages: {
            bg_image: {
                check_size: 'Image Dimension MUST be more than 720px*720px.'
            },
        },
    });
};

The actual checkImage function...

function checkImage(value, element, min_size)
{
   var check = 0;
   if (typeof (element.files) != "undefined") {
        var reader = new FileReader();
        reader.readAsDataURL(element.files[0]);
        reader.onload = function (e) {
            var image = new Image();
            image.src = e.target.result;
            image.onload = function () {
                var height = this.height;
                var width = this.width;
                if (height < min_size || width < min_size) 
                     { check=1; }
                else { check=2; }
            };
        }
    }
    if (check==2) { return true; }  // Doesn't Work - "check" didn't get set as I wish
    return false;
};
Sparky
  • 98,165
  • 25
  • 199
  • 285
humanjoy
  • 1
  • 1
  • so what are you getting instead?? – Umair Shah May 17 '16 at 23:46
  • @UmairShahYousafzai am getting "return false" all the time although my image is larger than 720x720 – humanjoy May 17 '16 at 23:58
  • any live link of your file?? – Umair Shah May 18 '16 at 00:07
  • Do `console.log(height+"X"+width);` and let us know back again..! – Umair Shah May 18 '16 at 00:08
  • it show my image size - 971X1279, the "check" variable get set but it is not the same global variable "check" ... – humanjoy May 18 '16 at 00:15
  • You have the `.validate()` method inside of a function called `runFormValidation()`. You should know that `.validate()` does not "run" validation... it only "sets up" the plugin on your form. Once properly initialized, the click of the submit button is automatically captured by the plugin and triggers validation. – Sparky May 18 '16 at 03:07

2 Answers2

0

The value of 'check' is set after the image loaded, so the if(check == 2) runs before the value is set.

So the rest of code will work after the image loaded, and set check again, with the right values, but the function returned the wrong value already.

You should wait with returning the value till you received the value you want, that is, the return should happen in the image.onload function.

(as i can't comment yet, i keep adding on this answer...)

Not a complete answer, but in comments what should be done somehow

function checkImage(value, element, min_size)
{
   var check = 0,
        returnValue;
   if (typeof (element.files) != "undefined") {
        var reader = new FileReader();
        reader.readAsDataURL(element.files[0]);
        reader.onload = function (e) {
            var image = new Image();
            image.src = e.target.result;
            image.onload = function () {
                var height = this.height;
                var width = this.width;
                if (height < min_size || width < min_size)
                     { returnValue = false; }
                else { returnValue = true; }
            };
        }
        /* as long as returnValue === undefined, do nothing, else
           return returnValue*/
    } else {
        return false;
    }
};

But best would be to run a function that displays the result, after the load function is ready, instead of returning a value, where you have to wait for.

Erik
  • 316
  • 1
  • 6
  • Yes, I did further debug by printing console.log, it's indeed the case. What can I do ? – humanjoy May 18 '16 at 00:21
  • having return in the image.onload function will not be the return for my "checkImage" function. Tried that and it won't work. – humanjoy May 18 '16 at 00:33
  • your suggestion didn't work as returnValue will always be "undefinied" – humanjoy May 19 '16 at 05:00
  • That would mean that it doesn't get in the onload function. If you use something like a while loop that will block everything. (an interval would be better in this case). But I really think the best solution is to write a function yourself that gives a message about the image dimensions, and refer to that function in the onload. So you have no return values and no blocking scripts. – Erik May 19 '16 at 07:38
0

updating my function with console logging...

function checkImage(value, element, param)
{
   var check = 0;
   if (typeof (element.files) != "undefined") {
        var reader = new FileReader();
        reader.readAsDataURL(element.files[0]);
        reader.onload = function (e) {
            var image = new Image();
            image.src = e.target.result;
            image.onload = function () {
                var height = this.height;
                var width = this.width;
                console.log("Print dimension : " + height + " X " + width);
                if (height < 720 || width < 720)
                     { check=1; console.log("inside check = 1"); }
                else { check=2; console.log("inside check = 2"); }
            };
        }
    }
    console.log("outside check value = " + check);
    if (check==2) { return true; }
    return false;
};

When I test with a small dimension image, here is the sequence of console log...

VM1207:149 outside check value = 0
VM1207:142 Print dimension : 498 X 696
VM1207:144 inside check = 1

Just to make it more complete, the following code (having return in image.onload) didn't work either...

function checkImage(value, element, param)
{
   var check = 0;
   if (typeof (element.files) != "undefined") {
        var reader = new FileReader();
        reader.readAsDataURL(element.files[0]);
        reader.onload = function (e) {
            var image = new Image();
            image.src = e.target.result;
            image.onload = function () {
                var height = this.height;
                var width = this.width;
                console.log("Print dimension : " + height + " X " + width);
                if (height < 720 || width < 720)
                     { check=1; console.log("inside check = 1"); return false; }
                else { check=2; console.log("inside check = 2"); return true;  }
            };
        }
    }
    // console.log("outside check value = " + check);
    // if (check==2) { return true; }
    // return false;
};

So how can I make the "check" set before I return for the function???

humanjoy
  • 1
  • 1