summaryrefslogtreecommitdiff
path: root/www/crm/wp-content/plugins/civicrm/civicrm/bower_components/angular-file-upload/src/module.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/crm/wp-content/plugins/civicrm/civicrm/bower_components/angular-file-upload/src/module.js')
-rw-r--r--www/crm/wp-content/plugins/civicrm/civicrm/bower_components/angular-file-upload/src/module.js1322
1 files changed, 1322 insertions, 0 deletions
diff --git a/www/crm/wp-content/plugins/civicrm/civicrm/bower_components/angular-file-upload/src/module.js b/www/crm/wp-content/plugins/civicrm/civicrm/bower_components/angular-file-upload/src/module.js
new file mode 100644
index 00000000..3813fd16
--- /dev/null
+++ b/www/crm/wp-content/plugins/civicrm/civicrm/bower_components/angular-file-upload/src/module.js
@@ -0,0 +1,1322 @@
+'use strict';
+
+/**
+ * Classes
+ *
+ * FileUploader
+ * FileUploader.FileLikeObject
+ * FileUploader.FileItem
+ * FileUploader.FileDirective
+ * FileUploader.FileSelect
+ * FileUploader.FileDrop
+ * FileUploader.FileOver
+ */
+
+module
+
+
+ .value('fileUploaderOptions', {
+ url: '/',
+ alias: 'file',
+ headers: {},
+ queue: [],
+ progress: 0,
+ autoUpload: false,
+ removeAfterUpload: false,
+ method: 'POST',
+ filters: [],
+ formData: [],
+ queueLimit: Number.MAX_VALUE,
+ withCredentials: false
+ })
+
+
+ .factory('FileUploader', ['fileUploaderOptions', '$rootScope', '$http', '$window', '$compile',
+ function(fileUploaderOptions, $rootScope, $http, $window, $compile) {
+ /**
+ * Creates an instance of FileUploader
+ * @param {Object} [options]
+ * @constructor
+ */
+ function FileUploader(options) {
+ var settings = angular.copy(fileUploaderOptions);
+ angular.extend(this, settings, options, {
+ isUploading: false,
+ _nextIndex: 0,
+ _failFilterIndex: -1,
+ _directives: {select: [], drop: [], over: []}
+ });
+
+ // add default filters
+ this.filters.unshift({name: 'queueLimit', fn: this._queueLimitFilter});
+ this.filters.unshift({name: 'folder', fn: this._folderFilter});
+ }
+ /**********************
+ * PUBLIC
+ **********************/
+ /**
+ * Checks a support the html5 uploader
+ * @returns {Boolean}
+ * @readonly
+ */
+ FileUploader.prototype.isHTML5 = !!($window.File && $window.FormData);
+ /**
+ * Adds items to the queue
+ * @param {File|HTMLInputElement|Object|FileList|Array<Object>} files
+ * @param {Object} [options]
+ * @param {Array<Function>|String} filters
+ */
+ FileUploader.prototype.addToQueue = function(files, options, filters) {
+ var list = this.isArrayLikeObject(files) ? files: [files];
+ var arrayOfFilters = this._getFilters(filters);
+ var count = this.queue.length;
+ var addedFileItems = [];
+
+ angular.forEach(list, function(some /*{File|HTMLInputElement|Object}*/) {
+ var temp = new FileUploader.FileLikeObject(some);
+
+ if (this._isValidFile(temp, arrayOfFilters, options)) {
+ var fileItem = new FileUploader.FileItem(this, some, options);
+ addedFileItems.push(fileItem);
+ this.queue.push(fileItem);
+ this._onAfterAddingFile(fileItem);
+ } else {
+ var filter = arrayOfFilters[this._failFilterIndex];
+ this._onWhenAddingFileFailed(temp, filter, options);
+ }
+ }, this);
+
+ if(this.queue.length !== count) {
+ this._onAfterAddingAll(addedFileItems);
+ this.progress = this._getTotalProgress();
+ }
+
+ this._render();
+ if (this.autoUpload) this.uploadAll();
+ };
+ /**
+ * Remove items from the queue. Remove last: index = -1
+ * @param {FileItem|Number} value
+ */
+ FileUploader.prototype.removeFromQueue = function(value) {
+ var index = this.getIndexOfItem(value);
+ var item = this.queue[index];
+ if (item.isUploading) item.cancel();
+ this.queue.splice(index, 1);
+ item._destroy();
+ this.progress = this._getTotalProgress();
+ };
+ /**
+ * Clears the queue
+ */
+ FileUploader.prototype.clearQueue = function() {
+ while(this.queue.length) {
+ this.queue[0].remove();
+ }
+ this.progress = 0;
+ };
+ /**
+ * Uploads a item from the queue
+ * @param {FileItem|Number} value
+ */
+ FileUploader.prototype.uploadItem = function(value) {
+ var index = this.getIndexOfItem(value);
+ var item = this.queue[index];
+ var transport = this.isHTML5 ? '_xhrTransport' : '_iframeTransport';
+
+ item._prepareToUploading();
+ if(this.isUploading) return;
+
+ this.isUploading = true;
+ this[transport](item);
+ };
+ /**
+ * Cancels uploading of item from the queue
+ * @param {FileItem|Number} value
+ */
+ FileUploader.prototype.cancelItem = function(value) {
+ var index = this.getIndexOfItem(value);
+ var item = this.queue[index];
+ var prop = this.isHTML5 ? '_xhr' : '_form';
+ if (item && item.isUploading) item[prop].abort();
+ };
+ /**
+ * Uploads all not uploaded items of queue
+ */
+ FileUploader.prototype.uploadAll = function() {
+ var items = this.getNotUploadedItems().filter(function(item) {
+ return !item.isUploading;
+ });
+ if (!items.length) return;
+
+ angular.forEach(items, function(item) {
+ item._prepareToUploading();
+ });
+ items[0].upload();
+ };
+ /**
+ * Cancels all uploads
+ */
+ FileUploader.prototype.cancelAll = function() {
+ var items = this.getNotUploadedItems();
+ angular.forEach(items, function(item) {
+ item.cancel();
+ });
+ };
+ /**
+ * Returns "true" if value an instance of File
+ * @param {*} value
+ * @returns {Boolean}
+ * @private
+ */
+ FileUploader.prototype.isFile = function(value) {
+ var fn = $window.File;
+ return (fn && value instanceof fn);
+ };
+ /**
+ * Returns "true" if value an instance of FileLikeObject
+ * @param {*} value
+ * @returns {Boolean}
+ * @private
+ */
+ FileUploader.prototype.isFileLikeObject = function(value) {
+ return value instanceof FileUploader.FileLikeObject;
+ };
+ /**
+ * Returns "true" if value is array like object
+ * @param {*} value
+ * @returns {Boolean}
+ */
+ FileUploader.prototype.isArrayLikeObject = function(value) {
+ return (angular.isObject(value) && 'length' in value);
+ };
+ /**
+ * Returns a index of item from the queue
+ * @param {Item|Number} value
+ * @returns {Number}
+ */
+ FileUploader.prototype.getIndexOfItem = function(value) {
+ return angular.isNumber(value) ? value : this.queue.indexOf(value);
+ };
+ /**
+ * Returns not uploaded items
+ * @returns {Array}
+ */
+ FileUploader.prototype.getNotUploadedItems = function() {
+ return this.queue.filter(function(item) {
+ return !item.isUploaded;
+ });
+ };
+ /**
+ * Returns items ready for upload
+ * @returns {Array}
+ */
+ FileUploader.prototype.getReadyItems = function() {
+ return this.queue
+ .filter(function(item) {
+ return (item.isReady && !item.isUploading);
+ })
+ .sort(function(item1, item2) {
+ return item1.index - item2.index;
+ });
+ };
+ /**
+ * Destroys instance of FileUploader
+ */
+ FileUploader.prototype.destroy = function() {
+ angular.forEach(this._directives, function(key) {
+ angular.forEach(this._directives[key], function(object) {
+ object.destroy();
+ }, this);
+ }, this);
+ };
+ /**
+ * Callback
+ * @param {Array} fileItems
+ */
+ FileUploader.prototype.onAfterAddingAll = function(fileItems) {};
+ /**
+ * Callback
+ * @param {FileItem} fileItem
+ */
+ FileUploader.prototype.onAfterAddingFile = function(fileItem) {};
+ /**
+ * Callback
+ * @param {File|Object} item
+ * @param {Object} filter
+ * @param {Object} options
+ * @private
+ */
+ FileUploader.prototype.onWhenAddingFileFailed = function(item, filter, options) {};
+ /**
+ * Callback
+ * @param {FileItem} fileItem
+ */
+ FileUploader.prototype.onBeforeUploadItem = function(fileItem) {};
+ /**
+ * Callback
+ * @param {FileItem} fileItem
+ * @param {Number} progress
+ */
+ FileUploader.prototype.onProgressItem = function(fileItem, progress) {};
+ /**
+ * Callback
+ * @param {Number} progress
+ */
+ FileUploader.prototype.onProgressAll = function(progress) {};
+ /**
+ * Callback
+ * @param {FileItem} item
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ */
+ FileUploader.prototype.onSuccessItem = function(item, response, status, headers) {};
+ /**
+ * Callback
+ * @param {FileItem} item
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ */
+ FileUploader.prototype.onErrorItem = function(item, response, status, headers) {};
+ /**
+ * Callback
+ * @param {FileItem} item
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ */
+ FileUploader.prototype.onCancelItem = function(item, response, status, headers) {};
+ /**
+ * Callback
+ * @param {FileItem} item
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ */
+ FileUploader.prototype.onCompleteItem = function(item, response, status, headers) {};
+ /**
+ * Callback
+ */
+ FileUploader.prototype.onCompleteAll = function() {};
+ /**********************
+ * PRIVATE
+ **********************/
+ /**
+ * Returns the total progress
+ * @param {Number} [value]
+ * @returns {Number}
+ * @private
+ */
+ FileUploader.prototype._getTotalProgress = function(value) {
+ if(this.removeAfterUpload) return value || 0;
+
+ var notUploaded = this.getNotUploadedItems().length;
+ var uploaded = notUploaded ? this.queue.length - notUploaded : this.queue.length;
+ var ratio = 100 / this.queue.length;
+ var current = (value || 0) * ratio / 100;
+
+ return Math.round(uploaded * ratio + current);
+ };
+ /**
+ * Returns array of filters
+ * @param {Array<Function>|String} filters
+ * @returns {Array<Function>}
+ * @private
+ */
+ FileUploader.prototype._getFilters = function(filters) {
+ if (angular.isUndefined(filters)) return this.filters;
+ if (angular.isArray(filters)) return filters;
+ var names = filters.match(/[^\s,]+/g);
+ return this.filters.filter(function(filter) {
+ return names.indexOf(filter.name) !== -1;
+ }, this);
+ };
+ /**
+ * Updates html
+ * @private
+ */
+ FileUploader.prototype._render = function() {
+ if (!$rootScope.$$phase) $rootScope.$apply();
+ };
+ /**
+ * Returns "true" if item is a file (not folder)
+ * @param {File|FileLikeObject} item
+ * @returns {Boolean}
+ * @private
+ */
+ FileUploader.prototype._folderFilter = function(item) {
+ return !!(item.size || item.type);
+ };
+ /**
+ * Returns "true" if the limit has not been reached
+ * @returns {Boolean}
+ * @private
+ */
+ FileUploader.prototype._queueLimitFilter = function() {
+ return this.queue.length < this.queueLimit;
+ };
+ /**
+ * Returns "true" if file pass all filters
+ * @param {File|Object} file
+ * @param {Array<Function>} filters
+ * @param {Object} options
+ * @returns {Boolean}
+ * @private
+ */
+ FileUploader.prototype._isValidFile = function(file, filters, options) {
+ this._failFilterIndex = -1;
+ return !filters.length ? true : filters.every(function(filter) {
+ this._failFilterIndex++;
+ return filter.fn.call(this, file, options);
+ }, this);
+ };
+ /**
+ * Checks whether upload successful
+ * @param {Number} status
+ * @returns {Boolean}
+ * @private
+ */
+ FileUploader.prototype._isSuccessCode = function(status) {
+ return (status >= 200 && status < 300) || status === 304;
+ };
+ /**
+ * Transforms the server response
+ * @param {*} response
+ * @param {Object} headers
+ * @returns {*}
+ * @private
+ */
+ FileUploader.prototype._transformResponse = function(response, headers) {
+ var headersGetter = this._headersGetter(headers);
+ angular.forEach($http.defaults.transformResponse, function(transformFn) {
+ response = transformFn(response, headersGetter);
+ });
+ return response;
+ };
+ /**
+ * Parsed response headers
+ * @param headers
+ * @returns {Object}
+ * @see https://github.com/angular/angular.js/blob/master/src/ng/http.js
+ * @private
+ */
+ FileUploader.prototype._parseHeaders = function(headers) {
+ var parsed = {}, key, val, i;
+
+ if (!headers) return parsed;
+
+ angular.forEach(headers.split('\n'), function(line) {
+ i = line.indexOf(':');
+ key = line.slice(0, i).trim().toLowerCase();
+ val = line.slice(i + 1).trim();
+
+ if (key) {
+ parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
+ }
+ });
+
+ return parsed;
+ };
+ /**
+ * Returns function that returns headers
+ * @param {Object} parsedHeaders
+ * @returns {Function}
+ * @private
+ */
+ FileUploader.prototype._headersGetter = function(parsedHeaders) {
+ return function(name) {
+ if (name) {
+ return parsedHeaders[name.toLowerCase()] || null;
+ }
+ return parsedHeaders;
+ };
+ };
+ /**
+ * The XMLHttpRequest transport
+ * @param {FileItem} item
+ * @private
+ */
+ FileUploader.prototype._xhrTransport = function(item) {
+ var xhr = item._xhr = new XMLHttpRequest();
+ var form = new FormData();
+ var that = this;
+
+ that._onBeforeUploadItem(item);
+
+ angular.forEach(item.formData, function(obj) {
+ angular.forEach(obj, function(value, key) {
+ form.append(key, value);
+ });
+ });
+
+ if ( typeof(item._file.size) != 'number' ) {
+ throw new TypeError('The file specified is no longer valid');
+ }
+
+ form.append(item.alias, item._file, item.file.name);
+
+ xhr.upload.onprogress = function(event) {
+ var progress = Math.round(event.lengthComputable ? event.loaded * 100 / event.total : 0);
+ that._onProgressItem(item, progress);
+ };
+
+ xhr.onload = function() {
+ var headers = that._parseHeaders(xhr.getAllResponseHeaders());
+ var response = that._transformResponse(xhr.response, headers);
+ var gist = that._isSuccessCode(xhr.status) ? 'Success' : 'Error';
+ var method = '_on' + gist + 'Item';
+ that[method](item, response, xhr.status, headers);
+ that._onCompleteItem(item, response, xhr.status, headers);
+ };
+
+ xhr.onerror = function() {
+ var headers = that._parseHeaders(xhr.getAllResponseHeaders());
+ var response = that._transformResponse(xhr.response, headers);
+ that._onErrorItem(item, response, xhr.status, headers);
+ that._onCompleteItem(item, response, xhr.status, headers);
+ };
+
+ xhr.onabort = function() {
+ var headers = that._parseHeaders(xhr.getAllResponseHeaders());
+ var response = that._transformResponse(xhr.response, headers);
+ that._onCancelItem(item, response, xhr.status, headers);
+ that._onCompleteItem(item, response, xhr.status, headers);
+ };
+
+ xhr.open(item.method, item.url, true);
+
+ xhr.withCredentials = item.withCredentials;
+
+ angular.forEach(item.headers, function(value, name) {
+ xhr.setRequestHeader(name, value);
+ });
+
+ xhr.send(form);
+ this._render();
+ };
+ /**
+ * The IFrame transport
+ * @param {FileItem} item
+ * @private
+ */
+ FileUploader.prototype._iframeTransport = function(item) {
+ var form = angular.element('<form style="display: none;" />');
+ var iframe = angular.element('<iframe name="iframeTransport' + Date.now() + '">');
+ var input = item._input;
+ var that = this;
+
+ if (item._form) item._form.replaceWith(input); // remove old form
+ item._form = form; // save link to new form
+
+ that._onBeforeUploadItem(item);
+
+ input.prop('name', item.alias);
+
+ angular.forEach(item.formData, function(obj) {
+ angular.forEach(obj, function(value, key) {
+ var element = angular.element('<input type="hidden" name="' + key + '" />');
+ element.val(value);
+ form.append(element);
+ });
+ });
+
+ form.prop({
+ action: item.url,
+ method: 'POST',
+ target: iframe.prop('name'),
+ enctype: 'multipart/form-data',
+ encoding: 'multipart/form-data' // old IE
+ });
+
+ iframe.bind('load', function() {
+ try {
+ // Fix for legacy IE browsers that loads internal error page
+ // when failed WS response received. In consequence iframe
+ // content access denied error is thrown becouse trying to
+ // access cross domain page. When such thing occurs notifying
+ // with empty response object. See more info at:
+ // http://stackoverflow.com/questions/151362/access-is-denied-error-on-accessing-iframe-document-object
+ // Note that if non standard 4xx or 5xx error code returned
+ // from WS then response content can be accessed without error
+ // but 'XHR' status becomes 200. In order to avoid confusion
+ // returning response via same 'success' event handler.
+
+ // fixed angular.contents() for iframes
+ var html = iframe[0].contentDocument.body.innerHTML;
+ } catch (e) {}
+
+ var xhr = {response: html, status: 200, dummy: true};
+ var headers = {};
+ var response = that._transformResponse(xhr.response, headers);
+
+ that._onSuccessItem(item, response, xhr.status, headers);
+ that._onCompleteItem(item, response, xhr.status, headers);
+ });
+
+ form.abort = function() {
+ var xhr = {status: 0, dummy: true};
+ var headers = {};
+ var response;
+
+ iframe.unbind('load').prop('src', 'javascript:false;');
+ form.replaceWith(input);
+
+ that._onCancelItem(item, response, xhr.status, headers);
+ that._onCompleteItem(item, response, xhr.status, headers);
+ };
+
+ input.after(form);
+ form.append(input).append(iframe);
+
+ form[0].submit();
+ this._render();
+ };
+ /**
+ * Inner callback
+ * @param {File|Object} item
+ * @param {Object} filter
+ * @param {Object} options
+ * @private
+ */
+ FileUploader.prototype._onWhenAddingFileFailed = function(item, filter, options) {
+ this.onWhenAddingFileFailed(item, filter, options);
+ };
+ /**
+ * Inner callback
+ * @param {FileItem} item
+ */
+ FileUploader.prototype._onAfterAddingFile = function(item) {
+ this.onAfterAddingFile(item);
+ };
+ /**
+ * Inner callback
+ * @param {Array<FileItem>} items
+ */
+ FileUploader.prototype._onAfterAddingAll = function(items) {
+ this.onAfterAddingAll(items);
+ };
+ /**
+ * Inner callback
+ * @param {FileItem} item
+ * @private
+ */
+ FileUploader.prototype._onBeforeUploadItem = function(item) {
+ item._onBeforeUpload();
+ this.onBeforeUploadItem(item);
+ };
+ /**
+ * Inner callback
+ * @param {FileItem} item
+ * @param {Number} progress
+ * @private
+ */
+ FileUploader.prototype._onProgressItem = function(item, progress) {
+ var total = this._getTotalProgress(progress);
+ this.progress = total;
+ item._onProgress(progress);
+ this.onProgressItem(item, progress);
+ this.onProgressAll(total);
+ this._render();
+ };
+ /**
+ * Inner callback
+ * @param {FileItem} item
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ * @private
+ */
+ FileUploader.prototype._onSuccessItem = function(item, response, status, headers) {
+ item._onSuccess(response, status, headers);
+ this.onSuccessItem(item, response, status, headers);
+ };
+ /**
+ * Inner callback
+ * @param {FileItem} item
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ * @private
+ */
+ FileUploader.prototype._onErrorItem = function(item, response, status, headers) {
+ item._onError(response, status, headers);
+ this.onErrorItem(item, response, status, headers);
+ };
+ /**
+ * Inner callback
+ * @param {FileItem} item
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ * @private
+ */
+ FileUploader.prototype._onCancelItem = function(item, response, status, headers) {
+ item._onCancel(response, status, headers);
+ this.onCancelItem(item, response, status, headers);
+ };
+ /**
+ * Inner callback
+ * @param {FileItem} item
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ * @private
+ */
+ FileUploader.prototype._onCompleteItem = function(item, response, status, headers) {
+ item._onComplete(response, status, headers);
+ this.onCompleteItem(item, response, status, headers);
+
+ var nextItem = this.getReadyItems()[0];
+ this.isUploading = false;
+
+ if(angular.isDefined(nextItem)) {
+ nextItem.upload();
+ return;
+ }
+
+ this.onCompleteAll();
+ this.progress = this._getTotalProgress();
+ this._render();
+ };
+ /**********************
+ * STATIC
+ **********************/
+ /**
+ * @borrows FileUploader.prototype.isFile
+ */
+ FileUploader.isFile = FileUploader.prototype.isFile;
+ /**
+ * @borrows FileUploader.prototype.isFileLikeObject
+ */
+ FileUploader.isFileLikeObject = FileUploader.prototype.isFileLikeObject;
+ /**
+ * @borrows FileUploader.prototype.isArrayLikeObject
+ */
+ FileUploader.isArrayLikeObject = FileUploader.prototype.isArrayLikeObject;
+ /**
+ * @borrows FileUploader.prototype.isHTML5
+ */
+ FileUploader.isHTML5 = FileUploader.prototype.isHTML5;
+ /**
+ * Inherits a target (Class_1) by a source (Class_2)
+ * @param {Function} target
+ * @param {Function} source
+ */
+ FileUploader.inherit = function(target, source) {
+ target.prototype = Object.create(source.prototype);
+ target.prototype.constructor = target;
+ target.super_ = source;
+ };
+ FileUploader.FileLikeObject = FileLikeObject;
+ FileUploader.FileItem = FileItem;
+ FileUploader.FileDirective = FileDirective;
+ FileUploader.FileSelect = FileSelect;
+ FileUploader.FileDrop = FileDrop;
+ FileUploader.FileOver = FileOver;
+
+ // ---------------------------
+
+ /**
+ * Creates an instance of FileLikeObject
+ * @param {File|HTMLInputElement|Object} fileOrInput
+ * @constructor
+ */
+ function FileLikeObject(fileOrInput) {
+ var isInput = angular.isElement(fileOrInput);
+ var fakePathOrObject = isInput ? fileOrInput.value : fileOrInput;
+ var postfix = angular.isString(fakePathOrObject) ? 'FakePath' : 'Object';
+ var method = '_createFrom' + postfix;
+ this[method](fakePathOrObject);
+ }
+
+ /**
+ * Creates file like object from fake path string
+ * @param {String} path
+ * @private
+ */
+ FileLikeObject.prototype._createFromFakePath = function(path) {
+ this.lastModifiedDate = null;
+ this.size = null;
+ this.type = 'like/' + path.slice(path.lastIndexOf('.') + 1).toLowerCase();
+ this.name = path.slice(path.lastIndexOf('/') + path.lastIndexOf('\\') + 2);
+ };
+ /**
+ * Creates file like object from object
+ * @param {File|FileLikeObject} object
+ * @private
+ */
+ FileLikeObject.prototype._createFromObject = function(object) {
+ this.lastModifiedDate = angular.copy(object.lastModifiedDate);
+ this.size = object.size;
+ this.type = object.type;
+ this.name = object.name;
+ };
+
+ // ---------------------------
+
+ /**
+ * Creates an instance of FileItem
+ * @param {FileUploader} uploader
+ * @param {File|HTMLInputElement|Object} some
+ * @param {Object} options
+ * @constructor
+ */
+ function FileItem(uploader, some, options) {
+ var isInput = angular.isElement(some);
+ var input = isInput ? angular.element(some) : null;
+ var file = !isInput ? some : null;
+
+ angular.extend(this, {
+ url: uploader.url,
+ alias: uploader.alias,
+ headers: angular.copy(uploader.headers),
+ formData: angular.copy(uploader.formData),
+ removeAfterUpload: uploader.removeAfterUpload,
+ withCredentials: uploader.withCredentials,
+ method: uploader.method
+ }, options, {
+ uploader: uploader,
+ file: new FileUploader.FileLikeObject(some),
+ isReady: false,
+ isUploading: false,
+ isUploaded: false,
+ isSuccess: false,
+ isCancel: false,
+ isError: false,
+ progress: 0,
+ index: null,
+ _file: file,
+ _input: input
+ });
+
+ if (input) this._replaceNode(input);
+ }
+ /**********************
+ * PUBLIC
+ **********************/
+ /**
+ * Uploads a FileItem
+ */
+ FileItem.prototype.upload = function() {
+ try {
+ this.uploader.uploadItem(this);
+ } catch (e) {
+ this.uploader._onCompleteItem( this, '', 0, [] );
+ this.uploader._onErrorItem( this, '', 0, [] );
+ }
+ };
+ /**
+ * Cancels uploading of FileItem
+ */
+ FileItem.prototype.cancel = function() {
+ this.uploader.cancelItem(this);
+ };
+ /**
+ * Removes a FileItem
+ */
+ FileItem.prototype.remove = function() {
+ this.uploader.removeFromQueue(this);
+ };
+ /**
+ * Callback
+ * @private
+ */
+ FileItem.prototype.onBeforeUpload = function() {};
+ /**
+ * Callback
+ * @param {Number} progress
+ * @private
+ */
+ FileItem.prototype.onProgress = function(progress) {};
+ /**
+ * Callback
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ */
+ FileItem.prototype.onSuccess = function(response, status, headers) {};
+ /**
+ * Callback
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ */
+ FileItem.prototype.onError = function(response, status, headers) {};
+ /**
+ * Callback
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ */
+ FileItem.prototype.onCancel = function(response, status, headers) {};
+ /**
+ * Callback
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ */
+ FileItem.prototype.onComplete = function(response, status, headers) {};
+ /**********************
+ * PRIVATE
+ **********************/
+ /**
+ * Inner callback
+ */
+ FileItem.prototype._onBeforeUpload = function() {
+ this.isReady = true;
+ this.isUploading = true;
+ this.isUploaded = false;
+ this.isSuccess = false;
+ this.isCancel = false;
+ this.isError = false;
+ this.progress = 0;
+ this.onBeforeUpload();
+ };
+ /**
+ * Inner callback
+ * @param {Number} progress
+ * @private
+ */
+ FileItem.prototype._onProgress = function(progress) {
+ this.progress = progress;
+ this.onProgress(progress);
+ };
+ /**
+ * Inner callback
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ * @private
+ */
+ FileItem.prototype._onSuccess = function(response, status, headers) {
+ this.isReady = false;
+ this.isUploading = false;
+ this.isUploaded = true;
+ this.isSuccess = true;
+ this.isCancel = false;
+ this.isError = false;
+ this.progress = 100;
+ this.index = null;
+ this.onSuccess(response, status, headers);
+ };
+ /**
+ * Inner callback
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ * @private
+ */
+ FileItem.prototype._onError = function(response, status, headers) {
+ this.isReady = false;
+ this.isUploading = false;
+ this.isUploaded = true;
+ this.isSuccess = false;
+ this.isCancel = false;
+ this.isError = true;
+ this.progress = 0;
+ this.index = null;
+ this.onError(response, status, headers);
+ };
+ /**
+ * Inner callback
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ * @private
+ */
+ FileItem.prototype._onCancel = function(response, status, headers) {
+ this.isReady = false;
+ this.isUploading = false;
+ this.isUploaded = false;
+ this.isSuccess = false;
+ this.isCancel = true;
+ this.isError = false;
+ this.progress = 0;
+ this.index = null;
+ this.onCancel(response, status, headers);
+ };
+ /**
+ * Inner callback
+ * @param {*} response
+ * @param {Number} status
+ * @param {Object} headers
+ * @private
+ */
+ FileItem.prototype._onComplete = function(response, status, headers) {
+ this.onComplete(response, status, headers);
+ if (this.removeAfterUpload) this.remove();
+ };
+ /**
+ * Destroys a FileItem
+ */
+ FileItem.prototype._destroy = function() {
+ if (this._input) this._input.remove();
+ if (this._form) this._form.remove();
+ delete this._form;
+ delete this._input;
+ };
+ /**
+ * Prepares to uploading
+ * @private
+ */
+ FileItem.prototype._prepareToUploading = function() {
+ this.index = this.index || ++this.uploader._nextIndex;
+ this.isReady = true;
+ };
+ /**
+ * Replaces input element on his clone
+ * @param {JQLite|jQuery} input
+ * @private
+ */
+ FileItem.prototype._replaceNode = function(input) {
+ var clone = $compile(input.clone())(input.scope());
+ clone.prop('value', null); // FF fix
+ input.css('display', 'none');
+ input.after(clone); // remove jquery dependency
+ };
+
+ // ---------------------------
+
+ /**
+ * Creates instance of {FileDirective} object
+ * @param {Object} options
+ * @param {Object} options.uploader
+ * @param {HTMLElement} options.element
+ * @param {Object} options.events
+ * @param {String} options.prop
+ * @constructor
+ */
+ function FileDirective(options) {
+ angular.extend(this, options);
+ this.uploader._directives[this.prop].push(this);
+ this._saveLinks();
+ this.bind();
+ }
+ /**
+ * Map of events
+ * @type {Object}
+ */
+ FileDirective.prototype.events = {};
+ /**
+ * Binds events handles
+ */
+ FileDirective.prototype.bind = function() {
+ for(var key in this.events) {
+ var prop = this.events[key];
+ this.element.bind(key, this[prop]);
+ }
+ };
+ /**
+ * Unbinds events handles
+ */
+ FileDirective.prototype.unbind = function() {
+ for(var key in this.events) {
+ this.element.unbind(key, this.events[key]);
+ }
+ };
+ /**
+ * Destroys directive
+ */
+ FileDirective.prototype.destroy = function() {
+ var index = this.uploader._directives[this.prop].indexOf(this);
+ this.uploader._directives[this.prop].splice(index, 1);
+ this.unbind();
+ // this.element = null;
+ };
+ /**
+ * Saves links to functions
+ * @private
+ */
+ FileDirective.prototype._saveLinks = function() {
+ for(var key in this.events) {
+ var prop = this.events[key];
+ this[prop] = this[prop].bind(this);
+ }
+ };
+
+ // ---------------------------
+
+ FileUploader.inherit(FileSelect, FileDirective);
+
+ /**
+ * Creates instance of {FileSelect} object
+ * @param {Object} options
+ * @constructor
+ */
+ function FileSelect(options) {
+ FileSelect.super_.apply(this, arguments);
+
+ if(!this.uploader.isHTML5) {
+ this.element.removeAttr('multiple');
+ }
+ this.element.prop('value', null); // FF fix
+ }
+ /**
+ * Map of events
+ * @type {Object}
+ */
+ FileSelect.prototype.events = {
+ $destroy: 'destroy',
+ change: 'onChange'
+ };
+ /**
+ * Name of property inside uploader._directive object
+ * @type {String}
+ */
+ FileSelect.prototype.prop = 'select';
+ /**
+ * Returns options
+ * @return {Object|undefined}
+ */
+ FileSelect.prototype.getOptions = function() {};
+ /**
+ * Returns filters
+ * @return {Array<Function>|String|undefined}
+ */
+ FileSelect.prototype.getFilters = function() {};
+ /**
+ * If returns "true" then HTMLInputElement will be cleared
+ * @returns {Boolean}
+ */
+ FileSelect.prototype.isEmptyAfterSelection = function() {
+ return !!this.element.attr('multiple');
+ };
+ /**
+ * Event handler
+ */
+ FileSelect.prototype.onChange = function() {
+ var files = this.uploader.isHTML5 ? this.element[0].files : this.element[0];
+ var options = this.getOptions();
+ var filters = this.getFilters();
+
+ if (!this.uploader.isHTML5) this.destroy();
+ this.uploader.addToQueue(files, options, filters);
+ if (this.isEmptyAfterSelection()) this.element.prop('value', null);
+ };
+
+ // ---------------------------
+
+ FileUploader.inherit(FileDrop, FileDirective);
+
+ /**
+ * Creates instance of {FileDrop} object
+ * @param {Object} options
+ * @constructor
+ */
+ function FileDrop(options) {
+ FileDrop.super_.apply(this, arguments);
+ }
+ /**
+ * Map of events
+ * @type {Object}
+ */
+ FileDrop.prototype.events = {
+ $destroy: 'destroy',
+ drop: 'onDrop',
+ dragover: 'onDragOver',
+ dragleave: 'onDragLeave'
+ };
+ /**
+ * Name of property inside uploader._directive object
+ * @type {String}
+ */
+ FileDrop.prototype.prop = 'drop';
+ /**
+ * Returns options
+ * @return {Object|undefined}
+ */
+ FileDrop.prototype.getOptions = function() {};
+ /**
+ * Returns filters
+ * @return {Array<Function>|String|undefined}
+ */
+ FileDrop.prototype.getFilters = function() {};
+ /**
+ * Event handler
+ */
+ FileDrop.prototype.onDrop = function(event) {
+ var transfer = this._getTransfer(event);
+ if (!transfer) return;
+ var options = this.getOptions();
+ var filters = this.getFilters();
+ this._preventAndStop(event);
+ angular.forEach(this.uploader._directives.over, this._removeOverClass, this);
+ this.uploader.addToQueue(transfer.files, options, filters);
+ };
+ /**
+ * Event handler
+ */
+ FileDrop.prototype.onDragOver = function(event) {
+ var transfer = this._getTransfer(event);
+ if(!this._haveFiles(transfer.types)) return;
+ transfer.dropEffect = 'copy';
+ this._preventAndStop(event);
+ angular.forEach(this.uploader._directives.over, this._addOverClass, this);
+ };
+ /**
+ * Event handler
+ */
+ FileDrop.prototype.onDragLeave = function(event) {
+ if (event.currentTarget !== this.element[0]) return;
+ this._preventAndStop(event);
+ angular.forEach(this.uploader._directives.over, this._removeOverClass, this);
+ };
+ /**
+ * Helper
+ */
+ FileDrop.prototype._getTransfer = function(event) {
+ return event.dataTransfer ? event.dataTransfer : event.originalEvent.dataTransfer; // jQuery fix;
+ };
+ /**
+ * Helper
+ */
+ FileDrop.prototype._preventAndStop = function(event) {
+ event.preventDefault();
+ event.stopPropagation();
+ };
+ /**
+ * Returns "true" if types contains files
+ * @param {Object} types
+ */
+ FileDrop.prototype._haveFiles = function(types) {
+ if (!types) return false;
+ if (types.indexOf) {
+ return types.indexOf('Files') !== -1;
+ } else if(types.contains) {
+ return types.contains('Files');
+ } else {
+ return false;
+ }
+ };
+ /**
+ * Callback
+ */
+ FileDrop.prototype._addOverClass = function(item) {
+ item.addOverClass();
+ };
+ /**
+ * Callback
+ */
+ FileDrop.prototype._removeOverClass = function(item) {
+ item.removeOverClass();
+ };
+
+ // ---------------------------
+
+ FileUploader.inherit(FileOver, FileDirective);
+
+ /**
+ * Creates instance of {FileDrop} object
+ * @param {Object} options
+ * @constructor
+ */
+ function FileOver(options) {
+ FileOver.super_.apply(this, arguments);
+ }
+ /**
+ * Map of events
+ * @type {Object}
+ */
+ FileOver.prototype.events = {
+ $destroy: 'destroy'
+ };
+ /**
+ * Name of property inside uploader._directive object
+ * @type {String}
+ */
+ FileOver.prototype.prop = 'over';
+ /**
+ * Over class
+ * @type {string}
+ */
+ FileOver.prototype.overClass = 'nv-file-over';
+ /**
+ * Adds over class
+ */
+ FileOver.prototype.addOverClass = function() {
+ this.element.addClass(this.getOverClass());
+ };
+ /**
+ * Removes over class
+ */
+ FileOver.prototype.removeOverClass = function() {
+ this.element.removeClass(this.getOverClass());
+ };
+ /**
+ * Returns over class
+ * @returns {String}
+ */
+ FileOver.prototype.getOverClass = function() {
+ return this.overClass;
+ };
+
+ return FileUploader;
+ }])
+
+
+ .directive('nvFileSelect', ['$parse', 'FileUploader', function($parse, FileUploader) {
+ return {
+ link: function(scope, element, attributes) {
+ var uploader = scope.$eval(attributes.uploader);
+
+ if (!(uploader instanceof FileUploader)) {
+ throw new TypeError('"Uploader" must be an instance of FileUploader');
+ }
+
+ var object = new FileUploader.FileSelect({
+ uploader: uploader,
+ element: element
+ });
+
+ object.getOptions = $parse(attributes.options).bind(object, scope);
+ object.getFilters = function() {return attributes.filters;};
+ }
+ };
+ }])
+
+
+ .directive('nvFileDrop', ['$parse', 'FileUploader', function($parse, FileUploader) {
+ return {
+ link: function(scope, element, attributes) {
+ var uploader = scope.$eval(attributes.uploader);
+
+ if (!(uploader instanceof FileUploader)) {
+ throw new TypeError('"Uploader" must be an instance of FileUploader');
+ }
+
+ if (!uploader.isHTML5) return;
+
+ var object = new FileUploader.FileDrop({
+ uploader: uploader,
+ element: element
+ });
+
+ object.getOptions = $parse(attributes.options).bind(object, scope);
+ object.getFilters = function() {return attributes.filters;};
+ }
+ };
+ }])
+
+
+ .directive('nvFileOver', ['FileUploader', function(FileUploader) {
+ return {
+ link: function(scope, element, attributes) {
+ var uploader = scope.$eval(attributes.uploader);
+
+ if (!(uploader instanceof FileUploader)) {
+ throw new TypeError('"Uploader" must be an instance of FileUploader');
+ }
+
+ var object = new FileUploader.FileOver({
+ uploader: uploader,
+ element: element
+ });
+
+ object.getOverClass = function() {
+ return attributes.overClass || this.overClass;
+ };
+ }
+ };
+ }])