app/assets/javascripts/jquery.fileupload.js in uploadbox-0.1.4 vs app/assets/javascripts/jquery.fileupload.js in uploadbox-0.2.0.beta
- old
+ new
@@ -1,18 +1,18 @@
/*
- * jQuery File Upload Plugin 5.32.3
+ * jQuery File Upload Plugin 5.40.1
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2010, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
*/
-/*jslint nomen: true, unparam: true, regexp: true */
-/*global define, window, document, location, File, Blob, FormData */
+/* jshint nomen:false */
+/* global define, window, document, location, Blob, FormData */
(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
@@ -38,13 +38,15 @@
).test(window.navigator.userAgent) ||
// Feature detection for all other devices:
$('<input type="file">').prop('disabled'));
// The FileReader API is not actually used, but works as feature detection,
- // as e.g. Safari supports XHR file uploads via the FormData API,
- // but not non-multipart XHR file uploads:
- $.support.xhrFileUpload = !!(window.XMLHttpRequestUpload && window.FileReader);
+ // as some Safari versions (5?) support XHR file uploads via the FormData API,
+ // but not non-multipart XHR file uploads.
+ // window.XMLHttpRequestUpload is not available on IE10, so we check for
+ // window.ProgressEvent instead to detect XHR2 file upload capability:
+ $.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader);
$.support.xhrFormDataFileUpload = !!window.FormData;
// Detect support for Blob slicing (required for chunked uploads):
$.support.blobSlice = window.Blob && (Blob.prototype.slice ||
Blob.prototype.webkitSlice || Blob.prototype.mozSlice);
@@ -86,10 +88,18 @@
// selections in one request each:
singleFileUploads: true,
// To limit the number of files uploaded with one XHR request,
// set the following option to an integer greater than 0:
limitMultiFileUploads: undefined,
+ // The following option limits the number of files uploaded with one
+ // XHR request to keep the request size under or equal to the defined
+ // limit in bytes:
+ limitMultiFileUploadSize: undefined,
+ // Multipart file uploads add a number of bytes to each uploaded file,
+ // therefore the following option adds an overhead for each file used
+ // in the limitMultiFileUploadSize configuration:
+ limitMultiFileUploadSizeOverhead: 512,
// Set the following option to true to issue all file upload requests
// in a sequential order:
sequentialUploads: false,
// To limit the number of concurrent uploads,
// set the following option to an integer greater than 0:
@@ -172,10 +182,13 @@
//
// data.submit() returns a Promise object and allows to attach additional
// handlers using jQuery's Deferred callbacks:
// data.submit().done(func).fail(func).always(func);
add: function (e, data) {
+ if (e.isDefaultPrevented()) {
+ return false;
+ }
if (data.autoUpload || (data.autoUpload !== false &&
$(this).fileupload('option', 'autoUpload'))) {
data.process().done(function () {
data.submit();
});
@@ -278,11 +291,11 @@
$.support.xhrFormDataFileUpload);
},
_getFormData: function (options) {
var formData;
- if (typeof options.formData === 'function') {
+ if ($.type(options.formData) === 'function') {
return options.formData(options.form);
}
if ($.isArray(options.formData)) {
return options.formData;
}
@@ -358,14 +371,22 @@
data.bitrateInterval
);
// Trigger a custom progress event with a total data property set
// to the file size(s) of the current upload and a loaded data
// property calculated accordingly:
- this._trigger('progress', e, data);
+ this._trigger(
+ 'progress',
+ $.Event('progress', {delegatedEvent: e}),
+ data
+ );
// Trigger a global progress event for all current file uploads,
// including ajax calls queued for sequential file uploads:
- this._trigger('progressall', e, this._progress);
+ this._trigger(
+ 'progressall',
+ $.Event('progressall', {delegatedEvent: e}),
+ this._progress
+ );
}
},
_initProgressListener: function (options) {
var that = this,
@@ -396,21 +417,22 @@
var that = this,
formData,
file = options.files[0],
// Ignore non-multipart setting if not supported:
multipart = options.multipart || !$.support.xhrFileUpload,
- paramName = options.paramName[0];
+ paramName = $.type(options.paramName) === 'array' ?
+ options.paramName[0] : options.paramName;
options.headers = $.extend({}, options.headers);
if (options.contentRange) {
options.headers['Content-Range'] = options.contentRange;
}
if (!multipart || options.blob || !this._isInstanceOf('File', file)) {
options.headers['Content-Disposition'] = 'attachment; filename="' +
encodeURI(file.name) + '"';
}
if (!multipart) {
- options.contentType = file.type;
+ options.contentType = file.type || 'application/octet-stream';
options.data = options.blob || file;
} else if ($.support.xhrFormDataFileUpload) {
if (options.postMessage) {
// window.postMessage does not allow sending FormData
// objects, so we just add the File/Blob objects to
@@ -423,11 +445,12 @@
value: options.blob
});
} else {
$.each(options.files, function (index, file) {
formData.push({
- name: options.paramName[index] || paramName,
+ name: ($.type(options.paramName) === 'array' &&
+ options.paramName[index]) || paramName,
value: file
});
});
}
} else {
@@ -446,13 +469,14 @@
// This check allows the tests to run with
// dummy objects:
if (that._isInstanceOf('File', file) ||
that._isInstanceOf('Blob', file)) {
formData.append(
- options.paramName[index] || paramName,
+ ($.type(options.paramName) === 'array' &&
+ options.paramName[index]) || paramName,
file,
- file.name
+ file.uploadName || file.name
);
}
});
}
}
@@ -532,12 +556,14 @@
options.paramName = this._getParamName(options);
if (!options.url) {
options.url = options.form.prop('action') || location.href;
}
// The HTTP request method must be "POST" or "PUT":
- options.type = (options.type || options.form.prop('method') || '')
- .toUpperCase();
+ options.type = (options.type ||
+ ($.type(options.form.prop('method')) === 'string' &&
+ options.form.prop('method')) || ''
+ ).toUpperCase();
if (options.type !== 'POST' && options.type !== 'PUT' &&
options.type !== 'PATCH') {
options.type = 'POST';
}
if (!options.formAcceptCharset) {
@@ -592,43 +618,59 @@
},
// Adds convenience methods to the data callback argument:
_addConvenienceMethods: function (e, data) {
var that = this,
- getPromise = function (data) {
- return $.Deferred().resolveWith(that, [data]).promise();
+ getPromise = function (args) {
+ return $.Deferred().resolveWith(that, args).promise();
};
data.process = function (resolveFunc, rejectFunc) {
if (resolveFunc || rejectFunc) {
data._processQueue = this._processQueue =
- (this._processQueue || getPromise(this))
- .pipe(resolveFunc, rejectFunc);
+ (this._processQueue || getPromise([this])).pipe(
+ function () {
+ if (data.errorThrown) {
+ return $.Deferred()
+ .rejectWith(that, [data]).promise();
+ }
+ return getPromise(arguments);
+ }
+ ).pipe(resolveFunc, rejectFunc);
}
- return this._processQueue || getPromise(this);
+ return this._processQueue || getPromise([this]);
};
data.submit = function () {
if (this.state() !== 'pending') {
data.jqXHR = this.jqXHR =
- (that._trigger('submit', e, this) !== false) &&
- that._onSend(e, this);
+ (that._trigger(
+ 'submit',
+ $.Event('submit', {delegatedEvent: e}),
+ this
+ ) !== false) && that._onSend(e, this);
}
return this.jqXHR || that._getXHRPromise();
};
data.abort = function () {
if (this.jqXHR) {
return this.jqXHR.abort();
}
- return that._getXHRPromise();
+ this.errorThrown = 'abort';
+ that._trigger('fail', null, this);
+ return that._getXHRPromise(false);
};
data.state = function () {
if (this.jqXHR) {
return that._getDeferredState(this.jqXHR);
}
if (this._processQueue) {
return that._getDeferredState(this._processQueue);
}
};
+ data.processing = function () {
+ return !this.jqXHR && this._processQueue && that
+ ._getDeferredState(this._processQueue) === 'pending';
+ };
data.progress = function () {
return this._progress;
};
data.response = function () {
return this._response;
@@ -827,11 +869,15 @@
send = function () {
that._sending += 1;
// Set timer for bitrate progress calculation:
options._bitrateTimer = new that._BitrateTimer();
jqXHR = jqXHR || (
- ((aborted || that._trigger('send', e, options) === false) &&
+ ((aborted || that._trigger(
+ 'send',
+ $.Event('send', {delegatedEvent: e}),
+ options
+ ) === false) &&
that._getXHRPromise(false, options.context, aborted)) ||
that._chunkedUpload(options) || $.ajax(options)
).done(function (result, textStatus, jqXHR) {
that._onDone(result, textStatus, jqXHR, options);
}).fail(function (jqXHR, textStatus, errorThrown) {
@@ -898,43 +944,74 @@
_onAdd: function (e, data) {
var that = this,
result = true,
options = $.extend({}, this.options, data),
+ files = data.files,
+ filesLength = files.length,
limit = options.limitMultiFileUploads,
+ limitSize = options.limitMultiFileUploadSize,
+ overhead = options.limitMultiFileUploadSizeOverhead,
+ batchSize = 0,
paramName = this._getParamName(options),
paramNameSet,
paramNameSlice,
fileSet,
- i;
- if (!(options.singleFileUploads || limit) ||
+ i,
+ j = 0;
+ if (limitSize && (!filesLength || files[0].size === undefined)) {
+ limitSize = undefined;
+ }
+ if (!(options.singleFileUploads || limit || limitSize) ||
!this._isXHRUpload(options)) {
- fileSet = [data.files];
+ fileSet = [files];
paramNameSet = [paramName];
- } else if (!options.singleFileUploads && limit) {
+ } else if (!(options.singleFileUploads || limitSize) && limit) {
fileSet = [];
paramNameSet = [];
- for (i = 0; i < data.files.length; i += limit) {
- fileSet.push(data.files.slice(i, i + limit));
+ for (i = 0; i < filesLength; i += limit) {
+ fileSet.push(files.slice(i, i + limit));
paramNameSlice = paramName.slice(i, i + limit);
if (!paramNameSlice.length) {
paramNameSlice = paramName;
}
paramNameSet.push(paramNameSlice);
}
+ } else if (!options.singleFileUploads && limitSize) {
+ fileSet = [];
+ paramNameSet = [];
+ for (i = 0; i < filesLength; i = i + 1) {
+ batchSize += files[i].size + overhead;
+ if (i + 1 === filesLength ||
+ ((batchSize + files[i + 1].size + overhead) > limitSize) ||
+ (limit && i + 1 - j >= limit)) {
+ fileSet.push(files.slice(j, i + 1));
+ paramNameSlice = paramName.slice(j, i + 1);
+ if (!paramNameSlice.length) {
+ paramNameSlice = paramName;
+ }
+ paramNameSet.push(paramNameSlice);
+ j = i + 1;
+ batchSize = 0;
+ }
+ }
} else {
paramNameSet = paramName;
}
- data.originalFiles = data.files;
- $.each(fileSet || data.files, function (index, element) {
+ data.originalFiles = files;
+ $.each(fileSet || files, function (index, element) {
var newData = $.extend({}, data);
newData.files = fileSet ? element : [element];
newData.paramName = paramNameSet[index];
that._initResponseObject(newData);
that._initProgressObject(newData);
that._addConvenienceMethods(e, newData);
- result = that._trigger('add', e, newData);
+ result = that._trigger(
+ 'add',
+ $.Event('add', {delegatedEvent: e}),
+ newData
+ );
return result;
});
return result;
},
@@ -1099,11 +1176,15 @@
this._getFileInputFiles(data.fileInput).always(function (files) {
data.files = files;
if (that.options.replaceFileInput) {
that._replaceFileInput(data.fileInput);
}
- if (that._trigger('change', e, data) !== false) {
+ if (that._trigger(
+ 'change',
+ $.Event('change', {delegatedEvent: e}),
+ data
+ ) !== false) {
that._onAdd(e, data);
}
});
},
@@ -1116,13 +1197,16 @@
var file = item.getAsFile && item.getAsFile();
if (file) {
data.files.push(file);
}
});
- if (this._trigger('paste', e, data) === false ||
- this._onAdd(e, data) === false) {
- return false;
+ if (this._trigger(
+ 'paste',
+ $.Event('paste', {delegatedEvent: e}),
+ data
+ ) !== false) {
+ this._onAdd(e, data);
}
}
},
_onDrop: function (e) {
@@ -1132,28 +1216,31 @@
data = {};
if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
e.preventDefault();
this._getDroppedFiles(dataTransfer).always(function (files) {
data.files = files;
- if (that._trigger('drop', e, data) !== false) {
+ if (that._trigger(
+ 'drop',
+ $.Event('drop', {delegatedEvent: e}),
+ data
+ ) !== false) {
that._onAdd(e, data);
}
});
}
},
_onDragOver: function (e) {
e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
var dataTransfer = e.dataTransfer;
- if (dataTransfer) {
- if (this._trigger('dragover', e) === false) {
- return false;
- }
- if ($.inArray('Files', dataTransfer.types) !== -1) {
- dataTransfer.dropEffect = 'copy';
- e.preventDefault();
- }
+ if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 &&
+ this._trigger(
+ 'dragover',
+ $.Event('dragover', {delegatedEvent: e})
+ ) !== false) {
+ e.preventDefault();
+ dataTransfer.dropEffect = 'copy';
}
},
_initEventHandlers: function () {
if (this._isXHRUpload(this.options)) {
@@ -1218,18 +1305,24 @@
/^\/.*\/[igm]{0,3}$/.test(value);
},
_initDataAttributes: function () {
var that = this,
- options = this.options;
+ options = this.options,
+ clone = $(this.element[0].cloneNode(false));
// Initialize options set via HTML5 data-attributes:
$.each(
- $(this.element[0].cloneNode(false)).data(),
+ clone.data(),
function (key, value) {
- if (that._isRegExpOption(key, value)) {
- value = that._getRegExp(value);
+ var dataAttributeName = 'data-' +
+ // Convert camelCase to hyphen-ated key:
+ key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
+ if (clone.attr(dataAttributeName)) {
+ if (that._isRegExpOption(key, value)) {
+ value = that._getRegExp(value);
+ }
+ options[key] = value;
}
- options[key] = value;
}
);
},
_create: function () {