card-mod-script 0.13.4 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/assets/script/decko/components.js.coffee +3 -0
  3. data/assets/script/decko/decko.js.coffee +0 -15
  4. data/assets/script/decko/editor.js.coffee +3 -1
  5. data/assets/script/decko/filter.js.coffee +13 -6
  6. data/assets/script/decko/mod.js.coffee +2 -8
  7. data/assets/script/{script_pointer_config.js.coffee → decko/pointer_config.js.coffee} +1 -2
  8. data/assets/script/{script_pointer_list_editor.js.coffee → decko/pointer_list_editor.js.coffee} +0 -0
  9. data/assets/script/decko/slot.js.coffee +2 -2
  10. data/assets/script/decko/slot_ready.js.coffee +1 -0
  11. data/assets/script/decko/slotter.js.coffee +23 -31
  12. data/assets/script/decko/type_editor.js.coffee +21 -0
  13. data/assets/script/decko/upload.js.coffee +12 -5
  14. data/assets/script/manifest.yml +15 -2
  15. data/set/abstract/00_script.rb +30 -31
  16. data/set/abstract/01_asset_script.rb +0 -16
  17. data/set/abstract/{script_asset_list.rb → script_group.rb} +12 -13
  18. data/set/all/head_javascript.rb +4 -5
  19. data/set/right/script.rb +1 -14
  20. data/set/type/local_script_folder_group.rb +2 -2
  21. data/set/type/local_script_manifest_group.rb +1 -1
  22. data/set/type_plus_right/mod/script.rb +56 -0
  23. data/set/type_plus_right/set/script.rb +7 -0
  24. data/vendor/jquery_file_upload/LICENSE.txt +11 -12
  25. data/vendor/jquery_file_upload/README.md +189 -72
  26. data/vendor/jquery_file_upload/SECURITY.md +227 -0
  27. data/vendor/jquery_file_upload/VULNERABILITIES.md +118 -0
  28. data/vendor/jquery_file_upload/cors/postmessage.html +68 -58
  29. data/vendor/jquery_file_upload/cors/result.html +12 -10
  30. data/vendor/jquery_file_upload/css/jquery.fileupload-ui.css +24 -13
  31. data/vendor/jquery_file_upload/css/jquery.fileupload.css +3 -4
  32. data/vendor/jquery_file_upload/docker-compose.yml +55 -0
  33. data/vendor/jquery_file_upload/index.html +332 -230
  34. data/vendor/jquery_file_upload/js/cors/jquery.postmessage-transport.js +109 -109
  35. data/vendor/jquery_file_upload/js/cors/jquery.xdr-transport.js +81 -73
  36. data/vendor/jquery_file_upload/js/demo.js +75 -0
  37. data/vendor/jquery_file_upload/js/jquery.fileupload-audio.js +82 -94
  38. data/vendor/jquery_file_upload/js/jquery.fileupload-image.js +321 -300
  39. data/vendor/jquery_file_upload/js/jquery.fileupload-process.js +138 -146
  40. data/vendor/jquery_file_upload/js/jquery.fileupload-ui.js +737 -692
  41. data/vendor/jquery_file_upload/js/jquery.fileupload-validate.js +91 -97
  42. data/vendor/jquery_file_upload/js/jquery.fileupload-video.js +82 -94
  43. data/vendor/jquery_file_upload/js/jquery.fileupload.js +1569 -1451
  44. data/vendor/jquery_file_upload/js/jquery.iframe-transport.js +208 -205
  45. data/vendor/jquery_file_upload/js/vendor/jquery.ui.widget.js +397 -340
  46. data/vendor/jquery_file_upload/package-lock.json +6853 -0
  47. data/vendor/jquery_file_upload/package.json +71 -10
  48. data/vendor/jquery_file_upload/server/gae-python/app.yaml +11 -10
  49. data/vendor/jquery_file_upload/server/php/Dockerfile +23 -17
  50. data/vendor/jquery_file_upload/server/php/UploadHandler.php +206 -137
  51. data/vendor/jquery_file_upload/server/php/php.ini +5 -0
  52. data/vendor/jquery_file_upload/test/index.html +36 -159
  53. data/vendor/jquery_file_upload/test/unit.js +989 -0
  54. data/vendor/jquery_file_upload/test/vendor/chai.js +10854 -0
  55. data/vendor/jquery_file_upload/test/vendor/mocha.css +325 -0
  56. data/vendor/jquery_file_upload/test/vendor/mocha.js +18178 -0
  57. data/vendor/jquery_file_upload/wdio/LICENSE.txt +20 -0
  58. data/vendor/jquery_file_upload/wdio/assets/black+white-3x2.jpg +0 -0
  59. data/vendor/jquery_file_upload/wdio/assets/black+white-60x40.gif +0 -0
  60. data/vendor/jquery_file_upload/wdio/conf/chrome.js +40 -0
  61. data/vendor/jquery_file_upload/wdio/conf/firefox.js +25 -0
  62. data/vendor/jquery_file_upload/wdio/hooks/index.js +36 -0
  63. data/vendor/jquery_file_upload/wdio/test/pages/file-upload.js +79 -0
  64. data/vendor/jquery_file_upload/wdio/test/specs/01-file-upload.js +25 -0
  65. data/vendor/jquery_file_upload/wdio/wdio.conf.js +4 -0
  66. metadata +34 -52
  67. data/file/mod_script_script_decko_machine_output/file.js +0 -2685
  68. data/file/mod_script_script_jquery_machine_output/file.js +0 -12926
  69. data/lib/javascript/script_html5shiv_printshiv.js +0 -1
  70. data/set/self/script_html5shiv_printshiv.rb +0 -11
  71. data/set/self/script_mods.rb +0 -1
  72. data/set/type/mod_script_assets.rb +0 -21
  73. data/vendor/jquery_file_upload/CONTRIBUTING.md +0 -15
  74. data/vendor/jquery_file_upload/angularjs.html +0 -211
  75. data/vendor/jquery_file_upload/basic-plus.html +0 -226
  76. data/vendor/jquery_file_upload/basic.html +0 -136
  77. data/vendor/jquery_file_upload/bower-version-update.js +0 -16
  78. data/vendor/jquery_file_upload/bower.json +0 -64
  79. data/vendor/jquery_file_upload/css/jquery-ui-demo-ie8.css +0 -21
  80. data/vendor/jquery_file_upload/css/jquery-ui-demo.css +0 -67
  81. data/vendor/jquery_file_upload/css/style.css +0 -15
  82. data/vendor/jquery_file_upload/jquery-ui.html +0 -252
  83. data/vendor/jquery_file_upload/js/app.js +0 -101
  84. data/vendor/jquery_file_upload/js/jquery.fileupload-angular.js +0 -437
  85. data/vendor/jquery_file_upload/js/jquery.fileupload-jquery-ui.js +0 -161
  86. data/vendor/jquery_file_upload/js/main.js +0 -75
  87. data/vendor/jquery_file_upload/server/gae-go/app/main.go +0 -361
  88. data/vendor/jquery_file_upload/server/gae-go/app.yaml +0 -12
  89. data/vendor/jquery_file_upload/server/gae-go/static/favicon.ico +0 -0
  90. data/vendor/jquery_file_upload/server/gae-go/static/robots.txt +0 -2
  91. data/vendor/jquery_file_upload/server/php/docker-compose.yml +0 -9
  92. data/vendor/jquery_file_upload/test/test.js +0 -1292
