Skip to content

Commit dcd288f

Browse files
committed
v2.0.11: fixed Drag'n'Drop
1 parent 26ac8c8 commit dcd288f

File tree

6 files changed

+274
-80
lines changed

6 files changed

+274
-80
lines changed

dist/FileAPI.html5.js

Lines changed: 132 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*! FileAPI 2.0.10 - BSD | git://github.com/mailru/FileAPI.git
1+
/*! FileAPI 2.0.11 - BSD | git://github.com/mailru/FileAPI.git
22
* FileAPI — a set of javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF.
33
*/
44

@@ -105,6 +105,7 @@
105105
document = window.document,
106106
doctype = document.doctype || {},
107107
userAgent = window.navigator.userAgent,
108+
safari = /safari\//i.test(userAgent) && !/chrome\//i.test(userAgent),
108109

109110
// https://github.com/blueimp/JavaScript-Load-Image/blob/master/load-image.js#L48
110111
apiURL = (window.createObjectURL && window) || (window.URL && URL.revokeObjectURL && URL) || (window.webkitURL && webkitURL),
@@ -119,12 +120,14 @@
119120
jQuery = window.jQuery,
120121

121122
html5 = !!(File && (FileReader && (window.Uint8Array || FormData || XMLHttpRequest.prototype.sendAsBinary)))
122-
&& !(/safari\//i.test(userAgent) && !/chrome\//i.test(userAgent) && /windows/i.test(userAgent)), // BugFix: https://github.com/mailru/FileAPI/issues/25
123+
&& !(safari && /windows/i.test(userAgent)), // BugFix: https://github.com/mailru/FileAPI/issues/25
123124

124125
cors = html5 && ('withCredentials' in (new XMLHttpRequest)),
125126

126127
chunked = html5 && !!Blob && !!(Blob.prototype.webkitSlice || Blob.prototype.mozSlice || Blob.prototype.slice),
127128

129+
normalize = ('' + ''.normalize).indexOf('[native code]') > 0,
130+
128131
// https://github.com/blueimp/JavaScript-Canvas-to-Blob
129132
dataURLtoBlob = window.dataURLtoBlob,
130133

@@ -280,7 +283,7 @@
280283
* FileAPI (core object)
281284
*/
282285
api = {
283-
version: '2.0.10',
286+
version: '2.0.11',
284287

285288
cors: false,
286289
html5: true,
@@ -795,28 +798,84 @@
795798
getDropFiles: function (evt, callback){
796799
var
797800
files = []
801+
, all = []
802+
, items
798803
, dataTransfer = _getDataTransfer(evt)
799-
, entrySupport = _isArray(dataTransfer.items) && dataTransfer.items[0] && _getAsEntry(dataTransfer.items[0])
800-
, queue = api.queue(function (){ callback(files); })
804+
, transFiles = dataTransfer.files
805+
, transItems = dataTransfer.items
806+
, entrySupport = _isArray(transItems) && transItems[0] && _getAsEntry(transItems[0])
807+
, queue = api.queue(function (){ callback(files, all); })
801808
;
802809

803-
_each((entrySupport ? dataTransfer.items : dataTransfer.files) || [], function (item){
810+
if( entrySupport ){
811+
if( normalize && transFiles ){
812+
var
813+
i = transFiles.length
814+
, file
815+
, entry
816+
;
817+
818+
items = new Array(i);
819+
while( i-- ){
820+
file = transFiles[i];
821+
822+
try {
823+
entry = _getAsEntry(transItems[i]);
824+
}
825+
catch( err ){
826+
api.log('[err] getDropFiles: ', err);
827+
entry = null;
828+
}
829+
830+
if( _isEntry(entry) ){
831+
// OSX filesystems use Unicode Normalization Form D (NFD),
832+
// and entry.file(…) can't read the files with the same names
833+
if( entry.isDirectory || (entry.isFile && file.name == file.name.normalize('NFC')) ){
834+
items[i] = entry;
835+
}
836+
else {
837+
items[i] = file;
838+
}
839+
}
840+
else {
841+
items[i] = file;
842+
}
843+
}
844+
}
845+
else {
846+
items = transItems;
847+
}
848+
}
849+
else {
850+
items = transFiles;
851+
}
852+
853+
_each(items || [], function (item){
804854
queue.inc();
805855

806856
try {
807-
if( entrySupport ){
808-
_readEntryAsFiles(item, function (err, entryFiles){
857+
if( entrySupport && _isEntry(item) ){
858+
_readEntryAsFiles(item, function (err, entryFiles, allEntries){
809859
if( err ){
810860
api.log('[err] getDropFiles:', err);
811861
} else {
812862
files.push.apply(files, entryFiles);
813863
}
864+
all.push.apply(all, allEntries);
865+
814866
queue.next();
815867
});
816868
}
817869
else {
818-
_isRegularFile(item, function (yes){
819-
yes && files.push(item);
870+
_isRegularFile(item, function (yes, err){
871+
if( yes ){
872+
files.push(item);
873+
}
874+
else {
875+
item.error = err;
876+
}
877+
all.push(item);
878+
820879
queue.next();
821880
});
822881
}
@@ -1537,26 +1596,29 @@
15371596

15381597
function _isRegularFile(file, callback){
15391598
// http://stackoverflow.com/questions/8856628/detecting-folders-directories-in-javascript-filelist-objects
1540-
if( !file.type && (file.size % 4096) === 0 && (file.size <= 102400) ){
1599+
if( !file.type && (safari || ((file.size % 4096) === 0 && (file.size <= 102400))) ){
15411600
if( FileReader ){
15421601
try {
1543-
var Reader = new FileReader();
1602+
var reader = new FileReader();
15441603

1545-
_one(Reader, _readerEvents, function (evt){
1604+
_one(reader, _readerEvents, function (evt){
15461605
var isFile = evt.type != 'error';
1547-
callback(isFile);
15481606
if( isFile ){
1549-
Reader.abort();
1607+
reader.abort();
1608+
callback(isFile);
1609+
}
1610+
else {
1611+
callback(false, reader.error);
15501612
}
15511613
});
15521614

1553-
Reader.readAsDataURL(file);
1615+
reader.readAsDataURL(file);
15541616
} catch( err ){
1555-
callback(false);
1617+
callback(false, err);
15561618
}
15571619
}
15581620
else {
1559-
callback(null);
1621+
callback(null, new Error('FileReader is not supported'));
15601622
}
15611623
}
15621624
else {
@@ -1565,6 +1627,11 @@
15651627
}
15661628

15671629

1630+
function _isEntry(item){
1631+
return item && (item.isFile || item.isDirectory);
1632+
}
1633+
1634+
15681635
function _getAsEntry(item){
15691636
var entry;
15701637
if( item.getAsEntry ){ entry = item.getAsEntry(); }
@@ -1576,34 +1643,52 @@
15761643
function _readEntryAsFiles(entry, callback){
15771644
if( !entry ){
15781645
// error
1579-
callback('invalid entry');
1646+
var err = new Error('invalid entry');
1647+
entry = new Object(entry);
1648+
entry.error = err;
1649+
callback(err.message, [], [entry]);
15801650
}
15811651
else if( entry.isFile ){
15821652
// Read as file
1583-
entry.file(function(file){
1653+
entry.file(function (file){
15841654
// success
15851655
file.fullPath = entry.fullPath;
1586-
callback(false, [file]);
1656+
callback(false, [file], [file]);
15871657
}, function (err){
15881658
// error
1589-
callback('FileError.code: '+err.code);
1659+
entry.error = err;
1660+
callback('FileError.code: ' + err.code, [], [entry]);
15901661
});
15911662
}
15921663
else if( entry.isDirectory ){
1593-
var reader = entry.createReader(), result = [];
1664+
var
1665+
reader = entry.createReader()
1666+
, firstAttempt = true
1667+
, files = []
1668+
, all = [entry]
1669+
;
15941670

1595-
var onerror = function() {
1671+
var onerror = function (err){
15961672
// error
1597-
callback('directory_reader');
1673+
entry.error = err;
1674+
callback('DirectoryError.code: ' + err.code, files, all);
15981675
};
1599-
var ondone = function ondone(entries) {
1676+
var ondone = function ondone(entries){
1677+
if( firstAttempt ){
1678+
firstAttempt = false;
1679+
if( !entries.length ){
1680+
entry.error = new Error('directory is empty');
1681+
}
1682+
}
1683+
16001684
// success
1601-
if ( entries.length ) {
1685+
if( entries.length ){
16021686
api.afor(entries, function (next, entry){
1603-
_readEntryAsFiles(entry, function (err, files){
1687+
_readEntryAsFiles(entry, function (err, entryFiles, allEntries){
16041688
if( !err ){
1605-
result = result.concat(files);
1689+
files = files.concat(entryFiles);
16061690
}
1691+
all = all.concat(allEntries);
16071692

16081693
if( next ){
16091694
next();
@@ -1615,7 +1700,7 @@
16151700
});
16161701
}
16171702
else {
1618-
callback(false, result);
1703+
callback(false, files, all);
16191704
}
16201705
};
16211706

@@ -1740,8 +1825,8 @@
17401825
_type = 0;
17411826
onHover.call(evt[currentTarget], false, evt);
17421827

1743-
api.getDropFiles(evt, function (files){
1744-
onDrop.call(evt[currentTarget], files, evt);
1828+
api.getDropFiles(evt, function (files, all){
1829+
onDrop.call(evt[currentTarget], files, all, evt);
17451830
});
17461831
});
17471832
}
@@ -2533,7 +2618,13 @@
25332618
});
25342619

25352620
this.each(function (file){
2536-
next(file, data, queue, arg);
2621+
try{
2622+
next(file, data, queue, arg);
2623+
}
2624+
catch( err ){
2625+
api.log('FileAPI.Form._to: ' + err.message);
2626+
complete(err);
2627+
}
25372628
});
25382629

25392630
queue.check();
@@ -2761,9 +2852,14 @@
27612852
var _this = this, options = this.options;
27622853

27632854
FormData.toData(function (data){
2764-
// Start uploading
2765-
options.upload(options, _this);
2766-
_this._send.call(_this, options, data);
2855+
if( data instanceof Error ){
2856+
_this.end(0, data.message);
2857+
}
2858+
else{
2859+
// Start uploading
2860+
options.upload(options, _this);
2861+
_this._send.call(_this, options, data);
2862+
}
27672863
}, options);
27682864
},
27692865

dist/FileAPI.html5.min.js

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)