Skip to content

Commit cd0c9ed

Browse files
committed
Added folder drag&drop support.
1 parent 788a49d commit cd0c9ed

File tree

1 file changed

+129
-27
lines changed

1 file changed

+129
-27
lines changed

js/jquery.fileupload.js

Lines changed: 129 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* jQuery File Upload Plugin 5.15
2+
* jQuery File Upload Plugin 5.16
33
* https://github.com/blueimp/jQuery-File-Upload
44
*
55
* Copyright 2010, Sebastian Tschan
@@ -696,7 +696,7 @@
696696
var args = [undefined, 'abort', 'abort'];
697697
if (!jqXHR) {
698698
if (slot) {
699-
slot.rejectWith(args);
699+
slot.rejectWith(pipe, args);
700700
}
701701
return send(false, args);
702702
}
@@ -775,21 +775,90 @@
775775
}
776776
},
777777

778+
_handleFileTreeEntry: function (entry, path) {
779+
var that = this,
780+
dfd = $.Deferred(),
781+
errorHandler = function () {
782+
dfd.reject();
783+
},
784+
dirReader;
785+
path = path || '';
786+
if (entry.isFile) {
787+
entry.file(function (file) {
788+
file.relativePath = path;
789+
dfd.resolve(file);
790+
}, errorHandler);
791+
} else if (entry.isDirectory) {
792+
dirReader = entry.createReader();
793+
dirReader.readEntries(function (entries) {
794+
that._handleFileTreeEntries(
795+
entries,
796+
path + entry.name + '/'
797+
).done(function (files) {
798+
dfd.resolve(files);
799+
}).fail(errorHandler);
800+
}, errorHandler);
801+
} else {
802+
errorHandler();
803+
}
804+
return dfd.promise();
805+
},
806+
807+
_handleFileTreeEntries: function (entries, path) {
808+
var that = this;
809+
return $.when.apply(
810+
$,
811+
$.map(entries, function (entry) {
812+
return that._handleFileTreeEntry(entry, path);
813+
})
814+
).pipe(function () {
815+
return Array.prototype.concat.apply(
816+
[],
817+
arguments
818+
);
819+
});
820+
},
821+
822+
_getDroppedFiles: function (dataTransfer) {
823+
dataTransfer = dataTransfer || {};
824+
var items = dataTransfer.items;
825+
if (items && items.length && (items[0].webkitGetAsEntry ||
826+
items[0].getAsEntry)) {
827+
return this._handleFileTreeEntries(
828+
$.map(items, function (item) {
829+
if (item.webkitGetAsEntry) {
830+
return item.webkitGetAsEntry();
831+
}
832+
return item.getAsEntry();
833+
})
834+
);
835+
}
836+
return $.Deferred().resolve(
837+
$.makeArray(dataTransfer.files)
838+
).promise();
839+
},
840+
778841
_getFileInputFiles: function (fileInput) {
779842
fileInput = $(fileInput);
780-
var files = $.makeArray(fileInput.prop('files')),
843+
var entries = fileInput.prop('webkitEntries') ||
844+
fileInput.prop('entries'),
845+
files,
781846
value;
847+
if (entries) {
848+
return this._handleFileTreeEntries(entries);
849+
}
850+
files = $.makeArray(fileInput.prop('files'));
782851
if (!files.length) {
783852
value = fileInput.prop('value');
784853
if (!value) {
785-
return [];
854+
return $.Deferred().reject([]).promise();
786855
}
787856
// If the files property is not available, the browser does not
788857
// support the File API and we add a pseudo File object with
789858
// the input value as name with path information removed:
790859
files = [{name: value.replace(/^.*\\/, '')}];
791860
}
792-
return files;
861+
return $.Deferred().resolve(files).promise();
793862
},
794863

