pure-upload
Advanced tools
Comparing version 1.0.0 to 1.0.1
607
index.js
@@ -0,5 +1,21 @@ | ||
function addEventHandler(el, event, handler) { | ||
if (el.addEventListener) { | ||
el.addEventListener(event, handler); | ||
} | ||
else { | ||
var elem = el; | ||
if (elem.attachEvent) { | ||
elem.attachEvent('on' + event, handler); | ||
} | ||
else { | ||
elem[event] = handler; | ||
} | ||
} | ||
} | ||
exports.addEventHandler = addEventHandler; | ||
exports.isFileApi = !!(window.File && window.FormData); | ||
function castFiles(fileList, status) { | ||
var files; | ||
if (typeof fileList === 'object') { | ||
files = Object.keys(fileList).map(function (key) { return fileList[key]; }); | ||
files = map(keys(fileList), function (key) { return fileList[key]; }); | ||
} | ||
@@ -9,3 +25,3 @@ else { | ||
} | ||
files.forEach(function (file) { | ||
forEach(files, function (file) { | ||
file.uploadStatus = status || file.uploadStatus; | ||
@@ -16,3 +32,3 @@ file.responseCode = file.responseCode || 0; | ||
file.sentBytes = file.sentBytes || 0; | ||
file.cancel = file.cancel || (function () { }); | ||
file.cancel = file.cancel || (function () { return; }); | ||
}); | ||
@@ -22,2 +38,21 @@ return files; | ||
exports.castFiles = castFiles; | ||
function filter(input, filterFn) { | ||
if (!input) | ||
return null; | ||
var result = []; | ||
forEach(input, function (item) { | ||
if (filterFn(item)) | ||
result.push(item); | ||
}); | ||
return result; | ||
} | ||
exports.filter = filter; | ||
function forEach(input, callback) { | ||
if (!input) | ||
return; | ||
for (var i = 0; i < input.length; i++) { | ||
callback(input[i], i); | ||
} | ||
} | ||
exports.forEach = forEach; | ||
function decorateSimpleFunction(origFn, newFn, newFirst) { | ||
@@ -38,4 +73,67 @@ if (newFirst === void 0) { newFirst = false; } | ||
}; | ||
function newGuid() { | ||
var d = new Date().getTime(); | ||
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { | ||
var r = (d + Math.random() * 16) % 16 | 0; | ||
d = Math.floor(d / 16); | ||
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); | ||
}); | ||
return uuid; | ||
} | ||
exports.newGuid = newGuid; | ||
; | ||
function indexOf(input, item) { | ||
if (!input) | ||
return -1; | ||
for (var i = 0; i < input.length; i++) { | ||
if (input[i] === item) | ||
return i; | ||
} | ||
return -1; | ||
} | ||
exports.indexOf = indexOf; | ||
function keys(obj) { | ||
if (Object && Object.keys) | ||
return Object.keys(obj); | ||
var keys = []; | ||
for (var i in obj) { | ||
if (obj.hasOwnProperty(i)) { | ||
keys.push(i); | ||
} | ||
} | ||
return keys; | ||
} | ||
exports.keys = keys; | ||
function map(input, mapper) { | ||
if (!input) | ||
return null; | ||
var result = []; | ||
forEach(input, function (item) { | ||
result.push(mapper(item)); | ||
}); | ||
return result; | ||
} | ||
exports.map = map; | ||
function removeEventHandler(el, event, handler) { | ||
if (el.removeEventListener) { | ||
el.removeEventListener(event, handler); | ||
} | ||
else { | ||
var elem = el; | ||
if (elem.detachEvent) { | ||
elem.detachEvent('on' + event, handler); | ||
} | ||
else { | ||
elem[event] = null; | ||
} | ||
} | ||
} | ||
exports.removeEventHandler = removeEventHandler; | ||
var UploadArea = (function () { | ||
function UploadArea(targetElement, options, uploader) { | ||
function UploadArea(targetElement, options, uploader, formForNoFileApi) { | ||
if (formForNoFileApi) { | ||
this.formForNoFileApi = formForNoFileApi.tagName.toLowerCase() === 'form' | ||
? formForNoFileApi | ||
: formForNoFileApi.getElementsByTagName('form')[0]; | ||
} | ||
this.targetElement = targetElement; | ||
@@ -45,61 +143,302 @@ this.options = options; | ||
this.uploadCore = exports.getUploadCore(this.options, this.uploader.queue.callbacks); | ||
this.setupHiddenInput(); | ||
this.setFullOptions(options); | ||
if (exports.isFileApi) { | ||
this.setupFileApiElements(); | ||
} | ||
else { | ||
this.setupOldSchoolElements(); | ||
} | ||
} | ||
UploadArea.prototype.putFilesToQueue = function (fileList) { | ||
UploadArea.prototype.destroy = function () { | ||
if (exports.isFileApi) { | ||
if (this.unregisterOnClick) | ||
this.unregisterOnClick(); | ||
if (this.unregisterOnDrop) | ||
this.unregisterOnDrop(); | ||
if (this.unregisterOnChange) | ||
this.unregisterOnChange(); | ||
if (this.unregisterOnDragOver) | ||
this.unregisterOnDragOver(); | ||
this.targetElement.removeEventListener('dragover', this.onDrag); | ||
this.targetElement.removeEventListener('drop', this.onDrop); | ||
document.body.removeChild(this.fileInput); | ||
} | ||
else { | ||
if (this.unregisterFormOnChange) | ||
this.unregisterFormOnChange(); | ||
if (this.lastIframe) | ||
this.formForNoFileApi.parentNode.removeChild(this.lastIframe); | ||
if (!this.formForNoFileApiProvided) { | ||
this.formForNoFileApi.parentNode.insertBefore(this.targetElement, this.formForNoFileApi.nextSibling || null); | ||
this.targetElement.parentNode.removeChild(this.formForNoFileApi); | ||
} | ||
} | ||
}; | ||
UploadArea.prototype.setFullOptions = function (options) { | ||
this.options.maxFileSize = options.maxFileSize || 1024; | ||
this.options.allowDragDrop = exports.isFileApi && | ||
(options.allowDragDrop === undefined || options.allowDragDrop === null ? true : options.allowDragDrop); | ||
this.options.clickable = options.clickable === undefined || options.clickable === null ? true : options.clickable; | ||
this.options.accept = options.accept || '*.*'; | ||
this.options.multiple = exports.isFileApi && | ||
(options.multiple === undefined || options.multiple === null ? true : options.multiple); | ||
}; | ||
UploadArea.prototype.putFilesToQueue = function (fileList, form) { | ||
var _this = this; | ||
var uploadFiles = castFiles(fileList); | ||
uploadFiles.forEach(function (file) { | ||
file.start = function () { | ||
_this.uploadCore.upload([file]); | ||
file.start = function () { }; | ||
}; | ||
forEach(uploadFiles, function (file) { | ||
if (_this.validateFile(file)) { | ||
file.start = function () { | ||
_this.uploadCore.upload([file]); | ||
file.start = function () { return; }; | ||
}; | ||
} | ||
}); | ||
this.uploader.queue.addFiles(uploadFiles); | ||
}; | ||
UploadArea.prototype.setupHiddenInput = function () { | ||
UploadArea.prototype.validateFile = function (file) { | ||
if (!this.isFileSizeValid(file)) { | ||
file.uploadStatus = exports.uploadStatus.failed; | ||
file.responseText = !!this.options.localizer | ||
? this.options.localizer('The size of this file exceeds the { maxFileSize } MB limit.', this.options) | ||
: 'The size of this file exceeds the ' + this.options.maxFileSize + ' MB limit.'; | ||
return false; | ||
} | ||
return true; | ||
}; | ||
UploadArea.prototype.setupFileApiElements = function () { | ||
var _this = this; | ||
this.fileInput = document.createElement("input"); | ||
this.fileInput.setAttribute("type", "file"); | ||
this.fileInput.style.display = "none"; | ||
this.fileInput.accept = this.options.accept; | ||
this.fileInput = document.createElement('input'); | ||
this.fileInput.setAttribute('type', 'file'); | ||
this.fileInput.setAttribute('accept', this.options.accept); | ||
this.fileInput.style.display = 'none'; | ||
if (this.formForNoFileApi) | ||
this.formForNoFileApi.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); }; | ||
if (this.options.multiple) { | ||
this.fileInput.setAttribute("multiple", ""); | ||
this.fileInput.setAttribute('multiple', ''); | ||
} | ||
if (this.uploader.uploaderOptions.autoStart) { | ||
this.fileInput.addEventListener("change", function (e) { | ||
console.log("changed"); | ||
console.log(e); | ||
_this.putFilesToQueue(e.target.files); | ||
}); | ||
} | ||
if (this.options.clickable) { | ||
this.targetElement.addEventListener("click", function (e) { | ||
_this.fileInput.click(); | ||
}); | ||
var onClick = function () { return _this.onClick(); }; | ||
addEventHandler(this.targetElement, 'click', onClick); | ||
this.unregisterOnClick = function () { return removeEventHandler(_this.targetElement, 'click', onClick); }; | ||
} | ||
if (this.options.allowDragDrop) { | ||
this.targetElement.addEventListener("dragover", function (e) { | ||
var efct; | ||
try { | ||
efct = e.dataTransfer.effectAllowed; | ||
var onDrag = function (e) { return _this.onDrag(e); }; | ||
addEventHandler(this.targetElement, 'dragover', onDrag); | ||
this.unregisterOnDragOver = function () { return removeEventHandler(_this.targetElement, 'dragover', onDrag); }; | ||
var onDrop = function (e) { return _this.onDrop(e); }; | ||
addEventHandler(this.targetElement, 'drop', onDrop); | ||
this.unregisterOnDrop = function () { return removeEventHandler(_this.targetElement, 'drop', onDrop); }; | ||
} | ||
// attach to body | ||
document.body.appendChild(this.fileInput); | ||
}; | ||
UploadArea.prototype.setupOldSchoolElements = function () { | ||
var _this = this; | ||
if (!this.options.clickable) | ||
return; | ||
if (this.formForNoFileApi) { | ||
this.decorateInputForm(); | ||
} | ||
else { | ||
this.createFormWrapper(); | ||
} | ||
var submitInput = this.findInnerSubmit(); | ||
var handler = function (e) { return _this.onFormChange(e, _this.fileInput, submitInput); }; | ||
addEventHandler(this.fileInput, 'change', handler); | ||
this.unregisterFormOnChange = function () { return removeEventHandler(_this.fileInput, 'change', handler); }; | ||
}; | ||
UploadArea.prototype.createFormWrapper = function () { | ||
this.fileInput = document.createElement('input'); | ||
this.fileInput.setAttribute('type', 'file'); | ||
this.fileInput.setAttribute('accept', this.options.accept); | ||
this.fileInput.setAttribute('name', 'file'); | ||
this.fileInput.style.position = 'absolute'; | ||
this.fileInput.style.left = '0'; | ||
this.fileInput.style.right = '0'; | ||
this.fileInput.style.top = '0'; | ||
this.fileInput.style.bottom = '0'; | ||
this.fileInput.style.width = '100%'; | ||
this.fileInput.style.height = '100%'; | ||
this.fileInput.style.fontSize = '10000%'; //IE one click | ||
this.fileInput.style.opacity = '0'; | ||
this.fileInput.style.filter = 'alpha(opacity=0)'; | ||
this.fileInput.style.cursor = 'pointer'; | ||
this.formForNoFileApi = document.createElement('form'); | ||
this.formForNoFileApi.setAttribute('method', this.uploadCore.options.method); | ||
this.formForNoFileApi.setAttribute('enctype', 'multipart/form-data'); | ||
this.formForNoFileApi.setAttribute('encoding', 'multipart/form-data'); | ||
this.formForNoFileApi.style.position = 'relative'; | ||
this.formForNoFileApi.style.display = 'inline-block'; | ||
this.formForNoFileApi.style.overflow = 'hidden'; | ||
this.formForNoFileApi.style.width = this.targetElement.offsetWidth.toString() + 'px'; | ||
this.formForNoFileApi.style.height = this.targetElement.offsetHeight.toString() + 'px'; | ||
if (this.targetElement.clientHeight === 0 || this.targetElement.clientWidth === 0) { | ||
console.warn('upload element height and width has to be set to be able catch upload'); | ||
} | ||
this.targetElement.parentNode.insertBefore(this.formForNoFileApi, this.targetElement.nextSibling || null); | ||
this.formForNoFileApi.appendChild(this.targetElement); | ||
this.formForNoFileApi.appendChild(this.fileInput); | ||
}; | ||
UploadArea.prototype.decorateInputForm = function () { | ||
this.formForNoFileApiProvided = true; | ||
this.targetElement.style.display = 'none'; | ||
this.formForNoFileApi.setAttribute('method', this.uploadCore.options.method); | ||
this.formForNoFileApi.setAttribute('enctype', 'multipart/form-data'); | ||
this.formForNoFileApi.setAttribute('encoding', 'multipart/form-data'); | ||
var submitInput; | ||
var inputs = this.formForNoFileApi.getElementsByTagName('input'); | ||
for (var i = 0; i < inputs.length; i++) { | ||
var el = inputs[i]; | ||
if (el.type === 'file') { | ||
this.fileInput = el; | ||
} | ||
} | ||
}; | ||
UploadArea.prototype.findInnerSubmit = function () { | ||
var inputs = this.formForNoFileApi.getElementsByTagName('input'); | ||
for (var i = 0; i < inputs.length; i++) { | ||
var el = inputs[i]; | ||
if (el.type === 'submit') { | ||
return el; | ||
} | ||
} | ||
return undefined; | ||
}; | ||
UploadArea.prototype.onFormChange = function (e, fileInput, submitInput) { | ||
var files = e.target | ||
? e.target.files | ||
? e.target.files | ||
: e.target.value | ||
? [{ name: e.target.value.replace(/^.+\\/, '') }] | ||
: [] | ||
: fileInput.value | ||
? [{ name: fileInput.value.replace(/^.+\\/, '') }] | ||
: []; | ||
forEach(files, function (file) { | ||
file.guid = file.guid || newGuid(); | ||
}); | ||
if (files.length === 0) | ||
return; | ||
this.addTargetIframe(); | ||
this.formForNoFileApi.setAttribute('action', this.uploadCore.getUrl(files[0])); | ||
if (!submitInput) { | ||
this.formForNoFileApi.submit(); | ||
} | ||
}; | ||
UploadArea.prototype.addTargetIframe = function () { | ||
if (this.lastIframe) { | ||
this.formForNoFileApi.parentNode.removeChild(this.lastIframe); | ||
} | ||
var iframeName = 'uploadIframe' + Date.now(); | ||
var iframe = this.lastIframe = document.createElement('iframe'); | ||
iframe.setAttribute('id', iframeName); | ||
iframe.setAttribute('name', iframeName); | ||
iframe.style.border = 'none'; | ||
iframe.style.display = 'none'; | ||
iframe.style.width = '0'; | ||
iframe.style.height = '0'; | ||
this.formForNoFileApi.setAttribute('target', iframeName); | ||
this.formForNoFileApi.parentNode.insertBefore(iframe, this.formForNoFileApi.nextSibling || null); | ||
window.frames[iframeName].name = iframeName; | ||
}; | ||
UploadArea.prototype.onChange = function (e) { | ||
this.putFilesToQueue(e.target.files, this.fileInput); | ||
}; | ||
UploadArea.prototype.onDrag = function (e) { | ||
var efct; | ||
try { | ||
efct = e.dataTransfer.effectAllowed; | ||
} | ||
catch (err) { | ||
; | ||
} | ||
e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; | ||
this.stopEventPropagation(e); | ||
}; | ||
UploadArea.prototype.onDrop = function (e) { | ||
this.stopEventPropagation(e); | ||
if (!e.dataTransfer) { | ||
return; | ||
} | ||
var files = e.dataTransfer.files; | ||
if (files.length) { | ||
if (!this.options.multiple) | ||
files = [files[0]]; | ||
var result; | ||
var items = e.dataTransfer.items; | ||
if (items && items.length && (items[0].webkitGetAsEntry !== null)) { | ||
if (!this.options.multiple) | ||
items = [items[0]]; | ||
this.addFilesFromItems(items); | ||
} | ||
else { | ||
this.handleFiles(files); | ||
} | ||
} | ||
}; | ||
UploadArea.prototype.onClick = function () { | ||
this.fileInput.value = ''; | ||
this.fileInput.click(); | ||
}; | ||
UploadArea.prototype.addFilesFromItems = function (items) { | ||
var entry; | ||
for (var i = 0; i < items.length; i++) { | ||
var item = items[i]; | ||
if ((item.webkitGetAsEntry) && (entry = item.webkitGetAsEntry())) { | ||
if (entry.isFile) { | ||
this.putFilesToQueue([item.getAsFile()], this.fileInput); | ||
} | ||
catch (_error) { } | ||
e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; | ||
_this.stopEventPropagation(e); | ||
}); | ||
this.targetElement.addEventListener("drop", function (e) { | ||
if (!e.dataTransfer) { | ||
return; | ||
else if (entry.isDirectory) { | ||
this.processDirectory(entry, entry.name); | ||
} | ||
var files = e.dataTransfer.files; | ||
if (files.length) { | ||
var items = e.dataTransfer.files; | ||
_this.putFilesToQueue(items); | ||
} | ||
else if (item.getAsFile) { | ||
if (!item.kind || item.kind === 'file') { | ||
this.putFilesToQueue([item.getAsFile()], this.fileInput); | ||
} | ||
_this.stopEventPropagation(e); | ||
}); | ||
} | ||
} | ||
// attach to body | ||
document.body.appendChild(this.fileInput); | ||
}; | ||
UploadArea.prototype.processDirectory = function (directory, path) { | ||
var _this = this; | ||
var dirReader = directory.createReader(); | ||
var self = this; | ||
var entryReader = function (entries) { | ||
for (var i = 0; i < entries.length; i++) { | ||
var entry = entries[i]; | ||
if (entry.isFile) { | ||
entry.file(function (file) { | ||
if (file.name.substring(0, 1) === '.') { | ||
return; | ||
} | ||
file.fullPath = '' + path + '/' + file.name; | ||
self.putFilesToQueue([file], _this.fileInput); | ||
}); | ||
} | ||
else if (entry.isDirectory) { | ||
self.processDirectory(entry, '' + path + '/' + entry.name); | ||
} | ||
} | ||
}; | ||
dirReader.readEntries(entryReader, function (error) { | ||
return typeof console !== 'undefined' && console !== null | ||
? typeof console.log === 'function' ? console.log(error) : void 0 | ||
: void 0; | ||
}); | ||
}; | ||
UploadArea.prototype.handleFiles = function (files) { | ||
for (var i = 0; i < files.length; i++) { | ||
this.putFilesToQueue([files[i]], this.fileInput); | ||
} | ||
}; | ||
UploadArea.prototype.isFileSizeValid = function (file) { | ||
var maxFileSize = this.options.maxFileSize * 1024 * 1024; // max file size in bytes | ||
if (file.size > maxFileSize) | ||
return false; | ||
return true; | ||
}; | ||
UploadArea.prototype.stopEventPropagation = function (e) { | ||
@@ -110,6 +449,6 @@ e.stopPropagation(); | ||
} | ||
else { | ||
return e.returnValue = false; | ||
} | ||
}; | ||
UploadArea.prototype.destroy = function () { | ||
document.body.removeChild(this.fileInput); | ||
}; | ||
return UploadArea; | ||
@@ -120,2 +459,3 @@ })(); | ||
function UploadCore(options, callbacks) { | ||
if (callbacks === void 0) { callbacks = {}; } | ||
this.options = options; | ||
@@ -128,25 +468,36 @@ this.callbacks = callbacks; | ||
var _this = this; | ||
if (!exports.isFileApi) | ||
return; | ||
var files = castFiles(fileList, exports.uploadStatus.uploading); | ||
files.forEach(function (file) { return _this.processFile(file); }); | ||
forEach(files, function (file) { return _this.processFile(file); }); | ||
}; | ||
UploadCore.prototype.getUrl = function (file) { | ||
return typeof this.options.url === 'function' | ||
? this.options.url(file) | ||
: this.options.url; | ||
}; | ||
UploadCore.prototype.processFile = function (file) { | ||
var xhr = this.createRequest(); | ||
var xhr = this.createRequest(file); | ||
this.setCallbacks(xhr, file); | ||
this.send(xhr, file); | ||
}; | ||
UploadCore.prototype.createRequest = function () { | ||
UploadCore.prototype.createRequest = function (file) { | ||
var xhr = new XMLHttpRequest(); | ||
xhr.open(this.options.method, this.options.url, true); | ||
var url = this.getUrl(file); | ||
xhr.open(this.options.method, url, true); | ||
xhr.withCredentials = !!this.options.withCredentials; | ||
this.setHeaders(xhr); | ||
this.setHeaders(xhr, file.name); | ||
return xhr; | ||
}; | ||
UploadCore.prototype.setHeaders = function (xhr) { | ||
UploadCore.prototype.setHeaders = function (xhr, fileName) { | ||
var _this = this; | ||
this.options.headers['Accept'] = this.options.headers['Accept'] || 'application/json'; | ||
this.options.headers['Cache-Control'] = this.options.headers['Cache-Control'] || 'no-cache'; | ||
this.options.headers['X-Requested-With'] = this.options.headers['X-Requested-With'] || 'XMLHttpRequest'; | ||
Object.keys(this.options.headers).forEach(function (headerName) { | ||
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'); | ||
forEach(keys(this.options.headers), function (headerName) { | ||
var headerValue = _this.options.headers[headerName]; | ||
if (headerValue != undefined) | ||
if (headerValue !== undefined && headerValue !== null) | ||
xhr.setRequestHeader(headerName, headerValue); | ||
@@ -178,5 +529,5 @@ }); | ||
var formData = new FormData(); | ||
Object.keys(this.options.params).forEach(function (paramName) { | ||
forEach(keys(this.options.params), function (paramName) { | ||
var paramValue = _this.options.params[paramName]; | ||
if (paramValue != undefined) | ||
if (paramValue !== undefined && paramValue !== null) | ||
formData.append(paramName, paramValue); | ||
@@ -195,5 +546,11 @@ }); | ||
UploadCore.prototype.updateProgress = function (file, e) { | ||
if (e != null) { | ||
file.progress = Math.round(100 * (e.loaded / e.total)); | ||
file.sentBytes = e.loaded; | ||
if (e !== null) { | ||
if (e.lengthComputable) { | ||
file.progress = Math.round(100 * (e.loaded / e.total)); | ||
file.sentBytes = e.loaded; | ||
} | ||
else { | ||
file.progress = 0; | ||
file.sentBytes = 0; | ||
} | ||
} | ||
@@ -204,3 +561,2 @@ else { | ||
} | ||
file.uploadStatus = file.progress === 100 ? exports.uploadStatus.uploaded : exports.uploadStatus.uploading; | ||
this.callbacks.onProgressCallback(file); | ||
@@ -211,8 +567,10 @@ }; | ||
return; | ||
if (file.progress != 100) | ||
if (file.progress !== 100) | ||
this.updateProgress(file); | ||
if (xhr.status === 200) | ||
if (xhr.status === 200) { | ||
this.finished(file, xhr); | ||
else | ||
} | ||
else { | ||
this.handleError(file, xhr); | ||
} | ||
}; | ||
@@ -229,19 +587,25 @@ UploadCore.prototype.finished = function (file, xhr) { | ||
file.responseCode = xhr.status; | ||
file.responseText = (xhr.statusText || xhr.status ? xhr.status.toString() : '' || 'Invalid response from server'); | ||
var response = xhr.responseText || xhr.statusText || (xhr.status | ||
? xhr.status.toString() | ||
: '' || 'Invalid response from server'); | ||
file.responseText = !!this.options.localizer | ||
? this.options.localizer(response, {}) | ||
: response; | ||
}; | ||
UploadCore.prototype.setFullOptions = function (options) { | ||
this.options.url = options.url, | ||
this.options.method = options.method, | ||
this.options.headers = options.headers || {}, | ||
this.options.params = options.params || {}, | ||
this.options.withCredentials = options.withCredentials || false; | ||
this.options.url = options.url; | ||
this.options.method = options.method; | ||
this.options.headers = options.headers || {}; | ||
this.options.params = options.params || {}; | ||
this.options.withCredentials = options.withCredentials || false; | ||
this.options.localizer = options.localizer; | ||
}; | ||
UploadCore.prototype.setFullCallbacks = function (callbacks) { | ||
this.callbacks.onProgressCallback = callbacks.onProgressCallback || (function () { }), | ||
this.callbacks.onCancelledCallback = callbacks.onCancelledCallback || (function () { }), | ||
this.callbacks.onFinishedCallback = callbacks.onFinishedCallback || (function () { }), | ||
this.callbacks.onUploadedCallback = callbacks.onUploadedCallback || (function () { }), | ||
this.callbacks.onErrorCallback = callbacks.onErrorCallback || (function () { }), | ||
this.callbacks.onUploadStartedCallback = callbacks.onUploadStartedCallback || (function () { }); | ||
this.callbacks.onFileStateChangedCallback = callbacks.onFileStateChangedCallback || (function () { }); | ||
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; }); | ||
}; | ||
@@ -253,2 +617,4 @@ return UploadCore; | ||
function Uploader(options, callbacks) { | ||
if (options === void 0) { options = {}; } | ||
if (callbacks === void 0) { callbacks = {}; } | ||
this.setOptions(options); | ||
@@ -259,10 +625,11 @@ this.uploadAreas = []; | ||
Uploader.prototype.setOptions = function (options) { | ||
this.uploaderOptions = options; | ||
this.options = options; | ||
}; | ||
Uploader.prototype.registerArea = function (element, options) { | ||
var uploadArea = new UploadArea(element, options, this); | ||
Uploader.prototype.registerArea = function (element, options, compatibilityForm) { | ||
var uploadArea = new UploadArea(element, options, this, compatibilityForm); | ||
this.uploadAreas.push(uploadArea); | ||
return uploadArea; | ||
}; | ||
Uploader.prototype.unregisterArea = function (area) { | ||
var areaIndex = this.uploadAreas.indexOf(area); | ||
var areaIndex = indexOf(this.uploadAreas, area); | ||
if (areaIndex >= 0) { | ||
@@ -278,5 +645,5 @@ this.uploadAreas[areaIndex].destroy(); | ||
function UploadQueue(options, callbacks) { | ||
this.queuedFiles = []; | ||
this.options = options; | ||
this.callbacks = callbacks; | ||
this.queuedFiles = []; | ||
this.setFullOptions(); | ||
@@ -287,5 +654,5 @@ this.setFullCallbacks(); | ||
var _this = this; | ||
files.forEach(function (file) { | ||
forEach(files, function (file) { | ||
_this.queuedFiles.push(file); | ||
file.uploadStatus = exports.uploadStatus.queued; | ||
file.guid = newGuid(); | ||
file.remove = decorateSimpleFunction(file.remove, function () { | ||
@@ -295,2 +662,10 @@ _this.removeFile(file); | ||
_this.callbacks.onFileAddedCallback(file); | ||
if (file.uploadStatus === exports.uploadStatus.failed) { | ||
if (_this.callbacks.onErrorCallback) { | ||
_this.callbacks.onErrorCallback(file); | ||
} | ||
} | ||
else { | ||
file.uploadStatus = exports.uploadStatus.queued; | ||
} | ||
}); | ||
@@ -301,3 +676,3 @@ this.filesChanged(); | ||
if (blockRecursive === void 0) { blockRecursive = false; } | ||
var index = this.queuedFiles.indexOf(file); | ||
var index = indexOf(this.queuedFiles, file); | ||
if (index < 0) | ||
@@ -311,9 +686,12 @@ return; | ||
}; | ||
UploadQueue.prototype.clearFiles = function () { | ||
UploadQueue.prototype.clearFiles = function (excludeStatuses, cancelProcessing) { | ||
var _this = this; | ||
this.queuedFiles.forEach(function (file) { return _this.deactivateFile(file); }); | ||
this.queuedFiles = []; | ||
if (excludeStatuses === void 0) { excludeStatuses = []; } | ||
if (cancelProcessing === void 0) { cancelProcessing = false; } | ||
if (!cancelProcessing) | ||
excludeStatuses = excludeStatuses.concat([exports.uploadStatus.queued, exports.uploadStatus.uploading]); | ||
forEach(filter(this.queuedFiles, function (file) { return indexOf(excludeStatuses, file.uploadStatus) < 0; }), function (file) { return _this.removeFile(file, true); }); | ||
this.callbacks.onQueueChangedCallback(this.queuedFiles); | ||
}; | ||
UploadQueue.prototype.filesChanged = function () { | ||
this.callbacks.onQueueChangedCallback(this.queuedFiles); | ||
if (this.options.autoRemove) | ||
@@ -323,9 +701,8 @@ this.removeFinishedFiles(); | ||
this.startWaitingFiles(); | ||
this.callbacks.onQueueChangedCallback(this.queuedFiles); | ||
this.checkAllFinished(); | ||
}; | ||
UploadQueue.prototype.checkAllFinished = function () { | ||
var unfinishedFiles = this.queuedFiles | ||
.filter(function (file) { return [exports.uploadStatus.queued, exports.uploadStatus.uploading] | ||
.indexOf(file.uploadStatus) >= 0; }); | ||
if (unfinishedFiles.length == 0) { | ||
var unfinishedFiles = filter(this.queuedFiles, function (file) { return indexOf([exports.uploadStatus.queued, exports.uploadStatus.uploading], file.uploadStatus) >= 0; }); | ||
if (unfinishedFiles.length === 0) { | ||
this.callbacks.onAllFinishedCallback(); | ||
@@ -336,3 +713,3 @@ } | ||
this.options.maxParallelUploads = this.options.maxParallelUploads || 0; | ||
this.options.autoStart = this.options.autoStart || false; | ||
this.options.autoStart = exports.isFileApi && (this.options.autoStart || false); | ||
this.options.autoRemove = this.options.autoRemove || false; | ||
@@ -342,28 +719,25 @@ }; | ||
var _this = this; | ||
this.callbacks.onFileAddedCallback = this.callbacks.onFileAddedCallback || (function () { }); | ||
this.callbacks.onFileRemovedCallback = this.callbacks.onFileRemovedCallback || (function () { }); | ||
this.callbacks.onAllFinishedCallback = this.callbacks.onAllFinishedCallback || (function () { }); | ||
this.callbacks.onQueueChangedCallback = this.callbacks.onQueueChangedCallback || (function () { }); | ||
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(); }; | ||
}; | ||
UploadQueue.prototype.startWaitingFiles = function () { | ||
var files = this.getWaitingFiles().forEach(function (file) { return file.start(); }); | ||
forEach(this.getWaitingFiles(), function (file) { return file.start(); }); | ||
}; | ||
UploadQueue.prototype.removeFinishedFiles = function () { | ||
var _this = this; | ||
this.queuedFiles | ||
.filter(function (file) { return [ | ||
forEach(filter(this.queuedFiles, function (file) { return indexOf([ | ||
exports.uploadStatus.uploaded, | ||
exports.uploadStatus.failed, | ||
exports.uploadStatus.canceled | ||
].indexOf(file.uploadStatus) >= 0; }) | ||
.forEach(function (file) { return _this.removeFile(file, true); }); | ||
], file.uploadStatus) >= 0; }), function (file) { return _this.removeFile(file, true); }); | ||
}; | ||
UploadQueue.prototype.deactivateFile = function (file) { | ||
if (file.uploadStatus == exports.uploadStatus.uploading) | ||
if (file.uploadStatus === exports.uploadStatus.uploading) | ||
file.cancel(); | ||
file.uploadStatus = exports.uploadStatus.removed; | ||
file.cancel = function () { }; | ||
file.remove = function () { }; | ||
file.start = function () { }; | ||
file.cancel = function () { return; }; | ||
file.remove = function () { return; }; | ||
file.start = function () { return; }; | ||
}; | ||
@@ -373,8 +747,5 @@ UploadQueue.prototype.getWaitingFiles = function () { | ||
return []; | ||
var result = this.queuedFiles | ||
.filter(function (file) { return file.uploadStatus == exports.uploadStatus.queued; }); | ||
var result = filter(this.queuedFiles, function (file) { return file.uploadStatus === exports.uploadStatus.queued; }); | ||
if (this.options.maxParallelUploads > 0) { | ||
var uploadingFilesCount = this.queuedFiles | ||
.filter(function (file) { return file.uploadStatus == exports.uploadStatus.uploading; }) | ||
.length; | ||
var uploadingFilesCount = filter(this.queuedFiles, function (file) { return file.uploadStatus === exports.uploadStatus.uploading; }).length; | ||
var count = this.options.maxParallelUploads - uploadingFilesCount; | ||
@@ -381,0 +752,0 @@ if (count <= 0) { |
794
index.ts
@@ -1,6 +0,21 @@ | ||
export function castFiles(fileList: File[]| Object, status?:IUploadStatus): IUploadFile[] { | ||
export function addEventHandler(el: HTMLInputElement | Element, event: string, handler: (ev: UIEvent) => void) { | ||
if (el.addEventListener) { | ||
el.addEventListener(event, handler); | ||
} else { | ||
var elem = <any>el; | ||
if (elem.attachEvent) { | ||
elem.attachEvent('on' + event, handler); | ||
} else { | ||
elem[event] = handler; | ||
} | ||
} | ||
} | ||
export let isFileApi: boolean = !!((<any>window).File && (<any>window).FormData); | ||
export function castFiles(fileList: File[]| Object, status?: IUploadStatus): IUploadFile[] { | ||
let files: IUploadFile[]; | ||
if (typeof fileList === 'object') { | ||
files = Object.keys(fileList).map((key) => fileList[key]); | ||
files = map(keys(fileList), (key) => fileList[key]); | ||
} else { | ||
@@ -10,3 +25,3 @@ files = <IUploadFile[]>fileList; | ||
files.forEach((file: IUploadFile) => { | ||
forEach(files, (file: IUploadFile) => { | ||
file.uploadStatus = status || file.uploadStatus; | ||
@@ -17,3 +32,3 @@ file.responseCode = file.responseCode || 0; | ||
file.sentBytes = file.sentBytes || 0; | ||
file.cancel = file.cancel || (() => { }); | ||
file.cancel = file.cancel || (() => { return; }); | ||
}); | ||
@@ -24,2 +39,23 @@ | ||
export function filter<T>(input: T[], filterFn: (item: T) => boolean): T[] { | ||
if (!input) | ||
return null; | ||
let result: T[] = []; | ||
forEach<T>(input, function(item: T) { | ||
if (filterFn(item)) | ||
result.push(item); | ||
}); | ||
return result; | ||
} | ||
export function forEach<T>(input: T[], callback: (item: T, index?: number) => void): void { | ||
if (!input) | ||
return; | ||
for (var i = 0; i < input.length; i++) { | ||
callback(input[i], i); | ||
} | ||
} | ||
export function decorateSimpleFunction(origFn: () => void, newFn: () => void, newFirst: boolean = false): () => void { | ||
@@ -31,3 +67,3 @@ if (!origFn) | ||
? () => { newFn(); origFn(); } | ||
: () => { origFn(); newFn(); } | ||
: () => { origFn(); newFn(); }; | ||
} | ||
@@ -37,14 +73,47 @@ | ||
return new UploadCore(options, callbacks); | ||
} | ||
}; | ||
export var getUploader = function (options: IUploadQueueOptions, callbacks: IUploadQueueCallbacks): Uploader { | ||
return new Uploader(options, callbacks); | ||
}; | ||
export function newGuid() : string { | ||
var d = new Date().getTime(); | ||
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { | ||
var r = (d + Math.random() * 16) % 16 | 0; | ||
d = Math.floor(d / 16); | ||
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); | ||
}); | ||
return uuid; | ||
}; | ||
export interface IFileExt extends File { | ||
kind: string; | ||
webkitGetAsEntry: () => File; | ||
getAsFile: () => File; | ||
file: (file: any) => void; | ||
isFile: boolean; | ||
isDirectory: boolean; | ||
fullPath: string; | ||
} | ||
export function indexOf<T>(input: T[], item: T): number { | ||
if (!input) | ||
return -1; | ||
for (var i = 0; i < input.length; i++) { | ||
if (input[i] === item) | ||
return i; | ||
} | ||
return -1; | ||
} | ||
export interface IUploadAreaOptions extends IUploadOptions { | ||
maxFileSize: number; | ||
allowDragDrop: boolean; | ||
clickable: boolean; | ||
accept: string; | ||
multiple: boolean; | ||
maxFileSize?: number; | ||
allowDragDrop?: boolean; | ||
clickable?: boolean; | ||
accept?: string; | ||
multiple?: boolean; | ||
} | ||
@@ -66,2 +135,3 @@ | ||
export interface IUploadFile extends File { | ||
guid: string; | ||
uploadStatus: IUploadStatus; | ||
@@ -79,7 +149,8 @@ responseCode: number; | ||
export interface IUploadOptions { | ||
url: string; | ||
url: string | ((file: IUploadFile) => string); | ||
method: string; | ||
withCredentials?: boolean; | ||
headers?: {[key:string]:any} | ||
params?: {[key:string]:any} | ||
headers?: { [key: string]: any }; | ||
params?: { [key: string]: any }; | ||
localizer?: (message: string, params?: Object) => string; | ||
} | ||
@@ -104,26 +175,135 @@ | ||
export interface IUploadStatus { | ||
queued: IUploadStatus, | ||
uploading: IUploadStatus, | ||
uploaded: IUploadStatus, | ||
failed: IUploadStatus, | ||
canceled: IUploadStatus, | ||
queued: IUploadStatus; | ||
uploading: IUploadStatus; | ||
uploaded: IUploadStatus; | ||
failed: IUploadStatus; | ||
canceled: IUploadStatus; | ||
removed: IUploadStatus; | ||
} | ||
export function keys(obj: Object) { | ||
if(Object && Object.keys) | ||
return Object.keys(obj); | ||
let keys = []; | ||
for (let i in obj) { | ||
if (obj.hasOwnProperty(i)) { | ||
keys.push(i); | ||
} | ||
} | ||
return keys; | ||
} | ||
export function map<T, K>(input: T[], mapper: (item: T) => K): K[] { | ||
if (!input) | ||
return null; | ||
let result: K[] = []; | ||
forEach<T>(input, function(item: T) { | ||
result.push(mapper(item)); | ||
}); | ||
return result; | ||
} | ||
export function removeEventHandler(el: HTMLInputElement | Element, event: string, handler: (ev: UIEvent) => void) { | ||
if (el.removeEventListener) { | ||
el.removeEventListener(event, handler); | ||
} else { | ||
var elem = <any>el; | ||
if (elem.detachEvent) { | ||
elem.detachEvent('on' + event, handler); | ||
} else { | ||
elem[event] = null; | ||
} | ||
} | ||
} | ||
export class UploadArea { | ||
public targetElement: HTMLElement; | ||
public options: IUploadAreaOptions; | ||
public uploader: Uploader; | ||
private uploadCore: UploadCore; | ||
private fileInput: HTMLInputElement; | ||
private formForNoFileApi: HTMLFormElement; | ||
private formForNoFileApiProvided: boolean; | ||
private lastIframe: HTMLElement; | ||
private unregisterOnClick: () => void; | ||
private unregisterOnDrop: () => void; | ||
private unregisterOnDragOver: () => void; | ||
private unregisterOnChange: () => void; | ||
private unregisterFormOnChange: () => void; | ||
constructor(public targetElement: Element, public options: IUploadAreaOptions, public uploader: Uploader) { | ||
constructor(targetElement: HTMLElement, options: IUploadAreaOptions, uploader: Uploader, formForNoFileApi?: HTMLFormElement) { | ||
if (formForNoFileApi) { | ||
this.formForNoFileApi = formForNoFileApi.tagName.toLowerCase() === 'form' | ||
? formForNoFileApi | ||
: formForNoFileApi.getElementsByTagName('form')[0]; | ||
} | ||
this.targetElement = targetElement; | ||
this.options = options; | ||
this.uploader = uploader; | ||
this.uploadCore = getUploadCore(this.options, this.uploader.queue.callbacks); | ||
this.setupHiddenInput(); | ||
this.setFullOptions(options); | ||
if (isFileApi) { | ||
this.setupFileApiElements(); | ||
} else { | ||
this.setupOldSchoolElements(); | ||
} | ||
} | ||
private putFilesToQueue(fileList: FileList): void { | ||
destroy(): void { | ||
if (isFileApi) { | ||
if (this.unregisterOnClick) | ||
this.unregisterOnClick(); | ||
if (this.unregisterOnDrop) | ||
this.unregisterOnDrop(); | ||
if (this.unregisterOnChange) | ||
this.unregisterOnChange(); | ||
if (this.unregisterOnDragOver) | ||
this.unregisterOnDragOver(); | ||
this.targetElement.removeEventListener('dragover', this.onDrag); | ||
this.targetElement.removeEventListener('drop', this.onDrop); | ||
document.body.removeChild(this.fileInput); | ||
} else { | ||
if (this.unregisterFormOnChange) | ||
this.unregisterFormOnChange(); | ||
if (this.lastIframe) | ||
this.formForNoFileApi.parentNode.removeChild(this.lastIframe); | ||
if (!this.formForNoFileApiProvided) { | ||
this.formForNoFileApi.parentNode.insertBefore(this.targetElement, this.formForNoFileApi.nextSibling || null); | ||
this.targetElement.parentNode.removeChild(this.formForNoFileApi); | ||
} | ||
} | ||
} | ||
private setFullOptions(options: IUploadAreaOptions): void { | ||
this.options.maxFileSize = options.maxFileSize || 1024; | ||
this.options.allowDragDrop = isFileApi && | ||
(options.allowDragDrop === undefined || options.allowDragDrop === null ? true : options.allowDragDrop); | ||
this.options.clickable = options.clickable === undefined || options.clickable === null ? true : options.clickable; | ||
this.options.accept = options.accept || '*.*'; | ||
this.options.multiple = isFileApi && | ||
(options.multiple === undefined || options.multiple === null ? true : options.multiple); | ||
} | ||
private putFilesToQueue(fileList: FileList | File[], form: HTMLInputElement): void { | ||
var uploadFiles = castFiles(fileList); | ||
uploadFiles.forEach((file: IUploadFile) => { | ||
file.start = () => { | ||
this.uploadCore.upload([file]); | ||
file.start = () => { }; | ||
}; | ||
forEach(uploadFiles, (file: IUploadFile) => { | ||
if (this.validateFile(file)) { | ||
file.start = () => { | ||
this.uploadCore.upload([file]); | ||
file.start = () => { return; }; | ||
}; | ||
} | ||
}); | ||
@@ -133,56 +313,42 @@ this.uploader.queue.addFiles(uploadFiles); | ||
private setupHiddenInput(): void { | ||
this.fileInput = document.createElement("input"); | ||
this.fileInput.setAttribute("type", "file"); | ||
this.fileInput.style.display = "none"; | ||
this.fileInput.accept = this.options.accept; | ||
private validateFile(file: IUploadFile): boolean { | ||
if (!this.isFileSizeValid(file)) { | ||
file.uploadStatus = uploadStatus.failed; | ||
file.responseText = !!this.options.localizer | ||
? this.options.localizer('The size of this file exceeds the { maxFileSize } MB limit.', this.options) | ||
: 'The size of this file exceeds the ' + this.options.maxFileSize + ' MB limit.'; | ||
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.fileInput.style.display = 'none'; | ||
if (this.formForNoFileApi) | ||
this.formForNoFileApi.style.display = 'none'; | ||
var onChange = (e) => this.onChange(e); | ||
addEventHandler(this.fileInput, 'change', onChange); | ||
this.unregisterOnChange = () => removeEventHandler(this.fileInput, 'change', onchange); | ||
if (this.options.multiple) { | ||
this.fileInput.setAttribute("multiple", ""); | ||
this.fileInput.setAttribute('multiple', ''); | ||
} | ||
if (this.uploader.uploaderOptions.autoStart) { | ||
this.fileInput.addEventListener("change", (e: any) => { | ||
console.log("changed"); | ||
console.log(e); | ||
this.putFilesToQueue(e.target.files); | ||
}); | ||
} | ||
if (this.options.clickable) { | ||
this.targetElement.addEventListener("click", (e) => { | ||
this.fileInput.click(); | ||
}); | ||
var onClick = () => this.onClick(); | ||
addEventHandler(this.targetElement, 'click', onClick); | ||
this.unregisterOnClick = () => removeEventHandler(this.targetElement, 'click', onClick); | ||
} | ||
if (this.options.allowDragDrop) { | ||
this.targetElement.addEventListener("dragover", (e: DragEvent) => { | ||
var efct; | ||
try { | ||
efct = e.dataTransfer.effectAllowed; | ||
} catch (_error) { } | ||
e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; | ||
this.stopEventPropagation(e); | ||
}); | ||
var onDrag = (e) => this.onDrag(e); | ||
addEventHandler(this.targetElement, 'dragover', onDrag); | ||
this.unregisterOnDragOver = () => removeEventHandler(this.targetElement, 'dragover', onDrag); | ||
this.targetElement.addEventListener("drop", (e: DragEvent) => { | ||
if (!e.dataTransfer) { | ||
return; | ||
} | ||
var files = e.dataTransfer.files; | ||
if (files.length) { | ||
var items = e.dataTransfer.files; | ||
this.putFilesToQueue(items); | ||
} | ||
this.stopEventPropagation(e); | ||
}); | ||
// this.targetElement.addEventListener("dragenter", (e) => { | ||
// console.log("dragenter"); | ||
// console.log(e); | ||
// }); | ||
// this.targetElement.addEventListener("dragstart", (e) => { | ||
// console.log("dragstart"); | ||
// console.log(e); | ||
// }); | ||
// this.targetElement.addEventListener("dragend", (e) => { | ||
// console.log("dragend"); | ||
// console.log(e); | ||
// }); | ||
var onDrop = (e) => this.onDrop(e); | ||
addEventHandler(this.targetElement, 'drop', onDrop); | ||
this.unregisterOnDrop = () => removeEventHandler(this.targetElement, 'drop', onDrop); | ||
} | ||
@@ -193,2 +359,225 @@ // attach to body | ||
private setupOldSchoolElements(): void { | ||
if (!this.options.clickable) | ||
return; | ||
if (this.formForNoFileApi) { | ||
this.decorateInputForm(); | ||
} else { | ||
this.createFormWrapper(); | ||
} | ||
let submitInput = this.findInnerSubmit(); | ||
let handler = (e) => this.onFormChange(e, this.fileInput, submitInput); | ||
addEventHandler(this.fileInput, 'change', handler); | ||
this.unregisterFormOnChange = () => removeEventHandler(this.fileInput, 'change', handler); | ||
} | ||
private createFormWrapper() { | ||
this.fileInput = document.createElement('input'); | ||
this.fileInput.setAttribute('type', 'file'); | ||
this.fileInput.setAttribute('accept', this.options.accept); | ||
this.fileInput.setAttribute('name', 'file'); | ||
this.fileInput.style.position = 'absolute'; | ||
this.fileInput.style.left = '0'; | ||
this.fileInput.style.right = '0'; | ||
this.fileInput.style.top = '0'; | ||
this.fileInput.style.bottom = '0'; | ||
this.fileInput.style.width = '100%'; | ||
this.fileInput.style.height = '100%'; | ||
this.fileInput.style.fontSize = '10000%'; //IE one click | ||
this.fileInput.style.opacity = '0'; | ||
this.fileInput.style.filter = 'alpha(opacity=0)'; | ||
this.fileInput.style.cursor = 'pointer'; | ||
this.formForNoFileApi = document.createElement('form'); | ||
this.formForNoFileApi.setAttribute('method', this.uploadCore.options.method); | ||
this.formForNoFileApi.setAttribute('enctype', 'multipart/form-data'); | ||
this.formForNoFileApi.setAttribute('encoding', 'multipart/form-data'); | ||
this.formForNoFileApi.style.position = 'relative'; | ||
this.formForNoFileApi.style.display = 'inline-block'; | ||
this.formForNoFileApi.style.overflow = 'hidden'; | ||
this.formForNoFileApi.style.width = this.targetElement.offsetWidth.toString() + 'px'; | ||
this.formForNoFileApi.style.height = this.targetElement.offsetHeight.toString() + 'px'; | ||
if (this.targetElement.clientHeight === 0 || this.targetElement.clientWidth === 0) { | ||
console.warn('upload element height and width has to be set to be able catch upload'); | ||
} | ||
this.targetElement.parentNode.insertBefore(this.formForNoFileApi, this.targetElement.nextSibling || null); | ||
this.formForNoFileApi.appendChild(this.targetElement); | ||
this.formForNoFileApi.appendChild(this.fileInput); | ||
} | ||
private decorateInputForm() { | ||
this.formForNoFileApiProvided = true; | ||
this.targetElement.style.display = 'none'; | ||
this.formForNoFileApi.setAttribute('method', this.uploadCore.options.method); | ||
this.formForNoFileApi.setAttribute('enctype', 'multipart/form-data'); | ||
this.formForNoFileApi.setAttribute('encoding', 'multipart/form-data'); | ||
let submitInput: HTMLInputElement; | ||
let inputs = this.formForNoFileApi.getElementsByTagName('input'); | ||
for (var i = 0; i < inputs.length; i++) { | ||
var el = inputs[i]; | ||
if (el.type === 'file') { | ||
this.fileInput = el; | ||
} | ||
} | ||
} | ||
private findInnerSubmit(): HTMLInputElement { | ||
let inputs = this.formForNoFileApi.getElementsByTagName('input'); | ||
for (var i = 0; i < inputs.length; i++) { | ||
var el = inputs[i]; | ||
if (el.type === 'submit') { | ||
return el; | ||
} | ||
} | ||
return undefined; | ||
} | ||
private onFormChange(e, fileInput: HTMLInputElement, submitInput: HTMLInputElement) { | ||
let files = e.target | ||
? e.target.files | ||
? e.target.files | ||
: e.target.value | ||
? [{ name: e.target.value.replace(/^.+\\/, '') }] | ||
: [] | ||
: fileInput.value | ||
? [{ name: fileInput.value.replace(/^.+\\/, '') }] | ||
: []; | ||
forEach(files, (file: IUploadFile) => { | ||
file.guid = file.guid || newGuid(); | ||
}); | ||
if (files.length === 0) | ||
return; | ||
this.addTargetIframe(); | ||
this.formForNoFileApi.setAttribute('action', this.uploadCore.getUrl(files[0])); | ||
if (!submitInput) { | ||
this.formForNoFileApi.submit(); | ||
} | ||
} | ||
private addTargetIframe() { | ||
if (this.lastIframe) { | ||
this.formForNoFileApi.parentNode.removeChild(this.lastIframe); | ||
} | ||
var iframeName = 'uploadIframe' + Date.now(); | ||
var iframe = this.lastIframe = document.createElement('iframe'); | ||
iframe.setAttribute('id', iframeName); | ||
iframe.setAttribute('name', iframeName); | ||
iframe.style.border = 'none'; | ||
iframe.style.display = 'none'; | ||
iframe.style.width = '0'; | ||
iframe.style.height = '0'; | ||
this.formForNoFileApi.setAttribute('target', iframeName); | ||
this.formForNoFileApi.parentNode.insertBefore(iframe, this.formForNoFileApi.nextSibling || null); | ||
window.frames[iframeName].name = iframeName; | ||
} | ||
private onChange(e): void { | ||
this.putFilesToQueue(e.target.files, this.fileInput); | ||
} | ||
private onDrag(e: DragEvent): void { | ||
var efct; | ||
try { | ||
efct = e.dataTransfer.effectAllowed; | ||
} catch (err) { ; } | ||
e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; | ||
this.stopEventPropagation(e); | ||
} | ||
private onDrop(e: DragEvent): void { | ||
this.stopEventPropagation(e); | ||
if (!e.dataTransfer) { | ||
return; | ||
} | ||
var files: FileList | File[] = e.dataTransfer.files; | ||
if (files.length) { | ||
if (!this.options.multiple) | ||
files = [files[0]]; | ||
let result: FileList; | ||
var items: FileList | File[] = e.dataTransfer.items; | ||
if (items && items.length && ((<any>items[0]).webkitGetAsEntry !== null)) { | ||
if (!this.options.multiple) | ||
items = [items[0]]; | ||
this.addFilesFromItems(items); | ||
} else { | ||
this.handleFiles(files); | ||
} | ||
} | ||
} | ||
private onClick(): void { | ||
this.fileInput.value = ''; | ||
this.fileInput.click(); | ||
} | ||
private addFilesFromItems(items: FileList | File[]): void { | ||
var entry; | ||
for (var i = 0; i < items.length; i++) { | ||
let item: IFileExt = <IFileExt>items[i]; | ||
if ((item.webkitGetAsEntry) && (entry = item.webkitGetAsEntry())) { | ||
if (entry.isFile) { | ||
this.putFilesToQueue([item.getAsFile()], this.fileInput); | ||
} else if (entry.isDirectory) { | ||
this.processDirectory(entry, entry.name); | ||
} | ||
} else if (item.getAsFile) { | ||
if (!item.kind || item.kind === 'file') { | ||
this.putFilesToQueue([item.getAsFile()], this.fileInput); | ||
} | ||
} | ||
} | ||
} | ||
private processDirectory(directory: any, path: string): void { | ||
var dirReader = directory.createReader(); | ||
var self = this; | ||
var entryReader = (entries: IFileExt[]) => { | ||
for (var i = 0; i < entries.length; i++) { | ||
var entry = entries[i]; | ||
if (entry.isFile) { | ||
entry.file((file: IFileExt) => { | ||
if (file.name.substring(0, 1) === '.') { | ||
return; | ||
} | ||
file.fullPath = '' + path + '/' + file.name; | ||
self.putFilesToQueue([file], this.fileInput); | ||
}); | ||
} else if (entry.isDirectory) { | ||
self.processDirectory(entry, '' + path + '/' + entry.name); | ||
} | ||
} | ||
}; | ||
dirReader.readEntries(entryReader, function(error) { | ||
return typeof console !== 'undefined' && console !== null | ||
? typeof console.log === 'function' ? console.log(error) : void 0 | ||
: void 0; | ||
}); | ||
} | ||
private handleFiles(files: FileList | File[]): void { | ||
for (var i = 0; i < files.length; i++) { | ||
this.putFilesToQueue([files[i]], this.fileInput); | ||
} | ||
} | ||
private isFileSizeValid(file: File): boolean { | ||
var maxFileSize = this.options.maxFileSize * 1024 * 1024; // max file size in bytes | ||
if (file.size > maxFileSize) return false; | ||
return true; | ||
} | ||
private stopEventPropagation(e) { | ||
@@ -198,12 +587,15 @@ e.stopPropagation(); | ||
e.preventDefault(); | ||
} else { | ||
return e.returnValue = false; | ||
} | ||
} | ||
destroy() : void { | ||
document.body.removeChild(this.fileInput); | ||
} | ||
} | ||
export class UploadCore { | ||
constructor(public options: IUploadOptions, public callbacks: IUploadCallbacksExt) { | ||
public options: IUploadOptions; | ||
public callbacks: IUploadCallbacksExt; | ||
constructor(options: IUploadOptions, callbacks: IUploadCallbacksExt = {}) { | ||
this.options = options; | ||
this.callbacks = callbacks; | ||
this.setFullOptions(options); | ||
@@ -213,9 +605,17 @@ this.setFullCallbacks(callbacks); | ||
upload(fileList: File[]| Object): void { | ||
upload(fileList: File[] | Object): void { | ||
if (!isFileApi) | ||
return; | ||
var files = castFiles(fileList, uploadStatus.uploading); | ||
files.forEach((file: IUploadFile) => this.processFile(file)); | ||
forEach(files, (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; | ||
} | ||
private processFile(file: IUploadFile): void { | ||
var xhr = this.createRequest(); | ||
var xhr = this.createRequest(file); | ||
this.setCallbacks(xhr, file); | ||
@@ -225,20 +625,25 @@ this.send(xhr, file); | ||
private createRequest(): XMLHttpRequest { | ||
private createRequest(file: IUploadFile): XMLHttpRequest { | ||
var xhr = new XMLHttpRequest(); | ||
xhr.open(this.options.method, this.options.url, true); | ||
var url = this.getUrl(file); | ||
xhr.open(this.options.method, url, true); | ||
xhr.withCredentials = !!this.options.withCredentials; | ||
this.setHeaders(xhr); | ||
this.setHeaders(xhr, file.name); | ||
return xhr; | ||
} | ||
private setHeaders(xhr: XMLHttpRequest) { | ||
this.options.headers['Accept'] = this.options.headers['Accept'] || 'application/json'; | ||
this.options.headers['Cache-Control'] = this.options.headers['Cache-Control'] || 'no-cache'; | ||
this.options.headers['X-Requested-With'] = this.options.headers['X-Requested-With'] || 'XMLHttpRequest'; | ||
private setHeaders(xhr: XMLHttpRequest, fileName: string) { | ||
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) => { | ||
forEach(keys(this.options.headers), (headerName: string) => { | ||
var headerValue = this.options.headers[headerName]; | ||
if (headerValue != undefined) | ||
if (headerValue !== undefined && headerValue !== null) | ||
xhr.setRequestHeader(headerName, headerValue); | ||
}) | ||
}); | ||
} | ||
@@ -248,11 +653,13 @@ | ||
var originalCancelFn = file.cancel; | ||
file.cancel = decorateSimpleFunction(file.cancel, () => { | ||
xhr.abort(); | ||
file.uploadStatus = uploadStatus.canceled; | ||
this.callbacks.onCancelledCallback(file); | ||
this.callbacks.onFileStateChangedCallback(file); | ||
this.callbacks.onFinishedCallback(file); | ||
}, true); | ||
file.cancel = decorateSimpleFunction( | ||
file.cancel, () => { | ||
xhr.abort(); | ||
file.uploadStatus = uploadStatus.canceled; | ||
this.callbacks.onCancelledCallback(file); | ||
this.callbacks.onFileStateChangedCallback(file); | ||
this.callbacks.onFinishedCallback(file); | ||
}, | ||
true); | ||
xhr.onload = (e) => this.onload(file, xhr) | ||
xhr.onload = (e) => this.onload(file, xhr); | ||
xhr.onerror = () => this.handleError(file, xhr); | ||
@@ -263,3 +670,3 @@ xhr.upload.onprogress = (e: ProgressEvent) => this.updateProgress(file, e); | ||
private send(xhr: XMLHttpRequest, file: IUploadFile) { | ||
var formData = this.createFormData(file) | ||
var formData = this.createFormData(file); | ||
this.callbacks.onUploadStartedCallback(file); | ||
@@ -272,7 +679,7 @@ this.callbacks.onFileStateChangedCallback(file); | ||
var formData = new FormData(); | ||
Object.keys(this.options.params).forEach((paramName: string) => { | ||
forEach(keys(this.options.params), (paramName: string) => { | ||
var paramValue = this.options.params[paramName]; | ||
if (paramValue != undefined) | ||
if (paramValue !== undefined && paramValue !== null) | ||
formData.append(paramName, paramValue); | ||
}) | ||
}); | ||
@@ -292,6 +699,10 @@ formData.append('file', file, file.name); | ||
private updateProgress(file: IUploadFile, e?: ProgressEvent) { | ||
if (e != null) { | ||
file.progress = Math.round(100 * (e.loaded / e.total)); | ||
file.sentBytes = e.loaded; | ||
if (e !== null) { | ||
if (e.lengthComputable) { | ||
file.progress = Math.round(100 * (e.loaded / e.total)); | ||
file.sentBytes = e.loaded; | ||
} else { | ||
file.progress = 0; | ||
file.sentBytes = 0; | ||
} | ||
} else { | ||
@@ -302,3 +713,2 @@ file.progress = 100; | ||
file.uploadStatus = file.progress === 100 ? uploadStatus.uploaded : uploadStatus.uploading; | ||
this.callbacks.onProgressCallback(file); | ||
@@ -311,9 +721,10 @@ } | ||
if (file.progress != 100) | ||
if (file.progress !== 100) | ||
this.updateProgress(file); | ||
if (xhr.status === 200) | ||
if (xhr.status === 200) { | ||
this.finished(file, xhr); | ||
else | ||
} else { | ||
this.handleError(file, xhr); | ||
} | ||
} | ||
@@ -331,22 +742,27 @@ | ||
file.responseCode = xhr.status; | ||
file.responseText = (xhr.statusText || xhr.status ? xhr.status.toString() : '' || 'Invalid response from server'); | ||
let response = xhr.responseText || xhr.statusText || (xhr.status | ||
? xhr.status.toString() | ||
: '' || 'Invalid response from server'); | ||
file.responseText = !!this.options.localizer | ||
? this.options.localizer(response, {}) | ||
: response; | ||
} | ||
private setFullOptions(options: IUploadOptions): void { | ||
this.options.url = options.url, | ||
this.options.method = options.method, | ||
this.options.headers = options.headers || {}, | ||
this.options.params = options.params || {}, | ||
this.options.withCredentials = options.withCredentials || false | ||
this.options.url = options.url; | ||
this.options.method = options.method; | ||
this.options.headers = options.headers || {}; | ||
this.options.params = options.params || {}; | ||
this.options.withCredentials = options.withCredentials || false; | ||
this.options.localizer = options.localizer; | ||
} | ||
private setFullCallbacks(callbacks: IUploadCallbacksExt) { | ||
this.callbacks.onProgressCallback = callbacks.onProgressCallback || (() => { }), | ||
this.callbacks.onCancelledCallback = callbacks.onCancelledCallback || (() => { }), | ||
this.callbacks.onFinishedCallback = callbacks.onFinishedCallback || (() => { }), | ||
this.callbacks.onUploadedCallback = callbacks.onUploadedCallback || (() => { }), | ||
this.callbacks.onErrorCallback = callbacks.onErrorCallback || (() => { }), | ||
this.callbacks.onUploadStartedCallback = callbacks.onUploadStartedCallback || (() => { }) | ||
this.callbacks.onFileStateChangedCallback = callbacks.onFileStateChangedCallback || (() => { }) | ||
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; }); | ||
} | ||
@@ -358,24 +774,25 @@ } | ||
queue: UploadQueue; | ||
uploaderOptions: IUploadQueueOptions; | ||
options: IUploadQueueOptions; | ||
constructor(options: IUploadQueueOptions, callbacks: IUploadQueueCallbacks) { | ||
constructor(options: IUploadQueueOptions = {}, callbacks: IUploadQueueCallbacks = {}) { | ||
this.setOptions(options); | ||
this.uploadAreas = []; | ||
this.queue = new UploadQueue(options,callbacks); | ||
this.queue = new UploadQueue(options, callbacks); | ||
} | ||
setOptions(options: IUploadQueueOptions) : void { | ||
this.uploaderOptions = options; | ||
setOptions(options: IUploadQueueOptions): void { | ||
this.options = options; | ||
} | ||
registerArea(element: Element, options: IUploadAreaOptions) : void { | ||
var uploadArea = new UploadArea(element, options, this); | ||
registerArea(element: HTMLElement, options: IUploadAreaOptions, compatibilityForm?: Element): UploadArea { | ||
var uploadArea = new UploadArea(element, options, this, <HTMLFormElement>compatibilityForm); | ||
this.uploadAreas.push(uploadArea); | ||
return uploadArea; | ||
} | ||
unregisterArea(area: UploadArea) : void { | ||
var areaIndex = this.uploadAreas.indexOf(area) | ||
unregisterArea(area: UploadArea): void { | ||
var areaIndex = indexOf(this.uploadAreas, area); | ||
if (areaIndex >= 0) { | ||
this.uploadAreas[areaIndex].destroy(); | ||
this.uploadAreas.splice(areaIndex, 1); | ||
this.uploadAreas[areaIndex].destroy(); | ||
this.uploadAreas.splice(areaIndex, 1); | ||
} | ||
@@ -386,5 +803,9 @@ } | ||
export class UploadQueue { | ||
options: IUploadQueueOptions; | ||
callbacks: IUploadQueueCallbacksExt; | ||
queuedFiles: IUploadFile[] = []; | ||
constructor(public options: IUploadQueueOptions, public callbacks: IUploadQueueCallbacksExt) { | ||
constructor(options: IUploadQueueOptions, callbacks: IUploadQueueCallbacksExt) { | ||
this.options = options; | ||
this.callbacks = callbacks; | ||
this.setFullOptions(); | ||
@@ -395,5 +816,5 @@ this.setFullCallbacks(); | ||
addFiles(files: IUploadFile[]): void { | ||
files.forEach(file => { | ||
forEach(files, file => { | ||
this.queuedFiles.push(file); | ||
file.uploadStatus = uploadStatus.queued; | ||
file.guid = newGuid(); | ||
@@ -405,9 +826,17 @@ file.remove = decorateSimpleFunction(file.remove, () => { | ||
this.callbacks.onFileAddedCallback(file); | ||
if (file.uploadStatus === uploadStatus.failed) { | ||
if (this.callbacks.onErrorCallback) { | ||
this.callbacks.onErrorCallback(file); | ||
} | ||
} else { | ||
file.uploadStatus = uploadStatus.queued; | ||
} | ||
}); | ||
this.filesChanged() | ||
this.filesChanged(); | ||
} | ||
removeFile(file: IUploadFile, blockRecursive: boolean = false) { | ||
var index = this.queuedFiles.indexOf(file); | ||
var index = indexOf(this.queuedFiles, file); | ||
@@ -426,10 +855,15 @@ if (index < 0) | ||
clearFiles() { | ||
this.queuedFiles.forEach(file => this.deactivateFile(file)); | ||
this.queuedFiles = []; | ||
clearFiles(excludeStatuses: IUploadStatus[] = [], cancelProcessing: boolean = false) { | ||
if (!cancelProcessing) | ||
excludeStatuses = excludeStatuses.concat([uploadStatus.queued, uploadStatus.uploading]); | ||
forEach( | ||
filter(this.queuedFiles, (file: IUploadFile) => indexOf(excludeStatuses, file.uploadStatus) < 0), | ||
file => this.removeFile(file, true) | ||
); | ||
this.callbacks.onQueueChangedCallback(this.queuedFiles); | ||
} | ||
private filesChanged(): void { | ||
this.callbacks.onQueueChangedCallback(this.queuedFiles); | ||
if (this.options.autoRemove) | ||
@@ -441,2 +875,4 @@ this.removeFinishedFiles(); | ||
this.callbacks.onQueueChangedCallback(this.queuedFiles); | ||
this.checkAllFinished(); | ||
@@ -446,7 +882,8 @@ } | ||
private checkAllFinished(): void { | ||
var unfinishedFiles = this.queuedFiles | ||
.filter(file=> [uploadStatus.queued, uploadStatus.uploading] | ||
.indexOf(file.uploadStatus) >= 0) | ||
var unfinishedFiles = filter( | ||
this.queuedFiles, | ||
file => indexOf([uploadStatus.queued, uploadStatus.uploading], file.uploadStatus) >= 0 | ||
); | ||
if (unfinishedFiles.length == 0) { | ||
if (unfinishedFiles.length === 0) { | ||
this.callbacks.onAllFinishedCallback(); | ||
@@ -458,3 +895,3 @@ } | ||
this.options.maxParallelUploads = this.options.maxParallelUploads || 0; | ||
this.options.autoStart = this.options.autoStart || false; | ||
this.options.autoStart = isFileApi && (this.options.autoStart || false); | ||
this.options.autoRemove = this.options.autoRemove || false; | ||
@@ -465,6 +902,6 @@ | ||
private setFullCallbacks(): void { | ||
this.callbacks.onFileAddedCallback = this.callbacks.onFileAddedCallback || (() => { }); | ||
this.callbacks.onFileRemovedCallback = this.callbacks.onFileRemovedCallback || (() => { }); | ||
this.callbacks.onAllFinishedCallback = this.callbacks.onAllFinishedCallback || (() => { }); | ||
this.callbacks.onQueueChangedCallback = this.callbacks.onQueueChangedCallback || (() => { }); | ||
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; }); | ||
@@ -475,23 +912,29 @@ this.callbacks.onFileStateChangedCallback = () => this.filesChanged(); | ||
private startWaitingFiles(): void { | ||
var files = this.getWaitingFiles().forEach(file=> file.start()) | ||
forEach(this.getWaitingFiles(), file => file.start()); | ||
} | ||
private removeFinishedFiles(): void { | ||
this.queuedFiles | ||
.filter(file=> [ | ||
uploadStatus.uploaded, | ||
uploadStatus.failed, | ||
uploadStatus.canceled | ||
].indexOf(file.uploadStatus) >= 0) | ||
.forEach(file => this.removeFile(file, true)); | ||
forEach( | ||
filter( | ||
this.queuedFiles, | ||
file => indexOf( | ||
[ | ||
uploadStatus.uploaded, | ||
uploadStatus.canceled | ||
], | ||
file.uploadStatus | ||
) >= 0 | ||
), | ||
file => this.removeFile(file, true) | ||
); | ||
} | ||
private deactivateFile(file: IUploadFile) { | ||
if (file.uploadStatus == uploadStatus.uploading) | ||
if (file.uploadStatus === uploadStatus.uploading) | ||
file.cancel(); | ||
file.uploadStatus = uploadStatus.removed; | ||
file.cancel = () => { }; | ||
file.remove = () => { }; | ||
file.start = () => { }; | ||
file.cancel = () => { return; }; | ||
file.remove = () => { return; }; | ||
file.start = () => { return; }; | ||
} | ||
@@ -503,9 +946,12 @@ | ||
var result = this.queuedFiles | ||
.filter(file=> file.uploadStatus == uploadStatus.queued) | ||
var result = filter( | ||
this.queuedFiles, | ||
file => file.uploadStatus === uploadStatus.queued | ||
); | ||
if (this.options.maxParallelUploads > 0) { | ||
var uploadingFilesCount = this.queuedFiles | ||
.filter(file=> file.uploadStatus == uploadStatus.uploading) | ||
.length; | ||
var uploadingFilesCount = filter( | ||
this.queuedFiles, | ||
file => file.uploadStatus === uploadStatus.uploading | ||
).length; | ||
@@ -512,0 +958,0 @@ var count = this.options.maxParallelUploads - uploadingFilesCount; |
{ | ||
"name": "pure-upload", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "The pure upload library without dependencies", | ||
"author": { | ||
"name": "t.rut, m.horyna" | ||
}, | ||
"contributors": [ | ||
@@ -6,0 +9,0 @@ { |
declare module "pure-upload" { | ||
export function addEventHandler(el: HTMLInputElement | Element, event: string, handler: (ev: UIEvent) => void): void; | ||
export let isFileApi: boolean; | ||
export function castFiles(fileList: File[] | Object, status?: IUploadStatus): IUploadFile[]; | ||
export function filter<T>(input: T[], filterFn: (item: T) => boolean): T[]; | ||
export function forEach<T>(input: T[], callback: (item: T, index?: number) => void): void; | ||
export function decorateSimpleFunction(origFn: () => void, newFn: () => void, newFirst?: boolean): () => void; | ||
export var getUploadCore: (options: IUploadOptions, callbacks: IUploadCallbacks) => UploadCore; | ||
export var getUploader: (options: IUploadQueueOptions, callbacks: IUploadQueueCallbacks) => Uploader; | ||
export function newGuid(): string; | ||
export interface IFileExt extends File { | ||
kind: string; | ||
webkitGetAsEntry: () => File; | ||
getAsFile: () => File; | ||
file: (file: any) => void; | ||
isFile: boolean; | ||
isDirectory: boolean; | ||
fullPath: string; | ||
} | ||
export function indexOf<T>(input: T[], item: T): number; | ||
export interface IUploadAreaOptions extends IUploadOptions { | ||
maxFileSize: number; | ||
allowDragDrop: boolean; | ||
clickable: boolean; | ||
accept: string; | ||
multiple: boolean; | ||
maxFileSize?: number; | ||
allowDragDrop?: boolean; | ||
clickable?: boolean; | ||
accept?: string; | ||
multiple?: boolean; | ||
} | ||
@@ -25,2 +40,3 @@ export interface IUploadCallbacks { | ||
export interface IUploadFile extends File { | ||
guid: string; | ||
uploadStatus: IUploadStatus; | ||
@@ -36,3 +52,3 @@ responseCode: number; | ||
export interface IUploadOptions { | ||
url: string; | ||
url: string | ((file: IUploadFile) => string); | ||
method: string; | ||
@@ -46,2 +62,3 @@ withCredentials?: boolean; | ||
}; | ||
localizer?: (message: string, params?: Object) => string; | ||
} | ||
@@ -69,4 +86,7 @@ export interface IUploadQueueCallbacks extends IUploadCallbacks { | ||
} | ||
export function keys(obj: Object): any[]; | ||
export function map<T, K>(input: T[], mapper: (item: T) => K): K[]; | ||
export function removeEventHandler(el: HTMLInputElement | Element, event: string, handler: (ev: UIEvent) => void): void; | ||
export class UploadArea { | ||
targetElement: Element; | ||
targetElement: HTMLElement; | ||
options: IUploadAreaOptions; | ||
@@ -76,7 +96,31 @@ uploader: Uploader; | ||
private fileInput; | ||
constructor(targetElement: Element, options: IUploadAreaOptions, uploader: Uploader); | ||
private putFilesToQueue(fileList); | ||
private setupHiddenInput(); | ||
private formForNoFileApi; | ||
private formForNoFileApiProvided; | ||
private lastIframe; | ||
private unregisterOnClick; | ||
private unregisterOnDrop; | ||
private unregisterOnDragOver; | ||
private unregisterOnChange; | ||
private unregisterFormOnChange; | ||
constructor(targetElement: HTMLElement, options: IUploadAreaOptions, uploader: Uploader, formForNoFileApi?: HTMLFormElement); | ||
destroy(): void; | ||
private setFullOptions(options); | ||
private putFilesToQueue(fileList, form); | ||
private validateFile(file); | ||
private setupFileApiElements(); | ||
private setupOldSchoolElements(); | ||
private createFormWrapper(); | ||
private decorateInputForm(); | ||
private findInnerSubmit(); | ||
private onFormChange(e, fileInput, submitInput); | ||
private addTargetIframe(); | ||
private onChange(e); | ||
private onDrag(e); | ||
private onDrop(e); | ||
private onClick(); | ||
private addFilesFromItems(items); | ||
private processDirectory(directory, path); | ||
private handleFiles(files); | ||
private isFileSizeValid(file); | ||
private stopEventPropagation(e); | ||
destroy(): void; | ||
} | ||
@@ -86,7 +130,8 @@ export class UploadCore { | ||
callbacks: IUploadCallbacksExt; | ||
constructor(options: IUploadOptions, callbacks: IUploadCallbacksExt); | ||
constructor(options: IUploadOptions, callbacks?: IUploadCallbacksExt); | ||
upload(fileList: File[] | Object): void; | ||
getUrl(file: IUploadFile): string; | ||
private processFile(file); | ||
private createRequest(); | ||
private setHeaders(xhr); | ||
private createRequest(file); | ||
private setHeaders(xhr, fileName); | ||
private setCallbacks(xhr, file); | ||
@@ -106,6 +151,6 @@ private send(xhr, file); | ||
queue: UploadQueue; | ||
uploaderOptions: IUploadQueueOptions; | ||
constructor(options: IUploadQueueOptions, callbacks: IUploadQueueCallbacks); | ||
options: IUploadQueueOptions; | ||
constructor(options?: IUploadQueueOptions, callbacks?: IUploadQueueCallbacks); | ||
setOptions(options: IUploadQueueOptions): void; | ||
registerArea(element: Element, options: IUploadAreaOptions): void; | ||
registerArea(element: HTMLElement, options: IUploadAreaOptions, compatibilityForm?: Element): UploadArea; | ||
unregisterArea(area: UploadArea): void; | ||
@@ -120,3 +165,3 @@ } | ||
removeFile(file: IUploadFile, blockRecursive?: boolean): void; | ||
clearFiles(): void; | ||
clearFiles(excludeStatuses?: IUploadStatus[], cancelProcessing?: boolean): void; | ||
private filesChanged(); | ||
@@ -123,0 +168,0 @@ private checkAllFinished(); |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
71643
1722
1