bkjxxxw/WebContent/static/ace/docs/sections/custom/file-input.html

577 lines
18 KiB
HTML

<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 =
$('&lt;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;" /&gt;')
.insertAfter(myform)
myform.append('&lt;input type="hidden" name="temporary-iframe-id" value="'+temporary_iframe_id+'" /&gt;');
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">
&lt;input multiple type="file" name="myfiles[]" id="myfiles" /&gt;
</pre>
</li>
</ul>
</div>
</div>
<!-- /section:custom/file-input -->
</section>