|
@@ -0,0 +1,578 @@
|
|
|
+/**!
|
|
|
+ * AngularJS file upload/drop directive and service with progress and abort
|
|
|
+ * @author Danial <danial.farid@gmail.com>
|
|
|
+ * @version 3.2.4
|
|
|
+ */
|
|
|
+(function () {
|
|
|
+
|
|
|
+var key, i;
|
|
|
+function patchXHR(fnName, newFn) {
|
|
|
+ window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]);
|
|
|
+}
|
|
|
+
|
|
|
+if (window.XMLHttpRequest && !window.XMLHttpRequest.__isFileAPIShim) {
|
|
|
+ patchXHR('setRequestHeader', function (orig) {
|
|
|
+ return function (header, value) {
|
|
|
+ if (header === '__setXHR_') {
|
|
|
+ var val = value(this);
|
|
|
+ // fix for angular < 1.2.0
|
|
|
+ if (val instanceof Function) {
|
|
|
+ val(this);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ orig.apply(this, arguments);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+var angularFileUpload = angular.module('angularFileUpload', []);
|
|
|
+
|
|
|
+angularFileUpload.version = '3.2.4';
|
|
|
+angularFileUpload.service('$upload', ['$http', '$q', '$timeout', function ($http, $q, $timeout) {
|
|
|
+ function sendHttp(config) {
|
|
|
+ config.method = config.method || 'POST';
|
|
|
+ config.headers = config.headers || {};
|
|
|
+ config.transformRequest = config.transformRequest || function (data, headersGetter) {
|
|
|
+ if (window.ArrayBuffer && data instanceof window.ArrayBuffer) {
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+ return $http.defaults.transformRequest[0](data, headersGetter);
|
|
|
+ };
|
|
|
+ var deferred = $q.defer();
|
|
|
+ var promise = deferred.promise;
|
|
|
+
|
|
|
+ config.headers['__setXHR_'] = function () {
|
|
|
+ return function (xhr) {
|
|
|
+ if (!xhr) return;
|
|
|
+ config.__XHR = xhr;
|
|
|
+ config.xhrFn && config.xhrFn(xhr);
|
|
|
+ xhr.upload.addEventListener('progress', function (e) {
|
|
|
+ e.config = config;
|
|
|
+ deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {
|
|
|
+ promise.progress_fn(e)
|
|
|
+ });
|
|
|
+ }, false);
|
|
|
+ //fix for firefox not firing upload progress end, also IE8-9
|
|
|
+ xhr.upload.addEventListener('load', function (e) {
|
|
|
+ if (e.lengthComputable) {
|
|
|
+ e.config = config;
|
|
|
+ deferred.notify ? deferred.notify(e) : promise.progress_fn && $timeout(function () {
|
|
|
+ promise.progress_fn(e)
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }, false);
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ $http(config).then(function (r) {
|
|
|
+ deferred.resolve(r)
|
|
|
+ }, function (e) {
|
|
|
+ deferred.reject(e)
|
|
|
+ }, function (n) {
|
|
|
+ deferred.notify(n)
|
|
|
+ });
|
|
|
+
|
|
|
+ promise.success = function (fn) {
|
|
|
+ promise.then(function (response) {
|
|
|
+ fn(response.data, response.status, response.headers, config);
|
|
|
+ });
|
|
|
+ return promise;
|
|
|
+ };
|
|
|
+
|
|
|
+ promise.error = function (fn) {
|
|
|
+ promise.then(null, function (response) {
|
|
|
+ fn(response.data, response.status, response.headers, config);
|
|
|
+ });
|
|
|
+ return promise;
|
|
|
+ };
|
|
|
+
|
|
|
+ promise.progress = function (fn) {
|
|
|
+ promise.progress_fn = fn;
|
|
|
+ promise.then(null, null, function (update) {
|
|
|
+ fn(update);
|
|
|
+ });
|
|
|
+ return promise;
|
|
|
+ };
|
|
|
+ promise.abort = function () {
|
|
|
+ if (config.__XHR) {
|
|
|
+ $timeout(function () {
|
|
|
+ config.__XHR.abort();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return promise;
|
|
|
+ };
|
|
|
+ promise.xhr = function (fn) {
|
|
|
+ config.xhrFn = (function (origXhrFn) {
|
|
|
+ return function () {
|
|
|
+ origXhrFn && origXhrFn.apply(promise, arguments);
|
|
|
+ fn.apply(promise, arguments);
|
|
|
+ }
|
|
|
+ })(config.xhrFn);
|
|
|
+ return promise;
|
|
|
+ };
|
|
|
+
|
|
|
+ return promise;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.upload = function (config) {
|
|
|
+ config.headers = config.headers || {};
|
|
|
+ config.headers['Content-Type'] = undefined;
|
|
|
+ config.transformRequest = config.transformRequest ?
|
|
|
+ (Object.prototype.toString.call(config.transformRequest) === '[object Array]' ?
|
|
|
+ config.transformRequest : [config.transformRequest]) : [];
|
|
|
+ config.transformRequest.push(function (data) {
|
|
|
+ var formData = new FormData();
|
|
|
+ var allFields = {};
|
|
|
+ for (key in config.fields) {
|
|
|
+ if (config.fields.hasOwnProperty(key)) {
|
|
|
+ allFields[key] = config.fields[key];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (data) allFields['data'] = data;
|
|
|
+
|
|
|
+ if (config.formDataAppender) {
|
|
|
+ for (key in allFields) {
|
|
|
+ if (allFields.hasOwnProperty(key)) {
|
|
|
+ config.formDataAppender(formData, key, allFields[key]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for (key in allFields) {
|
|
|
+ if (allFields.hasOwnProperty(key)) {
|
|
|
+ var val = allFields[key];
|
|
|
+ if (val !== undefined) {
|
|
|
+ if (Object.prototype.toString.call(val) === '[object String]') {
|
|
|
+ formData.append(key, val);
|
|
|
+ } else {
|
|
|
+ if (config.sendObjectsAsJsonBlob && typeof val === 'object') {
|
|
|
+ formData.append(key, new Blob([val], {type: 'application/json'}));
|
|
|
+ } else {
|
|
|
+ formData.append(key, JSON.stringify(val));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (config.file != null) {
|
|
|
+ var fileFormName = config.fileFormDataName || 'file';
|
|
|
+
|
|
|
+ if (Object.prototype.toString.call(config.file) === '[object Array]') {
|
|
|
+ var isFileFormNameString = Object.prototype.toString.call(fileFormName) === '[object String]';
|
|
|
+ for (i = 0; i < config.file.length; i++) {
|
|
|
+ formData.append(isFileFormNameString ? fileFormName : fileFormName[i], config.file[i],
|
|
|
+ (config.fileName && config.fileName[i]) || config.file[i].name);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ formData.append(fileFormName, config.file, config.fileName || config.file.name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return formData;
|
|
|
+ });
|
|
|
+
|
|
|
+ return sendHttp(config);
|
|
|
+ };
|
|
|
+
|
|
|
+ this.http = function (config) {
|
|
|
+ return sendHttp(config);
|
|
|
+ };
|
|
|
+}]);
|
|
|
+
|
|
|
+angularFileUpload.directive('ngFileSelect', ['$parse', '$timeout', '$compile',
|
|
|
+ function ($parse, $timeout, $compile) {
|
|
|
+ return {
|
|
|
+ restrict: 'AEC',
|
|
|
+ require: '?ngModel',
|
|
|
+ link: function (scope, elem, attr, ngModel) {
|
|
|
+ linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }]);
|
|
|
+
|
|
|
+function linkFileSelect(scope, elem, attr, ngModel, $parse, $timeout, $compile) {
|
|
|
+ function isInputTypeFile() {
|
|
|
+ return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file';
|
|
|
+ }
|
|
|
+
|
|
|
+ var isUpdating = false;
|
|
|
+ function changeFn(evt) {
|
|
|
+ if (!isUpdating) {
|
|
|
+ isUpdating = true;
|
|
|
+ try {
|
|
|
+ var fileList = evt.__files_ || (evt.target && evt.target.files);
|
|
|
+ var files = [], rejFiles = [];
|
|
|
+
|
|
|
+ var accept = $parse(attr.ngAccept);
|
|
|
+ for (i = 0; i < fileList.length; i++) {
|
|
|
+ var file = fileList.item(i);
|
|
|
+ if (isAccepted(scope, accept, file, evt)) {
|
|
|
+ files.push(file);
|
|
|
+ } else {
|
|
|
+ rejFiles.push(file);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ updateModel($parse, $timeout, scope, ngModel, attr,
|
|
|
+ attr.ngFileChange || attr.ngFileSelect, files, rejFiles, evt);
|
|
|
+ if (files.length == 0) evt.target.value = files;
|
|
|
+ if (evt.target && evt.target.getAttribute('__ngf_gen__')) {
|
|
|
+ angular.element(evt.target).remove();
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ isUpdating = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function bindAttrToFileInput(fileElem) {
|
|
|
+ if (attr.ngMultiple) fileElem.attr('multiple', $parse(attr.ngMultiple)(scope));
|
|
|
+ if (attr['accept']) fileElem.attr('accept', attr['accept']);
|
|
|
+ if (attr.ngCapture) fileElem.attr('capture', $parse(attr.ngCapture)(scope));
|
|
|
+ if (attr.ngDisabled) fileElem.attr('disabled', $parse(attr.ngDisabled)(scope));
|
|
|
+
|
|
|
+ fileElem.bind('change', changeFn);
|
|
|
+ }
|
|
|
+
|
|
|
+ function createFileInput(evt) {
|
|
|
+ if (elem.attr('disabled')) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var fileElem = angular.element('<input type="file">');
|
|
|
+
|
|
|
+ for (var i = 0; i < elem[0].attributes.length; i++) {
|
|
|
+ var attribute = elem[0].attributes[i];
|
|
|
+ fileElem.attr(attribute.name, attribute.value);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isInputTypeFile()) {
|
|
|
+ elem.replaceWith(fileElem);
|
|
|
+ elem = fileElem;
|
|
|
+ } else {
|
|
|
+ fileElem.css('width', '0px').css('height', '0px').css('position', 'absolute')
|
|
|
+ .css('padding', 0).css('margin', 0).css('overflow', 'hidden')
|
|
|
+ .attr('tabindex', '-1').css('opacity', 0).attr('__ngf_gen__', true);
|
|
|
+ if (elem.__ngf_ref_elem__) elem.__ngf_ref_elem__.remove();
|
|
|
+ elem.__ngf_ref_elem__ = fileElem;
|
|
|
+ elem.parent()[0].insertBefore(fileElem[0], elem[0]);
|
|
|
+ elem.css('overflow', 'hidden');
|
|
|
+ }
|
|
|
+
|
|
|
+ bindAttrToFileInput(fileElem);
|
|
|
+
|
|
|
+ return fileElem;
|
|
|
+ }
|
|
|
+
|
|
|
+ function resetModel(evt) {
|
|
|
+ updateModel($parse, $timeout, scope, ngModel, attr,
|
|
|
+ attr.ngFileChange || attr.ngFileSelect, [], [], evt, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ function clickHandler(evt) {
|
|
|
+ var fileElem = createFileInput(evt);
|
|
|
+ if (fileElem) {
|
|
|
+ resetModel(evt);
|
|
|
+
|
|
|
+ fileElem[0].click();
|
|
|
+ }
|
|
|
+ if (isInputTypeFile()) {
|
|
|
+ elem.bind('click', clickHandler);
|
|
|
+ evt.preventDefault()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (window.FileAPI && window.FileAPI.ngfFixIE) {
|
|
|
+ window.FileAPI.ngfFixIE(elem, createFileInput, changeFn, resetModel);
|
|
|
+ } else {
|
|
|
+ elem.bind('click', clickHandler);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+angularFileUpload.directive('ngFileDrop', ['$parse', '$timeout', '$location', function ($parse, $timeout, $location) {
|
|
|
+ return {
|
|
|
+ restrict: 'AEC',
|
|
|
+ require: '?ngModel',
|
|
|
+ link: function (scope, elem, attr, ngModel) {
|
|
|
+ linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}]);
|
|
|
+
|
|
|
+angularFileUpload.directive('ngNoFileDrop', function () {
|
|
|
+ return function (scope, elem) {
|
|
|
+ if (dropAvailable()) elem.css('display', 'none')
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+//for backward compatibility
|
|
|
+angularFileUpload.directive('ngFileDropAvailable', ['$parse', '$timeout', function ($parse, $timeout) {
|
|
|
+ return function (scope, elem, attr) {
|
|
|
+ if (dropAvailable()) {
|
|
|
+ var fn = $parse(attr['ngFileDropAvailable']);
|
|
|
+ $timeout(function () {
|
|
|
+ fn(scope);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+}]);
|
|
|
+
|
|
|
+function linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location) {
|
|
|
+ var available = dropAvailable();
|
|
|
+ if (attr['dropAvailable']) {
|
|
|
+ $timeout(function () {
|
|
|
+ scope.dropAvailable ? scope.dropAvailable.value = available :
|
|
|
+ scope.dropAvailable = available;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (!available) {
|
|
|
+ if ($parse(attr.hideOnDropNotAvailable)(scope) == true) {
|
|
|
+ elem.css('display', 'none');
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var leaveTimeout = null;
|
|
|
+ var stopPropagation = $parse(attr.stopPropagation);
|
|
|
+ var dragOverDelay = 1;
|
|
|
+ var accept = $parse(attr.ngAccept);
|
|
|
+ var disabled = $parse(attr.ngDisabled);
|
|
|
+ var actualDragOverClass;
|
|
|
+
|
|
|
+ elem[0].addEventListener('dragover', function (evt) {
|
|
|
+ if (disabled(scope)) return;
|
|
|
+ evt.preventDefault();
|
|
|
+ if (stopPropagation(scope)) evt.stopPropagation();
|
|
|
+ // handling dragover events from the Chrome download bar
|
|
|
+ if (navigator.userAgent.indexOf("Chrome") > -1) {
|
|
|
+ var b = evt.dataTransfer.effectAllowed;
|
|
|
+ evt.dataTransfer.dropEffect = ('move' === b || 'linkMove' === b) ? 'move' : 'copy';
|
|
|
+ }
|
|
|
+ $timeout.cancel(leaveTimeout);
|
|
|
+ if (!scope.actualDragOverClass) {
|
|
|
+ actualDragOverClass = calculateDragOverClass(scope, attr, evt);
|
|
|
+ }
|
|
|
+ elem.addClass(actualDragOverClass);
|
|
|
+ }, false);
|
|
|
+ elem[0].addEventListener('dragenter', function (evt) {
|
|
|
+ if (disabled(scope)) return;
|
|
|
+ evt.preventDefault();
|
|
|
+ if (stopPropagation(scope)) evt.stopPropagation();
|
|
|
+ }, false);
|
|
|
+ elem[0].addEventListener('dragleave', function () {
|
|
|
+ if (disabled(scope)) return;
|
|
|
+ leaveTimeout = $timeout(function () {
|
|
|
+ elem.removeClass(actualDragOverClass);
|
|
|
+ actualDragOverClass = null;
|
|
|
+ }, dragOverDelay || 1);
|
|
|
+ }, false);
|
|
|
+ elem[0].addEventListener('drop', function (evt) {
|
|
|
+ if (disabled(scope)) return;
|
|
|
+ evt.preventDefault();
|
|
|
+ if (stopPropagation(scope)) evt.stopPropagation();
|
|
|
+ elem.removeClass(actualDragOverClass);
|
|
|
+ actualDragOverClass = null;
|
|
|
+ extractFiles(evt, function (files, rejFiles) {
|
|
|
+ updateModel($parse, $timeout, scope, ngModel, attr,
|
|
|
+ attr.ngFileChange || attr.ngFileDrop, files, rejFiles, evt)
|
|
|
+ }, $parse(attr.allowDir)(scope) != false, attr.multiple || $parse(attr.ngMultiple)(scope));
|
|
|
+ }, false);
|
|
|
+
|
|
|
+ function calculateDragOverClass(scope, attr, evt) {
|
|
|
+ var accepted = true;
|
|
|
+ var items = evt.dataTransfer.items;
|
|
|
+ if (items != null) {
|
|
|
+ for (i = 0; i < items.length && accepted; i++) {
|
|
|
+ accepted = accepted
|
|
|
+ && (items[i].kind == 'file' || items[i].kind == '')
|
|
|
+ && isAccepted(scope, accept, items[i], evt);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ var clazz = $parse(attr.dragOverClass)(scope, {$event: evt});
|
|
|
+ if (clazz) {
|
|
|
+ if (clazz.delay) dragOverDelay = clazz.delay;
|
|
|
+ if (clazz.accept) clazz = accepted ? clazz.accept : clazz.reject;
|
|
|
+ }
|
|
|
+ return clazz || attr['dragOverClass'] || 'dragover';
|
|
|
+ }
|
|
|
+
|
|
|
+ function extractFiles(evt, callback, allowDir, multiple) {
|
|
|
+ var files = [], rejFiles = [], items = evt.dataTransfer.items, processing = 0;
|
|
|
+
|
|
|
+ function addFile(file) {
|
|
|
+ if (isAccepted(scope, accept, file, evt)) {
|
|
|
+ files.push(file);
|
|
|
+ } else {
|
|
|
+ rejFiles.push(file);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (items && items.length > 0 && $location.protocol() != 'file') {
|
|
|
+ for (i = 0; i < items.length; i++) {
|
|
|
+ if (items[i].webkitGetAsEntry && items[i].webkitGetAsEntry() && items[i].webkitGetAsEntry().isDirectory) {
|
|
|
+ var entry = items[i].webkitGetAsEntry();
|
|
|
+ if (entry.isDirectory && !allowDir) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (entry != null) {
|
|
|
+ traverseFileTree(files, entry);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ var f = items[i].getAsFile();
|
|
|
+ if (f != null) addFile(f);
|
|
|
+ }
|
|
|
+ if (!multiple && files.length > 0) break;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ var fileList = evt.dataTransfer.files;
|
|
|
+ if (fileList != null) {
|
|
|
+ for (i = 0; i < fileList.length; i++) {
|
|
|
+ addFile(fileList.item(i));
|
|
|
+ if (!multiple && files.length > 0) break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ var delays = 0;
|
|
|
+ (function waitForProcess(delay) {
|
|
|
+ $timeout(function () {
|
|
|
+ if (!processing) {
|
|
|
+ if (!multiple && files.length > 1) {
|
|
|
+ i = 0;
|
|
|
+ while (files[i].type == 'directory') i++;
|
|
|
+ files = [files[i]];
|
|
|
+ }
|
|
|
+ callback(files, rejFiles);
|
|
|
+ } else {
|
|
|
+ if (delays++ * 10 < 20 * 1000) {
|
|
|
+ waitForProcess(10);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, delay || 0)
|
|
|
+ })();
|
|
|
+
|
|
|
+ function traverseFileTree(files, entry, path) {
|
|
|
+ if (entry != null) {
|
|
|
+ if (entry.isDirectory) {
|
|
|
+ var filePath = (path || '') + entry.name;
|
|
|
+ addFile({name: entry.name, type: 'directory', path: filePath});
|
|
|
+ var dirReader = entry.createReader();
|
|
|
+ var entries = [];
|
|
|
+ processing++;
|
|
|
+ var readEntries = function () {
|
|
|
+ dirReader.readEntries(function (results) {
|
|
|
+ try {
|
|
|
+ if (!results.length) {
|
|
|
+ for (i = 0; i < entries.length; i++) {
|
|
|
+ traverseFileTree(files, entries[i], (path ? path : '') + entry.name + '/');
|
|
|
+ }
|
|
|
+ processing--;
|
|
|
+ } else {
|
|
|
+ entries = entries.concat(Array.prototype.slice.call(results || [], 0));
|
|
|
+ readEntries();
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ processing--;
|
|
|
+ console.error(e);
|
|
|
+ }
|
|
|
+ }, function () {
|
|
|
+ processing--;
|
|
|
+ });
|
|
|
+ };
|
|
|
+ readEntries();
|
|
|
+ } else {
|
|
|
+ processing++;
|
|
|
+ entry.file(function (file) {
|
|
|
+ try {
|
|
|
+ processing--;
|
|
|
+ file.path = (path ? path : '') + file.name;
|
|
|
+ addFile(file);
|
|
|
+ } catch (e) {
|
|
|
+ processing--;
|
|
|
+ console.error(e);
|
|
|
+ }
|
|
|
+ }, function () {
|
|
|
+ processing--;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function dropAvailable() {
|
|
|
+ var div = document.createElement('div');
|
|
|
+ return ('draggable' in div) && ('ondrop' in div);
|
|
|
+}
|
|
|
+
|
|
|
+function updateModel($parse, $timeout, scope, ngModel, attr, fileChange, files, rejFiles, evt, noDelay) {
|
|
|
+ function update() {
|
|
|
+ if (ngModel) {
|
|
|
+ $parse(attr.ngModel).assign(scope, files);
|
|
|
+ $timeout(function () {
|
|
|
+ ngModel && ngModel.$setViewValue(files != null && files.length == 0 ? null : files);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (attr.ngModelRejected) {
|
|
|
+ $parse(attr.ngModelRejected).assign(scope, rejFiles);
|
|
|
+ }
|
|
|
+ if (fileChange) {
|
|
|
+ $parse(fileChange)(scope, {
|
|
|
+ $files: files,
|
|
|
+ $rejectedFiles: rejFiles,
|
|
|
+ $event: evt
|
|
|
+ });
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (noDelay) {
|
|
|
+ update();
|
|
|
+ } else {
|
|
|
+ $timeout(function () {
|
|
|
+ update();
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function isAccepted(scope, accept, file, evt) {
|
|
|
+ var val = accept(scope, {$file: file, $event: evt});
|
|
|
+ if (val == null) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (angular.isString(val)) {
|
|
|
+ var regexp = new RegExp(globStringToRegex(val), 'gi')
|
|
|
+ val = (file.type != null && file.type.match(regexp)) ||
|
|
|
+ (file.name != null && file.name.match(regexp));
|
|
|
+ }
|
|
|
+ return val;
|
|
|
+}
|
|
|
+
|
|
|
+function globStringToRegex(str) {
|
|
|
+ if (str.length > 2 && str[0] === '/' && str[str.length - 1] === '/') {
|
|
|
+ return str.substring(1, str.length - 1);
|
|
|
+ }
|
|
|
+ var split = str.split(','), result = '';
|
|
|
+ if (split.length > 1) {
|
|
|
+ for (i = 0; i < split.length; i++) {
|
|
|
+ result += '(' + globStringToRegex(split[i]) + ')';
|
|
|
+ if (i < split.length - 1) {
|
|
|
+ result += '|'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (str.indexOf('.') == 0) {
|
|
|
+ str = '*' + str;
|
|
|
+ }
|
|
|
+ result = '^' + str.replace(new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\' + '-]', 'g'), '\\$&') + '$';
|
|
|
+ result = result.replace(/\\\*/g, '.*').replace(/\\\?/g, '.');
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+var ngFileUpload = angular.module('ngFileUpload', []);
|
|
|
+
|
|
|
+for (key in angularFileUpload) {
|
|
|
+ if (angularFileUpload.hasOwnProperty(key)) {
|
|
|
+ ngFileUpload[key] = angularFileUpload[key];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+})();
|