From ed6da70d3eee0cdad7c150684b4470b8af393f56 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Tue, 21 Jan 2020 15:38:57 +0100 Subject: [PATCH] Update to 12.2.13 Change-Id: Ie35ede414b46e28b0377d55ecdd4662ba964d8bf --- MANIFEST.in | 4 +- setup.cfg | 20 + setup.py | 8 +- xstatic/pkg/angular_fileupload/__init__.py | 6 +- .../angular_fileupload/data/FileAPI.min.js | 2 +- .../data/ng-file-upload-all.js | 541 +++++++++++------- .../data/ng-file-upload-all.min.js | 7 +- .../data/ng-file-upload-shim.js | 4 +- .../data/ng-file-upload-shim.min.js | 2 +- .../angular_fileupload/data/ng-file-upload.js | 537 ++++++++++------- .../data/ng-file-upload.min.js | 6 +- 11 files changed, 673 insertions(+), 464 deletions(-) create mode 100644 setup.cfg diff --git a/MANIFEST.in b/MANIFEST.in index 88c8d70..af3cdd3 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,8 +1,6 @@ include README.txt -recursive-include xstatic/pkg/angular_fileupload * - +recursive-include xstatic * global-exclude *.pyc global-exclude *.pyo global-exclude *.orig global-exclude *.rej - diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..67fb830 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,20 @@ +[metadata] +name = XStatic-Angular-FileUpload +description = Angular-FileUpload 12.2.13 (XStatic packaging standard) +description-file = README.rst +maintainer = Radomir Dopieralski +maintainer-email = openstack@sheep.art.pl +home-page = https://github.com/danialfarid/angular-file-upload +keywords = angular_fileupload xstatic +license = (same as Angular-FileUpload) +zip_safe = False +namespace_packages = + xstatic + xstatic.pkg + +[files] +packages = + xstatic + +[bdist_wheel] +universal = True diff --git a/setup.py b/setup.py index 7ed6188..d8d754f 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,10 @@ +from setuptools import setup, find_packages from xstatic.pkg import angular_fileupload as xs # The README.txt file should be written in reST so that PyPI can use # it to generate your project's PyPI page. long_description = open('README.txt').read() -from setuptools import setup, find_packages - setup( name=xs.PACKAGE_NAME, version=xs.PACKAGE_VERSION, @@ -19,9 +18,8 @@ setup( url=xs.HOMEPAGE, platforms=xs.PLATFORMS, packages=find_packages(), - namespace_packages=['xstatic', 'xstatic.pkg', ], + namespace_packages=['xstatic', 'xstatic.pkg'], include_package_data=True, zip_safe=False, - install_requires=[], # nothing! :) - # if you like, you MAY use the 'XStatic' package. + install_requires=[], ) diff --git a/xstatic/pkg/angular_fileupload/__init__.py b/xstatic/pkg/angular_fileupload/__init__.py index 43c9db9..b812f41 100644 --- a/xstatic/pkg/angular_fileupload/__init__.py +++ b/xstatic/pkg/angular_fileupload/__init__.py @@ -11,7 +11,7 @@ NAME = __name__.split('.')[-1] # package name (e.g. 'foo' or 'foo_bar') # please use a all-lowercase valid python # package name -VERSION = '12.0.4' # version of the packaged files, please use the upstream +VERSION = '12.2.13' # version of the packaged files, please use the upstream # version number BUILD = '0' # our package build number, so we can release new builds # with fixes for xstatic stuff. @@ -24,8 +24,8 @@ CLASSIFIERS = [] KEYWORDS = '%s xstatic' % NAME # XStatic-* package maintainer: -MAINTAINER = 'Rob Cresswell' -MAINTAINER_EMAIL = 'robert.cresswell@outlook.com' +MAINTAINER = 'Radomir Dopieralski' +MAINTAINER_EMAIL = 'openstack@sheep.art.pl' # this refers to the project homepage of the stuff we packaged: HOMEPAGE = 'https://github.com/danialfarid/angular-file-upload' diff --git a/xstatic/pkg/angular_fileupload/data/FileAPI.min.js b/xstatic/pkg/angular_fileupload/data/FileAPI.min.js index c7b0266..2afb71e 100644 --- a/xstatic/pkg/angular_fileupload/data/FileAPI.min.js +++ b/xstatic/pkg/angular_fileupload/data/FileAPI.min.js @@ -1,4 +1,4 @@ -/*! 12.0.4 */ +/*! 12.2.13 */ /*! FileAPI 2.0.7 - BSD | git://github.com/mailru/FileAPI.git * FileAPI — a set of javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF. */ diff --git a/xstatic/pkg/angular_fileupload/data/ng-file-upload-all.js b/xstatic/pkg/angular_fileupload/data/ng-file-upload-all.js index fca2e64..e342351 100644 --- a/xstatic/pkg/angular_fileupload/data/ng-file-upload-all.js +++ b/xstatic/pkg/angular_fileupload/data/ng-file-upload-all.js @@ -1,9 +1,9 @@ /**! - * AngularJS file upload directives and services. Supoorts: file upload/drop/paste, resume, cancel/abort, + * AngularJS file upload directives and services. Supports: file upload/drop/paste, resume, cancel/abort, * progress, resize, thumbnail, preview, validation and CORS * FileAPI Flash shim for old browsers not supporting FormData * @author Danial - * @version 12.0.4 + * @version 12.2.13 */ (function () { @@ -424,7 +424,7 @@ if (!window.FileReader) { * AngularJS file upload directives and services. Supoorts: file upload/drop/paste, resume, cancel/abort, * progress, resize, thumbnail, preview, validation and CORS * @author Danial - * @version 12.0.4 + * @version 12.2.13 */ if (window.XMLHttpRequest && !(window.FileAPI && FileAPI.shouldLoad)) { @@ -445,7 +445,7 @@ if (window.XMLHttpRequest && !(window.FileAPI && FileAPI.shouldLoad)) { var ngFileUpload = angular.module('ngFileUpload', []); -ngFileUpload.version = '12.0.4'; +ngFileUpload.version = '12.2.13'; ngFileUpload.service('UploadBase', ['$http', '$q', '$timeout', function ($http, $q, $timeout) { var upload = this; @@ -512,10 +512,12 @@ ngFileUpload.service('UploadBase', ['$http', '$q', '$timeout', function ($http, function uploadWithAngular() { $http(config).then(function (r) { if (resumeSupported && config._chunkSize && !config._finished && config._file) { + var fileSize = config._file && config._file.size || 0; notifyProgress({ - loaded: config._end, - total: config._file && config._file.size, - config: config, type: 'progress' + loaded: Math.min(config._end, fileSize), + total: fileSize, + config: config, + type: 'progress' } ); upload.upload(config, true); @@ -554,6 +556,9 @@ ngFileUpload.service('UploadBase', ['$http', '$q', '$timeout', function ($http, } else if (config.resumeSize) { config.resumeSize().then(function (size) { config._start = size; + if (config._chunkSize) { + config._end = config._start + config._chunkSize; + } uploadWithAngular(); }, function (e) { throw e; @@ -607,9 +612,11 @@ ngFileUpload.service('UploadBase', ['$http', '$q', '$timeout', function ($http, }; upload.promisesCount++; - promise['finally'](function () { - upload.promisesCount--; - }); + if (promise['finally'] && promise['finally'] instanceof Function) { + promise['finally'](function () { + upload.promisesCount--; + }); + } return promise; } @@ -793,9 +800,11 @@ ngFileUpload.service('UploadBase', ['$http', '$q', '$timeout', function ($http, var arrayBufferView = new Uint8Array(resp.data); var type = resp.headers('content-type') || 'image/WebP'; var blob = new window.Blob([arrayBufferView], {type: type}); + var matches = url.match(/.*\/(.+?)(\?.*)?$/); + if (matches.length > 1) { + blob.name = matches[1]; + } defer.resolve(blob); - //var split = type.split('[/;]'); - //blob.name = url.substring(0, 150).replace(/\W+/g, '') + '.' + (split.length > 1 ? split[1] : 'jpg'); }, function (e) { defer.reject(e); }); @@ -843,7 +852,7 @@ ngFileUpload.service('Upload', ['$parse', '$timeout', '$compile', '$q', 'UploadE }; upload.shouldUpdateOn = function (type, attr, scope) { - var modelOptions = upload.attrGetter('ngModelOptions', attr, scope); + var modelOptions = upload.attrGetter('ngfModelOptions', attr, scope); if (modelOptions && modelOptions.updateOn) { return modelOptions.updateOn.split(' ').indexOf(type) > -1; } @@ -893,13 +902,13 @@ ngFileUpload.service('Upload', ['$parse', '$timeout', '$compile', '$q', 'UploadE return $q.all(promises); } - function resize(files, attr, scope) { + function resizeFile(files, attr, scope, ngModel) { var resizeVal = upload.attrGetter('ngfResize', attr, scope); if (!resizeVal || !upload.isResizeSupported() || !files.length) return upload.emptyPromise(); if (resizeVal instanceof Function) { var defer = $q.defer(); - resizeVal(files).then(function (p) { - resizeWithParams(p, files, attr, scope).then(function (r) { + return resizeVal(files).then(function (p) { + resizeWithParams(p, files, attr, scope, ngModel).then(function (r) { defer.resolve(r); }, function (e) { defer.reject(e); @@ -908,27 +917,30 @@ ngFileUpload.service('Upload', ['$parse', '$timeout', '$compile', '$q', 'UploadE defer.reject(e); }); } else { - return resizeWithParams(resizeVal, files, attr, scope); + return resizeWithParams(resizeVal, files, attr, scope, ngModel); } } - function resizeWithParams(param, files, attr, scope) { + function resizeWithParams(params, files, attr, scope, ngModel) { var promises = [upload.emptyPromise()]; function handleFile(f, i) { if (f.type.indexOf('image') === 0) { - if (param.pattern && !upload.validatePattern(f, param.pattern)) return; - var promise = upload.resize(f, param.width, param.height, param.quality, - param.type, param.ratio, param.centerCrop, function (width, height) { - return upload.attrGetter('ngfResizeIf', attr, scope, - {$width: width, $height: height, $file: f}); - }, param.restoreExif !== false); + if (params.pattern && !upload.validatePattern(f, params.pattern)) return; + params.resizeIf = function (width, height) { + return upload.attrGetter('ngfResizeIf', attr, scope, + {$width: width, $height: height, $file: f}); + }; + var promise = upload.resize(f, params); promises.push(promise); promise.then(function (resizedFile) { files.splice(i, 1, resizedFile); }, function (e) { f.$error = 'resize'; + (f.$errorMessages = (f.$errorMessages || {})).resize = true; f.$errorParam = (e ? (e.message ? e.message : e) + ': ' : '') + (f && f.name); + ngModel.$ngfValidations.push({name: 'resize', valid: false}); + upload.applyModelValidation(ngModel, files); }); } } @@ -1015,18 +1027,6 @@ ngFileUpload.service('Upload', ['$parse', '$timeout', '$compile', '$q', 'UploadE return angular.isArray(v) ? v : [v]; } - function separateInvalids() { - valids = []; - invalids = []; - angular.forEach(allNewFiles, function (file) { - if (file.$error) { - invalids.push(file); - } else { - valids.push(file); - } - }); - } - function resizeAndUpdate() { function updateModel() { $timeout(function () { @@ -1036,17 +1036,30 @@ ngFileUpload.service('Upload', ['$parse', '$timeout', '$compile', '$q', 'UploadE }, options && options.debounce ? options.debounce.change || options.debounce : 0); } - resize(validateAfterResize ? allNewFiles : valids, attr, scope).then(function () { + var resizingFiles = validateAfterResize ? allNewFiles : valids; + resizeFile(resizingFiles, attr, scope, ngModel).then(function () { if (validateAfterResize) { - upload.validate(allNewFiles, prevValidFiles.length, ngModel, attr, scope).then(function () { - separateInvalids(); - updateModel(); - }); + upload.validate(allNewFiles, keep ? prevValidFiles.length : 0, ngModel, attr, scope) + .then(function (validationResult) { + valids = validationResult.validsFiles; + invalids = validationResult.invalidsFiles; + updateModel(); + }); } else { updateModel(); } - }, function (e) { - throw 'Could not resize files ' + e; + }, function () { + for (var i = 0; i < resizingFiles.length; i++) { + var f = resizingFiles[i]; + if (f.$error === 'resize') { + var index = valids.indexOf(f); + if (index > -1) { + valids.splice(index, 1); + invalids.push(f); + } + updateModel(); + } + } }); } @@ -1076,13 +1089,15 @@ ngFileUpload.service('Upload', ['$parse', '$timeout', '$compile', '$q', 'UploadE var validateAfterResize = upload.attrGetter('ngfValidateAfterResize', attr, scope); - var options = upload.attrGetter('ngModelOptions', attr, scope); - upload.validate(allNewFiles, prevValidFiles.length, ngModel, attr, scope).then(function () { + var options = upload.attrGetter('ngfModelOptions', attr, scope); + upload.validate(allNewFiles, keep ? prevValidFiles.length : 0, ngModel, attr, scope) + .then(function (validationResult) { if (noDelay) { update(allNewFiles, [], files, dupFiles, isSingleModel); } else { if ((!options || !options.allowInvalid) && !validateAfterResize) { - separateInvalids(); + valids = validationResult.validFiles; + invalids = validationResult.invalidFiles; } else { valids = allNewFiles; } @@ -1119,7 +1134,7 @@ ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', /** @namespace attr.ngfSelect */ /** @namespace attr.ngfChange */ /** @namespace attr.ngModel */ - /** @namespace attr.ngModelOptions */ + /** @namespace attr.ngfModelOptions */ /** @namespace attr.ngfMultiple */ /** @namespace attr.ngfCapture */ /** @namespace attr.ngfValidate */ @@ -1139,6 +1154,8 @@ ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', function changeFn(evt) { if (upload.shouldUpdateOn('change', attr, scope)) { var fileList = evt.__files_ || (evt.target && evt.target.files), files = []; + /* Handle duplicate call in IE11 */ + if (!fileList) return; for (var i = 0; i < fileList.length; i++) { files.push(fileList[i]); } @@ -1150,31 +1167,39 @@ ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', upload.registerModelChangeValidator(ngModel, attr, scope); var unwatches = []; - unwatches.push(scope.$watch(attrGetter('ngfMultiple'), function () { - fileElem.attr('multiple', attrGetter('ngfMultiple', scope)); - })); - unwatches.push(scope.$watch(attrGetter('ngfCapture'), function () { - fileElem.attr('capture', attrGetter('ngfCapture', scope)); - })); - unwatches.push(scope.$watch(attrGetter('ngfAccept'), function () { - fileElem.attr('accept', attrGetter('ngfAccept', scope)); - })); - attr.$observe('accept', function () { + if (attrGetter('ngfMultiple')) { + unwatches.push(scope.$watch(attrGetter('ngfMultiple'), function () { + fileElem.attr('multiple', attrGetter('ngfMultiple', scope)); + })); + } + if (attrGetter('ngfCapture')) { + unwatches.push(scope.$watch(attrGetter('ngfCapture'), function () { + fileElem.attr('capture', attrGetter('ngfCapture', scope)); + })); + } + if (attrGetter('ngfAccept')) { + unwatches.push(scope.$watch(attrGetter('ngfAccept'), function () { + fileElem.attr('accept', attrGetter('ngfAccept', scope)); + })); + } + unwatches.push(attr.$observe('accept', function () { fileElem.attr('accept', attrGetter('accept')); - }); - unwatches.push(function () { - if (attr.$$observers) delete attr.$$observers.accept; - }); - function bindAttrToFileInput(fileElem) { - if (elem !== fileElem) { - for (var i = 0; i < elem[0].attributes.length; i++) { - var attribute = elem[0].attributes[i]; - if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'style') { - if (attribute.value == null || attribute.value === '') { - if (attribute.name === 'required') attribute.value = 'required'; - if (attribute.name === 'multiple') attribute.value = 'multiple'; - } - fileElem.attr(attribute.name, attribute.name === 'id' ? 'ngf-' + attribute.value : attribute.value); + })); + function bindAttrToFileInput(fileElem, label) { + function updateId(val) { + fileElem.attr('id', 'ngf-' + val); + label.attr('id', 'ngf-label-' + val); + } + + for (var i = 0; i < elem[0].attributes.length; i++) { + var attribute = elem[0].attributes[i]; + if (attribute.name !== 'type' && attribute.name !== 'class' && attribute.name !== 'style') { + if (attribute.name === 'id') { + updateId(attribute.value); + unwatches.push(attr.$observe('id', updateId)); + } else { + fileElem.attr(attribute.name, (!attribute.value && (attribute.name === 'required' || + attribute.name === 'multiple')) ? attribute.name : attribute.value); } } } @@ -1187,12 +1212,12 @@ ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', var fileElem = angular.element(''); - bindAttrToFileInput(fileElem); - var label = angular.element(''); label.css('visibility', 'hidden').css('position', 'absolute').css('overflow', 'hidden') .css('width', '0px').css('height', '0px').css('border', 'none') .css('margin', '0px').css('padding', '0px').attr('tabindex', '-1'); + bindAttrToFileInput(fileElem, label); + generatedElems.push({el: elem, ref: label}); document.body.appendChild(label.append(fileElem)[0]); @@ -1200,13 +1225,12 @@ ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', return fileElem; } - var initialTouchStartY = 0; - function clickHandler(evt) { if (elem.attr('disabled')) return false; if (attrGetter('ngfSelectDisabled', scope)) return; - var r = handleTouch(evt); + var r = detectSwipe(evt); + // prevent the click if it is a swipe if (r != null) return r; resetModel(evt); @@ -1218,7 +1242,8 @@ ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', document.body.appendChild(fileElem.parent()[0]); fileElem.bind('change', changeFn); } - } catch(e){/*ignore*/} + } catch (e) {/*ignore*/ + } if (isDelayedClickSupported(navigator.userAgent)) { setTimeout(function () { @@ -1231,19 +1256,30 @@ ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', return false; } - function handleTouch(evt) { - var touches = evt.changedTouches || (evt.originalEvent && evt.originalEvent.changedTouches); - if (evt.type === 'touchstart') { - initialTouchStartY = touches ? touches[0].clientY : 0; - return true; // don't block event default - } else { - evt.stopPropagation(); - evt.preventDefault(); - // prevent scroll from triggering event - if (evt.type === 'touchend') { - var currentLocation = touches ? touches[0].clientY : 0; - if (Math.abs(currentLocation - initialTouchStartY) > 20) return false; + var initialTouchStartY = 0; + var initialTouchStartX = 0; + + function detectSwipe(evt) { + var touches = evt.changedTouches || (evt.originalEvent && evt.originalEvent.changedTouches); + if (touches) { + if (evt.type === 'touchstart') { + initialTouchStartX = touches[0].clientX; + initialTouchStartY = touches[0].clientY; + return true; // don't block event default + } else { + // prevent scroll from triggering event + if (evt.type === 'touchend') { + var currentX = touches[0].clientX; + var currentY = touches[0].clientY; + if ((Math.abs(currentX - initialTouchStartX) > 20) || + (Math.abs(currentY - initialTouchStartY) > 20)) { + evt.stopPropagation(); + evt.preventDefault(); + return false; + } + } + return true; } } } @@ -1474,14 +1510,19 @@ ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', var size = resizeParams; if (directiveName === 'ngfThumbnail') { if (!size) { - size = {width: elem[0].clientWidth, height: elem[0].clientHeight}; + size = { + width: elem[0].naturalWidth || elem[0].clientWidth, + height: elem[0].naturalHeight || elem[0].clientHeight + }; } if (size.width === 0 && window.getComputedStyle) { var style = getComputedStyle(elem[0]); - size = { - width: parseInt(style.width.slice(0, -2)), - height: parseInt(style.height.slice(0, -2)) - }; + if (style.width && style.width.indexOf('px') > -1 && style.height && style.height.indexOf('px') > -1) { + size = { + width: parseInt(style.width.slice(0, -2)), + height: parseInt(style.height.slice(0, -2)) + }; + } } } @@ -1496,7 +1537,11 @@ ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', if (file && file.type && file.type.search(getTagType(elem[0])) === 0 && (!isBackground || file.type.indexOf('image') === 0)) { if (size && Upload.isResizeSupported()) { - Upload.resize(file, size.width, size.height, size.quality).then( + size.resizeIf = function (width, height) { + return Upload.attrGetter('ngfResizeIf', attr, scope, + {$width: width, $height: height, $file: file}); + }; + Upload.resize(file, size).then( function (f) { constructDataUrl(f); }, function (e) { @@ -1558,8 +1603,8 @@ ngFileUpload.directive('ngfSelect', ['$parse', '$timeout', '$compile', 'Upload', }]); ngFileUpload.config(['$compileProvider', function ($compileProvider) { - if ($compileProvider.imgSrcSanitizationWhitelist) $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|local|file|data|blob):/); - if ($compileProvider.aHrefSanitizationWhitelist) $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|local|file|data|blob):/); + if ($compileProvider.imgSrcSanitizationWhitelist) $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|webcal|local|file|data|blob):/); + if ($compileProvider.aHrefSanitizationWhitelist) $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|webcal|local|file|data|blob):/); }]); ngFileUpload.filter('ngfDataUrl', ['UploadDataUrl', '$sce', function (UploadDataUrl, $sce) { @@ -1651,13 +1696,15 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct if (ngModel) { ngModel.$formatters.push(function (files) { if (ngModel.$dirty) { + var filesArray = files; if (files && !angular.isArray(files)) { - files = [files]; + filesArray = [files]; } - upload.validate(files, 0, ngModel, attr, scope).then(function () { - upload.applyModelValidation(ngModel, files); + upload.validate(filesArray, 0, ngModel, attr, scope).then(function () { + upload.applyModelValidation(ngModel, filesArray); }); } + return files; }); } }; @@ -1707,11 +1754,15 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct return upload.attrGetter(name, attr, scope, params); }; + var ignoredErrors = (upload.attrGetter('ngfIgnoreInvalid', attr, scope) || '').split(' '); + var runAllValidation = upload.attrGetter('ngfRunAllValidations', attr, scope); + if (files == null || files.length === 0) { - return upload.emptyPromise(ngModel); + return upload.emptyPromise({'validFiles': files, 'invalidFiles': []}); } files = files.length === undefined ? [files] : files.slice(0); + var invalidFiles = []; function validateSync(name, validationName, fn) { if (files) { @@ -1722,11 +1773,20 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct var val = upload.getValidationAttr(attr, scope, name, validationName, file); if (val != null) { if (!fn(file, val, i)) { - file.$error = name; - (file.$errorMessages = (file.$errorMessages || {}))[name] = true; - file.$errorParam = val; - files.splice(i, 1); - valid = false; + if (ignoredErrors.indexOf(name) === -1) { + file.$error = name; + (file.$errorMessages = (file.$errorMessages || {}))[name] = true; + file.$errorParam = val; + if (invalidFiles.indexOf(file) === -1) { + invalidFiles.push(file); + } + if (!runAllValidation) { + files.splice(i, 1); + } + valid = false; + } else { + files.splice(i, 1); + } } } } @@ -1737,9 +1797,6 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct } } - validateSync('maxFiles', null, function (file, val, i) { - return prevLength + i < val; - }); validateSync('pattern', null, upload.validatePattern); validateSync('minSize', 'size.min', function (file, val) { return file.size + 0.1 >= upload.translateScalars(val); @@ -1762,44 +1819,58 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct }); if (!files.length) { - return upload.emptyPromise(ngModel, ngModel.$ngfValidations); + return upload.emptyPromise({'validFiles': [], 'invalidFiles': invalidFiles}); } function validateAsync(name, validationName, type, asyncFn, fn) { function resolveResult(defer, file, val) { + function resolveInternal(fn) { + if (fn()) { + if (ignoredErrors.indexOf(name) === -1) { + file.$error = name; + (file.$errorMessages = (file.$errorMessages || {}))[name] = true; + file.$errorParam = val; + if (invalidFiles.indexOf(file) === -1) { + invalidFiles.push(file); + } + if (!runAllValidation) { + var i = files.indexOf(file); + if (i > -1) files.splice(i, 1); + } + defer.resolve(false); + } else { + var j = files.indexOf(file); + if (j > -1) files.splice(j, 1); + defer.resolve(true); + } + } else { + defer.resolve(true); + } + } + if (val != null) { asyncFn(file, val).then(function (d) { - if (!fn(d, val)) { - file.$error = name; - (file.$errorMessages = (file.$errorMessages || {}))[name] = true; - file.$errorParam = val; - defer.reject(); - } else { - defer.resolve(); - } + resolveInternal(function () { + return !fn(d, val); + }); }, function () { - if (attrGetter('ngfValidateForce', {$file: file})) { - file.$error = name; - (file.$errorMessages = (file.$errorMessages || {}))[name] = true; - file.$errorParam = val; - defer.reject(); - } else { - defer.resolve(); - } + resolveInternal(function () { + return attrGetter('ngfValidateForce', {$file: file}); + }); }); } else { - defer.resolve(); + defer.resolve(true); } } - var promises = [upload.emptyPromise()]; + var promises = [upload.emptyPromise(true)]; if (files) { files = files.length === undefined ? [files] : files; angular.forEach(files, function (file) { var defer = $q.defer(); promises.push(defer.promise); if (type && (file.type == null || file.type.search(type) !== 0)) { - defer.resolve(); + defer.resolve(true); return; } if (name === 'dimensions' && upload.attrGetter('ngfDimensions', attr) != null) { @@ -1807,96 +1878,120 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct resolveResult(defer, file, attrGetter('ngfDimensions', {$file: file, $width: d.width, $height: d.height})); }, function () { - defer.reject(); + defer.resolve(false); }); } else if (name === 'duration' && upload.attrGetter('ngfDuration', attr) != null) { upload.mediaDuration(file).then(function (d) { resolveResult(defer, file, attrGetter('ngfDuration', {$file: file, $duration: d})); }, function () { - defer.reject(); + defer.resolve(false); }); } else { resolveResult(defer, file, upload.getValidationAttr(attr, scope, name, validationName, file)); } }); - return $q.all(promises).then(function () { - ngModel.$ngfValidations.push({name: name, valid: true}); - }, function () { - ngModel.$ngfValidations.push({name: name, valid: false}); - }); } + var deffer = $q.defer(); + $q.all(promises).then(function (values) { + var isValid = true; + for (var i = 0; i < values.length; i++) { + if (!values[i]) { + isValid = false; + break; + } + } + ngModel.$ngfValidations.push({name: name, valid: isValid}); + deffer.resolve(isValid); + }); + return deffer.promise; } var deffer = $q.defer(); var promises = []; - promises.push(upload.happyPromise(validateAsync('maxHeight', 'height.max', /image/, + promises.push(validateAsync('maxHeight', 'height.max', /image/, this.imageDimensions, function (d, val) { return d.height <= val; - }))); - promises.push(upload.happyPromise(validateAsync('minHeight', 'height.min', /image/, + })); + promises.push(validateAsync('minHeight', 'height.min', /image/, this.imageDimensions, function (d, val) { return d.height >= val; - }))); - promises.push(upload.happyPromise(validateAsync('maxWidth', 'width.max', /image/, + })); + promises.push(validateAsync('maxWidth', 'width.max', /image/, this.imageDimensions, function (d, val) { return d.width <= val; - }))); - promises.push(upload.happyPromise(validateAsync('minWidth', 'width.min', /image/, + })); + promises.push(validateAsync('minWidth', 'width.min', /image/, this.imageDimensions, function (d, val) { return d.width >= val; - }))); - promises.push(upload.happyPromise(validateAsync('dimensions', null, /image/, + })); + promises.push(validateAsync('dimensions', null, /image/, function (file, val) { return upload.emptyPromise(val); }, function (r) { return r; - }))); - promises.push(upload.happyPromise(validateAsync('ratio', null, /image/, + })); + promises.push(validateAsync('ratio', null, /image/, this.imageDimensions, function (d, val) { var split = val.toString().split(','), valid = false; for (var i = 0; i < split.length; i++) { - if (Math.abs((d.width / d.height) - upload.ratioToFloat(split[i])) < 0.0001) { + if (Math.abs((d.width / d.height) - upload.ratioToFloat(split[i])) < 0.01) { valid = true; } } return valid; - }))); - promises.push(upload.happyPromise(validateAsync('maxRatio', 'ratio.max', /image/, + })); + promises.push(validateAsync('maxRatio', 'ratio.max', /image/, this.imageDimensions, function (d, val) { return (d.width / d.height) - upload.ratioToFloat(val) < 0.0001; - }))); - promises.push(upload.happyPromise(validateAsync('minRatio', 'ratio.min', /image/, + })); + promises.push(validateAsync('minRatio', 'ratio.min', /image/, this.imageDimensions, function (d, val) { return (d.width / d.height) - upload.ratioToFloat(val) > -0.0001; - }))); - promises.push(upload.happyPromise(validateAsync('maxDuration', 'duration.max', /audio|video/, + })); + promises.push(validateAsync('maxDuration', 'duration.max', /audio|video/, this.mediaDuration, function (d, val) { return d <= upload.translateScalars(val); - }))); - promises.push(upload.happyPromise(validateAsync('minDuration', 'duration.min', /audio|video/, + })); + promises.push(validateAsync('minDuration', 'duration.min', /audio|video/, this.mediaDuration, function (d, val) { return d >= upload.translateScalars(val); - }))); - promises.push(upload.happyPromise(validateAsync('duration', null, /audio|video/, + })); + promises.push(validateAsync('duration', null, /audio|video/, function (file, val) { return upload.emptyPromise(val); }, function (r) { return r; - }))); + })); - promises.push(upload.happyPromise(validateAsync('validateAsyncFn', null, null, + promises.push(validateAsync('validateAsyncFn', null, null, function (file, val) { return val; }, function (r) { return r === true || r === null || r === ''; - }))); + })); - return $q.all(promises).then(function () { - deffer.resolve(ngModel, ngModel.$ngfValidations); + $q.all(promises).then(function () { + + if (runAllValidation) { + for (var i = 0; i < files.length; i++) { + var file = files[i]; + if (file.$error) { + files.splice(i--, 1); + } + } + } + + runAllValidation = false; + validateSync('maxFiles', null, function (file, val, i) { + return prevLength + i < val; + }); + + deffer.resolve({'validFiles': files, 'invalidFiles': invalidFiles}); }); + return deffer.promise; }; upload.imageDimensions = function (file) { @@ -1921,8 +2016,8 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct .css('max-width', 'none !important').css('max-height', 'none !important'); function success() { - var width = img[0].clientWidth; - var height = img[0].clientHeight; + var width = img[0].naturalWidth || img[0].clientWidth; + var height = img[0].naturalHeight || img[0].clientHeight; img.remove(); file.$ngfWidth = width; file.$ngfHeight = height; @@ -1936,23 +2031,23 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct img.on('load', success); img.on('error', error); - var count = 0; - function checkLoadError() { + var secondsCounter = 0; + function checkLoadErrorInCaseOfNoCallback() { $timeout(function () { if (img[0].parentNode) { if (img[0].clientWidth) { success(); - } else if (count > 10) { + } else if (secondsCounter++ > 10) { error(); } else { - checkLoadError(); + checkLoadErrorInCaseOfNoCallback(); } } }, 1000); } - checkLoadError(); + checkLoadErrorInCaseOfNoCallback(); angular.element(document.getElementsByTagName('body')[0]).append(img); }, function () { @@ -2063,31 +2158,35 @@ ngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadVa var deferred = $q.defer(); var canvasElement = document.createElement('canvas'); var imageElement = document.createElement('img'); + imageElement.setAttribute('style', 'visibility:hidden;position:fixed;z-index:-100000'); + document.body.appendChild(imageElement); imageElement.onload = function () { - if (resizeIf != null && resizeIf(imageElement.width, imageElement.height) === false) { + var imgWidth = imageElement.width, imgHeight = imageElement.height; + imageElement.parentNode.removeChild(imageElement); + if (resizeIf != null && resizeIf(imgWidth, imgHeight) === false) { deferred.reject('resizeIf'); return; } try { if (ratio) { var ratioFloat = upload.ratioToFloat(ratio); - var imgRatio = imageElement.width / imageElement.height; + var imgRatio = imgWidth / imgHeight; if (imgRatio < ratioFloat) { - width = imageElement.width; + width = imgWidth; height = width / ratioFloat; } else { - height = imageElement.height; + height = imgHeight; width = height * ratioFloat; } } if (!width) { - width = imageElement.width; + width = imgWidth; } if (!height) { - height = imageElement.height; + height = imgHeight; } - var dimensions = calculateAspectRatioFit(imageElement.width, imageElement.height, width, height, centerCrop); + var dimensions = calculateAspectRatioFit(imgWidth, imgHeight, width, height, centerCrop); canvasElement.width = Math.min(dimensions.width, width); canvasElement.height = Math.min(dimensions.height, height); var context = canvasElement.getContext('2d'); @@ -2100,6 +2199,7 @@ ngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadVa } }; imageElement.onerror = function () { + imageElement.parentNode.removeChild(imageElement); deferred.reject(); }; imageElement.src = imagen; @@ -2136,14 +2236,15 @@ ngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadVa }); } - upload.resize = function (file, width, height, quality, type, ratio, centerCrop, resizeIf, restoreExif) { + upload.resize = function (file, options) { if (file.type.indexOf('image') !== 0) return upload.emptyPromise(file); var deferred = $q.defer(); upload.dataUrl(file, true).then(function (url) { - resize(url, width, height, quality, type || file.type, ratio, centerCrop, resizeIf) + resize(url, options.width, options.height, options.quality, options.type || file.type, + options.ratio, options.centerCrop, options.resizeIf) .then(function (dataUrl) { - if (file.type === 'image/jpeg' && restoreExif) { + if (file.type === 'image/jpeg' && options.restoreExif !== false) { try { dataUrl = upload.restoreExif(url, dataUrl); } catch (e) { @@ -2172,13 +2273,13 @@ ngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadVa }]); (function () { - ngFileUpload.directive('ngfDrop', ['$parse', '$timeout', '$location', 'Upload', '$http', '$q', - function ($parse, $timeout, $location, Upload, $http, $q) { + ngFileUpload.directive('ngfDrop', ['$parse', '$timeout', '$window', 'Upload', '$http', '$q', + function ($parse, $timeout, $window, Upload, $http, $q) { return { restrict: 'AEC', require: '?ngModel', link: function (scope, elem, attr, ngModel) { - linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location, Upload, $http, $q); + linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $window, Upload, $http, $q); } }; }]); @@ -2203,7 +2304,7 @@ ngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadVa }; }]); - function linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $location, upload, $http, $q) { + function linkDrop(scope, elem, attr, ngModel, $parse, $timeout, $window, upload, $http, $q) { var available = dropAvailable(); var attrGetter = function (name, scope, params) { @@ -2279,23 +2380,7 @@ ngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadVa if (stopPropagation(scope)) evt.stopPropagation(); if (actualDragOverClass) elem.removeClass(actualDragOverClass); actualDragOverClass = null; - var items = evt.dataTransfer.items; - var html; - try { - html = evt.dataTransfer && evt.dataTransfer.getData && evt.dataTransfer.getData('text/html'); - } catch (e) {/* Fix IE11 that throw error calling getData */ - } - - extractFiles(items, evt.dataTransfer.files, attrGetter('ngfAllowDir', scope) !== false, - attrGetter('multiple') || attrGetter('ngfMultiple', scope)).then(function (files) { - if (files.length) { - updateModel(files, evt); - } else { - extractFilesFromHtml('dropUrl', html).then(function (files) { - updateModel(files, evt); - }); - } - }); + extractFilesAndUpdateModel(evt.dataTransfer, evt, 'dropUrl'); }, false); elem[0].addEventListener('paste', function (evt) { if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1 && @@ -2303,22 +2388,7 @@ ngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadVa evt.preventDefault(); } if (isDisabled() || !upload.shouldUpdateOn('paste', attr, scope)) return; - var files = []; - var clipboard = evt.clipboardData || evt.originalEvent.clipboardData; - if (clipboard && clipboard.items) { - for (var k = 0; k < clipboard.items.length; k++) { - if (clipboard.items[k].type.indexOf('image') !== -1) { - files.push(clipboard.items[k].getAsFile()); - } - } - } - if (files.length) { - updateModel(files, evt); - } else { - extractFilesFromHtml('pasteUrl', clipboard).then(function (files) { - updateModel(files, evt); - }); - } + extractFilesAndUpdateModel(evt.clipboardData || evt.originalEvent.clipboardData, evt, 'pasteUrl'); }, false); if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1 && @@ -2331,12 +2401,33 @@ ngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadVa }); } + function extractFilesAndUpdateModel(source, evt, updateOnType) { + if (!source) return; + // html needs to be calculated on the same process otherwise the data will be wiped + // after promise resolve or setTimeout. + var html; + try { + html = source && source.getData && source.getData('text/html'); + } catch (e) {/* Fix IE11 that throw error calling getData */ + } + extractFiles(source.items, source.files, attrGetter('ngfAllowDir', scope) !== false, + attrGetter('multiple') || attrGetter('ngfMultiple', scope)).then(function (files) { + if (files.length) { + updateModel(files, evt); + } else { + extractFilesFromHtml(updateOnType, html).then(function (files) { + updateModel(files, evt); + }); + } + }); + } + function updateModel(files, evt) { upload.updateModel(ngModel, attr, scope, attrGetter('ngfChange') || attrGetter('ngfDrop'), files, evt); } function extractFilesFromHtml(updateOn, html) { - if (!upload.shouldUpdateOn(updateOn, attr, scope) || !html) return upload.rejectPromise([]); + if (!upload.shouldUpdateOn(updateOn, attr, scope) || typeof html !== 'string') return upload.rejectPromise([]); var urls = []; html.replace(/<(img src|img [^>]* src) *=\"([^\"]*)\"/gi, function (m, n, src) { urls.push(src); @@ -2387,8 +2478,14 @@ ngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadVa } function extractFiles(items, fileList, allowDir, multiple) { - var maxFiles = upload.getValidationAttr(attr, scope, 'maxFiles') || Number.MAX_VALUE; - var maxTotalSize = upload.getValidationAttr(attr, scope, 'maxTotalSize') || Number.MAX_VALUE; + var maxFiles = upload.getValidationAttr(attr, scope, 'maxFiles'); + if (maxFiles == null) { + maxFiles = Number.MAX_VALUE; + } + var maxTotalSize = upload.getValidationAttr(attr, scope, 'maxTotalSize'); + if (maxTotalSize == null) { + maxTotalSize = Number.MAX_VALUE; + } var includeDir = attrGetter('ngfIncludeDir', scope); var files = [], totalSize = 0; @@ -2399,7 +2496,7 @@ ngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadVa var promises = [upload.emptyPromise()]; if (includeDir) { var file = {type: 'directory'}; - file.name = file.path = (path || '') + entry.name + entry.name; + file.name = file.path = (path || '') + entry.name; files.push(file); } var dirReader = entry.createReader(); @@ -2453,7 +2550,7 @@ ngFileUpload.service('UploadResize', ['UploadValidate', '$q', function (UploadVa var promises = [upload.emptyPromise()]; - if (items && items.length > 0 && $location.protocol() !== 'file') { + if (items && items.length > 0 && $window.location.protocol !== 'file:') { for (var i = 0; i < items.length; i++) { if (items[i].webkitGetAsEntry && items[i].webkitGetAsEntry() && items[i].webkitGetAsEntry().isDirectory) { var entry = items[i].webkitGetAsEntry(); diff --git a/xstatic/pkg/angular_fileupload/data/ng-file-upload-all.min.js b/xstatic/pkg/angular_fileupload/data/ng-file-upload-all.min.js index f8c5ce8..4362546 100644 --- a/xstatic/pkg/angular_fileupload/data/ng-file-upload-all.min.js +++ b/xstatic/pkg/angular_fileupload/data/ng-file-upload-all.min.js @@ -1,4 +1,3 @@ -/*! 12.0.4 */ -!function(){function a(a,b){window.XMLHttpRequest.prototype[a]=b(window.XMLHttpRequest.prototype[a])}function b(a,b,c){try{Object.defineProperty(a,b,{get:c})}catch(d){}}if(window.FileAPI||(window.FileAPI={}),!window.XMLHttpRequest)throw"AJAX is not supported. XMLHttpRequest is not defined.";if(FileAPI.shouldLoad=!window.FormData||FileAPI.forceLoad,FileAPI.shouldLoad){var c=function(a){if(!a.__listeners){a.upload||(a.upload={}),a.__listeners=[];var b=a.upload.addEventListener;a.upload.addEventListener=function(c,d){a.__listeners[c]=d,b&&b.apply(this,arguments)}}};a("open",function(a){return function(b,d,e){c(this),this.__url=d;try{a.apply(this,[b,d,e])}catch(f){f.message.indexOf("Access is denied")>-1&&(this.__origError=f,a.apply(this,[b,"_fix_for_ie_crossdomain__",e]))}}}),a("getResponseHeader",function(a){return function(b){return this.__fileApiXHR&&this.__fileApiXHR.getResponseHeader?this.__fileApiXHR.getResponseHeader(b):null==a?null:a.apply(this,[b])}}),a("getAllResponseHeaders",function(a){return function(){return this.__fileApiXHR&&this.__fileApiXHR.getAllResponseHeaders?this.__fileApiXHR.getAllResponseHeaders():null==a?null:a.apply(this)}}),a("abort",function(a){return function(){return this.__fileApiXHR&&this.__fileApiXHR.abort?this.__fileApiXHR.abort():null==a?null:a.apply(this)}}),a("setRequestHeader",function(a){return function(b,d){if("__setXHR_"===b){c(this);var e=d(this);e instanceof Function&&e(this)}else this.__requestHeaders=this.__requestHeaders||{},this.__requestHeaders[b]=d,a.apply(this,arguments)}}),a("send",function(a){return function(){var c=this;if(arguments[0]&&arguments[0].__isFileAPIShim){var d=arguments[0],e={url:c.__url,jsonp:!1,cache:!0,complete:function(a,d){a&&angular.isString(a)&&-1!==a.indexOf("#2174")&&(a=null),c.__completed=!0,!a&&c.__listeners.load&&c.__listeners.load({type:"load",loaded:c.__loaded,total:c.__total,target:c,lengthComputable:!0}),!a&&c.__listeners.loadend&&c.__listeners.loadend({type:"loadend",loaded:c.__loaded,total:c.__total,target:c,lengthComputable:!0}),"abort"===a&&c.__listeners.abort&&c.__listeners.abort({type:"abort",loaded:c.__loaded,total:c.__total,target:c,lengthComputable:!0}),void 0!==d.status&&b(c,"status",function(){return 0===d.status&&a&&"abort"!==a?500:d.status}),void 0!==d.statusText&&b(c,"statusText",function(){return d.statusText}),b(c,"readyState",function(){return 4}),void 0!==d.response&&b(c,"response",function(){return d.response});var e=d.responseText||(a&&0===d.status&&"abort"!==a?a:void 0);b(c,"responseText",function(){return e}),b(c,"response",function(){return e}),a&&b(c,"err",function(){return a}),c.__fileApiXHR=d,c.onreadystatechange&&c.onreadystatechange(),c.onload&&c.onload()},progress:function(a){if(a.target=c,c.__listeners.progress&&c.__listeners.progress(a),c.__total=a.total,c.__loaded=a.loaded,a.total===a.loaded){var b=this;setTimeout(function(){c.__completed||(c.getAllResponseHeaders=function(){},b.complete(null,{status:204,statusText:"No Content"}))},FileAPI.noContentTimeout||1e4)}},headers:c.__requestHeaders};e.data={},e.files={};for(var f=0;f-1){e=h.substring(0,g+1);break}null==FileAPI.staticPath&&(FileAPI.staticPath=e),i.setAttribute("src",d||e+"FileAPI.min.js"),document.getElementsByTagName("head")[0].appendChild(i)}FileAPI.ngfFixIE=function(d,e,f){if(!b())throw'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"';var g=function(){var b=e.parent();d.attr("disabled")?b&&b.removeClass("js-fileapi-wrapper"):(e.attr("__ngf_flash_")||(e.unbind("change"),e.unbind("click"),e.bind("change",function(a){h.apply(this,[a]),f.apply(this,[a])}),e.attr("__ngf_flash_","true")),b.addClass("js-fileapi-wrapper"),a(d)||(b.css("position","absolute").css("top",c(d[0]).top+"px").css("left",c(d[0]).left+"px").css("width",d[0].offsetWidth+"px").css("height",d[0].offsetHeight+"px").css("filter","alpha(opacity=0)").css("display",d.css("display")).css("overflow","hidden").css("z-index","900000").css("visibility","visible"),e.css("width",d[0].offsetWidth+"px").css("height",d[0].offsetHeight+"px").css("position","absolute").css("top","0px").css("left","0px")))};d.bind("mouseenter",g);var h=function(a){for(var b=FileAPI.getFiles(a),c=0;c0},this.rename=function(a,b){return a.ngfName=b,a},this.jsonBlob=function(a){null==a||angular.isString(a)||(a=JSON.stringify(a));var b=new window.Blob([a],{type:"application/json"});return b._ngfBlob=!0,b},this.json=function(a){return angular.toJson(a)},this.isFile=function(a){return null!=a&&(a instanceof window.Blob||a.flashId&&a.name&&a.size)},this.upload=function(a,b){function c(b,c){if(b._ngfBlob)return b;if(a._file=a._file||b,null!=a._start&&g){a._end&&a._end>=b.size&&(a._finished=!0,a._end=b.size);var d=b.slice(a._start,a._end||b.size);return d.name=b.name,d.ngfName=b.ngfName,a._chunkSize&&(c.append("_chunkSize",a._chunkSize),c.append("_currentChunkSize",a._end-a._start),c.append("_chunkNumber",Math.floor(a._start/a._chunkSize)),c.append("_totalSize",a._file.size)),d}return b}function h(b,d,e){if(void 0!==d)if(angular.isDate(d)&&(d=d.toISOString()),angular.isString(d))b.append(e,d);else if(f.isFile(d)){var g=c(d,b),i=e.split(",");i[1]&&(g.ngfName=i[1].replace(/^\s+|\s+$/g,""),e=i[0]),a._fileKey=a._fileKey||e,b.append(e,g,g.ngfName||g.name)}else if(angular.isObject(d)){if(d.$$ngfCircularDetection)throw"ngFileUpload: Circular reference in config.data. Make sure specified data for Upload.upload() has no circular reference: "+e;d.$$ngfCircularDetection=!0;try{for(var j in d)if(d.hasOwnProperty(j)&&"$$ngfCircularDetection"!==j){var k=null==a.objectKey?"[i]":a.objectKey;d.length&&parseInt(j)>-1&&(k=null==a.arrayKey?k:a.arrayKey),h(b,d[j],e+k.replace(/[ik]/g,j))}}finally{delete d.$$ngfCircularDetection}}else b.append(e,d)}function i(){a._chunkSize=f.translateScalars(a.resumeChunkSize),a._chunkSize=a._chunkSize?parseInt(a._chunkSize.toString()):null,a.headers=a.headers||{},a.headers["Content-Type"]=void 0,a.transformRequest=a.transformRequest?angular.isArray(a.transformRequest)?a.transformRequest:[a.transformRequest]:[],a.transformRequest.push(function(b){var c,d=new window.FormData;b=b||a.fields||{},a.file&&(b.file=a.file);for(c in b)if(b.hasOwnProperty(c)){var e=b[c];a.formDataAppender?a.formDataAppender(d,c,e):h(d,e,c)}return d})}return b||(a=e(a)),a._isDigested||(a._isDigested=!0,i()),d(a)},this.http=function(b){return b=e(b),b.transformRequest=b.transformRequest||function(b){return window.ArrayBuffer&&b instanceof window.ArrayBuffer||b instanceof window.Blob?b:a.defaults.transformRequest[0].apply(this,arguments)},b._chunkSize=f.translateScalars(b.resumeChunkSize),b._chunkSize=b._chunkSize?parseInt(b._chunkSize.toString()):null,d(b)},this.translateScalars=function(a){if(angular.isString(a)){if(a.search(/kb/i)===a.length-2)return parseFloat(1024*a.substring(0,a.length-2));if(a.search(/mb/i)===a.length-2)return parseFloat(1048576*a.substring(0,a.length-2));if(a.search(/gb/i)===a.length-2)return parseFloat(1073741824*a.substring(0,a.length-2));if(a.search(/b/i)===a.length-1)return parseFloat(a.substring(0,a.length-1));if(a.search(/s/i)===a.length-1)return parseFloat(a.substring(0,a.length-1));if(a.search(/m/i)===a.length-1)return parseFloat(60*a.substring(0,a.length-1));if(a.search(/h/i)===a.length-1)return parseFloat(3600*a.substring(0,a.length-1))}return a},this.urlToBlob=function(c){var d=b.defer();return a({url:c,method:"get",responseType:"arraybuffer"}).then(function(a){var b=new Uint8Array(a.data),c=a.headers("content-type")||"image/WebP",e=new window.Blob([b],{type:c});d.resolve(e)},function(a){d.reject(a)}),d.promise},this.setDefaults=function(a){this.defaults=a||{}},this.defaults={},this.version=ngFileUpload.version}]),ngFileUpload.service("Upload",["$parse","$timeout","$compile","$q","UploadExif",function(a,b,c,d,e){function f(a,b,c){var e=[i.emptyPromise()];return angular.forEach(a,function(d,f){0===d.type.indexOf("image/jpeg")&&i.attrGetter("ngfFixOrientation",b,c,{$file:d})&&e.push(i.happyPromise(i.applyExifRotation(d),d).then(function(b){a.splice(f,1,b)}))}),d.all(e)}function g(a,b,c){var e=i.attrGetter("ngfResize",b,c);if(!e||!i.isResizeSupported()||!a.length)return i.emptyPromise();if(!(e instanceof Function))return h(e,a,b,c);var f=d.defer();e(a).then(function(d){h(d,a,b,c).then(function(a){f.resolve(a)},function(a){f.reject(a)})},function(a){f.reject(a)})}function h(a,b,c,e){function f(d,f){if(0===d.type.indexOf("image")){if(a.pattern&&!i.validatePattern(d,a.pattern))return;var h=i.resize(d,a.width,a.height,a.quality,a.type,a.ratio,a.centerCrop,function(a,b){return i.attrGetter("ngfResizeIf",c,e,{$width:a,$height:b,$file:d})},a.restoreExif!==!1);g.push(h),h.then(function(a){b.splice(f,1,a)},function(a){d.$error="resize",d.$errorParam=(a?(a.message?a.message:a)+": ":"")+(d&&d.name)})}}for(var g=[i.emptyPromise()],h=0;h-1:!0},i.emptyPromise=function(){var a=d.defer(),c=arguments;return b(function(){a.resolve.apply(a,c)}),a.promise},i.rejectPromise=function(){var a=d.defer(),c=arguments;return b(function(){a.reject.apply(a,c)}),a.promise},i.happyPromise=function(a,c){var e=d.defer();return a.then(function(a){e.resolve(a)},function(a){b(function(){throw a}),e.resolve(c)}),e.promise},i.updateModel=function(c,d,e,h,j,k,l){function m(f,g,j,l,m){d.$$ngfPrevValidFiles=f,d.$$ngfPrevInvalidFiles=g;var n=f&&f.length?f[0]:null,o=g&&g.length?g[0]:null;c&&(i.applyModelValidation(c,f),c.$setViewValue(m?n:f)),h&&a(h)(e,{$files:f,$file:n,$newFiles:j,$duplicateFiles:l,$invalidFiles:g,$invalidFile:o,$event:k});var p=i.attrGetter("ngfModelInvalid",d);p&&b(function(){a(p).assign(e,m?o:g)}),b(function(){})}function n(){function a(a,b){return a.name===b.name&&(a.$ngfOrigSize||a.size)===(b.$ngfOrigSize||b.size)&&a.type===b.type}function b(b){var c;for(c=0;c2){var c=d.defaults.androidFixMinorVersion||4;return parseInt(b[1])<4||parseInt(b[1])===c&&parseInt(b[2])');n(a);var c=angular.element("");return c.css("visibility","hidden").css("position","absolute").css("overflow","hidden").css("width","0px").css("height","0px").css("border","none").css("margin","0px").css("padding","0px").attr("tabindex","-1"),g.push({el:b,ref:c}),document.body.appendChild(c.append(a)[0]),a}function p(c){if(b.attr("disabled"))return!1;if(!t("ngfSelectDisabled",a)){var d=q(c);if(null!=d)return d;r(c);try{k()||document.body.contains(w[0])||(g.push({el:b,ref:w.parent()}),document.body.appendChild(w.parent()[0]),w.bind("change",m))}catch(f){}return e(navigator.userAgent)?setTimeout(function(){w[0].click()},0):w[0].click(),!1}}function q(a){var b=a.changedTouches||a.originalEvent&&a.originalEvent.changedTouches;if("touchstart"===a.type)return v=b?b[0].clientY:0,!0;if(a.stopPropagation(),a.preventDefault(),"touchend"===a.type){var c=b?b[0].clientY:0;if(Math.abs(c-v)>20)return!1}}function r(b){j.shouldUpdateOn("click",c,a)&&w.val()&&(w.val(null),j.updateModel(d,c,a,l(),null,b,!0))}function s(a){if(w&&!w.attr("__ngf_ie10_Fix_")){if(!w[0].parentNode)return void(w=null);a.preventDefault(),a.stopPropagation(),w.unbind("click");var b=w.clone();return w.replaceWith(b),w=b,w.attr("__ngf_ie10_Fix_","true"),w.bind("change",m),w.bind("click",s),w[0].click(),!1}w.removeAttr("__ngf_ie10_Fix_")}var t=function(a,b){return j.attrGetter(a,c,b)};j.registerModelChangeValidator(d,c,a);var u=[];u.push(a.$watch(t("ngfMultiple"),function(){w.attr("multiple",t("ngfMultiple",a))})),u.push(a.$watch(t("ngfCapture"),function(){w.attr("capture",t("ngfCapture",a))})),u.push(a.$watch(t("ngfAccept"),function(){w.attr("accept",t("ngfAccept",a))})),c.$observe("accept",function(){w.attr("accept",t("accept"))}),u.push(function(){c.$$observers&&delete c.$$observers.accept});var v=0,w=b;k()||(w=o()),w.bind("change",m),k()?b.bind("click",r):b.bind("click touchstart touchend",p),-1!==navigator.appVersion.indexOf("MSIE 10")&&w.bind("click",s),d&&d.$formatters.push(function(a){return(null==a||0===a.length)&&w.val()&&w.val(null),a}),a.$on("$destroy",function(){k()||w.parent().remove(),angular.forEach(u,function(a){a()})}),h(function(){for(var a=0;ab||d.blobUrls.length>e)&&d.blobUrls.length>1;){var h=d.blobUrls.splice(0,1)[0];c.revokeObjectURL(h.url),d.blobUrlsTotalSize-=h.size}}})}else{var i=new FileReader;i.onload=function(c){b(function(){a.$ngfDataUrl=c.target.result,g.resolve(c.target.result,a),b(function(){delete a.$ngfDataUrl},1e3)})},i.onerror=function(){b(function(){a.$ngfDataUrl="",g.reject()})},i.readAsDataURL(a)}}else b(function(){a[e?"$ngfDataUrl":"$ngfBlobUrl"]="",g.reject()})}),f=e?a.$$ngfDataUrlPromise=g.promise:a.$$ngfBlobUrlPromise=g.promise,f["finally"](function(){delete a[e?"$$ngfDataUrlPromise":"$$ngfBlobUrlPromise"]}),f},d}]),ngFileUpload.directive("ngfSrc",["Upload","$timeout",function(a,c){return{restrict:"AE",link:function(d,e,f){b(a,c,d,e,f,"ngfSrc",a.attrGetter("ngfResize",f,d),!1)}}}]),ngFileUpload.directive("ngfBackground",["Upload","$timeout",function(a,c){return{restrict:"AE",link:function(d,e,f){b(a,c,d,e,f,"ngfBackground",a.attrGetter("ngfResize",f,d),!0)}}}]),ngFileUpload.directive("ngfThumbnail",["Upload","$timeout",function(a,c){return{restrict:"AE",link:function(d,e,f){var g=a.attrGetter("ngfSize",f,d);b(a,c,d,e,f,"ngfThumbnail",g,a.attrGetter("ngfAsBackground",f,d))}}}]),ngFileUpload.config(["$compileProvider",function(a){a.imgSrcSanitizationWhitelist&&a.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|local|file|data|blob):/),a.aHrefSanitizationWhitelist&&a.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|local|file|data|blob):/)}]),ngFileUpload.filter("ngfDataUrl",["UploadDataUrl","$sce",function(a,b){return function(c,d,e){if(angular.isString(c))return b.trustAsResourceUrl(c);var f=c&&((d?c.$ngfDataUrl:c.$ngfBlobUrl)||c.$ngfDataUrl);return c&&!f?(!c.$ngfDataUrlFilterInProgress&&angular.isObject(c)&&(c.$ngfDataUrlFilterInProgress=!0,a.dataUrl(c,d)),""):(c&&delete c.$ngfDataUrlFilterInProgress,(c&&f?e?b.trustAsResourceUrl(f):f:c)||"")}}])}(),ngFileUpload.service("UploadValidate",["UploadDataUrl","$q","$timeout",function(a,b,c){function d(a){var b="",c=[];if(a.length>2&&"/"===a[0]&&"/"===a[a.length-1])b=a.substring(1,a.length-1);else{var e=a.split(",");if(e.length>1)for(var f=0;f|:\\-]","g"),"\\$&")+"$",b=b.replace(/\\\*/g,".*").replace(/\\\?/g,"."))}return{regexp:b,excludes:c}}function e(a,b){null==b||a.$dirty||(a.$setDirty?a.$setDirty():a.$dirty=!0)}var f=a;return f.validatePattern=function(a,b){if(!b)return!0;var c=d(b),e=!0;if(c.regexp&&c.regexp.length){var f=new RegExp(c.regexp,"i");e=null!=a.type&&f.test(a.type)||null!=a.name&&f.test(a.name)}for(var g=c.excludes.length;g--;){var h=new RegExp(c.excludes[g],"i");e=e&&(null==a.type||h.test(a.type))&&(null==a.name||h.test(a.name))}return e},f.ratioToFloat=function(a){var b=a.toString(),c=b.search(/[x:]/i);return b=c>-1?parseFloat(b.substring(0,c))/parseFloat(b.substring(c+1)):parseFloat(b)},f.registerModelChangeValidator=function(a,b,c){a&&a.$formatters.push(function(d){a.$dirty&&(d&&!angular.isArray(d)&&(d=[d]),f.validate(d,0,a,b,c).then(function(){f.applyModelValidation(a,d)}))})},f.applyModelValidation=function(a,b){e(a,b),angular.forEach(a.$ngfValidations,function(b){a.$setValidity(b.name,b.valid)})},f.getValidationAttr=function(a,b,c,d,e){var g="ngf"+c[0].toUpperCase()+c.substr(1),h=f.attrGetter(g,a,b,{$file:e});if(null==h&&(h=f.attrGetter("ngfValidate",a,b,{$file:e}))){var i=(d||c).split(".");h=h[i[0]],i.length>1&&(h=h&&h[i[1]])}return h},f.validate=function(a,c,d,e,g){function h(b,c,h){if(a){for(var i=a.length,j=null;i--;){var k=a[i];if(k){var l=f.getValidationAttr(e,g,b,c,k);null!=l&&(h(k,l,i)||(k.$error=b,(k.$errorMessages=k.$errorMessages||{})[b]=!0,k.$errorParam=l,a.splice(i,1),j=!1))}}null!==j&&d.$ngfValidations.push({name:b,valid:j})}}function i(c,h,i,k,l){function m(a,b,d){null!=d?k(b,d).then(function(e){l(e,d)?a.resolve():(b.$error=c,(b.$errorMessages=b.$errorMessages||{})[c]=!0,b.$errorParam=d,a.reject())},function(){j("ngfValidateForce",{$file:b})?(b.$error=c,(b.$errorMessages=b.$errorMessages||{})[c]=!0,b.$errorParam=d,a.reject()):a.resolve()}):a.resolve()}var n=[f.emptyPromise()];return a?(a=void 0===a.length?[a]:a,angular.forEach(a,function(a){var d=b.defer();return n.push(d.promise),!i||null!=a.type&&0===a.type.search(i)?void("dimensions"===c&&null!=f.attrGetter("ngfDimensions",e)?f.imageDimensions(a).then(function(b){m(d,a,j("ngfDimensions",{$file:a,$width:b.width,$height:b.height}))},function(){d.reject()}):"duration"===c&&null!=f.attrGetter("ngfDuration",e)?f.mediaDuration(a).then(function(b){m(d,a,j("ngfDuration",{$file:a,$duration:b}))},function(){d.reject()}):m(d,a,f.getValidationAttr(e,g,c,h,a))):void d.resolve()}),b.all(n).then(function(){d.$ngfValidations.push({name:c,valid:!0})},function(){d.$ngfValidations.push({name:c,valid:!1})})):void 0}d=d||{},d.$ngfValidations=d.$ngfValidations||[],angular.forEach(d.$ngfValidations,function(a){a.valid=!0});var j=function(a,b){return f.attrGetter(a,e,g,b)};if(null==a||0===a.length)return f.emptyPromise(d);a=void 0===a.length?[a]:a.slice(0),h("maxFiles",null,function(a,b,d){return b>c+d}),h("pattern",null,f.validatePattern),h("minSize","size.min",function(a,b){return a.size+.1>=f.translateScalars(b)}),h("maxSize","size.max",function(a,b){return a.size-.1<=f.translateScalars(b)});var k=0;if(h("maxTotalSize",null,function(b,c){return k+=b.size,k>f.translateScalars(c)?(a.splice(0,a.length),!1):!0}),h("validateFn",null,function(a,b){return b===!0||null===b||""===b}),!a.length)return f.emptyPromise(d,d.$ngfValidations);var l=b.defer(),m=[];return m.push(f.happyPromise(i("maxHeight","height.max",/image/,this.imageDimensions,function(a,b){return a.height<=b}))),m.push(f.happyPromise(i("minHeight","height.min",/image/,this.imageDimensions,function(a,b){return a.height>=b}))),m.push(f.happyPromise(i("maxWidth","width.max",/image/,this.imageDimensions,function(a,b){return a.width<=b}))),m.push(f.happyPromise(i("minWidth","width.min",/image/,this.imageDimensions,function(a,b){return a.width>=b}))),m.push(f.happyPromise(i("dimensions",null,/image/,function(a,b){return f.emptyPromise(b)},function(a){return a}))),m.push(f.happyPromise(i("ratio",null,/image/,this.imageDimensions,function(a,b){for(var c=b.toString().split(","),d=!1,e=0;e-1e-4}))),m.push(f.happyPromise(i("maxDuration","duration.max",/audio|video/,this.mediaDuration,function(a,b){return a<=f.translateScalars(b)}))),m.push(f.happyPromise(i("minDuration","duration.min",/audio|video/,this.mediaDuration,function(a,b){return a>=f.translateScalars(b)}))),m.push(f.happyPromise(i("duration",null,/audio|video/,function(a,b){return f.emptyPromise(b)},function(a){return a}))),m.push(f.happyPromise(i("validateAsyncFn",null,null,function(a,b){return b},function(a){return a===!0||null===a||""===a}))),b.all(m).then(function(){l.resolve(d,d.$ngfValidations)})},f.imageDimensions=function(a){if(a.$ngfWidth&&a.$ngfHeight){var d=b.defer();return c(function(){d.resolve({width:a.$ngfWidth,height:a.$ngfHeight})}),d.promise}if(a.$ngfDimensionPromise)return a.$ngfDimensionPromise;var e=b.defer();return c(function(){return 0!==a.type.indexOf("image")?void e.reject("not image"):void f.dataUrl(a).then(function(b){function d(){var b=h[0].clientWidth,c=h[0].clientHeight;h.remove(),a.$ngfWidth=b,a.$ngfHeight=c,e.resolve({width:b,height:c})}function f(){h.remove(),e.reject("load error")}function g(){c(function(){h[0].parentNode&&(h[0].clientWidth?d():i>10?f():g())},1e3)}var h=angular.element("").attr("src",b).css("visibility","hidden").css("position","fixed").css("max-width","none !important").css("max-height","none !important");h.on("load",d),h.on("error",f);var i=0;g(),angular.element(document.getElementsByTagName("body")[0]).append(h)},function(){e.reject("load error")})}),a.$ngfDimensionPromise=e.promise,a.$ngfDimensionPromise["finally"](function(){delete a.$ngfDimensionPromise}),a.$ngfDimensionPromise},f.mediaDuration=function(a){if(a.$ngfDuration){var d=b.defer();return c(function(){d.resolve(a.$ngfDuration)}),d.promise}if(a.$ngfDurationPromise)return a.$ngfDurationPromise;var e=b.defer();return c(function(){return 0!==a.type.indexOf("audio")&&0!==a.type.indexOf("video")?void e.reject("not media"):void f.dataUrl(a).then(function(b){function d(){var b=h[0].duration;a.$ngfDuration=b,h.remove(),e.resolve(b); - -}function f(){h.remove(),e.reject("load error")}function g(){c(function(){h[0].parentNode&&(h[0].duration?d():i>10?f():g())},1e3)}var h=angular.element(0===a.type.indexOf("audio")?"