@@ -9,706 +9,751 @@
9
9
  * https://opensource.org/licenses/MIT
10
10
  */
11
11
 
12
- /* jshint nomen:false */
13
- /* global define, require, window */
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
- 'blueimp-tmpl',
22
- './jquery.fileupload-image',
23
- './jquery.fileupload-audio',
24
- './jquery.fileupload-video',
25
- './jquery.fileupload-validate'
26
- ], factory);
27
- } else if (typeof exports === 'object') {
28
- // Node/CommonJS:
29
- factory(
30
- require('jquery'),
31
- require('blueimp-tmpl'),
32
- require('./jquery.fileupload-image'),
33
- require('./jquery.fileupload-audio'),
34
- require('./jquery.fileupload-video'),
35
- require('./jquery.fileupload-validate')
36
- );
37
- } else {
38
- // Browser globals:
39
- factory(
40
- window.jQuery,
41
- window.tmpl
42
- );
43
- }
44
- }(function ($, tmpl) {
45
- 'use strict';
46
-
47
- $.blueimp.fileupload.prototype._specialOptions.push(
48
- 'filesContainer',
49
- 'uploadTemplateId',
50
- 'downloadTemplateId'
12
+ /* global define, require */
13
+
14
+ (function (factory) {
15
+ 'use strict';
16
+ if (typeof define === 'function' && define.amd) {
17
+ // Register as an anonymous AMD module:
18
+ define([
19
+ 'jquery',
20
+ 'blueimp-tmpl',
21
+ './jquery.fileupload-image',
22
+ './jquery.fileupload-audio',
23
+ './jquery.fileupload-video',
24
+ './jquery.fileupload-validate'
25
+ ], factory);
26
+ } else if (typeof exports === 'object') {
27
+ // Node/CommonJS:
28
+ factory(
29
+ require('jquery'),
30
+ require('blueimp-tmpl'),
31
+ require('./jquery.fileupload-image'),
32
+ require('./jquery.fileupload-audio'),
33
+ require('./jquery.fileupload-video'),
34
+ require('./jquery.fileupload-validate')
51
35
  );
52
-
53
- // The UI version extends the file upload widget
54
- // and adds complete user interface interaction:
55
- $.widget('blueimp.fileupload', $.blueimp.fileupload, {
56
-
57
- options: {
58
- // By default, files added to the widget are uploaded as soon
59
- // as the user clicks on the start buttons. To enable automatic
60
- // uploads, set the following option to true:
61
- autoUpload: false,
62
- // The ID of the upload template:
63
- uploadTemplateId: 'template-upload',
64
- // The ID of the download template:
65
- downloadTemplateId: 'template-download',
66
- // The container for the list of files. If undefined, it is set to
67
- // an element with class "files" inside of the widget element:
68
- filesContainer: undefined,
69
- // By default, files are appended to the files container.
70
- // Set the following option to true, to prepend files instead:
71
- prependFiles: false,
72
- // The expected data type of the upload response, sets the dataType
73
- // option of the $.ajax upload requests:
74
- dataType: 'json',
75
-
76
- // Error and info messages:
77
- messages: {
78
- unknownError: 'Unknown error'
79
- },
80
-
81
- // Function returning the current number of files,
82
- // used by the maxNumberOfFiles validation:
83
- getNumberOfFiles: function () {
84
- return this.filesContainer.children()
85
- .not('.processing').length;
86
- },
87
-
88
- // Callback to retrieve the list of files from the server response:
89
- getFilesFromResponse: function (data) {
90
- if (data.result && $.isArray(data.result.files)) {
91
- return data.result.files;
92
- }
93
- return [];
94
- },
95
-
96
- // The add callback is invoked as soon as files are added to the fileupload
97
- // widget (via file input selection, drag & drop or add API call).
98
- // See the basic file upload widget for more information:
99
- add: function (e, data) {
100
- if (e.isDefaultPrevented()) {
101
- return false;
102
- }
103
- var $this = $(this),
104
- that = $this.data('blueimp-fileupload') ||
105
- $this.data('fileupload'),
106
- options = that.options;
107
- data.context = that._renderUpload(data.files)
108
- .data('data', data)
109
- .addClass('processing');
110
- options.filesContainer[
111
- options.prependFiles ? 'prepend' : 'append'
112
- ](data.context);
113
- that._forceReflow(data.context);
114
- that._transition(data.context);
115
- data.process(function () {
116
- return $this.fileupload('process', data);
117
- }).always(function () {
118
- data.context.each(function (index) {
119
- $(this).find('.size').text(
120
- that._formatFileSize(data.files[index].size)
121
- );
122
- }).removeClass('processing');
123
- that._renderPreviews(data);
124
- }).done(function () {
125
- data.context.find('.start').prop('disabled', false);
126
- if ((that._trigger('added', e, data) !== false) &&
127
- (options.autoUpload || data.autoUpload) &&
128
- data.autoUpload !== false) {
129
- data.submit();
130
- }
131
- }).fail(function () {
132
- if (data.files.error) {
133
- data.context.each(function (index) {
134
- var error = data.files[index].error;
135
- if (error) {
136
- $(this).find('.error').text(error);
137
- }
138
- });
139
- }
140
- });
141
- },
142
- // Callback for the start of each file upload request:
143
- send: function (e, data) {
144
- if (e.isDefaultPrevented()) {
145
- return false;
146
- }
147
- var that = $(this).data('blueimp-fileupload') ||
148
- $(this).data('fileupload');
149
- if (data.context && data.dataType &&
150
- data.dataType.substr(0, 6) === 'iframe') {
151
- // Iframe Transport does not support progress events.
152
- // In lack of an indeterminate progress bar, we set
153
- // the progress to 100%, showing the full animated bar:
154
- data.context
155
- .find('.progress').addClass(
156
- !$.support.transition && 'progress-animated'
157
- )
158
- .attr('aria-valuenow', 100)
159
- .children().first().css(
160
- 'width',
161
- '100%'
162
- );
163
- }
164
- return that._trigger('sent', e, data);
165
- },
166
- // Callback for successful uploads:
167
- done: function (e, data) {
168
- if (e.isDefaultPrevented()) {
169
- return false;
170
- }
171
- var that = $(this).data('blueimp-fileupload') ||
172
- $(this).data('fileupload'),
173
- getFilesFromResponse = data.getFilesFromResponse ||
174
- that.options.getFilesFromResponse,
175
- files = getFilesFromResponse(data),
176
- template,
177
- deferred;
178
- if (data.context) {
179
- data.context.each(function (index) {
180
- var file = files[index] ||
181
- {error: 'Empty file upload result'};
182
- deferred = that._addFinishedDeferreds();
183
- that._transition($(this)).done(
184
- function () {
185
- var node = $(this);
186
- template = that._renderDownload([file])
187
- .replaceAll(node);
188
- that._forceReflow(template);
189
- that._transition(template).done(
190
- function () {
191
- data.context = $(this);
192
- that._trigger('completed', e, data);
193
- that._trigger('finished', e, data);
194
- deferred.resolve();
195
- }
196
- );
197
- }
198
- );
199
- });
200
- } else {
201
- template = that._renderDownload(files)[
202
- that.options.prependFiles ? 'prependTo' : 'appendTo'
203
- ](that.options.filesContainer);
204
- that._forceReflow(template);
205
- deferred = that._addFinishedDeferreds();
206
- that._transition(template).done(
207
- function () {
208
- data.context = $(this);
209
- that._trigger('completed', e, data);
210
- that._trigger('finished', e, data);
211
- deferred.resolve();
212
- }
213
- );
214
- }
215
- },
216
- // Callback for failed (abort or error) uploads:
217
- fail: function (e, data) {
218
- if (e.isDefaultPrevented()) {
219
- return false;
220
- }
221
- var that = $(this).data('blueimp-fileupload') ||
222
- $(this).data('fileupload'),
223
- template,
224
- deferred;
225
- if (data.context) {
226
- data.context.each(function (index) {
227
- if (data.errorThrown !== 'abort') {
228
- var file = data.files[index];
229
- file.error = file.error || data.errorThrown ||
230
- data.i18n('unknownError');
231
- deferred = that._addFinishedDeferreds();
232
- that._transition($(this)).done(
233
- function () {
234
- var node = $(this);
235
- template = that._renderDownload([file])
236
- .replaceAll(node);
237
- that._forceReflow(template);
238
- that._transition(template).done(
239
- function () {
240
- data.context = $(this);
241
- that._trigger('failed', e, data);
242
- that._trigger('finished', e, data);
243
- deferred.resolve();
244
- }
245
- );
246
- }
247
- );
248
- } else {
249
- deferred = that._addFinishedDeferreds();
250
- that._transition($(this)).done(
251
- function () {
252
- $(this).remove();
253
- that._trigger('failed', e, data);
254
- that._trigger('finished', e, data);
255
- deferred.resolve();
256
- }
257
- );
258
- }
259
- });
260
- } else if (data.errorThrown !== 'abort') {
261
- data.context = that._renderUpload(data.files)[
262
- that.options.prependFiles ? 'prependTo' : 'appendTo'
263
- ](that.options.filesContainer)
264
- .data('data', data);
265
- that._forceReflow(data.context);
266
- deferred = that._addFinishedDeferreds();
267
- that._transition(data.context).done(
268
- function () {
269
- data.context = $(this);
270
- that._trigger('failed', e, data);
271
- that._trigger('finished', e, data);
272
- deferred.resolve();
273
- }
274
- );
275
- } else {
276
- that._trigger('failed', e, data);
277
- that._trigger('finished', e, data);
278
- that._addFinishedDeferreds().resolve();
279
- }
280
- },
281
- // Callback for upload progress events:
282
- progress: function (e, data) {
283
- if (e.isDefaultPrevented()) {
284
- return false;
285
- }
286
- var progress = Math.floor(data.loaded / data.total * 100);
287
- if (data.context) {
288
- data.context.each(function () {
289
- $(this).find('.progress')
290
- .attr('aria-valuenow', progress)
291
- .children().first().css(
292
- 'width',
293
- progress + '%'
294
- );
295
- });
296
- }
297
- },
298
- // Callback for global upload progress events:
299
- progressall: function (e, data) {
300
- if (e.isDefaultPrevented()) {
301
- return false;
302
- }
303
- var $this = $(this),
304
- progress = Math.floor(data.loaded / data.total * 100),
305
- globalProgressNode = $this.find('.fileupload-progress'),
306
- extendedProgressNode = globalProgressNode
307
- .find('.progress-extended');
308
- if (extendedProgressNode.length) {
309
- extendedProgressNode.html(
310
- ($this.data('blueimp-fileupload') || $this.data('fileupload'))
311
- ._renderExtendedProgress(data)
312
- );
313
- }
314
- globalProgressNode
315
- .find('.progress')
316
- .attr('aria-valuenow', progress)
317
- .children().first().css(
318
- 'width',
319
- progress + '%'
320
- );
321
- },
322
- // Callback for uploads start, equivalent to the global ajaxStart event:
323
- start: function (e) {
324
- if (e.isDefaultPrevented()) {
325
- return false;
326
- }
327
- var that = $(this).data('blueimp-fileupload') ||
328
- $(this).data('fileupload');
329
- that._resetFinishedDeferreds();
330
- that._transition($(this).find('.fileupload-progress')).done(
331
- function () {
332
- that._trigger('started', e);
333
- }
334
- );
335
- },
336
- // Callback for uploads stop, equivalent to the global ajaxStop event:
337
- stop: function (e) {
338
- if (e.isDefaultPrevented()) {
339
- return false;
340
- }
341
- var that = $(this).data('blueimp-fileupload') ||
342
- $(this).data('fileupload'),
343
- deferred = that._addFinishedDeferreds();
344
- $.when.apply($, that._getFinishedDeferreds())
345
- .done(function () {
346
- that._trigger('stopped', e);
347
- });
348
- that._transition($(this).find('.fileupload-progress')).done(
349
- function () {
350
- $(this).find('.progress')
351
- .attr('aria-valuenow', '0')
352
- .children().first().css('width', '0%');
353
- $(this).find('.progress-extended').html(' ');
354
- deferred.resolve();
355
- }
356
- );
357
- },
358
- processstart: function (e) {
359
- if (e.isDefaultPrevented()) {
360
- return false;
361
- }
362
- $(this).addClass('fileupload-processing');
363
- },
364
- processstop: function (e) {
365
- if (e.isDefaultPrevented()) {
366
- return false;
367
- }
368
- $(this).removeClass('fileupload-processing');
369
- },
370
- // Callback for file deletion:
371
- destroy: function (e, data) {
372
- if (e.isDefaultPrevented()) {
373
- return false;
374
- }
375
- var that = $(this).data('blueimp-fileupload') ||
376
- $(this).data('fileupload'),
377
- removeNode = function () {
378
- that._transition(data.context).done(
379
- function () {
380
- $(this).remove();
381
- that._trigger('destroyed', e, data);
382
- }
383
- );
384
- };
385
- if (data.url) {
386
- data.dataType = data.dataType || that.options.dataType;
387
- $.ajax(data).done(removeNode).fail(function () {
388
- that._trigger('destroyfailed', e, data);
389
- });
390
- } else {
391
- removeNode();
392
- }
393
- }
394
- },
395
-
396
- _resetFinishedDeferreds: function () {
397
- this._finishedUploads = [];
398
- },
399
-
400
- _addFinishedDeferreds: function (deferred) {
401
- if (!deferred) {
402
- deferred = $.Deferred();
403
- }
404
- this._finishedUploads.push(deferred);
405
- return deferred;
406
- },
407
-
408
- _getFinishedDeferreds: function () {
409
- return this._finishedUploads;
410
- },
411
-
412
- // Link handler, that allows to download files
413
- // by drag & drop of the links to the desktop:
414
- _enableDragToDesktop: function () {
415
- var link = $(this),
416
- url = link.prop('href'),
417
- name = link.prop('download'),
418
- type = 'application/octet-stream';
419
- link.bind('dragstart', function (e) {
420
- try {
421
- e.originalEvent.dataTransfer.setData(
422
- 'DownloadURL',
423
- [type, name, url].join(':')
424
- );
425
- } catch (ignore) {}
426
- });
427
- },
428
-
429
- _formatFileSize: function (bytes) {
430
- if (typeof bytes !== 'number') {
431
- return '';
432
- }
433
- if (bytes >= 1000000000) {
434
- return (bytes / 1000000000).toFixed(2) + ' GB';
435
- }
436
- if (bytes >= 1000000) {
437
- return (bytes / 1000000).toFixed(2) + ' MB';
438
- }
439
- return (bytes / 1000).toFixed(2) + ' KB';
440
- },
441
-
442
- _formatBitrate: function (bits) {
443
- if (typeof bits !== 'number') {
444
- return '';
445
- }
446
- if (bits >= 1000000000) {
447
- return (bits / 1000000000).toFixed(2) + ' Gbit/s';
448
- }
449
- if (bits >= 1000000) {
450
- return (bits / 1000000).toFixed(2) + ' Mbit/s';
451
- }
452
- if (bits >= 1000) {
453
- return (bits / 1000).toFixed(2) + ' kbit/s';
454
- }
455
- return bits.toFixed(2) + ' bit/s';
456
- },
457
-
458
- _formatTime: function (seconds) {
459
- var date = new Date(seconds * 1000),
460
- days = Math.floor(seconds / 86400);
461
- days = days ? days + 'd ' : '';
462
- return days +
463
- ('0' + date.getUTCHours()).slice(-2) + ':' +
464
- ('0' + date.getUTCMinutes()).slice(-2) + ':' +
465
- ('0' + date.getUTCSeconds()).slice(-2);
466
- },
467
-
468
- _formatPercentage: function (floatValue) {
469
- return (floatValue * 100).toFixed(2) + ' %';
470
- },
471
-
472
- _renderExtendedProgress: function (data) {
473
- return this._formatBitrate(data.bitrate) + ' | ' +
474
- this._formatTime(
475
- (data.total - data.loaded) * 8 / data.bitrate
476
- ) + ' | ' +
477
- this._formatPercentage(
478
- data.loaded / data.total
479
- ) + ' | ' +
480
- this._formatFileSize(data.loaded) + ' / ' +
481
- this._formatFileSize(data.total);
482
- },
483
-
484
- _renderTemplate: function (func, files) {
485
- if (!func) {
486
- return $();
36
+ } else {
37
+ // Browser globals:
38
+ factory(window.jQuery, window.tmpl);
39
+ }
40
+ })(function ($, tmpl) {
41
+ 'use strict';
42
+
43
+ $.blueimp.fileupload.prototype._specialOptions.push(
44
+ 'filesContainer',
45
+ 'uploadTemplateId',
46
+ 'downloadTemplateId'
47
+ );
48
+
49
+ // The UI version extends the file upload widget
50
+ // and adds complete user interface interaction:
51
+ $.widget('blueimp.fileupload', $.blueimp.fileupload, {
52
+ options: {
53
+ // By default, files added to the widget are uploaded as soon
54
+ // as the user clicks on the start buttons. To enable automatic
55
+ // uploads, set the following option to true:
56
+ autoUpload: false,
57
+ // The class to show/hide UI elements:
58
+ showElementClass: 'in',
59
+ // The ID of the upload template:
60
+ uploadTemplateId: 'template-upload',
61
+ // The ID of the download template:
62
+ downloadTemplateId: 'template-download',
63
+ // The container for the list of files. If undefined, it is set to
64
+ // an element with class "files" inside of the widget element:
65
+ filesContainer: undefined,
66
+ // By default, files are appended to the files container.
67
+ // Set the following option to true, to prepend files instead:
68
+ prependFiles: false,
69
+ // The expected data type of the upload response, sets the dataType
70
+ // option of the $.ajax upload requests:
71
+ dataType: 'json',
72
+
73
+ // Error and info messages:
74
+ messages: {
75
+ unknownError: 'Unknown error'
76
+ },
77
+
78
+ // Function returning the current number of files,
79
+ // used by the maxNumberOfFiles validation:
80
+ getNumberOfFiles: function () {
81
+ return this.filesContainer.children().not('.processing').length;
82
+ },
83
+
84
+ // Callback to retrieve the list of files from the server response:
85
+ getFilesFromResponse: function (data) {
86
+ if (data.result && $.isArray(data.result.files)) {
87
+ return data.result.files;
88
+ }
89
+ return [];
90
+ },
91
+
92
+ // The add callback is invoked as soon as files are added to the fileupload
93
+ // widget (via file input selection, drag & drop or add API call).
94
+ // See the basic file upload widget for more information:
95
+ add: function (e, data) {
96
+ if (e.isDefaultPrevented()) {
97
+ return false;
98
+ }
99
+ var $this = $(this),
100
+ that = $this.data('blueimp-fileupload') || $this.data('fileupload'),
101
+ options = that.options;
102
+ data.context = that
103
+ ._renderUpload(data.files)
104
+ .data('data', data)
105
+ .addClass('processing');
106
+ options.filesContainer[options.prependFiles ? 'prepend' : 'append'](
107
+ data.context
108
+ );
109
+ that._forceReflow(data.context);
110
+ that._transition(data.context);
111
+ data
112
+ .process(function () {
113
+ return $this.fileupload('process', data);
114
+ })
115
+ .always(function () {
116
+ data.context
117
+ .each(function (index) {
118
+ $(this)
119
+ .find('.size')
120
+ .text(that._formatFileSize(data.files[index].size));
121
+ })
122
+ .removeClass('processing');
123
+ that._renderPreviews(data);
124
+ })
125
+ .done(function () {
126
+ data.context.find('.edit,.start').prop('disabled', false);
127
+ if (
128
+ that._trigger('added', e, data) !== false &&
129
+ (options.autoUpload || data.autoUpload) &&
130
+ data.autoUpload !== false
131
+ ) {
132
+ data.submit();
487
133
  }
488
- var result = func({
489
- files: files,
490
- formatFileSize: this._formatFileSize,
491
- options: this.options
492
- });
493
- if (result instanceof $) {
494
- return result;
134
+ })
135
+ .fail(function () {
136
+ if (data.files.error) {
137
+ data.context.each(function (index) {
138
+ var error = data.files[index].error;
139
+ if (error) {
140
+ $(this).find('.error').text(error);
141
+ }
142
+ });
495
143
  }
496
- return $(this.options.templatesContainer).html(result).children();
497
- },
498
-
499
- _renderPreviews: function (data) {
500
- data.context.find('.preview').each(function (index, elm) {
501
- $(elm).append(data.files[index].preview);
144
+ });
145
+ },
146
+ // Callback for the start of each file upload request:
147
+ send: function (e, data) {
148
+ if (e.isDefaultPrevented()) {
149
+ return false;
150
+ }
151
+ var that =
152
+ $(this).data('blueimp-fileupload') || $(this).data('fileupload');
153
+ if (
154
+ data.context &&
155
+ data.dataType &&
156
+ data.dataType.substr(0, 6) === 'iframe'
157
+ ) {
158
+ // Iframe Transport does not support progress events.
159
+ // In lack of an indeterminate progress bar, we set
160
+ // the progress to 100%, showing the full animated bar:
161
+ data.context
162
+ .find('.progress')
163
+ .addClass(!$.support.transition && 'progress-animated')
164
+ .attr('aria-valuenow', 100)
165
+ .children()
166
+ .first()
167
+ .css('width', '100%');
168
+ }
169
+ return that._trigger('sent', e, data);
170
+ },
171
+ // Callback for successful uploads:
172
+ done: function (e, data) {
173
+ if (e.isDefaultPrevented()) {
174
+ return false;
175
+ }
176
+ var that =
177
+ $(this).data('blueimp-fileupload') || $(this).data('fileupload'),
178
+ getFilesFromResponse =
179
+ data.getFilesFromResponse || that.options.getFilesFromResponse,
180
+ files = getFilesFromResponse(data),
181
+ template,
182
+ deferred;
183
+ if (data.context) {
184
+ data.context.each(function (index) {
185
+ var file = files[index] || { error: 'Empty file upload result' };
186
+ deferred = that._addFinishedDeferreds();
187
+ that._transition($(this)).done(function () {
188
+ var node = $(this);
189
+ template = that._renderDownload([file]).replaceAll(node);
190
+ that._forceReflow(template);
191
+ that._transition(template).done(function () {
192
+ data.context = $(this);
193
+ that._trigger('completed', e, data);
194
+ that._trigger('finished', e, data);
195
+ deferred.resolve();
196
+ });
502
197
  });
503
- },
504
-
505
- _renderUpload: function (files) {
506
- return this._renderTemplate(
507
- this.options.uploadTemplate,
508
- files
198
+ });
199
+ } else {
200
+ template = that
201
+ ._renderDownload(files)
202
+ [that.options.prependFiles ? 'prependTo' : 'appendTo'](
203
+ that.options.filesContainer
509
204
  );
510
- },
511
-
512
- _renderDownload: function (files) {
513
- return this._renderTemplate(
514
- this.options.downloadTemplate,
515
- files
516
- ).find('a[download]').each(this._enableDragToDesktop).end();
517
- },
518
-
519
- _startHandler: function (e) {
520
- e.preventDefault();
521
- var button = $(e.currentTarget),
522
- template = button.closest('.template-upload'),
523
- data = template.data('data');
524
- button.prop('disabled', true);
525
- if (data && data.submit) {
526
- data.submit();
527
- }
528
- },
529
-
530
- _cancelHandler: function (e) {
531
- e.preventDefault();
532
- var template = $(e.currentTarget)
533
- .closest('.template-upload,.template-download'),
534
- data = template.data('data') || {};
535
- data.context = data.context || template;
536
- if (data.abort) {
537
- data.abort();
538
- } else {
539
- data.errorThrown = 'abort';
540
- this._trigger('fail', e, data);
541
- }
542
- },
543
-
544
- _deleteHandler: function (e) {
545
- e.preventDefault();
546
- var button = $(e.currentTarget);
547
- this._trigger('destroy', e, $.extend({
548
- context: button.closest('.template-download'),
549
- type: 'DELETE'
550
- }, button.data()));
551
- },
552
-
553
- _forceReflow: function (node) {
554
- return $.support.transition && node.length &&
555
- node[0].offsetWidth;
556
- },
557
-
558
- _transition: function (node) {
559
- var dfd = $.Deferred();
560
- if ($.support.transition && node.hasClass('fade') && node.is(':visible')) {
561
- node.bind(
562
- $.support.transition.end,
563
- function (e) {
564
- // Make sure we don't respond to other transitions events
565
- // in the container element, e.g. from button elements:
566
- if (e.target === node[0]) {
567
- node.unbind($.support.transition.end);
568
- dfd.resolveWith(node);
569
- }
570
- }
571
- ).toggleClass('in');
205
+ that._forceReflow(template);
206
+ deferred = that._addFinishedDeferreds();
207
+ that._transition(template).done(function () {
208
+ data.context = $(this);
209
+ that._trigger('completed', e, data);
210
+ that._trigger('finished', e, data);
211
+ deferred.resolve();
212
+ });
213
+ }
214
+ },
215
+ // Callback for failed (abort or error) uploads:
216
+ fail: function (e, data) {
217
+ if (e.isDefaultPrevented()) {
218
+ return false;
219
+ }
220
+ var that =
221
+ $(this).data('blueimp-fileupload') || $(this).data('fileupload'),
222
+ template,
223
+ deferred;
224
+ if (data.context) {
225
+ data.context.each(function (index) {
226
+ if (data.errorThrown !== 'abort') {
227
+ var file = data.files[index];
228
+ file.error =
229
+ file.error || data.errorThrown || data.i18n('unknownError');
230
+ deferred = that._addFinishedDeferreds();
231
+ that._transition($(this)).done(function () {
232
+ var node = $(this);
233
+ template = that._renderDownload([file]).replaceAll(node);
234
+ that._forceReflow(template);
235
+ that._transition(template).done(function () {
236
+ data.context = $(this);
237
+ that._trigger('failed', e, data);
238
+ that._trigger('finished', e, data);
239
+ deferred.resolve();
240
+ });
241
+ });
572
242
  } else {
573
- node.toggleClass('in');
574
- dfd.resolveWith(node);
243
+ deferred = that._addFinishedDeferreds();
244
+ that._transition($(this)).done(function () {
245
+ $(this).remove();
246
+ that._trigger('failed', e, data);
247
+ that._trigger('finished', e, data);
248
+ deferred.resolve();
249
+ });
575
250
  }
576
- return dfd;
577
- },
578
-
579
- _initButtonBarEventHandlers: function () {
580
- var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'),
581
- filesList = this.options.filesContainer;
582
- this._on(fileUploadButtonBar.find('.start'), {
583
- click: function (e) {
584
- e.preventDefault();
585
- filesList.find('.start').click();
586
- }
587
- });
588
- this._on(fileUploadButtonBar.find('.cancel'), {
589
- click: function (e) {
590
- e.preventDefault();
591
- filesList.find('.cancel').click();
592
- }
593
- });
594
- this._on(fileUploadButtonBar.find('.delete'), {
595
- click: function (e) {
596
- e.preventDefault();
597
- filesList.find('.toggle:checked')
598
- .closest('.template-download')
599
- .find('.delete').click();
600
- fileUploadButtonBar.find('.toggle')
601
- .prop('checked', false);
602
- }
251
+ });
252
+ } else if (data.errorThrown !== 'abort') {
253
+ data.context = that
254
+ ._renderUpload(data.files)
255
+ [that.options.prependFiles ? 'prependTo' : 'appendTo'](
256
+ that.options.filesContainer
257
+ )
258
+ .data('data', data);
259
+ that._forceReflow(data.context);
260
+ deferred = that._addFinishedDeferreds();
261
+ that._transition(data.context).done(function () {
262
+ data.context = $(this);
263
+ that._trigger('failed', e, data);
264
+ that._trigger('finished', e, data);
265
+ deferred.resolve();
266
+ });
267
+ } else {
268
+ that._trigger('failed', e, data);
269
+ that._trigger('finished', e, data);
270
+ that._addFinishedDeferreds().resolve();
271
+ }
272
+ },
273
+ // Callback for upload progress events:
274
+ progress: function (e, data) {
275
+ if (e.isDefaultPrevented()) {
276
+ return false;
277
+ }
278
+ var progress = Math.floor((data.loaded / data.total) * 100);
279
+ if (data.context) {
280
+ data.context.each(function () {
281
+ $(this)
282
+ .find('.progress')
283
+ .attr('aria-valuenow', progress)
284
+ .children()
285
+ .first()
286
+ .css('width', progress + '%');
287
+ });
288
+ }
289
+ },
290
+ // Callback for global upload progress events:
291
+ progressall: function (e, data) {
292
+ if (e.isDefaultPrevented()) {
293
+ return false;
294
+ }
295
+ var $this = $(this),
296
+ progress = Math.floor((data.loaded / data.total) * 100),
297
+ globalProgressNode = $this.find('.fileupload-progress'),
298
+ extendedProgressNode = globalProgressNode.find('.progress-extended');
299
+ if (extendedProgressNode.length) {
300
+ extendedProgressNode.html(
301
+ (
302
+ $this.data('blueimp-fileupload') || $this.data('fileupload')
303
+ )._renderExtendedProgress(data)
304
+ );
305
+ }
306
+ globalProgressNode
307
+ .find('.progress')
308
+ .attr('aria-valuenow', progress)
309
+ .children()
310
+ .first()
311
+ .css('width', progress + '%');
312
+ },
313
+ // Callback for uploads start, equivalent to the global ajaxStart event:
314
+ start: function (e) {
315
+ if (e.isDefaultPrevented()) {
316
+ return false;
317
+ }
318
+ var that =
319
+ $(this).data('blueimp-fileupload') || $(this).data('fileupload');
320
+ that._resetFinishedDeferreds();
321
+ that
322
+ ._transition($(this).find('.fileupload-progress'))
323
+ .done(function () {
324
+ that._trigger('started', e);
325
+ });
326
+ },
327
+ // Callback for uploads stop, equivalent to the global ajaxStop event:
328
+ stop: function (e) {
329
+ if (e.isDefaultPrevented()) {
330
+ return false;
331
+ }
332
+ var that =
333
+ $(this).data('blueimp-fileupload') || $(this).data('fileupload'),
334
+ deferred = that._addFinishedDeferreds();
335
+ $.when.apply($, that._getFinishedDeferreds()).done(function () {
336
+ that._trigger('stopped', e);
337
+ });
338
+ that
339
+ ._transition($(this).find('.fileupload-progress'))
340
+ .done(function () {
341
+ $(this)
342
+ .find('.progress')
343
+ .attr('aria-valuenow', '0')
344
+ .children()
345
+ .first()
346
+ .css('width', '0%');
347
+ $(this).find('.progress-extended').html(' ');
348
+ deferred.resolve();
349
+ });
350
+ },
351
+ processstart: function (e) {
352
+ if (e.isDefaultPrevented()) {
353
+ return false;
354
+ }
355
+ $(this).addClass('fileupload-processing');
356
+ },
357
+ processstop: function (e) {
358
+ if (e.isDefaultPrevented()) {
359
+ return false;
360
+ }
361
+ $(this).removeClass('fileupload-processing');
362
+ },
363
+ // Callback for file deletion:
364
+ destroy: function (e, data) {
365
+ if (e.isDefaultPrevented()) {
366
+ return false;
367
+ }
368
+ var that =
369
+ $(this).data('blueimp-fileupload') || $(this).data('fileupload'),
370
+ removeNode = function () {
371
+ that._transition(data.context).done(function () {
372
+ $(this).remove();
373
+ that._trigger('destroyed', e, data);
603
374
  });
604
- this._on(fileUploadButtonBar.find('.toggle'), {
605
- change: function (e) {
606
- filesList.find('.toggle').prop(
607
- 'checked',
608
- $(e.currentTarget).is(':checked')
609
- );
610
- }
375
+ };
376
+ if (data.url) {
377
+ data.dataType = data.dataType || that.options.dataType;
378
+ $.ajax(data)
379
+ .done(removeNode)
380
+ .fail(function () {
381
+ that._trigger('destroyfailed', e, data);
611
382
  });
612
- },
613
-
614
- _destroyButtonBarEventHandlers: function () {
615
- this._off(
616
- this.element.find('.fileupload-buttonbar')
617
- .find('.start, .cancel, .delete'),
618
- 'click'
619
- );
620
- this._off(
621
- this.element.find('.fileupload-buttonbar .toggle'),
622
- 'change.'
623
- );
624
- },
625
-
626
- _initEventHandlers: function () {
627
- this._super();
628
- this._on(this.options.filesContainer, {
629
- 'click .start': this._startHandler,
630
- 'click .cancel': this._cancelHandler,
631
- 'click .delete': this._deleteHandler
632
- });
633
- this._initButtonBarEventHandlers();
634
- },
635
-
636
- _destroyEventHandlers: function () {
637
- this._destroyButtonBarEventHandlers();
638
- this._off(this.options.filesContainer, 'click');
639
- this._super();
640
- },
641
-
642
- _enableFileInputButton: function () {
643
- this.element.find('.fileinput-button input')
644
- .prop('disabled', false)
645
- .parent().removeClass('disabled');
646
- },
647
-
648
- _disableFileInputButton: function () {
649
- this.element.find('.fileinput-button input')
650
- .prop('disabled', true)
651
- .parent().addClass('disabled');
652
- },
653
-
654
- _initTemplates: function () {
655
- var options = this.options;
656
- options.templatesContainer = this.document[0].createElement(
657
- options.filesContainer.prop('nodeName')
658
- );
659
- if (tmpl) {
660
- if (options.uploadTemplateId) {
661
- options.uploadTemplate = tmpl(options.uploadTemplateId);
662
- }
663
- if (options.downloadTemplateId) {
664
- options.downloadTemplate = tmpl(options.downloadTemplateId);
665
- }
666
- }
667
- },
668
-
669
- _initFilesContainer: function () {
670
- var options = this.options;
671
- if (options.filesContainer === undefined) {
672
- options.filesContainer = this.element.find('.files');
673
- } else if (!(options.filesContainer instanceof $)) {
674
- options.filesContainer = $(options.filesContainer);
675
- }
676
- },
677
-
678
- _initSpecialOptions: function () {
679
- this._super();
680
- this._initFilesContainer();
681
- this._initTemplates();
682
- },
683
-
684
- _create: function () {
685
- this._super();
686
- this._resetFinishedDeferreds();
687
- if (!$.support.fileInput) {
688
- this._disableFileInputButton();
689
- }
690
- },
691
-
692
- enable: function () {
693
- var wasDisabled = false;
694
- if (this.options.disabled) {
695
- wasDisabled = true;
696
- }
697
- this._super();
698
- if (wasDisabled) {
699
- this.element.find('input, button').prop('disabled', false);
700
- this._enableFileInputButton();
701
- }
702
- },
703
-
704
- disable: function () {
705
- if (!this.options.disabled) {
706
- this.element.find('input, button').prop('disabled', true);
707
- this._disableFileInputButton();
383
+ } else {
384
+ removeNode();
385
+ }
386
+ }
387
+ },
388
+
389
+ _resetFinishedDeferreds: function () {
390
+ this._finishedUploads = [];
391
+ },
392
+
393
+ _addFinishedDeferreds: function (deferred) {
394
+ // eslint-disable-next-line new-cap
395
+ var promise = deferred || $.Deferred();
396
+ this._finishedUploads.push(promise);
397
+ return promise;
398
+ },
399
+
400
+ _getFinishedDeferreds: function () {
401
+ return this._finishedUploads;
402
+ },
403
+
404
+ // Link handler, that allows to download files
405
+ // by drag & drop of the links to the desktop:
406
+ _enableDragToDesktop: function () {
407
+ var link = $(this),
408
+ url = link.prop('href'),
409
+ name = link.prop('download'),
410
+ type = 'application/octet-stream';
411
+ link.on('dragstart', function (e) {
412
+ try {
413
+ e.originalEvent.dataTransfer.setData(
414
+ 'DownloadURL',
415
+ [type, name, url].join(':')
416
+ );
417
+ } catch (ignore) {
418
+ // Ignore exceptions
419
+ }
420
+ });
421
+ },
422
+
423
+ _formatFileSize: function (bytes) {
424
+ if (typeof bytes !== 'number') {
425
+ return '';
426
+ }
427
+ if (bytes >= 1000000000) {
428
+ return (bytes / 1000000000).toFixed(2) + ' GB';
429
+ }
430
+ if (bytes >= 1000000) {
431
+ return (bytes / 1000000).toFixed(2) + ' MB';
432
+ }
433
+ return (bytes / 1000).toFixed(2) + ' KB';
434
+ },
435
+
436
+ _formatBitrate: function (bits) {
437
+ if (typeof bits !== 'number') {
438
+ return '';
439
+ }
440
+ if (bits >= 1000000000) {
441
+ return (bits / 1000000000).toFixed(2) + ' Gbit/s';
442
+ }
443
+ if (bits >= 1000000) {
444
+ return (bits / 1000000).toFixed(2) + ' Mbit/s';
445
+ }
446
+ if (bits >= 1000) {
447
+ return (bits / 1000).toFixed(2) + ' kbit/s';
448
+ }
449
+ return bits.toFixed(2) + ' bit/s';
450
+ },
451
+
452
+ _formatTime: function (seconds) {
453
+ var date = new Date(seconds * 1000),
454
+ days = Math.floor(seconds / 86400);
455
+ days = days ? days + 'd ' : '';
456
+ return (
457
+ days +
458
+ ('0' + date.getUTCHours()).slice(-2) +
459
+ ':' +
460
+ ('0' + date.getUTCMinutes()).slice(-2) +
461
+ ':' +
462
+ ('0' + date.getUTCSeconds()).slice(-2)
463
+ );
464
+ },
465
+
466
+ _formatPercentage: function (floatValue) {
467
+ return (floatValue * 100).toFixed(2) + ' %';
468
+ },
469
+
470
+ _renderExtendedProgress: function (data) {
471
+ return (
472
+ this._formatBitrate(data.bitrate) +
473
+ ' | ' +
474
+ this._formatTime(((data.total - data.loaded) * 8) / data.bitrate) +
475
+ ' | ' +
476
+ this._formatPercentage(data.loaded / data.total) +
477
+ ' | ' +
478
+ this._formatFileSize(data.loaded) +
479
+ ' / ' +
480
+ this._formatFileSize(data.total)
481
+ );
482
+ },
483
+
484
+ _renderTemplate: function (func, files) {
485
+ if (!func) {
486
+ return $();
487
+ }
488
+ var result = func({
489
+ files: files,
490
+ formatFileSize: this._formatFileSize,
491
+ options: this.options
492
+ });
493
+ if (result instanceof $) {
494
+ return result;
495
+ }
496
+ return $(this.options.templatesContainer).html(result).children();
497
+ },
498
+
499
+ _renderPreviews: function (data) {
500
+ data.context.find('.preview').each(function (index, elm) {
501
+ $(elm).empty().append(data.files[index].preview);
502
+ });
503
+ },
504
+
505
+ _renderUpload: function (files) {
506
+ return this._renderTemplate(this.options.uploadTemplate, files);
507
+ },
508
+
509
+ _renderDownload: function (files) {
510
+ return this._renderTemplate(this.options.downloadTemplate, files)
511
+ .find('a[download]')
512
+ .each(this._enableDragToDesktop)
513
+ .end();
514
+ },
515
+
516
+ _editHandler: function (e) {
517
+ e.preventDefault();
518
+ if (!this.options.edit) return;
519
+ var that = this,
520
+ button = $(e.currentTarget),
521
+ template = button.closest('.template-upload'),
522
+ data = template.data('data'),
523
+ index = button.data().index;
524
+ this.options.edit(data.files[index]).then(function (file) {
525
+ if (!file) return;
526
+ data.files[index] = file;
527
+ data.context.addClass('processing');
528
+ template.find('.edit,.start').prop('disabled', true);
529
+ $(that.element)
530
+ .fileupload('process', data)
531
+ .always(function () {
532
+ template
533
+ .find('.size')
534
+ .text(that._formatFileSize(data.files[index].size));
535
+ data.context.removeClass('processing');
536
+ that._renderPreviews(data);
537
+ })
538
+ .done(function () {
539
+ template.find('.edit,.start').prop('disabled', false);
540
+ })
541
+ .fail(function () {
542
+ template.find('.edit').prop('disabled', false);
543
+ var error = data.files[index].error;
544
+ if (error) {
545
+ template.find('.error').text(error);
708
546
  }
709
- this._super();
547
+ });
548
+ });
549
+ },
550
+
551
+ _startHandler: function (e) {
552
+ e.preventDefault();
553
+ var button = $(e.currentTarget),
554
+ template = button.closest('.template-upload'),
555
+ data = template.data('data');
556
+ button.prop('disabled', true);
557
+ if (data && data.submit) {
558
+ data.submit();
559
+ }
560
+ },
561
+
562
+ _cancelHandler: function (e) {
563
+ e.preventDefault();
564
+ var template = $(e.currentTarget).closest(
565
+ '.template-upload,.template-download'
566
+ ),
567
+ data = template.data('data') || {};
568
+ data.context = data.context || template;
569
+ if (data.abort) {
570
+ data.abort();
571
+ } else {
572
+ data.errorThrown = 'abort';
573
+ this._trigger('fail', e, data);
574
+ }
575
+ },
576
+
577
+ _deleteHandler: function (e) {
578
+ e.preventDefault();
579
+ var button = $(e.currentTarget);
580
+ this._trigger(
581
+ 'destroy',
582
+ e,
583
+ $.extend(
584
+ {
585
+ context: button.closest('.template-download'),
586
+ type: 'DELETE'
587
+ },
588
+ button.data()
589
+ )
590
+ );
591
+ },
592
+
593
+ _forceReflow: function (node) {
594
+ return $.support.transition && node.length && node[0].offsetWidth;
595
+ },
596
+
597
+ _transition: function (node) {
598
+ // eslint-disable-next-line new-cap
599
+ var dfd = $.Deferred();
600
+ if (
601
+ $.support.transition &&
602
+ node.hasClass('fade') &&
603
+ node.is(':visible')
604
+ ) {
605
+ var transitionEndHandler = function (e) {
606
+ // Make sure we don't respond to other transition events
607
+ // in the container element, e.g. from button elements:
608
+ if (e.target === node[0]) {
609
+ node.off($.support.transition.end, transitionEndHandler);
610
+ dfd.resolveWith(node);
611
+ }
612
+ };
613
+ node
614
+ .on($.support.transition.end, transitionEndHandler)
615
+ .toggleClass(this.options.showElementClass);
616
+ } else {
617
+ node.toggleClass(this.options.showElementClass);
618
+ dfd.resolveWith(node);
619
+ }
620
+ return dfd;
621
+ },
622
+
623
+ _initButtonBarEventHandlers: function () {
624
+ var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'),
625
+ filesList = this.options.filesContainer;
626
+ this._on(fileUploadButtonBar.find('.start'), {
627
+ click: function (e) {
628
+ e.preventDefault();
629
+ filesList.find('.start').trigger('click');
710
630
  }
711
-
712
- });
713
-
714
- }));
631
+ });
632
+ this._on(fileUploadButtonBar.find('.cancel'), {
633
+ click: function (e) {
634
+ e.preventDefault();
635
+ filesList.find('.cancel').trigger('click');
636
+ }
637
+ });
638
+ this._on(fileUploadButtonBar.find('.delete'), {
639
+ click: function (e) {
640
+ e.preventDefault();
641
+ filesList
642
+ .find('.toggle:checked')
643
+ .closest('.template-download')
644
+ .find('.delete')
645
+ .trigger('click');
646
+ fileUploadButtonBar.find('.toggle').prop('checked', false);
647
+ }
648
+ });
649
+ this._on(fileUploadButtonBar.find('.toggle'), {
650
+ change: function (e) {
651
+ filesList
652
+ .find('.toggle')
653
+ .prop('checked', $(e.currentTarget).is(':checked'));
654
+ }
655
+ });
656
+ },
657
+
658
+ _destroyButtonBarEventHandlers: function () {
659
+ this._off(
660
+ this.element
661
+ .find('.fileupload-buttonbar')
662
+ .find('.start, .cancel, .delete'),
663
+ 'click'
664
+ );
665
+ this._off(this.element.find('.fileupload-buttonbar .toggle'), 'change.');
666
+ },
667
+
668
+ _initEventHandlers: function () {
669
+ this._super();
670
+ this._on(this.options.filesContainer, {
671
+ 'click .edit': this._editHandler,
672
+ 'click .start': this._startHandler,
673
+ 'click .cancel': this._cancelHandler,
674
+ 'click .delete': this._deleteHandler
675
+ });
676
+ this._initButtonBarEventHandlers();
677
+ },
678
+
679
+ _destroyEventHandlers: function () {
680
+ this._destroyButtonBarEventHandlers();
681
+ this._off(this.options.filesContainer, 'click');
682
+ this._super();
683
+ },
684
+
685
+ _enableFileInputButton: function () {
686
+ this.element
687
+ .find('.fileinput-button input')
688
+ .prop('disabled', false)
689
+ .parent()
690
+ .removeClass('disabled');
691
+ },
692
+
693
+ _disableFileInputButton: function () {
694
+ this.element
695
+ .find('.fileinput-button input')
696
+ .prop('disabled', true)
697
+ .parent()
698
+ .addClass('disabled');
699
+ },
700
+
701
+ _initTemplates: function () {
702
+ var options = this.options;
703
+ options.templatesContainer = this.document[0].createElement(
704
+ options.filesContainer.prop('nodeName')
705
+ );
706
+ if (tmpl) {
707
+ if (options.uploadTemplateId) {
708
+ options.uploadTemplate = tmpl(options.uploadTemplateId);
709
+ }
710
+ if (options.downloadTemplateId) {
711
+ options.downloadTemplate = tmpl(options.downloadTemplateId);
712
+ }
713
+ }
714
+ },
715
+
716
+ _initFilesContainer: function () {
717
+ var options = this.options;
718
+ if (options.filesContainer === undefined) {
719
+ options.filesContainer = this.element.find('.files');
720
+ } else if (!(options.filesContainer instanceof $)) {
721
+ options.filesContainer = $(options.filesContainer);
722
+ }
723
+ },
724
+
725
+ _initSpecialOptions: function () {
726
+ this._super();
727
+ this._initFilesContainer();
728
+ this._initTemplates();
729
+ },
730
+
731
+ _create: function () {
732
+ this._super();
733
+ this._resetFinishedDeferreds();
734
+ if (!$.support.fileInput) {
735
+ this._disableFileInputButton();
736
+ }
737
+ },
738
+
739
+ enable: function () {
740
+ var wasDisabled = false;
741
+ if (this.options.disabled) {
742
+ wasDisabled = true;
743
+ }
744
+ this._super();
745
+ if (wasDisabled) {
746
+ this.element.find('input, button').prop('disabled', false);
747
+ this._enableFileInputButton();
748
+ }
749
+ },
750
+
751
+ disable: function () {
752
+ if (!this.options.disabled) {
753
+ this.element.find('input, button').prop('disabled', true);
754
+ this._disableFileInputButton();
755
+ }
756
+ this._super();
757
+ }
758
+ });
759
+ });