Styling a FileUpload by splitting it into a TextBox and a Button (and IE10 troubles)

This is a classic problem: you want to style your <input type="file" /> control but the options are kind of limited. The solution is to hide the control and add your own controls, passing any actions from one to the other.

With jQuery this can be fairly easily achieved by the following script:

$(function () {  
    $('input[type=file]').each(function () {
        var fileUpload = $(this);
        var textBox = $('<input type="text" />');
        textBox
            .css('width', fileUpload.width() - 85)
            .css('margin-right', 5)
            .prop('disabled', fileUpload.prop('disabled'));

        var button = $('<input type="button" value="Browse..." />')
            .prop('disabled', fileUpload.prop('disabled'));

        fileUpload.change(function () {
            textBox.val(fileUpload.val());
        });

        button.click(function () {
            fileUpload.click();
        });

        fileUpload.after(button).after(textBox);
        fileUpload.hide();
    });
});

However, in IE10, now you need to click the submit button twice before it will upload the file to the server. I have no idea why this is, but this question on StackOverflow led me to the solution. Instead of a button, use a label. With the for-attribute, you can tell the browser clicking on the label should activate the upload control.

This is the javascript:

$('input[type=file]').each(function () {  
    var fileUpload = $(this);
    var textBox = $('<input type="text" />');
    textBox
        .css('width', fileUpload.width() - 85)
        .css('margin-right', 5)
        .prop('disabled', fileUpload.prop('disabled'));

    var label = $('<label class="button">Browse...</label>').attr('for', fileUpload.attr('id'));

    fileUpload.change(function () {
        textBox.val(fileUpload.val());
    });

    fileUpload.after(label).after(textBox);
    fileUpload.hide();
});

One last thing you might have to pay attention to is the text of the button. Depending on your locale, it might need to be something different.