795864
_onChange: function (e) {
@@ -798,14 +867,15 @@
798867
fileInput: $(e.target),
799868
form: $(e.target.form)
800869
};
801-
data.files = that._getFileInputFiles(data.fileInput);
802-
if (that.options.replaceFileInput) {
803-
that._replaceFileInput(data.fileInput);
804-
}
805-
if (that._trigger('change', e, data) === false ||
806-
that._onAdd(e, data) === false) {
807-
return false;
808-
}
870+
that._getFileInputFiles(data.fileInput).always(function (files) {
871+
data.files = files;
872+
if (that.options.replaceFileInput) {
873+
that._replaceFileInput(data.fileInput);
874+
}
875+
if (that._trigger('change', e, data) !== false) {
876+
that._onAdd(e, data);
877+
}
878+
});
809879
},
810880

811881
_onPaste: function (e) {
@@ -826,16 +896,16 @@
826896
},
827897

828898
_onDrop: function (e) {
899+
e.preventDefault();
829900
var that = e.data.fileupload,
830901
dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer,
831-
data = {
832-
files: $.makeArray(dataTransfer && dataTransfer.files)
833-
};
834-
if (that._trigger('drop', e, data) === false ||
835-
that._onAdd(e, data) === false) {
836-
return false;
837-
}
838-
e.preventDefault();
902+
data = {};
903+
that._getDroppedFiles(dataTransfer).always(function (files) {
904+
data.files = files;
905+
if (that._trigger('drop', e, data) !== false) {
906+
that._onAdd(e, data);
907+
}
908+
});
839909
},
840910

841911
_onDragOver: function (e) {
@@ -929,29 +999,61 @@
929999
// must have a files property and can contain additional options:
9301000
// .fileupload('add', {files: filesList});
9311001
add: function (data) {
1002+
var that = this;
9321003
if (!data || this.options.disabled) {
9331004
return;
9341005
}
9351006
if (data.fileInput && !data.files) {
936-
data.files = this._getFileInputFiles(data.fileInput);
1007+
this._getFileInputFiles(data.fileInput).always(function (files) {
1008+
data.files = files;
1009+
that._onAdd(null, data);
1010+
});
9371011
} else {
9381012
data.files = $.makeArray(data.files);
1013+
this._onAdd(null, data);
9391014
}
940-
this._onAdd(null, data);
9411015
},
9421016

9431017
// This method is exposed to the widget API and allows sending files
9441018
// using the fileupload API. The data parameter accepts an object which
945-
// must have a files property and can contain additional options:
1019+
// must have a files or fileInput property and can contain additional options:
9461020
// .fileupload('send', {files: filesList});
9471021
// The method returns a Promise object for the file upload call.
9481022
send: function (data) {
9491023
if (data && !this.options.disabled) {
9501024
if (data.fileInput && !data.files) {
951-
data.files = this._getFileInputFiles(data.fileInput);
952-
} else {
953-
data.files = $.makeArray(data.files);
1025+
var that = this,
1026+
dfd = $.Deferred(),
1027+
promise = dfd.promise(),
1028+
jqXHR,
1029+
aborted;
1030+
promise.abort = function () {
1031+
aborted = true;
1032+
if (jqXHR) {
1033+
return jqXHR.abort();
1034+
}
1035+
dfd.reject(null, 'abort', 'abort');
1036+
return promise;
1037+
};
1038+
this._getFileInputFiles(data.fileInput).always(
1039+
function (files) {
1040+
if (aborted) {
1041+
return;
1042+
}
1043+
data.files = files;
1044+
jqXHR = that._onSend(null, data).then(
1045+
function (result, textStatus, jqXHR) {
1046+
dfd.resolve(result, textStatus, jqXHR);
1047+
},
1048+
function (jqXHR, textStatus, errorThrown) {
1049+
dfd.reject(jqXHR, textStatus, errorThrown);
1050+
}
1051+
);
1052+
}
1053+
);
1054+
return this._enhancePromise(promise);
9541055
}
1056+
data.files = $.makeArray(data.files);
9551057
if (data.files.length) {
9561058
return this._onSend(null, data);
9571059
}

0 commit comments

Comments
 (0)