Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

pure-upload

Package Overview
Dependencies
Maintainers
2
Versions
75
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pure-upload - npm Package Compare versions

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();

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc