This modification is a derived from the original work by Filament Group: http://filamentgroup.com/lab/jquery_custom_file_input_book_designing_with_progressive_enhancement/
A Pen by terryyounghk on CodePen.
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> | |
<title>File Uploader</title> | |
<style> | |
/* Style for demo, not required */ | |
body { font-size: 62.5%; margin: 50px; } | |
fieldset { padding: .6em 0;border:0;border-top: 1px dotted #ddd; } | |
legend { font-size: 1.5em; font-weight: bold; color: #555; padding: .5em 1em .5em 0; background: #fff; } | |
label { font-size: 1.4em; display: block; margin: .5em 10px .5em 0; } | |
input#upload { background: #aaa url(http://dl.dropbox.com/u/20165443/jsFiddle/images/jquery.fileinput.bg-btn.png) bottom repeat-x; padding: .4em 1.2em;border: 1px solid #aaa; color: #222; font-size: 1.2em; font-weight: bold; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; cursor: pointer; margin: 2em 0; } | |
input#upload:hover { background: #eee; color: #111; border-color:#777; } | |
</style> | |
</head> | |
<body> | |
<!-- realistic form attributes: <form action="#" method="post" enctype="multipart/form-data"> --> | |
<form action="#" onsubmit="return false;"> | |
<p>jQuery Custom File Upload Input (Enhancements)</p> | |
<p>This modification is a derived from the original work by Filament Group: http://filamentgroup.com/lab/jquery_custom_file_input_book_designing_with_progressive_enhancement/ </p> | |
<p>File Input Examples</p> | |
<label for="file_A">Default Style</label> | |
<input type="file" name="file" id="file_A"/> | |
<label for="file_B">Percentage Width</label> | |
<input type="file" name="file" id="file_B"/> | |
<label for="file_C">Custom Text</label> | |
<input type="file" name="file" id="file_C"/> | |
<label for="file_D">Test Auto-truncated file name (Try selecting a file with a long name and see what happens)</label> | |
<input type="file" name="file" id="file_D"/> | |
<label for="file_E">Button Only (I actually used this once to mashup with another jQuery plugin which enables multiple file uploads using a single button)</label> | |
<input type="file" name="file" id="file_E"/> | |
<label for="file_F">onChange event handler (This example writes the function arguments to the JavaScript Console, e.g. Firebug)</label> | |
<input type="file" name="file" id="file_F"/> | |
<input type="submit" name="upload" id="upload" value="Upload photo" /> | |
</form> | |
</body> | |
</html> | |
This modification is a derived from the original work by Filament Group: http://filamentgroup.com/lab/jquery_custom_file_input_book_designing_with_progressive_enhancement/
A Pen by terryyounghk on CodePen.
/** | |
* -------------------------------------------------------------------- | |
* jQuery customfileinput plugin | |
* Author: Scott Jehl, scott@filamentgroup.com | |
* Copyright (c) 2009 Filament Group | |
* licensed under MIT (filamentgroup.com/examples/mit-license.txt) | |
* -------------------------------------------------------------------- | |
*/ | |
/** | |
* Modifications: Terry Young (terryyounghk at gmail dot com) | |
* | |
* ##1: Added 'option' parameter. Initially for optionally specifying a width. Default is 'inherit' (i.e. not specified) | |
* ##2: Added options 'buttonText', 'inputText' and 'changeText' | |
* ##3: Added option 'maxFileSize'. For this technique, @see: http://www.tizag.com/htmlT/htmlupload.php | |
* ##4: Added auto-truncating the file name if text exceeds the available width (Uses the window.onresize event) | |
* ##5: Added option 'showInputText'. Default is true | |
* ##6: Added event handler 'onChange' | |
*/ | |
$.fn.customFileInput = function(options){ | |
// ##1 ++ | |
var defaults = { | |
width: 'inherit', | |
buttonText: 'Browse', | |
changeText: 'Change', | |
inputText: 'No file selected', | |
showInputText: true, | |
maxFileSize: 0, // ##3 ++ | |
onChange: $.noop | |
}; | |
// ##1 ++ | |
var opts = $.extend(true, {}, defaults, options); | |
//apply events and styles for file input element | |
var fileInput = $(this) | |
.addClass('customfile-input') //add class for CSS | |
.mouseover(function(){ upload.addClass('customfile-hover'); }) | |
.mouseout(function(){ upload.removeClass('customfile-hover'); }) | |
.focus(function(){ | |
upload.addClass('customfile-focus'); | |
fileInput.data('val', fileInput.val()); | |
}) | |
.blur(function(){ | |
upload.removeClass('customfile-focus'); | |
$(this).trigger('checkChange'); | |
}) | |
.bind('disable',function(){ | |
fileInput.attr('disabled',true); | |
upload.addClass('customfile-disabled'); | |
}) | |
.bind('enable',function(){ | |
fileInput.removeAttr('disabled'); | |
upload.removeClass('customfile-disabled'); | |
}) | |
.bind('checkChange', function(){ | |
if(fileInput.val() && fileInput.val() != fileInput.data('val')){ | |
fileInput.trigger('change'); | |
} | |
}) | |
.bind('change', function() { | |
// ##5 ++ | |
if (opts.showInputText) { | |
//get file name | |
var fileName = $(this).val().split(/\\/).pop(); | |
$(this).data('text', fileName); | |
//get file extension | |
var fileExt = 'customfile-ext-' + fileName.split('.').pop().toLowerCase(); | |
//change text of button | |
// uploadButton.text('Change'); // ##2 -- | |
uploadButton.text(opts.changeText); // ##2 ++ | |
//update the feedback | |
uploadFeedback | |
.text(fileName) //set feedback text to filename | |
.removeClass(uploadFeedback.data('fileExt') || '') //remove any existing file extension class | |
.addClass(fileExt) //add file extension class | |
.data('fileExt', fileExt) //store file extension for class removal on next change | |
.addClass('customfile-feedback-populated'); //add class to show populated state | |
autoTruncateFileName(); | |
} | |
if ($.isFunction(opts.onChange)) { | |
opts.onChange.apply(this, arguments); | |
} | |
}) | |
.click(function(){ //for IE and Opera, make sure change fires after choosing a file, using an async callback | |
fileInput.data('val', fileInput.val()); | |
setTimeout(function(){ | |
fileInput.trigger('checkChange'); | |
},100); | |
}); | |
//create custom control container | |
var upload = $('<div class="customfile"></div>'); | |
// ##1 ++ | |
upload.css({ | |
width: opts.width | |
}); | |
//create custom control button | |
// ##2 | |
var uploadButton = $('<span class="customfile-button" aria-hidden="true"></span>').html(opts.buttonText).appendTo(upload); | |
//create custom control feedback | |
// ##2 | |
var uploadFeedback = $('<span class="customfile-feedback" aria-hidden="true"></span>').html(opts.inputText).appendTo(upload); | |
// ##3 | |
if (opts.maxFileSize > 0 && $('input[type="hidden"][name="MAX_FILE_SIZE"]').length == 0) { | |
$('<input type="hidden" name="MAX_FILE_SIZE">').val(opts.maxFileSize).appendTo(upload); | |
} | |
// ##4 ++ | |
var autoTruncateFileName = function () { | |
//get file name | |
var fileName = fileInput.val() || opts.inputText; | |
if (fileName.length) { | |
var limit = 0, // ensuring we're not going into an infinite loop | |
trimmedFileName = fileName; | |
uploadFeedback | |
.text(fileName) | |
.css({ display: 'inline' }); | |
while (limit < 1024 && trimmedFileName.length > 0 && uploadButton.outerWidth() + uploadFeedback.outerWidth() + 5 >= uploadButton.parent().innerWidth()) { | |
trimmedFileName = trimmedFileName.substr(0, trimmedFileName.length - 1); | |
uploadFeedback.text(trimmedFileName + '...'); | |
limit++; | |
} | |
uploadFeedback.css({ display: 'block' }); // ##4 | |
} | |
}; | |
//match disabled state | |
if(fileInput.is('[disabled]')){ | |
fileInput.trigger('disable'); | |
} | |
uploadFeedback.data('text', opts.inputText); | |
// ##5 ++ | |
if (! opts.showInputText ) { | |
uploadFeedback.hide(); | |
uploadButton | |
.css({ | |
float: 'inherit', | |
display: 'block' // take up the full width of the parent container | |
}) | |
.parent() | |
.css({ | |
padding: 0 | |
}); | |
} else { | |
uploadFeedback.css({ | |
display: 'block' | |
}); | |
$(window).bind('resize', autoTruncateFileName); | |
} | |
//on mousemove, keep file input under the cursor to steal click | |
upload | |
.mousemove(function(e){ | |
fileInput.css({ | |
'left': e.pageX - upload.offset().left - fileInput.outerWidth() + 20, //position right side 20px right of cursor X) | |
'top': e.pageY - upload.offset().top - $(window).scrollTop() - 3 | |
}); | |
}) | |
.insertAfter(fileInput); //insert after the input | |
fileInput.appendTo(upload); | |
//return jQuery | |
return $(this); | |
}; | |
/** | |
* ---------------------------------------------------------- | |
* EXAMPLE | |
*/ | |
$(function(){ | |
// default | |
$('#file_A').customFileInput(); | |
// percentage width | |
$('#file_B').customFileInput({ | |
width: '50%' | |
}); | |
// Custom Text | |
$('#file_C').customFileInput({ | |
width: '30%', | |
buttonText: 'Select File', | |
changeText: 'Change File', | |
inputText: 'Please select a file' | |
}); | |
// Very short field (to test auto-truncated file name) | |
$('#file_D').customFileInput({ | |
width: 150, | |
inputText: '' | |
}); | |
// button only | |
$('#file_E').customFileInput({ | |
width: 90, | |
buttonText: 'Upload File', | |
changeText: 'Change', | |
inputText: '', | |
showInputText: false | |
}); | |
// Event Handlers | |
$('#file_F').customFileInput({ | |
width: 250, | |
onChange: function () { | |
console.info(arguments); | |
} | |
}); | |
}); | |
/** | |
* ##1: Removed fixed with of .customfile | |
* ##2: Added white-space: nowrap for text | |
*/ | |
html, body { | |
background-color:#222222; | |
color:white; | |
} | |
*, p { | |
font-family: Consolas; | |
} | |
/*custom upload elements*/ | |
.customfile-input { | |
position: absolute; | |
height: 100px; | |
cursor: pointer; | |
background: transparent; | |
border: 0; | |
opacity: 0; | |
-moz-opacity: 0; | |
filter: progid:DXImageTransform.Microsoft.Alpha(opacity = 0); | |
z-index: 999; | |
} | |
.customfile { | |
/*width: 400px;*/ /* ##1 -- */ | |
background: #666; | |
cursor: pointer; | |
overflow: hidden; | |
padding: 2px; | |
border: 1px solid #444; | |
-moz-border-radius: 7px; | |
-webkit-border-radius: 7px; | |
border-radius: 7px; | |
position: relative; | |
/* ##2 ++ */ | |
white-space: nowrap; | |
} | |
.customfile-disabled { | |
opacity: .5; | |
filter: progid:DXImageTransform.Microsoft.Alpha(opacity = 0); | |
cursor: default; | |
} | |
.customfile-feedback { | |
/*display: block;*/ | |
margin: 1px 1px 1px 5px; | |
font-size: 1.2em; | |
color: #fff; | |
font-style: italic; | |
padding: .3em .6em; | |
} | |
.customfile-feedback-populated { | |
color: #fff; | |
font-style: normal; | |
font-weight: bold; | |
padding-left: 20px; | |
background: url(http://dl.dropbox.com/u/20165443/jsFiddle/images/jquery.fileinput.icon-generic.gif) left 4px no-repeat; | |
} | |
.customfile-button { | |
border: 1px solid #999; | |
background: #333 url(http://dl.dropbox.com/u/20165443/jsFiddle/images/jquery.fileinput.bg-submit.gif) bottom repeat-x; | |
color: #fff; | |
font-weight: bold; | |
float: right; | |
/*width: 50px;*/ /* ##1 -- */ | |
padding: .3em .6em; | |
text-align: center; | |
text-decoration: none; | |
font-size: 1.2em; | |
-moz-border-radius: 5px; | |
-webkit-border-radius: 5px; | |
border-radius: 5px; | |
} | |
.customfile-hover .customfile-button, .customfile-focus .customfile-button { | |
color: #111; | |
background: #aaa url(http://dl.dropbox.com/u/20165443/jsFiddle/images/jquery.fileinput.bg-btn.png) bottom repeat-x; | |
border-color: #aaa; | |
padding: .3em .6em; | |
} | |
.customfile-focus .customfile-button { | |
outline: 1px dotted #ccc; | |
} | |
/*file type icons*/ | |
.customfile-ext-jpg, .customfile-ext-gif, .customfile-ext-png, .customfile-ext-jpeg, .customfile-ext-bmp { | |
background-image: url(http://dl.dropbox.com/u/20165443/jsFiddle/images/jquery.fileinput.icon-image.gif); | |
} | |
.customfile-ext-mp3, .customfile-ext-mp4, .customfile-ext-mov, .customfile-ext-swf, .customfile-ext-wav, .customfile-ext-m4v { | |
background-image: url(http://dl.dropbox.com/u/20165443/jsFiddle/images/jquery.fileinput.icon-media.gif); | |
} | |
.customfile-ext-zip, .customfile-ext-tar, .customfile-ext-sit { | |
background-image: url(http://dl.dropbox.com/u/20165443/jsFiddle/images/jquery.fileinput.icon-zip.gif); | |
} | |