1

I have a little piece of javascript which is meant to do some validating of a file input field. It works fine in Chrome, Safari, Opera, Firefox, but it doesn't work in Internet Explorer 9 and lower... I'm using Jquery 1.8.3, and apparently since 1.4.2 the .change property should work with IE. I've also tried $(".fileInput").live('change'...

Can't see what's up, any advice welcomed!

jQuery(document).ready(function($){

    // Detect sh*tty IE
    if ($.browser.msie && $.browser.version <= 9) {

    // Bind to property change
    $(".fileInput").bind('propertychange', function() {

        fileChange(this);
    });

    } else {

    $(".fileInput").change(function() {

        fileChange(this);
    });
    }

  function fileChange($item) {

    // Get the filename
    var $fileName = $($item).val();
    var $inputId = $($item).attr('id');
    var $fakeName = $($item).val().split('\\').pop();
    var $fileSize = (($item.files[0].size)/1024)/1024;
    var $ext = $($item).val().split('.').pop().toLowerCase();
    var $acceptFiles = ['jpg', 'jpeg'];

    if ($.inArray($ext, $acceptFiles) == -1) {

        alert('For security, we can only accept jpeg images');

        // Reset the value of $item item
        $($item).val('');

        return;
    }

    // Make sure the file size isn't bigger than 1mb
    if ($fileSize >= 1.8) {

        alert("The image you've chosen is too big. \n\nWe accept images up to 2mb in size");

        // Reset the value of $item item
        $($item).val('');

        return;
    }

    // Check that the file
    if ($fileName != '') {

        $fileNotification = $('<li>', { id: 'file_'+$inputId, class: 'fileNotification', text: $fakeName});

        // Append it to the list
        $('#filesList').append($fileNotification);
    }

    // Hide the file input
    $($item).css({display : 'none'});

    // Show the next field
    $($item).next().show();     

  };
});
ThePHPUnicorn
  • 619
  • 2
  • 7
  • 22

1 Answers1

0

This has nothing to do with IE's change event nor jQuery handlers, but rather old IE's lack of HTML5 APIs.

IE9 and below do not support the File API. Hence:

var $fileSize = (($item.files[0].size)/1024)/1024;

The input element's files property is undefined in old IE and you will get an error as you can't access the property 0 of undefined. That is, you won't be able to easily test file size client-side in old IE using the File API.

And as old IE doesn't support XHR2 either, you can't even send the file through Ajax to check the size server-side. You will need some really ugly workarounds if you want to have that test working in old IE - e.g. auto-submit the form to a hidden iframe to do the file size check server-side, or use flash.

I believe you have server-side validation for that anyway as the JS one can be easily circumvented, so just turning the client-side check into a progressive enhancement would be an easier way around:

if ($item.files) { //browser supports the HTML5 File API, do the client-side check
    var $fileSize = (($item.files[0].size)/1024)/1024;
    if ($fileSize >= 1.8) {
        alert("The image you've chosen is too big. \n\nWe accept images up to 2mb in size");
        $($item).val('');
        return;
    }
}

This means old IE users can still select large files, but as long as you're validating the form data server-side (which is necessary for any real-world web app) you just have to display a meaningful error message then.


ps. You don't need to .split('\\').pop() the input value - even though the file input displays the full path to the user, the browser will never allow JS to know the full path of the file in the disk, only its file name (unless you tamper with security settings, see related).

ps2. You don't need to do userAgent sniffing with $.browser much less bind a propertychange handler, the change event will fire equally for IE's file inputs as it does for other browsers.

Community
  • 1
  • 1
Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166
  • 1
    That worked a treat thanks, excellent stuff. Yep, there's server-side validation too, it initially was being validated at the server only, but we're adding this to make the experience a bit more intuitive for before people hit the 'send' button. THanks again – ThePHPUnicorn Feb 23 '13 at 15:26