|
1 | 1 | (function () { |
2 | 2 | var strUndef = 'undefined'; |
| 3 | + var protoHttps = 'https:'; |
3 | 4 |
|
4 | 5 | var classNone = 'none'; |
5 | 6 | var classHeader = 'header'; |
|
550 | 551 | return ts; |
551 | 552 | } |
552 | 553 |
|
553 | | - function entriesToFiles(entries, onDone) { |
554 | | - var files = []; |
555 | | - var len = entries.length; |
556 | | - var cb = 0; |
557 | | - if (!len) { |
558 | | - onDone(files); |
559 | | - } |
560 | | - |
561 | | - function increaseCb() { |
562 | | - cb++; |
563 | | - if (cb === len) { |
564 | | - onDone(files); |
| 554 | + var itemsToFiles; |
| 555 | + if (location.protocol === protoHttps && typeof FileSystemHandle !== strUndef && !DataTransferItem.prototype.webkitGetAsEntry) { |
| 556 | + var handleKindFile = 'file'; |
| 557 | + var handleKindDir = 'directory'; |
| 558 | + var permDescriptor = {mode: 'read'}; |
| 559 | + itemsToFiles = function (dataTransferItems, canMkdir, onDone, onLacksMkdir) { |
| 560 | + function resultsToFiles(results, files, dirPath) { |
| 561 | + return Promise.all(results.map(function (result) { |
| 562 | + var handle = result.value; |
| 563 | + if (handle.kind === handleKindFile) { |
| 564 | + return handle.queryPermission(permDescriptor).then(function (queryResult) { |
| 565 | + if (queryResult === 'prompt') return handle.requestPermission(permDescriptor); |
| 566 | + }).then(function () { |
| 567 | + return handle.getFile(); |
| 568 | + }).then(function (file) { |
| 569 | + var relativePath = dirPath + file.name; |
| 570 | + files.push({file: file, relativePath: relativePath}); |
| 571 | + })['catch'](function (err) { // workaround IE8- syntax error for ".catch"(reserved keyword) |
| 572 | + typeof console !== strUndef && console.error(err); |
| 573 | + }); |
| 574 | + } else if (handle.kind === handleKindDir) { |
| 575 | + return new Promise(function (resolve) { |
| 576 | + var childResults = []; |
| 577 | + var childIter = handle.values(); |
| 578 | + |
| 579 | + function onLevelDone() { |
| 580 | + childResults = null; |
| 581 | + childIter = null; |
| 582 | + resolve(); |
| 583 | + } |
| 584 | + |
| 585 | + function addChildResult() { |
| 586 | + childIter.next().then(function (result) { |
| 587 | + if (result.done) { |
| 588 | + if (childResults.length) { |
| 589 | + resultsToFiles(childResults, files, dirPath + handle.name + '/').then(onLevelDone); |
| 590 | + } else onLevelDone(); |
| 591 | + } else { |
| 592 | + childResults.push(result); |
| 593 | + addChildResult(); |
| 594 | + } |
| 595 | + }); |
| 596 | + } |
| 597 | + |
| 598 | + addChildResult(); |
| 599 | + }); |
| 600 | + } |
| 601 | + })); |
565 | 602 | } |
566 | | - } |
567 | 603 |
|
568 | | - entries.forEach(function (entry) { |
569 | | - if (entry.isFile) { |
570 | | - var relativePath = entry.fullPath; |
571 | | - if (relativePath[0] === '/') { |
572 | | - relativePath = relativePath.substring(1); |
| 604 | + var files = []; |
| 605 | + var hasDir = false; |
| 606 | + if (!dataTransferItems || !dataTransferItems.length) return onDone(files, hasDir); |
| 607 | + |
| 608 | + var items = Array.prototype.slice.call(dataTransferItems); |
| 609 | + Promise.all(items.map(function (item) { |
| 610 | + return item.getAsFileSystemHandle(); |
| 611 | + })).then(function (handles) { |
| 612 | + handles = handles.filter(Boolean); // undefined for pasted content |
| 613 | + hasDir = handles.some(function (handle) { |
| 614 | + return handle.kind === handleKindDir; |
| 615 | + }); |
| 616 | + if (hasDir && !canMkdir) { |
| 617 | + return onLacksMkdir(); |
573 | 618 | } |
574 | | - entry.file(function (file) { |
575 | | - files.push({file: file, relativePath: relativePath}); |
576 | | - increaseCb(); |
577 | | - }, function (err) { |
578 | | - increaseCb(); |
579 | | - typeof console !== strUndef && console.error(err); |
| 619 | + var handleResults = handles.map(function (handle) { |
| 620 | + return {value: handle, done: false}; |
580 | 621 | }); |
581 | | - } else if (entry.isDirectory) { |
582 | | - var reader = entry.createReader(); |
583 | | - reader.readEntries(function (subEntries) { |
584 | | - if (subEntries.length) { |
585 | | - entriesToFiles(subEntries, function (subFiles) { |
586 | | - Array.prototype.push.apply(files, subFiles); |
| 622 | + resultsToFiles(handleResults, files, '').then(function () { |
| 623 | + onDone(files, hasDir); |
| 624 | + }); |
| 625 | + }); |
| 626 | + } |
| 627 | + } else { |
| 628 | + itemsToFiles = function (dataTransferItems, canMkdir, onDone, onLacksMkdir) { |
| 629 | + function entriesToFiles(entries, files, onLevelDone) { |
| 630 | + var len = entries.length; |
| 631 | + var cb = 0; |
| 632 | + if (!len) return onLevelDone(); |
| 633 | + |
| 634 | + function increaseCb() { |
| 635 | + cb++; |
| 636 | + if (cb === len) { |
| 637 | + onLevelDone(); |
| 638 | + } |
| 639 | + } |
| 640 | + |
| 641 | + entries.forEach(function (entry) { |
| 642 | + if (entry.isFile) { |
| 643 | + var relativePath = entry.fullPath; |
| 644 | + if (relativePath[0] === '/') { |
| 645 | + relativePath = relativePath.substring(1); |
| 646 | + } |
| 647 | + entry.file(function (file) { |
| 648 | + files.push({file: file, relativePath: relativePath}); |
| 649 | + increaseCb(); |
| 650 | + }, function (err) { |
587 | 651 | increaseCb(); |
| 652 | + typeof console !== strUndef && console.error(err); |
| 653 | + }); |
| 654 | + } else if (entry.isDirectory) { |
| 655 | + var reader = entry.createReader(); |
| 656 | + reader.readEntries(function (subEntries) { |
| 657 | + if (subEntries.length) { |
| 658 | + entriesToFiles(subEntries, files, increaseCb); |
| 659 | + } else { |
| 660 | + increaseCb(); |
| 661 | + } |
588 | 662 | }); |
589 | | - } else { |
590 | | - increaseCb(); |
591 | 663 | } |
592 | 664 | }); |
593 | 665 | } |
594 | | - }); |
595 | | - } |
596 | 666 |
|
597 | | - function itemsToFiles(dataTransferItems, onDone) { |
598 | | - var files = []; |
599 | | - var len = dataTransferItems.length; |
600 | | - if (!len) { |
601 | | - onDone(files); |
602 | | - } |
| 667 | + var files = []; |
| 668 | + var hasDir = false; |
| 669 | + if (!dataTransferItems || !dataTransferItems.length || !dataTransferItems[0].webkitGetAsEntry) return onDone(files, hasDir); |
603 | 670 |
|
604 | | - var entries = []; |
605 | | - for (var i = 0; i < len; i++) { |
606 | | - var item = dataTransferItems[i]; |
607 | | - var entry = item.webkitGetAsEntry(); |
608 | | - if (!entry) { |
609 | | - continue; |
610 | | - } |
611 | | - if (entry.isFile) { |
612 | | - // Safari cannot get file from entry by entry.file(), if it is a pasted image |
613 | | - // so workaround is for all browsers, just get first hierarchy of files by item.getAsFile() |
614 | | - var file = item.getAsFile(); |
615 | | - files.push({file: file, relativePath: file.name}); |
616 | | - } else if (entry.isDirectory) { |
617 | | - entries.push(entry); |
| 671 | + var entries = []; |
| 672 | + for (var i = 0, len = dataTransferItems.length; i < len; i++) { |
| 673 | + var item = dataTransferItems[i]; |
| 674 | + var entry = item.webkitGetAsEntry(); |
| 675 | + if (!entry) { // undefined for pasted text |
| 676 | + continue; |
| 677 | + } |
| 678 | + if (entry.isFile) { |
| 679 | + // Safari cannot get file from entry by entry.file(), if it is a pasted image |
| 680 | + // so workaround is for all browsers, just get first hierarchy of files by item.getAsFile() |
| 681 | + var file = item.getAsFile(); |
| 682 | + files.push({file: file, relativePath: file.name}); |
| 683 | + } else if (entry.isDirectory) { |
| 684 | + hasDir = true; |
| 685 | + if (canMkdir) { |
| 686 | + entries.push(entry); |
| 687 | + } else { |
| 688 | + return onLacksMkdir(); |
| 689 | + } |
| 690 | + } |
618 | 691 | } |
619 | | - } |
620 | 692 |
|
621 | | - entriesToFiles(entries, function (entryFiles) { |
622 | | - files.push.apply(files, entryFiles); |
623 | | - onDone(files); |
624 | | - }); |
| 693 | + entriesToFiles(entries, files, function () { |
| 694 | + onDone(files, hasDir); |
| 695 | + }); |
| 696 | + } |
625 | 697 | } |
626 | 698 |
|
627 | | - function itemsHasDir(dataTransferItems) { |
628 | | - if (!dataTransferItems) { |
629 | | - return false; |
630 | | - } |
631 | | - var items = Array.prototype.slice.call(dataTransferItems); |
632 | | - if (items.length && items[0].webkitGetAsEntry) { |
633 | | - for (var i = 0, len = items.length; i < len; i++) { |
634 | | - var entry = items[i].webkitGetAsEntry(); |
635 | | - if (entry && entry.isDirectory) { |
636 | | - return true; |
637 | | - } |
| 699 | + function dataTransferToFiles(dataTransfer, canMkdir, onDone, onLacksMkdir) { |
| 700 | + itemsToFiles(dataTransfer.items, canMkdir, function (files, hasDir) { |
| 701 | + // ancient Browser |
| 702 | + if (files.length === 0 && dataTransfer.files && dataTransfer.files.length) { |
| 703 | + files = Array.prototype.slice.call(dataTransfer.files); |
638 | 704 | } |
639 | | - } |
640 | | - return false; |
| 705 | + onDone(files, hasDir); |
| 706 | + }, onLacksMkdir); |
641 | 707 | } |
642 | 708 |
|
643 | 709 | function switchToFileMode() { |
|
934 | 1000 | return; |
935 | 1001 | } |
936 | 1002 |
|
937 | | - var items = e.dataTransfer.items; |
938 | | - if (itemsHasDir(items)) { |
939 | | - // must use progressive upload by JS if has directory |
940 | | - if (!canMkdir || !uploadProgressively) { |
941 | | - typeof showUploadDirFailMessage !== strUndef && showUploadDirFailMessage(); |
942 | | - return; |
943 | | - } |
944 | | - itemsToFiles(items, function (files) { |
| 1003 | + dataTransferToFiles(e.dataTransfer, canMkdir && Boolean(uploadProgressively), function (files, hasDir) { |
| 1004 | + if (hasDir) { |
945 | 1005 | switchToDirMode(); |
946 | 1006 | uploadProgressively(files); |
947 | | - }); |
948 | | - } else { |
949 | | - switchToFileMode(); |
950 | | - |
951 | | - if (uploadProgressively) { |
952 | | - var files = Array.prototype.slice.call(e.dataTransfer.files); |
953 | | - uploadProgressively(files); |
954 | 1007 | } else { |
955 | | - fileInput.files = e.dataTransfer.files; |
956 | | - form.submit(); |
| 1008 | + switchToFileMode(); |
| 1009 | + if (uploadProgressively) { |
| 1010 | + uploadProgressively(files); |
| 1011 | + } else { |
| 1012 | + fileInput.files = files; |
| 1013 | + form.submit(); |
| 1014 | + } |
957 | 1015 | } |
958 | | - } |
| 1016 | + }, function () { |
| 1017 | + typeof showUploadDirFailMessage !== strUndef && showUploadDirFailMessage(); |
| 1018 | + }); |
959 | 1019 | } |
960 | 1020 |
|
961 | 1021 | document.body.addEventListener('dragstart', onSelfDragStart); |
|
1066 | 1126 | generatePastedFiles(data); |
1067 | 1127 | return; |
1068 | 1128 | } |
1069 | | - var hasDir = itemsHasDir(items); |
1070 | | - if (hasDir && !canMkdir) { |
1071 | | - typeof showUploadDirFailMessage !== strUndef && showUploadDirFailMessage(); |
1072 | | - return; |
1073 | | - } |
1074 | | - itemsToFiles(items, function (files) { |
| 1129 | + |
| 1130 | + itemsToFiles(items, canMkdir, function (files, hasDir) { |
| 1131 | + // for pasted text |
1075 | 1132 | if (!files.length) { |
1076 | | - // for pasted text |
1077 | 1133 | generatePastedFiles(data); |
1078 | 1134 | return; |
1079 | 1135 | } |
| 1136 | + |
| 1137 | + // suppose for pasted image data |
1080 | 1138 | if (files.length === 1 && files[0].file.type === 'image/png') { |
1081 | | - // suppose for pasted image |
1082 | 1139 | files = files.map(function (fileInfo) { |
1083 | 1140 | return fileInfo && fileInfo.file; |
1084 | 1141 | }); |
1085 | 1142 | generatePastedFiles({files: files}); |
1086 | 1143 | return; |
1087 | 1144 | } |
1088 | | - // pasted real files, not image binary |
| 1145 | + |
| 1146 | + // pasted real files |
1089 | 1147 | if (hasDir) { |
1090 | 1148 | switchToDirMode(); |
1091 | 1149 | } else { |
1092 | 1150 | switchToFileMode(); |
1093 | 1151 | } |
1094 | 1152 | uploadProgressively(files); |
| 1153 | + }, function () { |
| 1154 | + typeof showUploadDirFailMessage !== strUndef && showUploadDirFailMessage(); |
1095 | 1155 | }); |
1096 | 1156 | }); |
1097 | 1157 | } |
|
0 commit comments