jquery-fileupload-requirejs-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,782 @@
1
+ define(['jquery', './vendor/tmpl', './vendor/load-image', './jquery.fileupload-fp'], function ($, tmpl, loadImage) {
2
+
3
+ /*
4
+ * jQuery File Upload User Interface Plugin 7.3
5
+ * https://github.com/blueimp/jQuery-File-Upload
6
+ *
7
+ * Copyright 2010, Sebastian Tschan
8
+ * https://blueimp.net
9
+ *
10
+ * Licensed under the MIT license:
11
+ * http://www.opensource.org/licenses/MIT
12
+ */
13
+
14
+ /*jslint nomen: true, unparam: true, regexp: true */
15
+ /*global define, window, URL, webkitURL, FileReader */
16
+
17
+ 'use strict';
18
+
19
+ // The UI version extends the file upload widget
20
+ // and adds complete user interface interaction:
21
+ $.widget('blueimp.fileupload', $.blueimp.fileupload, {
22
+
23
+ options: {
24
+ // By default, files added to the widget are uploaded as soon
25
+ // as the user clicks on the start buttons. To enable automatic
26
+ // uploads, set the following option to true:
27
+ autoUpload: false,
28
+ // The following option limits the number of files that are
29
+ // allowed to be uploaded using this widget:
30
+ maxNumberOfFiles: undefined,
31
+ // The maximum allowed file size:
32
+ maxFileSize: undefined,
33
+ // The minimum allowed file size:
34
+ minFileSize: undefined,
35
+ // The regular expression for allowed file types, matches
36
+ // against either file type or file name:
37
+ acceptFileTypes: /.+$/i,
38
+ // The regular expression to define for which files a preview
39
+ // image is shown, matched against the file type:
40
+ previewSourceFileTypes: /^image\/(gif|jpeg|png)$/,
41
+ // The maximum file size of images that are to be displayed as preview:
42
+ previewSourceMaxFileSize: 5000000, // 5MB
43
+ // The maximum width of the preview images:
44
+ previewMaxWidth: 80,
45
+ // The maximum height of the preview images:
46
+ previewMaxHeight: 80,
47
+ // By default, preview images are displayed as canvas elements
48
+ // if supported by the browser. Set the following option to false
49
+ // to always display preview images as img elements:
50
+ previewAsCanvas: true,
51
+ // The ID of the upload template:
52
+ uploadTemplateId: 'template-upload',
53
+ // The ID of the download template:
54
+ downloadTemplateId: 'template-download',
55
+ // The container for the list of files. If undefined, it is set to
56
+ // an element with class "files" inside of the widget element:
57
+ filesContainer: undefined,
58
+ // By default, files are appended to the files container.
59
+ // Set the following option to true, to prepend files instead:
60
+ prependFiles: false,
61
+ // The expected data type of the upload response, sets the dataType
62
+ // option of the $.ajax upload requests:
63
+ dataType: 'json',
64
+
65
+ // The add callback is invoked as soon as files are added to the fileupload
66
+ // widget (via file input selection, drag & drop or add API call).
67
+ // See the basic file upload widget for more information:
68
+ add: function (e, data) {
69
+ var that = $(this).data('blueimp-fileupload') ||
70
+ $(this).data('fileupload'),
71
+ options = that.options,
72
+ files = data.files;
73
+ $(this).fileupload('process', data).done(function () {
74
+ that._adjustMaxNumberOfFiles(-files.length);
75
+ data.maxNumberOfFilesAdjusted = true;
76
+ data.files.valid = data.isValidated = that._validate(files);
77
+ data.context = that._renderUpload(files).data('data', data);
78
+ options.filesContainer[
79
+ options.prependFiles ? 'prepend' : 'append'
80
+ ](data.context);
81
+ that._renderPreviews(data);
82
+ that._forceReflow(data.context);
83
+ that._transition(data.context).done(
84
+ function () {
85
+ if ((that._trigger('added', e, data) !== false) &&
86
+ (options.autoUpload || data.autoUpload) &&
87
+ data.autoUpload !== false && data.isValidated) {
88
+ data.submit();
89
+ }
90
+ }
91
+ );
92
+ });
93
+ },
94
+ // Callback for the start of each file upload request:
95
+ send: function (e, data) {
96
+ var that = $(this).data('blueimp-fileupload') ||
97
+ $(this).data('fileupload');
98
+ if (!data.isValidated) {
99
+ if (!data.maxNumberOfFilesAdjusted) {
100
+ that._adjustMaxNumberOfFiles(-data.files.length);
101
+ data.maxNumberOfFilesAdjusted = true;
102
+ }
103
+ if (!that._validate(data.files)) {
104
+ return false;
105
+ }
106
+ }
107
+ if (data.context && data.dataType &&
108
+ data.dataType.substr(0, 6) === 'iframe') {
109
+ // Iframe Transport does not support progress events.
110
+ // In lack of an indeterminate progress bar, we set
111
+ // the progress to 100%, showing the full animated bar:
112
+ data.context
113
+ .find('.progress').addClass(
114
+ !$.support.transition && 'progress-animated'
115
+ )
116
+ .attr('aria-valuenow', 100)
117
+ .find('.bar').css(
118
+ 'width',
119
+ '100%'
120
+ );
121
+ }
122
+ return that._trigger('sent', e, data);
123
+ },
124
+ // Callback for successful uploads:
125
+ done: function (e, data) {
126
+ var that = $(this).data('blueimp-fileupload') ||
127
+ $(this).data('fileupload'),
128
+ files = that._getFilesFromResponse(data),
129
+ template,
130
+ deferred;
131
+ if (data.context) {
132
+ data.context.each(function (index) {
133
+ var file = files[index] ||
134
+ {error: 'Empty file upload result'},
135
+ deferred = that._addFinishedDeferreds();
136
+ if (file.error) {
137
+ that._adjustMaxNumberOfFiles(1);
138
+ }
139
+ that._transition($(this)).done(
140
+ function () {
141
+ var node = $(this);
142
+ template = that._renderDownload([file])
143
+ .replaceAll(node);
144
+ that._forceReflow(template);
145
+ that._transition(template).done(
146
+ function () {
147
+ data.context = $(this);
148
+ that._trigger('completed', e, data);
149
+ that._trigger('finished', e, data);
150
+ deferred.resolve();
151
+ }
152
+ );
153
+ }
154
+ );
155
+ });
156
+ } else {
157
+ if (files.length) {
158
+ $.each(files, function (index, file) {
159
+ if (data.maxNumberOfFilesAdjusted && file.error) {
160
+ that._adjustMaxNumberOfFiles(1);
161
+ } else if (!data.maxNumberOfFilesAdjusted &&
162
+ !file.error) {
163
+ that._adjustMaxNumberOfFiles(-1);
164
+ }
165
+ });
166
+ data.maxNumberOfFilesAdjusted = true;
167
+ }
168
+ template = that._renderDownload(files)
169
+ .appendTo(that.options.filesContainer);
170
+ that._forceReflow(template);
171
+ deferred = that._addFinishedDeferreds();
172
+ that._transition(template).done(
173
+ function () {
174
+ data.context = $(this);
175
+ that._trigger('completed', e, data);
176
+ that._trigger('finished', e, data);
177
+ deferred.resolve();
178
+ }
179
+ );
180
+ }
181
+ },
182
+ // Callback for failed (abort or error) uploads:
183
+ fail: function (e, data) {
184
+ var that = $(this).data('blueimp-fileupload') ||
185
+ $(this).data('fileupload'),
186
+ template,
187
+ deferred;
188
+ if (data.maxNumberOfFilesAdjusted) {
189
+ that._adjustMaxNumberOfFiles(data.files.length);
190
+ }
191
+ if (data.context) {
192
+ data.context.each(function (index) {
193
+ if (data.errorThrown !== 'abort') {
194
+ var file = data.files[index];
195
+ file.error = file.error || data.errorThrown ||
196
+ true;
197
+ deferred = that._addFinishedDeferreds();
198
+ that._transition($(this)).done(
199
+ function () {
200
+ var node = $(this);
201
+ template = that._renderDownload([file])
202
+ .replaceAll(node);
203
+ that._forceReflow(template);
204
+ that._transition(template).done(
205
+ function () {
206
+ data.context = $(this);
207
+ that._trigger('failed', e, data);
208
+ that._trigger('finished', e, data);
209
+ deferred.resolve();
210
+ }
211
+ );
212
+ }
213
+ );
214
+ } else {
215
+ deferred = that._addFinishedDeferreds();
216
+ that._transition($(this)).done(
217
+ function () {
218
+ $(this).remove();
219
+ that._trigger('failed', e, data);
220
+ that._trigger('finished', e, data);
221
+ deferred.resolve();
222
+ }
223
+ );
224
+ }
225
+ });
226
+ } else if (data.errorThrown !== 'abort') {
227
+ data.context = that._renderUpload(data.files)
228
+ .appendTo(that.options.filesContainer)
229
+ .data('data', data);
230
+ that._forceReflow(data.context);
231
+ deferred = that._addFinishedDeferreds();
232
+ that._transition(data.context).done(
233
+ function () {
234
+ data.context = $(this);
235
+ that._trigger('failed', e, data);
236
+ that._trigger('finished', e, data);
237
+ deferred.resolve();
238
+ }
239
+ );
240
+ } else {
241
+ that._trigger('failed', e, data);
242
+ that._trigger('finished', e, data);
243
+ that._addFinishedDeferreds().resolve();
244
+ }
245
+ },
246
+ // Callback for upload progress events:
247
+ progress: function (e, data) {
248
+ if (data.context) {
249
+ var progress = parseInt(data.loaded / data.total * 100, 10);
250
+ data.context.find('.progress')
251
+ .attr('aria-valuenow', progress)
252
+ .find('.bar').css(
253
+ 'width',
254
+ progress + '%'
255
+ );
256
+ }
257
+ },
258
+ // Callback for global upload progress events:
259
+ progressall: function (e, data) {
260
+ var $this = $(this),
261
+ progress = parseInt(data.loaded / data.total * 100, 10),
262
+ globalProgressNode = $this.find('.fileupload-progress'),
263
+ extendedProgressNode = globalProgressNode
264
+ .find('.progress-extended');
265
+ if (extendedProgressNode.length) {
266
+ extendedProgressNode.html(
267
+ ($this.data('blueimp-fileupload') || $this.data('fileupload'))
268
+ ._renderExtendedProgress(data)
269
+ );
270
+ }
271
+ globalProgressNode
272
+ .find('.progress')
273
+ .attr('aria-valuenow', progress)
274
+ .find('.bar').css(
275
+ 'width',
276
+ progress + '%'
277
+ );
278
+ },
279
+ // Callback for uploads start, equivalent to the global ajaxStart event:
280
+ start: function (e) {
281
+ var that = $(this).data('blueimp-fileupload') ||
282
+ $(this).data('fileupload');
283
+ that._resetFinishedDeferreds();
284
+ that._transition($(this).find('.fileupload-progress')).done(
285
+ function () {
286
+ that._trigger('started', e);
287
+ }
288
+ );
289
+ },
290
+ // Callback for uploads stop, equivalent to the global ajaxStop event:
291
+ stop: function (e) {
292
+ var that = $(this).data('blueimp-fileupload') ||
293
+ $(this).data('fileupload'),
294
+ deferred = that._addFinishedDeferreds();
295
+ $.when.apply($, that._getFinishedDeferreds())
296
+ .done(function () {
297
+ that._trigger('stopped', e);
298
+ });
299
+ that._transition($(this).find('.fileupload-progress')).done(
300
+ function () {
301
+ $(this).find('.progress')
302
+ .attr('aria-valuenow', '0')
303
+ .find('.bar').css('width', '0%');
304
+ $(this).find('.progress-extended').html(' ');
305
+ deferred.resolve();
306
+ }
307
+ );
308
+ },
309
+ // Callback for file deletion:
310
+ destroy: function (e, data) {
311
+ var that = $(this).data('blueimp-fileupload') ||
312
+ $(this).data('fileupload');
313
+ if (data.url) {
314
+ $.ajax(data);
315
+ that._adjustMaxNumberOfFiles(1);
316
+ }
317
+ that._transition(data.context).done(
318
+ function () {
319
+ $(this).remove();
320
+ that._trigger('destroyed', e, data);
321
+ }
322
+ );
323
+ }
324
+ },
325
+
326
+ _resetFinishedDeferreds: function () {
327
+ this._finishedUploads = [];
328
+ },
329
+
330
+ _addFinishedDeferreds: function (deferred) {
331
+ if (!deferred) {
332
+ deferred = $.Deferred();
333
+ }
334
+ this._finishedUploads.push(deferred);
335
+ return deferred;
336
+ },
337
+
338
+ _getFinishedDeferreds: function () {
339
+ return this._finishedUploads;
340
+ },
341
+
342
+ _getFilesFromResponse: function (data) {
343
+ if (data.result && $.isArray(data.result.files)) {
344
+ return data.result.files;
345
+ }
346
+ return [];
347
+ },
348
+
349
+ // Link handler, that allows to download files
350
+ // by drag & drop of the links to the desktop:
351
+ _enableDragToDesktop: function () {
352
+ var link = $(this),
353
+ url = link.prop('href'),
354
+ name = link.prop('download'),
355
+ type = 'application/octet-stream';
356
+ link.bind('dragstart', function (e) {
357
+ try {
358
+ e.originalEvent.dataTransfer.setData(
359
+ 'DownloadURL',
360
+ [type, name, url].join(':')
361
+ );
362
+ } catch (err) {}
363
+ });
364
+ },
365
+
366
+ _adjustMaxNumberOfFiles: function (operand) {
367
+ if (typeof this.options.maxNumberOfFiles === 'number') {
368
+ this.options.maxNumberOfFiles += operand;
369
+ if (this.options.maxNumberOfFiles < 1) {
370
+ this._disableFileInputButton();
371
+ } else {
372
+ this._enableFileInputButton();
373
+ }
374
+ }
375
+ },
376
+
377
+ _formatFileSize: function (bytes) {
378
+ if (typeof bytes !== 'number') {
379
+ return '';
380
+ }
381
+ if (bytes >= 1000000000) {
382
+ return (bytes / 1000000000).toFixed(2) + ' GB';
383
+ }
384
+ if (bytes >= 1000000) {
385
+ return (bytes / 1000000).toFixed(2) + ' MB';
386
+ }
387
+ return (bytes / 1000).toFixed(2) + ' KB';
388
+ },
389
+
390
+ _formatBitrate: function (bits) {
391
+ if (typeof bits !== 'number') {
392
+ return '';
393
+ }
394
+ if (bits >= 1000000000) {
395
+ return (bits / 1000000000).toFixed(2) + ' Gbit/s';
396
+ }
397
+ if (bits >= 1000000) {
398
+ return (bits / 1000000).toFixed(2) + ' Mbit/s';
399
+ }
400
+ if (bits >= 1000) {
401
+ return (bits / 1000).toFixed(2) + ' kbit/s';
402
+ }
403
+ return bits.toFixed(2) + ' bit/s';
404
+ },
405
+
406
+ _formatTime: function (seconds) {
407
+ var date = new Date(seconds * 1000),
408
+ days = parseInt(seconds / 86400, 10);
409
+ days = days ? days + 'd ' : '';
410
+ return days +
411
+ ('0' + date.getUTCHours()).slice(-2) + ':' +
412
+ ('0' + date.getUTCMinutes()).slice(-2) + ':' +
413
+ ('0' + date.getUTCSeconds()).slice(-2);
414
+ },
415
+
416
+ _formatPercentage: function (floatValue) {
417
+ return (floatValue * 100).toFixed(2) + ' %';
418
+ },
419
+
420
+ _renderExtendedProgress: function (data) {
421
+ return this._formatBitrate(data.bitrate) + ' | ' +
422
+ this._formatTime(
423
+ (data.total - data.loaded) * 8 / data.bitrate
424
+ ) + ' | ' +
425
+ this._formatPercentage(
426
+ data.loaded / data.total
427
+ ) + ' | ' +
428
+ this._formatFileSize(data.loaded) + ' / ' +
429
+ this._formatFileSize(data.total);
430
+ },
431
+
432
+ _hasError: function (file) {
433
+ if (file.error) {
434
+ return file.error;
435
+ }
436
+ // The number of added files is subtracted from
437
+ // maxNumberOfFiles before validation, so we check if
438
+ // maxNumberOfFiles is below 0 (instead of below 1):
439
+ if (this.options.maxNumberOfFiles < 0) {
440
+ return 'Maximum number of files exceeded';
441
+ }
442
+ // Files are accepted if either the file type or the file name
443
+ // matches against the acceptFileTypes regular expression, as
444
+ // only browsers with support for the File API report the type:
445
+ if (!(this.options.acceptFileTypes.test(file.type) ||
446
+ this.options.acceptFileTypes.test(file.name))) {
447
+ return 'Filetype not allowed';
448
+ }
449
+ if (this.options.maxFileSize &&
450
+ file.size > this.options.maxFileSize) {
451
+ return 'File is too big';
452
+ }
453
+ if (typeof file.size === 'number' &&
454
+ file.size < this.options.minFileSize) {
455
+ return 'File is too small';
456
+ }
457
+ return null;
458
+ },
459
+
460
+ _validate: function (files) {
461
+ var that = this,
462
+ valid = !!files.length;
463
+ $.each(files, function (index, file) {
464
+ file.error = that._hasError(file);
465
+ if (file.error) {
466
+ valid = false;
467
+ }
468
+ });
469
+ return valid;
470
+ },
471
+
472
+ _renderTemplate: function (func, files) {
473
+ if (!func) {
474
+ return $();
475
+ }
476
+ var result = func({
477
+ files: files,
478
+ formatFileSize: this._formatFileSize,
479
+ options: this.options
480
+ });
481
+ if (result instanceof $) {
482
+ return result;
483
+ }
484
+ return $(this.options.templatesContainer).html(result).children();
485
+ },
486
+
487
+ _renderPreview: function (file, node) {
488
+ var that = this,
489
+ options = this.options,
490
+ dfd = $.Deferred();
491
+ return ((loadImage && loadImage(
492
+ file,
493
+ function (img) {
494
+ node.append(img);
495
+ that._forceReflow(node);
496
+ that._transition(node).done(function () {
497
+ dfd.resolveWith(node);
498
+ });
499
+ if (!$.contains(that.document[0].body, node[0])) {
500
+ // If the element is not part of the DOM,
501
+ // transition events are not triggered,
502
+ // so we have to resolve manually:
503
+ dfd.resolveWith(node);
504
+ }
505
+ },
506
+ {
507
+ maxWidth: options.previewMaxWidth,
508
+ maxHeight: options.previewMaxHeight,
509
+ canvas: options.previewAsCanvas
510
+ }
511
+ )) || dfd.resolveWith(node)) && dfd;
512
+ },
513
+
514
+ _renderPreviews: function (data) {
515
+ var that = this,
516
+ options = this.options;
517
+ data.context.find('.preview span').each(function (index, element) {
518
+ var file = data.files[index];
519
+ if (options.previewSourceFileTypes.test(file.type) &&
520
+ ($.type(options.previewSourceMaxFileSize) !== 'number' ||
521
+ file.size < options.previewSourceMaxFileSize)) {
522
+ that._processingQueue = that._processingQueue.pipe(function () {
523
+ var dfd = $.Deferred(),
524
+ ev = $.Event('previewdone', {
525
+ target: element
526
+ });
527
+ that._renderPreview(file, $(element)).done(
528
+ function () {
529
+ that._trigger(ev.type, ev, data);
530
+ dfd.resolveWith(that);
531
+ }
532
+ );
533
+ return dfd.promise();
534
+ });
535
+ }
536
+ });
537
+ return this._processingQueue;
538
+ },
539
+
540
+ _renderUpload: function (files) {
541
+ return this._renderTemplate(
542
+ this.options.uploadTemplate,
543
+ files
544
+ );
545
+ },
546
+
547
+ _renderDownload: function (files) {
548
+ return this._renderTemplate(
549
+ this.options.downloadTemplate,
550
+ files
551
+ ).find('a[download]').each(this._enableDragToDesktop).end();
552
+ },
553
+
554
+ _startHandler: function (e) {
555
+ e.preventDefault();
556
+ var button = $(e.currentTarget),
557
+ template = button.closest('.template-upload'),
558
+ data = template.data('data');
559
+ if (data && data.submit && !data.jqXHR && data.submit()) {
560
+ button.prop('disabled', true);
561
+ }
562
+ },
563
+
564
+ _cancelHandler: function (e) {
565
+ e.preventDefault();
566
+ var template = $(e.currentTarget).closest('.template-upload'),
567
+ data = template.data('data') || {};
568
+ if (!data.jqXHR) {
569
+ data.errorThrown = 'abort';
570
+ this._trigger('fail', e, data);
571
+ } else {
572
+ data.jqXHR.abort();
573
+ }
574
+ },
575
+
576
+ _deleteHandler: function (e) {
577
+ e.preventDefault();
578
+ var button = $(e.currentTarget);
579
+ this._trigger('destroy', e, $.extend({
580
+ context: button.closest('.template-download'),
581
+ type: 'DELETE',
582
+ dataType: this.options.dataType
583
+ }, button.data()));
584
+ },
585
+
586
+ _forceReflow: function (node) {
587
+ return $.support.transition && node.length &&
588
+ node[0].offsetWidth;
589
+ },
590
+
591
+ _transition: function (node) {
592
+ var dfd = $.Deferred();
593
+ if ($.support.transition && node.hasClass('fade')) {
594
+ node.bind(
595
+ $.support.transition.end,
596
+ function (e) {
597
+ // Make sure we don't respond to other transitions events
598
+ // in the container element, e.g. from button elements:
599
+ if (e.target === node[0]) {
600
+ node.unbind($.support.transition.end);
601
+ dfd.resolveWith(node);
602
+ }
603
+ }
604
+ ).toggleClass('in');
605
+ } else {
606
+ node.toggleClass('in');
607
+ dfd.resolveWith(node);
608
+ }
609
+ return dfd;
610
+ },
611
+
612
+ _initButtonBarEventHandlers: function () {
613
+ var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'),
614
+ filesList = this.options.filesContainer;
615
+ this._on(fileUploadButtonBar.find('.start'), {
616
+ click: function (e) {
617
+ e.preventDefault();
618
+ filesList.find('.start button').click();
619
+ }
620
+ });
621
+ this._on(fileUploadButtonBar.find('.cancel'), {
622
+ click: function (e) {
623
+ e.preventDefault();
624
+ filesList.find('.cancel button').click();
625
+ }
626
+ });
627
+ this._on(fileUploadButtonBar.find('.delete'), {
628
+ click: function (e) {
629
+ e.preventDefault();
630
+ filesList.find('.delete input:checked')
631
+ .siblings('button').click();
632
+ fileUploadButtonBar.find('.toggle')
633
+ .prop('checked', false);
634
+ }
635
+ });
636
+ this._on(fileUploadButtonBar.find('.toggle'), {
637
+ change: function (e) {
638
+ filesList.find('.delete input').prop(
639
+ 'checked',
640
+ $(e.currentTarget).is(':checked')
641
+ );
642
+ }
643
+ });
644
+ },
645
+
646
+ _destroyButtonBarEventHandlers: function () {
647
+ this._off(
648
+ this.element.find('.fileupload-buttonbar button'),
649
+ 'click'
650
+ );
651
+ this._off(
652
+ this.element.find('.fileupload-buttonbar .toggle'),
653
+ 'change.'
654
+ );
655
+ },
656
+
657
+ _initEventHandlers: function () {
658
+ this._super();
659
+ this._on(this.options.filesContainer, {
660
+ 'click .start button': this._startHandler,
661
+ 'click .cancel button': this._cancelHandler,
662
+ 'click .delete button': this._deleteHandler
663
+ });
664
+ this._initButtonBarEventHandlers();
665
+ },
666
+
667
+ _destroyEventHandlers: function () {
668
+ this._destroyButtonBarEventHandlers();
669
+ this._off(this.options.filesContainer, 'click');
670
+ this._super();
671
+ },
672
+
673
+ _enableFileInputButton: function () {
674
+ this.element.find('.fileinput-button input')
675
+ .prop('disabled', false)
676
+ .parent().removeClass('disabled');
677
+ },
678
+
679
+ _disableFileInputButton: function () {
680
+ this.element.find('.fileinput-button input')
681
+ .prop('disabled', true)
682
+ .parent().addClass('disabled');
683
+ },
684
+
685
+ _initTemplates: function () {
686
+ var options = this.options;
687
+ options.templatesContainer = this.document[0].createElement(
688
+ options.filesContainer.prop('nodeName')
689
+ );
690
+ if (tmpl) {
691
+ if (options.uploadTemplateId) {
692
+ options.uploadTemplate = tmpl(options.uploadTemplateId);
693
+ }
694
+ if (options.downloadTemplateId) {
695
+ options.downloadTemplate = tmpl(options.downloadTemplateId);
696
+ }
697
+ }
698
+ },
699
+
700
+ _initFilesContainer: function () {
701
+ var options = this.options;
702
+ if (options.filesContainer === undefined) {
703
+ options.filesContainer = this.element.find('.files');
704
+ } else if (!(options.filesContainer instanceof $)) {
705
+ options.filesContainer = $(options.filesContainer);
706
+ }
707
+ },
708
+
709
+ _stringToRegExp: function (str) {
710
+ var parts = str.split('/'),
711
+ modifiers = parts.pop();
712
+ parts.shift();
713
+ return new RegExp(parts.join('/'), modifiers);
714
+ },
715
+
716
+ _initRegExpOptions: function () {
717
+ var options = this.options;
718
+ if ($.type(options.acceptFileTypes) === 'string') {
719
+ options.acceptFileTypes = this._stringToRegExp(
720
+ options.acceptFileTypes
721
+ );
722
+ }
723
+ if ($.type(options.previewSourceFileTypes) === 'string') {
724
+ options.previewSourceFileTypes = this._stringToRegExp(
725
+ options.previewSourceFileTypes
726
+ );
727
+ }
728
+ },
729
+
730
+ _initSpecialOptions: function () {
731
+ this._super();
732
+ this._initFilesContainer();
733
+ this._initTemplates();
734
+ this._initRegExpOptions();
735
+ },
736
+
737
+ _setOption: function (key, value) {
738
+ this._super(key, value);
739
+ if (key === 'maxNumberOfFiles') {
740
+ this._adjustMaxNumberOfFiles(0);
741
+ }
742
+ },
743
+
744
+ _create: function () {
745
+ this._super();
746
+ this._refreshOptionsList.push(
747
+ 'filesContainer',
748
+ 'uploadTemplateId',
749
+ 'downloadTemplateId'
750
+ );
751
+ if (!this._processingQueue) {
752
+ this._processingQueue = $.Deferred().resolveWith(this).promise();
753
+ this.process = function () {
754
+ return this._processingQueue;
755
+ };
756
+ }
757
+ this._resetFinishedDeferreds();
758
+ },
759
+
760
+ enable: function () {
761
+ var wasDisabled = false;
762
+ if (this.options.disabled) {
763
+ wasDisabled = true;
764
+ }
765
+ this._super();
766
+ if (wasDisabled) {
767
+ this.element.find('input, button').prop('disabled', false);
768
+ this._enableFileInputButton();
769
+ }
770
+ },
771
+
772
+ disable: function () {
773
+ if (!this.options.disabled) {
774
+ this.element.find('input, button').prop('disabled', true);
775
+ this._disableFileInputButton();
776
+ }
777
+ this._super();
778
+ }
779
+
780
+ });
781
+
782
+ });