Skip to content

Commit 6f13a8c

Browse files
committed
feat(tpl): can paste files for upload
1 parent 332b937 commit 6f13a8c

File tree

1 file changed

+111
-40
lines changed

1 file changed

+111
-40
lines changed

src/tpl/frontend/index.js

Lines changed: 111 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,9 @@
507507
var files = [];
508508
var len = entries.length;
509509
var cb = 0;
510+
if (!len) {
511+
onDone(files);
512+
}
510513

511514
function increaseCb() {
512515
cb++;
@@ -545,12 +548,33 @@
545548
}
546549

547550
function itemsToFiles(dataTransferItems, onDone) {
551+
var files = [];
552+
var len = dataTransferItems.length;
553+
if (!len) {
554+
onDone(files);
555+
}
556+
548557
var entries = [];
549-
for (var i = 0, len = dataTransferItems.length; i < len; i++) {
550-
var entry = dataTransferItems[i].webkitGetAsEntry();
551-
entries.push(entry);
558+
for (var i = 0; i < len; i++) {
559+
var item = dataTransferItems[i];
560+
var entry = item.webkitGetAsEntry();
561+
if (!entry) {
562+
continue;
563+
}
564+
if (entry.isFile) {
565+
// Safari cannot get file from entry by entry.file(), if it is a pasted image
566+
// so workaround is for all browsers, just get first hierarchy of files by item.getAsFile()
567+
var file = item.getAsFile();
568+
files.push({file: file, relativePath: file.name});
569+
} else {
570+
entries.push(entry);
571+
}
552572
}
553-
entriesToFiles(entries, onDone);
573+
574+
entriesToFiles(entries, function (entryFiles) {
575+
files.push.apply(files, entryFiles);
576+
onDone(files);
577+
});
554578
}
555579

556580
function itemsHasDir(dataTransferItems) {
@@ -562,7 +586,7 @@
562586
if (items.length && items[0].webkitGetAsEntry) {
563587
for (var i = 0, len = items.length; i < len; i++) {
564588
var entry = items[i].webkitGetAsEntry();
565-
if (entry.isDirectory) {
589+
if (entry && entry.isDirectory) {
566590
hasDir = true;
567591
break;
568592
}
@@ -579,9 +603,20 @@
579603
}
580604

581605
function switchToDirMode() {
582-
if (!optDirFile && !optInnerDirFile) {
583-
return;
606+
if (optDirFile) {
607+
if (optActive !== optDirFile) {
608+
optDirFile.focus();
609+
optDirFile.click();
610+
}
611+
} else if (optInnerDirFile) {
612+
if (optActive !== optInnerDirFile) {
613+
optInnerDirFile.focus();
614+
optInnerDirFile.click();
615+
}
584616
}
617+
}
618+
619+
function switchToAnyDirMode() {
585620
if (optActive === optFile) {
586621
if (optDirFile) {
587622
optDirFile.focus();
@@ -818,14 +853,16 @@
818853
return;
819854
}
820855

821-
if (itemsHasDir(e.dataTransfer.items)) {
856+
var items = e.dataTransfer.items;
857+
if (itemsHasDir(items)) {
822858
if (!uploadProgressively) {
823859
// must use progressive upload by JS if has directory
824860
return;
825861
}
826-
switchToDirMode();
827862
btnSubmit.disabled = true; // disable earlier
828-
itemsToFiles(e.dataTransfer.items, function (files) {
863+
var itemsCount = items.length; // save items count earlier, items will be lost after calling FileSystemFileEntry.file()
864+
itemsToFiles(items, function (files) {
865+
itemsCount > 1 ? switchToDirMode() : switchToAnyDirMode();
829866
uploadProgressively(files);
830867
});
831868
} else {
@@ -861,6 +898,21 @@
861898
}
862899

863900
var typeTextPlain = 'text/plain';
901+
var createTextFile;
902+
var textFilename = 'text.txt';
903+
if (Blob && Blob.prototype.msClose) { // legacy Edge
904+
createTextFile = function (content) {
905+
var file = new Blob([content], {type: typeTextPlain});
906+
file.name = textFilename;
907+
return file;
908+
};
909+
} else if (File) {
910+
createTextFile = function (content) {
911+
return new File([content], textFilename, {type: typeTextPlain});
912+
}
913+
}
914+
915+
var nonTextInputTypes = ['hidden', 'radio', 'checkbox', 'button', 'reset', 'submit', 'image'];
864916

865917
function uploadPastedFiles(files) {
866918
switchToFileMode();
@@ -880,41 +932,14 @@
880932
uploadProgressively(files);
881933
}
882934

883-
var createTextFile;
884-
var textFilename = 'text.txt';
885-
if (Blob && Blob.prototype.msClose) { // legacy Edge
886-
createTextFile = function (content) {
887-
var file = new Blob([content], {type: typeTextPlain});
888-
file.name = textFilename;
889-
return file;
890-
};
891-
} else if (File) {
892-
createTextFile = function (content) {
893-
return new File([content], textFilename, {type: typeTextPlain});
894-
}
895-
}
896-
897-
var nonTextInputTypes = ['hidden', 'radio', 'checkbox', 'button', 'reset', 'submit', 'image'];
898-
document.documentElement.addEventListener('paste', function (e) {
899-
var tagName = e.target.tagName;
900-
if (tagName === 'INPUT') {
901-
if (nonTextInputTypes.indexOf(e.target.type) < 0) {
902-
return;
903-
}
904-
}
905-
if (tagName === 'TEXTAREA') {
906-
return;
907-
}
908-
var data = e.clipboardData;
909-
if (!data) {
910-
return;
911-
}
912-
935+
function generatePastedFiles(data) {
913936
var files;
914937
var items;
915938
if (data.files && data.files.length) {
939+
// pasted content is image
916940
files = Array.prototype.slice.call(data.files);
917941
} else if (data.items && data.items.length) {
942+
// pasted content is text
918943
items = Array.prototype.slice.call(data.items);
919944
files = items.map(function (item) {
920945
return item.getAsFile();
@@ -948,6 +973,52 @@
948973
}
949974
});
950975
}
976+
}
977+
978+
document.documentElement.addEventListener('paste', function (e) {
979+
var tagName = e.target.tagName;
980+
if (tagName === 'INPUT') {
981+
if (nonTextInputTypes.indexOf(e.target.type) < 0) {
982+
return;
983+
}
984+
}
985+
if (tagName === 'TEXTAREA') {
986+
return;
987+
}
988+
var data = e.clipboardData;
989+
if (!data) {
990+
return;
991+
}
992+
993+
var items = data.items;
994+
var itemsCount = items.length; // save items count earlier, items will be lost after calling FileSystemFileEntry.file()
995+
if (!items || !itemsCount) {
996+
generatePastedFiles(data);
997+
return;
998+
}
999+
var hasDir = itemsHasDir(items);
1000+
itemsToFiles(items, function (files) {
1001+
if (!files.length) {
1002+
// for pasted text
1003+
generatePastedFiles(data);
1004+
return;
1005+
}
1006+
if (files.length === 1 && files[0].file.type === 'image/png') {
1007+
// suppose for pasted image
1008+
files = files.map(function (fileInfo) {
1009+
return fileInfo && fileInfo.file;
1010+
});
1011+
generatePastedFiles({files: files});
1012+
return;
1013+
}
1014+
// pasted real files, not image binary
1015+
if (hasDir) {
1016+
itemsCount > 1 ? switchToDirMode() : switchToAnyDirMode();
1017+
} else {
1018+
switchToFileMode();
1019+
}
1020+
uploadProgressively(files);
1021+
});
9511022
});
9521023
}
9531024

0 commit comments

Comments
 (0)