Search code examples
jqueryvalidationfile-type

Validating filetype and display image preview using jQuery


I have two scripts that work fine on their own, one validates that the file selected is a jpeg and then outputs a alert, which is given below:

(function($) {
    $.fn.checkFileType = function(options) {
    var defaults = {
        allowedExtensions: [],
        success: function() {},
        error: function() {}
    };
    options = $.extend(defaults, options);

    return this.each(function() {

        $(this).on('change', function() {
            var value = $(this).val(),
                file = value.toLowerCase(),
                extension = file.substring(file.lastIndexOf('.') + 1);

            if ($.inArray(extension, options.allowedExtensions) == -1) {
                options.error();
                $(this).focus();
            } else {
                options.success();

            }

        });

    });
};

})(jQuery);

$(function() {
$('#image').checkFileType({
    allowedExtensions: ['jpg', 'jpeg'],
    success: function() {
        alert('success')
    },
    error: function() {
        alert('Error');

    }
});

});

The other one displays a preview of a selected image inside an <img> element

function readURL(input) {
        if (input.files && input.files[0]) {  

            var reader = new FileReader();

            reader.onload = function (e) {

                $('#productImg').show();

                $('#productImg')
                    .attr('src', e.target.result)

            };

            reader.readAsDataURL(input.files[0]);
        }
    } 

I'm calling the above function as follows:

<input type="file" name="image" class="browse" id="image" onchange="readURL(this);" />

What I want to do is combine the two scripts so that if the image is not a jpeg it alerts the error like in the first script and then if the image is a jpeg it displays the preview like the second script.


Solution

  • As i mentioned in comments, you can simply specify the second function as the success callback of first function, and show the alert in second function, or call the second function after the alert (Since you're hardcoding the preview element in second function, it looks like that's enough for the current requirement.)

    If you really want to generalize it, you can try something like below

    $.fn.checkFileType = function (options) {
    var defaults = {
        allowedExtensions: [],
        preview: "",
        success: function () {},
        error: function () {}
    };
    options = $.extend(defaults, options);
    $previews = $(options.preview);
    return this.each(function (i) {
    
        $(this).on('change', function () {
            var value = $(this).val(),
                file = value.toLowerCase(),
                extension = file.substring(file.lastIndexOf('.') + 1),
                $preview = $previews.eq(i);
    
            if ($.inArray(extension, options.allowedExtensions) == -1) {
                options.error();
                $(this).focus();
            } else {
                if (this.files && this.files[0] && $preview) {
                    var reader = new FileReader();
                    reader.onload = function (e) {
                        $preview.show().attr('src', e.target.result);
                        options.success();
                    };
    
                    reader.readAsDataURL(this.files[0]);
                } else {
                    options.error();
                }
    
            }
    
        });
    
      });
    };
    

    You can use it as follows:

    $('#image').checkFileType({
      allowedExtensions: ['jpg', 'jpeg',"gif"],
      preview: ".preview",
      success: function () {
        alert('success')
      },
      error: function () {
        alert('Error');
      }
    });
    

    The image will be set as the src of element at the index of your <input> among the set of elements matched by the jQuery selector specified in preview option.

    Demo