|
1 | 1 | /* |
2 | | - * jQuery File Upload Plugin 5.13 |
| 2 | + * jQuery File Upload Plugin 5.16.1 |
3 | 3 | * https://github.com/blueimp/jQuery-File-Upload |
4 | 4 | * |
5 | 5 | * Copyright 2010, Sebastian Tschan |
|
447 | 447 | if (options.type !== 'POST' && options.type !== 'PUT') { |
448 | 448 | options.type = 'POST'; |
449 | 449 | } |
| 450 | + if (!options.formAcceptCharset) { |
| 451 | + options.formAcceptCharset = options.form.attr('accept-charset'); |
| 452 | + } |
450 | 453 | }, |
451 | 454 |
|
452 | 455 | _getAJAXSettings: function (data) { |
|
663 | 666 | options.limitConcurrentUploads > that._sending) { |
664 | 667 | // Start the next queued upload, |
665 | 668 | // that has not been aborted: |
666 | | - var nextSlot = that._slots.shift(); |
| 669 | + var nextSlot = that._slots.shift(), |
| 670 | + isPending; |
667 | 671 | while (nextSlot) { |
668 | | - if (!nextSlot.isRejected()) { |
| 672 | + // jQuery 1.6 doesn't provide .state(), |
| 673 | + // while jQuery 1.8+ removed .isRejected(): |
| 674 | + isPending = nextSlot.state ? |
| 675 | + nextSlot.state() === 'pending' : |
| 676 | + !nextSlot.isRejected(); |
| 677 | + if (isPending) { |
669 | 678 | nextSlot.resolve(); |
670 | 679 | break; |
671 | 680 | } |
|
693 | 702 | var args = [undefined, 'abort', 'abort']; |
694 | 703 | if (!jqXHR) { |
695 | 704 | if (slot) { |
696 | | - slot.rejectWith(args); |
| 705 | + slot.rejectWith(pipe, args); |
697 | 706 | } |
698 | 707 | return send(false, args); |
699 | 708 | } |
|
748 | 757 | return result; |
749 | 758 | }, |
750 | 759 |
|
751 | | - // File Normalization for Gecko 1.9.1 (Firefox 3.5) support: |
752 | | - _normalizeFile: function (index, file) { |
753 | | - if (file.name === undefined && file.size === undefined) { |
754 | | - file.name = file.fileName; |
755 | | - file.size = file.fileSize; |
756 | | - } |
757 | | - }, |
758 | | - |
759 | 760 | _replaceFileInput: function (input) { |
760 | 761 | var inputClone = input.clone(true); |
761 | 762 | $('<form></form>').append(inputClone)[0].reset(); |
|
780 | 781 | } |
781 | 782 | }, |
782 | 783 |
|
| 784 | + _handleFileTreeEntry: function (entry, path) { |
| 785 | + var that = this, |
| 786 | + dfd = $.Deferred(), |
| 787 | + errorHandler = function () { |
| 788 | + dfd.reject(); |
| 789 | + }, |
| 790 | + dirReader; |
| 791 | + path = path || ''; |
| 792 | + if (entry.isFile) { |
| 793 | + entry.file(function (file) { |
| 794 | + file.relativePath = path; |
| 795 | + dfd.resolve(file); |
| 796 | + }, errorHandler); |
| 797 | + } else if (entry.isDirectory) { |
| 798 | + dirReader = entry.createReader(); |
| 799 | + dirReader.readEntries(function (entries) { |
| 800 | + that._handleFileTreeEntries( |
| 801 | + entries, |
| 802 | + path + entry.name + '/' |
| 803 | + ).done(function (files) { |
| 804 | + dfd.resolve(files); |
| 805 | + }).fail(errorHandler); |
| 806 | + }, errorHandler); |
| 807 | + } else { |
| 808 | + errorHandler(); |
| 809 | + } |
| 810 | + return dfd.promise(); |
| 811 | + }, |
| 812 | + |
| 813 | + _handleFileTreeEntries: function (entries, path) { |
| 814 | + var that = this; |
| 815 | + return $.when.apply( |
| 816 | + $, |
| 817 | + $.map(entries, function (entry) { |
| 818 | + return that._handleFileTreeEntry(entry, path); |
| 819 | + }) |
| 820 | + ).pipe(function () { |
| 821 | + return Array.prototype.concat.apply( |
| 822 | + [], |
| 823 | + arguments |
| 824 | + ); |
| 825 | + }); |
| 826 | + }, |
| 827 | + |
| 828 | + _getDroppedFiles: function (dataTransfer) { |
| 829 | + dataTransfer = dataTransfer || {}; |
| 830 | + var items = dataTransfer.items; |
| 831 | + if (items && items.length && (items[0].webkitGetAsEntry || |
| 832 | + items[0].getAsEntry)) { |
| 833 | + return this._handleFileTreeEntries( |
| 834 | + $.map(items, function (item) { |
| 835 | + if (item.webkitGetAsEntry) { |
| 836 | + return item.webkitGetAsEntry(); |
| 837 | + } |
| 838 | + return item.getAsEntry(); |
| 839 | + }) |
| 840 | + ); |
| 841 | + } |
| 842 | + return $.Deferred().resolve( |
| 843 | + $.makeArray(dataTransfer.files) |
| 844 | + ).promise(); |
| 845 | + }, |
| 846 | + |
783 | 847 | _getFileInputFiles: function (fileInput) { |
784 | 848 | fileInput = $(fileInput); |
785 | | - var files = $.each($.makeArray(fileInput.prop('files')), this._normalizeFile), |
| 849 | + var entries = fileInput.prop('webkitEntries') || |
| 850 | + fileInput.prop('entries'), |
| 851 | + files, |
786 | 852 | value; |
| 853 | + if (entries) { |
| 854 | + return this._handleFileTreeEntries(entries); |
| 855 | + } |
| 856 | + files = $.makeArray(fileInput.prop('files')); |
787 | 857 | if (!files.length) { |
788 | 858 | value = fileInput.prop('value'); |
789 | 859 | if (!value) { |
790 | | - return []; |
| 860 | + return $.Deferred().reject([]).promise(); |
791 | 861 | } |
792 | 862 | // If the files property is not available, the browser does not |
793 | 863 | // support the File API and we add a pseudo File object with |
794 | 864 | // the input value as name with path information removed: |
795 | 865 | files = [{name: value.replace(/^.*\\/, '')}]; |
796 | 866 | } |
797 | | - return files; |
| 867 | + return $.Deferred().resolve(files).promise(); |
798 | 868 | }, |
799 | 869 |
|
800 | 870 | _onChange: function (e) { |
|
803 | 873 | fileInput: $(e.target), |
804 | 874 | form: $(e.target.form) |
805 | 875 | }; |
806 | | - data.files = that._getFileInputFiles(data.fileInput); |
807 | | - if (that.options.replaceFileInput) { |
808 | | - that._replaceFileInput(data.fileInput); |
809 | | - } |
810 | | - if (that._trigger('change', e, data) === false || |
811 | | - that._onAdd(e, data) === false) { |
812 | | - return false; |
813 | | - } |
| 876 | + that._getFileInputFiles(data.fileInput).always(function (files) { |
| 877 | + data.files = files; |
| 878 | + if (that.options.replaceFileInput) { |
| 879 | + that._replaceFileInput(data.fileInput); |
| 880 | + } |
| 881 | + if (that._trigger('change', e, data) !== false) { |
| 882 | + that._onAdd(e, data); |
| 883 | + } |
| 884 | + }); |
814 | 885 | }, |
815 | 886 |
|
816 | 887 | _onPaste: function (e) { |
|
831 | 902 | }, |
832 | 903 |
|
833 | 904 | _onDrop: function (e) { |
| 905 | + e.preventDefault(); |
834 | 906 | var that = e.data.fileupload, |
835 | 907 | dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer, |
836 | | - data = { |
837 | | - files: $.each( |
838 | | - $.makeArray(dataTransfer && dataTransfer.files), |
839 | | - that._normalizeFile |
840 | | - ) |
841 | | - }; |
842 | | - if (that._trigger('drop', e, data) === false || |
843 | | - that._onAdd(e, data) === false) { |
844 | | - return false; |
845 | | - } |
846 | | - e.preventDefault(); |
| 908 | + data = {}; |
| 909 | + that._getDroppedFiles(dataTransfer).always(function (files) { |
| 910 | + data.files = files; |
| 911 | + if (that._trigger('drop', e, data) !== false) { |
| 912 | + that._onAdd(e, data); |
| 913 | + } |
| 914 | + }); |
847 | 915 | }, |
848 | 916 |
|
849 | 917 | _onDragOver: function (e) { |
|
937 | 1005 | // must have a files property and can contain additional options: |
938 | 1006 | // .fileupload('add', {files: filesList}); |
939 | 1007 | add: function (data) { |
| 1008 | + var that = this; |
940 | 1009 | if (!data || this.options.disabled) { |
941 | 1010 | return; |
942 | 1011 | } |
943 | 1012 | if (data.fileInput && !data.files) { |
944 | | - data.files = this._getFileInputFiles(data.fileInput); |
| 1013 | + this._getFileInputFiles(data.fileInput).always(function (files) { |
| 1014 | + data.files = files; |
| 1015 | + that._onAdd(null, data); |
| 1016 | + }); |
945 | 1017 | } else { |
946 | | - data.files = $.each($.makeArray(data.files), this._normalizeFile); |
| 1018 | + data.files = $.makeArray(data.files); |
| 1019 | + this._onAdd(null, data); |
947 | 1020 | } |
948 | | - this._onAdd(null, data); |
949 | 1021 | }, |
950 | 1022 |
|
951 | 1023 | // This method is exposed to the widget API and allows sending files |
952 | 1024 | // using the fileupload API. The data parameter accepts an object which |
953 | | - // must have a files property and can contain additional options: |
| 1025 | + // must have a files or fileInput property and can contain additional options: |
954 | 1026 | // .fileupload('send', {files: filesList}); |
955 | 1027 | // The method returns a Promise object for the file upload call. |
956 | 1028 | send: function (data) { |
957 | 1029 | if (data && !this.options.disabled) { |
958 | 1030 | if (data.fileInput && !data.files) { |
959 | | - data.files = this._getFileInputFiles(data.fileInput); |
960 | | - } else { |
961 | | - data.files = $.each($.makeArray(data.files), this._normalizeFile); |
| 1031 | + var that = this, |
| 1032 | + dfd = $.Deferred(), |
| 1033 | + promise = dfd.promise(), |
| 1034 | + jqXHR, |
| 1035 | + aborted; |
| 1036 | + promise.abort = function () { |
| 1037 | + aborted = true; |
| 1038 | + if (jqXHR) { |
| 1039 | + return jqXHR.abort(); |
| 1040 | + } |
| 1041 | + dfd.reject(null, 'abort', 'abort'); |
| 1042 | + return promise; |
| 1043 | + }; |
| 1044 | + this._getFileInputFiles(data.fileInput).always( |
| 1045 | + function (files) { |
| 1046 | + if (aborted) { |
| 1047 | + return; |
| 1048 | + } |
| 1049 | + data.files = files; |
| 1050 | + jqXHR = that._onSend(null, data).then( |
| 1051 | + function (result, textStatus, jqXHR) { |
| 1052 | + dfd.resolve(result, textStatus, jqXHR); |
| 1053 | + }, |
| 1054 | + function (jqXHR, textStatus, errorThrown) { |
| 1055 | + dfd.reject(jqXHR, textStatus, errorThrown); |
| 1056 | + } |
| 1057 | + ); |
| 1058 | + } |
| 1059 | + ); |
| 1060 | + return this._enhancePromise(promise); |
962 | 1061 | } |
| 1062 | + data.files = $.makeArray(data.files); |
963 | 1063 | if (data.files.length) { |
964 | 1064 | return this._onSend(null, data); |
965 | 1065 | } |
|
0 commit comments