Administrator
2022-09-14 58d006e05dcf2a20d0ec5367dd03d66a61db6849
提交 | 用户 | 时间
58d006 1 /*
A 2  * jQuery File Upload AngularJS Plugin 1.4.4
3  * https://github.com/blueimp/jQuery-File-Upload
4  *
5  * Copyright 2013, Sebastian Tschan
6  * https://blueimp.net
7  *
8  * Licensed under the MIT license:
9  * http://www.opensource.org/licenses/MIT
10  */
11
12 /*jslint nomen: true, unparam: true */
13 /*global define, angular */
14
15 (function (factory) {
16     'use strict';
17     if (typeof define === 'function' && define.amd) {
18         // Register as an anonymous AMD module:
19         define([
20             'jquery',
21             'angular',
22             './jquery.fileupload-image',
23             './jquery.fileupload-audio',
24             './jquery.fileupload-video',
25             './jquery.fileupload-validate'
26         ], factory);
27     } else {
28         factory();
29     }
30 }(function () {
31     'use strict';
32
33     angular.module('blueimp.fileupload', [])
34
35         // The fileUpload service provides configuration options
36         // for the fileUpload directive and default handlers for
37         // File Upload events:
38         .provider('fileUpload', function () {
39             var scopeApply = function () {
40                     var scope = angular.element(this)
41                             .fileupload('option', 'scope')(),
42                         $timeout = angular.injector(['ng'])
43                             .get('$timeout');
44                     // Safe apply, makes sure $apply is called
45                     // asynchronously outside of the $digest cycle:
46                     $timeout(function () {
47                         scope.$apply();
48                     });
49                 },
50                 $config;
51             $config = this.defaults = {
52                 handleResponse: function (e, data) {
53                     var files = data.result && data.result.files;
54                     if (files) {
55                         data.scope().replace(data.files, files);
56                     } else if (data.errorThrown ||
57                             data.textStatus === 'error') {
58                         data.files[0].error = data.errorThrown ||
59                             data.textStatus;
60                     }
61                 },
62                 add: function (e, data) {
63                     var scope = data.scope();
64                     data.process(function () {
65                         return scope.process(data);
66                     }).always(
67                         function () {
68                             var file = data.files[0],
69                                 submit = function () {
70                                     return data.submit();
71                                 };
72                             angular.forEach(data.files, function (file, index) {
73                                 file._index = index;
74                                 file.$state = function () {
75                                     return data.state();
76                                 };
77                                 file.$progress = function () {
78                                     return data.progress();
79                                 };
80                                 file.$response = function () {
81                                     return data.response();
82                                 };
83                             });
84                             file.$cancel = function () {
85                                 scope.clear(data.files);
86                                 return data.abort();
87                             };
88                             if (file.$state() === 'rejected') {
89                                 file._$submit = submit;
90                             } else {
91                                 file.$submit = submit;
92                             }
93                             scope.$apply(function () {
94                                 var method = scope.option('prependFiles') ?
95                                         'unshift' : 'push';
96                                 Array.prototype[method].apply(
97                                     scope.queue,
98                                     data.files
99                                 );
100                                 if (file.$submit &&
101                                         (scope.option('autoUpload') ||
102                                         data.autoUpload) &&
103                                         data.autoUpload !== false) {
104                                     file.$submit();
105                                 }
106                             });
107                         }
108                     );
109                 },
110                 progress: function (e, data) {
111                     data.scope().$apply();
112                 },
113                 done: function (e, data) {
114                     var that = this;
115                     data.scope().$apply(function () {
116                         data.handleResponse.call(that, e, data);
117                     });
118                 },
119                 fail: function (e, data) {
120                     var that = this;
121                     if (data.errorThrown === 'abort') {
122                         return;
123                     }
124                     if (data.dataType &&
125                             data.dataType.indexOf('json') === data.dataType.length - 4) {
126                         try {
127                             data.result = angular.fromJson(data.jqXHR.responseText);
128                         } catch (ignore) {}
129                     }
130                     data.scope().$apply(function () {
131                         data.handleResponse.call(that, e, data);
132                     });
133                 },
134                 stop: scopeApply,
135                 processstart: scopeApply,
136                 processstop: scopeApply,
137                 getNumberOfFiles: function () {
138                     return this.scope().queue.length;
139                 },
140                 dataType: 'json',
141                 autoUpload: false
142             };
143             this.$get = [
144                 function () {
145                     return {
146                         defaults: $config
147                     };
148                 }
149             ];
150         })
151
152         // Format byte numbers to readable presentations:
153         .provider('formatFileSizeFilter', function () {
154             var $config = {
155                 // Byte units following the IEC format
156                 // http://en.wikipedia.org/wiki/Kilobyte
157                 units: [
158                     {size: 1000000000, suffix: ' GB'},
159                     {size: 1000000, suffix: ' MB'},
160                     {size: 1000, suffix: ' KB'}
161                 ]
162             };
163             this.defaults = $config;
164             this.$get = function () {
165                 return function (bytes) {
166                     if (!angular.isNumber(bytes)) {
167                         return '';
168                     }
169                     var unit = true,
170                         i = 0,
171                         prefix,
172                         suffix;
173                     while (unit) {
174                         unit = $config.units[i];
175                         prefix = unit.prefix || '';
176                         suffix = unit.suffix || '';
177                         if (i === $config.units.length - 1 || bytes >= unit.size) {
178                             return prefix + (bytes / unit.size).toFixed(2) + suffix;
179                         }
180                         i += 1;
181                     }
182                 };
183             };
184         })
185
186         // The FileUploadController initializes the fileupload widget and
187         // provides scope methods to control the File Upload functionality: 
188         .controller('FileUploadController', [
189             '$scope', '$element', '$attrs', '$window', 'fileUpload',
190             function ($scope, $element, $attrs, $window, fileUpload) {
191                 var uploadMethods = {
192                     progress: function () {
193                         return $element.fileupload('progress');
194                     },
195                     active: function () {
196                         return $element.fileupload('active');
197                     },
198                     option: function (option, data) {
199                         return $element.fileupload('option', option, data);
200                     },
201                     add: function (data) {
202                         return $element.fileupload('add', data);
203                     },
204                     send: function (data) {
205                         return $element.fileupload('send', data);
206                     },
207                     process: function (data) {
208                         return $element.fileupload('process', data);
209                     },
210                     processing: function (data) {
211                         return $element.fileupload('processing', data);
212                     }
213                 };
214                 $scope.disabled = !$window.jQuery.support.fileInput;
215                 $scope.queue = $scope.queue || [];
216                 $scope.clear = function (files) {
217                     var queue = this.queue,
218                         i = queue.length,
219                         file = files,
220                         length = 1;
221                     if (angular.isArray(files)) {
222                         file = files[0];
223                         length = files.length;
224                     }
225                     while (i) {
226                         i -= 1;
227                         if (queue[i] === file) {
228                             return queue.splice(i, length);
229                         }
230                     }
231                 };
232                 $scope.replace = function (oldFiles, newFiles) {
233                     var queue = this.queue,
234                         file = oldFiles[0],
235                         i,
236                         j;
237                     for (i = 0; i < queue.length; i += 1) {
238                         if (queue[i] === file) {
239                             for (j = 0; j < newFiles.length; j += 1) {
240                                 queue[i + j] = newFiles[j];
241                             }
242                             return;
243                         }
244                     }
245                 };
246                 $scope.applyOnQueue = function (method) {
247                     var list = this.queue.slice(0),
248                         i,
249                         file;
250                     for (i = 0; i < list.length; i += 1) {
251                         file = list[i];
252                         if (file[method]) {
253                             file[method]();
254                         }
255                     }
256                 };
257                 $scope.submit = function () {
258                     this.applyOnQueue('$submit');
259                 };
260                 $scope.cancel = function () {
261                     this.applyOnQueue('$cancel');
262                 };
263                 // Add upload methods to the scope:
264                 angular.extend($scope, uploadMethods);
265                 // The fileupload widget will initialize with
266                 // the options provided via "data-"-parameters,
267                 // as well as those given via options object:
268                 $element.fileupload(angular.extend(
269                     {scope: function () {
270                         return $scope;
271                     }},
272                     fileUpload.defaults
273                 )).on('fileuploadadd', function (e, data) {
274                     data.scope = $scope.option('scope');
275                 }).on([
276                     'fileuploadadd',
277                     'fileuploadsubmit',
278                     'fileuploadsend',
279                     'fileuploaddone',
280                     'fileuploadfail',
281                     'fileuploadalways',
282                     'fileuploadprogress',
283                     'fileuploadprogressall',
284                     'fileuploadstart',
285                     'fileuploadstop',
286                     'fileuploadchange',
287                     'fileuploadpaste',
288                     'fileuploaddrop',
289                     'fileuploaddragover',
290                     'fileuploadchunksend',
291                     'fileuploadchunkdone',
292                     'fileuploadchunkfail',
293                     'fileuploadchunkalways',
294                     'fileuploadprocessstart',
295                     'fileuploadprocess',
296                     'fileuploadprocessdone',
297                     'fileuploadprocessfail',
298                     'fileuploadprocessalways',
299                     'fileuploadprocessstop'
300                 ].join(' '), function (e, data) {
301                     if ($scope.$emit(e.type, data).defaultPrevented) {
302                         e.preventDefault();
303                     }
304                 }).on('remove', function () {
305                     // Remove upload methods from the scope,
306                     // when the widget is removed:
307                     var method;
308                     for (method in uploadMethods) {
309                         if (uploadMethods.hasOwnProperty(method)) {
310                             delete $scope[method];
311                         }
312                     }
313                 });
314                 // Observe option changes:
315                 $scope.$watch(
316                     $attrs.fileUpload,
317                     function (newOptions) {
318                         if (newOptions) {
319                             $element.fileupload('option', newOptions);
320                         }
321                     }
322                 );
323             }
324         ])
325
326         // Provide File Upload progress feedback:
327         .controller('FileUploadProgressController', [
328             '$scope', '$attrs', '$parse',
329             function ($scope, $attrs, $parse) {
330                 var fn = $parse($attrs.fileUploadProgress),
331                     update = function () {
332                         var progress = fn($scope);
333                         if (!progress || !progress.total) {
334                             return;
335                         }
336                         $scope.num = Math.floor(
337                             progress.loaded / progress.total * 100
338                         );
339                     };
340                 update();
341                 $scope.$watch(
342                     $attrs.fileUploadProgress + '.loaded',
343                     function (newValue, oldValue) {
344                         if (newValue !== oldValue) {
345                             update();
346                         }
347                     }
348                 );
349             }
350         ])
351
352         // Display File Upload previews:
353         .controller('FileUploadPreviewController', [
354             '$scope', '$element', '$attrs', '$parse',
355             function ($scope, $element, $attrs, $parse) {
356                 var fn = $parse($attrs.fileUploadPreview),
357                     file = fn($scope);
358                 if (file.preview) {
359                     $element.append(file.preview);
360                 }
361             }
362         ])
363
364         .directive('fileUpload', function () {
365             return {
366                 controller: 'FileUploadController'
367             };
368         })
369
370         .directive('fileUploadProgress', function () {
371             return {
372                 controller: 'FileUploadProgressController'
373             };
374         })
375
376         .directive('fileUploadPreview', function () {
377             return {
378                 controller: 'FileUploadPreviewController'
379             };
380         })
381
382         // Enhance the HTML5 download attribute to
383         // allow drag&drop of files to the desktop:
384         .directive('download', function () {
385             return function (scope, elm) {
386                 elm.on('dragstart', function (e) {
387                     try {
388                         e.originalEvent.dataTransfer.setData(
389                             'DownloadURL',
390                             [
391                                 'application/octet-stream',
392                                 elm.prop('download'),
393                                 elm.prop('href')
394                             ].join(':')
395                         );
396                     } catch (ignore) {}
397                 });
398             };
399         });
400
401 }));