pure-upload
Advanced tools
Comparing version 4.2.1 to 5.0.0
@@ -1,40 +0,43 @@ | ||
CHANGELOG | ||
=== | ||
4.2.1 | ||
-- | ||
# CHANGELOG | ||
## 5.0.0 | ||
Updated environment. | ||
Updated TS to 2.7.2. | ||
Higher restrictions. | ||
Prettier. | ||
## 4.2.1 | ||
Improved internal type definitions and casting | ||
4.2.0 | ||
-- | ||
## 4.2.0 | ||
Added highlighting on dnd. | ||
4.1.0 | ||
-- | ||
## 4.1.0 | ||
Added option to allow upload of empty files | ||
4.0.1 | ||
-- | ||
Fix | ||
- | ||
## 4.0.1 | ||
## Fix | ||
Options access modifier reverted to public. | ||
4.0.0 | ||
-- | ||
Changed localizations | ||
- | ||
## 4.0.0 | ||
## Changed localizations | ||
Localizations are now accessible through new options property with specific errors. | ||
3.0.0 | ||
-- | ||
Cleaning | ||
- | ||
## 3.0.0 | ||
## Cleaning | ||
Removed compatibility parts for obsolette browser without FileAPI. | ||
## 2.2.3 | ||
2.2.3 | ||
-- | ||
Fix | ||
- | ||
## Fix | ||
@@ -44,53 +47,40 @@ Removed duplications when same file is adding many times to queue. | ||
2.2.2 | ||
-- | ||
Fix | ||
- | ||
## 2.2.2 | ||
## Fix | ||
Automatic clearing of manual upload file list after puting to queue is done on parameter. | ||
2.2.0 | ||
-- | ||
New features | ||
- | ||
## 2.2.0 | ||
## New features | ||
Added manual triggering of adding file to UploadQueue in UploadArea. | ||
## 2.1.0 | ||
2.1.0 | ||
-- | ||
New features | ||
- | ||
## New features | ||
Added offset for batches limited by max uploading file count. | ||
## 2.0.5 - 2.0.8 | ||
2.0.5 - 2.0.8 | ||
-- | ||
Fixes | ||
## 2.0.4 | ||
2.0.4 | ||
-- | ||
## Fixes | ||
Fixes | ||
- | ||
Modified update progress condition to not throw in IE. | ||
2.0.3 | ||
-- | ||
## 2.0.3 | ||
Fixes | ||
- | ||
## Fixes | ||
Url is now loaded on file adding instead of request creating. | ||
2.0.2 | ||
-- | ||
## 2.0.2 | ||
New features | ||
- | ||
## New features | ||
Added onFileCanceled for UploadArea |
380
index.js
@@ -10,3 +10,3 @@ "use strict"; | ||
if (elem.attachEvent) { | ||
elem.attachEvent('on' + event, handler); | ||
elem.attachEvent("on" + event, handler); | ||
} | ||
@@ -22,5 +22,5 @@ else { | ||
var files; | ||
if (typeof fileList === 'object') { | ||
if (typeof fileList === "object") { | ||
files = Object.keys(fileList) | ||
.filter(function (key) { return key !== 'length'; }) | ||
.filter(function (key) { return key !== "length"; }) | ||
.map(function (key) { return fileList[key]; }); | ||
@@ -34,6 +34,10 @@ } | ||
file.responseCode = file.responseCode || 0; | ||
file.responseText = file.responseText || ''; | ||
file.responseText = file.responseText || ""; | ||
file.progress = file.progress || 0; | ||
file.sentBytes = file.sentBytes || 0; | ||
file.cancel = file.cancel || (function () { return; }); | ||
file.cancel = | ||
file.cancel || | ||
(function () { | ||
return; | ||
}); | ||
}); | ||
@@ -48,4 +52,10 @@ return files; | ||
return newFirst | ||
? function () { newFn(); origFn(); } | ||
: function () { origFn(); newFn(); }; | ||
? function () { | ||
newFn(); | ||
origFn(); | ||
} | ||
: function () { | ||
origFn(); | ||
newFn(); | ||
}; | ||
} | ||
@@ -56,3 +66,4 @@ exports.decorateSimpleFunction = decorateSimpleFunction; | ||
for (var nextKey in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, nextKey) && (to[nextKey] === undefined || to[nextKey] === null)) { | ||
if (Object.prototype.hasOwnProperty.call(source, nextKey) && | ||
(to[nextKey] === undefined || to[nextKey] === null)) { | ||
to[nextKey] = source[nextKey]; | ||
@@ -63,3 +74,2 @@ } | ||
} | ||
; | ||
function getUploadCore(options, callbacks) { | ||
@@ -69,3 +79,2 @@ return new UploadCore(options, callbacks); | ||
exports.getUploadCore = getUploadCore; | ||
; | ||
function getUploader(options, callbacks) { | ||
@@ -75,5 +84,4 @@ return new Uploader(options, callbacks); | ||
exports.getUploader = getUploader; | ||
; | ||
function getValueOrResult(valueOrGetter) { | ||
if (typeof valueOrGetter === 'function') | ||
if (typeof valueOrGetter === "function") | ||
return valueOrGetter(); | ||
@@ -85,7 +93,7 @@ return valueOrGetter; | ||
var d = new Date().getTime(); | ||
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { | ||
var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { | ||
/* tslint:disable */ | ||
var r = (d + Math.random() * 16) % 16 | 0; | ||
var r = ((d + Math.random() * 16) % 16) | 0; | ||
d = Math.floor(d / 16); | ||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); | ||
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16); | ||
/* tslint:enable */ | ||
@@ -96,9 +104,15 @@ }); | ||
exports.newGuid = newGuid; | ||
; | ||
function getDefaultLocalizer() { | ||
return { | ||
fileSizeInvalid: function (maxFileSize) { return 'The selected file exceeds the allowed size of ' + maxFileSize | ||
+ ' or its size is 0 MB. Please choose another file.'; }, | ||
fileTypeInvalid: function (accept) { return 'File format is not allowed. Only ' + (accept ? accept : '') + ' files are allowed.'; }, | ||
invalidResponseFromServer: function () { return 'Invalid response from server'; } | ||
fileSizeInvalid: function (maxFileSize) { | ||
return "The selected file exceeds the allowed size of " + | ||
maxFileSize + | ||
" or its size is 0 MB. Please choose another file."; | ||
}, | ||
fileTypeInvalid: function (accept) { | ||
return "File format is not allowed. Only " + | ||
(accept ? accept : "") + | ||
" files are allowed."; | ||
}, | ||
invalidResponseFromServer: function () { return "Invalid response from server"; } | ||
}; | ||
@@ -113,3 +127,3 @@ } | ||
if (elem.detachEvent) { | ||
elem.detachEvent('on' + event, handler); | ||
elem.detachEvent("on" + event, handler); | ||
} | ||
@@ -122,3 +136,3 @@ else { | ||
exports.removeEventHandler = removeEventHandler; | ||
var UploadArea = (function () { | ||
var UploadArea = /** @class */ (function () { | ||
function UploadArea(targetElement, options, uploader) { | ||
@@ -133,3 +147,3 @@ this.targetElement = targetElement; | ||
else { | ||
throw 'Only browsers with FileAPI supported.'; | ||
throw "Only browsers with FileAPI supported."; | ||
} | ||
@@ -163,3 +177,4 @@ } | ||
this.unregisterOnDragLeaveGlobal(); | ||
document.body.removeChild(this.fileInput); | ||
if (this.fileInput) | ||
document.body.removeChild(this.fileInput); | ||
}; | ||
@@ -172,3 +187,3 @@ UploadArea.prototype.defaultOptions = function () { | ||
clickable: true, | ||
accept: '*.*', | ||
accept: "*.*", | ||
validateExtension: false, | ||
@@ -198,4 +213,4 @@ multiple: true, | ||
file.url = _this.uploadCore.getUrl(file); | ||
file.onError = _this.options.onFileError || (function () { ; }); | ||
file.onCancel = _this.options.onFileCanceled || (function () { ; }); | ||
file.onError = _this.options.onFileError || (function () { }); | ||
file.onCancel = _this.options.onFileCanceled || (function () { }); | ||
if (_this.validateFile(file)) { | ||
@@ -207,3 +222,5 @@ file.start = function () { | ||
} | ||
file.start = function () { return; }; | ||
file.start = function () { | ||
return; | ||
}; | ||
}; | ||
@@ -232,11 +249,14 @@ } | ||
var _this = this; | ||
this.fileInput = document.createElement('input'); | ||
this.fileInput.setAttribute('type', 'file'); | ||
this.fileInput.setAttribute('accept', this.options.accept ? this.options.accept : ''); | ||
this.fileInput.style.display = 'none'; | ||
this.fileInput = document.createElement("input"); | ||
this.fileInput.setAttribute("type", "file"); | ||
this.fileInput.setAttribute("accept", this.options.accept ? this.options.accept : ""); | ||
this.fileInput.style.display = "none"; | ||
var onChange = function (e) { return _this.onChange(e); }; | ||
addEventHandler(this.fileInput, 'change', onChange); | ||
this.unregisterOnChange = function () { return removeEventHandler(_this.fileInput, 'change', onchange); }; | ||
addEventHandler(this.fileInput, "change", onChange); | ||
this.unregisterOnChange = function () { | ||
if (_this.fileInput) | ||
removeEventHandler(_this.fileInput, "change", onchange); | ||
}; | ||
if (this.options.multiple) { | ||
this.fileInput.setAttribute('multiple', ''); | ||
this.fileInput.setAttribute("multiple", ""); | ||
} | ||
@@ -250,19 +270,35 @@ this.registerEvents(); | ||
var onClick = function () { return _this.onClick(); }; | ||
addEventHandler(this.targetElement, 'click', onClick); | ||
this.unregisterOnClick = function () { return removeEventHandler(_this.targetElement, 'click', onClick); }; | ||
var onDrag = function (e) { return _this.onDrag(e); }; | ||
addEventHandler(this.targetElement, 'dragover', onDrag); | ||
this.unregisterOnDragOver = function () { return removeEventHandler(_this.targetElement, 'dragover', onDrag); }; | ||
addEventHandler(this.targetElement, "click", onClick); | ||
this.unregisterOnClick = function () { | ||
return removeEventHandler(_this.targetElement, "click", onClick); | ||
}; | ||
var onDrag = (function (e) { | ||
return _this.onDrag(e); | ||
}); | ||
addEventHandler(this.targetElement, "dragover", onDrag); | ||
this.unregisterOnDragOver = function () { | ||
return removeEventHandler(_this.targetElement, "dragover", onDrag); | ||
}; | ||
var onDragLeave = function () { return _this.onDragLeave(); }; | ||
addEventHandler(this.targetElement, 'dragleave', onDragLeave); | ||
this.unregisterOnDragOver = function () { return removeEventHandler(_this.targetElement, 'dragleave', onDragLeave); }; | ||
addEventHandler(this.targetElement, "dragleave", onDragLeave); | ||
this.unregisterOnDragOver = function () { | ||
return removeEventHandler(_this.targetElement, "dragleave", onDragLeave); | ||
}; | ||
var onDragGlobal = function () { return _this.onDragGlobal(); }; | ||
addEventHandler(document.body, 'dragover', onDragGlobal); | ||
this.unregisterOnDragOverGlobal = function () { return removeEventHandler(document.body, 'dragover', onDragGlobal); }; | ||
addEventHandler(document.body, "dragover", onDragGlobal); | ||
this.unregisterOnDragOverGlobal = function () { | ||
return removeEventHandler(document.body, "dragover", onDragGlobal); | ||
}; | ||
var onDragLeaveGlobal = function () { return _this.onDragLeaveGlobal(); }; | ||
addEventHandler(document.body, 'dragleave', onDragLeaveGlobal); | ||
this.unregisterOnDragOverGlobal = function () { return removeEventHandler(document.body, 'dragleave', onDragLeaveGlobal); }; | ||
var onDrop = function (e) { return _this.onDrop(e); }; | ||
addEventHandler(this.targetElement, 'drop', onDrop); | ||
this.unregisterOnDrop = function () { return removeEventHandler(_this.targetElement, 'drop', onDrop); }; | ||
addEventHandler(document.body, "dragleave", onDragLeaveGlobal); | ||
this.unregisterOnDragOverGlobal = function () { | ||
return removeEventHandler(document.body, "dragleave", onDragLeaveGlobal); | ||
}; | ||
var onDrop = (function (e) { | ||
return _this.onDrop(e); | ||
}); | ||
addEventHandler(this.targetElement, "drop", onDrop); | ||
this.unregisterOnDrop = function () { | ||
return removeEventHandler(_this.targetElement, "drop", onDrop); | ||
}; | ||
}; | ||
@@ -280,6 +316,5 @@ UploadArea.prototype.onChange = function (e) { | ||
} | ||
catch (err) { | ||
; | ||
} | ||
e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; | ||
catch (err) { } | ||
e.dataTransfer.dropEffect = | ||
"move" === efct || "linkMove" === efct ? "move" : "copy"; | ||
this.stopEventPropagation(e); | ||
@@ -325,3 +360,5 @@ }; | ||
var items = e.dataTransfer.items; | ||
if (items && items.length && (items[0].webkitGetAsEntry !== null)) { | ||
if (items && | ||
items.length && | ||
items[0].webkitGetAsEntry !== null) { | ||
if (!this.options.multiple) { | ||
@@ -341,11 +378,14 @@ var newItems = [items[0]]; | ||
UploadArea.prototype.isIeVersion = function (v) { | ||
return RegExp('msie' + (!isNaN(v) ? ('\\s' + v.toString()) : ''), 'i').test(navigator.userAgent); | ||
return RegExp("msie" + (!isNaN(v) ? "\\s" + v.toString() : ""), "i").test(navigator.userAgent); | ||
}; | ||
UploadArea.prototype.onClick = function () { | ||
var _this = this; | ||
if (!getValueOrResult(this.options.clickable)) | ||
if (!getValueOrResult(this.options.clickable) || !this.fileInput) | ||
return; | ||
this.fileInput.value = ''; | ||
this.fileInput.value = ""; | ||
if (this.isIeVersion(10)) { | ||
setTimeout(function () { _this.fileInput.click(); }, 200); | ||
setTimeout(function () { | ||
if (_this.fileInput) | ||
_this.fileInput.click(); | ||
}, 200); | ||
} | ||
@@ -360,3 +400,4 @@ else { | ||
var item = items[i]; | ||
if ((item.webkitGetAsEntry) && (entry = item.webkitGetAsEntry())) { | ||
if (item.webkitGetAsEntry && | ||
(entry = item.webkitGetAsEntry())) { | ||
if (entry.isFile) { | ||
@@ -370,3 +411,3 @@ this.selectFiles([item.getAsFile()]); | ||
else if (item.getAsFile) { | ||
if (!item.kind || item.kind === 'file') { | ||
if (!item.kind || item.kind === "file") { | ||
this.selectFiles([item.getAsFile()]); | ||
@@ -385,6 +426,6 @@ } | ||
entry.file(function (file) { | ||
if (file.name.substring(0, 1) === '.') { | ||
if (file.name.substring(0, 1) === ".") { | ||
return; | ||
} | ||
file.fullPath = '' + path + '/' + file.name; | ||
file.fullPath = "" + path + "/" + file.name; | ||
self.selectFiles([file]); | ||
@@ -394,3 +435,3 @@ }); | ||
else if (entry.isDirectory) { | ||
self.processDirectory(entry, '' + path + '/' + entry.name); | ||
self.processDirectory(entry, "" + path + "/" + entry.name); | ||
} | ||
@@ -400,4 +441,4 @@ } | ||
dirReader.readEntries(entryReader, function (error) { | ||
return typeof console !== 'undefined' && console !== null | ||
? typeof console.log === 'function' ? console.log(error) : void 0 | ||
return typeof console !== "undefined" && console !== null | ||
? typeof console.log === "function" ? console.log(error) : void 0 | ||
: void 0; | ||
@@ -413,3 +454,4 @@ }); | ||
var maxFileSize = this.options.maxFileSize * 1024 * 1024; // max file size in bytes | ||
if (file.size > maxFileSize || (!this.options.allowEmptyFile && file.size === 0)) | ||
if (file.size > maxFileSize || | ||
(!this.options.allowEmptyFile && file.size === 0)) | ||
return false; | ||
@@ -419,11 +461,16 @@ return true; | ||
UploadArea.prototype.isFileTypeInvalid = function (file) { | ||
if (file.name && this.options.accept && (this.options.accept.trim() !== '*' || this.options.accept.trim() !== '*.*') && | ||
this.options.validateExtension && this.options.accept.indexOf('/') === -1) { | ||
var acceptedExtensions = this.options.accept.split(','); | ||
var fileExtension = file.name.substring(file.name.lastIndexOf('.'), file.name.length); | ||
if (fileExtension.indexOf('.') === -1) | ||
if (file.name && | ||
this.options.accept && | ||
(this.options.accept.trim() !== "*" || | ||
this.options.accept.trim() !== "*.*") && | ||
this.options.validateExtension && | ||
this.options.accept.indexOf("/") === -1) { | ||
var acceptedExtensions = this.options.accept.split(","); | ||
var fileExtension = file.name.substring(file.name.lastIndexOf("."), file.name.length); | ||
if (fileExtension.indexOf(".") === -1) | ||
return true; | ||
var isFileExtensionExisted = true; | ||
for (var i = 0; i < acceptedExtensions.length; i++) { | ||
if (acceptedExtensions[i].toUpperCase().trim() === fileExtension.toUpperCase()) { | ||
if (acceptedExtensions[i].toUpperCase().trim() === | ||
fileExtension.toUpperCase()) { | ||
isFileExtensionExisted = false; | ||
@@ -448,3 +495,3 @@ } | ||
exports.UploadArea = UploadArea; | ||
var UploadCore = (function () { | ||
var UploadCore = /** @class */ (function () { | ||
function UploadCore(options, callbacks) { | ||
@@ -464,3 +511,3 @@ if (callbacks === void 0) { callbacks = {}; } | ||
UploadCore.prototype.getUrl = function (file) { | ||
return typeof this.options.url === 'function' | ||
return typeof this.options.url === "function" | ||
? this.options.url(file) | ||
@@ -486,8 +533,8 @@ : this.options.url; | ||
return; | ||
if (!this.options.headers['Accept']) | ||
xhr.setRequestHeader('Accept', 'application/json'); | ||
if (!this.options.headers['Cache-Control']) | ||
xhr.setRequestHeader('Cache-Control', 'no-cache'); | ||
if (!this.options.headers['X-Requested-With']) | ||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); | ||
if (!this.options.headers["Accept"]) | ||
xhr.setRequestHeader("Accept", "application/json"); | ||
if (!this.options.headers["Cache-Control"]) | ||
xhr.setRequestHeader("Cache-Control", "no-cache"); | ||
if (!this.options.headers["X-Requested-With"]) | ||
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); | ||
Object.keys(this.options.headers).forEach(function (headerName) { | ||
@@ -498,3 +545,3 @@ if (!_this.options.headers) | ||
if (headerValue !== undefined && headerValue !== null) | ||
xhr.setRequestHeader(headerName, (headerValue || '').toString()); | ||
xhr.setRequestHeader(headerName, (headerValue || "").toString()); | ||
}); | ||
@@ -540,13 +587,15 @@ }; | ||
} | ||
formData.append('file', file, file.name); | ||
formData.append("file", file, file.name); | ||
return formData; | ||
}; | ||
UploadCore.prototype.castParamType = function (param) { | ||
return this.isBoolean(param) || this.isNumber(param) ? param.toString() : param; | ||
return this.isBoolean(param) || this.isNumber(param) | ||
? param.toString() | ||
: param; | ||
}; | ||
UploadCore.prototype.isNumber = function (param) { | ||
return typeof param === 'number'; | ||
return typeof param === "number"; | ||
}; | ||
UploadCore.prototype.isBoolean = function (param) { | ||
return typeof param === 'number'; | ||
return typeof param === "number"; | ||
}; | ||
@@ -606,8 +655,10 @@ UploadCore.prototype.handleError = function (file, xhr) { | ||
}; | ||
; | ||
UploadCore.prototype.setResponse = function (file, xhr) { | ||
file.responseCode = xhr.status; | ||
file.responseText = xhr.responseText || xhr.statusText || (xhr.status | ||
? xhr.status.toString() | ||
: '' || this.options.localizer.invalidResponseFromServer()); | ||
file.responseText = | ||
xhr.responseText || | ||
xhr.statusText || | ||
(xhr.status | ||
? xhr.status.toString() | ||
: "" || this.options.localizer.invalidResponseFromServer()); | ||
}; | ||
@@ -623,9 +674,37 @@ UploadCore.prototype.getDefaultOptions = function () { | ||
UploadCore.prototype.setFullCallbacks = function (callbacks) { | ||
this.callbacks.onProgressCallback = callbacks.onProgressCallback || (function () { return; }); | ||
this.callbacks.onCancelledCallback = callbacks.onCancelledCallback || (function () { return; }); | ||
this.callbacks.onFinishedCallback = callbacks.onFinishedCallback || (function () { return; }); | ||
this.callbacks.onUploadedCallback = callbacks.onUploadedCallback || (function () { return; }); | ||
this.callbacks.onErrorCallback = callbacks.onErrorCallback || (function () { return; }); | ||
this.callbacks.onUploadStartedCallback = callbacks.onUploadStartedCallback || (function () { return; }); | ||
this.callbacks.onFileStateChangedCallback = callbacks.onFileStateChangedCallback || (function () { return; }); | ||
this.callbacks.onProgressCallback = | ||
callbacks.onProgressCallback || | ||
(function () { | ||
return; | ||
}); | ||
this.callbacks.onCancelledCallback = | ||
callbacks.onCancelledCallback || | ||
(function () { | ||
return; | ||
}); | ||
this.callbacks.onFinishedCallback = | ||
callbacks.onFinishedCallback || | ||
(function () { | ||
return; | ||
}); | ||
this.callbacks.onUploadedCallback = | ||
callbacks.onUploadedCallback || | ||
(function () { | ||
return; | ||
}); | ||
this.callbacks.onErrorCallback = | ||
callbacks.onErrorCallback || | ||
(function () { | ||
return; | ||
}); | ||
this.callbacks.onUploadStartedCallback = | ||
callbacks.onUploadStartedCallback || | ||
(function () { | ||
return; | ||
}); | ||
this.callbacks.onFileStateChangedCallback = | ||
callbacks.onFileStateChangedCallback || | ||
(function () { | ||
return; | ||
}); | ||
}; | ||
@@ -635,29 +714,3 @@ return UploadCore; | ||
exports.UploadCore = UploadCore; | ||
var Uploader = (function () { | ||
function Uploader(options, callbacks) { | ||
if (options === void 0) { options = {}; } | ||
if (callbacks === void 0) { callbacks = {}; } | ||
this.setOptions(options); | ||
this.uploadAreas = []; | ||
this.queue = new UploadQueue(options, callbacks); | ||
} | ||
Uploader.prototype.setOptions = function (options) { | ||
this.options = options; | ||
}; | ||
Uploader.prototype.registerArea = function (element, options) { | ||
var uploadArea = new UploadArea(element, options, this); | ||
this.uploadAreas.push(uploadArea); | ||
return uploadArea; | ||
}; | ||
Uploader.prototype.unregisterArea = function (area) { | ||
var areaIndex = this.uploadAreas.indexOf(area); | ||
if (areaIndex >= 0) { | ||
this.uploadAreas[areaIndex].destroy(); | ||
this.uploadAreas.splice(areaIndex, 1); | ||
} | ||
}; | ||
return Uploader; | ||
}()); | ||
exports.Uploader = Uploader; | ||
var UploadQueue = (function () { | ||
var UploadQueue = /** @class */ (function () { | ||
function UploadQueue(options, callbacks) { | ||
@@ -674,3 +727,6 @@ this.offset = { fileCount: 0, running: false }; | ||
files.forEach(function (file) { | ||
if (!_this.queuedFiles.some(function (queuedFile) { return queuedFile === file || (!!queuedFile.guid && queuedFile.guid === file.guid); })) { | ||
if (!_this.queuedFiles.some(function (queuedFile) { | ||
return queuedFile === file || | ||
(!!queuedFile.guid && queuedFile.guid === file.guid); | ||
})) { | ||
_this.queuedFiles.push(file); | ||
@@ -711,3 +767,6 @@ file.remove = decorateSimpleFunction(file.remove, function () { | ||
if (!cancelProcessing) | ||
excludeStatuses = excludeStatuses.concat([UploadStatus.queued, UploadStatus.uploading]); | ||
excludeStatuses = excludeStatuses.concat([ | ||
UploadStatus.queued, | ||
UploadStatus.uploading | ||
]); | ||
this.queuedFiles | ||
@@ -729,4 +788,5 @@ .filter(function (file) { return excludeStatuses.indexOf(file.uploadStatus) < 0; }) | ||
UploadQueue.prototype.checkAllFinished = function () { | ||
var unfinishedFiles = this.queuedFiles | ||
.filter(function (file) { return [UploadStatus.queued, UploadStatus.uploading].indexOf(file.uploadStatus) >= 0; }); | ||
var unfinishedFiles = this.queuedFiles.filter(function (file) { | ||
return [UploadStatus.queued, UploadStatus.uploading].indexOf(file.uploadStatus) >= 0; | ||
}); | ||
if (unfinishedFiles.length === 0 && this.callbacks.onAllFinishedCallback) { | ||
@@ -744,6 +804,22 @@ this.callbacks.onAllFinishedCallback(); | ||
var _this = this; | ||
this.callbacks.onFileAddedCallback = this.callbacks.onFileAddedCallback || (function () { return; }); | ||
this.callbacks.onFileRemovedCallback = this.callbacks.onFileRemovedCallback || (function () { return; }); | ||
this.callbacks.onAllFinishedCallback = this.callbacks.onAllFinishedCallback || (function () { return; }); | ||
this.callbacks.onQueueChangedCallback = this.callbacks.onQueueChangedCallback || (function () { return; }); | ||
this.callbacks.onFileAddedCallback = | ||
this.callbacks.onFileAddedCallback || | ||
(function () { | ||
return; | ||
}); | ||
this.callbacks.onFileRemovedCallback = | ||
this.callbacks.onFileRemovedCallback || | ||
(function () { | ||
return; | ||
}); | ||
this.callbacks.onAllFinishedCallback = | ||
this.callbacks.onAllFinishedCallback || | ||
(function () { | ||
return; | ||
}); | ||
this.callbacks.onQueueChangedCallback = | ||
this.callbacks.onQueueChangedCallback || | ||
(function () { | ||
return; | ||
}); | ||
this.callbacks.onFileStateChangedCallback = function () { return _this.filesChanged(); }; | ||
@@ -757,3 +833,5 @@ }; | ||
this.queuedFiles | ||
.filter(function (file) { return [UploadStatus.uploaded, UploadStatus.canceled].indexOf(file.uploadStatus) >= 0; }) | ||
.filter(function (file) { | ||
return [UploadStatus.uploaded, UploadStatus.canceled].indexOf(file.uploadStatus) >= 0; | ||
}) | ||
.forEach(function (file) { return _this.removeFile(file, true); }); | ||
@@ -765,5 +843,11 @@ }; | ||
file.uploadStatus = UploadStatus.removed; | ||
file.cancel = function () { return; }; | ||
file.remove = function () { return; }; | ||
file.start = function () { return; }; | ||
file.cancel = function () { | ||
return; | ||
}; | ||
file.remove = function () { | ||
return; | ||
}; | ||
file.start = function () { | ||
return; | ||
}; | ||
}; | ||
@@ -784,3 +868,4 @@ UploadQueue.prototype.getWaitingFiles = function () { | ||
} | ||
count = Math.min(this.offset.fileCount + count, this.options.maxParallelUploads) - this.offset.fileCount; | ||
count = | ||
Math.min(this.offset.fileCount + count, this.options.maxParallelUploads) - this.offset.fileCount; | ||
this.offset.fileCount += count; | ||
@@ -814,1 +899,24 @@ } | ||
})(UploadStatus = exports.UploadStatus || (exports.UploadStatus = {})); | ||
var Uploader = /** @class */ (function () { | ||
function Uploader(options, callbacks) { | ||
if (options === void 0) { options = {}; } | ||
if (callbacks === void 0) { callbacks = {}; } | ||
this.options = options; | ||
this.uploadAreas = []; | ||
this.queue = new UploadQueue(options, callbacks); | ||
} | ||
Uploader.prototype.registerArea = function (element, options) { | ||
var uploadArea = new UploadArea(element, options, this); | ||
this.uploadAreas.push(uploadArea); | ||
return uploadArea; | ||
}; | ||
Uploader.prototype.unregisterArea = function (area) { | ||
var areaIndex = this.uploadAreas.indexOf(area); | ||
if (areaIndex >= 0) { | ||
this.uploadAreas[areaIndex].destroy(); | ||
this.uploadAreas.splice(areaIndex, 1); | ||
} | ||
}; | ||
return Uploader; | ||
}()); | ||
exports.Uploader = Uploader; |
1706
index.ts
@@ -1,999 +0,1165 @@ | ||
export function addEventHandler(el: Element | HTMLElement, event: string, handler: (ev: UIEvent) => void) { | ||
if (el.addEventListener) { | ||
el.addEventListener(event, handler); | ||
export interface IFileExt extends File { | ||
kind: string; | ||
webkitGetAsEntry: () => File; | ||
getAsFile: () => File; | ||
file: (callback: (file: IFileExt) => void) => void; | ||
createReader: Function; | ||
isFile: boolean; | ||
isDirectory: boolean; | ||
fullPath: string; | ||
} | ||
export function addEventHandler( | ||
el: Element | HTMLElement, | ||
event: string, | ||
handler: EventListenerOrEventListenerObject | ||
) { | ||
if (el.addEventListener) { | ||
el.addEventListener(event, handler); | ||
} else { | ||
let elem = <IElementWithEvents>el; | ||
if (elem.attachEvent) { | ||
elem.attachEvent("on" + event, handler as EventListener); | ||
} else { | ||
let elem = <IElementWithEvents>el; | ||
if (elem.attachEvent) { | ||
elem.attachEvent('on' + event, handler); | ||
} else { | ||
elem[event] = handler; | ||
} | ||
elem[event] = handler; | ||
} | ||
} | ||
} | ||
interface IElementWithEvents extends HTMLElement { | ||
[key: string]: Function | Object | string | void | null | number | boolean; | ||
attachEvent: (event: string, handler: (ev: UIEvent) => void) => void; | ||
[key: string]: Function | Object | string | void | null | number | boolean; | ||
attachEvent: (event: string, handler: (ev: UIEvent) => void) => void; | ||
} | ||
export const isFileApi: boolean = !!((<{ File?: Object }>window).File && (<{ FormData?: Object }>window).FormData); | ||
export function castFiles(fileList: File[] | Object, status?: UploadStatus): IUploadFile[] { | ||
let files: IUploadFile[]; | ||
export const isFileApi: boolean = !!( | ||
(<{ File?: Object }>window).File && (<{ FormData?: Object }>window).FormData | ||
); | ||
if (typeof fileList === 'object') { | ||
files = Object.keys(fileList) | ||
.filter(key => key !== 'length') | ||
.map(key => (<IFileOrObjectWithIndexer>fileList)[key]); | ||
} else { | ||
files = <IUploadFile[]>fileList; | ||
} | ||
export function castFiles( | ||
fileList: File[] | Object, | ||
status?: UploadStatus | ||
): IUploadFile[] { | ||
let files: IUploadFile[]; | ||
files.forEach((file: IUploadFile) => { | ||
file.uploadStatus = status || file.uploadStatus; | ||
file.responseCode = file.responseCode || 0; | ||
file.responseText = file.responseText || ''; | ||
file.progress = file.progress || 0; | ||
file.sentBytes = file.sentBytes || 0; | ||
file.cancel = file.cancel || (() => { return; }); | ||
}); | ||
if (typeof fileList === "object") { | ||
files = Object.keys(fileList) | ||
.filter(key => key !== "length") | ||
.map(key => (<IFileOrObjectWithIndexer>fileList)[key]); | ||
} else { | ||
files = <IUploadFile[]>fileList; | ||
} | ||
return files; | ||
files.forEach((file: IUploadFile) => { | ||
file.uploadStatus = status || file.uploadStatus; | ||
file.responseCode = file.responseCode || 0; | ||
file.responseText = file.responseText || ""; | ||
file.progress = file.progress || 0; | ||
file.sentBytes = file.sentBytes || 0; | ||
file.cancel = | ||
file.cancel || | ||
(() => { | ||
return; | ||
}); | ||
}); | ||
return files; | ||
} | ||
interface IFileOrObjectWithIndexer { | ||
[key: string]: IUploadFile; | ||
[key: string]: IUploadFile; | ||
} | ||
export function decorateSimpleFunction(origFn: () => void, newFn: () => void, newFirst: boolean = false): () => void { | ||
if (!origFn) | ||
return newFn; | ||
return newFirst | ||
? () => { newFn(); origFn(); } | ||
: () => { origFn(); newFn(); }; | ||
export function decorateSimpleFunction( | ||
origFn: () => void, | ||
newFn: () => void, | ||
newFirst: boolean = false | ||
): () => void { | ||
if (!origFn) return newFn; | ||
return newFirst | ||
? () => { | ||
newFn(); | ||
origFn(); | ||
} | ||
: () => { | ||
origFn(); | ||
newFn(); | ||
}; | ||
} | ||
function applyDefaults<T, S>(target: T, source: S): T & S { | ||
let to = Object(target); | ||
let to = Object(target); | ||
for (let nextKey in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, nextKey) && (to[nextKey] === undefined || to[nextKey] === null)) { | ||
to[nextKey] = source[nextKey]; | ||
} | ||
for (let nextKey in source) { | ||
if ( | ||
Object.prototype.hasOwnProperty.call(source, nextKey) && | ||
(to[nextKey] === undefined || to[nextKey] === null) | ||
) { | ||
to[nextKey] = source[nextKey]; | ||
} | ||
return to; | ||
}; | ||
export function getUploadCore(options: IUploadOptions, callbacks: IUploadCallbacks): UploadCore { | ||
return new UploadCore(options, callbacks); | ||
}; | ||
} | ||
return to; | ||
} | ||
export function getUploader(options: IUploadQueueOptions, callbacks: IUploadQueueCallbacks): Uploader { | ||
return new Uploader(options, callbacks); | ||
}; | ||
export function getUploadCore( | ||
options: IUploadOptions, | ||
callbacks: IUploadCallbacks | ||
): UploadCore { | ||
return new UploadCore(options, callbacks); | ||
} | ||
export function getUploader( | ||
options: IUploadQueueOptions, | ||
callbacks: IUploadQueueCallbacks | ||
): Uploader { | ||
return new Uploader(options, callbacks); | ||
} | ||
export function getValueOrResult<T>(valueOrGetter?: T | (() => T)): T | undefined { | ||
if (typeof valueOrGetter === 'function') | ||
return valueOrGetter(); | ||
if (typeof valueOrGetter === "function") return valueOrGetter(); | ||
return valueOrGetter; | ||
return valueOrGetter; | ||
} | ||
export function newGuid(): string { | ||
let d = new Date().getTime(); | ||
let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { | ||
/* tslint:disable */ | ||
let r = (d + Math.random() * 16) % 16 | 0; | ||
d = Math.floor(d / 16); | ||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); | ||
/* tslint:enable */ | ||
}); | ||
return uuid; | ||
}; | ||
export interface IFileExt extends File { | ||
kind: string; | ||
webkitGetAsEntry: () => File; | ||
getAsFile: () => File; | ||
file: (callback: (file: IFileExt) => void) => void; | ||
createReader: Function; | ||
isFile: boolean; | ||
isDirectory: boolean; | ||
fullPath: string; | ||
let d = new Date().getTime(); | ||
let uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function( | ||
c | ||
) { | ||
/* tslint:disable */ | ||
let r = ((d + Math.random() * 16) % 16) | 0; | ||
d = Math.floor(d / 16); | ||
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16); | ||
/* tslint:enable */ | ||
}); | ||
return uuid; | ||
} | ||
export interface IFullUploadAreaOptions extends IUploadAreaOptions { | ||
maxFileSize: number; | ||
allowDragDrop: boolean | (() => boolean); | ||
clickable: boolean | (() => boolean); | ||
accept: string; | ||
multiple: boolean; | ||
validateExtension: boolean; | ||
maxFileSize: number; | ||
allowDragDrop: boolean | (() => boolean); | ||
clickable: boolean | (() => boolean); | ||
accept: string; | ||
multiple: boolean; | ||
validateExtension: boolean; | ||
localizer: ILocalizer; | ||
localizer: ILocalizer; | ||
} | ||
export interface IFullUploadOptions extends IUploadOptions { | ||
withCredentials: boolean; | ||
headers: { [key: string]: string | number | boolean }; | ||
params: { [key: string]: string | number | boolean | Blob }; | ||
localizer: ILocalizer; | ||
withCredentials: boolean; | ||
headers: { [key: string]: string | number | boolean }; | ||
params: { [key: string]: string | number | boolean | Blob }; | ||
localizer: ILocalizer; | ||
} | ||
export interface ILocalizer { | ||
fileSizeInvalid: (maxFileSize: number) => string; | ||
fileTypeInvalid: (accept: string) => string; | ||
invalidResponseFromServer: () => string; | ||
fileSizeInvalid: (maxFileSize: number) => string; | ||
fileTypeInvalid: (accept: string) => string; | ||
invalidResponseFromServer: () => string; | ||
} | ||
function getDefaultLocalizer(): ILocalizer { | ||
return { | ||
fileSizeInvalid: (maxFileSize) => 'The selected file exceeds the allowed size of ' + maxFileSize | ||
+ ' or its size is 0 MB. Please choose another file.', | ||
fileTypeInvalid: accept => 'File format is not allowed. Only ' + (accept ? accept : '') + ' files are allowed.', | ||
invalidResponseFromServer: () => 'Invalid response from server' | ||
}; | ||
return { | ||
fileSizeInvalid: maxFileSize => | ||
"The selected file exceeds the allowed size of " + | ||
maxFileSize + | ||
" or its size is 0 MB. Please choose another file.", | ||
fileTypeInvalid: accept => | ||
"File format is not allowed. Only " + | ||
(accept ? accept : "") + | ||
" files are allowed.", | ||
invalidResponseFromServer: () => "Invalid response from server" | ||
}; | ||
} | ||
export interface IOffsetInfo { | ||
running: boolean; | ||
fileCount: number; | ||
running: boolean; | ||
fileCount: number; | ||
} | ||
export interface IUploadAreaOptions extends IUploadOptions { | ||
maxFileSize?: number; | ||
allowDragDrop?: boolean | (() => boolean); | ||
clickable?: boolean | (() => boolean); | ||
accept?: string; | ||
multiple?: boolean; | ||
validateExtension?: boolean; | ||
manualStart?: boolean; | ||
allowEmptyFile?: boolean; | ||
dragOverStyle?: string; | ||
dragOverGlobalStyle?: string; | ||
maxFileSize?: number; | ||
allowDragDrop?: boolean | (() => boolean); | ||
clickable?: boolean | (() => boolean); | ||
accept?: string; | ||
multiple?: boolean; | ||
validateExtension?: boolean; | ||
manualStart?: boolean; | ||
allowEmptyFile?: boolean; | ||
dragOverStyle?: string; | ||
dragOverGlobalStyle?: string; | ||
onFileAdded?: (file: IUploadFile) => void; | ||
onFileSelected?: (file: IUploadFile) => void; | ||
onFileError?: (file: IUploadFile) => void; | ||
onFileCanceled?: (file: IUploadFile) => void; | ||
onFileAdded?: (file: IUploadFile) => void; | ||
onFileSelected?: (file: IUploadFile) => void; | ||
onFileError?: (file: IUploadFile) => void; | ||
onFileCanceled?: (file: IUploadFile) => void; | ||
} | ||
export interface IUploadCallbacks { | ||
onProgressCallback?: (file: IUploadFile) => void; | ||
onCancelledCallback?: (file: IUploadFile) => void; | ||
onFinishedCallback?: (file: IUploadFile) => void; | ||
onUploadedCallback?: (file: IUploadFile) => void; | ||
onErrorCallback?: (file: IUploadFile) => void; | ||
onUploadStartedCallback?: (file: IUploadFile) => void; | ||
onProgressCallback?: (file: IUploadFile) => void; | ||
onCancelledCallback?: (file: IUploadFile) => void; | ||
onFinishedCallback?: (file: IUploadFile) => void; | ||
onUploadedCallback?: (file: IUploadFile) => void; | ||
onErrorCallback?: (file: IUploadFile) => void; | ||
onUploadStartedCallback?: (file: IUploadFile) => void; | ||
} | ||
export interface IUploadCallbacksExt extends IUploadCallbacks { | ||
onFileStateChangedCallback?: (file: IUploadFile) => void; | ||
onFileStateChangedCallback?: (file: IUploadFile) => void; | ||
} | ||
export interface IUploadFile extends File { | ||
guid: string; | ||
url: string; | ||
uploadStatus: UploadStatus; | ||
responseCode: number; | ||
responseText: string; | ||
progress: number; | ||
sentBytes: number; | ||
guid: string; | ||
url: string; | ||
uploadStatus: UploadStatus; | ||
responseCode: number; | ||
responseText: string; | ||
progress: number; | ||
sentBytes: number; | ||
cancel: () => void; | ||
remove: () => void; | ||
start: () => void; | ||
onError: (file: IUploadFile) => void; | ||
onCancel: (file: IUploadFile) => void; | ||
cancel: () => void; | ||
remove: () => void; | ||
start: () => void; | ||
onError: (file: IUploadFile) => void; | ||
onCancel: (file: IUploadFile) => void; | ||
} | ||
export interface IUploadOptions { | ||
url: string | ((file: IUploadFile) => string); | ||
method: string; | ||
withCredentials?: boolean; | ||
headers?: { [key: string]: string | number | boolean }; | ||
params?: { [key: string]: string | number | boolean | Blob }; | ||
localizer?: ILocalizer; | ||
url: string | ((file: IUploadFile) => string); | ||
method: string; | ||
withCredentials?: boolean; | ||
headers?: { [key: string]: string | number | boolean }; | ||
params?: { [key: string]: string | number | boolean | Blob }; | ||
localizer?: ILocalizer; | ||
} | ||
export interface IUploadQueueCallbacks extends IUploadCallbacks { | ||
onFileAddedCallback?: (file: IUploadFile) => void; | ||
onFileRemovedCallback?: (file: IUploadFile) => void; | ||
onAllFinishedCallback?: () => void; | ||
onQueueChangedCallback?: (queue: IUploadFile[]) => void; | ||
onFileAddedCallback?: (file: IUploadFile) => void; | ||
onFileRemovedCallback?: (file: IUploadFile) => void; | ||
onAllFinishedCallback?: () => void; | ||
onQueueChangedCallback?: (queue: IUploadFile[]) => void; | ||
} | ||
export interface IUploadQueueCallbacksExt extends IUploadQueueCallbacks, IUploadCallbacksExt { | ||
} | ||
export interface IUploadQueueCallbacksExt | ||
extends IUploadQueueCallbacks, | ||
IUploadCallbacksExt {} | ||
export interface IUploadQueueOptions { | ||
maxParallelUploads?: number; | ||
parallelBatchOffset?: number; | ||
autoStart?: boolean; | ||
autoRemove?: boolean; | ||
maxParallelUploads?: number; | ||
parallelBatchOffset?: number; | ||
autoStart?: boolean; | ||
autoRemove?: boolean; | ||
} | ||
export function removeEventHandler(el: HTMLInputElement | Element, event: string, handler: (ev: UIEvent) => void) { | ||
if (el.removeEventListener) { | ||
el.removeEventListener(event, handler); | ||
export function removeEventHandler( | ||
el: HTMLInputElement | Element, | ||
event: string, | ||
handler: EventListenerOrEventListenerObject | ||
) { | ||
if (el.removeEventListener) { | ||
el.removeEventListener(event, handler); | ||
} else { | ||
let elem = <IElementWithDettachEvent>el; | ||
if (elem.detachEvent) { | ||
elem.detachEvent("on" + event, handler as EventListener); | ||
} else { | ||
let elem = <IElementWithDettachEvent>el; | ||
if (elem.detachEvent) { | ||
elem.detachEvent('on' + event, handler); | ||
} else { | ||
elem[event] = null; | ||
} | ||
elem[event] = null; | ||
} | ||
} | ||
} | ||
interface IElementWithDettachEvent extends HTMLElement { | ||
[key: string]: Function | Object | string | void | null | number | boolean; | ||
detachEvent: (event: string, handler: (ev: UIEvent) => void) => void; | ||
[key: string]: Function | Object | string | void | null | number | boolean; | ||
detachEvent: (event: string, handler: (ev: UIEvent) => void) => void; | ||
} | ||
export class UploadArea { | ||
public targetElement: HTMLElement; | ||
public uploader: Uploader; | ||
public options: IFullUploadAreaOptions; | ||
private uploadCore: UploadCore; | ||
private fileInput: HTMLInputElement; | ||
private fileList?: IUploadFile[] | null; | ||
private unregisterOnClick: () => void; | ||
private unregisterOnDrop: () => void; | ||
private unregisterOnDragOver: () => void; | ||
private unregisterOnDragLeave: () => void; | ||
private unregisterOnDragOverGlobal: () => void; | ||
private unregisterOnDragLeaveGlobal: () => void; | ||
private unregisterOnChange: () => void; | ||
public targetElement: HTMLElement; | ||
public uploader: Uploader; | ||
public options: IFullUploadAreaOptions; | ||
private uploadCore: UploadCore; | ||
private fileInput?: HTMLInputElement; | ||
private fileList?: IUploadFile[] | null; | ||
private unregisterOnClick?: () => void; | ||
private unregisterOnDrop?: () => void; | ||
private unregisterOnDragOver?: () => void; | ||
private unregisterOnDragLeave?: () => void; | ||
private unregisterOnDragOverGlobal?: () => void; | ||
private unregisterOnDragLeaveGlobal?: () => void; | ||
private unregisterOnChange?: () => void; | ||
constructor(targetElement: HTMLElement, options: IUploadAreaOptions, uploader: Uploader) { | ||
this.targetElement = targetElement; | ||
this.options = applyDefaults(options, this.defaultOptions()); | ||
this.uploader = uploader; | ||
this.uploadCore = getUploadCore(this.options, this.uploader.queue.callbacks); | ||
if (isFileApi) { | ||
this.setupFileApiElements(); | ||
} else { | ||
throw 'Only browsers with FileAPI supported.'; | ||
} | ||
constructor( | ||
targetElement: HTMLElement, | ||
options: IUploadAreaOptions, | ||
uploader: Uploader | ||
) { | ||
this.targetElement = targetElement; | ||
this.options = applyDefaults(options, this.defaultOptions()); | ||
this.uploader = uploader; | ||
this.uploadCore = getUploadCore( | ||
this.options, | ||
this.uploader.queue.callbacks | ||
); | ||
if (isFileApi) { | ||
this.setupFileApiElements(); | ||
} else { | ||
throw "Only browsers with FileAPI supported."; | ||
} | ||
} | ||
start(autoClear: boolean = false) { | ||
if (this.options.manualStart && this.fileList) { | ||
this.putFilesToQueue(); | ||
if (autoClear) | ||
this.clear(); | ||
} | ||
start(autoClear: boolean = false) { | ||
if (this.options.manualStart && this.fileList) { | ||
this.putFilesToQueue(); | ||
if (autoClear) this.clear(); | ||
} | ||
} | ||
clear() { | ||
this.fileList = null; | ||
} | ||
clear() { | ||
this.fileList = null; | ||
} | ||
destroy(): void { | ||
if (this.unregisterOnClick) | ||
this.unregisterOnClick(); | ||
destroy(): void { | ||
if (this.unregisterOnClick) this.unregisterOnClick(); | ||
if (this.unregisterOnDrop) | ||
this.unregisterOnDrop(); | ||
if (this.unregisterOnDrop) this.unregisterOnDrop(); | ||
if (this.unregisterOnChange) | ||
this.unregisterOnChange(); | ||
if (this.unregisterOnChange) this.unregisterOnChange(); | ||
if (this.unregisterOnDragOver) | ||
this.unregisterOnDragOver(); | ||
if (this.unregisterOnDragOver) this.unregisterOnDragOver(); | ||
if (this.unregisterOnDragLeave) | ||
this.unregisterOnDragLeave(); | ||
if (this.unregisterOnDragLeave) this.unregisterOnDragLeave(); | ||
if (this.unregisterOnDragOverGlobal) | ||
this.unregisterOnDragOverGlobal(); | ||
if (this.unregisterOnDragOverGlobal) this.unregisterOnDragOverGlobal(); | ||
if (this.unregisterOnDragLeaveGlobal) | ||
this.unregisterOnDragLeaveGlobal(); | ||
if (this.unregisterOnDragLeaveGlobal) this.unregisterOnDragLeaveGlobal(); | ||
document.body.removeChild(this.fileInput); | ||
} | ||
if (this.fileInput) document.body.removeChild(this.fileInput); | ||
} | ||
private defaultOptions() { | ||
return { | ||
localizer: getDefaultLocalizer(), | ||
maxFileSize: 1024, | ||
allowDragDrop: true, | ||
clickable: true, | ||
accept: '*.*', | ||
validateExtension: false, | ||
multiple: true, | ||
allowEmptyFile: false | ||
}; | ||
} | ||
private defaultOptions() { | ||
return { | ||
localizer: getDefaultLocalizer(), | ||
maxFileSize: 1024, | ||
allowDragDrop: true, | ||
clickable: true, | ||
accept: "*.*", | ||
validateExtension: false, | ||
multiple: true, | ||
allowEmptyFile: false | ||
}; | ||
} | ||
private selectFiles(fileList: FileList | File[]) { | ||
this.fileList = castFiles(fileList); | ||
private selectFiles(fileList: FileList | File[]) { | ||
this.fileList = castFiles(fileList); | ||
if (this.options.onFileSelected) | ||
this.fileList.forEach((file: IUploadFile) => { | ||
if (this.options.onFileSelected) | ||
this.options.onFileSelected(file); | ||
}); | ||
if (this.options.onFileSelected) | ||
this.fileList.forEach((file: IUploadFile) => { | ||
if (this.options.onFileSelected) this.options.onFileSelected(file); | ||
}); | ||
if (!this.options.manualStart) | ||
this.putFilesToQueue(); | ||
} | ||
if (!this.options.manualStart) this.putFilesToQueue(); | ||
} | ||
private putFilesToQueue(): void { | ||
if (!this.fileList) | ||
return; | ||
private putFilesToQueue(): void { | ||
if (!this.fileList) return; | ||
this.fileList.forEach((file: IUploadFile) => { | ||
file.guid = newGuid(); | ||
delete file.uploadStatus; | ||
file.url = this.uploadCore.getUrl(file); | ||
file.onError = this.options.onFileError || (() => { ; }); | ||
file.onCancel = this.options.onFileCanceled || (() => { ; }); | ||
if (this.validateFile(file)) { | ||
file.start = () => { | ||
this.uploadCore.upload([file]); | ||
this.fileList.forEach((file: IUploadFile) => { | ||
file.guid = newGuid(); | ||
delete file.uploadStatus; | ||
file.url = this.uploadCore.getUrl(file); | ||
file.onError = this.options.onFileError || (() => {}); | ||
file.onCancel = this.options.onFileCanceled || (() => {}); | ||
if (this.validateFile(file)) { | ||
file.start = () => { | ||
this.uploadCore.upload([file]); | ||
if (this.options.onFileAdded) { | ||
this.options.onFileAdded(file); | ||
} | ||
file.start = () => { return; }; | ||
}; | ||
} else { | ||
file.onError(file); | ||
} | ||
}); | ||
this.uploader.queue.addFiles(this.fileList); | ||
} | ||
if (this.options.onFileAdded) { | ||
this.options.onFileAdded(file); | ||
} | ||
file.start = () => { | ||
return; | ||
}; | ||
}; | ||
} else { | ||
file.onError(file); | ||
} | ||
}); | ||
this.uploader.queue.addFiles(this.fileList); | ||
} | ||
private validateFile(file: IUploadFile): boolean { | ||
if (!this.isFileSizeValid(file)) { | ||
file.uploadStatus = UploadStatus.failed; | ||
file.responseText = this.options.localizer.fileSizeInvalid(this.options.maxFileSize); | ||
return false; | ||
} | ||
if (this.isFileTypeInvalid(file)) { | ||
file.uploadStatus = UploadStatus.failed; | ||
file.responseText = this.options.localizer.fileTypeInvalid(this.options.accept); | ||
return false; | ||
} | ||
return true; | ||
private validateFile(file: IUploadFile): boolean { | ||
if (!this.isFileSizeValid(file)) { | ||
file.uploadStatus = UploadStatus.failed; | ||
file.responseText = this.options.localizer.fileSizeInvalid( | ||
this.options.maxFileSize | ||
); | ||
return false; | ||
} | ||
if (this.isFileTypeInvalid(file)) { | ||
file.uploadStatus = UploadStatus.failed; | ||
file.responseText = this.options.localizer.fileTypeInvalid( | ||
this.options.accept | ||
); | ||
return false; | ||
} | ||
return true; | ||
} | ||
private setupFileApiElements(): void { | ||
this.fileInput = document.createElement('input'); | ||
this.fileInput.setAttribute('type', 'file'); | ||
this.fileInput.setAttribute('accept', this.options.accept ? this.options.accept : ''); | ||
this.fileInput.style.display = 'none'; | ||
private setupFileApiElements(): void { | ||
this.fileInput = document.createElement("input"); | ||
this.fileInput.setAttribute("type", "file"); | ||
this.fileInput.setAttribute( | ||
"accept", | ||
this.options.accept ? this.options.accept : "" | ||
); | ||
this.fileInput.style.display = "none"; | ||
const onChange = (e: Event) => this.onChange(e); | ||
addEventHandler(this.fileInput, 'change', onChange); | ||
this.unregisterOnChange = () => removeEventHandler(this.fileInput, 'change', onchange); | ||
const onChange = (e: Event) => this.onChange(e); | ||
addEventHandler(this.fileInput, "change", onChange); | ||
this.unregisterOnChange = () => { | ||
if (this.fileInput) | ||
removeEventHandler(this.fileInput, "change", onchange); | ||
}; | ||
if (this.options.multiple) { | ||
this.fileInput.setAttribute('multiple', ''); | ||
} | ||
if (this.options.multiple) { | ||
this.fileInput.setAttribute("multiple", ""); | ||
} | ||
this.registerEvents(); | ||
this.registerEvents(); | ||
// attach to body | ||
document.body.appendChild(this.fileInput); | ||
} | ||
// attach to body | ||
document.body.appendChild(this.fileInput); | ||
} | ||
private registerEvents() { | ||
const onClick = () => this.onClick(); | ||
addEventHandler(this.targetElement, 'click', onClick); | ||
this.unregisterOnClick = () => removeEventHandler(this.targetElement, 'click', onClick); | ||
private registerEvents() { | ||
const onClick = () => this.onClick(); | ||
addEventHandler(this.targetElement, "click", onClick); | ||
this.unregisterOnClick = () => | ||
removeEventHandler(this.targetElement, "click", onClick); | ||
const onDrag = (e: DragEvent) => this.onDrag(e); | ||
addEventHandler(this.targetElement, 'dragover', onDrag); | ||
this.unregisterOnDragOver = () => removeEventHandler(this.targetElement, 'dragover', onDrag); | ||
const onDrag = ((e: DragEvent) => | ||
this.onDrag(e)) as EventListenerOrEventListenerObject; | ||
addEventHandler(this.targetElement, "dragover", onDrag); | ||
this.unregisterOnDragOver = () => | ||
removeEventHandler(this.targetElement, "dragover", onDrag); | ||
const onDragLeave = () => this.onDragLeave(); | ||
addEventHandler(this.targetElement, 'dragleave', onDragLeave); | ||
this.unregisterOnDragOver = () => removeEventHandler(this.targetElement, 'dragleave', onDragLeave); | ||
const onDragLeave = () => this.onDragLeave(); | ||
addEventHandler(this.targetElement, "dragleave", onDragLeave); | ||
this.unregisterOnDragOver = () => | ||
removeEventHandler(this.targetElement, "dragleave", onDragLeave); | ||
const onDragGlobal = () => this.onDragGlobal(); | ||
addEventHandler(document.body, 'dragover', onDragGlobal); | ||
this.unregisterOnDragOverGlobal = () => removeEventHandler(document.body, 'dragover', onDragGlobal); | ||
const onDragGlobal = () => this.onDragGlobal(); | ||
addEventHandler(document.body, "dragover", onDragGlobal); | ||
this.unregisterOnDragOverGlobal = () => | ||
removeEventHandler(document.body, "dragover", onDragGlobal); | ||
const onDragLeaveGlobal = () => this.onDragLeaveGlobal(); | ||
addEventHandler(document.body, 'dragleave', onDragLeaveGlobal); | ||
this.unregisterOnDragOverGlobal = () => removeEventHandler(document.body, 'dragleave', onDragLeaveGlobal); | ||
const onDragLeaveGlobal = () => this.onDragLeaveGlobal(); | ||
addEventHandler(document.body, "dragleave", onDragLeaveGlobal); | ||
this.unregisterOnDragOverGlobal = () => | ||
removeEventHandler(document.body, "dragleave", onDragLeaveGlobal); | ||
const onDrop = (e: DragEvent) => this.onDrop(e); | ||
addEventHandler(this.targetElement, 'drop', onDrop); | ||
this.unregisterOnDrop = () => removeEventHandler(this.targetElement, 'drop', onDrop); | ||
} | ||
const onDrop = ((e: DragEvent) => | ||
this.onDrop(e)) as EventListenerOrEventListenerObject; | ||
addEventHandler(this.targetElement, "drop", onDrop); | ||
this.unregisterOnDrop = () => | ||
removeEventHandler(this.targetElement, "drop", onDrop); | ||
} | ||
private onChange(e: Event): void { | ||
this.selectFiles(<FileList>(<HTMLInputElement>e.target).files); | ||
} | ||
private onChange(e: Event): void { | ||
this.selectFiles(<FileList>(<HTMLInputElement>e.target).files); | ||
} | ||
private onDrag(e: DragEvent): void { | ||
if (!getValueOrResult(this.options.allowDragDrop)) | ||
return; | ||
private onDrag(e: DragEvent): void { | ||
if (!getValueOrResult(this.options.allowDragDrop)) return; | ||
this.addDragOverStyle(this.options.dragOverStyle); | ||
let efct: string | undefined = undefined; | ||
try { | ||
efct = e.dataTransfer.effectAllowed; | ||
} catch (err) { ; } | ||
e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; | ||
this.stopEventPropagation(e); | ||
} | ||
this.addDragOverStyle(this.options.dragOverStyle); | ||
let efct: string | undefined = undefined; | ||
try { | ||
efct = e.dataTransfer.effectAllowed; | ||
} catch (err) {} | ||
e.dataTransfer.dropEffect = | ||
"move" === efct || "linkMove" === efct ? "move" : "copy"; | ||
this.stopEventPropagation(e); | ||
} | ||
private onDragLeave(): void { | ||
if (!getValueOrResult(this.options.allowDragDrop)) | ||
return; | ||
private onDragLeave(): void { | ||
if (!getValueOrResult(this.options.allowDragDrop)) return; | ||
this.removeDragOverStyle(this.options.dragOverStyle); | ||
} | ||
this.removeDragOverStyle(this.options.dragOverStyle); | ||
} | ||
private onDragGlobal(): void { | ||
if (!getValueOrResult(this.options.allowDragDrop)) | ||
return; | ||
private onDragGlobal(): void { | ||
if (!getValueOrResult(this.options.allowDragDrop)) return; | ||
this.addDragOverStyle(this.options.dragOverGlobalStyle); | ||
} | ||
this.addDragOverStyle(this.options.dragOverGlobalStyle); | ||
} | ||
private onDragLeaveGlobal(): void { | ||
if (!getValueOrResult(this.options.allowDragDrop)) | ||
return; | ||
private onDragLeaveGlobal(): void { | ||
if (!getValueOrResult(this.options.allowDragDrop)) return; | ||
this.removeDragOverStyle(this.options.dragOverGlobalStyle); | ||
} | ||
this.removeDragOverStyle(this.options.dragOverGlobalStyle); | ||
} | ||
private removeDragOverStyle(style?: string) { | ||
if (!style) | ||
return; | ||
private removeDragOverStyle(style?: string) { | ||
if (!style) return; | ||
this.targetElement.classList.remove(style); | ||
} | ||
this.targetElement.classList.remove(style); | ||
} | ||
private addDragOverStyle(style?: string) { | ||
if (!style) | ||
return; | ||
private addDragOverStyle(style?: string) { | ||
if (!style) return; | ||
this.targetElement.classList.add(style); | ||
} | ||
this.targetElement.classList.add(style); | ||
} | ||
private onDrop(e: DragEvent): void { | ||
if (!getValueOrResult(this.options.allowDragDrop)) | ||
return; | ||
private onDrop(e: DragEvent): void { | ||
if (!getValueOrResult(this.options.allowDragDrop)) return; | ||
this.stopEventPropagation(e); | ||
if (!e.dataTransfer) { | ||
return; | ||
} | ||
this.stopEventPropagation(e); | ||
if (!e.dataTransfer) { | ||
return; | ||
} | ||
this.removeDragOverStyle(this.options.dragOverStyle); | ||
this.removeDragOverStyle(this.options.dragOverStyle); | ||
let files: FileList | File[] = e.dataTransfer.files; | ||
if (files.length) { | ||
if (!this.options.multiple) | ||
files = [files[0]]; | ||
let files: FileList | File[] = e.dataTransfer.files; | ||
if (files.length) { | ||
if (!this.options.multiple) files = [files[0]]; | ||
let items = e.dataTransfer.items; | ||
if (items && items.length && ((<{ webkitGetAsEntry?: Object }>items[0]).webkitGetAsEntry !== null)) { | ||
if (!this.options.multiple) { | ||
let newItems = [items[0]]; | ||
this.addFilesFromItems(newItems); | ||
} else { | ||
this.addFilesFromItems(items); | ||
} | ||
} else { | ||
this.handleFiles(files); | ||
} | ||
let items = e.dataTransfer.items; | ||
if ( | ||
items && | ||
items.length && | ||
(<{ webkitGetAsEntry?: Object }>items[0]).webkitGetAsEntry !== null | ||
) { | ||
if (!this.options.multiple) { | ||
let newItems = [items[0]]; | ||
this.addFilesFromItems(newItems); | ||
} else { | ||
this.addFilesFromItems(items); | ||
} | ||
} else { | ||
this.handleFiles(files); | ||
} | ||
} | ||
} | ||
private isIeVersion(v: number): boolean { | ||
return RegExp('msie' + (!isNaN(v) ? ('\\s' + v.toString()) : ''), 'i').test(navigator.userAgent); | ||
} | ||
private isIeVersion(v: number): boolean { | ||
return RegExp("msie" + (!isNaN(v) ? "\\s" + v.toString() : ""), "i").test( | ||
navigator.userAgent | ||
); | ||
} | ||
private onClick(): void { | ||
if (!getValueOrResult(this.options.clickable)) | ||
return; | ||
private onClick(): void { | ||
if (!getValueOrResult(this.options.clickable) || !this.fileInput) return; | ||
this.fileInput.value = ''; | ||
this.fileInput.value = ""; | ||
if (this.isIeVersion(10)) { | ||
setTimeout(() => { this.fileInput.click(); }, 200); | ||
} else { | ||
this.fileInput.click(); | ||
} | ||
if (this.isIeVersion(10)) { | ||
setTimeout(() => { | ||
if (this.fileInput) this.fileInput.click(); | ||
}, 200); | ||
} else { | ||
this.fileInput.click(); | ||
} | ||
} | ||
private addFilesFromItems(items: FileList | File[] | DataTransferItemList | DataTransferItem[]): void { | ||
let entry: IFileExt; | ||
for (let i = 0; i < items.length; i++) { | ||
let item: IFileExt = <IFileExt>items[i]; | ||
if ((item.webkitGetAsEntry) && (entry = <IFileExt>item.webkitGetAsEntry())) { | ||
if (entry.isFile) { | ||
this.selectFiles([item.getAsFile()]); | ||
} else if (entry.isDirectory) { | ||
this.processDirectory(entry, entry.name); | ||
} | ||
} else if (item.getAsFile) { | ||
if (!item.kind || item.kind === 'file') { | ||
this.selectFiles([item.getAsFile()]); | ||
} | ||
} | ||
private addFilesFromItems( | ||
items: FileList | File[] | DataTransferItemList | DataTransferItem[] | ||
): void { | ||
let entry: IFileExt; | ||
for (let i = 0; i < items.length; i++) { | ||
let item: IFileExt = <IFileExt>items[i]; | ||
if ( | ||
item.webkitGetAsEntry && | ||
(entry = <IFileExt>item.webkitGetAsEntry()) | ||
) { | ||
if (entry.isFile) { | ||
this.selectFiles([item.getAsFile()]); | ||
} else if (entry.isDirectory) { | ||
this.processDirectory(entry, entry.name); | ||
} | ||
} else if (item.getAsFile) { | ||
if (!item.kind || item.kind === "file") { | ||
this.selectFiles([item.getAsFile()]); | ||
} | ||
} | ||
} | ||
} | ||
private processDirectory(directory: { createReader: Function }, path: string): void { | ||
let dirReader = directory.createReader(); | ||
let self = this; | ||
let entryReader = (entries: (IFileExt & { createReader: Function })[]) => { | ||
for (let i = 0; i < entries.length; i++) { | ||
let entry = entries[i]; | ||
if (entry.isFile) { | ||
entry.file((file: IFileExt) => { | ||
if (file.name.substring(0, 1) === '.') { | ||
return; | ||
} | ||
file.fullPath = '' + path + '/' + file.name; | ||
self.selectFiles([file]); | ||
}); | ||
} else if (entry.isDirectory) { | ||
self.processDirectory(entry, '' + path + '/' + entry.name); | ||
} | ||
private processDirectory( | ||
directory: { createReader: Function }, | ||
path: string | ||
): void { | ||
let dirReader = directory.createReader(); | ||
let self = this; | ||
let entryReader = (entries: (IFileExt & { createReader: Function })[]) => { | ||
for (let i = 0; i < entries.length; i++) { | ||
let entry = entries[i]; | ||
if (entry.isFile) { | ||
entry.file((file: IFileExt) => { | ||
if (file.name.substring(0, 1) === ".") { | ||
return; | ||
} | ||
}; | ||
dirReader.readEntries(entryReader, function (error: string) { | ||
return typeof console !== 'undefined' && console !== null | ||
? typeof console.log === 'function' ? console.log(error) : void 0 | ||
: void 0; | ||
}); | ||
} | ||
private handleFiles(files: FileList | File[]): void { | ||
for (let i = 0; i < files.length; i++) { | ||
this.selectFiles([files[i]]); | ||
file.fullPath = "" + path + "/" + file.name; | ||
self.selectFiles([file]); | ||
}); | ||
} else if (entry.isDirectory) { | ||
self.processDirectory(entry, "" + path + "/" + entry.name); | ||
} | ||
} | ||
} | ||
}; | ||
dirReader.readEntries(entryReader, function(error: string) { | ||
return typeof console !== "undefined" && console !== null | ||
? typeof console.log === "function" ? console.log(error) : void 0 | ||
: void 0; | ||
}); | ||
} | ||
private isFileSizeValid(file: File): boolean { | ||
let maxFileSize = this.options.maxFileSize * 1024 * 1024; // max file size in bytes | ||
if (file.size > maxFileSize || (!this.options.allowEmptyFile && file.size === 0)) return false; | ||
return true; | ||
private handleFiles(files: FileList | File[]): void { | ||
for (let i = 0; i < files.length; i++) { | ||
this.selectFiles([files[i]]); | ||
} | ||
} | ||
private isFileTypeInvalid(file: File): boolean { | ||
if (file.name && this.options.accept && (this.options.accept.trim() !== '*' || this.options.accept.trim() !== '*.*') && | ||
this.options.validateExtension && this.options.accept.indexOf('/') === -1) { | ||
let acceptedExtensions = this.options.accept.split(','); | ||
let fileExtension = file.name.substring(file.name.lastIndexOf('.'), file.name.length); | ||
if (fileExtension.indexOf('.') === -1) return true; | ||
let isFileExtensionExisted = true; | ||
for (let i = 0; i < acceptedExtensions.length; i++) { | ||
if (acceptedExtensions[i].toUpperCase().trim() === fileExtension.toUpperCase()) { | ||
isFileExtensionExisted = false; | ||
} | ||
} | ||
return isFileExtensionExisted; | ||
private isFileSizeValid(file: File): boolean { | ||
let maxFileSize = this.options.maxFileSize * 1024 * 1024; // max file size in bytes | ||
if ( | ||
file.size > maxFileSize || | ||
(!this.options.allowEmptyFile && file.size === 0) | ||
) | ||
return false; | ||
return true; | ||
} | ||
private isFileTypeInvalid(file: File): boolean { | ||
if ( | ||
file.name && | ||
this.options.accept && | ||
(this.options.accept.trim() !== "*" || | ||
this.options.accept.trim() !== "*.*") && | ||
this.options.validateExtension && | ||
this.options.accept.indexOf("/") === -1 | ||
) { | ||
let acceptedExtensions = this.options.accept.split(","); | ||
let fileExtension = file.name.substring( | ||
file.name.lastIndexOf("."), | ||
file.name.length | ||
); | ||
if (fileExtension.indexOf(".") === -1) return true; | ||
let isFileExtensionExisted = true; | ||
for (let i = 0; i < acceptedExtensions.length; i++) { | ||
if ( | ||
acceptedExtensions[i].toUpperCase().trim() === | ||
fileExtension.toUpperCase() | ||
) { | ||
isFileExtensionExisted = false; | ||
} | ||
return false; | ||
} | ||
return isFileExtensionExisted; | ||
} | ||
return false; | ||
} | ||
private stopEventPropagation(e: Event) { | ||
e.stopPropagation(); | ||
if (e.preventDefault) { | ||
e.preventDefault(); | ||
} else { | ||
e.returnValue = false; | ||
} | ||
private stopEventPropagation(e: Event) { | ||
e.stopPropagation(); | ||
if (e.preventDefault) { | ||
e.preventDefault(); | ||
} else { | ||
e.returnValue = false; | ||
} | ||
} | ||
} | ||
export class UploadCore { | ||
public options: IFullUploadOptions; | ||
public callbacks: IUploadCallbacksExt; | ||
public options: IFullUploadOptions; | ||
public callbacks: IUploadCallbacksExt; | ||
constructor(options: IUploadOptions, callbacks: IUploadCallbacksExt = {}) { | ||
this.callbacks = callbacks; | ||
this.options = applyDefaults(options, this.getDefaultOptions()); | ||
this.setFullCallbacks(callbacks); | ||
} | ||
constructor(options: IUploadOptions, callbacks: IUploadCallbacksExt = {}) { | ||
this.callbacks = callbacks; | ||
this.options = applyDefaults(options, this.getDefaultOptions()); | ||
this.setFullCallbacks(callbacks); | ||
} | ||
upload(fileList: File[] | Object): void { | ||
if (!isFileApi) | ||
return; | ||
let files = castFiles(fileList, UploadStatus.uploading); | ||
files.forEach((file: IUploadFile) => this.processFile(file)); | ||
} | ||
upload(fileList: File[] | Object): void { | ||
if (!isFileApi) return; | ||
let files = castFiles(fileList, UploadStatus.uploading); | ||
files.forEach((file: IUploadFile) => this.processFile(file)); | ||
} | ||
getUrl(file: IUploadFile): string { | ||
return typeof this.options.url === 'function' | ||
? (<(file: IUploadFile) => string>this.options.url)(file) | ||
: <string>this.options.url; | ||
} | ||
getUrl(file: IUploadFile): string { | ||
return typeof this.options.url === "function" | ||
? (<(file: IUploadFile) => string>this.options.url)(file) | ||
: <string>this.options.url; | ||
} | ||
private processFile(file: IUploadFile): void { | ||
let xhr = this.createRequest(file); | ||
this.setCallbacks(xhr, file); | ||
this.send(xhr, file); | ||
} | ||
private processFile(file: IUploadFile): void { | ||
let xhr = this.createRequest(file); | ||
this.setCallbacks(xhr, file); | ||
this.send(xhr, file); | ||
} | ||
private createRequest(file: IUploadFile): XMLHttpRequest { | ||
let xhr = new XMLHttpRequest(); | ||
let url = file.url || this.getUrl(file); | ||
xhr.open(this.options.method, url, true); | ||
private createRequest(file: IUploadFile): XMLHttpRequest { | ||
let xhr = new XMLHttpRequest(); | ||
let url = file.url || this.getUrl(file); | ||
xhr.open(this.options.method, url, true); | ||
xhr.withCredentials = !!this.options.withCredentials; | ||
this.setHeaders(xhr); | ||
return xhr; | ||
} | ||
xhr.withCredentials = !!this.options.withCredentials; | ||
this.setHeaders(xhr); | ||
return xhr; | ||
} | ||
private setHeaders(xhr: XMLHttpRequest) { | ||
if (!this.options.headers) | ||
return; | ||
private setHeaders(xhr: XMLHttpRequest) { | ||
if (!this.options.headers) return; | ||
if (!this.options.headers['Accept']) | ||
xhr.setRequestHeader('Accept', 'application/json'); | ||
if (!this.options.headers['Cache-Control']) | ||
xhr.setRequestHeader('Cache-Control', 'no-cache'); | ||
if (!this.options.headers['X-Requested-With']) | ||
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); | ||
if (!this.options.headers["Accept"]) | ||
xhr.setRequestHeader("Accept", "application/json"); | ||
if (!this.options.headers["Cache-Control"]) | ||
xhr.setRequestHeader("Cache-Control", "no-cache"); | ||
if (!this.options.headers["X-Requested-With"]) | ||
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); | ||
Object.keys(this.options.headers).forEach((headerName: string) => { | ||
if (!this.options.headers) | ||
return; | ||
let headerValue = this.options.headers[headerName]; | ||
if (headerValue !== undefined && headerValue !== null) | ||
xhr.setRequestHeader(headerName, (headerValue || '').toString()); | ||
}); | ||
} | ||
Object.keys(this.options.headers).forEach((headerName: string) => { | ||
if (!this.options.headers) return; | ||
let headerValue = this.options.headers[headerName]; | ||
if (headerValue !== undefined && headerValue !== null) | ||
xhr.setRequestHeader(headerName, (headerValue || "").toString()); | ||
}); | ||
} | ||
private setCallbacks(xhr: XMLHttpRequest, file: IUploadFile) { | ||
file.cancel = decorateSimpleFunction( | ||
file.cancel, () => { | ||
xhr.abort(); | ||
file.uploadStatus = UploadStatus.canceled; | ||
if (file.onCancel) | ||
file.onCancel(file); | ||
if (this.callbacks.onCancelledCallback) | ||
this.callbacks.onCancelledCallback(file); | ||
private setCallbacks(xhr: XMLHttpRequest, file: IUploadFile) { | ||
file.cancel = decorateSimpleFunction( | ||
file.cancel, | ||
() => { | ||
xhr.abort(); | ||
file.uploadStatus = UploadStatus.canceled; | ||
if (file.onCancel) file.onCancel(file); | ||
if (this.callbacks.onCancelledCallback) | ||
this.callbacks.onCancelledCallback(file); | ||
if (this.callbacks.onFileStateChangedCallback) | ||
this.callbacks.onFileStateChangedCallback(file); | ||
if (this.callbacks.onFileStateChangedCallback) | ||
this.callbacks.onFileStateChangedCallback(file); | ||
if (this.callbacks.onFinishedCallback) | ||
this.callbacks.onFinishedCallback(file); | ||
}, | ||
true); | ||
if (this.callbacks.onFinishedCallback) | ||
this.callbacks.onFinishedCallback(file); | ||
}, | ||
true | ||
); | ||
xhr.onload = () => this.onload(file, xhr); | ||
xhr.onerror = () => this.handleError(file, xhr); | ||
xhr.upload.onprogress = (e: ProgressEvent) => this.updateProgress(file, e); | ||
} | ||
xhr.onload = () => this.onload(file, xhr); | ||
xhr.onerror = () => this.handleError(file, xhr); | ||
xhr.upload.onprogress = (e: ProgressEvent) => this.updateProgress(file, e); | ||
} | ||
private send(xhr: XMLHttpRequest, file: IUploadFile) { | ||
let formData = this.createFormData(file); | ||
if (this.callbacks.onUploadStartedCallback) | ||
this.callbacks.onUploadStartedCallback(file); | ||
private send(xhr: XMLHttpRequest, file: IUploadFile) { | ||
let formData = this.createFormData(file); | ||
if (this.callbacks.onUploadStartedCallback) | ||
this.callbacks.onUploadStartedCallback(file); | ||
if (this.callbacks.onFileStateChangedCallback) | ||
this.callbacks.onFileStateChangedCallback(file); | ||
xhr.send(formData); | ||
if (this.callbacks.onFileStateChangedCallback) | ||
this.callbacks.onFileStateChangedCallback(file); | ||
xhr.send(formData); | ||
} | ||
private createFormData(file: IUploadFile): FormData { | ||
let formData = new FormData(); | ||
if (this.options.params) { | ||
Object.keys(this.options.params).forEach((paramName: string) => { | ||
if (!this.options.params) return; | ||
let paramValue = this.options.params[paramName]; | ||
if (paramValue !== undefined && paramValue !== null) | ||
formData.append(paramName, this.castParamType(paramValue)); | ||
}); | ||
} | ||
private createFormData(file: IUploadFile): FormData { | ||
let formData = new FormData(); | ||
if (this.options.params) { | ||
Object.keys(this.options.params).forEach((paramName: string) => { | ||
if (!this.options.params) | ||
return; | ||
let paramValue = this.options.params[paramName]; | ||
if (paramValue !== undefined && paramValue !== null) | ||
formData.append(paramName, this.castParamType(paramValue)); | ||
}); | ||
} | ||
formData.append("file", file, file.name); | ||
return formData; | ||
} | ||
formData.append('file', file, file.name); | ||
return formData; | ||
} | ||
private castParamType( | ||
param: string | number | boolean | Blob | ||
): string | Blob { | ||
return this.isBoolean(param) || this.isNumber(param) | ||
? param.toString() | ||
: param; | ||
} | ||
private castParamType(param: string | number | boolean | Blob): string | Blob { | ||
return this.isBoolean(param) || this.isNumber(param) ? param.toString() : param; | ||
} | ||
private isNumber(param: string | number | boolean | Blob): param is number { | ||
return typeof param === "number"; | ||
} | ||
private isNumber(param: string | number | boolean | Blob): param is number { | ||
return typeof param === 'number'; | ||
} | ||
private isBoolean(param: string | number | boolean | Blob): param is boolean { | ||
return typeof param === "number"; | ||
} | ||
private isBoolean(param: string | number | boolean | Blob): param is boolean { | ||
return typeof param === 'number'; | ||
private handleError(file: IUploadFile, xhr: XMLHttpRequest): void { | ||
file.uploadStatus = UploadStatus.failed; | ||
this.setResponse(file, xhr); | ||
if (file.onError) { | ||
file.onError(file); | ||
} | ||
private handleError(file: IUploadFile, xhr: XMLHttpRequest): void { | ||
file.uploadStatus = UploadStatus.failed; | ||
this.setResponse(file, xhr); | ||
if (file.onError) { | ||
file.onError(file); | ||
} | ||
if (this.callbacks.onErrorCallback) this.callbacks.onErrorCallback(file); | ||
if (this.callbacks.onFileStateChangedCallback) | ||
this.callbacks.onFileStateChangedCallback(file); | ||
if (this.callbacks.onFinishedCallback) | ||
this.callbacks.onFinishedCallback(file); | ||
} | ||
if (this.callbacks.onErrorCallback) | ||
this.callbacks.onErrorCallback(file); | ||
if (this.callbacks.onFileStateChangedCallback) | ||
this.callbacks.onFileStateChangedCallback(file); | ||
if (this.callbacks.onFinishedCallback) | ||
this.callbacks.onFinishedCallback(file); | ||
private updateProgress(file: IUploadFile, e?: ProgressEvent) { | ||
if (e) { | ||
if (e.lengthComputable) { | ||
file.progress = Math.round(100 * (e.loaded / e.total)); | ||
file.sentBytes = e.loaded; | ||
} else { | ||
file.progress = 0; | ||
file.sentBytes = 0; | ||
} | ||
} else { | ||
file.progress = 100; | ||
file.sentBytes = file.size; | ||
} | ||
private updateProgress(file: IUploadFile, e?: ProgressEvent) { | ||
if (e) { | ||
if (e.lengthComputable) { | ||
file.progress = Math.round(100 * (e.loaded / e.total)); | ||
file.sentBytes = e.loaded; | ||
} else { | ||
file.progress = 0; | ||
file.sentBytes = 0; | ||
} | ||
} else { | ||
file.progress = 100; | ||
file.sentBytes = file.size; | ||
} | ||
if (this.callbacks.onProgressCallback) | ||
this.callbacks.onProgressCallback(file); | ||
} | ||
if (this.callbacks.onProgressCallback) | ||
this.callbacks.onProgressCallback(file); | ||
} | ||
private onload(file: IUploadFile, xhr: XMLHttpRequest) { | ||
if (xhr.readyState !== 4) return; | ||
private onload(file: IUploadFile, xhr: XMLHttpRequest) { | ||
if (xhr.readyState !== 4) | ||
return; | ||
if (file.progress !== 100) this.updateProgress(file); | ||
if (file.progress !== 100) | ||
this.updateProgress(file); | ||
if (xhr.status === 200) { | ||
this.finished(file, xhr); | ||
} else { | ||
this.handleError(file, xhr); | ||
} | ||
if (xhr.status === 200) { | ||
this.finished(file, xhr); | ||
} else { | ||
this.handleError(file, xhr); | ||
} | ||
} | ||
private finished(file: IUploadFile, xhr: XMLHttpRequest) { | ||
file.uploadStatus = UploadStatus.uploaded; | ||
this.setResponse(file, xhr); | ||
private finished(file: IUploadFile, xhr: XMLHttpRequest) { | ||
file.uploadStatus = UploadStatus.uploaded; | ||
this.setResponse(file, xhr); | ||
if (this.callbacks.onUploadedCallback) | ||
this.callbacks.onUploadedCallback(file); | ||
if (this.callbacks.onFileStateChangedCallback) | ||
this.callbacks.onFileStateChangedCallback(file); | ||
if (this.callbacks.onFinishedCallback) | ||
this.callbacks.onFinishedCallback(file); | ||
}; | ||
if (this.callbacks.onUploadedCallback) | ||
this.callbacks.onUploadedCallback(file); | ||
if (this.callbacks.onFileStateChangedCallback) | ||
this.callbacks.onFileStateChangedCallback(file); | ||
if (this.callbacks.onFinishedCallback) | ||
this.callbacks.onFinishedCallback(file); | ||
} | ||
private setResponse(file: IUploadFile, xhr: XMLHttpRequest) { | ||
file.responseCode = xhr.status; | ||
file.responseText = xhr.responseText || xhr.statusText || (xhr.status | ||
? xhr.status.toString() | ||
: '' || this.options.localizer.invalidResponseFromServer()); | ||
} | ||
private setResponse(file: IUploadFile, xhr: XMLHttpRequest) { | ||
file.responseCode = xhr.status; | ||
file.responseText = | ||
xhr.responseText || | ||
xhr.statusText || | ||
(xhr.status | ||
? xhr.status.toString() | ||
: "" || this.options.localizer.invalidResponseFromServer()); | ||
} | ||
private getDefaultOptions(): IFullUploadOptions { | ||
return { | ||
headers: {}, | ||
params: {}, | ||
withCredentials: false, | ||
localizer: getDefaultLocalizer() | ||
} as IFullUploadOptions; | ||
} | ||
private getDefaultOptions(): IFullUploadOptions { | ||
return { | ||
headers: {}, | ||
params: {}, | ||
withCredentials: false, | ||
localizer: getDefaultLocalizer() | ||
} as IFullUploadOptions; | ||
} | ||
private setFullCallbacks(callbacks: IUploadCallbacksExt) { | ||
this.callbacks.onProgressCallback = callbacks.onProgressCallback || (() => { return; }); | ||
this.callbacks.onCancelledCallback = callbacks.onCancelledCallback || (() => { return; }); | ||
this.callbacks.onFinishedCallback = callbacks.onFinishedCallback || (() => { return; }); | ||
this.callbacks.onUploadedCallback = callbacks.onUploadedCallback || (() => { return; }); | ||
this.callbacks.onErrorCallback = callbacks.onErrorCallback || (() => { return; }); | ||
this.callbacks.onUploadStartedCallback = callbacks.onUploadStartedCallback || (() => { return; }); | ||
this.callbacks.onFileStateChangedCallback = callbacks.onFileStateChangedCallback || (() => { return; }); | ||
} | ||
private setFullCallbacks(callbacks: IUploadCallbacksExt) { | ||
this.callbacks.onProgressCallback = | ||
callbacks.onProgressCallback || | ||
(() => { | ||
return; | ||
}); | ||
this.callbacks.onCancelledCallback = | ||
callbacks.onCancelledCallback || | ||
(() => { | ||
return; | ||
}); | ||
this.callbacks.onFinishedCallback = | ||
callbacks.onFinishedCallback || | ||
(() => { | ||
return; | ||
}); | ||
this.callbacks.onUploadedCallback = | ||
callbacks.onUploadedCallback || | ||
(() => { | ||
return; | ||
}); | ||
this.callbacks.onErrorCallback = | ||
callbacks.onErrorCallback || | ||
(() => { | ||
return; | ||
}); | ||
this.callbacks.onUploadStartedCallback = | ||
callbacks.onUploadStartedCallback || | ||
(() => { | ||
return; | ||
}); | ||
this.callbacks.onFileStateChangedCallback = | ||
callbacks.onFileStateChangedCallback || | ||
(() => { | ||
return; | ||
}); | ||
} | ||
} | ||
export class Uploader { | ||
uploadAreas: UploadArea[]; | ||
queue: UploadQueue; | ||
options: IUploadQueueOptions; | ||
export class UploadQueue { | ||
offset: IOffsetInfo = { fileCount: 0, running: false }; | ||
options: IUploadQueueOptions; | ||
callbacks: IUploadQueueCallbacksExt; | ||
queuedFiles: IUploadFile[] = []; | ||
constructor(options: IUploadQueueOptions = {}, callbacks: IUploadQueueCallbacks = {}) { | ||
this.setOptions(options); | ||
this.uploadAreas = []; | ||
this.queue = new UploadQueue(options, callbacks); | ||
} | ||
constructor( | ||
options: IUploadQueueOptions, | ||
callbacks: IUploadQueueCallbacksExt | ||
) { | ||
this.options = options; | ||
this.callbacks = callbacks; | ||
this.setFullOptions(); | ||
this.setFullCallbacks(); | ||
} | ||
setOptions(options: IUploadQueueOptions): void { | ||
this.options = options; | ||
} | ||
addFiles(files: IUploadFile[]): void { | ||
files.forEach(file => { | ||
if ( | ||
!this.queuedFiles.some( | ||
queuedFile => | ||
queuedFile === file || | ||
(!!queuedFile.guid && queuedFile.guid === file.guid) | ||
) | ||
) { | ||
this.queuedFiles.push(file); | ||
registerArea(element: HTMLElement, options: IUploadAreaOptions): UploadArea { | ||
const uploadArea = new UploadArea(element, options, this); | ||
this.uploadAreas.push(uploadArea); | ||
return uploadArea; | ||
} | ||
file.remove = decorateSimpleFunction(file.remove, () => { | ||
this.removeFile(file); | ||
}); | ||
} | ||
unregisterArea(area: UploadArea): void { | ||
const areaIndex = this.uploadAreas.indexOf(area); | ||
if (areaIndex >= 0) { | ||
this.uploadAreas[areaIndex].destroy(); | ||
this.uploadAreas.splice(areaIndex, 1); | ||
if (this.callbacks.onFileAddedCallback) | ||
this.callbacks.onFileAddedCallback(file); | ||
if (file.uploadStatus === UploadStatus.failed) { | ||
if (this.callbacks.onErrorCallback) { | ||
this.callbacks.onErrorCallback(file); | ||
} | ||
} | ||
} | ||
} else { | ||
file.uploadStatus = UploadStatus.queued; | ||
} | ||
}); | ||
export class UploadQueue { | ||
offset: IOffsetInfo = { fileCount: 0, running: false }; | ||
options: IUploadQueueOptions; | ||
callbacks: IUploadQueueCallbacksExt; | ||
queuedFiles: IUploadFile[] = []; | ||
this.filesChanged(); | ||
} | ||
constructor(options: IUploadQueueOptions, callbacks: IUploadQueueCallbacksExt) { | ||
this.options = options; | ||
this.callbacks = callbacks; | ||
this.setFullOptions(); | ||
this.setFullCallbacks(); | ||
} | ||
removeFile(file: IUploadFile, blockRecursive: boolean = false) { | ||
let index = this.queuedFiles.indexOf(file); | ||
addFiles(files: IUploadFile[]): void { | ||
files.forEach(file => { | ||
if (!this.queuedFiles.some(queuedFile => queuedFile === file || (!!queuedFile.guid && queuedFile.guid === file.guid))) { | ||
this.queuedFiles.push(file); | ||
if (index < 0) return; | ||
file.remove = decorateSimpleFunction(file.remove, () => { | ||
this.removeFile(file); | ||
}); | ||
} | ||
this.deactivateFile(file); | ||
this.queuedFiles.splice(index, 1); | ||
if (this.callbacks.onFileAddedCallback) | ||
this.callbacks.onFileAddedCallback(file); | ||
if (this.callbacks.onFileRemovedCallback) | ||
this.callbacks.onFileRemovedCallback(file); | ||
if (file.uploadStatus === UploadStatus.failed) { | ||
if (this.callbacks.onErrorCallback) { | ||
this.callbacks.onErrorCallback(file); | ||
} | ||
} else { | ||
file.uploadStatus = UploadStatus.queued; | ||
} | ||
}); | ||
if (!blockRecursive) this.filesChanged(); | ||
} | ||
this.filesChanged(); | ||
} | ||
clearFiles( | ||
excludeStatuses: UploadStatus[] = [], | ||
cancelProcessing: boolean = false | ||
) { | ||
if (!cancelProcessing) | ||
excludeStatuses = excludeStatuses.concat([ | ||
UploadStatus.queued, | ||
UploadStatus.uploading | ||
]); | ||
removeFile(file: IUploadFile, blockRecursive: boolean = false) { | ||
let index = this.queuedFiles.indexOf(file); | ||
this.queuedFiles | ||
.filter( | ||
(file: IUploadFile) => excludeStatuses.indexOf(file.uploadStatus) < 0 | ||
) | ||
.forEach(file => this.removeFile(file, true)); | ||
if (index < 0) | ||
return; | ||
if (this.callbacks.onQueueChangedCallback) | ||
this.callbacks.onQueueChangedCallback(this.queuedFiles); | ||
} | ||
this.deactivateFile(file); | ||
this.queuedFiles.splice(index, 1); | ||
private filesChanged(): void { | ||
if (this.options.autoRemove) this.removeFinishedFiles(); | ||
if (this.callbacks.onFileRemovedCallback) | ||
this.callbacks.onFileRemovedCallback(file); | ||
if (this.options.autoStart) this.startWaitingFiles(); | ||
if (!blockRecursive) | ||
this.filesChanged(); | ||
} | ||
if (this.callbacks.onQueueChangedCallback) | ||
this.callbacks.onQueueChangedCallback(this.queuedFiles); | ||
clearFiles(excludeStatuses: UploadStatus[] = [], cancelProcessing: boolean = false) { | ||
if (!cancelProcessing) | ||
excludeStatuses = excludeStatuses.concat([UploadStatus.queued, UploadStatus.uploading]); | ||
this.checkAllFinished(); | ||
} | ||
this.queuedFiles | ||
.filter((file: IUploadFile) => excludeStatuses.indexOf(file.uploadStatus) < 0) | ||
.forEach(file => this.removeFile(file, true) | ||
); | ||
private checkAllFinished(): void { | ||
const unfinishedFiles = this.queuedFiles.filter( | ||
file => | ||
[UploadStatus.queued, UploadStatus.uploading].indexOf( | ||
file.uploadStatus | ||
) >= 0 | ||
); | ||
if (this.callbacks.onQueueChangedCallback) | ||
this.callbacks.onQueueChangedCallback(this.queuedFiles); | ||
if (unfinishedFiles.length === 0 && this.callbacks.onAllFinishedCallback) { | ||
this.callbacks.onAllFinishedCallback(); | ||
} | ||
} | ||
private filesChanged(): void { | ||
if (this.options.autoRemove) | ||
this.removeFinishedFiles(); | ||
private setFullOptions(): void { | ||
this.options.maxParallelUploads = this.options.maxParallelUploads || 0; | ||
this.options.parallelBatchOffset = this.options.parallelBatchOffset || 0; | ||
this.options.autoStart = isFileApi && (this.options.autoStart || false); | ||
this.options.autoRemove = this.options.autoRemove || false; | ||
} | ||
if (this.options.autoStart) | ||
this.startWaitingFiles(); | ||
private setFullCallbacks(): void { | ||
this.callbacks.onFileAddedCallback = | ||
this.callbacks.onFileAddedCallback || | ||
(() => { | ||
return; | ||
}); | ||
this.callbacks.onFileRemovedCallback = | ||
this.callbacks.onFileRemovedCallback || | ||
(() => { | ||
return; | ||
}); | ||
this.callbacks.onAllFinishedCallback = | ||
this.callbacks.onAllFinishedCallback || | ||
(() => { | ||
return; | ||
}); | ||
this.callbacks.onQueueChangedCallback = | ||
this.callbacks.onQueueChangedCallback || | ||
(() => { | ||
return; | ||
}); | ||
if (this.callbacks.onQueueChangedCallback) | ||
this.callbacks.onQueueChangedCallback(this.queuedFiles); | ||
this.callbacks.onFileStateChangedCallback = () => this.filesChanged(); | ||
} | ||
this.checkAllFinished(); | ||
} | ||
private startWaitingFiles(): void { | ||
this.getWaitingFiles().forEach(file => file.start()); | ||
} | ||
private checkAllFinished(): void { | ||
const unfinishedFiles = this.queuedFiles | ||
.filter(file => [UploadStatus.queued, UploadStatus.uploading].indexOf(file.uploadStatus) >= 0); | ||
private removeFinishedFiles(): void { | ||
this.queuedFiles | ||
.filter( | ||
file => | ||
[UploadStatus.uploaded, UploadStatus.canceled].indexOf( | ||
file.uploadStatus | ||
) >= 0 | ||
) | ||
.forEach(file => this.removeFile(file, true)); | ||
} | ||
if (unfinishedFiles.length === 0 && this.callbacks.onAllFinishedCallback) { | ||
this.callbacks.onAllFinishedCallback(); | ||
} | ||
} | ||
private deactivateFile(file: IUploadFile) { | ||
if (file.uploadStatus === UploadStatus.uploading) file.cancel(); | ||
private setFullOptions(): void { | ||
this.options.maxParallelUploads = this.options.maxParallelUploads || 0; | ||
this.options.parallelBatchOffset = this.options.parallelBatchOffset || 0; | ||
this.options.autoStart = isFileApi && (this.options.autoStart || false); | ||
this.options.autoRemove = this.options.autoRemove || false; | ||
file.uploadStatus = UploadStatus.removed; | ||
file.cancel = () => { | ||
return; | ||
}; | ||
file.remove = () => { | ||
return; | ||
}; | ||
file.start = () => { | ||
return; | ||
}; | ||
} | ||
} | ||
private getWaitingFiles() { | ||
if (!this.options.autoStart) return []; | ||
private setFullCallbacks(): void { | ||
this.callbacks.onFileAddedCallback = this.callbacks.onFileAddedCallback || (() => { return; }); | ||
this.callbacks.onFileRemovedCallback = this.callbacks.onFileRemovedCallback || (() => { return; }); | ||
this.callbacks.onAllFinishedCallback = this.callbacks.onAllFinishedCallback || (() => { return; }); | ||
this.callbacks.onQueueChangedCallback = this.callbacks.onQueueChangedCallback || (() => { return; }); | ||
let result = this.queuedFiles.filter( | ||
file => file.uploadStatus === UploadStatus.queued | ||
); | ||
this.callbacks.onFileStateChangedCallback = () => this.filesChanged(); | ||
} | ||
if (this.options.maxParallelUploads) { | ||
const uploadingFilesCount = this.queuedFiles.filter( | ||
file => file.uploadStatus === UploadStatus.uploading | ||
).length; | ||
private startWaitingFiles(): void { | ||
this.getWaitingFiles().forEach(file => file.start()); | ||
} | ||
let count = Math.min( | ||
result.length, | ||
this.options.maxParallelUploads - uploadingFilesCount | ||
); | ||
private removeFinishedFiles(): void { | ||
this.queuedFiles | ||
.filter(file => [UploadStatus.uploaded, UploadStatus.canceled].indexOf(file.uploadStatus) >= 0) | ||
.forEach(file => this.removeFile(file, true)); | ||
} | ||
if (count <= 0) { | ||
return []; | ||
} | ||
private deactivateFile(file: IUploadFile) { | ||
if (file.uploadStatus === UploadStatus.uploading) | ||
file.cancel(); | ||
if (this.options.parallelBatchOffset) { | ||
if (!this.offset.running) { | ||
this.startOffset(); | ||
} | ||
file.uploadStatus = UploadStatus.removed; | ||
file.cancel = () => { return; }; | ||
file.remove = () => { return; }; | ||
file.start = () => { return; }; | ||
count = | ||
Math.min( | ||
this.offset.fileCount + count, | ||
this.options.maxParallelUploads | ||
) - this.offset.fileCount; | ||
this.offset.fileCount += count; | ||
} | ||
result = result.slice(0, count); | ||
} | ||
private getWaitingFiles() { | ||
if (!this.options.autoStart) | ||
return []; | ||
return result; | ||
} | ||
let result = this.queuedFiles.filter(file => file.uploadStatus === UploadStatus.queued); | ||
private startOffset() { | ||
this.offset.fileCount = 0; | ||
this.offset.running = true; | ||
if (this.options.maxParallelUploads) { | ||
const uploadingFilesCount = this.queuedFiles.filter(file => file.uploadStatus === UploadStatus.uploading).length; | ||
setTimeout(() => { | ||
this.offset.fileCount = 0; | ||
this.offset.running = false; | ||
this.filesChanged(); | ||
}, this.options.parallelBatchOffset); | ||
} | ||
} | ||
let count = Math.min(result.length, this.options.maxParallelUploads - uploadingFilesCount); | ||
export enum UploadStatus { | ||
queued, | ||
uploading, | ||
uploaded, | ||
failed, | ||
canceled, | ||
removed | ||
} | ||
if (count <= 0) { | ||
return []; | ||
} | ||
export class Uploader { | ||
uploadAreas: UploadArea[]; | ||
queue: UploadQueue; | ||
options: IUploadQueueOptions; | ||
if (this.options.parallelBatchOffset) { | ||
if (!this.offset.running) { | ||
this.startOffset(); | ||
} | ||
constructor( | ||
options: IUploadQueueOptions = {}, | ||
callbacks: IUploadQueueCallbacks = {} | ||
) { | ||
this.options = options; | ||
this.uploadAreas = []; | ||
this.queue = new UploadQueue(options, callbacks); | ||
} | ||
count = Math.min(this.offset.fileCount + count, this.options.maxParallelUploads) - this.offset.fileCount; | ||
this.offset.fileCount += count; | ||
} | ||
registerArea(element: HTMLElement, options: IUploadAreaOptions): UploadArea { | ||
const uploadArea = new UploadArea(element, options, this); | ||
this.uploadAreas.push(uploadArea); | ||
return uploadArea; | ||
} | ||
result = result.slice(0, count); | ||
} | ||
return result; | ||
unregisterArea(area: UploadArea): void { | ||
const areaIndex = this.uploadAreas.indexOf(area); | ||
if (areaIndex >= 0) { | ||
this.uploadAreas[areaIndex].destroy(); | ||
this.uploadAreas.splice(areaIndex, 1); | ||
} | ||
private startOffset() { | ||
this.offset.fileCount = 0; | ||
this.offset.running = true; | ||
setTimeout( | ||
() => { | ||
this.offset.fileCount = 0; | ||
this.offset.running = false; | ||
this.filesChanged(); | ||
}, | ||
this.options.parallelBatchOffset | ||
); | ||
} | ||
} | ||
} | ||
export enum UploadStatus { | ||
queued, | ||
uploading, | ||
uploaded, | ||
failed, | ||
canceled, | ||
removed | ||
} |
{ | ||
"name": "pure-upload", | ||
"version": "4.2.1", | ||
"version": "5.0.0", | ||
"description": "The pure upload library without dependencies", | ||
@@ -13,6 +13,2 @@ "author": { | ||
"email": "trut.cz@gmail.com" | ||
}, | ||
{ | ||
"name": "Marek Horyna", | ||
"email": "marek.horyna@outlook.com" | ||
} | ||
@@ -38,8 +34,7 @@ ], | ||
"@types/cors": "^2.8.0", | ||
"@types/jasmine": "^2.5.43", | ||
"@types/karma": "^0.13.33", | ||
"@types/jasmine": "^2.8.6", | ||
"@types/multer": "0.0.33", | ||
"cors": "^2.8.1", | ||
"express": "^4.14.1", | ||
"gulp": "^3.9.0", | ||
"gulp": "^3.9.1", | ||
"gulp-clean": "^0.3.1", | ||
@@ -67,4 +62,5 @@ "gulp-concat": "^2.6.0", | ||
"run-sequence": "^1.1.2", | ||
"typescript": "^2.3.1" | ||
} | ||
} | ||
"typescript": "^2.7.2" | ||
}, | ||
"dependencies": {} | ||
} |
declare module "pure-upload" { | ||
export function addEventHandler(el: Element | HTMLElement, event: string, handler: (ev: UIEvent) => void): void; | ||
export const isFileApi: boolean; | ||
export function castFiles(fileList: File[] | Object, status?: UploadStatus): IUploadFile[]; | ||
export function decorateSimpleFunction(origFn: () => void, newFn: () => void, newFirst?: boolean): () => void; | ||
export function getUploadCore(options: IUploadOptions, callbacks: IUploadCallbacks): UploadCore; | ||
export function getUploader(options: IUploadQueueOptions, callbacks: IUploadQueueCallbacks): Uploader; | ||
export function getValueOrResult<T>(valueOrGetter?: T | (() => T)): T | undefined; | ||
export function newGuid(): string; | ||
export interface IFileExt extends File { | ||
@@ -20,2 +12,10 @@ kind: string; | ||
} | ||
export function addEventHandler(el: Element | HTMLElement, event: string, handler: EventListenerOrEventListenerObject): void; | ||
export const isFileApi: boolean; | ||
export function castFiles(fileList: File[] | Object, status?: UploadStatus): IUploadFile[]; | ||
export function decorateSimpleFunction(origFn: () => void, newFn: () => void, newFirst?: boolean): () => void; | ||
export function getUploadCore(options: IUploadOptions, callbacks: IUploadCallbacks): UploadCore; | ||
export function getUploader(options: IUploadQueueOptions, callbacks: IUploadQueueCallbacks): Uploader; | ||
export function getValueOrResult<T>(valueOrGetter?: T | (() => T)): T | undefined; | ||
export function newGuid(): string; | ||
export interface IFullUploadAreaOptions extends IUploadAreaOptions { | ||
@@ -116,3 +116,3 @@ maxFileSize: number; | ||
} | ||
export function removeEventHandler(el: HTMLInputElement | Element, event: string, handler: (ev: UIEvent) => void): void; | ||
export function removeEventHandler(el: HTMLInputElement | Element, event: string, handler: EventListenerOrEventListenerObject): void; | ||
export class UploadArea { | ||
@@ -123,11 +123,11 @@ targetElement: HTMLElement; | ||
private uploadCore; | ||
private fileInput; | ||
private fileInput?; | ||
private fileList?; | ||
private unregisterOnClick; | ||
private unregisterOnDrop; | ||
private unregisterOnDragOver; | ||
private unregisterOnDragLeave; | ||
private unregisterOnDragOverGlobal; | ||
private unregisterOnDragLeaveGlobal; | ||
private unregisterOnChange; | ||
private unregisterOnClick?; | ||
private unregisterOnDrop?; | ||
private unregisterOnDragOver?; | ||
private unregisterOnDragLeave?; | ||
private unregisterOnDragOverGlobal?; | ||
private unregisterOnDragLeaveGlobal?; | ||
private unregisterOnChange?; | ||
constructor(targetElement: HTMLElement, options: IUploadAreaOptions, uploader: Uploader); | ||
@@ -183,11 +183,2 @@ start(autoClear?: boolean): void; | ||
} | ||
export class Uploader { | ||
uploadAreas: UploadArea[]; | ||
queue: UploadQueue; | ||
options: IUploadQueueOptions; | ||
constructor(options?: IUploadQueueOptions, callbacks?: IUploadQueueCallbacks); | ||
setOptions(options: IUploadQueueOptions): void; | ||
registerArea(element: HTMLElement, options: IUploadAreaOptions): UploadArea; | ||
unregisterArea(area: UploadArea): void; | ||
} | ||
export class UploadQueue { | ||
@@ -220,2 +211,10 @@ offset: IOffsetInfo; | ||
} | ||
export class Uploader { | ||
uploadAreas: UploadArea[]; | ||
queue: UploadQueue; | ||
options: IUploadQueueOptions; | ||
constructor(options?: IUploadQueueOptions, callbacks?: IUploadQueueCallbacks); | ||
registerArea(element: HTMLElement, options: IUploadAreaOptions): UploadArea; | ||
unregisterArea(area: UploadArea): void; | ||
} | ||
} |
@@ -0,0 +0,0 @@ # Pure-upload |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
29
2085
79590