123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- /*
- * jQuery File Upload AngularJS Plugin
- * https://github.com/blueimp/jQuery-File-Upload
- *
- * Copyright 2013, Sebastian Tschan
- * https://blueimp.net
- *
- * Licensed under the MIT license:
- * https://opensource.org/licenses/MIT
- */
- /* jshint nomen:false */
- /* global define, angular, require */
- ;(function (factory) {
- 'use strict';
- if (typeof define === 'function' && define.amd) {
- // Register as an anonymous AMD module:
- define([
- 'jquery',
- 'angular',
- './jquery.fileupload-image',
- './jquery.fileupload-audio',
- './jquery.fileupload-video',
- './jquery.fileupload-validate'
- ], factory);
- } else if (typeof exports === 'object') {
- // Node/CommonJS:
- factory(
- require('jquery'),
- require('angular'),
- require('./jquery.fileupload-image'),
- require('./jquery.fileupload-audio'),
- require('./jquery.fileupload-video'),
- require('./jquery.fileupload-validate')
- );
- } else {
- factory();
- }
- }(function () {
- 'use strict';
- angular.module('blueimp.fileupload', [])
- // The fileUpload service provides configuration options
- // for the fileUpload directive and default handlers for
- // File Upload events:
- .provider('fileUpload', function () {
- var scopeEvalAsync = function (expression) {
- var scope = angular.element(this)
- .fileupload('option', 'scope');
- // Schedule a new $digest cycle if not already inside of one
- // and evaluate the given expression:
- scope.$evalAsync(expression);
- },
- addFileMethods = function (scope, data) {
- var files = data.files,
- file = files[0];
- angular.forEach(files, function (file, index) {
- file._index = index;
- file.$state = function () {
- return data.state();
- };
- file.$processing = function () {
- return data.processing();
- };
- file.$progress = function () {
- return data.progress();
- };
- file.$response = function () {
- return data.response();
- };
- });
- file.$submit = function () {
- if (!file.error) {
- return data.submit();
- }
- };
- file.$cancel = function () {
- return data.abort();
- };
- },
- $config;
- $config = this.defaults = {
- handleResponse: function (e, data) {
- var files = data.result && data.result.files;
- if (files) {
- data.scope.replace(data.files, files);
- } else if (data.errorThrown ||
- data.textStatus === 'error') {
- data.files[0].error = data.errorThrown ||
- data.textStatus;
- }
- },
- add: function (e, data) {
- if (e.isDefaultPrevented()) {
- return false;
- }
- var scope = data.scope,
- filesCopy = [];
- angular.forEach(data.files, function (file) {
- filesCopy.push(file);
- });
- scope.$parent.$applyAsync(function () {
- addFileMethods(scope, data);
- var method = scope.option('prependFiles') ?
- 'unshift' : 'push';
- Array.prototype[method].apply(scope.queue, data.files);
- });
- data.process(function () {
- return scope.process(data);
- }).always(function () {
- scope.$parent.$applyAsync(function () {
- addFileMethods(scope, data);
- scope.replace(filesCopy, data.files);
- });
- }).then(function () {
- if ((scope.option('autoUpload') ||
- data.autoUpload) &&
- data.autoUpload !== false) {
- data.submit();
- }
- });
- },
- done: function (e, data) {
- if (e.isDefaultPrevented()) {
- return false;
- }
- var that = this;
- data.scope.$apply(function () {
- data.handleResponse.call(that, e, data);
- });
- },
- fail: function (e, data) {
- if (e.isDefaultPrevented()) {
- return false;
- }
- var that = this,
- scope = data.scope;
- if (data.errorThrown === 'abort') {
- scope.clear(data.files);
- return;
- }
- scope.$apply(function () {
- data.handleResponse.call(that, e, data);
- });
- },
- stop: scopeEvalAsync,
- processstart: scopeEvalAsync,
- processstop: scopeEvalAsync,
- getNumberOfFiles: function () {
- var scope = this.scope;
- return scope.queue.length - scope.processing();
- },
- dataType: 'json',
- autoUpload: false
- };
- this.$get = [
- function () {
- return {
- defaults: $config
- };
- }
- ];
- })
- // Format byte numbers to readable presentations:
- .provider('formatFileSizeFilter', function () {
- var $config = {
- // Byte units following the IEC format
- // http://en.wikipedia.org/wiki/Kilobyte
- units: [
- {size: 1000000000, suffix: ' GB'},
- {size: 1000000, suffix: ' MB'},
- {size: 1000, suffix: ' KB'}
- ]
- };
- this.defaults = $config;
- this.$get = function () {
- return function (bytes) {
- if (!angular.isNumber(bytes)) {
- return '';
- }
- var unit = true,
- i = 0,
- prefix,
- suffix;
- while (unit) {
- unit = $config.units[i];
- prefix = unit.prefix || '';
- suffix = unit.suffix || '';
- if (i === $config.units.length - 1 || bytes >= unit.size) {
- return prefix + (bytes / unit.size).toFixed(2) + suffix;
- }
- i += 1;
- }
- };
- };
- })
- // The FileUploadController initializes the fileupload widget and
- // provides scope methods to control the File Upload functionality:
- .controller('FileUploadController', [
- '$scope', '$element', '$attrs', '$window', 'fileUpload','$q',
- function ($scope, $element, $attrs, $window, fileUpload, $q) {
- var uploadMethods = {
- progress: function () {
- return $element.fileupload('progress');
- },
- active: function () {
- return $element.fileupload('active');
- },
- option: function (option, data) {
- if (arguments.length === 1) {
- return $element.fileupload('option', option);
- }
- $element.fileupload('option', option, data);
- },
- add: function (data) {
- return $element.fileupload('add', data);
- },
- send: function (data) {
- return $element.fileupload('send', data);
- },
- process: function (data) {
- return $element.fileupload('process', data);
- },
- processing: function (data) {
- return $element.fileupload('processing', data);
- }
- };
- $scope.disabled = !$window.jQuery.support.fileInput;
- $scope.queue = $scope.queue || [];
- $scope.clear = function (files) {
- var queue = this.queue,
- i = queue.length,
- file = files,
- length = 1;
- if (angular.isArray(files)) {
- file = files[0];
- length = files.length;
- }
- while (i) {
- i -= 1;
- if (queue[i] === file) {
- return queue.splice(i, length);
- }
- }
- };
- $scope.replace = function (oldFiles, newFiles) {
- var queue = this.queue,
- file = oldFiles[0],
- i,
- j;
- for (i = 0; i < queue.length; i += 1) {
- if (queue[i] === file) {
- for (j = 0; j < newFiles.length; j += 1) {
- queue[i + j] = newFiles[j];
- }
- return;
- }
- }
- };
- $scope.applyOnQueue = function (method) {
- var list = this.queue.slice(0),
- i,
- file,
- promises = [];
- for (i = 0; i < list.length; i += 1) {
- file = list[i];
- if (file[method]) {
- promises.push(file[method]());
- }
- }
- return $q.all(promises);
- };
- $scope.submit = function () {
- return this.applyOnQueue('$submit');
- };
- $scope.cancel = function () {
- return this.applyOnQueue('$cancel');
- };
- // Add upload methods to the scope:
- angular.extend($scope, uploadMethods);
- // The fileupload widget will initialize with
- // the options provided via "data-"-parameters,
- // as well as those given via options object:
- $element.fileupload(angular.extend(
- {scope: $scope},
- fileUpload.defaults
- )).on('fileuploadadd', function (e, data) {
- data.scope = $scope;
- }).on('fileuploadfail', function (e, data) {
- if (data.errorThrown === 'abort') {
- return;
- }
- if (data.dataType &&
- data.dataType.indexOf('json') === data.dataType.length - 4) {
- try {
- data.result = angular.fromJson(data.jqXHR.responseText);
- } catch (ignore) {}
- }
- }).on([
- 'fileuploadadd',
- 'fileuploadsubmit',
- 'fileuploadsend',
- 'fileuploaddone',
- 'fileuploadfail',
- 'fileuploadalways',
- 'fileuploadprogress',
- 'fileuploadprogressall',
- 'fileuploadstart',
- 'fileuploadstop',
- 'fileuploadchange',
- 'fileuploadpaste',
- 'fileuploaddrop',
- 'fileuploaddragover',
- 'fileuploadchunksend',
- 'fileuploadchunkdone',
- 'fileuploadchunkfail',
- 'fileuploadchunkalways',
- 'fileuploadprocessstart',
- 'fileuploadprocess',
- 'fileuploadprocessdone',
- 'fileuploadprocessfail',
- 'fileuploadprocessalways',
- 'fileuploadprocessstop'
- ].join(' '), function (e, data) {
- $scope.$parent.$applyAsync(function () {
- if ($scope.$emit(e.type, data).defaultPrevented) {
- e.preventDefault();
- }
- });
- }).on('remove', function () {
- // Remove upload methods from the scope,
- // when the widget is removed:
- var method;
- for (method in uploadMethods) {
- if (uploadMethods.hasOwnProperty(method)) {
- delete $scope[method];
- }
- }
- });
- // Observe option changes:
- $scope.$watch(
- $attrs.fileUpload,
- function (newOptions) {
- if (newOptions) {
- $element.fileupload('option', newOptions);
- }
- }
- );
- }
- ])
- // Provide File Upload progress feedback:
- .controller('FileUploadProgressController', [
- '$scope', '$attrs', '$parse',
- function ($scope, $attrs, $parse) {
- var fn = $parse($attrs.fileUploadProgress),
- update = function () {
- var progress = fn($scope);
- if (!progress || !progress.total) {
- return;
- }
- $scope.num = Math.floor(
- progress.loaded / progress.total * 100
- );
- };
- update();
- $scope.$watch(
- $attrs.fileUploadProgress + '.loaded',
- function (newValue, oldValue) {
- if (newValue !== oldValue) {
- update();
- }
- }
- );
- }
- ])
- // Display File Upload previews:
- .controller('FileUploadPreviewController', [
- '$scope', '$element', '$attrs',
- function ($scope, $element, $attrs) {
- $scope.$watch(
- $attrs.fileUploadPreview + '.preview',
- function (preview) {
- $element.empty();
- if (preview) {
- $element.append(preview);
- }
- }
- );
- }
- ])
- .directive('fileUpload', function () {
- return {
- controller: 'FileUploadController',
- scope: true
- };
- })
- .directive('fileUploadProgress', function () {
- return {
- controller: 'FileUploadProgressController',
- scope: true
- };
- })
- .directive('fileUploadPreview', function () {
- return {
- controller: 'FileUploadPreviewController'
- };
- })
- // Enhance the HTML5 download attribute to
- // allow drag&drop of files to the desktop:
- .directive('download', function () {
- return function (scope, elm) {
- elm.on('dragstart', function (e) {
- try {
- e.originalEvent.dataTransfer.setData(
- 'DownloadURL',
- [
- 'application/octet-stream',
- elm.prop('download'),
- elm.prop('href')
- ].join(':')
- );
- } catch (ignore) {}
- });
- };
- });
- }));
|