Prologue
fileupload is a great jQuery plugin that enables asynchronous file uploads.
I have found it very useful, but encountered an obstacle when I began to rely on the position of file in a certain list.
Background
In
Affectix, we create online messages and allow the user to upload images to attach to the message.
For example - if I want to create a message about my lost pet, I would upload images of the pet, and Affectix will attach those images to the message.
From different reasons, I decided to save the images in a list. It looks like this:
MessageObject
|
|--> Images = [img1, img2, img3, ....]
On a Second Look
If you consider the
MessageObject
's Editor-WebPage, you realize that the uploaded images appear on screen as a list. This list contains href encors that might
GET
/
POST
to the server - instructing the deletion of an image.
The Problem
We would like to be able to
GET
/
POST
the instruction: "Delete image at index 3", but fileupload does not provide an 'index' value on the file records.
The Solution
We enhance the fileupload plugin to include indexes.
The Details
fileupload comes with 2
.js files:
- jquery.fileupload.js
- jquery.fileupload-ui.js
In this solution, we modify the second file:
jquery.fileupload-ui.js.
Step 1
Add a support function ('
_set_indexes
') that queries the fileupload DOM, and creates the desired indexes.
Note: The indexes are stored in the jQuery '
data
' object:
(function ($) {
'use strict';
$.widget('blueimpUI.fileupload', $.blueimp.fileupload, {
options: {
...
},
...
_set_indexes: function() {
$('$.files .template-download').each(function(index, obj) {
var jObj = $(obj);
jObj.data('index', index);
});
},
...
});
}(jQuery));
Step 2
Launch the support function whenever the list changes (the
bold lines). For example, when a file just finished uploading, or when a file has been removed from the list:
(function ($) {
'use strict';
$.widget('blueimpUI.fileupload', $.blueimp.fileupload, {
options: {
...
done: function (e, data) {
var that = $(this).data('fileupload');
if (data.context) {
data.context.each(function (index) {
var file = ($.isArray(data.result) &&
data.result[index]) || {error: 'emptyResult'};
if (file.error) {
that._adjustMaxNumberOfFiles(1);
}
$(this).fadeOut(function () {
that._renderDownload([file])
.css('display', 'none')
.replaceAll(this)
.fadeIn(function () {
$(this).show();
that._set_indexes();
});
});
});
} else {
that._renderDownload(data.result)
.css('display', 'none')
.appendTo($(this).find('.files'))
.fadeIn(function () {
$(this).show();
that._set_indexes();
});
}
},
...
destroy: function (e, data) {
var that = $(this).data('fileupload');
if (data.url) {
debug(data);
$.ajax(data)
.success(function () {
that._adjustMaxNumberOfFiles(1);
$(this).fadeOut(function () {
$(this).remove();
that._set_indexes();
});
});
} else {
data.context.fadeOut(function () {
$(this).remove();
that._set_indexes();
});
}
}
...
},
...
});
}(jQuery));
Step 3
Fix the '
delete
' Ajax call:
(function ($) {
'use strict';
$.widget('blueimpUI.fileupload', $.blueimp.fileupload, {
options: {
...
},
_deleteHandler: function (e) {
e.preventDefault();
var button = $(this);
var context = button.closest('.template-download');
e.data.fileupload._trigger('destroy', e, {
context: context,
url: button.attr('data-url'),
type: button.attr('data-type'),
dataType: e.data.fileupload.options.dataType ,
data: { 'index': context.data('index') }
});
},
...
});
}(jQuery));
Step 4
On the server side, you will receive the '
index
' variable. You can take it from there.
Summary
In this code tip, we implemented an enhancement to the jquery fileupload plugin. We added an index to the file list, and fixed the '
delete
' call to include that index. The attached code refreshes the index everytime the list changes. As a result, we are able to delete files using only their index and context.
Good Luck!
Or (David) Berkovitch