问题
My Fine Uploader implementation - using the core mode and jQuery - works fine until I try to upload a second batch of files.
When the first batch of files have been uploaded (successfully), I can click the button to add files and get the dialog to select files. However, after I confirm the file(s) selection nothing happens.
This bit of code in the complete
handler is causing the trouble:
$('#attachments-upload').button('reset'); // Bootstrap stateful button
#attachments-upload
is the id of the button which is set as the button:
option as well. Here's the full JS code listing:
$('#attachments-list').fineUploader({
uploaderType: 'basic',
button: $('#attachments-upload'),
debug: true,
request: {
endpoint: $route_atatachments_upload,
inputName: 'attachments'
},
validation: {
allowedExtensions: ['png', 'jpeg', 'gif', 'pdf', 'doc', 'bmp'],
sizeLimit: 10485760 // 10MB
}
})
.on('upload', function(event, id, fileName) {
$('#attachments-upload-error').hide();
$('#attachments-upload').button('loading');
$('#attachments-upload-progress').show().attr('aria-valuenow', 0);
})
.on('progress', function(event, id, fileName, loaded, total) {
if (loaded < total) {
var progress = Math.round(loaded / total * 100) + '% of ' + Math.round(total / 1024) + ' kB';
$('#attachments-upload-progress').attr('aria-valuenow', progress);
} else {
$('#attachments-upload-progress').attr('aria-valuenow', 100);
}
})
.on('complete', function(event, id, fileName, responseJSON) {
$('#attachments-upload-progress').hide();
$('#attachments-upload').button('reset');
if (responseJSON.success) {
$('<tr class="attachment" data-attachment-uuid="'+ responseJSON.uuid + '">' +
'<td>' + fileName +'</td>' +
'<td>' + humanFileSize(responseJSON.size) + '</td>' +
'<td style="text-align: center"><a class="delete-attachment" href="#"><span class="glyphicon glyphicon-trash" </a></td>' +
'</tr>').
insertBefore($('#add-attachment'));
} else {
$('#attachments-upload-error').show();
console.log(responseJSON.error);
}
});
And this is the HTML:
<table class="table table-bordered" id="attachments-list">
<thead>
<tr>
<th>Name</th>
<th>Size</th>
<th></th>
</tr>
</thead>
<tbody id="added-attachments">
<tr id="add-attachment">
<td colspan="2">
<div id="attachments-upload-progress" class="progress progress-striped active" style="display:none">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</td><td style="width:1%; white-space:nowrap;">
<button id="attachments-upload" class="btn btn-success" data-loading-text="loading ..." style="position: relative; overflow: hidden; direction: ltr; ">Add Files ...</button>
</td>
</tr>
</tbody>
</table>
But as I said, if I comment the following line,
$('#attachments-upload').button('reset');
Everything works fine.
回答1:
I delved into the Bootstrap rabbit hole, and came out with your answer.
The .button('reset')
method offered by Bootstrap is a bit wonky. When the state of the button is changed, (i.e., .button('loading')
or .button('reset')
is called) the Bootstrap JS caches the HTML contents of the button before the state change and stores it as a string under the element's data
attribute.
So, first the button is like:
<button id="attachments-upload"...>
Add files ...
<input type='file' name='qqfile'>
</button>
Once you call $("#attachments-upload").button('loading')
the button's inner-HTML gets changed:
<button id="attachments-upload" ...>loading ...</button>
Notice that the file input element is not there anymore.
Resetting the button reverts it back to its original state by re-injecting the cached HTML:
<button id="attachments-upload"...>
Add files ...
<input type='file' name='qqfile'>
</button>
but at this point the file input element has been removed from the DOM and all previously attached event handlers are not longer valid on that element. Fine Uploader binds to this input element's onChange
event internally to track files that have been submitted via that input element.
You have a few options.
Above all else, remove the call to .button('reset')
and .button('loading')
1) Forget about setting the 'loading...' text on the button. The behavior it displays now leads me to infer that you would not like your users to be able to upload any files until the current uploading file is completed (onComplete
is reached). This behavior is a bit strange as the Upload Files button should remain stateless.
2) Programmatically change the loading text of the button inside of your handlers if you would like to keep the current behavior without the removal of the input element.
3) Display another progress notification such as a spinner (which you can show()
inside of the onSubmit
and hide()
inside of the onComplete
)
Also, another small thing I noticed that you probably want to add "jpg" to your allowed extensions. Right now those'll get denied, but "jpeg" files will be accepted.
来源:https://stackoverflow.com/questions/18476872/fine-uploader-only-works-for-a-single-batch-of-files