|
1 | 1 | /*
|
2 |
| - * jQuery File Upload AngularJS Plugin 1.0.1 |
| 2 | + * jQuery File Upload AngularJS Plugin 1.4.4 |
3 | 3 | * https://github.com/blueimp/jQuery-File-Upload
|
4 | 4 | *
|
5 | 5 | * Copyright 2013, Sebastian Tschan
|
|
10 | 10 | */
|
11 | 11 |
|
12 | 12 | /*jslint nomen: true, unparam: true */
|
13 |
| -/*global angular */ |
| 13 | +/*global define, angular */ |
14 | 14 |
|
15 |
| -(function () { |
| 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 () { |
16 | 31 | 'use strict';
|
17 | 32 |
|
18 | 33 | angular.module('blueimp.fileupload', [])
|
19 | 34 |
|
| 35 | + // The fileUpload service provides configuration options |
| 36 | + // for the fileUpload directive and default handlers for |
| 37 | + // File Upload events: |
20 | 38 | .provider('fileUpload', function () {
|
21 | 39 | var scopeApply = function () {
|
22 | 40 | var scope = angular.element(this)
|
23 |
| - .fileupload('option', 'scope')(); |
24 |
| - if (!scope.$$phase) { |
| 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 () { |
25 | 47 | scope.$apply();
|
26 |
| - } |
| 48 | + }); |
27 | 49 | },
|
28 | 50 | $config;
|
29 | 51 | $config = this.defaults = {
|
|
47 | 69 | submit = function () {
|
48 | 70 | return data.submit();
|
49 | 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 | + }); |
50 | 84 | file.$cancel = function () {
|
51 | 85 | scope.clear(data.files);
|
52 | 86 | return data.abort();
|
53 | 87 | };
|
54 |
| - file.$state = function () { |
55 |
| - return data.state(); |
56 |
| - }; |
57 |
| - file.$progress = function () { |
58 |
| - return data.progress(); |
59 |
| - }; |
60 |
| - file.$response = function () { |
61 |
| - return data.response(); |
62 |
| - }; |
63 | 88 | if (file.$state() === 'rejected') {
|
64 | 89 | file._$submit = submit;
|
65 | 90 | } else {
|
|
96 | 121 | if (data.errorThrown === 'abort') {
|
97 | 122 | return;
|
98 | 123 | }
|
99 |
| - if (data.dataType.indexOf('json') === data.dataType.length - 4) { |
| 124 | + if (data.dataType && |
| 125 | + data.dataType.indexOf('json') === data.dataType.length - 4) { |
100 | 126 | try {
|
101 | 127 | data.result = angular.fromJson(data.jqXHR.responseText);
|
102 |
| - } catch (err) {} |
| 128 | + } catch (ignore) {} |
103 | 129 | }
|
104 | 130 | data.scope().$apply(function () {
|
105 | 131 | data.handleResponse.call(that, e, data);
|
|
112 | 138 | return this.scope().queue.length;
|
113 | 139 | },
|
114 | 140 | dataType: 'json',
|
115 |
| - prependFiles: true, |
116 | 141 | autoUpload: false
|
117 | 142 | };
|
118 | 143 | this.$get = [
|
|
124 | 149 | ];
|
125 | 150 | })
|
126 | 151 |
|
| 152 | + // Format byte numbers to readable presentations: |
127 | 153 | .provider('formatFileSizeFilter', function () {
|
128 |
| - var $config = this.defaults = { |
| 154 | + var $config = { |
129 | 155 | // Byte units following the IEC format
|
130 | 156 | // http://en.wikipedia.org/wiki/Kilobyte
|
131 | 157 | units: [
|
|
134 | 160 | {size: 1000, suffix: ' KB'}
|
135 | 161 | ]
|
136 | 162 | };
|
| 163 | + this.defaults = $config; |
137 | 164 | this.$get = function () {
|
138 | 165 | return function (bytes) {
|
139 | 166 | if (!angular.isNumber(bytes)) {
|
140 | 167 | return '';
|
141 | 168 | }
|
142 | 169 | var unit = true,
|
143 |
| - i = -1; |
| 170 | + i = 0, |
| 171 | + prefix, |
| 172 | + suffix; |
144 | 173 | while (unit) {
|
145 |
| - unit = $config.units[i += 1]; |
| 174 | + unit = $config.units[i]; |
| 175 | + prefix = unit.prefix || ''; |
| 176 | + suffix = unit.suffix || ''; |
146 | 177 | if (i === $config.units.length - 1 || bytes >= unit.size) {
|
147 |
| - return (bytes / unit.size).toFixed(2) + unit.suffix; |
| 178 | + return prefix + (bytes / unit.size).toFixed(2) + suffix; |
148 | 179 | }
|
| 180 | + i += 1; |
149 | 181 | }
|
150 | 182 | };
|
151 | 183 | };
|
152 | 184 | })
|
153 | 185 |
|
| 186 | + // The FileUploadController initializes the fileupload widget and |
| 187 | + // provides scope methods to control the File Upload functionality: |
154 | 188 | .controller('FileUploadController', [
|
155 |
| - '$scope', '$element', '$attrs', 'fileUpload', |
156 |
| - function ($scope, $element, $attrs, fileUpload) { |
157 |
| - $scope.disabled = angular.element('<input type="file">') |
158 |
| - .prop('disabled'); |
| 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; |
159 | 215 | $scope.queue = $scope.queue || [];
|
160 | 216 | $scope.clear = function (files) {
|
161 | 217 | var queue = this.queue,
|
|
167 | 223 | length = files.length;
|
168 | 224 | }
|
169 | 225 | while (i) {
|
170 |
| - if (queue[i -= 1] === file) { |
| 226 | + i -= 1; |
| 227 | + if (queue[i] === file) { |
171 | 228 | return queue.splice(i, length);
|
172 | 229 | }
|
173 | 230 | }
|
|
186 | 243 | }
|
187 | 244 | }
|
188 | 245 | };
|
189 |
| - $scope.progress = function () { |
190 |
| - return $element.fileupload('progress'); |
191 |
| - }; |
192 |
| - $scope.active = function () { |
193 |
| - return $element.fileupload('active'); |
194 |
| - }; |
195 |
| - $scope.option = function (option, data) { |
196 |
| - return $element.fileupload('option', option, data); |
197 |
| - }; |
198 |
| - $scope.add = function (data) { |
199 |
| - return $element.fileupload('add', data); |
200 |
| - }; |
201 |
| - $scope.send = function (data) { |
202 |
| - return $element.fileupload('send', data); |
203 |
| - }; |
204 |
| - $scope.process = function (data) { |
205 |
| - return $element.fileupload('process', data); |
206 |
| - }; |
207 |
| - $scope.processing = function (data) { |
208 |
| - return $element.fileupload('processing', data); |
209 |
| - }; |
210 | 246 | $scope.applyOnQueue = function (method) {
|
211 | 247 | var list = this.queue.slice(0),
|
212 | 248 | i,
|
|
224 | 260 | $scope.cancel = function () {
|
225 | 261 | this.applyOnQueue('$cancel');
|
226 | 262 | };
|
| 263 | + // Add upload methods to the scope: |
| 264 | + angular.extend($scope, uploadMethods); |
227 | 265 | // The fileupload widget will initialize with
|
228 | 266 | // the options provided via "data-"-parameters,
|
229 | 267 | // as well as those given via options object:
|
|
260 | 298 | 'fileuploadprocessalways',
|
261 | 299 | 'fileuploadprocessstop'
|
262 | 300 | ].join(' '), function (e, data) {
|
263 |
| - $scope.$emit(e.type, 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 | + } |
264 | 313 | });
|
265 | 314 | // Observe option changes:
|
266 | 315 | $scope.$watch(
|
267 |
| - $attrs.fileupload, |
268 |
| - function (newOptions, oldOptions) { |
| 316 | + $attrs.fileUpload, |
| 317 | + function (newOptions) { |
269 | 318 | if (newOptions) {
|
270 | 319 | $element.fileupload('option', newOptions);
|
271 | 320 | }
|
|
274 | 323 | }
|
275 | 324 | ])
|
276 | 325 |
|
| 326 | + // Provide File Upload progress feedback: |
277 | 327 | .controller('FileUploadProgressController', [
|
278 | 328 | '$scope', '$attrs', '$parse',
|
279 | 329 | function ($scope, $attrs, $parse) {
|
280 |
| - var fn = $parse($attrs.progress), |
| 330 | + var fn = $parse($attrs.fileUploadProgress), |
281 | 331 | update = function () {
|
282 | 332 | var progress = fn($scope);
|
283 | 333 | if (!progress || !progress.total) {
|
|
289 | 339 | };
|
290 | 340 | update();
|
291 | 341 | $scope.$watch(
|
292 |
| - $attrs.progress + '.loaded', |
| 342 | + $attrs.fileUploadProgress + '.loaded', |
293 | 343 | function (newValue, oldValue) {
|
294 | 344 | if (newValue !== oldValue) {
|
295 | 345 | update();
|
|
299 | 349 | }
|
300 | 350 | ])
|
301 | 351 |
|
| 352 | + // Display File Upload previews: |
302 | 353 | .controller('FileUploadPreviewController', [
|
303 | 354 | '$scope', '$element', '$attrs', '$parse',
|
304 | 355 | function ($scope, $element, $attrs, $parse) {
|
305 |
| - var fn = $parse($attrs.preview), |
| 356 | + var fn = $parse($attrs.fileUploadPreview), |
306 | 357 | file = fn($scope);
|
307 | 358 | if (file.preview) {
|
308 | 359 | $element.append(file.preview);
|
309 | 360 | }
|
310 | 361 | }
|
311 | 362 | ])
|
312 | 363 |
|
313 |
| - .directive('fileupload', function () { |
| 364 | + .directive('fileUpload', function () { |
314 | 365 | return {
|
315 | 366 | controller: 'FileUploadController'
|
316 | 367 | };
|
317 | 368 | })
|
318 | 369 |
|
319 |
| - .directive('progress', function () { |
| 370 | + .directive('fileUploadProgress', function () { |
320 | 371 | return {
|
321 | 372 | controller: 'FileUploadProgressController'
|
322 | 373 | };
|
323 | 374 | })
|
324 | 375 |
|
325 |
| - .directive('preview', function () { |
| 376 | + .directive('fileUploadPreview', function () { |
326 | 377 | return {
|
327 | 378 | controller: 'FileUploadPreviewController'
|
328 | 379 | };
|
329 | 380 | })
|
330 | 381 |
|
| 382 | + // Enhance the HTML5 download attribute to |
| 383 | + // allow drag&drop of files to the desktop: |
331 | 384 | .directive('download', function () {
|
332 |
| - return function (scope, elm, attrs) { |
| 385 | + return function (scope, elm) { |
333 | 386 | elm.on('dragstart', function (e) {
|
334 | 387 | try {
|
335 | 388 | e.originalEvent.dataTransfer.setData(
|
|
340 | 393 | elm.prop('href')
|
341 | 394 | ].join(':')
|
342 | 395 | );
|
343 |
| - } catch (err) {} |
| 396 | + } catch (ignore) {} |
344 | 397 | });
|
345 | 398 | };
|
346 | 399 | });
|
347 | 400 |
|
348 |
| -}()); |
| 401 | +})); |
0 commit comments