Subversion-Projekte lars-tiefland.ci

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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