Styling an input type=”file” using jQuery

August 21st, 2008 | by David |

During the last days I had to work on some forms that are using file upload inputs. I wondered how to make the file input fields look nicer (they are not affected very much by css) and found this appealing solution. Since the application needs JavaScript anyway, there was nothing wrong with the approach and it worked fine. However, I didn’t like the look of the (working!) JavaScript code and wanted to do it more niftily using jQuery.

This is how the original code looks like:

var W3CDOM = (document.createElement && document.getElementsByTagName);
 
function initFileUploads() {
	if (!W3CDOM) return;
	var fakeFileUpload = document.createElement('div');
	fakeFileUpload.className = 'fakefile';
	fakeFileUpload.appendChild(document.createElement('input'));
	var image = document.createElement('img');
	image.src='pix/button_select.gif';
	fakeFileUpload.appendChild(image);
	var x = document.getElementsByTagName('input');
	for (var i=0;i<x.length;i++) {
		if (x[i].type != 'file') continue;
		if (x[i].parentNode.className != 'fileinputs') continue;
		x[i].className = 'file hidden';
		var clone = fakeFileUpload.cloneNode(true);
		x[i].parentNode.appendChild(clone);
		x[i].relatedElement = clone.getElementsByTagName('input')[0];
		x[i].onchange = x[i].onmouseout = function () {
			this.relatedElement.value = this.value;
		}
	}
}

As I said before it works fine, but it is… well… clumsy. I like the clean and efficient approach of JavaScript using the jQuery library and this is why I went for this replacement:

$('input[type=file]').each(function(){
  $(this).addClass('file').addClass('hidden');
  $(this).parent().append($('<div class="fakefile" />').append($('<input type="text" />').attr('id',$(this).attr('id')+'__fake')).append($('<img src="pix/button_select.gif" alt="" />')));
 
  $(this).bind('change', function() {
    $('#'+$(this).attr('id')+'__fake').val($(this).val());;
  });
  $(this).bind('mouseout', function() {
    $('#'+$(this).attr('id')+'__fake').val($(this).val());;
  });
});

Instead of selecting the newly generated input field by its tag name, I decided to give it the same ID as the original field plus ‘__fake’ appended – if you have any field with the same name, just change the postfix to something else. This makes the addressing in the event handler functions easier.

Of course this code should be executed after the document is fully loaded, this is why it goes into another block:

$(document).ready(function() {
  $('input[type=file]').each(function(){
    $(this).addClass('file').addClass('hidden');
    $(this).parent().append($('<div class="fakefile" />').append($('<input type="text" />').attr('id',$(this).attr('id')+'__fake')).append($('<img src="pix/button_select.gif" alt="" />')));
 
    $(this).bind('change', function() {
      $('#'+$(this).attr('id')+'__fake').val($(this).val());;
    });
    $(this).bind('mouseout', function() {
      $('#'+$(this).attr('id')+'__fake').val($(this).val());;
    });
  });
});

Voilá! I like it more this way, especially because now it’s a lot easier to modify the behaviour of the script, e.g. if you only want to do it for some specific fields or if you want to add something other than an image as the button.
It’s your freedom of choice!

  1. 7 Responses to “Styling an input type=”file” using jQuery”

  2. By Hunts on Jul 31, 2009 | Reply

    How can create multiple “input file” fields in one page using this method.

  3. By David on Aug 1, 2009 | Reply

    This automatically converts all file inputs in the page.

  4. By ViX on Jun 17, 2010 | Reply

    Thanks for the idea and I will try it with my settings.

  5. By Josh on Oct 11, 2010 | Reply

    Why not..

    $(document).ready(function() {
    $(‘input[type=file]‘).each(function(){
    $(this).addClass(‘file’).addClass(‘hidden’);
    $(this).parent().append($(”).append($(”).attr(‘id’,$(this).attr(‘id’)+’__fake’)).append($(”)));

    $(this).bind(‘change mouseout’, function() {
    $(‘#’+$(this).attr(‘id’)+’__fake’).val($(this).val());;
    });

    });
    });

  6. By Phil on Apr 18, 2011 | Reply

    @JOSH:

    Did you try that ? I mean – why are you counteracting a functional usable piece of code with your – “why not?”-stuff.
    Well then I will tell why not:
    First – BECAUSE it DOES NOT work
    Second – Im not gonna debug your “Why not”-stuff to find out WHY NOT

  7. By Phil on Apr 18, 2011 | Reply

    @David – thx a lot ! – exactly what I was looking for -

  8. By Harrison Powers on Jan 3, 2014 | Reply

    Thank goodness for this script. You rock David!

Sorry, comments for this entry are closed at this time.