<section>
|
<h1 class="blue" data-id="#custom/file-input"><i class="ace-icon fa fa-desktop grey"></i> File Input</h1>
|
|
<div class="hr hr-double hr32"></div>
|
|
<!-- #section:custom/file-input -->
|
<div class="help-content">
|
<h3 class="info-title smaller">1. Custom File Input</h3>
|
<div class="info-section">
|
<ul class="info-list list-unstyled">
|
<li>
|
A simple file input control which styles browsers default input and adds some extra features
|
</li>
|
<li>
|
If you want advanced functionality, you should consider using <a href="#plugins/misc.dropzone" class="help-more">dropzone.js</a> or other library.
|
</li>
|
|
<li>
|
Basic usage is:
|
<pre data-language="html">
|
<input type="file" name="myfile" id="my-file-input" />
|
</pre>
|
<pre data-language="javascript">
|
$('#my-file-input').ace_file_input();
|
</pre>
|
</li>
|
</ul>
|
</div>
|
|
<h3 class="info-title smaller">2. Options</h3>
|
<div class="info-section">
|
<ul class="info-list list-unstyled">
|
<li>
|
You can use one of the following options:
|
<ol>
|
<li><code>style</code> default=false. If you set it to <b>well</b>, the large style will be displayed</li>
|
<li><code>no_file</code> the text to show when no file is selected</li>
|
<li><code>no_icon</code> the icon to show when no file is selected</li>
|
<li><code>btn_choose</code> button text when no file is selected</li>
|
<li><code>btn_change</code> button text when a file is selected</li>
|
<li><code>icon_remove</code> icon to use for remove(reset) button</li>
|
<li><code>droppable</code> default=false. set <b>true</b> to enable drag & drop</li>
|
<li><code>thumbnail</code> <b>small</b>, <b>large</b> or <b>fit</b>. Used when <b>style</b> options is <b>well</b></li>
|
<li class="space-6"></li>
|
<li><code>allowExt</code> a list of allowed extensions (whitelist)</li>
|
<li><code>denyExt</code> a list of denied extensions (blacklist)</li>
|
<li><code>allowMime</code> a list of allowed mime types (whitelist)</li>
|
<li><code>denyMime</code> a list of denied mime types (blacklist)</li>
|
<li><code>maxSize</code> maximum file size allowed in bytes</li>
|
</ol>
|
The above allow/deny options, trigger <code>file.error.ace</code> event when an invalid file is selected.
|
<br />
|
Please refer to "File Filtering" section for more info.
|
<Br />
|
|
<pre data-language="javascript">
|
$('#my-file-input').ace_file_input({
|
style: 'well',
|
no_file: 'Click to choose or drag & drop',
|
droppable: true, //html5 browsers only
|
thumbnail: 'small', //html5 browsers only
|
|
maxSize: 100000, //~100 KB
|
allowExt: ['jpg', 'jpeg', 'png', 'gif', 'tif', 'tiff', 'bmp'],
|
allowMime: ['image/jpg', 'image/jpeg', 'image/png', 'image/gif', 'image/tif', 'image/tiff', 'image/bmp'] //html5 browsers only
|
});
|
|
$('#my-file-input2').ace_file_input({
|
denyExt: ['exe', 'php']
|
});
|
</pre>
|
</li>
|
</ul>
|
</div>
|
|
<h3 class="info-title smaller">3. Callbacks</h3>
|
<div class="info-section">
|
<ul class="info-list list-unstyled">
|
<li>
|
There are 3 callback option
|
</li>
|
|
<li>
|
<code>before_change</code> callback is called when user selects/drops files
|
and before files are displayed.
|
<br />
|
Inside it you can return:
|
<ol>
|
<li>a modified file list</li>
|
<li><code>true</code> and all files will be kept</li>
|
<li><code>false</code> and no files will be kept</li>
|
<li><code>-1</code> and no files will be kept and input will be reset</li>
|
</ol>
|
<br />
|
Also it accepts following arguments:
|
<ol>
|
<li>
|
<code>files</code> a list of selected/dropped files which is a FileList in modern browsers
|
and a string (filename) array for older browsers
|
</li>
|
<li><code>dropped</code> whether files have been dropped or selected</li>
|
</ol>
|
<br />
|
<pre data-language="javascript">
|
$('#my-file-input').ace_file_input({
|
...
|
,
|
before_change: function(files, dropped) {
|
//files is a "File" object array in modern browsers
|
//files is a "string" (file name) array in older browsers
|
|
//dropped=true if files are drag & dropped
|
|
var valid_files = []
|
|
for(var i = 0; i < files.length; i++) {
|
var file = files[i];
|
|
if( typeof file === 'string') {
|
/older browsers that don't support FileReader API, such as IE
|
//here, file is just a filename string
|
//if (file is valid) valid_files.push(file);
|
} else if( 'File' in window && file instanceof window.File ) {
|
//file is a "File" object with following properties
|
//file.name
|
//file.type (mime type)
|
//file.size
|
//if (file is valid) valid_files.push(file);
|
}
|
}
|
|
|
return valid_files;
|
|
//or
|
return true;//original input files
|
|
//or
|
return false;//all are invalid, but don't reset input
|
|
//or
|
return -1;//all are invalid, reset input
|
}
|
</pre>
|
</li>
|
|
<li>
|
<b>before_remove</b> can be used to disable resetting file input, for example during a file upload session:
|
<pre data-language="javascript">
|
$('#my-file-input').ace_file_input({
|
...
|
,
|
before_remove : function() {
|
if( uploadInProgress) return false;//don't allow resetting
|
return true;
|
}
|
});
|
</pre>
|
</li>
|
|
<li>
|
If <b>preview_error</b> is defined, it will be called in case there's an error when building preview of image files:
|
<pre data-language="javascript">
|
$('#my-file-input').ace_file_input({
|
...,
|
preview_error : function(filename, error_code) {
|
//filename = name of the file that had a problem
|
switch(error_code) {
|
case 1:
|
//FILE_LOAD_FAILED
|
break;
|
|
case 2:
|
//IMAGE_LOAD_FAILED
|
break;
|
|
case 3:
|
//THUMBNAIL_FAILED
|
break;
|
}
|
}
|
});
|
</pre>
|
</li>
|
|
</ul>
|
</div>
|
|
|
|
<h3 class="info-title smaller" data-id="#custom/file-input.filter">4. File Filtering</h3>
|
<!-- #section:custom/file-input.filter -->
|
<div class="info-section">
|
<ul class="info-list list-unstyled">
|
<li>
|
As mentioned in previous sections, you can use the following options and callbacks to filter
|
the list of selected files:
|
<ol>
|
<li><code>allowExt</code></li>
|
<li><code>denyExt</code></li>
|
<li><code>allowMime</code></li>
|
<li><code>denyMime</code></li>
|
<li><code>maxSize</code></li>
|
<li><code>before_change</code></li>
|
</ol>
|
</li>
|
|
<li>
|
Please note that when you select a file using file dialog,
|
browser's file input element cannot be modified. It can only be reset (emptied).
|
<br />
|
For example if you specify <code>allowExt</code> option
|
to select only image files, but user selects none-image files as well,
|
the browser keeps all selected files but Ace file input shows image files only.
|
</li>
|
|
<li>
|
When user selects an invalid file <code>file.error.ace</code> event is triggered which
|
has some info about the error.
|
</li>
|
|
<li>
|
If you call <code>preventDefault</code> on event object, the file control will be reset and becomes empty.
|
<br />
|
Otherwise, file control won't be reset and browser keeps all selected files.
|
<br />
|
However, Ace file input displays valid files and the
|
<code>$('#my-file-input').data('ace_input_files')</code> returns valid files only.
|
</li>
|
|
<li>
|
<pre data-language="html">
|
$('#my-file-input').ace_file_input({
|
'allowExt': ['jpg', 'jpeg', 'png']
|
})
|
.on('file.error.ace', function(event, info) {
|
//info.file_count > number of files selected
|
//info.invalid_count > number of invalid files
|
|
//info.error_count['ext'] > number of files with invalid extension (only if allowExt or denyExt is set)
|
//info.error_count['mime'] > number of files with invalid mime type (only if allowMime or denyMime is set)
|
//info.error_count['size'] > number of files with invalid size (only if maxSize option is set)
|
|
//info.error_list['ext'] > list of file names with invalid extension
|
//info.error_list['mime'] > ...
|
//info.error_list['size'] > ...
|
|
//info.dropped > true if files have been selected by drag & drop
|
|
|
//if you do this
|
event.preventDefault();
|
//it will reset (empty) file input, i.e. no files selected
|
});
|
</pre>
|
</li>
|
|
<li>
|
There is also <code>before_change</code> callback.
|
Please see previous section for more info.
|
</li>
|
|
</ul>
|
</div>
|
<!-- /section:custom/file-input.filter -->
|
|
|
|
<h3 class="info-title smaller">5. Functions</h3>
|
<div class="info-section">
|
<ul class="info-list list-unstyled">
|
<li>
|
The following functions are available for file input control.
|
</li>
|
<li>
|
<code>show_file_list</code> takes a list of file names and shows them inside the control:
|
<pre data-language="javascript">
|
$('#my-input').ace_file_input('show_file_list', ['file1.txt']);
|
</pre>
|
For example, you may want to edit a file input
|
which has user's previous selection.
|
|
<div class="alert alert-info">
|
From version 1.3.2 you can also preview images inside file input control.
|
</div>
|
<pre data-language="javascript">
|
$('#my-input')
|
.ace_file_input('show_file_list', [
|
{type: 'image', name: 'name of image', path: 'http://path/to/image/for/preview'},
|
{type: 'file', name: 'hello.txt'}
|
]);
|
//type can be 'image', 'video', 'audio', 'file'
|
</pre>
|
|
</li>
|
<li>
|
<code>update_settings</code> to update options:
|
<pre data-language="javascript">
|
$('#my-input').ace_file_input('update_settings', {
|
allowExt: ['pdf', 'doc', 'docx']
|
});
|
</pre>
|
</li>
|
<li>
|
<code>files</code> returns list of selected files:
|
<pre data-language="javascript">
|
var files = $('#my-input').ace_file_input('files');
|
//is similar to:
|
var files = $('#my-input').data('ace_input_files');
|
</pre>
|
</li>
|
<li>
|
<code>method</code> returns method used by user which is 'select' or 'drop':
|
<pre data-language="javascript">
|
var method = $('#my-input').ace_file_input('method');
|
//is similar to:
|
var method = $('#my-input').data('ace_input_method');
|
</pre>
|
</li>
|
<li>
|
<code>disable</code> disables file input:
|
<pre data-language="javascript">
|
$('#my-input').ace_file_input('disable');
|
</pre>
|
</li>
|
<li>
|
<code>enable</code> enables file input:
|
<pre data-language="javascript">
|
$('#my-input').ace_file_input('enable');
|
</pre>
|
</li>
|
|
<li>
|
<code>enable_reset</code> takes an argument and enables/disables reset button:
|
<pre data-language="javascript">
|
$('#my-input').ace_file_input('enable_reset', false);
|
$('#my-input').ace_file_input('enable_reset', true);
|
</pre>
|
</li>
|
|
<li>
|
<code>reset_input</code> resets file input:
|
<pre data-language="javascript">
|
$('#my-input').ace_file_input('reset_input');
|
</pre>
|
</li>
|
<li>
|
<code>reset_input_ui</code> resets file input's UI only:
|
<pre data-language="javascript">
|
$('#my-input').ace_file_input('reset_input_ui');
|
</pre>
|
Suppose you have a form with a reset button.
|
<br />
|
When you hit "reset", file input field will be reset, but Ace file input's UI won't be reset.
|
<br />
|
You should do this on your own:
|
<pre data-language="javascript">
|
$('#my-form').on('reset', function(e) {
|
$('#my-input').ace_file_input('reset_input_ui');
|
});
|
</pre>
|
</li>
|
<li>
|
<code>reset_input_field</code> resets file input field
|
</li>
|
|
|
<li>
|
<code>loading</code> adds/updates/removes a loading/waiting overlay for example during a file upload:
|
<pre data-language="javascript">
|
$('#my-input').ace_file_input('loading' , true);//adds overlay
|
$('#my-input').ace_file_input('loading' , false);//removes overlay
|
$('#my-input').ace_file_input('loading' , ' custom content inside overlay such as a progressbar ');
|
</pre>
|
</li>
|
</ul>
|
</div>
|
|
|
<h3 class="info-title smaller">6. Events</h3>
|
<div class="info-section">
|
<ul class="info-list list-unstyled">
|
<li>
|
If you use file filter options and user selects or drops an invalid file, a
|
<code>file.error.ace</code> event is triggered with some info about invalid files.
|
<br />
|
You can find more info about it in the <b>File Filtering</b> section.
|
</li>
|
|
<li>
|
<code>file.preview.ace</code> event is triggered with extra info about image files and you can call <code>e.preventDefault()</code> to prevent
|
displaying image preview.
|
<br />
|
<pre data-language="javascript">
|
$('#my-file-input').on('file.preview.ace', function(e, info) {
|
//info.file is the File object
|
if(info.file.width > 1000) {
|
e.preventDefault();//don't show image preview
|
alert("Invalid image width!");
|
}
|
}
|
</pre>
|
</li>
|
|
<li>
|
You can also add a <b>change</b> event listener to the file input and it will be triggered
|
when files are selected or dropped:
|
<pre data-language="javascript">
|
$('#my-file-input').ace_file_input({
|
droppable: true
|
})
|
.on('change', function() {
|
var files = $(this).data('ace_input_files');
|
var method = $(this).data('ace_input_method');
|
});
|
</pre>
|
</li>
|
</ul>
|
</div>
|
|
|
<h3 class="info-title smaller">7. Uploading</h3>
|
<div class="info-section">
|
<ul class="info-list list-unstyled">
|
<li>
|
If you don't use <b>drag & drop</b> functionality, file upload is done as normal,
|
by submitting the form and browser takes care of it.
|
</li>
|
|
<li>
|
However when you enable <b>drag & drop</b> feature and user drops some files onto the control,
|
file field is not modified and by submitting form, no files are uploaded.
|
</li>
|
|
<li>
|
In this case, you should use modern HTML5 features and upload your files using Ajax
|
and <b>FormData</b> object.
|
<br />
|
<a href="https://developer.mozilla.org/en-US/docs/Web/Guide/Using_FormData_Objects">FormData</a>
|
</li>
|
|
<li>
|
The list of files which should be uploaded is retrieved like this:
|
<pre data-language="javascript">
|
var files = $('#my-file-input').data('ace_input_files');
|
</pre>
|
</li>
|
|
<li>
|
For a working example and more info please see <code>examples/file-upload.html</code>.
|
</li>
|
|
<li>
|
When using FormData object if you use the following to create your FormData object,
|
browser will include all the files that are selected by user:
|
<pre data-language="javascript">
|
var myform = $('#myform');
|
var fd = new FormData(myform.get(0));//populate FormData with myform data
|
</pre>
|
This way our filtered files are not taken into account.
|
<br />
|
So you can do the following instead:
|
<pre data-language="javascript">
|
var myform = $('#myform');
|
var fd = new FormData();//empty FormData object
|
$.each(myform.serializeArray(), function(i, item) {
|
//add form fields one by one to our FormData
|
fd.append(item.name, item.value);
|
});
|
</pre>
|
The above does not add file fields to FormData and we should append our files like this:
|
<pre data-language="javascript">
|
myform.find('input[type=file]').each(function(){
|
var field_name = $(this).attr('name');
|
//for fields with "multiple" file support
|
//field name should be something like `myfile[]`
|
|
var files = $(this).data('ace_input_files');
|
if(files && files.length > 0) {
|
for(var f = 0; f < files.length; f++) {
|
fd.append(field_name, files[f]);
|
}
|
}
|
});
|
</pre>
|
Now our FormData object can be submitted using Ajax:
|
<pre data-language="javascript">
|
var deferred = $.ajax({
|
url: myform.attr('action'),
|
type: myform.attr('method'),
|
processData: false,//important
|
contentType: false,//important
|
dataType: 'json',//depending on your server side response
|
data: fd//our FormData object
|
})
|
|
deferred.done(function(result) {
|
//on success (successful response from server)
|
}).fail(function(result) {
|
//unable to receive a valid response from server
|
});
|
</pre>
|
|
</li>
|
|
<li>
|
For older browsers that don't support <code>FormData</code> object, we can use
|
an invisible frame to upload our form without leaving or refreshing the page:
|
<pre data-language="javascript">
|
var deferred = new $.Deferred //create a custom deferred object, because there's no ajax here to create it for us
|
var temporary_iframe_id = 'temporary-iframe-'+(new Date()).getTime()+'-'+(parseInt(Math.random()*1000));
|
var temp_iframe =
|
$('<iframe id="'+temporary_iframe_id+'" name="'+temporary_iframe_id+'" \
|
frameborder="0" width="0" height="0" src="about:blank"\
|
style="position:absolute; z-index:-1; visibility: hidden;" />')
|
.insertAfter(myform)
|
|
myform.append('<input type="hidden" name="temporary-iframe-id" value="'+temporary_iframe_id+'" />');
|
|
temp_iframe.data('deferrer' , deferred);
|
//we save the deferred object to the iframe and in our server side response
|
//we use "temporary-iframe-id" to access iframe and its deferred object
|
|
myform.attr({
|
'method': 'POST',
|
'enctype': 'multipart/form-data',
|
'target': temporary_iframe_id //important
|
});
|
|
myform.get(0).submit();
|
|
//if we don't receive a response after 30 seconds, let's declare it as failed!
|
ie_timeout = setTimeout(function(){
|
ie_timeout = null;
|
temp_iframe.attr('src', 'about:blank').remove();
|
deferred.reject({'status':'fail', 'message':'Timeout!'});
|
} , 30000);
|
}
|
</pre>
|
|
And deferred callbacks are similar to ajax example.
|
</li>
|
|
</ul>
|
</div>
|
|
|
|
<h3 class="info-title smaller">8. Notes</h3>
|
<div class="info-section">
|
<ul class="info-list list-unstyled">
|
<li>
|
Please note that validating files inside browser is not secure.
|
<br />
|
You should always check uploaded files in your server side script.
|
<br />
|
A php example inside <code>examples/file-upload.php</code>
|
validates files and only allows image files.
|
</li>
|
|
<li>
|
Most modern browsers allow multiple file selection.
|
<br />
|
If you want that, make sure your file input control has <code>multiple</code> attribute
|
and input name has brackets like <code>myfiles[]</code>:
|
<pre data-language="html">
|
<input multiple type="file" name="myfiles[]" id="myfiles" />
|
</pre>
|
</li>
|
</ul>
|
</div>
|
|
</div>
|
|
<!-- /section:custom/file-input -->
|
|
</section>
|